summaryrefslogtreecommitdiffstats
path: root/lib/dns
diff options
context:
space:
mode:
authordougb <dougb@FreeBSD.org>2009-05-31 00:11:36 +0000
committerdougb <dougb@FreeBSD.org>2009-05-31 00:11:36 +0000
commitfd553238c94c3abfef11bfdfc5cb05b32cbe5f76 (patch)
tree72d567a9bc3fb8adcfcbaa9baedc122d53071209 /lib/dns
parentd342cb576b0154d48c90bc32e251331282264cd4 (diff)
downloadFreeBSD-src-fd553238c94c3abfef11bfdfc5cb05b32cbe5f76.zip
FreeBSD-src-fd553238c94c3abfef11bfdfc5cb05b32cbe5f76.tar.gz
Vendor import of BIND 9.6.1rc1
Diffstat (limited to 'lib/dns')
-rw-r--r--lib/dns/Makefile.in32
-rw-r--r--lib/dns/acache.c4
-rw-r--r--lib/dns/acl.c557
-rw-r--r--lib/dns/adb.c693
-rw-r--r--lib/dns/api6
-rw-r--r--lib/dns/byaddr.c6
-rw-r--r--lib/dns/cache.c127
-rw-r--r--lib/dns/callbacks.c6
-rw-r--r--lib/dns/compress.c6
-rw-r--r--lib/dns/db.c125
-rw-r--r--lib/dns/dbiterator.c6
-rw-r--r--lib/dns/dbtable.c6
-rw-r--r--lib/dns/diff.c130
-rw-r--r--lib/dns/dispatch.c190
-rw-r--r--lib/dns/dlz.c10
-rw-r--r--lib/dns/dnssec.c39
-rw-r--r--lib/dns/ds.c6
-rw-r--r--lib/dns/dst_api.c152
-rw-r--r--lib/dns/dst_internal.h85
-rw-r--r--lib/dns/dst_lib.c6
-rw-r--r--lib/dns/dst_openssl.h12
-rw-r--r--lib/dns/dst_parse.c59
-rw-r--r--lib/dns/dst_parse.h22
-rw-r--r--lib/dns/dst_result.c9
-rw-r--r--lib/dns/forward.c6
-rw-r--r--lib/dns/gen-unix.h8
-rw-r--r--lib/dns/gen.c46
-rw-r--r--lib/dns/gssapi_link.c178
-rw-r--r--lib/dns/gssapictx.c684
-rw-r--r--lib/dns/hmac_link.c337
-rw-r--r--lib/dns/include/Makefile.in6
-rw-r--r--lib/dns/include/dns/Makefile.in12
-rw-r--r--lib/dns/include/dns/acache.h6
-rw-r--r--lib/dns/include/dns/acl.h114
-rw-r--r--lib/dns/include/dns/adb.h19
-rw-r--r--lib/dns/include/dns/bit.h8
-rw-r--r--lib/dns/include/dns/byaddr.h16
-rw-r--r--lib/dns/include/dns/cache.h8
-rw-r--r--lib/dns/include/dns/callbacks.h8
-rw-r--r--lib/dns/include/dns/cert.h8
-rw-r--r--lib/dns/include/dns/compress.h12
-rw-r--r--lib/dns/include/dns/db.h210
-rw-r--r--lib/dns/include/dns/dbiterator.h8
-rw-r--r--lib/dns/include/dns/dbtable.h8
-rw-r--r--lib/dns/include/dns/diff.h31
-rw-r--r--lib/dns/include/dns/dispatch.h23
-rw-r--r--lib/dns/include/dns/dlz.h16
-rw-r--r--lib/dns/include/dns/dnssec.h8
-rw-r--r--lib/dns/include/dns/ds.h6
-rw-r--r--lib/dns/include/dns/events.h9
-rw-r--r--lib/dns/include/dns/fixedname.h8
-rw-r--r--lib/dns/include/dns/forward.h8
-rw-r--r--lib/dns/include/dns/iptable.h70
-rw-r--r--lib/dns/include/dns/journal.h26
-rw-r--r--lib/dns/include/dns/keyflags.h8
-rw-r--r--lib/dns/include/dns/keytable.h6
-rw-r--r--lib/dns/include/dns/keyvalues.h12
-rw-r--r--lib/dns/include/dns/lib.h8
-rw-r--r--lib/dns/include/dns/log.h11
-rw-r--r--lib/dns/include/dns/lookup.h12
-rw-r--r--lib/dns/include/dns/master.h39
-rw-r--r--lib/dns/include/dns/masterdump.h34
-rw-r--r--lib/dns/include/dns/message.h24
-rw-r--r--lib/dns/include/dns/name.h23
-rw-r--r--lib/dns/include/dns/ncache.h28
-rw-r--r--lib/dns/include/dns/nsec.h19
-rw-r--r--lib/dns/include/dns/nsec3.h194
-rw-r--r--lib/dns/include/dns/opcode.h8
-rw-r--r--lib/dns/include/dns/order.h8
-rw-r--r--lib/dns/include/dns/peer.h21
-rw-r--r--lib/dns/include/dns/portlist.h8
-rw-r--r--lib/dns/include/dns/rbt.h769
-rw-r--r--lib/dns/include/dns/rcode.h23
-rw-r--r--lib/dns/include/dns/rdata.h20
-rw-r--r--lib/dns/include/dns/rdataclass.h8
-rw-r--r--lib/dns/include/dns/rdatalist.h29
-rw-r--r--lib/dns/include/dns/rdataset.h68
-rw-r--r--lib/dns/include/dns/rdatasetiter.h8
-rw-r--r--lib/dns/include/dns/rdataslab.h19
-rw-r--r--lib/dns/include/dns/rdatatype.h11
-rw-r--r--lib/dns/include/dns/request.h18
-rw-r--r--lib/dns/include/dns/resolver.h50
-rw-r--r--lib/dns/include/dns/result.h11
-rw-r--r--lib/dns/include/dns/rootns.h8
-rw-r--r--lib/dns/include/dns/sdb.h12
-rw-r--r--lib/dns/include/dns/sdlz.h12
-rw-r--r--lib/dns/include/dns/secalg.h8
-rw-r--r--lib/dns/include/dns/secproto.h8
-rw-r--r--lib/dns/include/dns/soa.h8
-rw-r--r--lib/dns/include/dns/ssu.h58
-rw-r--r--lib/dns/include/dns/stats.h319
-rw-r--r--lib/dns/include/dns/tcpmsg.h8
-rw-r--r--lib/dns/include/dns/time.h8
-rw-r--r--lib/dns/include/dns/timer.h8
-rw-r--r--lib/dns/include/dns/tkey.h78
-rw-r--r--lib/dns/include/dns/tsig.h13
-rw-r--r--lib/dns/include/dns/ttl.h8
-rw-r--r--lib/dns/include/dns/types.h37
-rw-r--r--lib/dns/include/dns/validator.h20
-rw-r--r--lib/dns/include/dns/version.h8
-rw-r--r--lib/dns/include/dns/view.h103
-rw-r--r--lib/dns/include/dns/xfrin.h10
-rw-r--r--lib/dns/include/dns/zone.h224
-rw-r--r--lib/dns/include/dns/zonekey.h8
-rw-r--r--lib/dns/include/dns/zt.h8
-rw-r--r--lib/dns/include/dst/Makefile.in8
-rw-r--r--lib/dns/include/dst/dst.h36
-rw-r--r--lib/dns/include/dst/gssapi.h175
-rw-r--r--lib/dns/include/dst/lib.h8
-rw-r--r--lib/dns/include/dst/result.h11
-rw-r--r--lib/dns/iptable.c188
-rw-r--r--lib/dns/journal.c67
-rw-r--r--lib/dns/key.c6
-rw-r--r--lib/dns/keytable.c6
-rw-r--r--lib/dns/lib.c6
-rw-r--r--lib/dns/log.c11
-rw-r--r--lib/dns/lookup.c2
-rw-r--r--lib/dns/master.c101
-rw-r--r--lib/dns/masterdump.c35
-rw-r--r--lib/dns/message.c134
-rw-r--r--lib/dns/name.c36
-rw-r--r--lib/dns/ncache.c217
-rw-r--r--lib/dns/nsec.c69
-rw-r--r--lib/dns/nsec3.c1377
-rw-r--r--lib/dns/openssl_link.c246
-rw-r--r--lib/dns/openssldh_link.c58
-rw-r--r--lib/dns/openssldsa_link.c205
-rw-r--r--lib/dns/opensslrsa_link.c525
-rw-r--r--lib/dns/order.c6
-rw-r--r--lib/dns/peer.c63
-rw-r--r--lib/dns/portlist.c6
-rw-r--r--lib/dns/rbt.c213
-rw-r--r--lib/dns/rbtdb.c2651
-rw-r--r--lib/dns/rbtdb.h6
-rw-r--r--lib/dns/rbtdb64.c6
-rw-r--r--lib/dns/rbtdb64.h6
-rw-r--r--lib/dns/rcode.c27
-rw-r--r--lib/dns/rdata.c57
-rw-r--r--lib/dns/rdata/any_255/tsig_250.c6
-rw-r--r--lib/dns/rdata/any_255/tsig_250.h6
-rw-r--r--lib/dns/rdata/ch_3/a_1.c6
-rw-r--r--lib/dns/rdata/ch_3/a_1.h6
-rw-r--r--lib/dns/rdata/generic/afsdb_18.c6
-rw-r--r--lib/dns/rdata/generic/afsdb_18.h6
-rw-r--r--lib/dns/rdata/generic/cert_37.c6
-rw-r--r--lib/dns/rdata/generic/cert_37.h6
-rw-r--r--lib/dns/rdata/generic/cname_5.c6
-rw-r--r--lib/dns/rdata/generic/cname_5.h6
-rw-r--r--lib/dns/rdata/generic/dlv_32769.c2
-rw-r--r--lib/dns/rdata/generic/dlv_32769.h6
-rw-r--r--lib/dns/rdata/generic/dname_39.c6
-rw-r--r--lib/dns/rdata/generic/dname_39.h6
-rw-r--r--lib/dns/rdata/generic/dnskey_48.c6
-rw-r--r--lib/dns/rdata/generic/dnskey_48.h6
-rw-r--r--lib/dns/rdata/generic/ds_43.c2
-rw-r--r--lib/dns/rdata/generic/ds_43.h6
-rw-r--r--lib/dns/rdata/generic/gpos_27.c6
-rw-r--r--lib/dns/rdata/generic/gpos_27.h6
-rw-r--r--lib/dns/rdata/generic/hinfo_13.c6
-rw-r--r--lib/dns/rdata/generic/hinfo_13.h6
-rw-r--r--lib/dns/rdata/generic/ipseckey_45.c22
-rw-r--r--lib/dns/rdata/generic/ipseckey_45.h6
-rw-r--r--lib/dns/rdata/generic/isdn_20.c6
-rw-r--r--lib/dns/rdata/generic/isdn_20.h6
-rw-r--r--lib/dns/rdata/generic/key_25.c6
-rw-r--r--lib/dns/rdata/generic/key_25.h6
-rw-r--r--lib/dns/rdata/generic/loc_29.c13
-rw-r--r--lib/dns/rdata/generic/loc_29.h6
-rw-r--r--lib/dns/rdata/generic/mb_7.c6
-rw-r--r--lib/dns/rdata/generic/mb_7.h6
-rw-r--r--lib/dns/rdata/generic/md_3.c6
-rw-r--r--lib/dns/rdata/generic/md_3.h6
-rw-r--r--lib/dns/rdata/generic/mf_4.c6
-rw-r--r--lib/dns/rdata/generic/mf_4.h6
-rw-r--r--lib/dns/rdata/generic/mg_8.c6
-rw-r--r--lib/dns/rdata/generic/mg_8.h6
-rw-r--r--lib/dns/rdata/generic/minfo_14.c6
-rw-r--r--lib/dns/rdata/generic/minfo_14.h6
-rw-r--r--lib/dns/rdata/generic/mr_9.c6
-rw-r--r--lib/dns/rdata/generic/mr_9.h6
-rw-r--r--lib/dns/rdata/generic/mx_15.c6
-rw-r--r--lib/dns/rdata/generic/mx_15.h6
-rw-r--r--lib/dns/rdata/generic/ns_2.c6
-rw-r--r--lib/dns/rdata/generic/ns_2.h6
-rw-r--r--lib/dns/rdata/generic/nsec3_50.c481
-rw-r--r--lib/dns/rdata/generic/nsec3_50.h93
-rw-r--r--lib/dns/rdata/generic/nsec3param_51.c314
-rw-r--r--lib/dns/rdata/generic/nsec3param_51.h38
-rw-r--r--lib/dns/rdata/generic/nsec_47.c4
-rw-r--r--lib/dns/rdata/generic/nsec_47.h4
-rw-r--r--lib/dns/rdata/generic/null_10.c6
-rw-r--r--lib/dns/rdata/generic/null_10.h6
-rw-r--r--lib/dns/rdata/generic/nxt_30.c6
-rw-r--r--lib/dns/rdata/generic/nxt_30.h6
-rw-r--r--lib/dns/rdata/generic/opt_41.c6
-rw-r--r--lib/dns/rdata/generic/opt_41.h6
-rw-r--r--lib/dns/rdata/generic/proforma.c6
-rw-r--r--lib/dns/rdata/generic/proforma.h6
-rw-r--r--lib/dns/rdata/generic/ptr_12.c6
-rw-r--r--lib/dns/rdata/generic/ptr_12.h6
-rw-r--r--lib/dns/rdata/generic/rp_17.c6
-rw-r--r--lib/dns/rdata/generic/rp_17.h6
-rw-r--r--lib/dns/rdata/generic/rrsig_46.c6
-rw-r--r--lib/dns/rdata/generic/rrsig_46.h6
-rw-r--r--lib/dns/rdata/generic/rt_21.c6
-rw-r--r--lib/dns/rdata/generic/rt_21.h6
-rw-r--r--lib/dns/rdata/generic/sig_24.c6
-rw-r--r--lib/dns/rdata/generic/sig_24.h6
-rw-r--r--lib/dns/rdata/generic/soa_6.c35
-rw-r--r--lib/dns/rdata/generic/soa_6.h6
-rw-r--r--lib/dns/rdata/generic/spf_99.c6
-rw-r--r--lib/dns/rdata/generic/spf_99.h6
-rw-r--r--lib/dns/rdata/generic/sshfp_44.c6
-rw-r--r--lib/dns/rdata/generic/sshfp_44.h6
-rw-r--r--lib/dns/rdata/generic/tkey_249.c6
-rw-r--r--lib/dns/rdata/generic/tkey_249.h6
-rw-r--r--lib/dns/rdata/generic/txt_16.c4
-rw-r--r--lib/dns/rdata/generic/txt_16.h6
-rw-r--r--lib/dns/rdata/generic/unspec_103.c6
-rw-r--r--lib/dns/rdata/generic/unspec_103.h6
-rw-r--r--lib/dns/rdata/generic/x25_19.c6
-rw-r--r--lib/dns/rdata/generic/x25_19.h6
-rw-r--r--lib/dns/rdata/hs_4/a_1.c6
-rw-r--r--lib/dns/rdata/hs_4/a_1.h6
-rw-r--r--lib/dns/rdata/in_1/a6_38.c6
-rw-r--r--lib/dns/rdata/in_1/a6_38.h6
-rw-r--r--lib/dns/rdata/in_1/a_1.c6
-rw-r--r--lib/dns/rdata/in_1/a_1.h6
-rw-r--r--lib/dns/rdata/in_1/aaaa_28.c6
-rw-r--r--lib/dns/rdata/in_1/aaaa_28.h6
-rw-r--r--lib/dns/rdata/in_1/apl_42.c4
-rw-r--r--lib/dns/rdata/in_1/apl_42.h6
-rw-r--r--lib/dns/rdata/in_1/dhcid_49.c229
-rw-r--r--lib/dns/rdata/in_1/dhcid_49.h30
-rw-r--r--lib/dns/rdata/in_1/kx_36.c6
-rw-r--r--lib/dns/rdata/in_1/kx_36.h6
-rw-r--r--lib/dns/rdata/in_1/naptr_35.c4
-rw-r--r--lib/dns/rdata/in_1/naptr_35.h6
-rw-r--r--lib/dns/rdata/in_1/nsap-ptr_23.c6
-rw-r--r--lib/dns/rdata/in_1/nsap-ptr_23.h6
-rw-r--r--lib/dns/rdata/in_1/nsap_22.c6
-rw-r--r--lib/dns/rdata/in_1/nsap_22.h6
-rw-r--r--lib/dns/rdata/in_1/px_26.c6
-rw-r--r--lib/dns/rdata/in_1/px_26.h6
-rw-r--r--lib/dns/rdata/in_1/srv_33.c6
-rw-r--r--lib/dns/rdata/in_1/srv_33.h6
-rw-r--r--lib/dns/rdata/in_1/wks_11.c10
-rw-r--r--lib/dns/rdata/in_1/wks_11.h6
-rw-r--r--lib/dns/rdata/rdatastructpre.h6
-rw-r--r--lib/dns/rdata/rdatastructsuf.h6
-rw-r--r--lib/dns/rdatalist.c172
-rw-r--r--lib/dns/rdatalist_p.h15
-rw-r--r--lib/dns/rdataset.c43
-rw-r--r--lib/dns/rdatasetiter.c6
-rw-r--r--lib/dns/rdataslab.c111
-rw-r--r--lib/dns/request.c8
-rw-r--r--lib/dns/resolver.c993
-rw-r--r--lib/dns/result.c9
-rw-r--r--lib/dns/rootns.c11
-rw-r--r--lib/dns/sdb.c28
-rw-r--r--lib/dns/sdlz.c34
-rw-r--r--lib/dns/soa.c6
-rw-r--r--lib/dns/spnego.asn152
-rw-r--r--lib/dns/spnego.c1792
-rw-r--r--lib/dns/spnego.h71
-rw-r--r--lib/dns/spnego_asn1.c885
-rwxr-xr-xlib/dns/spnego_asn1.pl200
-rw-r--r--lib/dns/ssu.c220
-rw-r--r--lib/dns/stats.c353
-rw-r--r--lib/dns/tcpmsg.c6
-rw-r--r--lib/dns/time.c8
-rw-r--r--lib/dns/timer.c6
-rw-r--r--lib/dns/tkey.c337
-rw-r--r--lib/dns/tsig.c157
-rw-r--r--lib/dns/ttl.c6
-rw-r--r--lib/dns/validator.c770
-rw-r--r--lib/dns/version.c6
-rw-r--r--lib/dns/view.c118
-rw-r--r--lib/dns/xfrin.c57
-rw-r--r--lib/dns/zone.c3742
-rw-r--r--lib/dns/zonekey.c6
-rw-r--r--lib/dns/zt.c9
282 files changed, 21418 insertions, 3918 deletions
diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in
index 286a5f9..ef5c12a 100644
--- a/lib/dns/Makefile.in
+++ b/lib/dns/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2003 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.144.18.10 2006/01/06 00:01:43 marka Exp $
+# $Id: Makefile.in,v 1.163 2008/09/24 02:46:22 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -29,10 +29,14 @@ top_srcdir = @top_srcdir@
@BIND9_MAKE_INCLUDES@
+USE_ISC_SPNEGO = @USE_ISC_SPNEGO@
+
CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} \
${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
-CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@
+CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_PKCS11@ @USE_GSSAPI@ \
+ ${USE_ISC_SPNEGO}
+
CWARNINGS =
ISCLIBS = ../../lib/isc/libisc.@A@
@@ -43,7 +47,8 @@ LIBS = @LIBS@
# Alphabetically
-DSTOBJS = dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
+DSTOBJS = @DST_EXTRA_OBJS@ \
+ dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@ \
openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \
opensslrsa_link.@O@
@@ -52,10 +57,10 @@ DSTOBJS = dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
cache.@O@ callbacks.@O@ compress.@O@ \
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
- dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ journal.@O@ keytable.@O@ \
- lib.@O@ log.@O@ lookup.@O@ \
+ dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ journal.@O@ \
+ keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
master.@O@ masterdump.@O@ message.@O@ \
- name.@O@ ncache.@O@ nsec.@O@ order.@O@ peer.@O@ portlist.@O@ \
+ name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ portlist.@O@ \
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@O@ \
rdatalist.@O@ \
rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ request.@O@ \
@@ -68,7 +73,8 @@ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS}
# Alphabetically
-DSTSRCS = dst_api.c dst_lib.c dst_parse.c \
+DSTSRCS = @DST_EXTRA_SRCS@ \
+ dst_api.c dst_lib.c dst_parse.c \
dst_result.c gssapi_link.c gssapictx.c \
hmac_link.c key.c \
openssl_link.c openssldh_link.c \
@@ -77,10 +83,10 @@ DSTSRCS = dst_api.c dst_lib.c dst_parse.c \
DNSSRCS = acache.c acl.c adb.c byaddr.c \
cache.c callbacks.c compress.c \
db.c dbiterator.c dbtable.c diff.c dispatch.c \
- dlz.c dnssec.c ds.c forward.c journal.c keytable.c \
- lib.c log.c lookup.c \
+ dlz.c dnssec.c ds.c forward.c iptable.c journal.c \
+ keytable.c lib.c log.c lookup.c \
master.c masterdump.c message.c \
- name.c ncache.c nsec.c order.c peer.c portlist.c \
+ name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \
rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c \
rdatalist.c \
rdataset.c rdatasetiter.c rdataslab.c request.c \
@@ -169,3 +175,5 @@ subdirs: include/dns/enumtype.h include/dns/enumclass.h \
include/dns/rdatastruct.h code.h
${OBJS}: include/dns/enumtype.h include/dns/enumclass.h \
include/dns/rdatastruct.h
+
+spnego.@O@: spnego_asn1.c spnego.h
diff --git a/lib/dns/acache.c b/lib/dns/acache.c
index cd56c3c..2ad4981 100644
--- a/lib/dns/acache.c
+++ b/lib/dns/acache.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acache.c,v 1.3.2.18 2008/02/07 23:45:56 tbox Exp $ */
+/* $Id: acache.c,v 1.22 2008/02/07 23:46:54 tbox Exp $ */
#include <config.h>
diff --git a/lib/dns/acl.c b/lib/dns/acl.c
index 844c132..3af8dd3 100644
--- a/lib/dns/acl.c
+++ b/lib/dns/acl.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,18 +15,25 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acl.c,v 1.25.18.5 2006/03/02 00:37:21 marka Exp $ */
+/* $Id: acl.c,v 1.50.44.3 2009/01/18 23:47:35 tbox Exp $ */
/*! \file */
#include <config.h>
#include <isc/mem.h>
+#include <isc/once.h>
#include <isc/string.h>
#include <isc/util.h>
#include <dns/acl.h>
+#include <dns/iptable.h>
+/*
+ * Create a new ACL, including an IP table and an array with room
+ * for 'n' ACL elements. The elements are uninitialized and the
+ * length is 0.
+ */
isc_result_t
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
isc_result_t result;
@@ -43,14 +50,23 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
return (ISC_R_NOMEMORY);
acl->mctx = mctx;
acl->name = NULL;
+
result = isc_refcount_init(&acl->refcount, 1);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mctx, acl, sizeof(*acl));
return (result);
}
+
+ result = dns_iptable_create(mctx, &acl->iptable);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, acl, sizeof(*acl));
+ return (result);
+ }
+
acl->elements = NULL;
acl->alloc = 0;
acl->length = 0;
+ acl->has_negatives = ISC_FALSE;
ISC_LINK_INIT(acl, nextincache);
/*
@@ -73,111 +89,282 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
return (result);
}
-isc_result_t
-dns_acl_appendelement(dns_acl_t *acl, const dns_aclelement_t *elt) {
- if (acl->length + 1 > acl->alloc) {
- /*
- * Resize the ACL.
- */
- unsigned int newalloc;
- void *newmem;
-
- newalloc = acl->alloc * 2;
- if (newalloc < 4)
- newalloc = 4;
- newmem = isc_mem_get(acl->mctx,
- newalloc * sizeof(dns_aclelement_t));
- if (newmem == NULL)
- return (ISC_R_NOMEMORY);
- memcpy(newmem, acl->elements,
- acl->length * sizeof(dns_aclelement_t));
- isc_mem_put(acl->mctx, acl->elements,
- acl->alloc * sizeof(dns_aclelement_t));
- acl->elements = newmem;
- acl->alloc = newalloc;
- }
- /*
- * Append the new element.
- */
- acl->elements[acl->length++] = *elt;
-
- return (ISC_R_SUCCESS);
-}
-
+/*
+ * Create a new ACL and initialize it with the value "any" or "none",
+ * depending on the value of the "neg" parameter.
+ * "any" is a positive iptable entry with bit length 0.
+ * "none" is the same as "!any".
+ */
static isc_result_t
dns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
isc_result_t result;
dns_acl_t *acl = NULL;
- result = dns_acl_create(mctx, 1, &acl);
+ result = dns_acl_create(mctx, 0, &acl);
if (result != ISC_R_SUCCESS)
return (result);
- acl->elements[0].negative = neg;
- acl->elements[0].type = dns_aclelementtype_any;
- acl->length = 1;
+
+ result = dns_iptable_addprefix(acl->iptable, NULL, 0, ISC_TF(!neg));
+ if (result != ISC_R_SUCCESS) {
+ dns_acl_detach(&acl);
+ return (result);
+ }
+
*target = acl;
return (result);
}
+/*
+ * Create a new ACL that matches everything.
+ */
isc_result_t
dns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
return (dns_acl_anyornone(mctx, ISC_FALSE, target));
}
+/*
+ * Create a new ACL that matches nothing.
+ */
isc_result_t
dns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
return (dns_acl_anyornone(mctx, ISC_TRUE, target));
}
+/*
+ * If pos is ISC_TRUE, test whether acl is set to "{ any; }"
+ * If pos is ISC_FALSE, test whether acl is set to "{ none; }"
+ */
+static isc_boolean_t
+dns_acl_isanyornone(dns_acl_t *acl, isc_boolean_t pos)
+{
+ /* Should never happen but let's be safe */
+ if (acl == NULL ||
+ acl->iptable == NULL ||
+ acl->iptable->radix == NULL ||
+ acl->iptable->radix->head == NULL ||
+ acl->iptable->radix->head->prefix == NULL)
+ return (ISC_FALSE);
+
+ if (acl->length != 0 || acl->node_count != 1)
+ return (ISC_FALSE);
+
+ if (acl->iptable->radix->head->prefix->bitlen == 0 &&
+ acl->iptable->radix->head->data[0] != NULL &&
+ acl->iptable->radix->head->data[0] ==
+ acl->iptable->radix->head->data[1] &&
+ *(isc_boolean_t *) (acl->iptable->radix->head->data[0]) == pos)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE); /* All others */
+}
+
+/*
+ * Test whether acl is set to "{ any; }"
+ */
+isc_boolean_t
+dns_acl_isany(dns_acl_t *acl)
+{
+ return (dns_acl_isanyornone(acl, ISC_TRUE));
+}
+
+/*
+ * Test whether acl is set to "{ none; }"
+ */
+isc_boolean_t
+dns_acl_isnone(dns_acl_t *acl)
+{
+ return (dns_acl_isanyornone(acl, ISC_FALSE));
+}
+
+/*
+ * Determine whether a given address or signer matches a given ACL.
+ * For a match with a positive ACL element or iptable radix entry,
+ * return with a positive value in match; for a match with a negated ACL
+ * element or radix entry, return with a negative value in match.
+ */
isc_result_t
dns_acl_match(const isc_netaddr_t *reqaddr,
const dns_name_t *reqsigner,
const dns_acl_t *acl,
const dns_aclenv_t *env,
int *match,
- dns_aclelement_t const**matchelt)
+ const dns_aclelement_t **matchelt)
{
+ isc_uint16_t bitlen, family;
+ isc_prefix_t pfx;
+ isc_radix_node_t *node = NULL;
+ const isc_netaddr_t *addr;
+ isc_netaddr_t v4addr;
+ isc_result_t result;
+ int match_num = -1;
unsigned int i;
REQUIRE(reqaddr != NULL);
REQUIRE(matchelt == NULL || *matchelt == NULL);
-
+
+ if (env == NULL || env->match_mapped == ISC_FALSE ||
+ reqaddr->family != AF_INET6 ||
+ !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
+ addr = reqaddr;
+ else {
+ isc_netaddr_fromv4mapped(&v4addr, reqaddr);
+ addr = &v4addr;
+ }
+
+ /* Always match with host addresses. */
+ family = addr->family;
+ bitlen = family == AF_INET6 ? 128 : 32;
+ NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
+
+ /* Assume no match. */
+ *match = 0;
+
+ /* Search radix. */
+ result = isc_radix_search(acl->iptable->radix, &node, &pfx);
+
+ /* Found a match. */
+ if (result == ISC_R_SUCCESS && node != NULL) {
+ match_num = node->node_num[ISC_IS6(family)];
+ if (*(isc_boolean_t *) node->data[ISC_IS6(family)] == ISC_TRUE)
+ *match = match_num;
+ else
+ *match = -match_num;
+ }
+
+ /* Now search non-radix elements for a match with a lower node_num. */
for (i = 0; i < acl->length; i++) {
dns_aclelement_t *e = &acl->elements[i];
+ /* Already found a better match? */
+ if (match_num != -1 && match_num < e->node_num) {
+ isc_refcount_destroy(&pfx.refcount);
+ return (ISC_R_SUCCESS);
+ }
+
if (dns_aclelement_match(reqaddr, reqsigner,
e, env, matchelt)) {
- *match = e->negative ? -((int)i+1) : ((int)i+1);
+ if (match_num == -1 || e->node_num < match_num) {
+ if (e->negative == ISC_TRUE)
+ *match = -e->node_num;
+ else
+ *match = e->node_num;
+ }
+ isc_refcount_destroy(&pfx.refcount);
return (ISC_R_SUCCESS);
}
}
- /* No match. */
- *match = 0;
+
+ isc_refcount_destroy(&pfx.refcount);
return (ISC_R_SUCCESS);
}
+/*
+ * Merge the contents of one ACL into another. Call dns_iptable_merge()
+ * for the IP tables, then concatenate the element arrays.
+ *
+ * If pos is set to false, then the nested ACL is to be negated. This
+ * means reverse the sense of each *positive* element or IP table node,
+ * but leave negatives alone, so as to prevent a double-negative causing
+ * an unexpected positive match in the parent ACL.
+ */
isc_result_t
-dns_acl_elementmatch(const dns_acl_t *acl,
- const dns_aclelement_t *elt,
- const dns_aclelement_t **matchelt)
+dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
{
- unsigned int i;
+ isc_result_t result;
+ unsigned int newalloc, nelem, i;
+ int max_node = 0, nodes;
- REQUIRE(elt != NULL);
- REQUIRE(matchelt == NULL || *matchelt == NULL);
-
- for (i = 0; i < acl->length; i++) {
- dns_aclelement_t *e = &acl->elements[i];
+ /* Resize the element array if needed. */
+ if (dest->length + source->length > dest->alloc) {
+ void *newmem;
- if (dns_aclelement_equal(e, elt) == ISC_TRUE) {
- if (matchelt != NULL)
- *matchelt = e;
- return (ISC_R_SUCCESS);
+ newalloc = dest->alloc + source->alloc;
+ if (newalloc < 4)
+ newalloc = 4;
+
+ newmem = isc_mem_get(dest->mctx,
+ newalloc * sizeof(dns_aclelement_t));
+ if (newmem == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* Copy in the original elements */
+ memcpy(newmem, dest->elements,
+ dest->length * sizeof(dns_aclelement_t));
+
+ /* Release the memory for the old elements array */
+ isc_mem_put(dest->mctx, dest->elements,
+ dest->alloc * sizeof(dns_aclelement_t));
+ dest->elements = newmem;
+ dest->alloc = newalloc;
+ }
+
+ /*
+ * Now copy in the new elements, increasing their node_num
+ * values so as to keep the new ACL consistent. If we're
+ * negating, then negate positive elements, but keep negative
+ * elements the same for security reasons.
+ */
+ nelem = dest->length;
+ dest->length += source->length;
+ for (i = 0; i < source->length; i++) {
+ if (source->elements[i].node_num > max_node)
+ max_node = source->elements[i].node_num;
+
+ /* Copy type. */
+ dest->elements[nelem + i].type = source->elements[i].type;
+
+ /* Adjust node numbering. */
+ dest->elements[nelem + i].node_num =
+ source->elements[i].node_num + dest->node_count;
+
+ /* Duplicate nested acl. */
+ if (source->elements[i].type == dns_aclelementtype_nestedacl &&
+ source->elements[i].nestedacl != NULL)
+ dns_acl_attach(source->elements[i].nestedacl,
+ &dest->elements[nelem + i].nestedacl);
+
+ /* Duplicate key name. */
+ if (source->elements[i].type == dns_aclelementtype_keyname) {
+ dns_name_init(&dest->elements[nelem+i].keyname, NULL);
+ result = dns_name_dup(&source->elements[i].keyname,
+ dest->mctx,
+ &dest->elements[nelem+i].keyname);
+ if (result != ISC_R_SUCCESS)
+ return result;
+ }
+
+ /* reverse sense of positives if this is a negative acl */
+ if (!pos && source->elements[i].negative == ISC_FALSE) {
+ dest->elements[nelem + i].negative = ISC_TRUE;
+ } else {
+ dest->elements[nelem + i].negative =
+ source->elements[i].negative;
}
}
- return (ISC_R_NOTFOUND);
+
+ /*
+ * Merge the iptables. Make sure the destination ACL's
+ * node_count value is set correctly afterward.
+ */
+ nodes = max_node + dest->node_count;
+ result = dns_iptable_merge(dest->iptable, source->iptable, pos);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (nodes > dest->node_count)
+ dest->node_count = nodes;
+
+ return (ISC_R_SUCCESS);
}
+/*
+ * Like dns_acl_match, but matches against the single ACL element 'e'
+ * rather than a complete ACL, and returns ISC_TRUE iff it matched.
+ *
+ * To determine whether the match was positive or negative, the
+ * caller should examine e->negative. Since the element 'e' may be
+ * a reference to a named ACL or a nested ACL, a matching element
+ * returned through 'matchelt' is not necessarily 'e' itself.
+ */
isc_boolean_t
dns_aclelement_match(const isc_netaddr_t *reqaddr,
const dns_name_t *reqsigner,
@@ -186,92 +373,68 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
const dns_aclelement_t **matchelt)
{
dns_acl_t *inner = NULL;
- const isc_netaddr_t *addr;
- isc_netaddr_t v4addr;
int indirectmatch;
isc_result_t result;
switch (e->type) {
- case dns_aclelementtype_ipprefix:
- if (env == NULL ||
- env->match_mapped == ISC_FALSE ||
- reqaddr->family != AF_INET6 ||
- !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
- addr = reqaddr;
- else {
- isc_netaddr_fromv4mapped(&v4addr, reqaddr);
- addr = &v4addr;
- }
-
- if (isc_netaddr_eqprefix(addr,
- &e->u.ip_prefix.address,
- e->u.ip_prefix.prefixlen))
- goto matched;
- break;
-
case dns_aclelementtype_keyname:
if (reqsigner != NULL &&
- dns_name_equal(reqsigner, &e->u.keyname))
- goto matched;
- break;
-
+ dns_name_equal(reqsigner, &e->keyname)) {
+ if (matchelt != NULL)
+ *matchelt = e;
+ return (ISC_TRUE);
+ } else {
+ return (ISC_FALSE);
+ }
+
case dns_aclelementtype_nestedacl:
- inner = e->u.nestedacl;
- nested:
- result = dns_acl_match(reqaddr, reqsigner,
- inner,
- env,
- &indirectmatch, matchelt);
- INSIST(result == ISC_R_SUCCESS);
-
- /*
- * Treat negative matches in indirect ACLs as
- * "no match".
- * That way, a negated indirect ACL will never become
- * a surprise positive match through double negation.
- * XXXDCL this should be documented.
- */
- if (indirectmatch > 0)
- goto matchelt_set;
-
- /*
- * A negative indirect match may have set *matchelt,
- * but we don't want it set when we return.
- */
- if (matchelt != NULL)
- *matchelt = NULL;
+ inner = e->nestedacl;
break;
-
- case dns_aclelementtype_any:
- matched:
- if (matchelt != NULL)
- *matchelt = e;
- matchelt_set:
- return (ISC_TRUE);
-
+
case dns_aclelementtype_localhost:
- if (env != NULL && env->localhost != NULL) {
- inner = env->localhost;
- goto nested;
- } else {
- break;
- }
-
+ if (env == NULL || env->localhost == NULL)
+ return (ISC_FALSE);
+ inner = env->localhost;
+ break;
+
case dns_aclelementtype_localnets:
- if (env != NULL && env->localnets != NULL) {
- inner = env->localnets;
- goto nested;
- } else {
- break;
- }
-
+ if (env == NULL || env->localnets == NULL)
+ return (ISC_FALSE);
+ inner = env->localnets;
+ break;
+
default:
+ /* Should be impossible. */
INSIST(0);
- break;
}
+ result = dns_acl_match(reqaddr, reqsigner, inner, env,
+ &indirectmatch, matchelt);
+ INSIST(result == ISC_R_SUCCESS);
+
+ /*
+ * Treat negative matches in indirect ACLs as "no match".
+ * That way, a negated indirect ACL will never become a
+ * surprise positive match through double negation.
+ * XXXDCL this should be documented.
+ */
+
+ if (indirectmatch > 0) {
+ if (matchelt != NULL)
+ *matchelt = e;
+ return (ISC_TRUE);
+ }
+
+ /*
+ * A negative indirect match may have set *matchelt, but we don't
+ * want it set when we return.
+ */
+
+ if (matchelt != NULL)
+ *matchelt = NULL;
+
return (ISC_FALSE);
-}
+}
void
dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
@@ -285,15 +448,10 @@ destroy(dns_acl_t *dacl) {
unsigned int i;
for (i = 0; i < dacl->length; i++) {
dns_aclelement_t *de = &dacl->elements[i];
- switch (de->type) {
- case dns_aclelementtype_keyname:
- dns_name_free(&de->u.keyname, dacl->mctx);
- break;
- case dns_aclelementtype_nestedacl:
- dns_acl_detach(&de->u.nestedacl);
- break;
- default:
- break;
+ if (de->type == dns_aclelementtype_keyname) {
+ dns_name_free(&de->keyname, dacl->mctx);
+ } else if (de->type == dns_aclelementtype_nestedacl) {
+ dns_acl_detach(&de->nestedacl);
}
}
if (dacl->elements != NULL)
@@ -301,6 +459,8 @@ destroy(dns_acl_t *dacl) {
dacl->alloc * sizeof(dns_aclelement_t));
if (dacl->name != NULL)
isc_mem_free(dacl->mctx, dacl->name);
+ if (dacl->iptable != NULL)
+ dns_iptable_detach(&dacl->iptable);
isc_refcount_destroy(&dacl->refcount);
dacl->magic = 0;
isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
@@ -317,69 +477,83 @@ dns_acl_detach(dns_acl_t **aclp) {
*aclp = NULL;
}
-isc_boolean_t
-dns_aclelement_equal(const dns_aclelement_t *ea, const dns_aclelement_t *eb) {
- if (ea->type != eb->type)
- return (ISC_FALSE);
- switch (ea->type) {
- case dns_aclelementtype_ipprefix:
- if (ea->u.ip_prefix.prefixlen !=
- eb->u.ip_prefix.prefixlen)
- return (ISC_FALSE);
- return (isc_netaddr_eqprefix(&ea->u.ip_prefix.address,
- &eb->u.ip_prefix.address,
- ea->u.ip_prefix.prefixlen));
- case dns_aclelementtype_keyname:
- return (dns_name_equal(&ea->u.keyname, &eb->u.keyname));
- case dns_aclelementtype_nestedacl:
- return (dns_acl_equal(ea->u.nestedacl, eb->u.nestedacl));
- case dns_aclelementtype_localhost:
- case dns_aclelementtype_localnets:
- case dns_aclelementtype_any:
- return (ISC_TRUE);
- default:
- INSIST(0);
- return (ISC_FALSE);
- }
+
+static isc_once_t insecure_prefix_once = ISC_ONCE_INIT;
+static isc_mutex_t insecure_prefix_lock;
+static isc_boolean_t insecure_prefix_found;
+
+static void
+initialize_action(void) {
+ RUNTIME_CHECK(isc_mutex_init(&insecure_prefix_lock) == ISC_R_SUCCESS);
}
-isc_boolean_t
-dns_acl_equal(const dns_acl_t *a, const dns_acl_t *b) {
- unsigned int i;
- if (a == b)
- return (ISC_TRUE);
- if (a->length != b->length)
- return (ISC_FALSE);
- for (i = 0; i < a->length; i++) {
- if (! dns_aclelement_equal(&a->elements[i],
- &b->elements[i]))
- return (ISC_FALSE);
+/*
+ * Called via isc_radix_walk() to find IP table nodes that are
+ * insecure.
+ */
+static void
+is_insecure(isc_prefix_t *prefix, void **data) {
+ isc_boolean_t secure;
+ int bitlen, family;
+
+ bitlen = prefix->bitlen;
+ family = prefix->family;
+
+ /* Negated entries are always secure. */
+ secure = * (isc_boolean_t *)data[ISC_IS6(family)];
+ if (!secure) {
+ return;
}
- return (ISC_TRUE);
-}
-static isc_boolean_t
-is_loopback(const dns_aclipprefix_t *p) {
- switch (p->address.family) {
+ /* If loopback prefix found, return */
+ switch (family) {
case AF_INET:
- if (p->prefixlen == 32 &&
- htonl(p->address.type.in.s_addr) == INADDR_LOOPBACK)
- return (ISC_TRUE);
+ if (bitlen == 32 &&
+ htonl(prefix->add.sin.s_addr) == INADDR_LOOPBACK)
+ return;
break;
case AF_INET6:
- if (p->prefixlen == 128 &&
- IN6_IS_ADDR_LOOPBACK(&p->address.type.in6))
- return (ISC_TRUE);
+ if (bitlen == 128 && IN6_IS_ADDR_LOOPBACK(&prefix->add.sin6))
+ return;
break;
default:
break;
}
- return (ISC_FALSE);
+
+ /* Non-negated, non-loopback */
+ insecure_prefix_found = ISC_TRUE; /* LOCKED */
+ return;
}
+/*
+ * Return ISC_TRUE iff the acl 'a' is considered insecure, that is,
+ * if it contains IP addresses other than those of the local host.
+ * This is intended for applications such as printing warning
+ * messages for suspect ACLs; it is not intended for making access
+ * control decisions. We make no guarantee that an ACL for which
+ * this function returns ISC_FALSE is safe.
+ */
isc_boolean_t
dns_acl_isinsecure(const dns_acl_t *a) {
unsigned int i;
+ isc_boolean_t insecure;
+
+ RUNTIME_CHECK(isc_once_do(&insecure_prefix_once,
+ initialize_action) == ISC_R_SUCCESS);
+
+ /*
+ * Walk radix tree to find out if there are any non-negated,
+ * non-loopback prefixes.
+ */
+ LOCK(&insecure_prefix_lock);
+ insecure_prefix_found = ISC_FALSE;
+ isc_radix_process(a->iptable->radix, is_insecure);
+ insecure = insecure_prefix_found;
+ UNLOCK(&insecure_prefix_lock);
+ if (insecure)
+ return(ISC_TRUE);
+
+ /* Now check non-radix elements */
for (i = 0; i < a->length; i++) {
dns_aclelement_t *e = &a->elements[i];
@@ -388,23 +562,16 @@ dns_acl_isinsecure(const dns_acl_t *a) {
continue;
switch (e->type) {
- case dns_aclelementtype_ipprefix:
- /* The loopback address is considered secure. */
- if (! is_loopback(&e->u.ip_prefix))
- return (ISC_TRUE);
- continue;
-
case dns_aclelementtype_keyname:
case dns_aclelementtype_localhost:
continue;
case dns_aclelementtype_nestedacl:
- if (dns_acl_isinsecure(e->u.nestedacl))
+ if (dns_acl_isinsecure(e->nestedacl))
return (ISC_TRUE);
continue;
-
+
case dns_aclelementtype_localnets:
- case dns_aclelementtype_any:
return (ISC_TRUE);
default:
@@ -412,10 +579,14 @@ dns_acl_isinsecure(const dns_acl_t *a) {
return (ISC_TRUE);
}
}
+
/* No insecure elements were found. */
return (ISC_FALSE);
}
+/*
+ * Initialize ACL environment, setting up localhost and localnets ACLs
+ */
isc_result_t
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
isc_result_t result;
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
index ae5dec8..7056215 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.c,v 1.215.18.24 2008/10/17 03:35:14 marka Exp $ */
+/* $Id: adb.c,v 1.243.42.4 2009/02/03 22:34:28 jinmei Exp $ */
/*! \file
*
@@ -26,13 +26,6 @@
*
*/
-/*%
- * After we have cleaned all buckets, dump the database contents.
- */
-#if 0
-#define DUMP_ADB_AFTER_CLEANING
-#endif
-
#include <config.h>
#include <limits.h>
@@ -40,9 +33,9 @@
#include <isc/mutexblock.h>
#include <isc/netaddr.h>
#include <isc/random.h>
-#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/stats.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/task.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/adb.h>
@@ -55,28 +48,29 @@
#include <dns/rdatatype.h>
#include <dns/resolver.h>
#include <dns/result.h>
+#include <dns/stats.h>
-#define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b')
-#define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
-#define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N')
-#define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
-#define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H')
+#define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b')
+#define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
+#define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N')
+#define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
+#define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H')
#define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
-#define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z')
+#define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z')
#define DNS_ADBLAMEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
-#define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E')
-#define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
-#define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4')
-#define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
-#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
-#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
+#define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E')
+#define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
+#define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4')
+#define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
+#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
+#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
/*!
* The number of buckets needs to be a prime (for good hashing).
*
* XXXRTH How many buckets do we need?
*/
-#define NBUCKETS 1009 /*%< how many buckets for names/addrs */
+#define NBUCKETS 1009 /*%< how many buckets for names/addrs */
/*!
* For type 3 negative cache entries, we will remember that the address is
@@ -84,26 +78,25 @@
* The intent is to keep us from constantly asking about A/AAAA records
* if the zone has extremely low TTLs.
*/
-#define ADB_CACHE_MINIMUM 10 /*%< seconds */
-#define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
-#define ADB_ENTRY_WINDOW 1800 /*%< seconds */
+#define ADB_CACHE_MINIMUM 10 /*%< seconds */
+#define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
+#define ADB_ENTRY_WINDOW 1800 /*%< seconds */
/*%
- * Wake up every CLEAN_SECONDS and clean CLEAN_BUCKETS buckets, so that all
- * buckets are cleaned in CLEAN_PERIOD seconds.
+ * The period in seconds after which an ADB name entry is regarded as stale
+ * and forced to be cleaned up.
+ * TODO: This should probably be configurable at run-time.
*/
-#define CLEAN_PERIOD 3600
-/*% See #CLEAN_PERIOD */
-#define CLEAN_SECONDS 30
-/*% See #CLEAN_PERIOD */
-#define CLEAN_BUCKETS ((NBUCKETS * CLEAN_SECONDS) / CLEAN_PERIOD)
+#ifndef ADB_STALE_MARGIN
+#define ADB_STALE_MARGIN 1800
+#endif
-#define FREE_ITEMS 64 /*%< free count for memory pools */
-#define FILL_COUNT 16 /*%< fill count for memory pools */
+#define FREE_ITEMS 64 /*%< free count for memory pools */
+#define FILL_COUNT 16 /*%< fill count for memory pools */
-#define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */
+#define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */
-#define DNS_ADB_MINADBSIZE (1024*1024) /*%< 1 Megabyte */
+#define DNS_ADB_MINADBSIZE (1024*1024) /*%< 1 Megabyte */
typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
typedef struct dns_adbnamehook dns_adbnamehook_t;
@@ -115,61 +108,62 @@ typedef struct dns_adbfetch6 dns_adbfetch6_t;
/*% dns adb structure */
struct dns_adb {
- unsigned int magic;
+ unsigned int magic;
- isc_mutex_t lock;
- isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */
+ isc_mutex_t lock;
+ isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */
isc_mutex_t overmemlock; /*%< Covers overmem */
- isc_mem_t *mctx;
- dns_view_t *view;
- isc_timermgr_t *timermgr;
- isc_timer_t *timer;
- isc_taskmgr_t *taskmgr;
- isc_task_t *task;
- isc_boolean_t overmem;
-
- isc_interval_t tick_interval;
- int next_cleanbucket;
-
- unsigned int irefcnt;
- unsigned int erefcnt;
-
- isc_mutex_t mplock;
- isc_mempool_t *nmp; /*%< dns_adbname_t */
- isc_mempool_t *nhmp; /*%< dns_adbnamehook_t */
- isc_mempool_t *limp; /*%< dns_adblameinfo_t */
- isc_mempool_t *emp; /*%< dns_adbentry_t */
- isc_mempool_t *ahmp; /*%< dns_adbfind_t */
- isc_mempool_t *aimp; /*%< dns_adbaddrinfo_t */
- isc_mempool_t *afmp; /*%< dns_adbfetch_t */
+ isc_mem_t *mctx;
+ dns_view_t *view;
+
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *task;
+ isc_boolean_t overmem;
+
+ isc_interval_t tick_interval;
+ int next_cleanbucket;
+
+ unsigned int irefcnt;
+ unsigned int erefcnt;
+
+ isc_mutex_t mplock;
+ isc_mempool_t *nmp; /*%< dns_adbname_t */
+ isc_mempool_t *nhmp; /*%< dns_adbnamehook_t */
+ isc_mempool_t *limp; /*%< dns_adblameinfo_t */
+ isc_mempool_t *emp; /*%< dns_adbentry_t */
+ isc_mempool_t *ahmp; /*%< dns_adbfind_t */
+ isc_mempool_t *aimp; /*%< dns_adbaddrinfo_t */
+ isc_mempool_t *afmp; /*%< dns_adbfetch_t */
/*!
* Bucketized locks and lists for names.
*
* XXXRTH Have a per-bucket structure that contains all of these?
*/
- dns_adbnamelist_t names[NBUCKETS];
+ dns_adbnamelist_t names[NBUCKETS];
+ dns_adbnamelist_t deadnames[NBUCKETS];
/*% See dns_adbnamelist_t */
- isc_mutex_t namelocks[NBUCKETS];
+ isc_mutex_t namelocks[NBUCKETS];
/*% See dns_adbnamelist_t */
- isc_boolean_t name_sd[NBUCKETS];
+ isc_boolean_t name_sd[NBUCKETS];
/*% See dns_adbnamelist_t */
- unsigned int name_refcnt[NBUCKETS];
+ unsigned int name_refcnt[NBUCKETS];
/*!
* Bucketized locks for entries.
*
* XXXRTH Have a per-bucket structure that contains all of these?
*/
- dns_adbentrylist_t entries[NBUCKETS];
- isc_mutex_t entrylocks[NBUCKETS];
- isc_boolean_t entry_sd[NBUCKETS]; /*%< shutting down */
- unsigned int entry_refcnt[NBUCKETS];
-
- isc_event_t cevent;
- isc_boolean_t cevent_sent;
- isc_boolean_t shutting_down;
- isc_eventlist_t whenshutdown;
+ dns_adbentrylist_t entries[NBUCKETS];
+ dns_adbentrylist_t deadentries[NBUCKETS];
+ isc_mutex_t entrylocks[NBUCKETS];
+ isc_boolean_t entry_sd[NBUCKETS]; /*%< shutting down */
+ unsigned int entry_refcnt[NBUCKETS];
+
+ isc_event_t cevent;
+ isc_boolean_t cevent_sent;
+ isc_boolean_t shutting_down;
+ isc_eventlist_t whenshutdown;
};
/*
@@ -178,34 +172,35 @@ struct dns_adb {
/*% dns_adbname structure */
struct dns_adbname {
- unsigned int magic;
- dns_name_t name;
- dns_adb_t *adb;
- unsigned int partial_result;
- unsigned int flags;
- int lock_bucket;
- dns_name_t target;
- isc_stdtime_t expire_target;
- isc_stdtime_t expire_v4;
- isc_stdtime_t expire_v6;
- unsigned int chains;
- dns_adbnamehooklist_t v4;
- dns_adbnamehooklist_t v6;
- dns_adbfetch_t *fetch_a;
- dns_adbfetch_t *fetch_aaaa;
- unsigned int fetch_err;
- unsigned int fetch6_err;
- dns_adbfindlist_t finds;
- ISC_LINK(dns_adbname_t) plink;
+ unsigned int magic;
+ dns_name_t name;
+ dns_adb_t *adb;
+ unsigned int partial_result;
+ unsigned int flags;
+ int lock_bucket;
+ dns_name_t target;
+ isc_stdtime_t expire_target;
+ isc_stdtime_t expire_v4;
+ isc_stdtime_t expire_v6;
+ unsigned int chains;
+ dns_adbnamehooklist_t v4;
+ dns_adbnamehooklist_t v6;
+ dns_adbfetch_t *fetch_a;
+ dns_adbfetch_t *fetch_aaaa;
+ unsigned int fetch_err;
+ unsigned int fetch6_err;
+ dns_adbfindlist_t finds;
+ /* for LRU-based management */
+ isc_stdtime_t last_used;
+
+ ISC_LINK(dns_adbname_t) plink;
};
/*% The adbfetch structure */
struct dns_adbfetch {
- unsigned int magic;
- dns_adbnamehook_t *namehook;
- dns_adbentry_t *entry;
- dns_fetch_t *fetch;
- dns_rdataset_t rdataset;
+ unsigned int magic;
+ dns_fetch_t *fetch;
+ dns_rdataset_t rdataset;
};
/*%
@@ -214,9 +209,9 @@ struct dns_adbfetch {
* namehook that will contain the next address this host has.
*/
struct dns_adbnamehook {
- unsigned int magic;
- dns_adbentry_t *entry;
- ISC_LINK(dns_adbnamehook_t) plink;
+ unsigned int magic;
+ dns_adbentry_t *entry;
+ ISC_LINK(dns_adbnamehook_t) plink;
};
/*%
@@ -225,13 +220,13 @@ struct dns_adbnamehook {
* extended to other types of information about zones.
*/
struct dns_adblameinfo {
- unsigned int magic;
+ unsigned int magic;
- dns_name_t qname;
- dns_rdatatype_t qtype;
- isc_stdtime_t lame_timer;
+ dns_name_t qname;
+ dns_rdatatype_t qtype;
+ isc_stdtime_t lame_timer;
- ISC_LINK(dns_adblameinfo_t) plink;
+ ISC_LINK(dns_adblameinfo_t) plink;
};
/*%
@@ -240,16 +235,16 @@ struct dns_adblameinfo {
* the host.
*/
struct dns_adbentry {
- unsigned int magic;
+ unsigned int magic;
- int lock_bucket;
- unsigned int refcnt;
+ int lock_bucket;
+ unsigned int refcnt;
- unsigned int flags;
- unsigned int srtt;
- isc_sockaddr_t sockaddr;
+ unsigned int flags;
+ unsigned int srtt;
+ isc_sockaddr_t sockaddr;
- isc_stdtime_t expires;
+ isc_stdtime_t expires;
/*%<
* A nonzero 'expires' field indicates that the entry should
* persist until that time. This allows entries found
@@ -258,8 +253,8 @@ struct dns_adbentry {
* name.
*/
- ISC_LIST(dns_adblameinfo_t) lameinfo;
- ISC_LINK(dns_adbentry_t) plink;
+ ISC_LIST(dns_adblameinfo_t) lameinfo;
+ ISC_LINK(dns_adbentry_t) plink;
};
/*
@@ -284,7 +279,8 @@ static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
unsigned int, int *);
static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
- isc_sockaddr_t *, int *);
+ isc_sockaddr_t *, int *,
+ isc_stdtime_t);
static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
static void print_dns_name(FILE *, dns_name_t *);
static void print_namehook_list(FILE *, const char *legend,
@@ -305,15 +301,15 @@ static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
static void clean_target(dns_adb_t *, dns_name_t *);
static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
unsigned int);
-static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t,
- isc_boolean_t);
+static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
+static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
+ isc_stdtime_t);
static void cancel_fetches_at_name(dns_adbname_t *);
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
dns_rdatatype_t);
static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
dns_rdatatype_t);
static inline void check_exit(dns_adb_t *);
-static void timer_cleanup(isc_task_t *, isc_event_t *);
static void destroy(dns_adb_t *);
static isc_boolean_t shutdown_names(dns_adb_t *);
static isc_boolean_t shutdown_entries(dns_adb_t *);
@@ -328,28 +324,34 @@ static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
/*
* MUST NOT overlap DNS_ADBFIND_* flags!
*/
-#define FIND_EVENT_SENT 0x40000000
-#define FIND_EVENT_FREED 0x80000000
-#define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
-#define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
-
-#define NAME_NEEDS_POKE 0x80000000
-#define NAME_IS_DEAD 0x40000000
-#define NAME_HINT_OK DNS_ADBFIND_HINTOK
-#define NAME_GLUE_OK DNS_ADBFIND_GLUEOK
-#define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE
-#define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
-#define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
-#define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
-#define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
+#define FIND_EVENT_SENT 0x40000000
+#define FIND_EVENT_FREED 0x80000000
+#define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
+#define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
+
+#define NAME_NEEDS_POKE 0x80000000
+#define NAME_IS_DEAD 0x40000000
+#define NAME_HINT_OK DNS_ADBFIND_HINTOK
+#define NAME_GLUE_OK DNS_ADBFIND_GLUEOK
+#define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE
+#define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
+#define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
+#define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
+#define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
+
+/*
+ * Private flag(s) for entries.
+ * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0.
+ */
+#define ENTRY_IS_DEAD 0x80000000
/*
* To the name, address classes are all that really exist. If it has a
* V6 address it doesn't care if it came from a AAAA query.
*/
-#define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
-#define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
-#define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n))
+#define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
+#define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
+#define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n))
/*
* Fetches are broken out into A and AAAA types. In some cases,
@@ -358,34 +360,34 @@ static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
* Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
* are now equal to FETCH_V4 and FETCH_V6, respectively.
*/
-#define NAME_FETCH_A(n) ((n)->fetch_a != NULL)
-#define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
-#define NAME_FETCH_V4(n) (NAME_FETCH_A(n))
-#define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n))
-#define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
+#define NAME_FETCH_A(n) ((n)->fetch_a != NULL)
+#define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
+#define NAME_FETCH_V4(n) (NAME_FETCH_A(n))
+#define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n))
+#define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
/*
* Find options and tests to see if there are addresses on the list.
*/
-#define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
-#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
-#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
+#define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
+#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
+#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
!= 0)
-#define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \
+#define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \
!= 0)
-#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
-#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
-#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
-#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
+#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
+#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
+#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
+#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
/*
* These are currently used on simple unsigned ints, so they are
* not really associated with any particular type.
*/
-#define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0)
-#define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
+#define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0)
+#define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
-#define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
+#define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
/*
* Find out if the flags on a name (nf) indicate if it is a hint or
@@ -398,19 +400,19 @@ static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
#define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
((o) & DNS_ADBFIND_STARTATZONE))
-#define ENTER_LEVEL ISC_LOG_DEBUG(50)
-#define EXIT_LEVEL ENTER_LEVEL
-#define CLEAN_LEVEL ISC_LOG_DEBUG(100)
-#define DEF_LEVEL ISC_LOG_DEBUG(5)
-#define NCACHE_LEVEL ISC_LOG_DEBUG(20)
+#define ENTER_LEVEL ISC_LOG_DEBUG(50)
+#define EXIT_LEVEL ENTER_LEVEL
+#define CLEAN_LEVEL ISC_LOG_DEBUG(100)
+#define DEF_LEVEL ISC_LOG_DEBUG(5)
+#define NCACHE_LEVEL ISC_LOG_DEBUG(20)
-#define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
+#define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
(r) == DNS_R_NCACHENXRRSET)
-#define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \
+#define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \
(r) == DNS_R_NXRRSET)
-#define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \
+#define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \
(r) == DNS_R_NCACHENXDOMAIN)
-#define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \
+#define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \
(r) == DNS_R_NXRRSET || \
(r) == DNS_R_HINTNXRRSET)
@@ -418,14 +420,14 @@ static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
* Error state rankings.
*/
-#define FIND_ERR_SUCCESS 0 /* highest rank */
-#define FIND_ERR_CANCELED 1
-#define FIND_ERR_FAILURE 2
-#define FIND_ERR_NXDOMAIN 3
-#define FIND_ERR_NXRRSET 4
-#define FIND_ERR_UNEXPECTED 5
-#define FIND_ERR_NOTFOUND 6
-#define FIND_ERR_MAX 7
+#define FIND_ERR_SUCCESS 0 /* highest rank */
+#define FIND_ERR_CANCELED 1
+#define FIND_ERR_FAILURE 2
+#define FIND_ERR_NXDOMAIN 3
+#define FIND_ERR_NXRRSET 4
+#define FIND_ERR_UNEXPECTED 5
+#define FIND_ERR_NOTFOUND 6
+#define FIND_ERR_MAX 7
static const char *errnames[] = {
"success",
@@ -437,7 +439,7 @@ static const char *errnames[] = {
"not_found"
};
-#define NEWERR(old, new) (ISC_MIN((old), (new)))
+#define NEWERR(old, new) (ISC_MIN((old), (new)))
static isc_result_t find_err_map[FIND_ERR_MAX] = {
ISC_R_SUCCESS,
@@ -446,7 +448,7 @@ static isc_result_t find_err_map[FIND_ERR_MAX] = {
DNS_R_NXDOMAIN,
DNS_R_NXRRSET,
ISC_R_UNEXPECTED,
- ISC_R_NOTFOUND /* not YET found */
+ ISC_R_NOTFOUND /* not YET found */
};
static void
@@ -463,6 +465,15 @@ DP(int level, const char *format, ...) {
va_end(args);
}
+/*%
+ * Increment resolver-related statistics counters.
+ */
+static inline void
+inc_stats(dns_adb_t *adb, isc_statscounter_t counter) {
+ if (adb->view->resstats != NULL)
+ isc_stats_increment(adb->view->resstats, counter);
+}
+
static inline dns_ttl_t
ttlclamp(dns_ttl_t ttl) {
if (ttl < ADB_CACHE_MINIMUM)
@@ -536,7 +547,8 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
goto fail;
}
- foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket);
+ foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket,
+ now);
if (foundentry == NULL) {
dns_adbentry_t *entry;
@@ -617,6 +629,7 @@ kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
dns_adbname_t *name;
isc_boolean_t result = ISC_FALSE;
isc_boolean_t result4, result6;
+ int bucket;
dns_adb_t *adb;
INSIST(n != NULL);
@@ -661,8 +674,13 @@ kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
if (result)
result = dec_adb_irefcnt(adb);
} else {
- name->flags |= NAME_IS_DEAD;
cancel_fetches_at_name(name);
+ if (!NAME_DEAD(name)) {
+ bucket = name->lock_bucket;
+ ISC_LIST_UNLINK(adb->names[bucket], name, plink);
+ ISC_LIST_APPEND(adb->deadnames[bucket], name, plink);
+ name->flags |= NAME_IS_DEAD;
+ }
}
return (result);
}
@@ -671,11 +689,8 @@ kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
* Requires the name's bucket be locked and no entry buckets be locked.
*/
static isc_boolean_t
-check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now,
- isc_boolean_t overmem)
-{
+check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
dns_adb_t *adb;
- isc_boolean_t expire;
isc_boolean_t result4 = ISC_FALSE;
isc_boolean_t result6 = ISC_FALSE;
@@ -683,20 +698,10 @@ check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now,
adb = name->adb;
INSIST(DNS_ADB_VALID(adb));
- if (overmem) {
- isc_uint32_t val;
-
- isc_random_get(&val);
-
- expire = ISC_TF((val % 4) == 0);
- } else
- expire = ISC_FALSE;
-
/*
* Check to see if we need to remove the v4 addresses
*/
- if (!NAME_FETCH_V4(name) &&
- (expire || EXPIRE_OK(name->expire_v4, now))) {
+ if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
if (NAME_HAS_V4(name)) {
DP(DEF_LEVEL, "expiring v4 for name %p", name);
result4 = clean_namehooks(adb, &name->v4);
@@ -709,8 +714,7 @@ check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now,
/*
* Check to see if we need to remove the v6 addresses
*/
- if (!NAME_FETCH_V6(name) &&
- (expire || EXPIRE_OK(name->expire_v6, now))) {
+ if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
if (NAME_HAS_V6(name)) {
DP(DEF_LEVEL, "expiring v6 for name %p", name);
result6 = clean_namehooks(adb, &name->v6);
@@ -723,7 +727,7 @@ check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now,
/*
* Check to see if we need to remove the alias target.
*/
- if (expire || EXPIRE_OK(name->expire_target, now)) {
+ if (EXPIRE_OK(name->expire_target, now)) {
clean_target(adb, &name->target);
name->expire_target = INT_MAX;
}
@@ -753,7 +757,10 @@ unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
bucket = name->lock_bucket;
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
- ISC_LIST_UNLINK(adb->names[bucket], name, plink);
+ if (NAME_DEAD(name))
+ ISC_LIST_UNLINK(adb->deadnames[bucket], name, plink);
+ else
+ ISC_LIST_UNLINK(adb->names[bucket], name, plink);
name->lock_bucket = DNS_ADB_INVALIDBUCKET;
INSIST(adb->name_refcnt[bucket] > 0);
adb->name_refcnt[bucket]--;
@@ -767,6 +774,26 @@ unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
*/
static inline void
link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
+ int i;
+ dns_adbentry_t *e;
+
+ if (adb->overmem) {
+ for (i = 0; i < 2; i++) {
+ e = ISC_LIST_TAIL(adb->entries[bucket]);
+ if (e == NULL)
+ break;
+ if (e->refcnt == 0) {
+ unlink_entry(adb, e);
+ free_adbentry(adb, &e);
+ continue;
+ }
+ INSIST((e->flags & ENTRY_IS_DEAD) == 0);
+ e->flags |= ENTRY_IS_DEAD;
+ ISC_LIST_UNLINK(adb->entries[bucket], e, plink);
+ ISC_LIST_PREPEND(adb->deadentries[bucket], e, plink);
+ }
+ }
+
ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
entry->lock_bucket = bucket;
adb->entry_refcnt[bucket]++;
@@ -783,7 +810,10 @@ unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
bucket = entry->lock_bucket;
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
- ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
+ if ((entry->flags & ENTRY_IS_DEAD) != 0)
+ ISC_LIST_UNLINK(adb->deadentries[bucket], entry, plink);
+ else
+ ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
INSIST(adb->entry_refcnt[bucket] > 0);
adb->entry_refcnt[bucket]--;
@@ -862,7 +892,7 @@ shutdown_entries(dns_adb_t *adb) {
adb->entry_sd[bucket] = ISC_TRUE;
entry = ISC_LIST_HEAD(adb->entries[bucket]);
- if (entry == NULL) {
+ if (adb->entry_refcnt[bucket] == 0) {
/*
* This bucket has no entries. We must decrement the
* irefcnt ourselves, since it will not be
@@ -1140,7 +1170,7 @@ check_exit(dns_adb_t *adb) {
* If there aren't any external references either, we're
* done. Send the control event to initiate shutdown.
*/
- INSIST(!adb->cevent_sent); /* Sanity check. */
+ INSIST(!adb->cevent_sent); /* Sanity check. */
event = &adb->cevent;
isc_task_send(adb->task, &event);
adb->cevent_sent = ISC_TRUE;
@@ -1220,7 +1250,8 @@ dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
destroy_entry = ISC_FALSE;
if (entry->refcnt == 0 &&
- (adb->entry_sd[bucket] || entry->expires == 0)) {
+ (adb->entry_sd[bucket] || entry->expires == 0 || adb->overmem ||
+ (entry->flags & ENTRY_IS_DEAD) != 0)) {
destroy_entry = ISC_TRUE;
result = unlink_entry(adb, entry);
}
@@ -1235,7 +1266,7 @@ dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
free_adbentry(adb, &entry);
if (result)
- result =dec_adb_irefcnt(adb);
+ result = dec_adb_irefcnt(adb);
return (result);
}
@@ -1463,31 +1494,13 @@ new_adbfetch(dns_adb_t *adb) {
return (NULL);
f->magic = 0;
- f->namehook = NULL;
- f->entry = NULL;
f->fetch = NULL;
- f->namehook = new_adbnamehook(adb, NULL);
- if (f->namehook == NULL)
- goto err;
-
- f->entry = new_adbentry(adb);
- if (f->entry == NULL)
- goto err;
-
dns_rdataset_init(&f->rdataset);
f->magic = DNS_ADBFETCH_MAGIC;
return (f);
-
- err:
- if (f->namehook != NULL)
- free_adbnamehook(adb, &f->namehook);
- if (f->entry != NULL)
- free_adbentry(adb, &f->entry);
- isc_mempool_put(adb->afmp, f);
- return (NULL);
}
static inline void
@@ -1500,11 +1513,6 @@ free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
f->magic = 0;
- if (f->namehook != NULL)
- free_adbnamehook(adb, &f->namehook);
- if (f->entry != NULL)
- free_adbentry(adb, &f->entry);
-
if (dns_rdataset_isassociated(&f->rdataset))
dns_rdataset_disassociate(&f->rdataset);
@@ -1622,8 +1630,10 @@ find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
* the bucket changes.
*/
static inline dns_adbentry_t *
-find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp) {
- dns_adbentry_t *entry;
+find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
+ isc_stdtime_t now)
+{
+ dns_adbentry_t *entry, *entry_next;
int bucket;
bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS;
@@ -1637,11 +1647,18 @@ find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp) {
*bucketp = bucket;
}
- entry = ISC_LIST_HEAD(adb->entries[bucket]);
- while (entry != NULL) {
- if (isc_sockaddr_equal(addr, &entry->sockaddr))
+ /* Search the list, while cleaning up expired entries. */
+ for (entry = ISC_LIST_HEAD(adb->entries[bucket]);
+ entry != NULL;
+ entry = entry_next) {
+ entry_next = ISC_LIST_NEXT(entry, plink);
+ (void)check_expire_entry(adb, &entry, now);
+ if (entry != NULL &&
+ isc_sockaddr_equal(addr, &entry->sockaddr)) {
+ ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
+ ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
return (entry);
- entry = ISC_LIST_NEXT(entry, plink);
+ }
}
return (NULL);
@@ -1775,19 +1792,12 @@ shutdown_task(isc_task_t *task, isc_event_t *ev) {
adb = ev->ev_arg;
INSIST(DNS_ADB_VALID(adb));
+ isc_event_free(&ev);
/*
* Wait for lock around check_exit() call to be released.
*/
LOCK(&adb->lock);
- /*
- * Kill the timer, and then the ADB itself. Note that this implies
- * that this task was the one scheduled to get timer events. If
- * this is not true (and it is unfortunate there is no way to INSIST()
- * this) badness will occur.
- */
- isc_timer_detach(&adb->timer);
UNLOCK(&adb->lock);
- isc_event_free(&ev);
destroy(adb);
}
@@ -1826,6 +1836,62 @@ check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
return (result);
}
+/*%
+ * Examine the tail entry of the LRU list to see if it expires or is stale
+ * (unused for some period); if so, the name entry will be freed. If the ADB
+ * is in the overmem condition, the tail and the next to tail entries
+ * will be unconditionally removed (unless they have an outstanding fetch).
+ * We don't care about a race on 'overmem' at the risk of causing some
+ * collateral damage or a small delay in starting cleanup, so we don't bother
+ * to lock ADB (if it's not locked).
+ *
+ * Name bucket must be locked; adb may be locked; no other locks held.
+ */
+static void
+check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
+ int victims, max_victims;
+ isc_boolean_t result;
+ dns_adbname_t *victim, *next_victim;
+ isc_boolean_t overmem = adb->overmem;
+ int scans = 0;
+
+ INSIST(bucket != DNS_ADB_INVALIDBUCKET);
+
+ max_victims = overmem ? 2 : 1;
+
+ /*
+ * We limit the number of scanned entries to 10 (arbitrary choice)
+ * in order to avoid examining too many entries when there are many
+ * tail entries that have fetches (this should be rare, but could
+ * happen).
+ */
+ victim = ISC_LIST_TAIL(adb->names[bucket]);
+ for (victims = 0;
+ victim != NULL && victims < max_victims && scans < 10;
+ victim = next_victim) {
+ INSIST(!NAME_DEAD(victim));
+ scans++;
+ next_victim = ISC_LIST_PREV(victim, plink);
+ result = check_expire_name(&victim, now);
+ if (victim == NULL) {
+ victims++;
+ goto next;
+ }
+
+ if (!NAME_FETCH(victim) &&
+ (overmem || victim->last_used + ADB_STALE_MARGIN <= now)) {
+ RUNTIME_CHECK(kill_name(&victim,
+ DNS_EVENT_ADBCANCELED) ==
+ ISC_FALSE);
+ victims++;
+ }
+
+ next:
+ if (!overmem)
+ break;
+ }
+}
+
/*
* Entry bucket must be locked; adb may be locked; no other locks held.
*/
@@ -1833,7 +1899,6 @@ static isc_boolean_t
check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
{
dns_adbentry_t *entry;
- isc_boolean_t expire;
isc_boolean_t result = ISC_FALSE;
INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
@@ -1842,16 +1907,7 @@ check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
if (entry->refcnt != 0)
return (result);
- if (adb->overmem) {
- isc_uint32_t val;
-
- isc_random_get(&val);
-
- expire = ISC_TF((val % 4) == 0);
- } else
- expire = ISC_FALSE;
-
- if (entry->expires == 0 || (! expire && entry->expires > now))
+ if (entry->expires == 0 || entry->expires > now)
return (result);
/*
@@ -1888,7 +1944,7 @@ cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
while (name != NULL) {
next_name = ISC_LIST_NEXT(name, plink);
INSIST(result == ISC_FALSE);
- result = check_expire_namehooks(name, now, adb->overmem);
+ result = check_expire_namehooks(name, now);
if (!result)
result = check_expire_name(&name, now);
name = next_name;
@@ -1920,66 +1976,9 @@ cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
}
static void
-timer_cleanup(isc_task_t *task, isc_event_t *ev) {
- dns_adb_t *adb;
- isc_stdtime_t now;
- unsigned int i;
- isc_interval_t interval;
-
- UNUSED(task);
-
- adb = ev->ev_arg;
- INSIST(DNS_ADB_VALID(adb));
-
- LOCK(&adb->lock);
-
- isc_stdtime_get(&now);
-
- for (i = 0; i < CLEAN_BUCKETS; i++) {
- /*
- * Call our cleanup routines.
- */
- RUNTIME_CHECK(cleanup_names(adb, adb->next_cleanbucket, now) ==
- ISC_FALSE);
- RUNTIME_CHECK(cleanup_entries(adb, adb->next_cleanbucket, now)
- == ISC_FALSE);
-
- /*
- * Set the next bucket to be cleaned.
- */
- adb->next_cleanbucket++;
- if (adb->next_cleanbucket >= NBUCKETS) {
- adb->next_cleanbucket = 0;
-#ifdef DUMP_ADB_AFTER_CLEANING
- dump_adb(adb, stdout, ISC_TRUE, now);
-#endif
- }
- }
-
- /*
- * Reset the timer.
- * XXXDCL isc_timer_reset might return ISC_R_UNEXPECTED or
- * ISC_R_NOMEMORY, but it isn't clear what could be done here
- * if either one of those things happened.
- */
- interval = adb->tick_interval;
- if (adb->overmem)
- isc_interval_set(&interval, 0, 1);
- (void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,
- &interval, ISC_FALSE);
-
- UNLOCK(&adb->lock);
-
- isc_event_free(&ev);
-}
-
-static void
destroy(dns_adb_t *adb) {
adb->magic = 0;
- /*
- * The timer is already dead, from the task's shutdown callback.
- */
isc_task_detach(&adb->task);
isc_mempool_destroy(&adb->nmp);
@@ -2016,10 +2015,12 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
REQUIRE(mem != NULL);
REQUIRE(view != NULL);
- REQUIRE(timermgr != NULL);
+ REQUIRE(timermgr != NULL); /* this is actually unused */
REQUIRE(taskmgr != NULL);
REQUIRE(newadb != NULL && *newadb == NULL);
+ UNUSED(timermgr);
+
adb = isc_mem_get(mem, sizeof(dns_adb_t));
if (adb == NULL)
return (ISC_R_NOMEMORY);
@@ -2039,10 +2040,8 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->aimp = NULL;
adb->afmp = NULL;
adb->task = NULL;
- adb->timer = NULL;
adb->mctx = NULL;
adb->view = view;
- adb->timermgr = timermgr;
adb->taskmgr = taskmgr;
adb->next_cleanbucket = 0;
ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
@@ -2080,12 +2079,14 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
goto fail1;
for (i = 0; i < NBUCKETS; i++) {
ISC_LIST_INIT(adb->names[i]);
+ ISC_LIST_INIT(adb->deadnames[i]);
adb->name_sd[i] = ISC_FALSE;
adb->name_refcnt[i] = 0;
adb->irefcnt++;
}
for (i = 0; i < NBUCKETS; i++) {
ISC_LIST_INIT(adb->entries[i]);
+ ISC_LIST_INIT(adb->deadentries[i]);
adb->entry_sd[i] = ISC_FALSE;
adb->entry_refcnt[i] = 0;
adb->irefcnt++;
@@ -2118,25 +2119,12 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
#undef MPINIT
/*
- * Allocate a timer and a task for our periodic cleanup.
+ * Allocate an internal task.
*/
result = isc_task_create(adb->taskmgr, 0, &adb->task);
if (result != ISC_R_SUCCESS)
goto fail3;
isc_task_setname(adb->task, "ADB", adb);
- /*
- * XXXMLG When this is changed to be a config file option,
- */
- isc_interval_set(&adb->tick_interval, CLEAN_SECONDS, 0);
- result = isc_timer_create(adb->timermgr, isc_timertype_once,
- NULL, &adb->tick_interval, adb->task,
- timer_cleanup, adb, &adb->timer);
- if (result != ISC_R_SUCCESS)
- goto fail3;
-
- DP(ISC_LOG_DEBUG(5), "cleaning interval for adb: "
- "%u buckets every %u seconds, %u buckets in system, %u cl.interval",
- CLEAN_BUCKETS, CLEAN_SECONDS, NBUCKETS, CLEAN_PERIOD);
/*
* Normal return.
@@ -2148,8 +2136,6 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
fail3:
if (adb->task != NULL)
isc_task_detach(&adb->task);
- if (adb->timer != NULL)
- isc_timer_detach(&adb->timer);
/* clean up entrylocks */
DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
@@ -2328,18 +2314,18 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
*
* Possibilities: Note that these are not always exclusive.
*
- * No name found. In this case, allocate a new name header and
- * an initial namehook or two. If any of these allocations
- * fail, clean up and return ISC_R_NOMEMORY.
+ * No name found. In this case, allocate a new name header and
+ * an initial namehook or two. If any of these allocations
+ * fail, clean up and return ISC_R_NOMEMORY.
*
- * Name found, valid addresses present. Allocate one addrinfo
- * structure for each found and append it to the linked list
- * of addresses for this header.
+ * Name found, valid addresses present. Allocate one addrinfo
+ * structure for each found and append it to the linked list
+ * of addresses for this header.
*
- * Name found, queries pending. In this case, if a task was
- * passed in, allocate a job id, attach it to the name's job
- * list and remember to tell the caller that there will be
- * more info coming later.
+ * Name found, queries pending. In this case, if a task was
+ * passed in, allocate a job id, attach it to the name's job
+ * list and remember to tell the caller that there will be
+ * more info coming later.
*/
find = new_adbfind(adb);
@@ -2374,6 +2360,12 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
* Nothing found. Allocate a new adbname structure for this name.
*/
if (adbname == NULL) {
+ /*
+ * See if there is any stale name at the end of list, and purge
+ * it if so.
+ */
+ check_stale_name(adb, bucket, now);
+
adbname = new_adbname(adb, name);
if (adbname == NULL) {
RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
@@ -2387,13 +2379,17 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
adbname->flags |= NAME_GLUE_OK;
if (FIND_STARTATZONE(find))
adbname->flags |= NAME_STARTATZONE;
+ } else {
+ /* Move this name forward in the LRU list */
+ ISC_LIST_UNLINK(adb->names[bucket], adbname, plink);
+ ISC_LIST_PREPEND(adb->names[bucket], adbname, plink);
}
+ adbname->last_used = now;
/*
* Expire old entries, etc.
*/
- RUNTIME_CHECK(check_expire_namehooks(adbname, now, adb->overmem) ==
- ISC_FALSE);
+ RUNTIME_CHECK(check_expire_namehooks(adbname, now) == ISC_FALSE);
/*
* Do we know that the name is an alias?
@@ -2953,8 +2949,8 @@ print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list,
static inline void
print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
- fprintf(f, "\t\tFetch(%s): %p -> { nh %p, entry %p, fetch %p }\n",
- type, ft, ft->namehook, ft->entry, ft->fetch);
+ fprintf(f, "\t\tFetch(%s): %p -> { fetch %p }\n",
+ type, ft, ft->fetch);
}
static void
@@ -2991,7 +2987,7 @@ dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
dns_fixedname_init(&foundname);
- fname = dns_fixedname_name(&foundname);
+ fname = dns_fixedname_name(&foundname);
dns_rdataset_init(&rdataset);
if (rdtype == dns_rdatatype_a)
@@ -3202,6 +3198,7 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
name->fetch_err = FIND_ERR_NXDOMAIN;
else
name->fetch_err = FIND_ERR_NXRRSET;
+ inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
} else {
DP(NCACHE_LEVEL, "adb fetch name %p: "
"caching negative entry for AAAA (ttl %u)",
@@ -3212,6 +3209,7 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
name->fetch6_err = FIND_ERR_NXDOMAIN;
else
name->fetch6_err = FIND_ERR_NXRRSET;
+ inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
}
goto out;
}
@@ -3251,9 +3249,11 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
if (address_type == DNS_ADBFIND_INET) {
name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
name->fetch_err = FIND_ERR_FAILURE;
+ inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
} else {
name->expire_v6 = ISC_MIN(name->expire_v6, now + 300);
name->fetch6_err = FIND_ERR_FAILURE;
+ inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
}
goto out;
}
@@ -3338,10 +3338,13 @@ fetch_name(dns_adbname_t *adbname,
if (result != ISC_R_SUCCESS)
goto cleanup;
- if (type == dns_rdatatype_a)
+ if (type == dns_rdatatype_a) {
adbname->fetch_a = fetch;
- else
+ inc_stats(adb, dns_resstatscounter_gluefetchv4);
+ } else {
adbname->fetch_aaaa = fetch;
+ inc_stats(adb, dns_resstatscounter_gluefetchv6);
+ }
fetch = NULL; /* Keep us from cleaning this up below. */
cleanup:
@@ -3464,7 +3467,7 @@ dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
result = ISC_R_SUCCESS;
bucket = DNS_ADB_INVALIDBUCKET;
- entry = find_entry_and_lock(adb, sa, &bucket);
+ entry = find_entry_and_lock(adb, sa, &bucket, now);
if (adb->entry_sd[bucket]) {
result = ISC_R_SHUTTINGDOWN;
goto unlock;
@@ -3590,7 +3593,6 @@ static void
water(void *arg, int mark) {
dns_adb_t *adb = arg;
isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
- isc_interval_t interval;
REQUIRE(DNS_ADB_VALID(adb));
@@ -3604,11 +3606,6 @@ water(void *arg, int mark) {
LOCK(&adb->overmemlock);
if (adb->overmem != overmem) {
adb->overmem = overmem;
- if (overmem) {
- isc_interval_set(&interval, 0, 1);
- (void)isc_timer_reset(adb->timer, isc_timertype_once,
- NULL, &interval, ISC_TRUE);
- }
isc_mem_waterack(adb->mctx, mark);
}
UNLOCK(&adb->overmemlock);
diff --git a/lib/dns/api b/lib/dns/api
index 0b8a3bc..5ef8dc0 100644
--- a/lib/dns/api
+++ b/lib/dns/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 36
-LIBREVISION = 2
-LIBAGE = 0
+LIBINTERFACE = 51
+LIBREVISION = 1
+LIBAGE = 1
diff --git a/lib/dns/byaddr.c b/lib/dns/byaddr.c
index 38d6e8b..234d6b2 100644
--- a/lib/dns/byaddr.c
+++ b/lib/dns/byaddr.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: byaddr.c,v 1.34.18.3 2005/04/29 00:15:49 marka Exp $ */
+/* $Id: byaddr.c,v 1.39 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/cache.c b/lib/dns/cache.c
index c9b4a95..aee824e 100644
--- a/lib/dns/cache.c
+++ b/lib/dns/cache.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,13 +15,14 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cache.c,v 1.57.18.18 2008/02/07 23:45:56 tbox Exp $ */
+/* $Id: cache.c,v 1.80.50.3 2009/05/06 23:34:30 jinmei Exp $ */
/*! \file */
#include <config.h>
#include <isc/mem.h>
+#include <isc/string.h>
#include <isc/task.h>
#include <isc/time.h>
#include <isc/timer.h>
@@ -47,7 +48,7 @@
* DNS_CACHE_MINSIZE is how many bytes is the floor for dns_cache_setcachesize().
* See also DNS_CACHE_CLEANERINCREMENT
*/
-#define DNS_CACHE_MINSIZE 2097152 /*%< Bytes. 2097152 = 2 MB */
+#define DNS_CACHE_MINSIZE 2097152 /*%< Bytes. 2097152 = 2 MB */
/*!
* Control incremental cleaning.
* CLEANERINCREMENT is how many nodes are examined in one pass.
@@ -60,7 +61,7 @@
***/
/*
- * A cache_cleaner_t encapsulsates the state of the periodic
+ * A cache_cleaner_t encapsulates the state of the periodic
* cache cleaning.
*/
@@ -69,7 +70,7 @@ typedef struct cache_cleaner cache_cleaner_t;
typedef enum {
cleaner_s_idle, /*%< Waiting for cleaning-interval to expire. */
cleaner_s_busy, /*%< Currently cleaning. */
- cleaner_s_done /*%< Freed enough memory after being overmem. */
+ cleaner_s_done /*%< Freed enough memory after being overmem. */
} cleaner_state_t;
/*
@@ -95,19 +96,19 @@ struct cache_cleaner {
*/
dns_cache_t *cache;
- isc_task_t *task;
+ isc_task_t *task;
unsigned int cleaning_interval; /*% The cleaning-interval from
named.conf, in seconds. */
- isc_timer_t *cleaning_timer;
+ isc_timer_t *cleaning_timer;
isc_event_t *resched_event; /*% Sent by cleaner task to
itself to reschedule */
isc_event_t *overmem_event;
dns_dbiterator_t *iterator;
- unsigned int increment; /*% Number of names to
+ unsigned int increment; /*% Number of names to
clean in one increment */
- cleaner_state_t state; /*% Idle/Busy. */
- isc_boolean_t overmem; /*% The cache is in an overmem state. */
+ cleaner_state_t state; /*% Idle/Busy. */
+ isc_boolean_t overmem; /*% The cache is in an overmem state. */
isc_boolean_t replaceiterator;
};
@@ -133,7 +134,7 @@ struct dns_cache {
char **db_argv;
/* Locked by 'filelock'. */
- char * filename;
+ char *filename;
/* Access to the on-disk cache file is also locked by 'filelock'. */
};
@@ -157,79 +158,6 @@ cleaner_shutdown_action(isc_task_t *task, isc_event_t *event);
static void
overmem_cleaning_action(isc_task_t *task, isc_event_t *event);
-/*%
- * Work out how many nodes can be cleaned in the time between two
- * requests to the nameserver. Smooth the resulting number and use
- * it as a estimate for the number of nodes to be cleaned in the next
- * iteration.
- */
-static void
-adjust_increment(cache_cleaner_t *cleaner, unsigned int remaining,
- isc_time_t *start)
-{
- isc_time_t end;
- isc_uint64_t usecs;
- isc_uint64_t new;
- unsigned int pps = dns_pps;
- unsigned int interval;
- unsigned int names;
-
- /*
- * Tune for minumum of 100 packets per second (pps).
- */
- if (pps < 100)
- pps = 100;
-
- isc_time_now(&end);
-
- interval = 1000000 / pps; /* Interval between packets in usecs. */
- if (interval == 0)
- interval = 1;
-
- INSIST(cleaner->increment >= remaining);
- names = cleaner->increment - remaining;
- usecs = isc_time_microdiff(&end, start);
-
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
- ISC_LOG_DEBUG(1), "adjust_increment interval=%u "
- "names=%u usec=%" ISC_PLATFORM_QUADFORMAT "u",
- interval, names, usecs);
-
- if (usecs == 0) {
- /*
- * If we cleaned all the nodes in unmeasurable time
- * double the number of nodes to be cleaned next time.
- */
- if (names == cleaner->increment) {
- cleaner->increment *= 2;
- if (cleaner->increment > DNS_CACHE_CLEANERINCREMENT)
- cleaner->increment = DNS_CACHE_CLEANERINCREMENT;
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
- "%p:new cleaner->increment = %u\n",
- cleaner, cleaner->increment);
- }
- return;
- }
-
- new = (names * interval);
- new /= (usecs * 2);
- if (new == 0)
- new = 1;
-
- /* Smooth */
- new = (new + cleaner->increment * 7) / 8;
-
- if (new > DNS_CACHE_CLEANERINCREMENT)
- new = DNS_CACHE_CLEANERINCREMENT;
-
- cleaner->increment = (unsigned int)new;
-
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
- ISC_LOG_DEBUG(1), "%p:new cleaner->increment = %u\n",
- cleaner, cleaner->increment);
-}
-
static inline isc_result_t
cache_create_db(dns_cache_t *cache, dns_db_t **db) {
return (dns_db_create(cache->mctx, cache->db_type, dns_rootname,
@@ -246,6 +174,7 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_result_t result;
dns_cache_t *cache;
int i;
+ isc_task_t *dbtask;
REQUIRE(cachep != NULL);
REQUIRE(*cachep == NULL);
@@ -301,12 +230,29 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
result = cache_create_db(cache, &cache->db);
if (result != ISC_R_SUCCESS)
goto cleanup_dbargv;
+ if (taskmgr != NULL) {
+ dbtask = NULL;
+ result = isc_task_create(taskmgr, 1, &dbtask);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_db;
+ dns_db_settask(cache->db, dbtask);
+ isc_task_detach(&dbtask);
+ }
cache->filename = NULL;
cache->magic = CACHE_MAGIC;
- result = cache_cleaner_init(cache, taskmgr, timermgr, &cache->cleaner);
+ /*
+ * RBT-type cache DB has its own mechanism of cache cleaning and doesn't
+ * need the control of the generic cleaner.
+ */
+ if (strcmp(db_type, "rbt") == 0)
+ result = cache_cleaner_init(cache, NULL, NULL, &cache->cleaner);
+ else {
+ result = cache_cleaner_init(cache, taskmgr, timermgr,
+ &cache->cleaner);
+ }
if (result != ISC_R_SUCCESS)
goto cleanup_db;
@@ -603,8 +549,7 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
cleaner->cleaning_interval = 0; /* Initially turned off. */
result = isc_timer_create(timermgr, isc_timertype_inactive,
- NULL, NULL,
- cleaner->task,
+ NULL, NULL, cleaner->task,
cleaning_timer_action, cleaner,
&cleaner->cleaning_timer);
if (result != ISC_R_SUCCESS) {
@@ -848,7 +793,6 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
"cache cleaner: dns_dbiterator_current() "
"failed: %s", dns_result_totext(result));
- adjust_increment(cleaner, n_names, &start);
end_cleaning(cleaner, event);
return;
}
@@ -892,14 +836,11 @@ incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
}
}
- adjust_increment(cleaner, n_names, &start);
end_cleaning(cleaner, event);
return;
}
}
- adjust_increment(cleaner, 0U, &start);
-
/*
* We have successfully performed a cleaning increment but have
* not gone through the entire cache. Free the iterator locks
@@ -929,7 +870,7 @@ dns_cache_clean(dns_cache_t *cache, isc_stdtime_t now) {
REQUIRE(VALID_CACHE(cache));
- result = dns_db_createiterator(cache->db, ISC_FALSE, &iterator);
+ result = dns_db_createiterator(cache->db, 0, &iterator);
if (result != ISC_R_SUCCESS)
return result;
@@ -1002,7 +943,7 @@ dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) {
REQUIRE(VALID_CACHE(cache));
/*
- * Impose a minumum cache size; pathological things happen if there
+ * Impose a minimum cache size; pathological things happen if there
* is too little room.
*/
if (size != 0 && size < DNS_CACHE_MINSIZE)
diff --git a/lib/dns/callbacks.c b/lib/dns/callbacks.c
index a487ed0..928f37d 100644
--- a/lib/dns/callbacks.c
+++ b/lib/dns/callbacks.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: callbacks.c,v 1.13.18.2 2005/04/29 00:15:49 marka Exp $ */
+/* $Id: callbacks.c,v 1.17 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/compress.c b/lib/dns/compress.c
index 2103767..11473ee 100644
--- a/lib/dns/compress.c
+++ b/lib/dns/compress.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: compress.c,v 1.52.18.5 2006/03/02 00:37:21 marka Exp $ */
+/* $Id: compress.c,v 1.59 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/db.c b/lib/dns/db.c
index 32ff6ae..a4c2864 100644
--- a/lib/dns/db.c
+++ b/lib/dns/db.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.c,v 1.74.18.6 2005/10/13 02:12:24 marka Exp $ */
+/* $Id: db.c,v 1.88 2008/09/24 02:46:22 marka Exp $ */
/*! \file */
@@ -95,7 +95,7 @@ static inline dns_dbimplementation_t *
impfind(const char *name) {
dns_dbimplementation_t *imp;
- for (imp = ISC_LIST_HEAD(implementations);
+ for (imp = ISC_LIST_HEAD(implementations);
imp != NULL;
imp = ISC_LIST_NEXT(imp, link))
if (strcasecmp(name, imp->name) == 0)
@@ -229,6 +229,21 @@ dns_db_isstub(dns_db_t *db) {
}
isc_boolean_t
+dns_db_isdnssec(dns_db_t *db) {
+
+ /*
+ * Is 'db' secure or partially secure?
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
+
+ if (db->methods->isdnssec != NULL)
+ return ((db->methods->isdnssec)(db));
+ return ((db->methods->issecure)(db));
+}
+
+isc_boolean_t
dns_db_issecure(dns_db_t *db) {
/*
@@ -450,6 +465,21 @@ dns_db_findnode(dns_db_t *db, dns_name_t *name,
}
isc_result_t
+dns_db_findnsec3node(dns_db_t *db, dns_name_t *name,
+ isc_boolean_t create, dns_dbnode_t **nodep)
+{
+
+ /*
+ * Find the node with name 'name'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ return ((db->methods->findnsec3node)(db, name, create, nodep));
+}
+
+isc_result_t
dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
dns_dbnode_t **nodep, dns_name_t *foundname,
@@ -527,6 +557,30 @@ dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
ENSURE(*nodep == NULL);
}
+void
+dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep,
+ dns_dbnode_t **targetp)
+{
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+ /*
+ * This doesn't check the implementation magic. If we find that
+ * we need such checks in future then this will be done in the
+ * method.
+ */
+ REQUIRE(sourcep != NULL && *sourcep != NULL);
+
+ UNUSED(db);
+
+ if (db->methods->transfernode == NULL) {
+ *targetp = *sourcep;
+ *sourcep = NULL;
+ } else
+ (db->methods->transfernode)(db, sourcep, targetp);
+
+ ENSURE(*sourcep == NULL);
+}
+
isc_result_t
dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
@@ -559,7 +613,7 @@ dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
***/
isc_result_t
-dns_db_createiterator(dns_db_t *db, isc_boolean_t relative_names,
+dns_db_createiterator(dns_db_t *db, unsigned int flags,
dns_dbiterator_t **iteratorp)
{
/*
@@ -569,7 +623,7 @@ dns_db_createiterator(dns_db_t *db, isc_boolean_t relative_names,
REQUIRE(DNS_DB_VALID(db));
REQUIRE(iteratorp != NULL && *iteratorp == NULL);
- return (db->methods->createiterator(db, relative_names, iteratorp));
+ return (db->methods->createiterator(db, flags, iteratorp));
}
/***
@@ -687,7 +741,7 @@ dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
type, covers));
}
-void
+void
dns_db_overmem(dns_db_t *db, isc_boolean_t overmem) {
REQUIRE(DNS_DB_VALID(db));
@@ -713,11 +767,11 @@ dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp)
dns_rdataset_init(&rdataset);
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0,
(isc_stdtime_t)0, &rdataset, NULL);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
goto freenode;
result = dns_rdataset_first(&rdataset);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
goto freerdataset;
dns_rdataset_current(&rdataset, &rdata);
result = dns_rdataset_next(&rdataset);
@@ -770,7 +824,7 @@ dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
RWUNLOCK(&implock, isc_rwlocktype_write);
return (ISC_R_EXISTS);
}
-
+
imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t));
if (imp == NULL) {
RWUNLOCK(&implock, isc_rwlocktype_write);
@@ -819,3 +873,54 @@ dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
return (ISC_R_NOTFOUND);
}
+
+dns_stats_t *
+dns_db_getrrsetstats(dns_db_t *db) {
+ REQUIRE(DNS_DB_VALID(db));
+
+ if (db->methods->getrrsetstats != NULL)
+ return ((db->methods->getrrsetstats)(db));
+
+ return (NULL);
+}
+
+isc_result_t
+dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
+ dns_hash_t *hash, isc_uint8_t *flags,
+ isc_uint16_t *iterations,
+ unsigned char *salt, size_t *salt_length)
+{
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(dns_db_iszone(db) == ISC_TRUE);
+
+ if (db->methods->getnsec3parameters != NULL)
+ return ((db->methods->getnsec3parameters)(db, version, hash,
+ flags, iterations,
+ salt, salt_length));
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
+ isc_stdtime_t resign)
+{
+ if (db->methods->setsigningtime != NULL)
+ return ((db->methods->setsigningtime)(db, rdataset, resign));
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_result_t
+dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name)
+{
+ if (db->methods->getsigningtime != NULL)
+ return ((db->methods->getsigningtime)(db, rdataset, name));
+ return (ISC_R_NOTFOUND);
+}
+
+void
+dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
+{
+ if (db->methods->resigned != NULL)
+ (db->methods->resigned)(db, rdataset, version);
+}
diff --git a/lib/dns/dbiterator.c b/lib/dns/dbiterator.c
index d462ad5..8981e49 100644
--- a/lib/dns/dbiterator.c
+++ b/lib/dns/dbiterator.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dbiterator.c,v 1.14.18.2 2005/04/29 00:15:50 marka Exp $ */
+/* $Id: dbiterator.c,v 1.18 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/dbtable.c b/lib/dns/dbtable.c
index b091e42..57bbfc1 100644
--- a/lib/dns/dbtable.c
+++ b/lib/dns/dbtable.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -16,7 +16,7 @@
*/
/*
- * $Id: dbtable.c,v 1.28.18.3 2005/07/12 01:22:19 marka Exp $
+ * $Id: dbtable.c,v 1.33 2007/06/19 23:47:16 tbox Exp $
*/
/*! \file
diff --git a/lib/dns/diff.c b/lib/dns/diff.c
index 22a3938..9489821 100644
--- a/lib/dns/diff.c
+++ b/lib/dns/diff.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: diff.c,v 1.9.18.3 2005/04/27 05:01:15 sra Exp $ */
+/* $Id: diff.c,v 1.18.50.2 2009/01/05 23:47:22 tbox Exp $ */
/*! \file */
@@ -35,6 +35,7 @@
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
@@ -120,6 +121,7 @@ dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp) {
void
dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff) {
diff->mctx = mctx;
+ diff->resign = 0;
ISC_LIST_INIT(diff->tuples);
diff->magic = DNS_DIFF_MAGIC;
}
@@ -192,6 +194,40 @@ dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep)
ENSURE(*tuplep == NULL);
}
+static isc_stdtime_t
+setresign(dns_rdataset_t *modified, isc_uint32_t delta) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t sig;
+ isc_stdtime_t when;
+ isc_result_t result;
+
+ result = dns_rdataset_first(modified);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(modified, &rdata);
+ (void)dns_rdata_tostruct(&rdata, &sig, NULL);
+ if ((rdata.flags & DNS_RDATA_OFFLINE) != 0)
+ when = 0;
+ else
+ when = sig.timeexpire - delta;
+ dns_rdata_reset(&rdata);
+
+ result = dns_rdataset_next(modified);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(modified, &rdata);
+ (void)dns_rdata_tostruct(&rdata, &sig, NULL);
+ if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) {
+ goto next_rr;
+ }
+ if (when == 0 || sig.timeexpire - delta < when)
+ when = sig.timeexpire - delta;
+ next_rr:
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(modified);
+ }
+ INSIST(result == ISC_R_NOMORE);
+ return (when);
+}
+
static isc_result_t
diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
isc_boolean_t warn)
@@ -220,14 +256,15 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
* but such diffs should never be created in the first
* place.
*/
- node = NULL;
- CHECK(dns_db_findnode(db, name, ISC_TRUE, &node));
while (t != NULL && dns_name_equal(&t->name, name)) {
dns_rdatatype_t type, covers;
dns_diffop_t op;
dns_rdatalist_t rdl;
dns_rdataset_t rds;
+ dns_rdataset_t ardataset;
+ dns_rdataset_t *modified = NULL;
+ isc_boolean_t offline;
op = t->op;
type = t->rdata.type;
@@ -255,6 +292,16 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
ISC_LIST_INIT(rdl.rdata);
ISC_LINK_INIT(&rdl, link);
+ node = NULL;
+ if (type != dns_rdatatype_nsec3 &&
+ covers != dns_rdatatype_nsec3)
+ CHECK(dns_db_findnode(db, name, ISC_TRUE,
+ &node));
+ else
+ CHECK(dns_db_findnsec3node(db, name, ISC_TRUE,
+ &node));
+
+ offline = ISC_FALSE;
while (t != NULL &&
dns_name_equal(&t->name, name) &&
t->op == op &&
@@ -269,13 +316,15 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
sizeof(classbuf));
if (t->ttl != rdl.ttl && warn)
isc_log_write(DIFF_COMMON_LOGARGS,
- ISC_LOG_WARNING,
+ ISC_LOG_WARNING,
"'%s/%s/%s': TTL differs in "
"rdataset, adjusting "
"%lu -> %lu",
namebuf, typebuf, classbuf,
(unsigned long) t->ttl,
(unsigned long) rdl.ttl);
+ if (t->rdata.flags & DNS_RDATA_OFFLINE)
+ offline = ISC_TRUE;
ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
t = ISC_LIST_NEXT(t, link);
}
@@ -285,28 +334,52 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
*/
dns_rdataset_init(&rds);
CHECK(dns_rdatalist_tordataset(&rdl, &rds));
+ if (rds.type == dns_rdatatype_rrsig)
+ switch (op) {
+ case DNS_DIFFOP_ADDRESIGN:
+ case DNS_DIFFOP_DELRESIGN:
+ modified = &ardataset;
+ dns_rdataset_init(modified);
+ break;
+ default:
+ break;
+ }
rds.trust = dns_trust_ultimate;
/*
* Merge the rdataset into the database.
*/
- if (op == DNS_DIFFOP_ADD) {
+ switch (op) {
+ case DNS_DIFFOP_ADD:
+ case DNS_DIFFOP_ADDRESIGN:
result = dns_db_addrdataset(db, node, ver,
0, &rds,
DNS_DBADD_MERGE|
DNS_DBADD_EXACT|
DNS_DBADD_EXACTTTL,
- NULL);
- } else if (op == DNS_DIFFOP_DEL) {
+ modified);
+ break;
+ case DNS_DIFFOP_DEL:
+ case DNS_DIFFOP_DELRESIGN:
result = dns_db_subtractrdataset(db, node, ver,
&rds,
DNS_DBSUB_EXACT,
- NULL);
- } else {
+ modified);
+ break;
+ default:
INSIST(0);
}
- if (result == DNS_R_UNCHANGED) {
- /*
+
+ if (result == ISC_R_SUCCESS) {
+ if (modified != NULL) {
+ isc_stdtime_t resign;
+ resign = setresign(modified,
+ diff->resign);
+ dns_db_setsigningtime(db, modified,
+ resign);
+ }
+ } else if (result == DNS_R_UNCHANGED) {
+ /*
* This will not happen when executing a
* dynamic update, because that code will
* generate strictly minimal diffs.
@@ -318,16 +391,21 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
isc_log_write(DIFF_COMMON_LOGARGS,
ISC_LOG_WARNING,
"update with no effect");
- } else if (result == ISC_R_SUCCESS ||
- result == DNS_R_NXRRSET) {
+ } else if (result == DNS_R_NXRRSET) {
/*
* OK.
*/
} else {
+ if (modified != NULL &&
+ dns_rdataset_isassociated(modified))
+ dns_rdataset_disassociate(modified);
CHECK(result);
}
+ dns_db_detachnode(db, &node);
+ if (modified != NULL &&
+ dns_rdataset_isassociated(modified))
+ dns_rdataset_disassociate(modified);
}
- dns_db_detachnode(db, &node);
}
return (ISC_R_SUCCESS);
@@ -455,7 +533,7 @@ dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare) {
/*
* Create an rdataset containing the single RR of the given
- * tuple. The caller must allocate the the rdata, rdataset and
+ * tuple. The caller must allocate the rdata, rdataset and
* an rdatalist structure for it to refer to.
*/
@@ -485,6 +563,7 @@ dns_diff_print(dns_diff_t *diff, FILE *file) {
dns_difftuple_t *t;
char *mem = NULL;
unsigned int size = 2048;
+ const char *op = NULL;
REQUIRE(DNS_DIFF_VALID(diff));
@@ -536,15 +615,20 @@ dns_diff_print(dns_diff_t *diff, FILE *file) {
buf.used--;
isc_buffer_usedregion(&buf, &r);
+ switch (t->op) {
+ case DNS_DIFFOP_EXISTS: op = "exists"; break;
+ case DNS_DIFFOP_ADD: op = "add"; break;
+ case DNS_DIFFOP_DEL: op = "del"; break;
+ case DNS_DIFFOP_ADDRESIGN: op = "add re-sign"; break;
+ case DNS_DIFFOP_DELRESIGN: op = "del re-sign"; break;
+ }
if (file != NULL)
- fprintf(file, "%s %.*s\n",
- t->op == DNS_DIFFOP_ADD ? "add" : "del",
- (int) r.length, (char *) r.base);
+ fprintf(file, "%s %.*s\n", op, (int) r.length,
+ (char *) r.base);
else
isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_DEBUG(7),
- "%s %.*s",
- t->op == DNS_DIFFOP_ADD ? "add" : "del",
- (int) r.length, (char *) r.base);
+ "%s %.*s", op, (int) r.length,
+ (char *) r.base);
}
result = ISC_R_SUCCESS;
cleanup:
diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c
index 794cdb5..9b4e968 100644
--- a/lib/dns/dispatch.c
+++ b/lib/dns/dispatch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dispatch.c,v 1.116.18.37 2008/09/04 00:24:41 jinmei Exp $ */
+/* $Id: dispatch.c,v 1.155.12.7 2009/04/28 21:39:45 jinmei Exp $ */
/*! \file */
@@ -32,6 +32,7 @@
#include <isc/portset.h>
#include <isc/print.h>
#include <isc/random.h>
+#include <isc/stats.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/time.h>
@@ -43,14 +44,18 @@
#include <dns/log.h>
#include <dns/message.h>
#include <dns/portlist.h>
+#include <dns/stats.h>
#include <dns/tcpmsg.h>
#include <dns/types.h>
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
-typedef struct dispsocket dispsocket_t;
+typedef struct dispsocket dispsocket_t;
typedef ISC_LIST(dispsocket_t) dispsocketlist_t;
+typedef struct dispportentry dispportentry_t;
+typedef ISC_LIST(dispportentry_t) dispportlist_t;
+
/* ARC4 Random generator state */
typedef struct arc4ctx {
isc_uint8_t i;
@@ -76,6 +81,7 @@ struct dns_dispatchmgr {
isc_mem_t *mctx;
dns_acl_t *blackhole;
dns_portlist_t *portlist;
+ isc_stats_t *stats;
isc_entropy_t *entropy; /*%< entropy source */
/* Locked by "lock". */
@@ -170,7 +176,8 @@ struct dispsocket {
isc_socket_t *socket;
dns_dispatch_t *disp;
isc_sockaddr_t host;
- in_port_t localport;
+ in_port_t localport; /* XXX: should be removed later */
+ dispportentry_t *portentry;
dns_dispentry_t *resp;
isc_task_t *task;
ISC_LINK(dispsocket_t) link;
@@ -178,6 +185,21 @@ struct dispsocket {
ISC_LINK(dispsocket_t) blink;
};
+/*%
+ * A port table entry. We remember every port we first open in a table with a
+ * reference counter so that we can 'reuse' the same port (with different
+ * destination addresses) using the SO_REUSEADDR socket option.
+ */
+struct dispportentry {
+ in_port_t port;
+ unsigned int refs;
+ ISC_LINK(struct dispportentry) link;
+};
+
+#ifndef DNS_DISPATCH_PORTTABLESIZE
+#define DNS_DISPATCH_PORTTABLESIZE 1024
+#endif
+
#define INVALID_BUCKET (0xffffdead)
/*%
@@ -227,6 +249,8 @@ struct dns_dispatch {
dns_tcpmsg_t tcpmsg; /*%< for tcp streams */
dns_qid_t *qid;
arc4ctx_t arc4ctx; /*%< for QID/UDP port num */
+ dispportlist_t *port_table; /*%< hold ports 'owned' by us */
+ isc_mempool_t *portpool; /*%< port table entries */
};
#define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ')
@@ -330,6 +354,12 @@ mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) {
level, "dispatchmgr %p: %s", mgr, msgbuf);
}
+static inline void
+inc_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) {
+ if (mgr->stats != NULL)
+ isc_stats_increment(mgr->stats, counter);
+}
+
static void
dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...)
ISC_FORMAT_PRINTF(3, 4);
@@ -677,6 +707,64 @@ destroy_disp(isc_task_t *task, isc_event_t *event) {
}
/*%
+ * Manipulate port table per dispatch: find an entry for a given port number,
+ * create a new entry, and decrement a given entry with possible clean-up.
+ */
+static dispportentry_t *
+port_search(dns_dispatch_t *disp, in_port_t port) {
+ dispportentry_t *portentry;
+
+ REQUIRE(disp->port_table != NULL);
+
+ portentry = ISC_LIST_HEAD(disp->port_table[port %
+ DNS_DISPATCH_PORTTABLESIZE]);
+ while (portentry != NULL) {
+ if (portentry->port == port)
+ return (portentry);
+ portentry = ISC_LIST_NEXT(portentry, link);
+ }
+
+ return (NULL);
+}
+
+static dispportentry_t *
+new_portentry(dns_dispatch_t *disp, in_port_t port) {
+ dispportentry_t *portentry;
+
+ REQUIRE(disp->port_table != NULL);
+
+ portentry = isc_mempool_get(disp->portpool);
+ if (portentry == NULL)
+ return (portentry);
+
+ portentry->port = port;
+ portentry->refs = 0;
+ ISC_LINK_INIT(portentry, link);
+ ISC_LIST_APPEND(disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE],
+ portentry, link);
+
+ return (portentry);
+}
+
+static void
+deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
+ dispportentry_t *portentry = *portentryp;
+
+ REQUIRE(disp->port_table != NULL);
+ REQUIRE(portentry != NULL && portentry->refs > 0);
+
+ portentry->refs--;
+ if (portentry->refs == 0) {
+ ISC_LIST_UNLINK(disp->port_table[portentry->port %
+ DNS_DISPATCH_PORTTABLESIZE],
+ portentry, link);
+ isc_mempool_put(disp->portpool, portentry);
+ }
+
+ *portentryp = NULL;
+}
+
+/*%
* Find a dispsocket for socket address 'dest', and port number 'port'.
* Return NULL if no such entry exists.
*/
@@ -692,7 +780,7 @@ socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port,
while (dispsock != NULL) {
if (isc_sockaddr_equal(dest, &dispsock->host) &&
- dispsock->localport == port)
+ dispsock->portentry->port == port)
return (dispsock);
dispsock = ISC_LIST_NEXT(dispsock, blink);
}
@@ -720,6 +808,8 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
dispsocket_t *dispsock;
unsigned int nports;
in_port_t *ports;
+ unsigned int bindoptions;
+ dispportentry_t *portentry = NULL;
if (isc_sockaddr_pf(&disp->local) == AF_INET) {
nports = disp->mgr->nv4ports;
@@ -745,6 +835,7 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
dispsock->socket = NULL;
dispsock->disp = disp;
dispsock->resp = NULL;
+ dispsock->portentry = NULL;
isc_random_get(&r);
dispsock->task = NULL;
isc_task_attach(disp->task[r % disp->ntasks], &dispsock->task);
@@ -767,16 +858,29 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
bucket = dns_hash(qid, dest, 0, port);
if (socket_search(qid, dest, port, bucket) != NULL)
continue;
-
- result = open_socket(sockmgr, &localaddr, 0, &sock);
- if (result == ISC_R_SUCCESS || result != ISC_R_ADDRINUSE)
+ bindoptions = 0;
+ portentry = port_search(disp, port);
+ if (portentry != NULL)
+ bindoptions |= ISC_SOCKET_REUSEADDRESS;
+ result = open_socket(sockmgr, &localaddr, bindoptions, &sock);
+ if (result == ISC_R_SUCCESS) {
+ if (portentry == NULL) {
+ portentry = new_portentry(disp, port);
+ if (portentry == NULL) {
+ result = ISC_R_NOMEMORY;
+ break;
+ }
+ }
+ portentry->refs++;
+ break;
+ } else if (result != ISC_R_ADDRINUSE)
break;
}
if (result == ISC_R_SUCCESS) {
dispsock->socket = sock;
dispsock->host = *dest;
- dispsock->localport = port;
+ dispsock->portentry = portentry;
dispsock->bucket = bucket;
ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink);
*dispsockp = dispsock;
@@ -813,6 +917,8 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
disp->nsockets--;
dispsock->magic = 0;
+ if (dispsock->portentry != NULL)
+ deref_portentry(disp, &dispsock->portentry);
if (dispsock->socket != NULL)
isc_socket_detach(&dispsock->socket);
if (ISC_LINK_LINKED(dispsock, blink)) {
@@ -847,6 +953,9 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
dispsock->resp->dispsocket = NULL;
}
+ INSIST(dispsock->portentry != NULL);
+ deref_portentry(disp, &dispsock->portentry);
+
if (disp->nsockets > DNS_DISPATCH_POOLSOCKS)
destroy_dispsocket(disp, &dispsock);
else {
@@ -1161,6 +1270,7 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
bucket, (resp == NULL ? "not found" : "found"));
if (resp == NULL) {
+ inc_stats(mgr, dns_resstatscounter_mismatch);
free_buffer(disp, ev->region.base, ev->region.length);
goto unlock;
}
@@ -1168,6 +1278,7 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
&resp->host)) {
dispatch_log(disp, LVL(90),
"response to an exclusive socket doesn't match");
+ inc_stats(mgr, dns_resstatscounter_mismatch);
free_buffer(disp, ev->region.base, ev->region.length);
goto unlock;
}
@@ -1603,6 +1714,9 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
if (mgr->blackhole != NULL)
dns_acl_detach(&mgr->blackhole);
+ if (mgr->stats != NULL)
+ isc_stats_detach(&mgr->stats);
+
if (mgr->v4ports != NULL) {
isc_mem_put(mctx, mgr->v4ports,
mgr->nv4ports * sizeof(in_port_t));
@@ -1628,6 +1742,7 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
isc_sockettype_udp, &sock);
if (result != ISC_R_SUCCESS)
return (result);
+ isc_socket_setname(sock, "dispatcher", NULL);
} else {
result = isc_socket_open(sock);
if (result != ISC_R_SUCCESS)
@@ -1692,6 +1807,7 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
isc_mem_attach(mctx, &mgr->mctx);
mgr->blackhole = NULL;
+ mgr->stats = NULL;
result = isc_mutex_init(&mgr->lock);
if (result != ISC_R_SUCCESS)
@@ -2001,6 +2117,15 @@ dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
destroy_mgr(&mgr);
}
+void
+dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) {
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ REQUIRE(ISC_LIST_EMPTY(mgr->list));
+ REQUIRE(mgr->stats == NULL);
+
+ isc_stats_attach(stats, &mgr->stats);
+}
+
static int
port_cmp(const void *key, const void *ent) {
in_port_t p1 = *(const in_port_t *)key;
@@ -2269,6 +2394,8 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
ISC_LIST_INIT(disp->inactivesockets);
disp->nsockets = 0;
dispatch_arc4init(&disp->arc4ctx, mgr->entropy, NULL);
+ disp->port_table = NULL;
+ disp->portpool = NULL;
result = isc_mutex_init(&disp->lock);
if (result != ISC_R_SUCCESS)
@@ -2298,13 +2425,14 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
/*
- * MUST be unlocked, and not used by anthing.
+ * MUST be unlocked, and not used by anything.
*/
static void
dispatch_free(dns_dispatch_t **dispp)
{
dns_dispatch_t *disp;
dns_dispatchmgr_t *mgr;
+ int i;
REQUIRE(VALID_DISPATCH(*dispp));
disp = *dispp;
@@ -2329,6 +2457,18 @@ dispatch_free(dns_dispatch_t **dispp)
if (disp->qid != NULL)
qid_destroy(mgr->mctx, &disp->qid);
+
+ if (disp->port_table != NULL) {
+ for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++)
+ INSIST(ISC_LIST_EMPTY(disp->port_table[i]));
+ isc_mem_put(mgr->mctx, disp->port_table,
+ sizeof(disp->port_table[0]) *
+ DNS_DISPATCH_PORTTABLESIZE);
+ }
+
+ if (disp->portpool != NULL)
+ isc_mempool_destroy(&disp->portpool);
+
disp->mgr = NULL;
DESTROYLOCK(&disp->lock);
disp->magic = 0;
@@ -2462,9 +2602,8 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
}
/*
- * First, see if we have a dispatcher that matches.
+ * See if we have a dispatcher that matches.
*/
- disp = NULL;
result = dispatch_find(mgr, localaddr, attributes, mask, &disp);
if (result == ISC_R_SUCCESS) {
disp->refcount++;
@@ -2569,6 +2708,15 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
* If this fails 1024 times, we then ask the kernel for
* choosing one.
*/
+ } else {
+ /* Allow to reuse address for non-random ports. */
+ result = open_socket(sockmgr, localaddr,
+ ISC_SOCKET_REUSEADDRESS, &sock);
+
+ if (result == ISC_R_SUCCESS)
+ *sockp = sock;
+
+ return (result);
}
memset(held, 0, sizeof(held));
@@ -2650,6 +2798,21 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
if (result != ISC_R_SUCCESS)
goto deallocate_dispatch;
}
+
+ disp->port_table = isc_mem_get(mgr->mctx,
+ sizeof(disp->port_table[0]) *
+ DNS_DISPATCH_PORTTABLESIZE);
+ if (disp->port_table == NULL)
+ goto deallocate_dispatch;
+ for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++)
+ ISC_LIST_INIT(disp->port_table[i]);
+
+ result = isc_mempool_create(mgr->mctx, sizeof(dispportentry_t),
+ &disp->portpool);
+ if (result != ISC_R_SUCCESS)
+ goto deallocate_dispatch;
+ isc_mempool_setname(disp->portpool, "disp_portpool");
+ isc_mempool_setfreemax(disp->portpool, 128);
}
disp->socktype = isc_sockettype_udp;
disp->socket = sock;
@@ -2829,6 +2992,8 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
oldestresp->item_out = ISC_TRUE;
isc_task_send(oldestresp->task,
ISC_EVENT_PTR(&rev));
+ inc_stats(disp->mgr,
+ dns_resstatscounter_dispabort);
}
}
@@ -2852,6 +3017,7 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
if (result != ISC_R_SUCCESS) {
UNLOCK(&qid->lock);
UNLOCK(&disp->lock);
+ inc_stats(disp->mgr, dns_resstatscounter_dispsockfail);
return (result);
}
} else {
diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c
index ee6c03b..75486af 100644
--- a/lib/dns/dlz.c
+++ b/lib/dns/dlz.c
@@ -1,8 +1,8 @@
/*
- * Portions Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -50,7 +50,7 @@
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dlz.c,v 1.2.2.2 2005/09/06 03:47:17 marka Exp $ */
+/* $Id: dlz.c,v 1.5.332.2 2009/01/18 23:47:35 tbox Exp $ */
/*! \file */
@@ -126,7 +126,7 @@ dns_dlzallowzonexfr(dns_view_t *view, dns_name_t *name,
dlzdatabase = view->dlzdatabase;
allowzonexfr = dlzdatabase->implementation->methods->allowzonexfr;
result = (*allowzonexfr)(dlzdatabase->implementation->driverarg,
- dlzdatabase->dbdata, dlzdatabase->mctx,
+ dlzdatabase->dbdata, dlzdatabase->mctx,
view->rdclass, name, clientaddr, dbp);
if (result == ISC_R_NOTIMPLEMENTED)
@@ -275,7 +275,7 @@ dns_dlzfindzone(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
* trying shorter names portions of the name until we find a
* match, have an error, or are below the 'minlabels'
* threshold. minlabels is 0, if the standard database didn't
- * have a zone name match. Otherwise minlables is the number
+ * have a zone name match. Otherwise minlabels is the number
* of labels in that name. We need to beat that for a
* "better" match for the DLZ database to be authoritative
* instead of the standard database.
diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c
index 75ca440..f06d715 100644
--- a/lib/dns/dnssec.c
+++ b/lib/dns/dnssec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +16,7 @@
*/
/*
- * $Id: dnssec.c,v 1.81.18.10 2007/09/14 04:35:42 marka Exp $
+ * $Id: dnssec.c,v 1.93 2008/11/14 23:47:33 tbox Exp $
*/
/*! \file */
@@ -366,6 +366,9 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
if (ret != ISC_R_SUCCESS)
return (ret);
+ if (set->type != sig.covered)
+ return (DNS_R_SIGINVALID);
+
if (isc_serial_lt(sig.timeexpire, sig.timesigned))
return (DNS_R_SIGINVALID);
@@ -382,6 +385,27 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
}
/*
+ * NS, SOA and DNSSKEY records are signed by their owner.
+ * DS records are signed by the parent.
+ */
+ switch (set->type) {
+ case dns_rdatatype_ns:
+ case dns_rdatatype_soa:
+ case dns_rdatatype_dnskey:
+ if (!dns_name_equal(name, &sig.signer))
+ return (DNS_R_SIGINVALID);
+ break;
+ case dns_rdatatype_ds:
+ if (dns_name_equal(name, &sig.signer))
+ return (DNS_R_SIGINVALID);
+ /* FALLTHROUGH */
+ default:
+ if (!dns_name_issubdomain(name, &sig.signer))
+ return (DNS_R_SIGINVALID);
+ break;
+ }
+
+ /*
* Is the key allowed to sign data?
*/
flags = dst_key_flags(key);
@@ -407,7 +431,7 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
dns_fixedname_init(&fnewname);
labels = dns_name_countlabels(name) - 1;
RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
- NULL) == ISC_R_SUCCESS);
+ NULL) == ISC_R_SUCCESS);
if (labels - sig.labels > 0)
dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1,
NULL, dns_fixedname_name(&fnewname));
@@ -487,9 +511,9 @@ cleanup_struct:
dns_rdata_freestruct(&sig);
if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
- if (wild != NULL)
+ if (wild != NULL)
RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname,
- dns_fixedname_name(&fnewname),
+ dns_fixedname_name(&fnewname),
wild, NULL) == ISC_R_SUCCESS);
ret = DNS_R_FROMWILDCARD;
}
@@ -541,6 +565,9 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
if (!is_zone_key(pubkey) ||
(dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
goto next;
+ /* Corrupted .key file? */
+ if (!dns_name_equal(name, dst_key_name(pubkey)))
+ goto next;
keys[count] = NULL;
result = dst_key_fromfile(dst_key_name(pubkey),
dst_key_id(pubkey),
@@ -802,7 +829,7 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
RETERR(dst_context_create(key, mctx, &ctx));
/*
- * Digest the SIG(0) record, except for the signature.
+ * Digest the SIG(0) record, except for the signature.
*/
dns_rdata_toregion(&rdata, &r);
r.length -= sig.siglen;
diff --git a/lib/dns/ds.c b/lib/dns/ds.c
index 7cd1609..e994cc5 100644
--- a/lib/dns/ds.c
+++ b/lib/dns/ds.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ds.c,v 1.4.20.5 2006/02/22 23:50:09 marka Exp $ */
+/* $Id: ds.c,v 1.11 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c
index 7d98e10..144c685 100644
--- a/lib/dns/dst_api.c
+++ b/lib/dns/dst_api.c
@@ -1,9 +1,22 @@
/*
- * Portions Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-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 AND NETWORK ASSOCIATES 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.
+ *
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: dst_api.c,v 1.1.6.7 2006/01/27 23:57:44 marka Exp $
+ * $Id: dst_api.c,v 1.16.12.3 2009/03/02 02:00:34 marka Exp $
*/
/*! \file */
@@ -60,6 +73,8 @@ static isc_entropy_t *dst_entropy_pool = NULL;
static unsigned int dst_entropy_flags = 0;
static isc_boolean_t dst_initialized = ISC_FALSE;
+void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
+
isc_mem_t *dst__memory_pool = NULL;
/*
@@ -110,19 +125,21 @@ static isc_result_t addsuffix(char *filename, unsigned int len,
return (_r); \
} while (0); \
+#ifdef OPENSSL
static void *
default_memalloc(void *arg, size_t size) {
- UNUSED(arg);
- if (size == 0U)
- size = 1;
- return (malloc(size));
+ UNUSED(arg);
+ if (size == 0U)
+ size = 1;
+ return (malloc(size));
}
static void
default_memfree(void *arg, void *ptr) {
- UNUSED(arg);
- free(ptr);
+ UNUSED(arg);
+ free(ptr);
}
+#endif
isc_result_t
dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
@@ -147,6 +164,7 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
NULL, &dst__memory_pool, 0);
if (result != ISC_R_SUCCESS)
return (result);
+ isc_mem_setname(dst__memory_pool, "dst", NULL);
isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE);
#else
isc_mem_attach(mctx, &dst__memory_pool);
@@ -167,8 +185,10 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
RETERR(dst__openssl_init());
RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5]));
RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1]));
+ RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1]));
#ifdef HAVE_OPENSSL_DSA
RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA]));
+ RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
#endif
RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
#endif /* OPENSSL */
@@ -223,7 +243,7 @@ dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
if (key->func->createctx == NULL)
return (DST_R_UNSUPPORTEDALG);
- if (key->opaque == NULL)
+ if (key->keydata.generic == NULL)
return (DST_R_NULLKEY);
dctx = isc_mem_get(mctx, sizeof(dst_context_t));
@@ -273,8 +293,9 @@ dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
key = dctx->key;
CHECKALG(key->key_alg);
- if (key->opaque == NULL)
+ if (key->keydata.generic == NULL)
return (DST_R_NULLKEY);
+
if (key->func->sign == NULL)
return (DST_R_NOTPRIVATEKEY);
if (key->func->isprivate == NULL ||
@@ -290,7 +311,7 @@ dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
REQUIRE(sig != NULL);
CHECKALG(dctx->key->key_alg);
- if (dctx->key->opaque == NULL)
+ if (dctx->key->keydata.generic == NULL)
return (DST_R_NULLKEY);
if (dctx->key->func->verify == NULL)
return (DST_R_NOTPUBLICKEY);
@@ -309,7 +330,7 @@ dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
CHECKALG(pub->key_alg);
CHECKALG(priv->key_alg);
- if (pub->opaque == NULL || priv->opaque == NULL)
+ if (pub->keydata.generic == NULL || priv->keydata.generic == NULL)
return (DST_R_NULLKEY);
if (pub->key_alg != priv->key_alg ||
@@ -383,10 +404,8 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
return (result);
}
- if (!dns_name_equal(name, key->key_name) ||
- id != key->key_id ||
- alg != key->key_alg)
- {
+ if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
+ alg != key->key_alg) {
dst_key_free(&key);
return (DST_R_INVALIDPRIVATEKEY);
}
@@ -427,8 +446,7 @@ dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
return (result);
if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
- (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
- {
+ (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
result = computeid(pubkey);
if (result != ISC_R_SUCCESS) {
dst_key_free(&pubkey);
@@ -512,7 +530,7 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
& 0xffff));
}
- if (key->opaque == NULL) /*%< NULL KEY */
+ if (key->keydata.generic == NULL) /*%< NULL KEY */
return (ISC_R_SUCCESS);
return (key->func->todns(key, target));
@@ -620,20 +638,71 @@ dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
return (result);
}
+gss_ctx_id_t
+dst_key_getgssctx(const dst_key_t *key)
+{
+ REQUIRE(key != NULL);
+
+ return (key->keydata.gssctx);
+}
+
isc_result_t
-dst_key_fromgssapi(dns_name_t *name, void *opaque, isc_mem_t *mctx,
+dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
dst_key_t **keyp)
{
dst_key_t *key;
- REQUIRE(opaque != NULL);
+ REQUIRE(gssctx != NULL);
REQUIRE(keyp != NULL && *keyp == NULL);
key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC,
0, dns_rdataclass_in, mctx);
if (key == NULL)
return (ISC_R_NOMEMORY);
- key->opaque = opaque;
+
+ key->keydata.gssctx = gssctx;
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags,
+ unsigned int protocol, dns_rdataclass_t rdclass,
+ const char *engine, const char *label, const char *pin,
+ isc_mem_t *mctx, dst_key_t **keyp)
+{
+ dst_key_t *key;
+ isc_result_t result;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(mctx != NULL);
+ REQUIRE(keyp != NULL && *keyp == NULL);
+ REQUIRE(label != NULL);
+
+ CHECKALG(alg);
+
+ key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx);
+ if (key == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (key->func->fromlabel == NULL) {
+ dst_key_free(&key);
+ return (DST_R_UNSUPPORTEDALG);
+ }
+
+ result = key->func->fromlabel(key, engine, label, pin);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (result);
+ }
+
+ result = computeid(key);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (result);
+ }
+
*keyp = key;
return (ISC_R_SUCCESS);
}
@@ -734,11 +803,14 @@ dst_key_free(dst_key_t **keyp) {
key = *keyp;
mctx = key->mctx;
- if (key->opaque != NULL) {
+ if (key->keydata.generic != NULL) {
INSIST(key->func->destroy != NULL);
key->func->destroy(key);
}
-
+ if (key->engine != NULL)
+ isc_mem_free(mctx, key->engine);
+ if (key->label != NULL)
+ isc_mem_free(mctx, key->label);
dns_name_free(key->key_name, mctx);
isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
memset(key, 0, sizeof(dst_key_t));
@@ -775,9 +847,11 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
switch (key->key_alg) {
case DST_ALG_RSAMD5:
case DST_ALG_RSASHA1:
+ case DST_ALG_NSEC3RSASHA1:
*n = (key->key_size + 7) / 8;
break;
case DST_ALG_DSA:
+ case DST_ALG_NSEC3DSA:
*n = DNS_SIG_DSASIGSIZE;
break;
case DST_ALG_HMACMD5:
@@ -860,7 +934,7 @@ get_key_struct(dns_name_t *name, unsigned int alg,
key->key_flags = flags;
key->key_proto = protocol;
key->mctx = mctx;
- key->opaque = NULL;
+ key->keydata.generic = NULL;
key->key_size = bits;
key->key_class = rdclass;
key->func = dst_t_func[alg];
@@ -925,6 +999,13 @@ dst_key_read_public(const char *filename, int type,
NEXTTOKEN(lex, opt, &token);
if (token.type != isc_tokentype_string)
BADTOKEN();
+
+ /*
+ * We don't support "@" in .key files.
+ */
+ if (!strcmp(DST_AS_STR(token), "@"))
+ BADTOKEN();
+
dns_fixedname_init(&name);
isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
isc_buffer_add(&b, strlen(DST_AS_STR(token)));
@@ -990,7 +1071,9 @@ issymmetric(const dst_key_t *key) {
switch (key->key_alg) {
case DST_ALG_RSAMD5:
case DST_ALG_RSASHA1:
+ case DST_ALG_NSEC3RSASHA1:
case DST_ALG_DSA:
+ case DST_ALG_NSEC3DSA:
case DST_ALG_DH:
return (ISC_FALSE);
case DST_ALG_HMACMD5:
@@ -1080,9 +1163,12 @@ write_public_key(const dst_key_t *key, int type, const char *directory) {
fwrite(r.base, 1, r.length, fp);
fputc('\n', fp);
+ fflush(fp);
+ if (ferror(fp))
+ ret = DST_R_WRITEERROR;
fclose(fp);
- return (ISC_R_SUCCESS);
+ return (ret);
}
static isc_result_t
@@ -1116,8 +1202,10 @@ buildfilename(dns_name_t *name, dns_keytag_t id,
len = 1 + 3 + 1 + 5 + strlen(suffix) + 1;
if (isc_buffer_availablelength(out) < len)
return (ISC_R_NOSPACE);
- sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id, suffix);
+ sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id,
+ suffix);
isc_buffer_add(out, len);
+
return (ISC_R_SUCCESS);
}
@@ -1186,7 +1274,8 @@ algorithm_status(unsigned int alg) {
#ifndef OPENSSL
if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
alg == DST_ALG_DSA || alg == DST_ALG_DH ||
- alg == DST_ALG_HMACMD5)
+ alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA ||
+ alg == DST_ALG_NSEC3RSASHA1)
return (DST_R_NOCRYPTO);
#endif
return (DST_R_UNSUPPORTEDALG);
@@ -1219,3 +1308,8 @@ dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
flags &= ~ISC_ENTROPY_GOODONLY;
return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
}
+
+unsigned int
+dst__entropy_status(void) {
+ return (isc_entropy_status(dst_entropy_pool));
+}
diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h
index f2deb72..0c1a71c 100644
--- a/lib/dns/dst_internal.h
+++ b/lib/dns/dst_internal.h
@@ -1,9 +1,22 @@
/*
- * Portions Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 2000-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 AND NETWORK ASSOCIATES 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.
+ *
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -16,7 +29,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_internal.h,v 1.1.6.5 2006/01/27 23:57:44 marka Exp $ */
+/* $Id: dst_internal.h,v 1.11 2008/04/01 23:47:10 tbox Exp $ */
#ifndef DST_DST_INTERNAL_H
#define DST_DST_INTERNAL_H 1
@@ -27,9 +40,22 @@
#include <isc/magic.h>
#include <isc/region.h>
#include <isc/types.h>
+#include <isc/md5.h>
+#include <isc/sha1.h>
+#include <isc/hmacmd5.h>
+#include <isc/hmacsha.h>
#include <dst/dst.h>
+#ifdef OPENSSL
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+#endif
+
ISC_LANG_BEGINDECLS
#define KEY_MAGIC ISC_MAGIC('D','S','T','K')
@@ -46,6 +72,13 @@ extern isc_mem_t *dst__memory_pool;
typedef struct dst_func dst_func_t;
+typedef struct dst_hmacmd5_key dst_hmacmd5_key_t;
+typedef struct dst_hmacsha1_key dst_hmacsha1_key_t;
+typedef struct dst_hmacsha224_key dst_hmacsha224_key_t;
+typedef struct dst_hmacsha256_key dst_hmacsha256_key_t;
+typedef struct dst_hmacsha384_key dst_hmacsha384_key_t;
+typedef struct dst_hmacsha512_key dst_hmacsha512_key_t;
+
/*% DST Key Structure */
struct dst_key {
unsigned int magic;
@@ -58,7 +91,27 @@ struct dst_key {
isc_uint16_t key_bits; /*%< hmac digest bits */
dns_rdataclass_t key_class; /*%< class of the key record */
isc_mem_t *mctx; /*%< memory context */
- void * opaque; /*%< pointer to key in crypto pkg fmt */
+ char *engine; /*%< engine name (HSM) */
+ char *label; /*%< engine label (HSM) */
+ union {
+ void *generic;
+ gss_ctx_id_t gssctx;
+#ifdef OPENSSL
+#if USE_EVP_RSA
+ RSA *rsa;
+#endif
+ DSA *dsa;
+ DH *dh;
+ EVP_PKEY *pkey;
+#endif
+ dst_hmacmd5_key_t *hmacmd5;
+ dst_hmacsha1_key_t *hmacsha1;
+ dst_hmacsha224_key_t *hmacsha224;
+ dst_hmacsha256_key_t *hmacsha256;
+ dst_hmacsha384_key_t *hmacsha384;
+ dst_hmacsha512_key_t *hmacsha512;
+
+ } keydata; /*%< pointer to key in crypto pkg fmt */
dst_func_t * func; /*%< crypto package specific functions */
};
@@ -66,7 +119,21 @@ struct dst_context {
unsigned int magic;
dst_key_t *key;
isc_mem_t *mctx;
- void *opaque;
+ union {
+ void *generic;
+ dst_gssapi_signverifyctx_t *gssctx;
+ isc_md5_t *md5ctx;
+ isc_sha1_t *sha1ctx;
+ isc_hmacmd5_t *hmacmd5ctx;
+ isc_hmacsha1_t *hmacsha1ctx;
+ isc_hmacsha224_t *hmacsha224ctx;
+ isc_hmacsha256_t *hmacsha256ctx;
+ isc_hmacsha384_t *hmacsha384ctx;
+ isc_hmacsha512_t *hmacsha512ctx;
+#ifdef OPENSSL
+ EVP_MD_CTX *evp_md_ctx;
+#endif
+ } ctxdata;
};
struct dst_func {
@@ -100,6 +167,9 @@ struct dst_func {
/* cleanup */
void (*cleanup)(void);
+
+ isc_result_t (*fromlabel)(dst_key_t *key, const char *engine,
+ const char *label, const char *pin);
};
/*%
@@ -136,6 +206,11 @@ void * dst__mem_realloc(void *ptr, size_t size);
isc_result_t dst__entropy_getdata(void *buf, unsigned int len,
isc_boolean_t pseudo);
+/*
+ * Entropy status hook.
+ */
+unsigned int dst__entropy_status(void);
+
ISC_LANG_ENDDECLS
#endif /* DST_DST_INTERNAL_H */
diff --git a/lib/dns/dst_lib.c b/lib/dns/dst_lib.c
index 305051c..f1021d3 100644
--- a/lib/dns/dst_lib.c
+++ b/lib/dns/dst_lib.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -17,7 +17,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: dst_lib.c,v 1.1.6.3 2005/04/29 00:15:51 marka Exp $
+ * $Id: dst_lib.c,v 1.5 2007/06/19 23:47:16 tbox Exp $
*/
/*! \file */
diff --git a/lib/dns/dst_openssl.h b/lib/dns/dst_openssl.h
index 79e10b0..80eef93 100644
--- a/lib/dns/dst_openssl.h
+++ b/lib/dns/dst_openssl.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_openssl.h,v 1.1.4.3 2005/04/29 00:15:52 marka Exp $ */
+/* $Id: dst_openssl.h,v 1.7 2008/04/01 23:47:10 tbox Exp $ */
#ifndef DST_OPENSSL_H
#define DST_OPENSSL_H 1
@@ -28,6 +28,12 @@ ISC_LANG_BEGINDECLS
isc_result_t
dst__openssl_toresult(isc_result_t fallback);
+ENGINE *
+dst__openssl_getengine(const char *name);
+
+isc_result_t
+dst__openssl_setdefault(const char *name);
+
ISC_LANG_ENDDECLS
#endif /* DST_OPENSSL_H */
diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c
index ce361ef..2da72ae 100644
--- a/lib/dns/dst_parse.c
+++ b/lib/dns/dst_parse.c
@@ -1,6 +1,19 @@
/*
- * Portions Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-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 AND NETWORK ASSOCIATES 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.
+ *
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -18,7 +31,7 @@
/*%
* Principal Author: Brian Wellington
- * $Id: dst_parse.c,v 1.1.6.9 2008/01/22 23:27:05 tbox Exp $
+ * $Id: dst_parse.c,v 1.14.120.2 2009/03/02 23:47:11 tbox Exp $
*/
#include <config.h>
@@ -54,6 +67,9 @@ static struct parse_map map[] = {
{TAG_RSA_EXPONENT1, "Exponent1:"},
{TAG_RSA_EXPONENT2, "Exponent2:"},
{TAG_RSA_COEFFICIENT, "Coefficient:"},
+ {TAG_RSA_ENGINE, "Engine:" },
+ {TAG_RSA_LABEL, "Label:" },
+ {TAG_RSA_PIN, "PIN:" },
{TAG_DH_PRIME, "Prime(p):"},
{TAG_DH_GENERATOR, "Generator(g):"},
@@ -115,16 +131,39 @@ find_tag(const int value) {
static int
check_rsa(const dst_private_t *priv) {
int i, j;
- if (priv->nelements != RSA_NTAGS)
- return (-1);
- for (i = 0; i < RSA_NTAGS; i++) {
- for (j = 0; j < priv->nelements; j++)
+ isc_boolean_t have[RSA_NTAGS];
+ isc_boolean_t ok;
+ unsigned int mask;
+
+ for (i = 0; i < RSA_NTAGS; i++)
+ have[i] = ISC_FALSE;
+ for (j = 0; j < priv->nelements; j++) {
+ for (i = 0; i < RSA_NTAGS; i++)
if (priv->elements[j].tag == TAG(DST_ALG_RSAMD5, i))
break;
- if (j == priv->nelements)
+ if (i == RSA_NTAGS)
return (-1);
+ have[i] = ISC_TRUE;
}
- return (0);
+
+ mask = ~0;
+ mask <<= sizeof(mask) * 8 - TAG_SHIFT;
+ mask >>= sizeof(mask) * 8 - TAG_SHIFT;
+
+ if (have[TAG_RSA_ENGINE & mask])
+ ok = have[TAG_RSA_MODULUS & mask] &&
+ have[TAG_RSA_PUBLICEXPONENT & mask] &&
+ have[TAG_RSA_LABEL & mask];
+ else
+ ok = have[TAG_RSA_MODULUS & mask] &&
+ have[TAG_RSA_PUBLICEXPONENT & mask] &&
+ have[TAG_RSA_PRIVATEEXPONENT & mask] &&
+ have[TAG_RSA_PRIME1 & mask] &&
+ have[TAG_RSA_PRIME2 & mask] &&
+ have[TAG_RSA_EXPONENT1 & mask] &&
+ have[TAG_RSA_EXPONENT2 & mask] &&
+ have[TAG_RSA_COEFFICIENT & mask];
+ return (ok ? 0 : -1 );
}
static int
@@ -486,8 +525,10 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
fprintf(fp, "\n");
}
+ fflush(fp);
+ iret = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
fclose(fp);
- return (ISC_R_SUCCESS);
+ return (iret);
}
/*! \file */
diff --git a/lib/dns/dst_parse.h b/lib/dns/dst_parse.h
index 665fcfc..27c7580 100644
--- a/lib/dns/dst_parse.h
+++ b/lib/dns/dst_parse.h
@@ -1,6 +1,19 @@
/*
- * Portions Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 2000-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 AND NETWORK ASSOCIATES 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.
+ *
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +29,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_parse.h,v 1.1.6.7 2008/05/15 23:46:06 tbox Exp $ */
+/* $Id: dst_parse.h,v 1.11 2008/05/15 00:50:26 each Exp $ */
/*! \file */
#ifndef DST_DST_PARSE_H
@@ -37,7 +50,7 @@
#define TAG(alg, off) (((alg) << TAG_SHIFT) + (off))
/* These are used by both RSA-MD5 and RSA-SHA1 */
-#define RSA_NTAGS 8
+#define RSA_NTAGS 11
#define TAG_RSA_MODULUS ((DST_ALG_RSAMD5 << TAG_SHIFT) + 0)
#define TAG_RSA_PUBLICEXPONENT ((DST_ALG_RSAMD5 << TAG_SHIFT) + 1)
#define TAG_RSA_PRIVATEEXPONENT ((DST_ALG_RSAMD5 << TAG_SHIFT) + 2)
@@ -46,6 +59,9 @@
#define TAG_RSA_EXPONENT1 ((DST_ALG_RSAMD5 << TAG_SHIFT) + 5)
#define TAG_RSA_EXPONENT2 ((DST_ALG_RSAMD5 << TAG_SHIFT) + 6)
#define TAG_RSA_COEFFICIENT ((DST_ALG_RSAMD5 << TAG_SHIFT) + 7)
+#define TAG_RSA_ENGINE ((DST_ALG_RSAMD5 << TAG_SHIFT) + 8)
+#define TAG_RSA_LABEL ((DST_ALG_RSAMD5 << TAG_SHIFT) + 9)
+#define TAG_RSA_PIN ((DST_ALG_RSAMD5 << TAG_SHIFT) + 10)
#define DH_NTAGS 4
#define TAG_DH_PRIME ((DST_ALG_DH << TAG_SHIFT) + 0)
diff --git a/lib/dns/dst_result.c b/lib/dns/dst_result.c
index c9bf073..429dbb2 100644
--- a/lib/dns/dst_result.c
+++ b/lib/dns/dst_result.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -17,7 +17,7 @@
/*%
* Principal Author: Brian Wellington
- * $Id: dst_result.c,v 1.1.6.3 2005/04/29 00:15:52 marka Exp $
+ * $Id: dst_result.c,v 1.7 2008/04/01 23:47:10 tbox Exp $
*/
#include <config.h>
@@ -49,7 +49,8 @@ static const char *text[DST_R_NRESULTS] = {
"not a key that can compute a secret", /*%< 17 */
"failure computing a shared secret", /*%< 18 */
"no randomness available", /*%< 19 */
- "bad key type" /*%< 20 */
+ "bad key type", /*%< 20 */
+ "no engine" /*%< 21 */
};
#define DST_RESULT_RESULTSET 2
diff --git a/lib/dns/forward.c b/lib/dns/forward.c
index e80a477..39e2ef5 100644
--- a/lib/dns/forward.c
+++ b/lib/dns/forward.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: forward.c,v 1.6.18.4 2005/07/12 01:22:20 marka Exp $ */
+/* $Id: forward.c,v 1.12 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/gen-unix.h b/lib/dns/gen-unix.h
index fc2dbf2..4186f63 100644
--- a/lib/dns/gen-unix.h
+++ b/lib/dns/gen-unix.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gen-unix.h,v 1.14.18.3 2005/06/08 02:07:54 marka Exp $ */
+/* $Id: gen-unix.h,v 1.19.332.2 2009/01/18 23:47:35 tbox Exp $ */
/*! \file
* \brief
@@ -23,7 +23,7 @@
* directly portable between Unix-like systems and Windows NT, option
* parsing and directory scanning. It is here because it was decided
* that the "gen" build utility was not to depend on libisc.a, so
- * the functions delcared in isc/commandline.h and isc/dir.h could not
+ * the functions declared in isc/commandline.h and isc/dir.h could not
* be used.
*
* The commandline stuff is really just a wrapper around getopt().
diff --git a/lib/dns/gen.c b/lib/dns/gen.c
index 1e6212a..ede8bc0 100644
--- a/lib/dns/gen.c
+++ b/lib/dns/gen.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gen.c,v 1.73.18.6 2006/10/02 06:36:43 marka Exp $ */
+/* $Id: gen.c,v 1.83 2008/09/25 04:02:38 tbox Exp $ */
/*! \file */
@@ -41,6 +41,8 @@
#include "gen-unix.h"
#endif
+#define TYPECLASSLEN 21
+
#define FROMTEXTARGS "rdclass, type, lexer, origin, options, target, callbacks"
#define FROMTEXTCLASS "rdclass"
#define FROMTEXTTYPE "type"
@@ -134,21 +136,21 @@ const char copyright[] =
struct cc {
struct cc *next;
int rdclass;
- char classname[11];
+ char classname[TYPECLASSLEN];
} *classes;
struct tt {
struct tt *next;
int rdclass;
int type;
- char classname[11];
- char typename[11];
+ char classname[TYPECLASSLEN];
+ char typename[TYPECLASSLEN];
char dirname[256]; /* XXX Should be max path length */
} *types;
struct ttnam {
- char typename[11];
- char macroname[11];
+ char typename[TYPECLASSLEN];
+ char macroname[TYPECLASSLEN];
char attr[256];
unsigned int sorted;
int type;
@@ -215,7 +217,7 @@ doswitch(const char *name, const char *function, const char *args,
int first = 1;
int lasttype = 0;
int subswitch = 0;
- char buf1[11], buf2[11];
+ char buf1[TYPECLASSLEN], buf2[TYPECLASSLEN];
const char *result = " result =";
if (res == NULL)
@@ -281,7 +283,7 @@ doswitch(const char *name, const char *function, const char *args,
void
dodecl(char *type, char *function, char *args) {
struct tt *tt;
- char buf1[11], buf2[11];
+ char buf1[TYPECLASSLEN], buf2[TYPECLASSLEN];
fputs("\n", stdout);
for (tt = types; tt; tt = tt->next)
@@ -332,7 +334,7 @@ insert_into_typenames(int type, const char *typename, const char *attr) {
fprintf(stderr, "Error: typenames array too small\n");
exit(1);
}
-
+
if (strlen(typename) > sizeof(ttn->typename) - 1) {
fprintf(stderr, "Error: type name %s is too long\n",
typename);
@@ -392,6 +394,8 @@ add(int rdclass, const char *classname, int type, const char *typename,
newtt->type = type;
strcpy(newtt->classname, classname);
strcpy(newtt->typename, typename);
+ if (strncmp(dirname, "./", 2) == 0)
+ dirname += 2;
strcpy(newtt->dirname, dirname);
tt = types;
@@ -449,16 +453,16 @@ add(int rdclass, const char *classname, int type, const char *typename,
void
sd(int rdclass, const char *classname, const char *dirname, char filetype) {
- char buf[sizeof("0123456789_65535.h")];
- char fmt[sizeof("%10[-0-9a-z]_%d.h")];
+ char buf[sizeof("01234567890123456789_65535.h")];
+ char fmt[sizeof("%20[-0-9a-z]_%d.h")];
int type;
- char typename[11];
+ char typename[TYPECLASSLEN];
isc_dir_t dir;
if (!start_directory(dirname, &dir))
return;
- sprintf(fmt,"%s%c", "%10[-0-9a-z]_%d.", filetype);
+ sprintf(fmt,"%s%c", "%20[-0-9a-z]_%d.", filetype);
while (next_file(&dir)) {
if (sscanf(dir.filename, fmt, typename, &type) != 2)
continue;
@@ -495,7 +499,7 @@ main(int argc, char **argv) {
char buf[256]; /* XXX Should be max path length */
char srcdir[256]; /* XXX Should be max path length */
int rdclass;
- char classname[11];
+ char classname[TYPECLASSLEN];
struct tt *tt;
struct cc *cc;
struct ttnam *ttn, *ttn2;
@@ -510,7 +514,7 @@ main(int argc, char **argv) {
int structs = 0;
int depend = 0;
int c, i, j;
- char buf1[11];
+ char buf1[TYPECLASSLEN];
char filetype = 'c';
FILE *fd;
char *prefix = NULL;
@@ -594,7 +598,7 @@ main(int argc, char **argv) {
sd(0, "", buf, filetype);
if (time(&now) != -1) {
- if ((tm = localtime(&now)) != NULL && tm->tm_year > 104)
+ if ((tm = localtime(&now)) != NULL && tm->tm_year > 104)
sprintf(year, "-%d", tm->tm_year + 1900);
else
year[0] = 0;
@@ -692,7 +696,7 @@ main(int argc, char **argv) {
"\t\t strncasecmp(_s,(_tn),"
"(sizeof(_s) - 1)) == 0) { \\\n");
fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & "
- "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
+ "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n");
fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n");
fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n");
@@ -743,7 +747,7 @@ main(int argc, char **argv) {
if (ttn == NULL)
continue;
fprintf(stdout, "\tcase %u: return (%s); \\\n",
- i, upper(ttn->attr));
+ i, upper(ttn->attr));
}
fprintf(stdout, "\t}\n");
@@ -755,7 +759,7 @@ main(int argc, char **argv) {
continue;
fprintf(stdout, "\tcase %u: return "
"(str_totext(\"%s\", target)); \\\n",
- i, upper(ttn->typename));
+ i, upper(ttn->typename));
}
fprintf(stdout, "\t}\n");
diff --git a/lib/dns/gssapi_link.c b/lib/dns/gssapi_link.c
index a6a367a..0dd27bb 100644
--- a/lib/dns/gssapi_link.c
+++ b/lib/dns/gssapi_link.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -16,13 +16,13 @@
*/
/*
- * $Id: gssapi_link.c,v 1.1.6.3 2005/04/29 00:15:53 marka Exp $
+ * $Id: gssapi_link.c,v 1.12 2008/11/11 03:55:01 marka Exp $
*/
-#ifdef GSSAPI
-
#include <config.h>
+#ifdef GSSAPI
+
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/string.h>
@@ -33,60 +33,73 @@
#include "dst_internal.h"
#include "dst_parse.h"
-#include <gssapi/gssapi.h>
+#include <dst/gssapi.h>
#define INITIAL_BUFFER_SIZE 1024
#define BUFFER_EXTRA 1024
#define REGION_TO_GBUFFER(r, gb) \
do { \
- (gb).length = (r).length; \
- (gb).value = (r).base; \
+ (gb).length = (r).length; \
+ (gb).value = (r).base; \
} while (0)
-typedef struct gssapi_ctx {
- isc_buffer_t *buffer;
- gss_ctx_id_t *context_id;
-} gssapi_ctx_t;
+struct dst_gssapi_signverifyctx {
+ isc_buffer_t *buffer;
+};
+/*%
+ * Allocate a temporary "context" for use in gathering data for signing
+ * or verifying.
+ */
static isc_result_t
-gssapi_createctx(dst_key_t *key, dst_context_t *dctx) {
- gssapi_ctx_t *ctx;
+gssapi_create_signverify_ctx(dst_key_t *key, dst_context_t *dctx) {
+ dst_gssapi_signverifyctx_t *ctx;
isc_result_t result;
UNUSED(key);
- ctx = isc_mem_get(dctx->mctx, sizeof(gssapi_ctx_t));
+ ctx = isc_mem_get(dctx->mctx, sizeof(dst_gssapi_signverifyctx_t));
if (ctx == NULL)
return (ISC_R_NOMEMORY);
ctx->buffer = NULL;
result = isc_buffer_allocate(dctx->mctx, &ctx->buffer,
INITIAL_BUFFER_SIZE);
if (result != ISC_R_SUCCESS) {
- isc_mem_put(dctx->mctx, ctx, sizeof(gssapi_ctx_t));
+ isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
return (result);
}
- ctx->context_id = key->opaque;
- dctx->opaque = ctx;
+
+ dctx->ctxdata.gssctx = ctx;
+
return (ISC_R_SUCCESS);
}
+/*%
+ * Destroy the temporary sign/verify context.
+ */
static void
-gssapi_destroyctx(dst_context_t *dctx) {
- gssapi_ctx_t *ctx = dctx->opaque;
+gssapi_destroy_signverify_ctx(dst_context_t *dctx) {
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
if (ctx != NULL) {
if (ctx->buffer != NULL)
isc_buffer_free(&ctx->buffer);
- isc_mem_put(dctx->mctx, ctx, sizeof(gssapi_ctx_t));
- dctx->opaque = NULL;
+ isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
+ dctx->ctxdata.gssctx = NULL;
}
}
+/*%
+ * Add data to our running buffer of data we will be signing or verifying.
+ * This code will see if the new data will fit in our existing buffer, and
+ * copy it in if it will. If not, it will attempt to allocate a larger
+ * buffer and copy old+new into it, and free the old buffer.
+ */
static isc_result_t
gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
- gssapi_ctx_t *ctx = dctx->opaque;
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
isc_buffer_t *newbuffer = NULL;
isc_region_t r;
unsigned int length;
@@ -103,8 +116,8 @@ gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
return (result);
isc_buffer_usedregion(ctx->buffer, &r);
- (void) isc_buffer_copyregion(newbuffer, &r);
- (void) isc_buffer_copyregion(newbuffer, data);
+ (void)isc_buffer_copyregion(newbuffer, &r);
+ (void)isc_buffer_copyregion(newbuffer, data);
isc_buffer_free(&ctx->buffer);
ctx->buffer = newbuffer;
@@ -112,56 +125,129 @@ gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
return (ISC_R_SUCCESS);
}
+/*%
+ * Sign.
+ */
static isc_result_t
gssapi_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- gssapi_ctx_t *ctx = dctx->opaque;
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
isc_region_t message;
gss_buffer_desc gmessage, gsig;
OM_uint32 minor, gret;
+ gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
+ char buf[1024];
+ /*
+ * Convert the data we wish to sign into a structure gssapi can
+ * understand.
+ */
isc_buffer_usedregion(ctx->buffer, &message);
REGION_TO_GBUFFER(message, gmessage);
- gret = gss_get_mic(&minor, ctx->context_id,
- GSS_C_QOP_DEFAULT, &gmessage, &gsig);
- if (gret != 0)
+ /*
+ * Generate the signature.
+ */
+ gret = gss_get_mic(&minor, gssctx, GSS_C_QOP_DEFAULT, &gmessage,
+ &gsig);
+
+ /*
+ * If it did not complete, we log the result and return a generic
+ * failure code.
+ */
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "GSS sign error: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
return (ISC_R_FAILURE);
+ }
+ /*
+ * If it will not fit in our allocated buffer, return that we need
+ * more space.
+ */
if (gsig.length > isc_buffer_availablelength(sig)) {
gss_release_buffer(&minor, &gsig);
return (ISC_R_NOSPACE);
}
+ /*
+ * Copy the output into our buffer space, and release the gssapi
+ * allocated space.
+ */
isc_buffer_putmem(sig, gsig.value, gsig.length);
-
- gss_release_buffer(&minor, &gsig);
+ if (gsig.length != 0)
+ gss_release_buffer(&minor, &gsig);
return (ISC_R_SUCCESS);
}
+/*%
+ * Verify.
+ */
static isc_result_t
gssapi_verify(dst_context_t *dctx, const isc_region_t *sig) {
- gssapi_ctx_t *ctx = dctx->opaque;
- isc_region_t message;
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
+ isc_region_t message, r;
gss_buffer_desc gmessage, gsig;
OM_uint32 minor, gret;
-
+ gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
+ unsigned char *buf;
+ char err[1024];
+
+ /*
+ * Convert the data we wish to sign into a structure gssapi can
+ * understand.
+ */
isc_buffer_usedregion(ctx->buffer, &message);
REGION_TO_GBUFFER(message, gmessage);
- REGION_TO_GBUFFER(*sig, gsig);
-
- gret = gss_verify_mic(&minor, ctx->context_id, &gmessage, &gsig, NULL);
- if (gret != 0)
+ /*
+ * XXXMLG
+ * It seem that gss_verify_mic() modifies the signature buffer,
+ * at least on Heimdal's implementation. Copy it here to an allocated
+ * buffer.
+ */
+ buf = isc_mem_allocate(dst__memory_pool, sig->length);
+ if (buf == NULL)
return (ISC_R_FAILURE);
+ memcpy(buf, sig->base, sig->length);
+ r.base = buf;
+ r.length = sig->length;
+ REGION_TO_GBUFFER(r, gsig);
+
+ /*
+ * Verify the data.
+ */
+ gret = gss_verify_mic(&minor, gssctx, &gmessage, &gsig, NULL);
+
+ isc_mem_free(dst__memory_pool, buf);
+
+ /*
+ * Convert return codes into something useful to us.
+ */
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "GSS verify error: %s",
+ gss_error_tostring(gret, minor, err, sizeof(err)));
+ if (gret == GSS_S_DEFECTIVE_TOKEN ||
+ gret == GSS_S_BAD_SIG ||
+ gret == GSS_S_DUPLICATE_TOKEN ||
+ gret == GSS_S_OLD_TOKEN ||
+ gret == GSS_S_UNSEQ_TOKEN ||
+ gret == GSS_S_GAP_TOKEN ||
+ gret == GSS_S_CONTEXT_EXPIRED ||
+ gret == GSS_S_NO_CONTEXT ||
+ gret == GSS_S_FAILURE)
+ return(DST_R_VERIFYFAILURE);
+ else
+ return (ISC_R_FAILURE);
+ }
return (ISC_R_SUCCESS);
}
static isc_boolean_t
gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) {
- gss_ctx_id_t gsskey1 = key1->opaque;
- gss_ctx_id_t gsskey2 = key2->opaque;
+ gss_ctx_id_t gsskey1 = key1->keydata.gssctx;
+ gss_ctx_id_t gsskey2 = key2->keydata.gssctx;
/* No idea */
return (ISC_TF(gsskey1 == gsskey2));
@@ -179,18 +265,19 @@ gssapi_generate(dst_key_t *key, int unused) {
static isc_boolean_t
gssapi_isprivate(const dst_key_t *key) {
UNUSED(key);
- return (ISC_TRUE);
+ return (ISC_TRUE);
}
static void
gssapi_destroy(dst_key_t *key) {
- UNUSED(key);
- /* No idea */
+ REQUIRE(key != NULL);
+ dst_gssapi_deletectx(key->mctx, &key->keydata.gssctx);
+ key->keydata.gssctx = NULL;
}
static dst_func_t gssapi_functions = {
- gssapi_createctx,
- gssapi_destroyctx,
+ gssapi_create_signverify_ctx,
+ gssapi_destroy_signverify_ctx,
gssapi_adddata,
gssapi_sign,
gssapi_verify,
@@ -205,6 +292,7 @@ static dst_func_t gssapi_functions = {
NULL, /*%< tofile */
NULL, /*%< parse */
NULL, /*%< cleanup */
+ NULL /*%< fromlabel */
};
isc_result_t
diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c
index ce5d6fa..11eadb9 100644
--- a/lib/dns/gssapictx.c
+++ b/lib/dns/gssapictx.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,11 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gssapictx.c,v 1.1.6.3 2005/04/29 00:15:54 marka Exp $ */
+/* $Id: gssapictx.c,v 1.12 2008/04/03 06:09:04 tbox Exp $ */
#include <config.h>
#include <stdlib.h>
+#include <string.h>
#include <isc/buffer.h>
#include <isc/dir.h>
@@ -27,6 +28,7 @@
#include <isc/lex.h>
#include <isc/mem.h>
#include <isc/once.h>
+#include <isc/print.h>
#include <isc/random.h>
#include <isc/string.h>
#include <isc/time.h>
@@ -39,34 +41,76 @@
#include <dns/result.h>
#include <dns/types.h>
#include <dns/keyvalues.h>
+#include <dns/log.h>
#include <dst/gssapi.h>
#include <dst/result.h>
#include "dst_internal.h"
-#ifdef GSSAPI
+/*
+ * If we're using our own SPNEGO implementation (see configure.in),
+ * pull it in now. Otherwise, we just use whatever GSSAPI supplies.
+ */
+#if defined(GSSAPI) && defined(USE_ISC_SPNEGO)
+#include "spnego.h"
+#define gss_accept_sec_context gss_accept_sec_context_spnego
+#define gss_init_sec_context gss_init_sec_context_spnego
+#endif
-#include <gssapi/gssapi.h>
+/*
+ * Solaris8 apparently needs an explicit OID set, and Solaris10 needs
+ * one for anything but Kerberos. Supplying an explicit OID set
+ * doesn't appear to hurt anything in other implementations, so we
+ * always use one. If we're not using our own SPNEGO implementation,
+ * we include SPNEGO's OID.
+ */
+#if defined(GSSAPI)
-#define RETERR(x) do { \
- result = (x); \
- if (result != ISC_R_SUCCESS) \
- goto out; \
+static unsigned char krb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+#ifndef USE_ISC_SPNEGO
+static unsigned char spnego_mech_oid_bytes[] = {
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
+};
+#endif
+
+static gss_OID_desc mech_oid_set_array[] = {
+ { sizeof(krb5_mech_oid_bytes), krb5_mech_oid_bytes },
+#ifndef USE_ISC_SPNEGO
+ { sizeof(spnego_mech_oid_bytes), spnego_mech_oid_bytes },
+#endif
+};
+
+static gss_OID_set_desc mech_oid_set = {
+ sizeof(mech_oid_set_array) / sizeof(*mech_oid_set_array),
+ mech_oid_set_array
+};
+
+#endif
+
+#define REGION_TO_GBUFFER(r, gb) \
+ do { \
+ (gb).length = (r).length; \
+ (gb).value = (r).base; \
} while (0)
-#define REGION_TO_GBUFFER(r, gb) \
- do { \
- (gb).length = (r).length; \
- (gb).value = (r).base; \
+#define GBUFFER_TO_REGION(gb, r) \
+ do { \
+ (r).length = (gb).length; \
+ (r).base = (gb).value; \
} while (0)
-#define GBUFFER_TO_REGION(gb, r) \
- do { \
- (r).length = (gb).length; \
- (r).base = (gb).value; \
+
+#define RETERR(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto out; \
} while (0)
+#ifdef GSSAPI
static inline void
name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
gss_buffer_desc *gbuffer)
@@ -77,22 +121,81 @@ name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
if (!dns_name_isabsolute(name))
namep = name;
- else {
+ else
+ {
unsigned int labels;
dns_name_init(&tname, NULL);
labels = dns_name_countlabels(name);
dns_name_getlabelsequence(name, 0, labels - 1, &tname);
namep = &tname;
}
-
+
result = dns_name_totext(namep, ISC_FALSE, buffer);
isc_buffer_putuint8(buffer, 0);
isc_buffer_usedregion(buffer, &r);
REGION_TO_GBUFFER(r, *gbuffer);
}
+static void
+log_cred(const gss_cred_id_t cred) {
+ OM_uint32 gret, minor, lifetime;
+ gss_name_t gname;
+ gss_buffer_desc gbuffer;
+ gss_cred_usage_t usage;
+ const char *usage_text;
+ char buf[1024];
+
+ gret = gss_inquire_cred(&minor, cred, &gname, &lifetime, &usage, NULL);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_inquire_cred: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ return;
+ }
+
+ gret = gss_display_name(&minor, gname, &gbuffer, NULL);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_display_name: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ else {
+ switch (usage) {
+ case GSS_C_BOTH:
+ usage_text = "GSS_C_BOTH";
+ break;
+ case GSS_C_INITIATE:
+ usage_text = "GSS_C_INITIATE";
+ break;
+ case GSS_C_ACCEPT:
+ usage_text = "GSS_C_ACCEPT";
+ break;
+ default:
+ usage_text = "???";
+ }
+ gss_log(3, "gss cred: \"%s\", %s, %lu", (char *)gbuffer.value,
+ usage_text, (unsigned long)lifetime);
+ }
+
+ if (gret == GSS_S_COMPLETE) {
+ if (gbuffer.length != 0) {
+ gret = gss_release_buffer(&minor, &gbuffer);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_buffer: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+ }
+
+ gret = gss_release_name(&minor, &gname);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_name: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+}
+#endif
+
isc_result_t
-dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) {
+dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
+ gss_cred_id_t *cred)
+{
+#ifdef GSSAPI
isc_buffer_t namebuf;
gss_name_t gname;
gss_buffer_desc gnamebuf;
@@ -101,164 +204,535 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) {
gss_OID_set mechs;
OM_uint32 lifetime;
gss_cred_usage_t usage;
+ char buf[1024];
REQUIRE(cred != NULL && *cred == NULL);
+ /*
+ * XXXSRA In theory we could use GSS_C_NT_HOSTBASED_SERVICE
+ * here when we're in the acceptor role, which would let us
+ * default the hostname and use a compiled in default service
+ * name of "DNS", giving one less thing to configure in
+ * named.conf. Unfortunately, this creates a circular
+ * dependency due to DNS-based realm lookup in at least one
+ * GSSAPI implementation (Heimdal). Oh well.
+ */
if (name != NULL) {
isc_buffer_init(&namebuf, array, sizeof(array));
name_to_gbuffer(name, &namebuf, &gnamebuf);
- gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID,
- &gname);
- if (gret != GSS_S_COMPLETE)
+ gret = gss_import_name(&minor, &gnamebuf,
+ GSS_C_NO_OID, &gname);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_import_name: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
return (ISC_R_FAILURE);
+ }
} else
gname = NULL;
+ /* Get the credentials. */
+ if (gname != NULL)
+ gss_log(3, "acquiring credentials for %s",
+ (char *)gnamebuf.value);
+ else {
+ /* XXXDCL does this even make any sense? */
+ gss_log(3, "acquiring credentials for ?");
+ }
+
if (initiate)
usage = GSS_C_INITIATE;
else
usage = GSS_C_ACCEPT;
gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE,
- GSS_C_NO_OID_SET, usage,
- cred, &mechs, &lifetime);
- if (gret != GSS_S_COMPLETE)
+ &mech_oid_set,
+ usage, cred, &mechs, &lifetime);
+
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed to acquire %s credentials for %s: %s",
+ initiate ? "initiate" : "accept",
+ (char *)gnamebuf.value,
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
return (ISC_R_FAILURE);
+ }
+
+ gss_log(4, "acquired %s credentials for %s",
+ initiate ? "initiate" : "accept",
+ (char *)gnamebuf.value);
+
+ log_cred(*cred);
+
return (ISC_R_SUCCESS);
+#else
+ UNUSED(name);
+ UNUSED(initiate);
+ UNUSED(cred);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm)
+{
+#ifdef GSSAPI
+ char sbuf[DNS_NAME_FORMATSIZE];
+ char nbuf[DNS_NAME_FORMATSIZE];
+ char rbuf[DNS_NAME_FORMATSIZE];
+ char *sname;
+ char *rname;
+
+ /*
+ * It is far, far easier to write the names we are looking at into
+ * a string, and do string operations on them.
+ */
+ dns_name_format(signer, sbuf, sizeof(sbuf));
+ if (name != NULL)
+ dns_name_format(name, nbuf, sizeof(nbuf));
+ dns_name_format(realm, rbuf, sizeof(rbuf));
+
+ /*
+ * Find the realm portion. This is the part after the @. If it
+ * does not exist, we don't have something we like, so we fail our
+ * compare.
+ */
+ rname = strstr(sbuf, "\\@");
+ if (rname == NULL)
+ return (isc_boolean_false);
+ *rname = '\0';
+ rname += 2;
+
+ /*
+ * Find the host portion of the signer's name. We do this by
+ * searching for the first / character. We then check to make
+ * certain the instance name is "host"
+ *
+ * This will work for
+ * host/example.com@EXAMPLE.COM
+ */
+ sname = strchr(sbuf, '/');
+ if (sname == NULL)
+ return (isc_boolean_false);
+ *sname = '\0';
+ sname++;
+ if (strcmp(sbuf, "host") != 0)
+ return (isc_boolean_false);
+
+ /*
+ * Now, we do a simple comparison between the name and the realm.
+ */
+ if (name != NULL) {
+ if ((strcasecmp(sname, nbuf) == 0)
+ && (strcmp(rname, rbuf) == 0))
+ return (isc_boolean_true);
+ } else {
+ if (strcmp(rname, rbuf) == 0)
+ return (isc_boolean_true);
+ }
+
+ return (isc_boolean_false);
+#else
+ UNUSED(signer);
+ UNUSED(name);
+ UNUSED(realm);
+ return (isc_boolean_false);
+#endif
+}
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm)
+{
+#ifdef GSSAPI
+ char sbuf[DNS_NAME_FORMATSIZE];
+ char nbuf[DNS_NAME_FORMATSIZE];
+ char rbuf[DNS_NAME_FORMATSIZE];
+ char *sname;
+ char *nname;
+ char *rname;
+
+ /*
+ * It is far, far easier to write the names we are looking at into
+ * a string, and do string operations on them.
+ */
+ dns_name_format(signer, sbuf, sizeof(sbuf));
+ if (name != NULL)
+ dns_name_format(name, nbuf, sizeof(nbuf));
+ dns_name_format(realm, rbuf, sizeof(rbuf));
+
+ /*
+ * Find the realm portion. This is the part after the @. If it
+ * does not exist, we don't have something we like, so we fail our
+ * compare.
+ */
+ rname = strstr(sbuf, "\\@");
+ if (rname == NULL)
+ return (isc_boolean_false);
+ sname = strstr(sbuf, "\\$");
+ if (sname == NULL)
+ return (isc_boolean_false);
+
+ /*
+ * Verify that the $ and @ follow one another.
+ */
+ if (rname - sname != 2)
+ return (isc_boolean_false);
+
+ /*
+ * Find the host portion of the signer's name. Zero out the $ so
+ * it terminates the signer's name, and skip past the @ for
+ * the realm.
+ *
+ * All service principals in Microsoft format seem to be in
+ * machinename$@EXAMPLE.COM
+ * format.
+ */
+ *rname = '\0';
+ rname += 2;
+ *sname = '\0';
+ sname = sbuf;
+
+ /*
+ * Find the first . in the target name, and make it the end of
+ * the string. The rest of the name has to match the realm.
+ */
+ if (name != NULL) {
+ nname = strchr(nbuf, '.');
+ if (nname == NULL)
+ return (isc_boolean_false);
+ *nname++ = '\0';
+ }
+
+ /*
+ * Now, we do a simple comparison between the name and the realm.
+ */
+ if (name != NULL) {
+ if ((strcasecmp(sname, nbuf) == 0)
+ && (strcmp(rname, rbuf) == 0)
+ && (strcasecmp(nname, rbuf) == 0))
+ return (isc_boolean_true);
+ } else {
+ if (strcmp(rname, rbuf) == 0)
+ return (isc_boolean_true);
+ }
+
+
+ return (isc_boolean_false);
+#else
+ UNUSED(signer);
+ UNUSED(name);
+ UNUSED(realm);
+ return (isc_boolean_false);
+#endif
}
isc_result_t
-dst_gssapi_initctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context)
+dst_gssapi_releasecred(gss_cred_id_t *cred) {
+#ifdef GSSAPI
+ OM_uint32 gret, minor;
+ char buf[1024];
+
+ REQUIRE(cred != NULL && *cred != NULL);
+
+ gret = gss_release_cred(&minor, cred);
+ if (gret != GSS_S_COMPLETE) {
+ /* Log the error, but still free the credential's memory */
+ gss_log(3, "failed releasing credential: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ }
+ *cred = NULL;
+
+ return(ISC_R_SUCCESS);
+#else
+ UNUSED(cred);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_result_t
+dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
+ isc_buffer_t *outtoken, gss_ctx_id_t *gssctx)
{
+#ifdef GSSAPI
isc_region_t r;
isc_buffer_t namebuf;
- gss_buffer_desc gnamebuf, gintoken, *gintokenp, gouttoken;
- OM_uint32 gret, minor, flags, ret_flags;
- gss_OID mech_type, ret_mech_type;
- OM_uint32 lifetime;
gss_name_t gname;
+ OM_uint32 gret, minor, ret_flags, flags;
+ gss_buffer_desc gintoken, *gintokenp, gouttoken = GSS_C_EMPTY_BUFFER;
isc_result_t result;
+ gss_buffer_desc gnamebuf;
unsigned char array[DNS_NAME_MAXTEXT + 1];
+ char buf[1024];
+
+ /* Client must pass us a valid gss_ctx_id_t here */
+ REQUIRE(gssctx != NULL);
isc_buffer_init(&namebuf, array, sizeof(array));
name_to_gbuffer(name, &namebuf, &gnamebuf);
+
+ /* Get the name as a GSS name */
gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
- if (gret != GSS_S_COMPLETE)
- return (ISC_R_FAILURE);
+ if (gret != GSS_S_COMPLETE) {
+ result = ISC_R_FAILURE;
+ goto out;
+ }
if (intoken != NULL) {
+ /* Don't call gss_release_buffer for gintoken! */
REGION_TO_GBUFFER(*intoken, gintoken);
gintokenp = &gintoken;
- } else
+ } else {
gintokenp = NULL;
+ }
- if (*context == NULL)
- *context = GSS_C_NO_CONTEXT;
flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG |
- GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG;
- mech_type = GSS_C_NO_OID;
-
- gret = gss_init_sec_context(&minor, cred, context, gname,
- mech_type, flags, 0,
- GSS_C_NO_CHANNEL_BINDINGS, gintokenp,
- &ret_mech_type, &gouttoken, &ret_flags,
- &lifetime);
- if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED)
- return (ISC_R_FAILURE);
+ GSS_C_SEQUENCE_FLAG | GSS_C_INTEG_FLAG;
+
+ gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx,
+ gname, GSS_SPNEGO_MECHANISM, flags,
+ 0, NULL, gintokenp,
+ NULL, &gouttoken, &ret_flags, NULL);
+
+ if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
+ gss_log(3, "Failure initiating security context");
+ gss_log(3, "%s", gss_error_tostring(gret, minor,
+ buf, sizeof(buf)));
+ result = ISC_R_FAILURE;
+ goto out;
+ }
- GBUFFER_TO_REGION(gouttoken, r);
- RETERR(isc_buffer_copyregion(outtoken, &r));
+ /*
+ * XXXSRA Not handled yet: RFC 3645 3.1.1: check ret_flags
+ * MUTUAL and INTEG flags, fail if either not set.
+ */
+
+ /*
+ * RFC 2744 states the a valid output token has a non-zero length.
+ */
+ if (gouttoken.length != 0) {
+ GBUFFER_TO_REGION(gouttoken, r);
+ RETERR(isc_buffer_copyregion(outtoken, &r));
+ (void)gss_release_buffer(&minor, &gouttoken);
+ }
+ (void)gss_release_name(&minor, &gname);
if (gret == GSS_S_COMPLETE)
- return (ISC_R_SUCCESS);
+ result = ISC_R_SUCCESS;
else
- return (DNS_R_CONTINUE);
+ result = DNS_R_CONTINUE;
out:
- return (result);
+ return (result);
+#else
+ UNUSED(name);
+ UNUSED(intoken);
+ UNUSED(outtoken);
+ UNUSED(gssctx);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
}
isc_result_t
-dst_gssapi_acceptctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context)
+dst_gssapi_acceptctx(gss_cred_id_t cred,
+ isc_region_t *intoken, isc_buffer_t **outtoken,
+ gss_ctx_id_t *ctxout, dns_name_t *principal,
+ isc_mem_t *mctx)
{
+#ifdef GSSAPI
isc_region_t r;
isc_buffer_t namebuf;
- gss_buffer_desc gnamebuf, gintoken, gouttoken;
- OM_uint32 gret, minor, flags;
- gss_OID mech_type;
- OM_uint32 lifetime;
- gss_cred_id_t delegated_cred;
- gss_name_t gname;
+ gss_buffer_desc gnamebuf = GSS_C_EMPTY_BUFFER, gintoken,
+ gouttoken = GSS_C_EMPTY_BUFFER;
+ OM_uint32 gret, minor;
+ gss_ctx_id_t context = GSS_C_NO_CONTEXT;
+ gss_name_t gname = NULL;
isc_result_t result;
- unsigned char array[DNS_NAME_MAXTEXT + 1];
+ char buf[1024];
- isc_buffer_init(&namebuf, array, sizeof(array));
- name_to_gbuffer(name, &namebuf, &gnamebuf);
- gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
- if (gret != GSS_S_COMPLETE)
- return (ISC_R_FAILURE);
+ REQUIRE(outtoken != NULL && *outtoken == NULL);
+
+ log_cred(cred);
REGION_TO_GBUFFER(*intoken, gintoken);
- if (*context == NULL)
- *context = GSS_C_NO_CONTEXT;
+ if (*ctxout == NULL)
+ context = GSS_C_NO_CONTEXT;
+ else
+ context = *ctxout;
+
+ gret = gss_accept_sec_context(&minor, &context, cred, &gintoken,
+ GSS_C_NO_CHANNEL_BINDINGS, &gname,
+ NULL, &gouttoken, NULL, NULL, NULL);
+
+ result = ISC_R_FAILURE;
+
+ switch (gret) {
+ case GSS_S_COMPLETE:
+ result = ISC_R_SUCCESS;
+ break;
+ case GSS_S_CONTINUE_NEEDED:
+ result = DNS_R_CONTINUE;
+ break;
+ case GSS_S_DEFECTIVE_TOKEN:
+ case GSS_S_DEFECTIVE_CREDENTIAL:
+ case GSS_S_BAD_SIG:
+ case GSS_S_DUPLICATE_TOKEN:
+ case GSS_S_OLD_TOKEN:
+ case GSS_S_NO_CRED:
+ case GSS_S_CREDENTIALS_EXPIRED:
+ case GSS_S_BAD_BINDINGS:
+ case GSS_S_NO_CONTEXT:
+ case GSS_S_BAD_MECH:
+ case GSS_S_FAILURE:
+ result = DNS_R_INVALIDTKEY;
+ /* fall through */
+ default:
+ gss_log(3, "failed gss_accept_sec_context: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ return (result);
+ }
- gret = gss_accept_sec_context(&minor, context, cred, &gintoken,
- GSS_C_NO_CHANNEL_BINDINGS, gname,
- &mech_type, &gouttoken, &flags,
- &lifetime, &delegated_cred);
- if (gret != GSS_S_COMPLETE)
- return (ISC_R_FAILURE);
+ if (gouttoken.length > 0) {
+ RETERR(isc_buffer_allocate(mctx, outtoken, gouttoken.length));
+ GBUFFER_TO_REGION(gouttoken, r);
+ RETERR(isc_buffer_copyregion(*outtoken, &r));
+ (void)gss_release_buffer(&minor, &gouttoken);
+ }
- GBUFFER_TO_REGION(gouttoken, r);
- RETERR(isc_buffer_copyregion(outtoken, &r));
+ if (gret == GSS_S_COMPLETE) {
+ gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_display_name: %s",
+ gss_error_tostring(gret, minor,
+ buf, sizeof(buf)));
+ RETERR(ISC_R_FAILURE);
+ }
+
+ /*
+ * Compensate for a bug in Solaris8's implementation
+ * of gss_display_name(). Should be harmless in any
+ * case, since principal names really should not
+ * contain null characters.
+ */
+ if (gnamebuf.length > 0 &&
+ ((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
+ gnamebuf.length--;
+
+ gss_log(3, "gss-api source name (accept) is %.*s",
+ (int)gnamebuf.length, (char *)gnamebuf.value);
+
+ GBUFFER_TO_REGION(gnamebuf, r);
+ isc_buffer_init(&namebuf, r.base, r.length);
+ isc_buffer_add(&namebuf, r.length);
+
+ RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname,
+ ISC_FALSE, NULL));
+
+ if (gnamebuf.length != 0) {
+ gret = gss_release_buffer(&minor, &gnamebuf);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_buffer: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+ }
- return (ISC_R_SUCCESS);
+ *ctxout = context;
out:
- return (result);
-}
+ if (gname != NULL) {
+ gret = gss_release_name(&minor, &gname);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_name: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+ return (result);
#else
-
-isc_result_t
-dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred) {
- UNUSED(name);
- UNUSED(initiate);
- UNUSED(cred);
- return (ISC_R_NOTIMPLEMENTED);
-}
-
-isc_result_t
-dst_gssapi_initctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context)
-{
- UNUSED(name);
UNUSED(cred);
UNUSED(intoken);
UNUSED(outtoken);
- UNUSED(context);
+ UNUSED(ctxout);
+ UNUSED(principal);
+ UNUSED(mctx);
+
return (ISC_R_NOTIMPLEMENTED);
+#endif
}
isc_result_t
-dst_gssapi_acceptctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context)
+dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx)
{
- UNUSED(name);
- UNUSED(cred);
- UNUSED(intoken);
- UNUSED(outtoken);
- UNUSED(context);
+#ifdef GSSAPI
+ OM_uint32 gret, minor;
+ char buf[1024];
+
+ UNUSED(mctx);
+
+ REQUIRE(gssctx != NULL && *gssctx != NULL);
+
+ /* Delete the context from the GSS provider */
+ gret = gss_delete_sec_context(&minor, gssctx, GSS_C_NO_BUFFER);
+ if (gret != GSS_S_COMPLETE) {
+ /* Log the error, but still free the context's memory */
+ gss_log(3, "Failure deleting security context %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ }
+ return(ISC_R_SUCCESS);
+#else
+ UNUSED(mctx);
+ UNUSED(gssctx);
return (ISC_R_NOTIMPLEMENTED);
+#endif
}
+char *
+gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
+ char *buf, size_t buflen) {
+#ifdef GSSAPI
+ gss_buffer_desc msg_minor = GSS_C_EMPTY_BUFFER,
+ msg_major = GSS_C_EMPTY_BUFFER;
+ OM_uint32 msg_ctx, minor_stat;
+
+ /* Handle major status */
+ msg_ctx = 0;
+ (void)gss_display_status(&minor_stat, major, GSS_C_GSS_CODE,
+ GSS_C_NULL_OID, &msg_ctx, &msg_major);
+
+ /* Handle minor status */
+ msg_ctx = 0;
+ (void)gss_display_status(&minor_stat, minor, GSS_C_MECH_CODE,
+ GSS_C_NULL_OID, &msg_ctx, &msg_minor);
+
+ snprintf(buf, buflen, "GSSAPI error: Major = %s, Minor = %s.",
+ (char *)msg_major.value, (char *)msg_minor.value);
+
+ if (msg_major.length != 0)
+ (void)gss_release_buffer(&minor_stat, &msg_major);
+ if (msg_minor.length != 0)
+ (void)gss_release_buffer(&minor_stat, &msg_minor);
+ return(buf);
+#else
+ snprintf(buf, buflen, "GSSAPI error: Major = %u, Minor = %u.",
+ major, minor);
+
+ return (buf);
#endif
+}
+
+void
+gss_log(int level, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_TKEY, ISC_LOG_DEBUG(level), fmt, ap);
+ va_end(ap);
+}
/*! \file */
diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c
index 9655c89..fce98d7 100644
--- a/lib/dns/hmac_link.c
+++ b/lib/dns/hmac_link.c
@@ -1,9 +1,22 @@
/*
- * Portions Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-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 AND NETWORK ASSOCIATES 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.
+ *
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: hmac_link.c,v 1.1.6.5 2006/01/27 23:57:44 marka Exp $
+ * $Id: hmac_link.c,v 1.11 2008/04/01 23:47:10 tbox Exp $
*/
#include <config.h>
@@ -43,9 +56,9 @@
static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct hmackey {
+struct dst_hmacmd5_key {
unsigned char key[HMAC_LEN];
-} HMAC_Key;
+};
static isc_result_t
getkeybits(dst_key_t *key, struct dst_private_element *element) {
@@ -61,30 +74,30 @@ getkeybits(dst_key_t *key, struct dst_private_element *element) {
static isc_result_t
hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacmd5_t *hmacmd5ctx;
- HMAC_Key *hkey = key->opaque;
+ dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
if (hmacmd5ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacmd5_init(hmacmd5ctx, hkey->key, HMAC_LEN);
- dctx->opaque = hmacmd5ctx;
+ dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
return (ISC_R_SUCCESS);
}
static void
hmacmd5_destroyctx(dst_context_t *dctx) {
- isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
if (hmacmd5ctx != NULL) {
isc_hmacmd5_invalidate(hmacmd5ctx);
isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacmd5ctx = NULL;
}
}
static isc_result_t
hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
return (ISC_R_SUCCESS);
@@ -92,7 +105,7 @@ hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
static isc_result_t
hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
@@ -106,7 +119,7 @@ hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
static isc_result_t
hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacmd5_t *hmacmd5ctx = dctx->opaque;
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
if (sig->length > ISC_MD5_DIGESTLENGTH)
return (DST_R_VERIFYFAILURE);
@@ -119,10 +132,10 @@ hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
static isc_boolean_t
hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMAC_Key *hkey1, *hkey2;
+ dst_hmacmd5_key_t *hkey1, *hkey2;
- hkey1 = (HMAC_Key *)key1->opaque;
- hkey2 = (HMAC_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacmd5;
+ hkey2 = key2->keydata.hmacmd5;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
@@ -170,20 +183,20 @@ hmacmd5_isprivate(const dst_key_t *key) {
static void
hmacmd5_destroy(dst_key_t *key) {
- HMAC_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMAC_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMAC_Key));
- key->opaque = NULL;
+ dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
+ memset(hkey, 0, sizeof(dst_hmacmd5_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacmd5_key_t));
+ key->keydata.hmacmd5 = NULL;
}
static isc_result_t
hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMAC_Key *hkey;
+ dst_hmacmd5_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacmd5 != NULL);
- hkey = (HMAC_Key *) key->opaque;
+ hkey = key->keydata.hmacmd5;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
@@ -195,7 +208,7 @@ hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMAC_Key *hkey;
+ dst_hmacmd5_key_t *hkey;
int keylen;
isc_region_t r;
isc_md5_t md5ctx;
@@ -204,7 +217,7 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMAC_Key *) isc_mem_get(key->mctx, sizeof(HMAC_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
@@ -222,7 +235,7 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacmd5 = hkey;
return (ISC_R_SUCCESS);
}
@@ -230,15 +243,15 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacmd5_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMAC_Key *hkey;
+ dst_hmacmd5_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacmd5 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMAC_Key *) key->opaque;
+ hkey = key->keydata.hmacmd5;
priv.elements[cnt].tag = TAG_HMACMD5_KEY;
priv.elements[cnt].length = bytes;
@@ -272,7 +285,7 @@ hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer) {
switch (priv.elements[i].tag) {
case TAG_HMACMD5_KEY:
isc_buffer_init(&b, priv.elements[i].data,
- priv.elements[i].length);
+ priv.elements[i].length);
isc_buffer_add(&b, priv.elements[i].length);
tresult = hmacmd5_fromdns(key, &b);
if (tresult != ISC_R_SUCCESS)
@@ -310,6 +323,7 @@ static dst_func_t hmacmd5_functions = {
hmacmd5_tofile,
hmacmd5_parse,
NULL, /*%< cleanup */
+ NULL, /*%< fromlabel */
};
isc_result_t
@@ -322,37 +336,37 @@ dst__hmacmd5_init(dst_func_t **funcp) {
static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha1_key {
unsigned char key[ISC_SHA1_DIGESTLENGTH];
-} HMACSHA1_Key;
+};
static isc_result_t
hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha1_t *hmacsha1ctx;
- HMACSHA1_Key *hkey = key->opaque;
+ dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
if (hmacsha1ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_DIGESTLENGTH);
- dctx->opaque = hmacsha1ctx;
+ dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha1_destroyctx(dst_context_t *dctx) {
- isc_hmacsha1_t *hmacsha1ctx = dctx->opaque;
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
if (hmacsha1ctx != NULL) {
isc_hmacsha1_invalidate(hmacsha1ctx);
isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha1ctx = NULL;
}
}
static isc_result_t
hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha1_t *hmacsha1ctx = dctx->opaque;
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
return (ISC_R_SUCCESS);
@@ -360,7 +374,7 @@ hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
static isc_result_t
hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha1_t *hmacsha1ctx = dctx->opaque;
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
@@ -374,7 +388,7 @@ hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
static isc_result_t
hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha1_t *hmacsha1ctx = dctx->opaque;
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
@@ -387,10 +401,10 @@ hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
static isc_boolean_t
hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA1_Key *hkey1, *hkey2;
+ dst_hmacsha1_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA1_Key *)key1->opaque;
- hkey2 = (HMACSHA1_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha1;
+ hkey2 = key2->keydata.hmacsha1;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
@@ -438,20 +452,20 @@ hmacsha1_isprivate(const dst_key_t *key) {
static void
hmacsha1_destroy(dst_key_t *key) {
- HMACSHA1_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA1_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA1_Key));
- key->opaque = NULL;
+ dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
+ memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
+ key->keydata.hmacsha1 = NULL;
}
static isc_result_t
hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA1_Key *hkey;
+ dst_hmacsha1_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha1 != NULL);
- hkey = (HMACSHA1_Key *) key->opaque;
+ hkey = key->keydata.hmacsha1;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
@@ -463,7 +477,7 @@ hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA1_Key *hkey;
+ dst_hmacsha1_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha1_t sha1ctx;
@@ -472,7 +486,7 @@ hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA1_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA1_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
@@ -490,7 +504,7 @@ hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha1 = hkey;
return (ISC_R_SUCCESS);
}
@@ -498,15 +512,15 @@ hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha1_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA1_Key *hkey;
+ dst_hmacsha1_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha1 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA1_Key *) key->opaque;
+ hkey = key->keydata.hmacsha1;
priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
priv.elements[cnt].length = bytes;
@@ -541,7 +555,7 @@ hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer) {
switch (priv.elements[i].tag) {
case TAG_HMACSHA1_KEY:
isc_buffer_init(&b, priv.elements[i].data,
- priv.elements[i].length);
+ priv.elements[i].length);
isc_buffer_add(&b, priv.elements[i].length);
tresult = hmacsha1_fromdns(key, &b);
if (tresult != ISC_R_SUCCESS)
@@ -579,6 +593,7 @@ static dst_func_t hmacsha1_functions = {
hmacsha1_tofile,
hmacsha1_parse,
NULL, /* cleanup */
+ NULL, /* fromlabel */
};
isc_result_t
@@ -591,37 +606,37 @@ dst__hmacsha1_init(dst_func_t **funcp) {
static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha224_key {
unsigned char key[ISC_SHA224_DIGESTLENGTH];
-} HMACSHA224_Key;
+};
static isc_result_t
hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha224_t *hmacsha224ctx;
- HMACSHA224_Key *hkey = key->opaque;
+ dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
if (hmacsha224ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_DIGESTLENGTH);
- dctx->opaque = hmacsha224ctx;
+ dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha224_destroyctx(dst_context_t *dctx) {
- isc_hmacsha224_t *hmacsha224ctx = dctx->opaque;
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
if (hmacsha224ctx != NULL) {
isc_hmacsha224_invalidate(hmacsha224ctx);
isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha224ctx = NULL;
}
}
static isc_result_t
hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha224_t *hmacsha224ctx = dctx->opaque;
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
return (ISC_R_SUCCESS);
@@ -629,7 +644,7 @@ hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
static isc_result_t
hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha224_t *hmacsha224ctx = dctx->opaque;
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
@@ -643,7 +658,7 @@ hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
static isc_result_t
hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha224_t *hmacsha224ctx = dctx->opaque;
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
@@ -656,10 +671,10 @@ hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
static isc_boolean_t
hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA224_Key *hkey1, *hkey2;
+ dst_hmacsha224_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA224_Key *)key1->opaque;
- hkey2 = (HMACSHA224_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha224;
+ hkey2 = key2->keydata.hmacsha224;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
@@ -707,20 +722,20 @@ hmacsha224_isprivate(const dst_key_t *key) {
static void
hmacsha224_destroy(dst_key_t *key) {
- HMACSHA224_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA224_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA224_Key));
- key->opaque = NULL;
+ dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
+ memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
+ key->keydata.hmacsha224 = NULL;
}
static isc_result_t
hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA224_Key *hkey;
+ dst_hmacsha224_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha224 != NULL);
- hkey = (HMACSHA224_Key *) key->opaque;
+ hkey = key->keydata.hmacsha224;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
@@ -732,7 +747,7 @@ hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA224_Key *hkey;
+ dst_hmacsha224_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha224_t sha224ctx;
@@ -741,7 +756,7 @@ hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA224_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA224_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
@@ -759,7 +774,7 @@ hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha224 = hkey;
return (ISC_R_SUCCESS);
}
@@ -767,15 +782,15 @@ hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha224_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA224_Key *hkey;
+ dst_hmacsha224_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha224 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA224_Key *) key->opaque;
+ hkey = key->keydata.hmacsha224;
priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
priv.elements[cnt].length = bytes;
@@ -810,7 +825,7 @@ hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer) {
switch (priv.elements[i].tag) {
case TAG_HMACSHA224_KEY:
isc_buffer_init(&b, priv.elements[i].data,
- priv.elements[i].length);
+ priv.elements[i].length);
isc_buffer_add(&b, priv.elements[i].length);
tresult = hmacsha224_fromdns(key, &b);
if (tresult != ISC_R_SUCCESS)
@@ -848,6 +863,7 @@ static dst_func_t hmacsha224_functions = {
hmacsha224_tofile,
hmacsha224_parse,
NULL, /* cleanup */
+ NULL, /* fromlabel */
};
isc_result_t
@@ -860,37 +876,37 @@ dst__hmacsha224_init(dst_func_t **funcp) {
static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha256_key {
unsigned char key[ISC_SHA256_DIGESTLENGTH];
-} HMACSHA256_Key;
+};
static isc_result_t
hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha256_t *hmacsha256ctx;
- HMACSHA256_Key *hkey = key->opaque;
+ dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
if (hmacsha256ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_DIGESTLENGTH);
- dctx->opaque = hmacsha256ctx;
+ dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha256_destroyctx(dst_context_t *dctx) {
- isc_hmacsha256_t *hmacsha256ctx = dctx->opaque;
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
if (hmacsha256ctx != NULL) {
isc_hmacsha256_invalidate(hmacsha256ctx);
isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha256ctx = NULL;
}
}
static isc_result_t
hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha256_t *hmacsha256ctx = dctx->opaque;
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
return (ISC_R_SUCCESS);
@@ -898,7 +914,7 @@ hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
static isc_result_t
hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha256_t *hmacsha256ctx = dctx->opaque;
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
@@ -912,7 +928,7 @@ hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
static isc_result_t
hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha256_t *hmacsha256ctx = dctx->opaque;
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
@@ -925,10 +941,10 @@ hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
static isc_boolean_t
hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA256_Key *hkey1, *hkey2;
+ dst_hmacsha256_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA256_Key *)key1->opaque;
- hkey2 = (HMACSHA256_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha256;
+ hkey2 = key2->keydata.hmacsha256;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
@@ -976,20 +992,20 @@ hmacsha256_isprivate(const dst_key_t *key) {
static void
hmacsha256_destroy(dst_key_t *key) {
- HMACSHA256_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA256_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA256_Key));
- key->opaque = NULL;
+ dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
+ memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
+ key->keydata.hmacsha256 = NULL;
}
static isc_result_t
hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA256_Key *hkey;
+ dst_hmacsha256_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha256 != NULL);
- hkey = (HMACSHA256_Key *) key->opaque;
+ hkey = key->keydata.hmacsha256;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
@@ -1001,7 +1017,7 @@ hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA256_Key *hkey;
+ dst_hmacsha256_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha256_t sha256ctx;
@@ -1010,7 +1026,7 @@ hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA256_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA256_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
@@ -1028,7 +1044,7 @@ hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha256 = hkey;
return (ISC_R_SUCCESS);
}
@@ -1036,15 +1052,15 @@ hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha256_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA256_Key *hkey;
+ dst_hmacsha256_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha256 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA256_Key *) key->opaque;
+ hkey = key->keydata.hmacsha256;
priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
priv.elements[cnt].length = bytes;
@@ -1079,7 +1095,7 @@ hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer) {
switch (priv.elements[i].tag) {
case TAG_HMACSHA256_KEY:
isc_buffer_init(&b, priv.elements[i].data,
- priv.elements[i].length);
+ priv.elements[i].length);
isc_buffer_add(&b, priv.elements[i].length);
tresult = hmacsha256_fromdns(key, &b);
if (tresult != ISC_R_SUCCESS)
@@ -1117,6 +1133,7 @@ static dst_func_t hmacsha256_functions = {
hmacsha256_tofile,
hmacsha256_parse,
NULL, /* cleanup */
+ NULL, /* fromlabel */
};
isc_result_t
@@ -1129,37 +1146,37 @@ dst__hmacsha256_init(dst_func_t **funcp) {
static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha384_key {
unsigned char key[ISC_SHA384_DIGESTLENGTH];
-} HMACSHA384_Key;
+};
static isc_result_t
hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha384_t *hmacsha384ctx;
- HMACSHA384_Key *hkey = key->opaque;
+ dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
if (hmacsha384ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_DIGESTLENGTH);
- dctx->opaque = hmacsha384ctx;
+ dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha384_destroyctx(dst_context_t *dctx) {
- isc_hmacsha384_t *hmacsha384ctx = dctx->opaque;
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
if (hmacsha384ctx != NULL) {
isc_hmacsha384_invalidate(hmacsha384ctx);
isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha384ctx = NULL;
}
}
static isc_result_t
hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha384_t *hmacsha384ctx = dctx->opaque;
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
return (ISC_R_SUCCESS);
@@ -1167,7 +1184,7 @@ hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
static isc_result_t
hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha384_t *hmacsha384ctx = dctx->opaque;
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
@@ -1181,7 +1198,7 @@ hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
static isc_result_t
hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha384_t *hmacsha384ctx = dctx->opaque;
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
@@ -1194,10 +1211,10 @@ hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
static isc_boolean_t
hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA384_Key *hkey1, *hkey2;
+ dst_hmacsha384_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA384_Key *)key1->opaque;
- hkey2 = (HMACSHA384_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha384;
+ hkey2 = key2->keydata.hmacsha384;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
@@ -1245,20 +1262,20 @@ hmacsha384_isprivate(const dst_key_t *key) {
static void
hmacsha384_destroy(dst_key_t *key) {
- HMACSHA384_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA384_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA384_Key));
- key->opaque = NULL;
+ dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
+ memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
+ key->keydata.hmacsha384 = NULL;
}
static isc_result_t
hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA384_Key *hkey;
+ dst_hmacsha384_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha384 != NULL);
- hkey = (HMACSHA384_Key *) key->opaque;
+ hkey = key->keydata.hmacsha384;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
@@ -1270,7 +1287,7 @@ hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA384_Key *hkey;
+ dst_hmacsha384_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha384_t sha384ctx;
@@ -1279,7 +1296,7 @@ hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA384_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA384_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
@@ -1297,7 +1314,7 @@ hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha384 = hkey;
return (ISC_R_SUCCESS);
}
@@ -1305,15 +1322,15 @@ hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha384_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA384_Key *hkey;
+ dst_hmacsha384_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha384 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA384_Key *) key->opaque;
+ hkey = key->keydata.hmacsha384;
priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
priv.elements[cnt].length = bytes;
@@ -1348,7 +1365,7 @@ hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer) {
switch (priv.elements[i].tag) {
case TAG_HMACSHA384_KEY:
isc_buffer_init(&b, priv.elements[i].data,
- priv.elements[i].length);
+ priv.elements[i].length);
isc_buffer_add(&b, priv.elements[i].length);
tresult = hmacsha384_fromdns(key, &b);
if (tresult != ISC_R_SUCCESS)
@@ -1386,6 +1403,7 @@ static dst_func_t hmacsha384_functions = {
hmacsha384_tofile,
hmacsha384_parse,
NULL, /* cleanup */
+ NULL, /* fromlabel */
};
isc_result_t
@@ -1398,37 +1416,37 @@ dst__hmacsha384_init(dst_func_t **funcp) {
static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
-typedef struct {
+struct dst_hmacsha512_key {
unsigned char key[ISC_SHA512_DIGESTLENGTH];
-} HMACSHA512_Key;
+};
static isc_result_t
hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
isc_hmacsha512_t *hmacsha512ctx;
- HMACSHA512_Key *hkey = key->opaque;
+ dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
if (hmacsha512ctx == NULL)
return (ISC_R_NOMEMORY);
isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_DIGESTLENGTH);
- dctx->opaque = hmacsha512ctx;
+ dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
return (ISC_R_SUCCESS);
}
static void
hmacsha512_destroyctx(dst_context_t *dctx) {
- isc_hmacsha512_t *hmacsha512ctx = dctx->opaque;
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
if (hmacsha512ctx != NULL) {
isc_hmacsha512_invalidate(hmacsha512ctx);
isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.hmacsha512ctx = NULL;
}
}
static isc_result_t
hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_hmacsha512_t *hmacsha512ctx = dctx->opaque;
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
return (ISC_R_SUCCESS);
@@ -1436,7 +1454,7 @@ hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
static isc_result_t
hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_hmacsha512_t *hmacsha512ctx = dctx->opaque;
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
unsigned char *digest;
if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
@@ -1450,7 +1468,7 @@ hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
static isc_result_t
hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_hmacsha512_t *hmacsha512ctx = dctx->opaque;
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
return (DST_R_VERIFYFAILURE);
@@ -1463,10 +1481,10 @@ hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
static isc_boolean_t
hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
- HMACSHA512_Key *hkey1, *hkey2;
+ dst_hmacsha512_key_t *hkey1, *hkey2;
- hkey1 = (HMACSHA512_Key *)key1->opaque;
- hkey2 = (HMACSHA512_Key *)key2->opaque;
+ hkey1 = key1->keydata.hmacsha512;
+ hkey2 = key2->keydata.hmacsha512;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
@@ -1514,20 +1532,20 @@ hmacsha512_isprivate(const dst_key_t *key) {
static void
hmacsha512_destroy(dst_key_t *key) {
- HMACSHA512_Key *hkey = key->opaque;
- memset(hkey, 0, sizeof(HMACSHA512_Key));
- isc_mem_put(key->mctx, hkey, sizeof(HMACSHA512_Key));
- key->opaque = NULL;
+ dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
+ memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
+ isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
+ key->keydata.hmacsha512 = NULL;
}
static isc_result_t
hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
- HMACSHA512_Key *hkey;
+ dst_hmacsha512_key_t *hkey;
unsigned int bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.hmacsha512 != NULL);
- hkey = (HMACSHA512_Key *) key->opaque;
+ hkey = key->keydata.hmacsha512;
bytes = (key->key_size + 7) / 8;
if (isc_buffer_availablelength(data) < bytes)
@@ -1539,7 +1557,7 @@ hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
- HMACSHA512_Key *hkey;
+ dst_hmacsha512_key_t *hkey;
int keylen;
isc_region_t r;
isc_sha512_t sha512ctx;
@@ -1548,7 +1566,7 @@ hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
if (r.length == 0)
return (ISC_R_SUCCESS);
- hkey = (HMACSHA512_Key *) isc_mem_get(key->mctx, sizeof(HMACSHA512_Key));
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
if (hkey == NULL)
return (ISC_R_NOMEMORY);
@@ -1566,7 +1584,7 @@ hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
}
key->key_size = keylen * 8;
- key->opaque = hkey;
+ key->keydata.hmacsha512 = hkey;
return (ISC_R_SUCCESS);
}
@@ -1574,15 +1592,15 @@ hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
static isc_result_t
hmacsha512_tofile(const dst_key_t *key, const char *directory) {
int cnt = 0;
- HMACSHA512_Key *hkey;
+ dst_hmacsha512_key_t *hkey;
dst_private_t priv;
int bytes = (key->key_size + 7) / 8;
unsigned char buf[2];
- if (key->opaque == NULL)
+ if (key->keydata.hmacsha512 == NULL)
return (DST_R_NULLKEY);
- hkey = (HMACSHA512_Key *) key->opaque;
+ hkey = key->keydata.hmacsha512;
priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
priv.elements[cnt].length = bytes;
@@ -1617,7 +1635,7 @@ hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer) {
switch (priv.elements[i].tag) {
case TAG_HMACSHA512_KEY:
isc_buffer_init(&b, priv.elements[i].data,
- priv.elements[i].length);
+ priv.elements[i].length);
isc_buffer_add(&b, priv.elements[i].length);
tresult = hmacsha512_fromdns(key, &b);
if (tresult != ISC_R_SUCCESS)
@@ -1655,6 +1673,7 @@ static dst_func_t hmacsha512_functions = {
hmacsha512_tofile,
hmacsha512_parse,
NULL, /* cleanup */
+ NULL, /* fromlabel */
};
isc_result_t
diff --git a/lib/dns/include/Makefile.in b/lib/dns/include/Makefile.in
index 593ad5a..b52cb98 100644
--- a/lib/dns/include/Makefile.in
+++ b/lib/dns/include/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.12.18.1 2004/12/09 04:41:46 marka Exp $
+# $Id: Makefile.in,v 1.15 2007/06/19 23:47:16 tbox Exp $
srcdir = @srcdir@
VPATH = @srcdir@
diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in
index 3f367bc..e9e049e 100644
--- a/lib/dns/include/dns/Makefile.in
+++ b/lib/dns/include/dns/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2003 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.50 2004/03/05 05:09:40 marka Exp $
+# $Id: Makefile.in,v 1.55 2008/11/14 23:47:33 tbox Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -23,14 +23,14 @@ top_srcdir = @top_srcdir@
HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h \
cert.h compress.h \
- db.h dbiterator.h dbtable.h diff.h dispatch.h \
- dnssec.h ds.h events.h fixedname.h journal.h keyflags.h \
+ db.h dbiterator.h dbtable.h diff.h dispatch.h dlz.h \
+ dnssec.h ds.h events.h fixedname.h iptable.h journal.h keyflags.h \
keytable.h keyvalues.h lib.h log.h master.h masterdump.h \
message.h name.h ncache.h \
nsec.h peer.h portlist.h rbt.h rcode.h \
rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \
rdataslab.h rdatatype.h request.h resolver.h result.h \
- rootns.h sdb.h secalg.h secproto.h soa.h ssu.h \
+ rootns.h sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h \
tcpmsg.h time.h tkey.h \
tsig.h ttl.h types.h validator.h version.h view.h xfrin.h \
zone.h zonekey.h zt.h
diff --git a/lib/dns/include/dns/acache.h b/lib/dns/include/dns/acache.h
index 50d7fc1..28990c2 100644
--- a/lib/dns/include/dns/acache.h
+++ b/lib/dns/include/dns/acache.h
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acache.h,v 1.3.2.4 2006/05/03 00:07:49 marka Exp $ */
+/* $Id: acache.h,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_ACACHE_H
#define DNS_ACACHE_H 1
diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h
index 34e394f..721fe51 100644
--- a/lib/dns/include/dns/acl.h
+++ b/lib/dns/include/dns/acl.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acl.h,v 1.22.18.4 2006/03/02 00:37:21 marka Exp $ */
+/* $Id: acl.h,v 1.31.206.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_ACL_H
#define DNS_ACL_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/acl.h
* \brief
* Address match list handling.
*/
@@ -40,6 +40,7 @@
#include <dns/name.h>
#include <dns/types.h>
+#include <dns/iptable.h>
/***
*** Types
@@ -62,20 +63,21 @@ struct dns_aclipprefix {
};
struct dns_aclelement {
- dns_aclelemettype_t type;
- isc_boolean_t negative;
- union {
- dns_aclipprefix_t ip_prefix;
- dns_name_t keyname;
- dns_acl_t *nestedacl;
- } u;
+ dns_aclelemettype_t type;
+ isc_boolean_t negative;
+ dns_name_t keyname;
+ dns_acl_t *nestedacl;
+ int node_num;
};
struct dns_acl {
unsigned int magic;
isc_mem_t *mctx;
isc_refcount_t refcount;
+ dns_iptable_t *iptable;
+#define node_count iptable->radix->num_added_node
dns_aclelement_t *elements;
+ isc_boolean_t has_negatives;
unsigned int alloc; /*%< Elements allocated */
unsigned int length; /*%< Elements initialized */
char *name; /*%< Temporary use only */
@@ -100,14 +102,9 @@ ISC_LANG_BEGINDECLS
isc_result_t
dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target);
/*%<
- * Create a new ACL with room for 'n' elements.
- * The elements are uninitialized and the length is 0.
- */
-
-isc_result_t
-dns_acl_appendelement(dns_acl_t *acl, const dns_aclelement_t *elt);
-/*%<
- * Append an element to an existing ACL.
+ * Create a new ACL, including an IP table and an array with room
+ * for 'n' ACL elements. The elements are uninitialized and the
+ * length is 0.
*/
isc_result_t
@@ -122,6 +119,30 @@ dns_acl_none(isc_mem_t *mctx, dns_acl_t **target);
* Create a new ACL that matches nothing.
*/
+isc_boolean_t
+dns_acl_isany(dns_acl_t *acl);
+/*%<
+ * Test whether ACL is set to "{ any; }"
+ */
+
+isc_boolean_t
+dns_acl_isnone(dns_acl_t *acl);
+/*%<
+ * Test whether ACL is set to "{ none; }"
+ */
+
+isc_result_t
+dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos);
+/*%<
+ * Merge the contents of one ACL into another. Call dns_iptable_merge()
+ * for the IP tables, then concatenate the element arrays.
+ *
+ * If pos is set to false, then the nested ACL is to be negated. This
+ * means reverse the sense of each *positive* element or IP table node,
+ * but leave negatives alone, so as to prevent a double-negative causing
+ * an unexpected positive match in the parent ACL.
+ */
+
void
dns_acl_attach(dns_acl_t *source, dns_acl_t **target);
@@ -129,17 +150,11 @@ void
dns_acl_detach(dns_acl_t **aclp);
isc_boolean_t
-dns_aclelement_equal(const dns_aclelement_t *ea, const dns_aclelement_t *eb);
-
-isc_boolean_t
-dns_acl_equal(const dns_acl_t *a, const dns_acl_t *b);
-
-isc_boolean_t
dns_acl_isinsecure(const dns_acl_t *a);
/*%<
* Return #ISC_TRUE iff the acl 'a' is considered insecure, that is,
* if it contains IP addresses other than those of the local host.
- * This is intended for applications such as printing warning
+ * This is intended for applications such as printing warning
* messages for suspect ACLs; it is not intended for making access
* control decisions. We make no guarantee that an ACL for which
* this function returns #ISC_FALSE is safe.
@@ -147,6 +162,9 @@ dns_acl_isinsecure(const dns_acl_t *a);
isc_result_t
dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env);
+/*%<
+ * Initialize ACL environment, setting up localhost and localnets ACLs
+ */
void
dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s);
@@ -168,19 +186,17 @@ dns_acl_match(const isc_netaddr_t *reqaddr,
* Match the address 'reqaddr', and optionally the key name 'reqsigner',
* against 'acl'. 'reqsigner' may be NULL.
*
- * If there is a positive match, '*match' will be set to a positive value
- * indicating the distance from the beginning of the list.
- *
- * If there is a negative match, '*match' will be set to a negative value
- * whose absolute value indicates the distance from the beginning of
- * the list.
- *
- * If there is a match (either positive or negative) and 'matchelt' is
- * non-NULL, *matchelt will be attached to the primitive
- * (non-indirect) address match list element that matched.
+ * If there is a match, '*match' will be set to an integer whose absolute
+ * value corresponds to the order in which the matching value was inserted
+ * into the ACL. For a positive match, this value will be positive; for a
+ * negative match, it will be negative.
*
* If there is no match, *match will be set to zero.
*
+ * If there is a match in the element list (either positive or negative)
+ * and 'matchelt' is non-NULL, *matchelt will be pointed to the matching
+ * element.
+ *
* Returns:
*\li #ISC_R_SUCCESS Always succeeds.
*/
@@ -189,34 +205,18 @@ isc_boolean_t
dns_aclelement_match(const isc_netaddr_t *reqaddr,
const dns_name_t *reqsigner,
const dns_aclelement_t *e,
- const dns_aclenv_t *env,
+ const dns_aclenv_t *env,
const dns_aclelement_t **matchelt);
/*%<
* Like dns_acl_match, but matches against the single ACL element 'e'
- * rather than a complete list and returns ISC_TRUE iff it matched.
- * To determine whether the match was prositive or negative, the
+ * rather than a complete ACL, and returns ISC_TRUE iff it matched.
+ *
+ * To determine whether the match was positive or negative, the
* caller should examine e->negative. Since the element 'e' may be
- * a reference to a named ACL or a nested ACL, the matching element
+ * a reference to a named ACL or a nested ACL, a matching element
* returned through 'matchelt' is not necessarily 'e' itself.
*/
-isc_result_t
-dns_acl_elementmatch(const dns_acl_t *acl,
- const dns_aclelement_t *elt,
- const dns_aclelement_t **matchelt);
-/*%<
- * Search for an ACL element in 'acl' which is exactly the same as 'elt'.
- * If there is one, and 'matchelt' is non NULL, then '*matchelt' will point
- * to the entry.
- *
- * This function is intended to be used for avoiding duplicated ACL entries
- * before adding an entry.
- *
- * Returns:
- *\li #ISC_R_SUCCESS Match succeeds.
- *\li #ISC_R_NOTFOUND Match fails.
- */
-
ISC_LANG_ENDDECLS
#endif /* DNS_ACL_H */
diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h
index 1e3cd61..d4ac40c 100644
--- a/lib/dns/include/dns/adb.h
+++ b/lib/dns/include/dns/adb.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.h,v 1.76.18.3 2005/06/23 04:23:16 marka Exp $ */
+/* $Id: adb.h,v 1.85 2008/04/03 06:09:04 tbox Exp $ */
#ifndef DNS_ADB_H
#define DNS_ADB_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/adb.h
*\brief
* DNS Address Database
*
@@ -99,7 +99,7 @@ ISC_LANG_BEGINDECLS
typedef struct dns_adbname dns_adbname_t;
-/*!
+/*!
*\brief
* Represents a lookup for a single name.
*
@@ -220,7 +220,7 @@ struct dns_adbaddrinfo {
ISC_LINK(dns_adbaddrinfo_t) publink;
};
-/*!<
+/*!<
* The event sent to the caller task is just a plain old isc_event_t. It
* contains no data other than a simple status, passed in the "type" field
* to indicate that another address resolved, or all partially resolved
@@ -345,7 +345,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
*
* If no events will be generated, the *find->result_v4 and/or result_v6
* members may be examined for address lookup status. The usual #ISC_R_SUCCESS,
- * #ISC_R_FAILURE, and #DNS_R_NX{DOMAIN,RRSET} are returned, along with
+ * #ISC_R_FAILURE, #DNS_R_NXDOMAIN, and #DNS_R_NXRRSET are returned, along with
* #ISC_R_NOTFOUND meaning the ADB has not _yet_ found the values. In this
* latter case, retrying may produce more addresses.
*
@@ -520,7 +520,7 @@ void
dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
unsigned int rtt, unsigned int factor);
/*%<
- * Mix the round trip time into the existing smoothed rtt.
+ * Mix the round trip time into the existing smoothed rtt.
* The formula used
* (where srtt is the existing rtt value, and rtt and factor are arguments to
@@ -623,13 +623,12 @@ void
dns_adb_flushname(dns_adb_t *adb, dns_name_t *name);
/*%<
* Flush 'name' from the adb cache.
- *
+ *
* Requires:
*\li 'adb' is valid.
*\li 'name' is valid.
*/
-
ISC_LANG_ENDDECLS
#endif /* DNS_ADB_H */
diff --git a/lib/dns/include/dns/bit.h b/lib/dns/include/dns/bit.h
index 770f294..28c733d 100644
--- a/lib/dns/include/dns/bit.h
+++ b/lib/dns/include/dns/bit.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: bit.h,v 1.8.18.2 2005/04/29 00:16:09 marka Exp $ */
+/* $Id: bit.h,v 1.14 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_BIT_H
#define DNS_BIT_H 1
-/*! \file */
+/*! \file dns/bit.h */
#include <isc/int.h>
#include <isc/boolean.h>
diff --git a/lib/dns/include/dns/byaddr.h b/lib/dns/include/dns/byaddr.h
index 1f1e88c..edf8430 100644
--- a/lib/dns/include/dns/byaddr.h
+++ b/lib/dns/include/dns/byaddr.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: byaddr.h,v 1.16.18.2 2005/04/29 00:16:09 marka Exp $ */
+/* $Id: byaddr.h,v 1.22 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_BYADDR_H
#define DNS_BYADDR_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/byaddr.h
* \brief
* The byaddr module provides reverse lookup services for IPv4 and IPv6
* addresses.
@@ -121,8 +121,8 @@ dns_byaddr_cancel(dns_byaddr_t *byaddr);
*
* Notes:
*
- *\li If 'byaddr' has not completed, post its #BYADDRDONE event with a
- * result code of #ISC_R_CANCELED.
+ *\li If 'byaddr' has not completed, post its #DNS_EVENT_BYADDRDONE
+ * event with a result code of #ISC_R_CANCELED.
*
* Requires:
*
@@ -138,8 +138,8 @@ dns_byaddr_destroy(dns_byaddr_t **byaddrp);
*
*\li '*byaddrp' is a valid byaddr.
*
- *\li The caller has received the BYADDRDONE event (either because the
- * byaddr completed or because dns_byaddr_cancel() was called).
+ *\li The caller has received the #DNS_EVENT_BYADDRDONE event (either because
+ * the byaddr completed or because dns_byaddr_cancel() was called).
*
* Ensures:
*
diff --git a/lib/dns/include/dns/cache.h b/lib/dns/include/dns/cache.h
index fc4f78e..7b37235 100644
--- a/lib/dns/include/dns/cache.h
+++ b/lib/dns/include/dns/cache.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cache.h,v 1.19.18.3 2005/08/23 02:31:38 marka Exp $ */
+/* $Id: cache.h,v 1.26 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_CACHE_H
#define DNS_CACHE_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/cache.h
* \brief
* Defines dns_cache_t, the cache object.
*
diff --git a/lib/dns/include/dns/callbacks.h b/lib/dns/include/dns/callbacks.h
index 6aee70b..8a8385a 100644
--- a/lib/dns/include/dns/callbacks.h
+++ b/lib/dns/include/dns/callbacks.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: callbacks.h,v 1.18.18.2 2005/04/29 00:16:10 marka Exp $ */
+/* $Id: callbacks.h,v 1.24 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_CALLBACKS_H
#define DNS_CALLBACKS_H 1
-/*! \file */
+/*! \file dns/callbacks.h */
/***
*** Imports
diff --git a/lib/dns/include/dns/cert.h b/lib/dns/include/dns/cert.h
index 4de1aec..1cda848 100644
--- a/lib/dns/include/dns/cert.h
+++ b/lib/dns/include/dns/cert.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cert.h,v 1.13.18.2 2005/04/29 00:16:10 marka Exp $ */
+/* $Id: cert.h,v 1.19 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_CERT_H
#define DNS_CERT_H 1
-/*! \file */
+/*! \file dns/cert.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/compress.h b/lib/dns/include/dns/compress.h
index 4d9c011..4632aff 100644
--- a/lib/dns/include/dns/compress.h
+++ b/lib/dns/include/dns/compress.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: compress.h,v 1.32.18.6 2006/03/02 00:37:21 marka Exp $ */
+/* $Id: compress.h,v 1.40.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_COMPRESS_H
#define DNS_COMPRESS_H 1
@@ -32,7 +32,7 @@ ISC_LANG_BEGINDECLS
#define DNS_COMPRESS_ALL 0x01 /*%< all compression. */
#define DNS_COMPRESS_CASESENSITIVE 0x02 /*%< case sensitive compression. */
-/*! \file
+/*! \file dns/compress.h
* Direct manipulation of the structures is strongly discouraged.
*/
@@ -77,7 +77,7 @@ struct dns_decompress {
isc_result_t
dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx);
/*%<
- * Inialise the compression context structure pointed to by 'cctx'.
+ * Initialise the compression context structure pointed to by 'cctx'.
*
* Requires:
* \li 'cctx' is a valid dns_compress_t structure.
@@ -136,7 +136,7 @@ dns_compress_setsensitive(dns_compress_t *cctx, isc_boolean_t sensitive);
isc_boolean_t
dns_compress_getsensitive(dns_compress_t *cctx);
/*
- * Return whether case is to be preservered when compressing
+ * Return whether case is to be preserved when compressing
* domain names.
*
* Requires:
diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h
index b03ae57..3b78208 100644
--- a/lib/dns/include/dns/db.h
+++ b/lib/dns/include/dns/db.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.h,v 1.76.18.10 2007/08/28 07:20:05 tbox Exp $ */
+/* $Id: db.h,v 1.93.50.3 2009/01/18 23:25:17 marka Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/db.h
* \brief
* The DNS DB interface allows named rdatasets to be stored and retrieved.
*
@@ -111,8 +111,7 @@ typedef struct dns_dbmethods {
isc_stdtime_t now);
void (*printnode)(dns_db_t *db, dns_dbnode_t *node,
FILE *out);
- isc_result_t (*createiterator)(dns_db_t *db,
- isc_boolean_t relative_names,
+ isc_result_t (*createiterator)(dns_db_t *db, unsigned int options,
dns_dbiterator_t **iteratorp);
isc_result_t (*findrdataset)(dns_db_t *db, dns_dbnode_t *node,
dns_dbversion_t *version,
@@ -146,6 +145,28 @@ typedef struct dns_dbmethods {
void (*overmem)(dns_db_t *db, isc_boolean_t overmem);
void (*settask)(dns_db_t *db, isc_task_t *);
isc_result_t (*getoriginnode)(dns_db_t *db, dns_dbnode_t **nodep);
+ void (*transfernode)(dns_db_t *db, dns_dbnode_t **sourcep,
+ dns_dbnode_t **targetp);
+ isc_result_t (*getnsec3parameters)(dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_hash_t *hash,
+ isc_uint8_t *flags,
+ isc_uint16_t *iterations,
+ unsigned char *salt,
+ size_t *salt_len);
+ isc_result_t (*findnsec3node)(dns_db_t *db, dns_name_t *name,
+ isc_boolean_t create,
+ dns_dbnode_t **nodep);
+ isc_result_t (*setsigningtime)(dns_db_t *db,
+ dns_rdataset_t *rdataset,
+ isc_stdtime_t resign);
+ isc_result_t (*getsigningtime)(dns_db_t *db,
+ dns_rdataset_t *rdataset,
+ dns_name_t *name);
+ void (*resigned)(dns_db_t *db, dns_rdataset_t *rdataset,
+ dns_dbversion_t *version);
+ isc_boolean_t (*isdnssec)(dns_db_t *db);
+ dns_stats_t *(*getrrsetstats)(dns_db_t *db);
} dns_dbmethods_t;
typedef isc_result_t
@@ -153,7 +174,7 @@ typedef isc_result_t
dns_dbtype_t type, dns_rdataclass_t rdclass,
unsigned int argc, char *argv[], void *driverarg,
dns_db_t **dbp);
-
+
#define DNS_DB_MAGIC ISC_MAGIC('D','N','S','D')
#define DNS_DB_VALID(db) ISC_MAGIC_VALID(db, DNS_DB_MAGIC)
@@ -191,6 +212,7 @@ struct dns_db {
#define DNS_DBFIND_NOEXACT 0x10
#define DNS_DBFIND_FORCENSEC 0x20
#define DNS_DBFIND_COVERINGNSEC 0x40
+#define DNS_DBFIND_FORCENSEC3 0x80
/*@}*/
/*@{*/
@@ -208,6 +230,15 @@ struct dns_db {
*/
#define DNS_DBSUB_EXACT 0x01
+/*@{*/
+/*%
+ * Iterator options
+ */
+#define DNS_DB_RELATIVENAMES 0x1
+#define DNS_DB_NSEC3ONLY 0x2
+#define DNS_DB_NONSEC3 0x4
+/*@}*/
+
/*****
***** Methods
*****/
@@ -355,6 +386,20 @@ dns_db_issecure(dns_db_t *db);
* \li #ISC_FALSE 'db' is not secure.
*/
+isc_boolean_t
+dns_db_isdnssec(dns_db_t *db);
+/*%<
+ * Is 'db' secure or partially secure?
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database with zone semantics.
+ *
+ * Returns:
+ * \li #ISC_TRUE 'db' is secure or is partially.
+ * \li #ISC_FALSE 'db' is not secure.
+ */
+
dns_name_t *
dns_db_origin(dns_db_t *db);
/*%<
@@ -626,7 +671,7 @@ dns_db_findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
*
* \li #ISC_R_SUCCESS
* \li #ISC_R_NOTFOUND If !create and name not found.
- * \li #ISC_R_NOMEMORY Can only happen if create is ISC_TRUE.
+ * \li #ISC_R_NOMEMORY Can only happen if create is ISC_TRUE.
*
* \li Other results are possible, depending upon the database
* implementation used.
@@ -785,8 +830,8 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* name, and 'rdataset' contains
* the negative caching proof.
*
- * \li #DNS_R_EMPTYNAME The name exists but there is
- * no data at the name.
+ * \li #DNS_R_EMPTYNAME The name exists but there is
+ * no data at the name.
*
* \li #DNS_R_COVERINGNSEC The returned data is a NSEC
* that potentially covers 'name'.
@@ -883,6 +928,27 @@ dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep);
* \li *nodep is NULL.
*/
+void
+dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep,
+ dns_dbnode_t **targetp);
+/*%<
+ * Transfer a node between pointer.
+ *
+ * This is equivalent to calling dns_db_attachnode() then dns_db_detachnode().
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li '*sourcep' is a valid node.
+ *
+ * \li 'targetp' points to a NULL dns_dbnode_t *.
+ *
+ * Ensures:
+ *
+ * \li '*sourcep' is NULL.
+ */
+
isc_result_t
dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now);
/*%<
@@ -917,16 +983,17 @@ dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out);
***/
isc_result_t
-dns_db_createiterator(dns_db_t *db, isc_boolean_t relative_names,
+dns_db_createiterator(dns_db_t *db, unsigned int options,
dns_dbiterator_t **iteratorp);
/*%<
* Create an iterator for version 'version' of 'db'.
*
* Notes:
*
- * \li If 'relative_names' is ISC_TRUE, then node names returned by the
- * iterator will be relative to the iterator's current origin. If
- * #ISC_FALSE, then the node names will be absolute.
+ * \li One or more of the following options can be set.
+ * #DNS_DB_RELATIVENAMES
+ * #DNS_DB_NSEC3ONLY
+ * #DNS_DB_NONSEC3
*
* Requires:
*
@@ -1005,7 +1072,7 @@ isc_result_t
dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_stdtime_t now, dns_rdatasetiter_t **iteratorp);
/*%<
- * Make '*iteratorp' an rdataset iteratator for all rdatasets at 'node' in
+ * Make '*iteratorp' an rdataset iterator for all rdatasets at 'node' in
* version 'version' of 'db'.
*
* Notes:
@@ -1192,7 +1259,7 @@ dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp);
void
dns_db_overmem(dns_db_t *db, isc_boolean_t overmem);
/*%<
- * Enable / disable agressive cache cleaning.
+ * Enable / disable aggressive cache cleaning.
*/
unsigned int
@@ -1262,7 +1329,7 @@ dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
void
dns_db_unregister(dns_dbimplementation_t **dbimp);
/*%<
- * Remove a database implementation from the the list of supported
+ * Remove a database implementation from the list of supported
* implementations. No databases of this type can be active when this
* is called.
*
@@ -1294,6 +1361,117 @@ dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep);
* \li #ISC_R_NOTFOUND - the DB implementation does not support this feature.
*/
+isc_result_t
+dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
+ dns_hash_t *hash, isc_uint8_t *flags,
+ isc_uint16_t *interations,
+ unsigned char *salt, size_t *salt_length);
+/*%<
+ * Get the NSEC3 parameters that are associated with this zone.
+ *
+ * Requires:
+ * \li 'db' is a valid zone database.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND - the DB implementation does not support this feature
+ * or this zone does not have NSEC3 records.
+ */
+
+isc_result_t
+dns_db_findnsec3node(dns_db_t *db, dns_name_t *name,
+ isc_boolean_t create, dns_dbnode_t **nodep);
+/*%<
+ * Find the NSEC3 node with name 'name'.
+ *
+ * Notes:
+ * \li If 'create' is ISC_TRUE and no node with name 'name' exists, then
+ * such a node will be created.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'name' is a valid, non-empty, absolute name.
+ *
+ * \li nodep != NULL && *nodep == NULL
+ *
+ * Ensures:
+ *
+ * \li On success, *nodep is attached to the node with name 'name'.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND If !create and name not found.
+ * \li #ISC_R_NOMEMORY Can only happen if create is ISC_TRUE.
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+isc_result_t
+dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
+ isc_stdtime_t resign);
+/*%<
+ * Sets the re-signing time associated with 'rdataset' to 'resign'.
+ *
+ * Requires:
+ * \li 'db' is a valid zone database.
+ * \li 'rdataset' to be associated with 'db'.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ * \li #ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
+ */
+
+isc_result_t
+dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name);
+/*%<
+ * Return the rdataset with the earliest signing time in the zone.
+ * Note: the rdataset is version agnostic.
+ *
+ * Requires:
+ * \li 'db' is a valid zone database.
+ * \li 'rdataset' to be initialized but not associated.
+ * \li 'name' to be NULL or have a buffer associated with it.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND - No dataset exists.
+ */
+
+void
+dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset,
+ dns_dbversion_t *version);
+/*%<
+ * Mark 'rdataset' as not being available to be returned by
+ * dns_db_getsigningtime(). If the changes associated with 'version'
+ * are committed this will be permanent. If the version is not committed
+ * this change will be rolled back when the version is closed.
+ *
+ * Requires:
+ * \li 'db' is a valid zone database.
+ * \li 'rdataset' to be associated with 'db'.
+ * \li 'version' to be open for writing.
+ */
+
+dns_stats_t *
+dns_db_getrrsetstats(dns_db_t *db);
+/*%<
+ * Get statistics information counting RRsets stored in the DB, when available.
+ * The statistics may not be available depending on the DB implementation.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database (zone or cache).
+ *
+ * Returns:
+ * \li when available, a pointer to a statistics object created by
+ * dns_rdatasetstats_create(); otherwise NULL.
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_DB_H */
diff --git a/lib/dns/include/dns/dbiterator.h b/lib/dns/include/dns/dbiterator.h
index 47ce082..366d676 100644
--- a/lib/dns/include/dns/dbiterator.h
+++ b/lib/dns/include/dns/dbiterator.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dbiterator.h,v 1.19.18.2 2005/04/29 00:16:11 marka Exp $ */
+/* $Id: dbiterator.h,v 1.25 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_DBITERATOR_H
#define DNS_DBITERATOR_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/dbiterator.h
* \brief
* The DNS DB Iterator interface allows iteration of all of the nodes in a
* database.
diff --git a/lib/dns/include/dns/dbtable.h b/lib/dns/include/dns/dbtable.h
index 18d3e50..503de95 100644
--- a/lib/dns/include/dns/dbtable.h
+++ b/lib/dns/include/dns/dbtable.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dbtable.h,v 1.17.18.2 2005/04/29 00:16:11 marka Exp $ */
+/* $Id: dbtable.h,v 1.23 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_DBTABLE_H
#define DNS_DBTABLE_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/dbtable.h
* \brief
* DNS DB Tables
*
diff --git a/lib/dns/include/dns/diff.h b/lib/dns/include/dns/diff.h
index cd96a0b..a13b678 100644
--- a/lib/dns/include/dns/diff.h
+++ b/lib/dns/include/dns/diff.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: diff.h,v 1.6.18.2 2005/04/29 00:16:12 marka Exp $ */
+/* $Id: diff.h,v 1.15.120.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_DIFF_H
#define DNS_DIFF_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/diff.h
* \brief
* A diff is a convenience type representing a list of changes to be
* made to a database.
@@ -59,12 +59,18 @@
* individual RRs of a "RRset exists (value dependent)"
* prerequisite set. In this case, op==DNS_DIFFOP_EXISTS,
* and the TTL is ignored.
+ *
+ * DNS_DIFFOP_*RESIGN will cause the 'resign' attribute of the resulting
+ * RRset to be recomputed to be 'resign' seconds before the earliest RRSIG
+ * timeexpire.
*/
typedef enum {
- DNS_DIFFOP_ADD, /*%< Add an RR. */
- DNS_DIFFOP_DEL, /*%< Delete an RR. */
- DNS_DIFFOP_EXISTS /*%< Assert RR existence. */
+ DNS_DIFFOP_ADD = 0, /*%< Add an RR. */
+ DNS_DIFFOP_DEL = 1, /*%< Delete an RR. */
+ DNS_DIFFOP_EXISTS = 2, /*%< Assert RR existence. */
+ DNS_DIFFOP_ADDRESIGN = 4, /*%< ADD + RESIGN. */
+ DNS_DIFFOP_DELRESIGN = 5, /*%< DEL + RESIGN. */
} dns_diffop_t;
typedef struct dns_difftuple dns_difftuple_t;
@@ -73,7 +79,7 @@ typedef struct dns_difftuple dns_difftuple_t;
#define DNS_DIFFTUPLE_VALID(t) ISC_MAGIC_VALID(t, DNS_DIFFTUPLE_MAGIC)
struct dns_difftuple {
- unsigned int magic;
+ unsigned int magic;
isc_mem_t *mctx;
dns_diffop_t op;
dns_name_t name;
@@ -96,10 +102,15 @@ typedef struct dns_diff dns_diff_t;
struct dns_diff {
unsigned int magic;
isc_mem_t * mctx;
+ /*
+ * Set the 'resign' attribute to this many second before the
+ * earliest RRSIG timeexpire.
+ */
+ isc_uint32_t resign;
ISC_LIST(dns_difftuple_t) tuples;
};
-/* Type of comparision function for sorting diffs. */
+/* Type of comparison function for sorting diffs. */
typedef int dns_diff_compare_func(const void *, const void *);
/***
@@ -110,7 +121,7 @@ ISC_LANG_BEGINDECLS
/**************************************************************************/
/*
- * Maniuplation of diffs and tuples.
+ * Manipulation of diffs and tuples.
*/
isc_result_t
diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h
index 8c14320..96a44fe 100644
--- a/lib/dns/include/dns/dispatch.h
+++ b/lib/dns/include/dns/dispatch.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dispatch.h,v 1.48.18.9 2008/06/24 23:45:55 tbox Exp $ */
+/* $Id: dispatch.h,v 1.60.82.2 2009/01/29 23:47:44 tbox Exp $ */
#ifndef DNS_DISPATCH_H
#define DNS_DISPATCH_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/dispatch.h
* \brief
* DNS Dispatch Management
* Shared UDP and single-use TCP dispatches for queries and responses.
@@ -55,7 +55,7 @@
#include <isc/buffer.h>
#include <isc/lang.h>
#include <isc/socket.h>
-#include <dns/types.h>
+#include <isc/types.h>
#include <dns/types.h>
@@ -222,6 +222,21 @@ dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
*\li v6portset is NULL or a valid port set
*/
+void
+dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats);
+/*%<
+ * Sets statistics counter for the dispatchmgr. This function is expected to
+ * be called only on zone creation (when necessary).
+ * Once installed, it cannot be removed or replaced. Also, there is no
+ * interface to get the installed stats from the zone; the caller must keep the
+ * stats to reference (e.g. dump) it later.
+ *
+ * Requires:
+ *\li mgr is a valid dispatchmgr with no managed dispatch.
+ *\li stats is a valid statistics supporting resolver statistics counters
+ * (see dns/stats.h).
+ */
+
isc_result_t
dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
diff --git a/lib/dns/include/dns/dlz.h b/lib/dns/include/dns/dlz.h
index 4c61c91..75ba99f 100644
--- a/lib/dns/include/dns/dlz.h
+++ b/lib/dns/include/dns/dlz.h
@@ -1,8 +1,8 @@
/*
- * Portions Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -50,9 +50,9 @@
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dlz.h,v 1.2.2.2 2005/09/06 03:47:18 marka Exp $ */
+/* $Id: dlz.h,v 1.7.332.2 2009/01/18 23:47:41 tbox Exp $ */
-/*! \file */
+/*! \file dns/dlz.h */
#ifndef DLZ_H
#define DLZ_H 1
@@ -133,7 +133,7 @@ typedef void
/*%<
* Method prototype. Drivers implementing the DLZ interface MUST
* supply a destroy method. This method is called when the DNS server
- * is shuting down and no longer needs the driver.
+ * is shutting down and no longer needs the driver.
*/
typedef isc_result_t
@@ -157,7 +157,7 @@ typedef isc_result_t
* \li 3) we run out of domain name labels. I.E. we have tried the
* shortest domain name
* \li 4) the number of labels in the domain name is less than
- * min_lables for dns_dlzfindzone
+ * min_labels for dns_dlzfindzone
*
* The driver's find zone method should return ISC_R_SUCCESS and a
* database pointer to the name server if the zone is supported by the
@@ -202,7 +202,7 @@ dns_dlzallowzonexfr(dns_view_t *view, dns_name_t *name,
/*%<
* This method is called when the DNS server is performing a zone
- * transfer query. It will call the DLZ driver's allow zone tranfer
+ * transfer query. It will call the DLZ driver's allow zone transfer
* method.
*/
@@ -223,7 +223,7 @@ void
dns_dlzdestroy(dns_dlzdb_t **dbp);
/*%<
- * This method is called when the DNS server is shuting down and no
+ * This method is called when the DNS server is shutting down and no
* longer needs the driver. If the DLZ driver supplies a destroy
* methods, this function will call it.
*/
diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h
index 2804e03..f8a59d0 100644
--- a/lib/dns/include/dns/dnssec.h
+++ b/lib/dns/include/dns/dnssec.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec.h,v 1.26.18.2 2005/04/29 00:16:12 marka Exp $ */
+/* $Id: dnssec.h,v 1.32 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_DNSSEC_H
#define DNS_DNSSEC_H 1
-/*! \file */
+/*! \file dns/dnssec.h */
#include <isc/lang.h>
#include <isc/stdtime.h>
diff --git a/lib/dns/include/dns/ds.h b/lib/dns/include/dns/ds.h
index 5e4cc40..b59fb83 100644
--- a/lib/dns/include/dns/ds.h
+++ b/lib/dns/include/dns/ds.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ds.h,v 1.3.20.5 2006/02/22 23:50:09 marka Exp $ */
+/* $Id: ds.h,v 1.10 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_DS_H
#define DNS_DS_H 1
diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h
index d1ebef3..bb61b9d 100644
--- a/lib/dns/include/dns/events.h
+++ b/lib/dns/include/dns/events.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,14 +15,14 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: events.h,v 1.42.18.3 2005/04/29 00:16:13 marka Exp $ */
+/* $Id: events.h,v 1.49.332.2 2009/05/07 23:47:12 tbox Exp $ */
#ifndef DNS_EVENTS_H
#define DNS_EVENTS_H 1
#include <isc/eventclass.h>
-/*! \file
+/*! \file dns/events.h
* \brief
* Registry of DNS event numbers.
*/
@@ -68,6 +68,7 @@
#define DNS_EVENT_ACACHECONTROL (ISC_EVENTCLASS_DNS + 38)
#define DNS_EVENT_ACACHECLEAN (ISC_EVENTCLASS_DNS + 39)
#define DNS_EVENT_ACACHEOVERMEM (ISC_EVENTCLASS_DNS + 40)
+#define DNS_EVENT_RBTPRUNE (ISC_EVENTCLASS_DNS + 41)
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
diff --git a/lib/dns/include/dns/fixedname.h b/lib/dns/include/dns/fixedname.h
index 8380de6..5a2aaf3 100644
--- a/lib/dns/include/dns/fixedname.h
+++ b/lib/dns/include/dns/fixedname.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: fixedname.h,v 1.13.18.2 2005/04/29 00:16:13 marka Exp $ */
+/* $Id: fixedname.h,v 1.19 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_FIXEDNAME_H
#define DNS_FIXEDNAME_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/fixedname.h
* \brief
* Fixed-size Names
*
diff --git a/lib/dns/include/dns/forward.h b/lib/dns/include/dns/forward.h
index ddf6d7f..512c5e3 100644
--- a/lib/dns/include/dns/forward.h
+++ b/lib/dns/include/dns/forward.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: forward.h,v 1.3.18.3 2005/04/27 05:01:33 sra Exp $ */
+/* $Id: forward.h,v 1.11 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_FORWARD_H
#define DNS_FORWARD_H 1
-/*! \file */
+/*! \file dns/forward.h */
#include <isc/lang.h>
#include <isc/result.h>
diff --git a/lib/dns/include/dns/iptable.h b/lib/dns/include/dns/iptable.h
new file mode 100644
index 0000000..d7eb140
--- /dev/null
+++ b/lib/dns/include/dns/iptable.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: iptable.h,v 1.4 2007/09/14 01:46:05 marka Exp $ */
+
+#ifndef DNS_IPTABLE_H
+#define DNS_IPTABLE_H 1
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/radix.h>
+
+struct dns_iptable {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_refcount_t refcount;
+ isc_radix_tree_t *radix;
+ ISC_LINK(dns_iptable_t) nextincache;
+};
+
+#define DNS_IPTABLE_MAGIC ISC_MAGIC('T','a','b','l')
+#define DNS_IPTABLE_VALID(a) ISC_MAGIC_VALID(a, DNS_IPTABLE_MAGIC)
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_iptable_create(isc_mem_t *mctx, dns_iptable_t **target);
+/*
+ * Create a new IP table and the underlying radix structure
+ */
+
+isc_result_t
+dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
+ isc_uint16_t bitlen, isc_boolean_t pos);
+/*
+ * Add an IP prefix to an existing IP table
+ */
+
+isc_result_t
+dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos);
+/*
+ * Merge one IP table into another one.
+ */
+
+void
+dns_iptable_attach(dns_iptable_t *source, dns_iptable_t **target);
+
+void
+dns_iptable_detach(dns_iptable_t **tabp);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_IPTABLE_H */
diff --git a/lib/dns/include/dns/journal.h b/lib/dns/include/dns/journal.h
index b776a30..3917d8d 100644
--- a/lib/dns/include/dns/journal.h
+++ b/lib/dns/include/dns/journal.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: journal.h,v 1.25.18.2 2005/04/29 00:16:13 marka Exp $ */
+/* $Id: journal.h,v 1.33.120.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_JOURNAL_H
#define DNS_JOURNAL_H 1
@@ -24,9 +24,9 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/journal.h
* \brief
- * Database journalling.
+ * Database journaling.
*/
/***
@@ -42,6 +42,11 @@
#include <dns/types.h>
/***
+ *** Defines.
+ ***/
+#define DNS_JOURNALOPT_RESIGN 0x00000001
+
+/***
*** Types
***/
@@ -188,7 +193,7 @@ dns_journal_iter_init(dns_journal_t *j,
* Returns:
*\li ISC_R_SUCCESS
*\li ISC_R_RANGE begin_serial is outside the addressable range.
- *\li ISC_R_NOTFOUND begin_serial is within the range of adressable
+ *\li ISC_R_NOTFOUND begin_serial is within the range of addressable
* serial numbers covered by the journal, but
* this particular serial number does not exist.
*/
@@ -225,17 +230,18 @@ dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, isc_uint32_t *ttl,
*/
isc_result_t
-dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, const char *filename);
+dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, unsigned int options,
+ const char *filename);
/*%<
* Roll forward (play back) the journal file "filename" into the
* database "db". This should be called when the server starts
* after a shutdown or crash.
*
* Requires:
- *\li 'mctx' is a valid memory context.
+ *\li 'mctx' is a valid memory context.
*\li 'db' is a valid database which does not have a version
* open for writing.
- * \li 'filename' is the name of the journal file belonging to 'db'.
+ *\li 'filename' is the name of the journal file belonging to 'db'.
*
* Returns:
*\li DNS_R_NOJOURNAL when journal does not exist.
@@ -264,7 +270,7 @@ dns_db_diff(isc_mem_t *mctx,
isc_result_t
dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
- isc_uint32_t target_size);
+ isc_uint32_t target_size);
/*%<
* Attempt to compact the journal if it is greater that 'target_size'.
* Changes from 'serial' onwards will be preserved. If the journal
diff --git a/lib/dns/include/dns/keyflags.h b/lib/dns/include/dns/keyflags.h
index 665b517..74a1740 100644
--- a/lib/dns/include/dns/keyflags.h
+++ b/lib/dns/include/dns/keyflags.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keyflags.h,v 1.10.18.2 2005/04/29 00:16:13 marka Exp $ */
+/* $Id: keyflags.h,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_KEYFLAGS_H
#define DNS_KEYFLAGS_H 1
-/*! \file */
+/*! \file dns/keyflags.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/keytable.h b/lib/dns/include/dns/keytable.h
index b8bfcc1..553aa99 100644
--- a/lib/dns/include/dns/keytable.h
+++ b/lib/dns/include/dns/keytable.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keytable.h,v 1.11.18.3 2005/12/05 00:00:03 marka Exp $ */
+/* $Id: keytable.h,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_KEYTABLE_H
#define DNS_KEYTABLE_H 1
diff --git a/lib/dns/include/dns/keyvalues.h b/lib/dns/include/dns/keyvalues.h
index df17ace..7040389 100644
--- a/lib/dns/include/dns/keyvalues.h
+++ b/lib/dns/include/dns/keyvalues.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keyvalues.h,v 1.15.18.2 2005/04/29 00:16:14 marka Exp $ */
+/* $Id: keyvalues.h,v 1.23 2008/09/25 04:02:39 tbox Exp $ */
#ifndef DNS_KEYVALUES_H
#define DNS_KEYVALUES_H 1
-/*! \file */
+/*! \file dns/keyvalues.h */
/*
* Flags field of the KEY RR rdata
@@ -64,9 +64,11 @@
#define DNS_KEYALG_RSA DNS_KEYALG_RSAMD5
#define DNS_KEYALG_DH 2 /*%< Diffie Hellman KEY */
#define DNS_KEYALG_DSA 3 /*%< DSA KEY */
-#define DNS_KEYALG_DSS NS_ALG_DSA
+#define DNS_KEYALG_NSEC3DSA 6
+#define DNS_KEYALG_DSS DNS_ALG_DSA
#define DNS_KEYALG_ECC 4
#define DNS_KEYALG_RSASHA1 5
+#define DNS_KEYALG_NSEC3RSASHA1 7
#define DNS_KEYALG_INDIRECT 252
#define DNS_KEYALG_PRIVATEDNS 253
#define DNS_KEYALG_PRIVATEOID 254 /*%< Key begins with OID giving alg */
diff --git a/lib/dns/include/dns/lib.h b/lib/dns/include/dns/lib.h
index d59dde3..fd3325b 100644
--- a/lib/dns/include/dns/lib.h
+++ b/lib/dns/include/dns/lib.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lib.h,v 1.8.18.4 2005/09/20 04:33:48 marka Exp $ */
+/* $Id: lib.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_LIB_H
#define DNS_LIB_H 1
-/*! \file */
+/*! \file dns/lib.h */
#include <isc/types.h>
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h
index 7bee174..b7aed42 100644
--- a/lib/dns/include/dns/log.h
+++ b/lib/dns/include/dns/log.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,9 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.h,v 1.33.18.4 2005/09/05 00:18:27 marka Exp $ */
+/* $Id: log.h,v 1.42.332.2 2009/01/18 23:47:41 tbox Exp $ */
-/*! \file
+/*! \file dns/log.h
* \author Principal Authors: DCL */
#ifndef DNS_LOG_H
@@ -41,6 +41,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
#define DNS_LOGCATEGORY_DISPATCH (&dns_categories[8])
#define DNS_LOGCATEGORY_LAME_SERVERS (&dns_categories[9])
#define DNS_LOGCATEGORY_DELEGATION_ONLY (&dns_categories[10])
+#define DNS_LOGCATEGORY_EDNS_DISABLED (&dns_categories[11])
/* Backwards compatibility. */
#define DNS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL
@@ -87,7 +88,7 @@ dns_log_init(isc_log_t *lctx);
*\li dns_log_init() is called only once.
*
* Ensures:
- * \li The catgories and modules defined above are available for
+ * \li The categories and modules defined above are available for
* use by isc_log_usechannnel() and isc_log_write().
*/
diff --git a/lib/dns/include/dns/lookup.h b/lib/dns/include/dns/lookup.h
index aea6f84..0e9a327 100644
--- a/lib/dns/include/dns/lookup.h
+++ b/lib/dns/include/dns/lookup.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lookup.h,v 1.6.18.2 2005/04/29 00:16:15 marka Exp $ */
+/* $Id: lookup.h,v 1.12.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_LOOKUP_H
#define DNS_LOOKUP_H 1
@@ -24,11 +24,11 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/lookup.h
* \brief
* The lookup module performs simple DNS lookups. It implements
- * the full resolver algorithm, both looking for local data and
- * resoving external names as necessary.
+ * the full resolver algorithm, both looking for local data and
+ * resolving external names as necessary.
*
* MP:
*\li The module ensures appropriate synchronization of data structures it
diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h
index 1f94c8c..93a782d 100644
--- a/lib/dns/include/dns/master.h
+++ b/lib/dns/include/dns/master.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: master.h,v 1.38.18.6 2005/06/20 01:19:43 marka Exp $ */
+/* $Id: master.h,v 1.51 2008/04/02 02:37:42 marka Exp $ */
#ifndef DNS_MASTER_H
#define DNS_MASTER_H 1
-/*! \file */
+/*! \file dns/master.h */
/***
*** Imports
@@ -42,7 +42,7 @@
#define DNS_MASTER_HINT 0x00000010 /*%< Loading a hint master file. */
#define DNS_MASTER_SLAVE 0x00000020 /*%< Loading a slave master file. */
#define DNS_MASTER_CHECKNS 0x00000040 /*%<
- * Check NS records to see
+ * Check NS records to see
* if they are an address
*/
#define DNS_MASTER_FATALNS 0x00000080 /*%<
@@ -55,6 +55,8 @@
#define DNS_MASTER_CHECKMX 0x00000800
#define DNS_MASTER_CHECKMXFAIL 0x00001000
+#define DNS_MASTER_RESIGN 0x00002000
+
ISC_LANG_BEGINDECLS
/*
@@ -113,6 +115,17 @@ dns_master_loadfile2(const char *master_file,
dns_masterformat_t format);
isc_result_t
+dns_master_loadfile3(const char *master_file,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ isc_uint32_t resign,
+ dns_rdatacallbacks_t *callbacks,
+ isc_mem_t *mctx,
+ dns_masterformat_t format);
+
+isc_result_t
dns_master_loadstream(FILE *stream,
dns_name_t *top,
dns_name_t *origin,
@@ -163,6 +176,19 @@ dns_master_loadfileinc2(const char *master_file,
dns_masterformat_t format);
isc_result_t
+dns_master_loadfileinc3(const char *master_file,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ isc_uint32_t resign,
+ dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **ctxp, isc_mem_t *mctx,
+ dns_masterformat_t format);
+
+isc_result_t
dns_master_loadstreaminc(FILE *stream,
dns_name_t *top,
dns_name_t *origin,
@@ -212,6 +238,9 @@ dns_master_loadlexerinc(isc_lex_t *lex,
* is completed or has failed. If the initial setup fails 'done' is
* not called.
*
+ * 'resign' the number of seconds before a RRSIG expires that it should
+ * be re-signed. 0 is used if not provided.
+ *
* Requires:
*\li 'master_file' points to a valid string.
*\li 'lexer' points to a valid lexer.
diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h
index 8cf5c13..42521b3 100644
--- a/lib/dns/include/dns/masterdump.h
+++ b/lib/dns/include/dns/masterdump.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: masterdump.h,v 1.31.14.4 2005/09/01 03:04:28 marka Exp $ */
+/* $Id: masterdump.h,v 1.42 2008/09/24 02:46:23 marka Exp $ */
#ifndef DNS_MASTERDUMP_H
#define DNS_MASTERDUMP_H 1
-/*! \file */
+/*! \file dns/masterdump.h */
/***
*** Imports
@@ -91,11 +91,14 @@ typedef struct dns_master_style dns_master_style_t;
/*% Print negative caching entries. */
#define DNS_STYLEFLAG_NCACHE 0x00800000U
-/*% Never print the TTL */
+/*% Never print the TTL. */
#define DNS_STYLEFLAG_NO_TTL 0x01000000U
-
-/*% Never print the CLASS */
-#define DNS_STYLEFLAG_NO_CLASS 0x02000000U
+
+/*% Never print the CLASS. */
+#define DNS_STYLEFLAG_NO_CLASS 0x02000000U
+
+/*% Report re-signing time. */
+#define DNS_STYLEFLAG_RESIGN 0x04000000U
ISC_LANG_BEGINDECLS
@@ -119,8 +122,8 @@ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_default;
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_full;
/*%
- * A master file style that prints explicit TTL values on each
- * record line, never using $TTL statements. The TTL has a tab
+ * A master file style that prints explicit TTL values on each
+ * record line, never using $TTL statements. The TTL has a tab
* stop of its own, but the class and type share one.
*/
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t
@@ -133,9 +136,9 @@ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_cache;
/*%
- * A master style that prints name, ttl, class, type, and value on
- * every line. Similar to explicitttl above, but more verbose.
- * Intended for generating master files which can be easily parsed
+ * A master style that prints name, ttl, class, type, and value on
+ * every line. Similar to explicitttl above, but more verbose.
+ * Intended for generating master files which can be easily parsed
* by perl scripts and similar applications.
*/
LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_simple;
@@ -231,7 +234,7 @@ dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db,
*\li 'task' to be valid.
*\li 'done' to be non NULL.
*\li 'dctxp' to be non NULL && '*dctxp' to be NULL.
- *
+ *
* Returns:
*\li ISC_R_SUCCESS
*\li ISC_R_CONTINUE dns_master_dumptostreaminc() only.
@@ -329,6 +332,9 @@ dns_master_stylecreate(dns_master_style_t **style, unsigned int flags,
void
dns_master_styledestroy(dns_master_style_t **style, isc_mem_t *mctx);
+const char *
+dns_trust_totext(dns_trust_t trust);
+
ISC_LANG_ENDDECLS
#endif /* DNS_MASTERDUMP_H */
diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h
index 9002b83..f880095 100644
--- a/lib/dns/include/dns/message.h
+++ b/lib/dns/include/dns/message.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: message.h,v 1.114.18.6 2006/03/02 23:19:20 marka Exp $ */
+/* $Id: message.h,v 1.125.118.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_MESSAGE_H
#define DNS_MESSAGE_H 1
@@ -33,7 +33,7 @@
#include <dst/dst.h>
-/*! \file
+/*! \file dns/message.h
* \brief Message Handling Module
*
* How this beast works:
@@ -101,8 +101,12 @@
#define DNS_MESSAGEFLAG_AD 0x0020U
#define DNS_MESSAGEFLAG_CD 0x0010U
+/*%< EDNS0 extended message flags */
#define DNS_MESSAGEEXTFLAG_DO 0x8000U
+/*%< EDNS0 extended OPT codes */
+#define DNS_OPT_NSID 0x0003 /*%< NSID opt code */
+
#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
@@ -157,7 +161,7 @@ typedef int dns_messagetextflag_t;
occurs */
#define DNS_MESSAGEPARSE_CLONEBUFFER 0x0004 /*%< save a copy of the
source buffer */
-#define DNS_MESSAGEPARSE_IGNORETRUNCATION 0x0008 /*%< trucation errors are
+#define DNS_MESSAGEPARSE_IGNORETRUNCATION 0x0008 /*%< truncation errors are
* not fatal. */
/*
@@ -771,7 +775,7 @@ dns_message_addname(dns_message_t *msg, dns_name_t *name,
void
dns_message_removename(dns_message_t *msg, dns_name_t *name,
- dns_section_t section);
+ dns_section_t section);
/*%<
* Remove a existing name from a given section.
*
@@ -1031,7 +1035,7 @@ dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt);
*\li The OPT record has either been freed or ownership of it has
* been transferred to the message.
*
- *\li If ISC_R_SUCCESS was returned, the OPT record will be rendered
+ *\li If ISC_R_SUCCESS was returned, the OPT record will be rendered
* when dns_message_renderend() is called.
*
* Returns:
@@ -1195,7 +1199,7 @@ dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer);
*\li msg be a valid message.
*
*\li buffer != NULL && *buffer is a valid isc_buffer_t, which was
- * dynamincally allocated via isc_buffer_allocate().
+ * dynamically allocated via isc_buffer_allocate().
*/
isc_result_t
@@ -1315,7 +1319,7 @@ dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
*\li order_arg is NULL if and only if order is NULL.
*/
-void
+void
dns_message_settimeadjust(dns_message_t *msg, int timeadjust);
/*%<
* Adjust the time used to sign/verify a message by timeadjust.
@@ -1325,7 +1329,7 @@ dns_message_settimeadjust(dns_message_t *msg, int timeadjust);
*\li msg be a valid message.
*/
-int
+int
dns_message_gettimeadjust(dns_message_t *msg);
/*%<
* Return the current time adjustment.
diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h
index 038ae05..0149301 100644
--- a/lib/dns/include/dns/name.h
+++ b/lib/dns/include/dns/name.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: name.h,v 1.107.18.15 2006/03/02 00:37:21 marka Exp $ */
+/* $Id: name.h,v 1.126.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_NAME_H
#define DNS_NAME_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/name.h
* \brief
* Provides facilities for manipulating DNS names and labels, including
* conversions to and from wire format and text format.
@@ -131,6 +131,7 @@ struct dns_name {
#define DNS_NAMEATTR_READONLY 0x0002
#define DNS_NAMEATTR_DYNAMIC 0x0004
#define DNS_NAMEATTR_DYNOFFSETS 0x0008
+#define DNS_NAMEATTR_NOCOMPRESS 0x0010
/*
* Attributes below 0x0100 reserved for name.c usage.
*/
@@ -242,7 +243,7 @@ dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer);
*
* Notes:
* \li Specification of a target buffer in dns_name_fromwire(),
- * dns_name_fromtext(), and dns_name_concatentate() is optional if
+ * dns_name_fromtext(), and dns_name_concatenate() is optional if
* 'name' has a dedicated buffer.
*
* \li The caller must not write to buffer until the name has been
@@ -721,7 +722,7 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
isc_result_t
dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
- isc_buffer_t *target);
+ isc_buffer_t *target);
/*%<
* Convert 'name' into wire format, compressing it as specified by the
* compression context 'cctx', and storing the result in 'target'.
@@ -840,7 +841,7 @@ dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
* name as generated by dns_name_totext(). This does not
* include space for a terminating NULL.
*
- * This definition is conservative - the actual maximum
+ * This definition is conservative - the actual maximum
* is 1004, derived as follows:
*
* A backslash-decimal escaped character takes 4 bytes.
@@ -952,7 +953,7 @@ dns_name_split(dns_name_t *name, unsigned int suffixlabels,
*
* Notes:
* \li 'name' is split such that 'suffix' holds the most significant
- * 'suffixlabels' labels. All other labels are stored in 'prefix'.
+ * 'suffixlabels' labels. All other labels are stored in 'prefix'.
*
*\li Copying name data is avoided as much as possible, so 'prefix'
* and 'suffix' will end up pointing at the data for 'name'.
@@ -1082,7 +1083,7 @@ dns_name_dynamic(dns_name_t *name);
*
* Returns:
*
- *\li 'ISC_TRUE' if the name is dynamic othewise 'ISC_FALSE'.
+ *\li 'ISC_TRUE' if the name is dynamic otherwise 'ISC_FALSE'.
*/
isc_result_t
@@ -1185,7 +1186,7 @@ dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard);
* Requires:
* 'name' to be valid.
*/
-
+
isc_boolean_t
dns_name_ismailbox(const dns_name_t *name);
@@ -1220,7 +1221,7 @@ dns_name_destroy(void);
ISC_LANG_ENDDECLS
/*
- *** High Peformance Macros
+ *** High Performance Macros
***/
/*
diff --git a/lib/dns/include/dns/ncache.h b/lib/dns/include/dns/ncache.h
index 459effb..a818fe6 100644
--- a/lib/dns/include/dns/ncache.h
+++ b/lib/dns/include/dns/ncache.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.h,v 1.17.18.2 2005/04/29 00:16:16 marka Exp $ */
+/* $Id: ncache.h,v 1.25 2008/09/25 04:02:39 tbox Exp $ */
#ifndef DNS_NCACHE_H
#define DNS_NCACHE_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/ncache.h
*\brief
* DNS Ncache
*
@@ -63,6 +63,11 @@ isc_result_t
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
dns_rdataset_t *addedrdataset);
+isc_result_t
+dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
+ dns_dbnode_t *node, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_ttl_t maxttl,
+ isc_boolean_t optout, dns_rdataset_t *addedrdataset);
/*%<
* Convert the authority data from 'message' into a negative cache
* rdataset, and store it in 'cache' at 'node' with a TTL limited to
@@ -71,6 +76,8 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
* The 'covers' argument is the RR type whose nonexistence we are caching,
* or dns_rdatatype_any when caching a NXDOMAIN response.
*
+ * 'optout' indicates a DNS_RATASETATTR_OPTOUT should be set.
+ *
* Note:
*\li If 'addedrdataset' is not NULL, then it will be attached to the added
* rdataset. See dns_db_addrdataset() for more details.
@@ -154,6 +161,19 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
*
*/
+void
+dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
+ dns_rdataset_t *rdataset);
+
+/*%<
+ * Extract the current rdataset and name from a ncache entry.
+ *
+ * Requires:
+ * \li 'ncacherdataset' to be valid and to be a negative cache entry
+ * \li 'found' to be valid.
+ * \li 'rdataset' to be unassociated.
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_NCACHE_H */
diff --git a/lib/dns/include/dns/nsec.h b/lib/dns/include/dns/nsec.h
index 46b75fa..335a463 100644
--- a/lib/dns/include/dns/nsec.h
+++ b/lib/dns/include/dns/nsec.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec.h,v 1.4.20.2 2005/04/29 00:16:16 marka Exp $ */
+/* $Id: nsec.h,v 1.12 2008/09/25 04:02:39 tbox Exp $ */
#ifndef DNS_NSEC_H
#define DNS_NSEC_H 1
-/*! \file */
+/*! \file dns/nsec.h */
#include <isc/lang.h>
@@ -64,6 +64,17 @@ dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type);
*\li 'nsec' points to a valid rdataset of type NSEC
*/
+isc_result_t
+dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t *answer);
+/*
+ * Report whether the DNSKEY RRset has a NSEC only algorithm. Unknown
+ * algorithms are assumed to support NSEC3.
+ *
+ * Requires:
+ * 'answer' to be non NULL.
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_NSEC_H */
diff --git a/lib/dns/include/dns/nsec3.h b/lib/dns/include/dns/nsec3.h
new file mode 100644
index 0000000..2d6a8dd
--- /dev/null
+++ b/lib/dns/include/dns/nsec3.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: nsec3.h,v 1.5.48.2 2009/01/18 23:47:41 tbox Exp $ */
+
+#ifndef DNS_NSEC3_H
+#define DNS_NSEC3_H 1
+
+#include <isc/lang.h>
+#include <isc/iterated_hash.h>
+
+#include <dns/db.h>
+#include <dns/diff.h>
+#include <dns/name.h>
+#include <dns/rdatastruct.h>
+#include <dns/types.h>
+
+/*
+ * hash = 1, flags =1, iterations = 2, salt length = 1, salt = 255 (max)
+ * hash length = 1, hash = 255 (max), bitmap = 8192 + 512 (max)
+ */
+#define DNS_NSEC3_BUFFERSIZE (6 + 255 + 255 + 8192 + 512)
+/*
+ * hash = 1, flags = 1, iterations = 2, salt length = 1, salt = 255 (max)
+ */
+#define DNS_NSEC3PARAM_BUFFERSIZE (5 + 255)
+
+/*
+ * Test "unknown" algorithm. Is mapped to dns_hash_sha1.
+ */
+#define DNS_NSEC3_UNKNOWNALG 245U
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, unsigned int hashalg,
+ unsigned int optin, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length,
+ const unsigned char *nexthash, size_t hash_length,
+ unsigned char *buffer, dns_rdata_t *rdata);
+/*%<
+ * Build the rdata of a NSEC3 record for the data at 'node'.
+ * Note: 'node' is not the node where the NSEC3 record will be stored.
+ *
+ * Requires:
+ * buffer Points to a temporary buffer of at least
+ * DNS_NSEC_BUFFERSIZE bytes.
+ * rdata Points to an initialized dns_rdata_t.
+ *
+ * Ensures:
+ * *rdata Contains a valid NSEC3 rdata. The 'data' member refers
+ * to 'buffer'.
+ */
+
+isc_boolean_t
+dns_nsec3_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type);
+/*%<
+ * Determine if a type is marked as present in an NSEC3 record.
+ *
+ * Requires:
+ * 'nsec' points to a valid rdataset of type NSEC3
+ */
+
+isc_result_t
+dns_nsec3_hashname(dns_fixedname_t *result,
+ unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
+ size_t *hash_length, dns_name_t *name, dns_name_t *origin,
+ dns_hash_t hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t saltlength);
+/*%<
+ * Make a hashed domain name from an unhashed one. If rethash is not NULL
+ * the raw hash is stored there.
+ */
+
+unsigned int
+dns_nsec3_hashlength(dns_hash_t hash);
+/*%<
+ * Return the length of the hash produced by the specified algorithm
+ * or zero when unknown.
+ */
+
+isc_boolean_t
+dns_nsec3_supportedhash(dns_hash_t hash);
+/*%<
+ * Return whether we support this hash algorithm or not.
+ */
+
+isc_result_t
+dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
+ dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff);
+
+isc_result_t
+dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, dns_ttl_t nsecttl,
+ isc_boolean_t unsecure, dns_diff_t *diff);
+/*%<
+ * Add NSEC3 records for 'name', recording the change in 'diff'.
+ * Adjust previous NSEC3 records, if any, to reflect the addition.
+ * The existing NSEC3 records are removed.
+ *
+ * dns_nsec3_addnsec3() will only add records to the chain identified by
+ * 'nsec3param'.
+ *
+ * 'unsecure' should be set to reflect if this is a potentially
+ * unsecure delegation (no DS record).
+ *
+ * dns_nsec3_addnsec3s() will examine the NSEC3PARAM RRset to determine which
+ * chains to be updated. NSEC3PARAM records with the DNS_NSEC3FLAG_CREATE
+ * will be preferentially chosen over NSEC3PARAM records without
+ * DNS_NSEC3FLAG_CREATE set. NSEC3PARAM records with DNS_NSEC3FLAG_REMOVE
+ * set will be ignored by dns_nsec3_addnsec3s(). If DNS_NSEC3FLAG_CREATE
+ * is set then the new NSEC3 will have OPTOUT set to match the that in the
+ * NSEC3PARAM record otherwise OPTOUT will be inherited from the previous
+ * record in the chain.
+ *
+ * Requires:
+ * 'db' to be valid.
+ * 'version' to be valid or NULL.
+ * 'name' to be valid.
+ * 'nsec3param' to be valid.
+ * 'diff' to be valid.
+ */
+
+isc_result_t
+dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff);
+
+isc_result_t
+dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_diff_t *diff);
+/*%<
+ * Remove NSEC3 records for 'name', recording the change in 'diff'.
+ * Adjust previous NSEC3 records, if any, to reflect the removal.
+ *
+ * dns_nsec3_delnsec3() performs the above for the chain identified by
+ * 'nsec3param'.
+ *
+ * dns_nsec3_delnsec3s() examines the NSEC3PARAM RRset in a similar manner
+ * to dns_nsec3_addnsec3s(). Unlike dns_nsec3_addnsec3s() updated NSEC3
+ * records have the OPTOUT flag preserved.
+ *
+ * Requires:
+ * 'db' to be valid.
+ * 'version' to be valid or NULL.
+ * 'name' to be valid.
+ * 'nsec3param' to be valid.
+ * 'diff' to be valid.
+ */
+
+isc_result_t
+dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t complete, isc_boolean_t *answer);
+/*%<
+ * Check if there are any complete/to be built NSEC3 chains.
+ * If 'complete' is ISC_TRUE only complete chains will be recognized.
+ *
+ * Requires:
+ * 'db' to be valid.
+ * 'version' to be valid or NULL.
+ * 'answer' to be non NULL.
+ */
+
+isc_result_t
+dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
+ isc_mem_t *mctx, unsigned int *iterationsp);
+/*%<
+ * Find the maximum permissible number of iterations allowed based on
+ * the key strength.
+ *
+ * Requires:
+ * 'db' to be valid.
+ * 'version' to be valid or NULL.
+ * 'mctx' to be valid.
+ * 'iterationsp' to be non NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_NSEC3_H */
diff --git a/lib/dns/include/dns/opcode.h b/lib/dns/include/dns/opcode.h
index 4796dba..368b2b2 100644
--- a/lib/dns/include/dns/opcode.h
+++ b/lib/dns/include/dns/opcode.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: opcode.h,v 1.2.18.2 2005/04/29 00:16:16 marka Exp $ */
+/* $Id: opcode.h,v 1.8 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_OPCODE_H
#define DNS_OPCODE_H 1
-/*! \file */
+/*! \file dns/opcode.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/order.h b/lib/dns/include/dns/order.h
index 6458db0..85663c3 100644
--- a/lib/dns/include/dns/order.h
+++ b/lib/dns/include/dns/order.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: order.h,v 1.3.18.2 2005/04/29 00:16:17 marka Exp $ */
+/* $Id: order.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_ORDER_H
#define DNS_ORDER_H 1
-/*! \file */
+/*! \file dns/order.h */
#include <isc/lang.h>
#include <isc/types.h>
diff --git a/lib/dns/include/dns/peer.h b/lib/dns/include/dns/peer.h
index be5a8c3..9e7a188 100644
--- a/lib/dns/include/dns/peer.h
+++ b/lib/dns/include/dns/peer.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: peer.h,v 1.20.18.8 2006/02/28 03:10:48 marka Exp $ */
+/* $Id: peer.h,v 1.33.118.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_PEER_H
#define DNS_PEER_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/peer.h
* \brief
* Data structures for peers (e.g. a 'server' config file statement)
*/
@@ -73,11 +73,12 @@ struct dns_peer {
isc_boolean_t provide_ixfr;
isc_boolean_t request_ixfr;
isc_boolean_t support_edns;
+ isc_boolean_t request_nsid;
dns_name_t *key;
isc_sockaddr_t *transfer_source;
- isc_sockaddr_t *notify_source;
- isc_sockaddr_t *query_source;
- isc_uint16_t udpsize; /* recieve size */
+ isc_sockaddr_t *notify_source;
+ isc_sockaddr_t *query_source;
+ isc_uint16_t udpsize; /* receive size */
isc_uint16_t maxudp; /* transmit size */
isc_uint32_t bitflags;
@@ -150,6 +151,12 @@ isc_result_t
dns_peer_getprovideixfr(dns_peer_t *peer, isc_boolean_t *retval);
isc_result_t
+dns_peer_setrequestnsid(dns_peer_t *peer, isc_boolean_t newval);
+
+isc_result_t
+dns_peer_getrequestnsid(dns_peer_t *peer, isc_boolean_t *retval);
+
+isc_result_t
dns_peer_setsupportedns(dns_peer_t *peer, isc_boolean_t newval);
isc_result_t
diff --git a/lib/dns/include/dns/portlist.h b/lib/dns/include/dns/portlist.h
index 2d400d4..f76731a 100644
--- a/lib/dns/include/dns/portlist.h
+++ b/lib/dns/include/dns/portlist.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,9 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: portlist.h,v 1.3.18.2 2005/04/29 00:16:17 marka Exp $ */
+/* $Id: portlist.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
-/*! \file */
+/*! \file dns/portlist.h */
#include <isc/lang.h>
#include <isc/net.h>
diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h
index a1edf0c..6eea787 100644
--- a/lib/dns/include/dns/rbt.h
+++ b/lib/dns/include/dns/rbt.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbt.h,v 1.59.18.5 2005/10/13 01:26:07 marka Exp $ */
+/* $Id: rbt.h,v 1.71.48.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_RBT_H
#define DNS_RBT_H 1
-/*! \file */
+/*! \file dns/rbt.h */
#include <isc/lang.h>
#include <isc/magic.h>
@@ -37,10 +37,10 @@ ISC_LANG_BEGINDECLS
* Option values for dns_rbt_findnode() and dns_rbt_findname().
* These are used to form a bitmask.
*/
-#define DNS_RBTFIND_NOOPTIONS 0x00
-#define DNS_RBTFIND_EMPTYDATA 0x01
-#define DNS_RBTFIND_NOEXACT 0x02
-#define DNS_RBTFIND_NOPREDECESSOR 0x04
+#define DNS_RBTFIND_NOOPTIONS 0x00
+#define DNS_RBTFIND_EMPTYDATA 0x01
+#define DNS_RBTFIND_NOEXACT 0x02
+#define DNS_RBTFIND_NOPREDECESSOR 0x04
/*@}*/
#ifndef DNS_RBT_USEISCREFCOUNT
@@ -52,14 +52,14 @@ ISC_LANG_BEGINDECLS
/*
* These should add up to 30.
*/
-#define DNS_RBT_LOCKLENGTH 10
-#define DNS_RBT_REFLENGTH 20
+#define DNS_RBT_LOCKLENGTH 10
+#define DNS_RBT_REFLENGTH 20
-#define DNS_RBTNODE_MAGIC ISC_MAGIC('R','B','N','O')
+#define DNS_RBTNODE_MAGIC ISC_MAGIC('R','B','N','O')
#if DNS_RBT_USEMAGIC
-#define DNS_RBTNODE_VALID(n) ISC_MAGIC_VALID(n, DNS_RBTNODE_MAGIC)
+#define DNS_RBTNODE_VALID(n) ISC_MAGIC_VALID(n, DNS_RBTNODE_MAGIC)
#else
-#define DNS_RBTNODE_VALID(n) ISC_TRUE
+#define DNS_RBTNODE_VALID(n) ISC_TRUE
#endif
/*%
@@ -69,22 +69,31 @@ ISC_LANG_BEGINDECLS
* appended to this structure. Allocating a contiguous block of memory for
* multiple dns_rbtnode structures will not work.
*/
-typedef struct dns_rbtnode {
+typedef struct dns_rbtnode dns_rbtnode_t;
+struct dns_rbtnode {
#if DNS_RBT_USEMAGIC
unsigned int magic;
#endif
- struct dns_rbtnode *parent;
- struct dns_rbtnode *left;
- struct dns_rbtnode *right;
- struct dns_rbtnode *down;
+ dns_rbtnode_t *parent;
+ dns_rbtnode_t *left;
+ dns_rbtnode_t *right;
+ dns_rbtnode_t *down;
#ifdef DNS_RBT_USEHASH
- struct dns_rbtnode *hashnext;
+ dns_rbtnode_t *hashnext;
#endif
+
+ /*%
+ * Used for LRU cache. This linked list is used to mark nodes which
+ * have no data any longer, but we cannot unlink at that exact moment
+ * because we did not or could not obtain a write lock on the tree.
+ */
+ ISC_LINK(dns_rbtnode_t) deadlink;
+
/*@{*/
/*!
* The following bitfields add up to a total bitwidth of 32.
* The range of values necessary for each item is indicated,
- * but in the case of "attributes" the field is wider to accomodate
+ * but in the case of "attributes" the field is wider to accommodate
* possible future expansion. "offsetlen" could be one bit
* narrower by always adjusting its value by 1 to find the real
* offsetlen, but doing so does not gain anything (except perhaps
@@ -93,13 +102,14 @@ typedef struct dns_rbtnode {
* In each case below the "range" indicated is what's _necessary_ for
* the bitfield to hold, not what it actually _can_ hold.
*/
- unsigned int is_root : 1; /*%< range is 0..1 */
- unsigned int color : 1; /*%< range is 0..1 */
- unsigned int find_callback : 1; /*%< range is 0..1 */
- unsigned int attributes : 4; /*%< range is 0..2 */
- unsigned int namelen : 8; /*%< range is 1..255 */
- unsigned int offsetlen : 8; /*%< range is 1..128 */
- unsigned int padbytes : 9; /*%< range is 0..380 */
+ unsigned int is_root : 1; /*%< range is 0..1 */
+ unsigned int color : 1; /*%< range is 0..1 */
+ unsigned int find_callback : 1; /*%< range is 0..1 */
+ unsigned int attributes : 3; /*%< range is 0..2 */
+ unsigned int nsec3 : 1; /*%< range is 0..1 */
+ unsigned int namelen : 8; /*%< range is 1..255 */
+ unsigned int offsetlen : 8; /*%< range is 1..128 */
+ unsigned int padbytes : 9; /*%< range is 0..380 */
/*@}*/
#ifdef DNS_RBT_USEHASH
@@ -121,14 +131,14 @@ typedef struct dns_rbtnode {
isc_refcount_t references; /* note that this is not in the bitfield */
#endif
/*@}*/
-} dns_rbtnode_t;
+};
typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node,
dns_name_t *name,
void *callback_arg);
/*****
- ***** Chain Info
+ ***** Chain Info
*****/
/*!
@@ -145,7 +155,7 @@ typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node,
* tree when a node is added). The obvious implication of this is that for a
* chain to remain valid, the tree has to be locked down against writes for the
* duration of the useful life of the chain, because additions or removals can
- * change the path from the root to the node the chain has targetted.
+ * change the path from the root to the node the chain has targeted.
*
* The dns_rbtnodechain_ functions _first, _last, _prev and _next all take
* dns_name_t parameters for the name and the origin, which can be NULL. If
@@ -182,15 +192,15 @@ typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node,
#define DNS_RBT_LEVELBLOCK 254
typedef struct dns_rbtnodechain {
- unsigned int magic;
- isc_mem_t * mctx;
+ unsigned int magic;
+ isc_mem_t * mctx;
/*%
* The terminal node of the chain. It is not in levels[].
* This is ostensibly private ... but in a pinch it could be
* used tell that the chain points nowhere without needing to
* call dns_rbtnodechain_current().
*/
- dns_rbtnode_t * end;
+ dns_rbtnode_t * end;
/*%
* The maximum number of labels in a name is 128; bitstrings mean
* a conceptually very large number (which I have not bothered to
@@ -199,7 +209,7 @@ typedef struct dns_rbtnodechain {
* labels in a name to 255, meaning only 254 pointers are needed
* in the worst case.
*/
- dns_rbtnode_t * levels[DNS_RBT_LEVELBLOCK];
+ dns_rbtnode_t * levels[DNS_RBT_LEVELBLOCK];
/*%
* level_count indicates how deep the chain points into the
* tree of trees, and is the index into the levels[] array.
@@ -208,7 +218,7 @@ typedef struct dns_rbtnodechain {
* a level_count of 0, the first level has a level_count of 1, and
* so on.
*/
- unsigned int level_count;
+ unsigned int level_count;
/*%
* level_matches tells how many levels matched above the node
* returned by dns_rbt_findnode(). A match (partial or exact) found
@@ -216,7 +226,7 @@ typedef struct dns_rbtnodechain {
* This is used by the rbtdb to set the start point for a recursive
* search of superdomains until the RR it is looking for is found.
*/
- unsigned int level_matches;
+ unsigned int level_matches;
} dns_rbtnodechain_t;
/*****
@@ -229,27 +239,27 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
* Initialize a red-black tree of trees.
*
* Notes:
- *\li The deleter argument, if non-null, points to a function that is
- * responsible for cleaning up any memory associated with the data
- * pointer of a node when the node is deleted. It is passed the
- * deleted node's data pointer as its first argument and deleter_arg
- * as its second argument.
+ *\li The deleter argument, if non-null, points to a function that is
+ * responsible for cleaning up any memory associated with the data
+ * pointer of a node when the node is deleted. It is passed the
+ * deleted node's data pointer as its first argument and deleter_arg
+ * as its second argument.
*
* Requires:
- * \li mctx is a pointer to a valid memory context.
- *\li rbtp != NULL && *rbtp == NULL
- *\li arg == NULL iff deleter == NULL
+ * \li mctx is a pointer to a valid memory context.
+ *\li rbtp != NULL && *rbtp == NULL
+ *\li arg == NULL iff deleter == NULL
*
* Ensures:
- *\li If result is ISC_R_SUCCESS:
- * *rbtp points to a valid red-black tree manager
+ *\li If result is ISC_R_SUCCESS:
+ * *rbtp points to a valid red-black tree manager
*
- *\li If result is failure:
- * *rbtp does not point to a valid red-black tree manager.
+ *\li If result is failure:
+ * *rbtp does not point to a valid red-black tree manager.
*
* Returns:
- *\li #ISC_R_SUCCESS Success
- *\li #ISC_R_NOMEMORY Resource limit: Out of Memory
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource limit: Out of Memory
*/
isc_result_t
@@ -258,38 +268,38 @@ dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data);
* Add 'name' to the tree of trees, associated with 'data'.
*
* Notes:
- *\li 'data' is never required to be non-NULL, but specifying it
- * when the name is added is faster than searching for 'name'
- * again and then setting the data pointer. The lack of a data pointer
- * for a node also has other ramifications regarding whether
- * dns_rbt_findname considers a node to exist, or dns_rbt_deletename
- * joins nodes.
+ *\li 'data' is never required to be non-NULL, but specifying it
+ * when the name is added is faster than searching for 'name'
+ * again and then setting the data pointer. The lack of a data pointer
+ * for a node also has other ramifications regarding whether
+ * dns_rbt_findname considers a node to exist, or dns_rbt_deletename
+ * joins nodes.
*
* Requires:
- *\li rbt is a valid rbt manager.
- *\li dns_name_isabsolute(name) == TRUE
+ *\li rbt is a valid rbt manager.
+ *\li dns_name_isabsolute(name) == TRUE
*
* Ensures:
- *\li 'name' is not altered in any way.
+ *\li 'name' is not altered in any way.
*
- *\li Any external references to nodes in the tree are unaffected by
- * node splits that are necessary to insert the new name.
+ *\li Any external references to nodes in the tree are unaffected by
+ * node splits that are necessary to insert the new name.
*
- *\li If result is #ISC_R_SUCCESS:
- * 'name' is findable in the red/black tree of trees in O(log N).
- * The data pointer of the node for 'name' is set to 'data'.
+ *\li If result is #ISC_R_SUCCESS:
+ * 'name' is findable in the red/black tree of trees in O(log N).
+ * The data pointer of the node for 'name' is set to 'data'.
*
- *\li If result is #ISC_R_EXISTS or #ISC_R_NOSPACE:
- * The tree of trees is unaltered.
+ *\li If result is #ISC_R_EXISTS or #ISC_R_NOSPACE:
+ * The tree of trees is unaltered.
*
- *\li If result is #ISC_R_NOMEMORY:
- * No guarantees.
+ *\li If result is #ISC_R_NOMEMORY:
+ * No guarantees.
*
* Returns:
- *\li #ISC_R_SUCCESS Success
- *\li #ISC_R_EXISTS The name already exists with associated data.
- *\li #ISC_R_NOSPACE The name had more logical labels than are allowed.
- *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_EXISTS The name already exists with associated data.
+ *\li #ISC_R_NOSPACE The name had more logical labels than are allowed.
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory
*/
isc_result_t
@@ -299,31 +309,31 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep);
* Just like dns_rbt_addname, but returns the address of the node.
*
* Requires:
- *\li rbt is a valid rbt structure.
- *\li dns_name_isabsolute(name) == TRUE
- *\li nodep != NULL && *nodep == NULL
+ *\li rbt is a valid rbt structure.
+ *\li dns_name_isabsolute(name) == TRUE
+ *\li nodep != NULL && *nodep == NULL
*
* Ensures:
- *\li 'name' is not altered in any way.
+ *\li 'name' is not altered in any way.
*
- *\li Any external references to nodes in the tree are unaffected by
- * node splits that are necessary to insert the new name.
+ *\li Any external references to nodes in the tree are unaffected by
+ * node splits that are necessary to insert the new name.
*
- *\li If result is ISC_R_SUCCESS:
- * 'name' is findable in the red/black tree of trees in O(log N).
- * *nodep is the node that was added for 'name'.
+ *\li If result is ISC_R_SUCCESS:
+ * 'name' is findable in the red/black tree of trees in O(log N).
+ * *nodep is the node that was added for 'name'.
*
- *\li If result is ISC_R_EXISTS:
- * The tree of trees is unaltered.
- * *nodep is the existing node for 'name'.
+ *\li If result is ISC_R_EXISTS:
+ * The tree of trees is unaltered.
+ * *nodep is the existing node for 'name'.
*
- *\li If result is ISC_R_NOMEMORY:
- * No guarantees.
+ *\li If result is ISC_R_NOMEMORY:
+ * No guarantees.
*
* Returns:
- *\li #ISC_R_SUCCESS Success
- *\li #ISC_R_EXISTS The name already exists, possibly without data.
- *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_EXISTS The name already exists, possibly without data.
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory
*/
isc_result_t
@@ -333,36 +343,36 @@ dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
* Get the data pointer associated with 'name'.
*
* Notes:
- *\li When #DNS_RBTFIND_NOEXACT is set, the closest matching superdomain is
+ *\li When #DNS_RBTFIND_NOEXACT is set, the closest matching superdomain is
* returned (also subject to #DNS_RBTFIND_EMPTYDATA), even when there is
- * an exact match in the tree.
+ * an exact match in the tree.
*
*\li A node that has no data is considered not to exist for this function,
* unless the #DNS_RBTFIND_EMPTYDATA option is set.
*
* Requires:
- *\li rbt is a valid rbt manager.
- *\li dns_name_isabsolute(name) == TRUE
- *\li data != NULL && *data == NULL
+ *\li rbt is a valid rbt manager.
+ *\li dns_name_isabsolute(name) == TRUE
+ *\li data != NULL && *data == NULL
*
* Ensures:
- *\li 'name' and the tree are not altered in any way.
+ *\li 'name' and the tree are not altered in any way.
*
- *\li If result is ISC_R_SUCCESS:
- * *data is the data associated with 'name'.
+ *\li If result is ISC_R_SUCCESS:
+ * *data is the data associated with 'name'.
*
- *\li If result is DNS_R_PARTIALMATCH:
- * *data is the data associated with the deepest superdomain
- * of 'name' which has data.
+ *\li If result is DNS_R_PARTIALMATCH:
+ * *data is the data associated with the deepest superdomain
+ * of 'name' which has data.
*
- *\li If result is ISC_R_NOTFOUND:
- * Neither the name nor a superdomain was found with data.
+ *\li If result is ISC_R_NOTFOUND:
+ * Neither the name nor a superdomain was found with data.
*
* Returns:
- *\li #ISC_R_SUCCESS Success
- *\li #DNS_R_PARTIALMATCH Superdomain found with data
- *\li #ISC_R_NOTFOUND No match
- *\li #ISC_R_NOSPACE Concatenating nodes to form foundname failed
+ *\li #ISC_R_SUCCESS Success
+ *\li #DNS_R_PARTIALMATCH Superdomain found with data
+ *\li #ISC_R_NOTFOUND No match
+ *\li #ISC_R_NOSPACE Concatenating nodes to form foundname failed
*/
isc_result_t
@@ -374,100 +384,100 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
* Find the node for 'name'.
*
* Notes:
- *\li A node that has no data is considered not to exist for this function,
- * unless the DNS_RBTFIND_EMPTYDATA option is set. This applies to both
- * exact matches and partial matches.
- *
- *\li If the chain parameter is non-NULL, then the path through the tree
- * to the DNSSEC predecessor of the searched for name is maintained,
- * unless the DNS_RBTFIND_NOPREDECESSOR or DNS_RBTFIND_NOEXACT option
- * is used. (For more details on those options, see below.)
- *
- *\li If there is no predecessor, then the chain will point to nowhere, as
- * indicated by chain->end being NULL or dns_rbtnodechain_current
- * returning ISC_R_NOTFOUND. Note that in a normal Internet DNS RBT
- * there will always be a predecessor for all names except the root
- * name, because '.' will exist and '.' is the predecessor of
- * everything. But you can certainly construct a trivial tree and a
- * search for it that has no predecessor.
- *
- *\li Within the chain structure, the 'levels' member of the structure holds
- * the root node of each level except the first.
- *
- *\li The 'level_count' of the chain indicates how deep the chain to the
- * predecessor name is, as an index into the 'levels[]' array. It does
- * not count name elements, per se, but only levels of the tree of trees,
- * the distinction arrising because multiple labels from a name can be
- * stored on only one level. It is also does not include the level
- * that has the node, since that level is not stored in levels[].
- *
- *\li The chain's 'level_matches' is not directly related to the predecessor.
- * It is the number of levels above the level of the found 'node',
- * regardless of whether it was a partial match or exact match. When
- * the node is found in the top level tree, or no node is found at all,
- * level_matches is 0.
- *
- *\li When DNS_RBTFIND_NOEXACT is set, the closest matching superdomain is
+ *\li A node that has no data is considered not to exist for this function,
+ * unless the DNS_RBTFIND_EMPTYDATA option is set. This applies to both
+ * exact matches and partial matches.
+ *
+ *\li If the chain parameter is non-NULL, then the path through the tree
+ * to the DNSSEC predecessor of the searched for name is maintained,
+ * unless the DNS_RBTFIND_NOPREDECESSOR or DNS_RBTFIND_NOEXACT option
+ * is used. (For more details on those options, see below.)
+ *
+ *\li If there is no predecessor, then the chain will point to nowhere, as
+ * indicated by chain->end being NULL or dns_rbtnodechain_current
+ * returning ISC_R_NOTFOUND. Note that in a normal Internet DNS RBT
+ * there will always be a predecessor for all names except the root
+ * name, because '.' will exist and '.' is the predecessor of
+ * everything. But you can certainly construct a trivial tree and a
+ * search for it that has no predecessor.
+ *
+ *\li Within the chain structure, the 'levels' member of the structure holds
+ * the root node of each level except the first.
+ *
+ *\li The 'level_count' of the chain indicates how deep the chain to the
+ * predecessor name is, as an index into the 'levels[]' array. It does
+ * not count name elements, per se, but only levels of the tree of trees,
+ * the distinction arising because multiple labels from a name can be
+ * stored on only one level. It is also does not include the level
+ * that has the node, since that level is not stored in levels[].
+ *
+ *\li The chain's 'level_matches' is not directly related to the predecessor.
+ * It is the number of levels above the level of the found 'node',
+ * regardless of whether it was a partial match or exact match. When
+ * the node is found in the top level tree, or no node is found at all,
+ * level_matches is 0.
+ *
+ *\li When DNS_RBTFIND_NOEXACT is set, the closest matching superdomain is
* returned (also subject to DNS_RBTFIND_EMPTYDATA), even when
* there is an exact match in the tree. In this case, the chain
- * will not point to the DNSSEC predecessor, but will instead point
- * to the exact match, if there was any. Thus the preceding paragraphs
- * should have "exact match" substituted for "predecessor" to describe
- * how the various elements of the chain are set. This was done to
- * ensure that the chain's state was sane, and to prevent problems that
- * occurred when running the predecessor location code under conditions
- * it was not designed for. It is not clear *where* the chain should
- * point when DNS_RBTFIND_NOEXACT is set, so if you end up using a chain
- * with this option because you want a particular node, let us know
- * where you want the chain pointed, so this can be made more firm.
+ * will not point to the DNSSEC predecessor, but will instead point
+ * to the exact match, if there was any. Thus the preceding paragraphs
+ * should have "exact match" substituted for "predecessor" to describe
+ * how the various elements of the chain are set. This was done to
+ * ensure that the chain's state was sane, and to prevent problems that
+ * occurred when running the predecessor location code under conditions
+ * it was not designed for. It is not clear *where* the chain should
+ * point when DNS_RBTFIND_NOEXACT is set, so if you end up using a chain
+ * with this option because you want a particular node, let us know
+ * where you want the chain pointed, so this can be made more firm.
*
* Requires:
- *\li rbt is a valid rbt manager.
- *\li dns_name_isabsolute(name) == TRUE.
- *\li node != NULL && *node == NULL.
- *\li #DNS_RBTFIND_NOEXACT and DNS_RBTFIND_NOPREDECESSOR are mutally
- * exclusive.
+ *\li rbt is a valid rbt manager.
+ *\li dns_name_isabsolute(name) == TRUE.
+ *\li node != NULL && *node == NULL.
+ *\li #DNS_RBTFIND_NOEXACT and DNS_RBTFIND_NOPREDECESSOR are mutually
+ * exclusive.
*
* Ensures:
- *\li 'name' and the tree are not altered in any way.
+ *\li 'name' and the tree are not altered in any way.
*
- *\li If result is ISC_R_SUCCESS:
+ *\li If result is ISC_R_SUCCESS:
*\verbatim
- * *node is the terminal node for 'name'.
+ * *node is the terminal node for 'name'.
- * 'foundname' and 'name' represent the same name (though not
- * the same memory).
+ * 'foundname' and 'name' represent the same name (though not
+ * the same memory).
- * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
+ * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
*
- * chain->level_matches and chain->level_count are equal.
+ * chain->level_matches and chain->level_count are equal.
*\endverbatim
*
- * If result is DNS_R_PARTIALMATCH:
+ * If result is DNS_R_PARTIALMATCH:
*\verbatim
- * *node is the data associated with the deepest superdomain
- * of 'name' which has data.
+ * *node is the data associated with the deepest superdomain
+ * of 'name' which has data.
*
- * 'foundname' is the name of deepest superdomain (which has
- * data, unless the DNS_RBTFIND_EMPTYDATA option is set).
+ * 'foundname' is the name of deepest superdomain (which has
+ * data, unless the DNS_RBTFIND_EMPTYDATA option is set).
*
- * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
+ * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
*\endverbatim
*
- *\li If result is ISC_R_NOTFOUND:
+ *\li If result is ISC_R_NOTFOUND:
*\verbatim
- * Neither the name nor a superdomain was found. *node is NULL.
+ * Neither the name nor a superdomain was found. *node is NULL.
*
- * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
+ * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
*
- * chain->level_matches is 0.
+ * chain->level_matches is 0.
*\endverbatim
*
* Returns:
- *\li #ISC_R_SUCCESS Success
- *\li #DNS_R_PARTIALMATCH Superdomain found with data
- *\li #ISC_R_NOTFOUND No match, or superdomain with no data
- *\li #ISC_R_NOSPACE Concatenating nodes to form foundname failed
+ *\li #ISC_R_SUCCESS Success
+ *\li #DNS_R_PARTIALMATCH Superdomain found with data
+ *\li #ISC_R_NOTFOUND No match, or superdomain with no data
+ *\li #ISC_R_NOSPACE Concatenating nodes to form foundname failed
*/
isc_result_t
@@ -476,41 +486,41 @@ dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse);
* Delete 'name' from the tree of trees.
*
* Notes:
- *\li When 'name' is removed, if recurse is ISC_TRUE then all of its
+ *\li When 'name' is removed, if recurse is ISC_TRUE then all of its
* subnames are removed too.
*
* Requires:
- *\li rbt is a valid rbt manager.
- *\li dns_name_isabsolute(name) == TRUE
+ *\li rbt is a valid rbt manager.
+ *\li dns_name_isabsolute(name) == TRUE
*
* Ensures:
- *\li 'name' is not altered in any way.
+ *\li 'name' is not altered in any way.
*
- *\li Does NOT ensure that any external references to nodes in the tree
- * are unaffected by node joins.
+ *\li Does NOT ensure that any external references to nodes in the tree
+ * are unaffected by node joins.
*
- *\li If result is ISC_R_SUCCESS:
- * 'name' does not appear in the tree with data; however,
- * the node for the name might still exist which can be
- * found with dns_rbt_findnode (but not dns_rbt_findname).
+ *\li If result is ISC_R_SUCCESS:
+ * 'name' does not appear in the tree with data; however,
+ * the node for the name might still exist which can be
+ * found with dns_rbt_findnode (but not dns_rbt_findname).
*
- *\li If result is ISC_R_NOTFOUND:
- * 'name' does not appear in the tree with data, because
- * it did not appear in the tree before the function was called.
+ *\li If result is ISC_R_NOTFOUND:
+ * 'name' does not appear in the tree with data, because
+ * it did not appear in the tree before the function was called.
*
- *\li If result is something else:
- * See result codes for dns_rbt_findnode (if it fails, the
- * node is not deleted) or dns_rbt_deletenode (if it fails,
- * the node is deleted, but the tree is not optimized when
- * it could have been).
+ *\li If result is something else:
+ * See result codes for dns_rbt_findnode (if it fails, the
+ * node is not deleted) or dns_rbt_deletenode (if it fails,
+ * the node is deleted, but the tree is not optimized when
+ * it could have been).
*
* Returns:
- *\li #ISC_R_SUCCESS Success
- *\li #ISC_R_NOTFOUND No match
- *\li something_else Any return code from dns_rbt_findnode except
- * DNS_R_PARTIALMATCH (which causes ISC_R_NOTFOUND
- * to be returned instead), and any code from
- * dns_rbt_deletenode.
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOTFOUND No match
+ *\li something_else Any return code from dns_rbt_findnode except
+ * DNS_R_PARTIALMATCH (which causes ISC_R_NOTFOUND
+ * to be returned instead), and any code from
+ * dns_rbt_deletenode.
*/
isc_result_t
@@ -519,32 +529,32 @@ dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse);
* Delete 'node' from the tree of trees.
*
* Notes:
- *\li When 'node' is removed, if recurse is ISC_TRUE then all nodes
- * in levels down from it are removed too.
+ *\li When 'node' is removed, if recurse is ISC_TRUE then all nodes
+ * in levels down from it are removed too.
*
* Requires:
- *\li rbt is a valid rbt manager.
- *\li node != NULL.
+ *\li rbt is a valid rbt manager.
+ *\li node != NULL.
*
* Ensures:
- *\li Does NOT ensure that any external references to nodes in the tree
- * are unaffected by node joins.
+ *\li Does NOT ensure that any external references to nodes in the tree
+ * are unaffected by node joins.
*
- *\li If result is ISC_R_SUCCESS:
- * 'node' does not appear in the tree with data; however,
- * the node might still exist if it serves as a pointer to
- * a lower tree level as long as 'recurse' was false, hence
- * the node could can be found with dns_rbt_findnode whem
- * that function's empty_data_ok parameter is true.
+ *\li If result is ISC_R_SUCCESS:
+ * 'node' does not appear in the tree with data; however,
+ * the node might still exist if it serves as a pointer to
+ * a lower tree level as long as 'recurse' was false, hence
+ * the node could can be found with dns_rbt_findnode when
+ * that function's empty_data_ok parameter is true.
*
- *\li If result is ISC_R_NOMEMORY or ISC_R_NOSPACE:
- * The node was deleted, but the tree structure was not
- * optimized.
+ *\li If result is ISC_R_NOMEMORY or ISC_R_NOSPACE:
+ * The node was deleted, but the tree structure was not
+ * optimized.
*
* Returns:
- *\li #ISC_R_SUCCESS Success
- *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory when joining nodes.
- *\li #ISC_R_NOSPACE dns_name_concatenate failed when joining nodes.
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory when joining nodes.
+ *\li #ISC_R_NOSPACE dns_name_concatenate failed when joining nodes.
*/
void
@@ -553,24 +563,24 @@ dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name);
* Convert the sequence of labels stored at 'node' into a 'name'.
*
* Notes:
- *\li This function does not return the full name, from the root, but
- * just the labels at the indicated node.
+ *\li This function does not return the full name, from the root, but
+ * just the labels at the indicated node.
*
- *\li The name data pointed to by 'name' is the information stored
- * in the node, not a copy. Altering the data at this pointer
- * will likely cause grief.
+ *\li The name data pointed to by 'name' is the information stored
+ * in the node, not a copy. Altering the data at this pointer
+ * will likely cause grief.
*
* Requires:
- * \li name->offsets == NULL
+ * \li name->offsets == NULL
*
* Ensures:
- * \li 'name' is DNS_NAMEATTR_READONLY.
+ * \li 'name' is DNS_NAMEATTR_READONLY.
*
- * \li 'name' will point directly to the labels stored after the
- * dns_rbtnode_t struct.
+ * \li 'name' will point directly to the labels stored after the
+ * dns_rbtnode_t struct.
*
- * \li 'name' will have offsets that also point to the information stored
- * as part of the node.
+ * \li 'name' will have offsets that also point to the information stored
+ * as part of the node.
*/
isc_result_t
@@ -579,18 +589,18 @@ dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name);
* Like dns_rbt_namefromnode, but returns the full name from the root.
*
* Notes:
- * \li Unlike dns_rbt_namefromnode, the name will not point directly
- * to node data. Rather, dns_name_concatenate will be used to copy
- * the name data from each node into the 'name' argument.
+ * \li Unlike dns_rbt_namefromnode, the name will not point directly
+ * to node data. Rather, dns_name_concatenate will be used to copy
+ * the name data from each node into the 'name' argument.
*
* Requires:
- * \li name != NULL
- * \li name has a dedicated buffer.
+ * \li name != NULL
+ * \li name has a dedicated buffer.
*
* Returns:
- * \li ISC_R_SUCCESS
- * \li ISC_R_NOSPACE (possible via dns_name_concatenate)
- * \li DNS_R_NAMETOOLONG (possible via dns_name_concatenate)
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOSPACE (possible via dns_name_concatenate)
+ * \li DNS_R_NAMETOOLONG (possible via dns_name_concatenate)
*/
char *
@@ -600,14 +610,14 @@ dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname,
* Format the full name of a node for printing, using dns_name_format().
*
* Notes:
- * \li 'size' is the length of the printname buffer. This should be
- * DNS_NAME_FORMATSIZE or larger.
+ * \li 'size' is the length of the printname buffer. This should be
+ * DNS_NAME_FORMATSIZE or larger.
*
* Requires:
- * \li node and printname are not NULL.
+ * \li node and printname are not NULL.
*
* Returns:
- * \li The 'printname' pointer.
+ * \li The 'printname' pointer.
*/
unsigned int
@@ -616,7 +626,7 @@ dns_rbt_nodecount(dns_rbt_t *rbt);
* Obtain the number of nodes in the tree of trees.
*
* Requires:
- * \li rbt is a valid rbt manager.
+ * \li rbt is a valid rbt manager.
*/
void
@@ -624,25 +634,25 @@ dns_rbt_destroy(dns_rbt_t **rbtp);
isc_result_t
dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum);
/*%<
- * Stop working with a red-black tree of trees.
+ * Stop working with a red-black tree of trees.
* If 'quantum' is zero then the entire tree will be destroyed.
* If 'quantum' is non zero then up to 'quantum' nodes will be destroyed
* allowing the rbt to be incrementally destroyed by repeated calls to
* dns_rbt_destroy2(). Once dns_rbt_destroy2() has been called no other
* operations than dns_rbt_destroy()/dns_rbt_destroy2() should be
* performed on the tree of trees.
- *
+ *
* Requires:
- * \li *rbt is a valid rbt manager.
+ * \li *rbt is a valid rbt manager.
*
* Ensures on ISC_R_SUCCESS:
- * \li All space allocated by the RBT library has been returned.
+ * \li All space allocated by the RBT library has been returned.
*
- * \li *rbt is invalidated as an rbt manager.
+ * \li *rbt is invalidated as an rbt manager.
*
* Returns:
- * \li ISC_R_SUCCESS
- * \li ISC_R_QUOTA if 'quantum' nodes have been destroyed.
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_QUOTA if 'quantum' nodes have been destroyed.
*/
void
@@ -652,10 +662,10 @@ dns_rbt_printall(dns_rbt_t *rbt);
* tree of trees.
*
* Notes:
- * \li The name stored at each node, along with the node's color, is printed.
- * Then the down pointer, left and right pointers are displayed
- * recursively in turn. NULL down pointers are silently omitted;
- * NULL left and right pointers are printed.
+ * \li The name stored at each node, along with the node's color, is printed.
+ * Then the down pointer, left and right pointers are displayed
+ * recursively in turn. NULL down pointers are silently omitted;
+ * NULL left and right pointers are printed.
*/
/*****
@@ -668,12 +678,12 @@ dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx);
* Initialize 'chain'.
*
* Requires:
- *\li 'chain' is a valid pointer.
+ *\li 'chain' is a valid pointer.
*
- *\li 'mctx' is a valid memory context.
+ *\li 'mctx' is a valid memory context.
*
* Ensures:
- *\li 'chain' is suitable for use.
+ *\li 'chain' is suitable for use.
*/
void
@@ -683,10 +693,10 @@ dns_rbtnodechain_reset(dns_rbtnodechain_t *chain);
* 'chain'.
*
* Requires:
- *\li 'chain' is a valid pointer.
+ *\li 'chain' is a valid pointer.
*
* Ensures:
- *\li 'chain' is suitable for use, and uses no dynamic storage.
+ *\li 'chain' is suitable for use, and uses no dynamic storage.
*/
void
@@ -695,15 +705,15 @@ dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain);
* Free any dynamic storage associated with 'chain', and then invalidates it.
*
* Notes:
- *\li Future calls to any dns_rbtnodechain_ function will need to call
- * dns_rbtnodechain_init on the chain first (except, of course,
- * dns_rbtnodechain_init itself).
+ *\li Future calls to any dns_rbtnodechain_ function will need to call
+ * dns_rbtnodechain_init on the chain first (except, of course,
+ * dns_rbtnodechain_init itself).
*
* Requires:
- *\li 'chain' is a valid chain.
+ *\li 'chain' is a valid chain.
*
* Ensures:
- *\li 'chain' is no longer suitable for use, and uses no dynamic storage.
+ *\li 'chain' is no longer suitable for use, and uses no dynamic storage.
*/
isc_result_t
@@ -713,37 +723,37 @@ dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
* Provide the name, origin and node to which the chain is currently pointed.
*
* Notes:
- *\li The tree need not have be locked against additions for the chain
- * to remain valid, however there are no guarantees if any deletion
- * has been made since the chain was established.
+ *\li The tree need not have be locked against additions for the chain
+ * to remain valid, however there are no guarantees if any deletion
+ * has been made since the chain was established.
*
* Requires:
- *\li 'chain' is a valid chain.
+ *\li 'chain' is a valid chain.
*
* Ensures:
- *\li 'node', if non-NULL, is the node to which the chain was pointed
- * by dns_rbt_findnode, dns_rbtnodechain_first or dns_rbtnodechain_last.
- * If none were called for the chain since it was initialized or reset,
- * or if the was no predecessor to the name searched for with
- * dns_rbt_findnode, then '*node' is NULL and ISC_R_NOTFOUND is returned.
+ *\li 'node', if non-NULL, is the node to which the chain was pointed
+ * by dns_rbt_findnode, dns_rbtnodechain_first or dns_rbtnodechain_last.
+ * If none were called for the chain since it was initialized or reset,
+ * or if the was no predecessor to the name searched for with
+ * dns_rbt_findnode, then '*node' is NULL and ISC_R_NOTFOUND is returned.
*
- *\li 'name', if non-NULL, is the name stored at the terminal level of
- * the chain. This is typically a single label, like the "www" of
- * "www.isc.org", but need not be so. At the root of the tree of trees,
- * if the node is "." then 'name' is ".", otherwise it is relative to ".".
- * (Minimalist and atypical case: if the tree has just the name
- * "isc.org." then the root node's stored name is "isc.org." but 'name'
- * will be "isc.org".)
+ *\li 'name', if non-NULL, is the name stored at the terminal level of
+ * the chain. This is typically a single label, like the "www" of
+ * "www.isc.org", but need not be so. At the root of the tree of trees,
+ * if the node is "." then 'name' is ".", otherwise it is relative to ".".
+ * (Minimalist and atypical case: if the tree has just the name
+ * "isc.org." then the root node's stored name is "isc.org." but 'name'
+ * will be "isc.org".)
*
- *\li 'origin', if non-NULL, is the sequence of labels in the levels
- * above the terminal level, such as "isc.org." in the above example.
- * 'origin' is always "." for the root node.
+ *\li 'origin', if non-NULL, is the sequence of labels in the levels
+ * above the terminal level, such as "isc.org." in the above example.
+ * 'origin' is always "." for the root node.
*
*
* Returns:
- *\li #ISC_R_SUCCESS name, origin & node were successfully set.
- *\li #ISC_R_NOTFOUND The chain does not point to any node.
- *\li &lt;something_else> Any error return from dns_name_concatenate.
+ *\li #ISC_R_SUCCESS name, origin & node were successfully set.
+ *\li #ISC_R_NOTFOUND The chain does not point to any node.
+ *\li &lt;something_else> Any error return from dns_name_concatenate.
*/
isc_result_t
@@ -753,23 +763,23 @@ dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
* Set the chain to the lexically first node in the tree of trees.
*
* Notes:
- *\li By the definition of ordering for DNS names, the root of the tree of
- * trees is the very first node, since everything else in the megatree
- * uses it as a common suffix.
+ *\li By the definition of ordering for DNS names, the root of the tree of
+ * trees is the very first node, since everything else in the megatree
+ * uses it as a common suffix.
*
* Requires:
- *\li 'chain' is a valid chain.
- *\li 'rbt' is a valid rbt manager.
+ *\li 'chain' is a valid chain.
+ *\li 'rbt' is a valid rbt manager.
*
* Ensures:
- *\li The chain points to the very first node of the tree.
+ *\li The chain points to the very first node of the tree.
*
- *\li 'name' and 'origin', if non-NULL, are set as described for
- * dns_rbtnodechain_current. Thus 'origin' will always be ".".
+ *\li 'name' and 'origin', if non-NULL, are set as described for
+ * dns_rbtnodechain_current. Thus 'origin' will always be ".".
*
* Returns:
- *\li #DNS_R_NEWORIGIN The name & origin were successfully set.
- *\li &lt;something_else> Any error result from dns_rbtnodechain_current.
+ *\li #DNS_R_NEWORIGIN The name & origin were successfully set.
+ *\li &lt;something_else> Any error result from dns_rbtnodechain_current.
*/
isc_result_t
@@ -779,19 +789,19 @@ dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
* Set the chain to the lexically last node in the tree of trees.
*
* Requires:
- *\li 'chain' is a valid chain.
- *\li 'rbt' is a valid rbt manager.
+ *\li 'chain' is a valid chain.
+ *\li 'rbt' is a valid rbt manager.
*
* Ensures:
- *\li The chain points to the very last node of the tree.
+ *\li The chain points to the very last node of the tree.
*
- *\li 'name' and 'origin', if non-NULL, are set as described for
- * dns_rbtnodechain_current.
+ *\li 'name' and 'origin', if non-NULL, are set as described for
+ * dns_rbtnodechain_current.
*
* Returns:
- *\li #DNS_R_NEWORIGIN The name & origin were successfully set.
- *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory building chain.
- *\li &lt;something_else> Any error result from dns_name_concatenate.
+ *\li #DNS_R_NEWORIGIN The name & origin were successfully set.
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory building chain.
+ *\li &lt;something_else> Any error result from dns_name_concatenate.
*/
isc_result_t
@@ -802,26 +812,26 @@ dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
* is currently pointed.
*
* Requires:
- *\li 'chain' is a valid chain.
- *\li 'chain' has been pointed somewhere in the tree with dns_rbt_findnode,
- * dns_rbtnodechain_first or dns_rbtnodechain_last -- and remember that
- * dns_rbt_findnode is not guaranteed to point the chain somewhere,
- * since there may have been no predecessor to the searched for name.
+ *\li 'chain' is a valid chain.
+ *\li 'chain' has been pointed somewhere in the tree with dns_rbt_findnode,
+ * dns_rbtnodechain_first or dns_rbtnodechain_last -- and remember that
+ * dns_rbt_findnode is not guaranteed to point the chain somewhere,
+ * since there may have been no predecessor to the searched for name.
*
* Ensures:
- *\li The chain is pointed to the predecessor of its current target.
+ *\li The chain is pointed to the predecessor of its current target.
*
- *\li 'name' and 'origin', if non-NULL, are set as described for
- * dns_rbtnodechain_current.
+ *\li 'name' and 'origin', if non-NULL, are set as described for
+ * dns_rbtnodechain_current.
*
- *\li 'origin' is only if a new origin was found.
+ *\li 'origin' is only if a new origin was found.
*
* Returns:
- *\li #ISC_R_SUCCESS The predecessor was found and 'name' was set.
- *\li #DNS_R_NEWORIGIN The predecessor was found with a different
- * origin and 'name' and 'origin' were set.
- *\li #ISC_R_NOMORE There was no predecessor.
- *\li &lt;something_else> Any error result from dns_rbtnodechain_current.
+ *\li #ISC_R_SUCCESS The predecessor was found and 'name' was set.
+ *\li #DNS_R_NEWORIGIN The predecessor was found with a different
+ * origin and 'name' and 'origin' were set.
+ *\li #ISC_R_NOMORE There was no predecessor.
+ *\li &lt;something_else> Any error result from dns_rbtnodechain_current.
*/
isc_result_t
@@ -832,26 +842,39 @@ dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
* is currently pointed.
*
* Requires:
- *\li 'chain' is a valid chain.
- *\li 'chain' has been pointed somewhere in the tree with dns_rbt_findnode,
- * dns_rbtnodechain_first or dns_rbtnodechain_last -- and remember that
- * dns_rbt_findnode is not guaranteed to point the chain somewhere,
- * since there may have been no predecessor to the searched for name.
+ *\li 'chain' is a valid chain.
+ *\li 'chain' has been pointed somewhere in the tree with dns_rbt_findnode,
+ * dns_rbtnodechain_first or dns_rbtnodechain_last -- and remember that
+ * dns_rbt_findnode is not guaranteed to point the chain somewhere,
+ * since there may have been no predecessor to the searched for name.
*
* Ensures:
- *\li The chain is pointed to the successor of its current target.
+ *\li The chain is pointed to the successor of its current target.
*
- *\li 'name' and 'origin', if non-NULL, are set as described for
- * dns_rbtnodechain_current.
+ *\li 'name' and 'origin', if non-NULL, are set as described for
+ * dns_rbtnodechain_current.
*
- *\li 'origin' is only if a new origin was found.
+ *\li 'origin' is only if a new origin was found.
*
* Returns:
- *\li #ISC_R_SUCCESS The successor was found and 'name' was set.
- *\li #DNS_R_NEWORIGIN The successor was found with a different
- * origin and 'name' and 'origin' were set.
- *\li #ISC_R_NOMORE There was no successor.
- *\li &lt;something_else> Any error result from dns_name_concatenate.
+ *\li #ISC_R_SUCCESS The successor was found and 'name' was set.
+ *\li #DNS_R_NEWORIGIN The successor was found with a different
+ * origin and 'name' and 'origin' were set.
+ *\li #ISC_R_NOMORE There was no successor.
+ *\li &lt;something_else> Any error result from dns_name_concatenate.
+ */
+
+isc_result_t
+dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin);
+/*%<
+ * Descend down if possible.
+ */
+
+isc_result_t
+dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
+/*%<
+ * Find the next node at the current depth in DNSSEC order.
*/
/*
@@ -862,53 +885,53 @@ dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
* hiding the back-end. The usage is the same as that of isc_refcount_xxx().
*/
#ifdef DNS_RBT_USEISCREFCOUNT
-#define dns_rbtnode_refinit(node, n) \
- do { \
- isc_refcount_init(&(node)->references, (n)); \
- } while (0)
-#define dns_rbtnode_refdestroy(node) \
- do { \
- isc_refcount_destroy(&(node)->references); \
- } while (0)
-#define dns_rbtnode_refcurrent(node) \
+#define dns_rbtnode_refinit(node, n) \
+ do { \
+ isc_refcount_init(&(node)->references, (n)); \
+ } while (0)
+#define dns_rbtnode_refdestroy(node) \
+ do { \
+ isc_refcount_destroy(&(node)->references); \
+ } while (0)
+#define dns_rbtnode_refcurrent(node) \
isc_refcount_current(&(node)->references)
-#define dns_rbtnode_refincrement0(node, refs) \
- do { \
+#define dns_rbtnode_refincrement0(node, refs) \
+ do { \
isc_refcount_increment0(&(node)->references, (refs)); \
- } while (0)
-#define dns_rbtnode_refincrement(node, refs) \
- do { \
+ } while (0)
+#define dns_rbtnode_refincrement(node, refs) \
+ do { \
isc_refcount_increment(&(node)->references, (refs)); \
- } while (0)
-#define dns_rbtnode_refdecrement(node, refs) \
- do { \
+ } while (0)
+#define dns_rbtnode_refdecrement(node, refs) \
+ do { \
isc_refcount_decrement(&(node)->references, (refs)); \
- } while (0)
+ } while (0)
#else /* DNS_RBT_USEISCREFCOUNT */
-#define dns_rbtnode_refinit(node, n) ((node)->references = (n))
-#define dns_rbtnode_refdestroy(node) (REQUIRE((node)->references == 0))
-#define dns_rbtnode_refcurrent(node) ((node)->references)
-#define dns_rbtnode_refincrement0(node, refs) \
- do { \
- unsigned int *_tmp = (unsigned int *)(refs); \
- (node)->references++; \
- if ((_tmp) != NULL) \
- (*_tmp) = (node)->references; \
- } while (0)
-#define dns_rbtnode_refincrement(node, refs) \
- do { \
- REQUIRE((node)->references > 0); \
- (node)->references++; \
- if ((refs) != NULL) \
- (*refs) = (node)->references; \
- } while (0)
-#define dns_rbtnode_refdecrement(node, refs) \
- do { \
- REQUIRE((node)->references > 0); \
- (node)->references--; \
- if ((refs) != NULL) \
- (*refs) = (node)->references; \
- } while (0)
+#define dns_rbtnode_refinit(node, n) ((node)->references = (n))
+#define dns_rbtnode_refdestroy(node) (REQUIRE((node)->references == 0))
+#define dns_rbtnode_refcurrent(node) ((node)->references)
+#define dns_rbtnode_refincrement0(node, refs) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(refs); \
+ (node)->references++; \
+ if ((_tmp) != NULL) \
+ (*_tmp) = (node)->references; \
+ } while (0)
+#define dns_rbtnode_refincrement(node, refs) \
+ do { \
+ REQUIRE((node)->references > 0); \
+ (node)->references++; \
+ if ((refs) != NULL) \
+ (*refs) = (node)->references; \
+ } while (0)
+#define dns_rbtnode_refdecrement(node, refs) \
+ do { \
+ REQUIRE((node)->references > 0); \
+ (node)->references--; \
+ if ((refs) != NULL) \
+ (*refs) = (node)->references; \
+ } while (0)
#endif /* DNS_RBT_USEISCREFCOUNT */
ISC_LANG_ENDDECLS
diff --git a/lib/dns/include/dns/rcode.h b/lib/dns/include/dns/rcode.h
index 03c145b..94e831b 100644
--- a/lib/dns/include/dns/rcode.h
+++ b/lib/dns/include/dns/rcode.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rcode.h,v 1.13.18.2 2005/04/29 00:16:18 marka Exp $ */
+/* $Id: rcode.h,v 1.21 2008/09/25 04:02:39 tbox Exp $ */
#ifndef DNS_RCODE_H
#define DNS_RCODE_H 1
-/*! \file */
+/*! \file dns/rcode.h */
#include <isc/lang.h>
@@ -93,6 +93,21 @@ isc_result_t dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target);
*\li #ISC_R_NOSPACE target buffer is too small
*/
+isc_result_t
+dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a has algorithm value.
+ *
+ * Requires:
+ *\li 'hashalg' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #DNS_R_UNKNOWN type is unknown
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_RCODE_H */
diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h
index a14bde7..126bc96 100644
--- a/lib/dns/include/dns/rdata.h
+++ b/lib/dns/include/dns/rdata.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdata.h,v 1.60.18.3 2005/05/19 04:59:56 marka Exp $ */
+/* $Id: rdata.h,v 1.70.120.3 2009/02/16 00:29:27 marka Exp $ */
#ifndef DNS_RDATA_H
#define DNS_RDATA_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/rdata.h
* \brief
* Provides facilities for manipulating DNS rdata, including conversions to
* and from wire format and text format.
@@ -49,7 +49,7 @@
* build process from a set of source files, one per rdata type. For
* portability, it's probably best that the building be done by a C
* program. Adding a new rdata type will be a simple matter of adding
- * a file to a directory and rebuilding the server. *All* knowlege of
+ * a file to a directory and rebuilding the server. *All* knowledge of
* the format of a particular rdata type is in this file.
*
* MP:
@@ -124,7 +124,8 @@ struct dns_rdata {
#define DNS_RDATA_INIT { NULL, 0, 0, 0, 0, {(void*)(-1), (void *)(-1)}}
-#define DNS_RDATA_UPDATE 0x0001 /*%< update pseudo record */
+#define DNS_RDATA_UPDATE 0x0001 /*%< update pseudo record. */
+#define DNS_RDATA_OFFLINE 0x0002 /*%< RRSIG has a offline key. */
/*
* Flags affecting rdata formatting style. Flags 0xFFFF0000
@@ -327,11 +328,11 @@ dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
*\li 'target' is a valid region.
*
*\li 'origin' if non NULL it must be absolute.
- *
+ *
*\li 'callbacks' to be NULL or callbacks->warn and callbacks->error be
* initialized.
*
- * Ensures,
+ * Ensures,
* if result is success:
*\li If 'rdata' is not NULL, it is attached to the target.
@@ -384,7 +385,8 @@ dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target);
isc_result_t
dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, unsigned int flags,
- unsigned int width, char *linebreak, isc_buffer_t *target);
+ unsigned int width, const char *linebreak,
+ isc_buffer_t *target);
/*%<
* Like dns_rdata_totext, but do formatted output suitable for
* database dumps. This is intended for use by dns_db_dump();
diff --git a/lib/dns/include/dns/rdataclass.h b/lib/dns/include/dns/rdataclass.h
index fc622bf..786eb6a 100644
--- a/lib/dns/include/dns/rdataclass.h
+++ b/lib/dns/include/dns/rdataclass.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataclass.h,v 1.18.18.2 2005/04/29 00:16:18 marka Exp $ */
+/* $Id: rdataclass.h,v 1.24 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_RDATACLASS_H
#define DNS_RDATACLASS_H 1
-/*! \file */
+/*! \file dns/rdataclass.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/rdatalist.h b/lib/dns/include/dns/rdatalist.h
index 697386f..57debc3 100644
--- a/lib/dns/include/dns/rdatalist.h
+++ b/lib/dns/include/dns/rdatalist.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatalist.h,v 1.14.18.2 2005/04/29 00:16:19 marka Exp $ */
+/* $Id: rdatalist.h,v 1.22 2008/04/03 06:09:05 tbox Exp $ */
#ifndef DNS_RDATALIST_H
#define DNS_RDATALIST_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/rdatalist.h
* \brief
* A DNS rdatalist is a list of rdata of a common type and class.
*
@@ -98,6 +98,27 @@ dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
*\li #ISC_R_SUCCESS
*/
+isc_result_t
+dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
+ dns_rdatalist_t **rdatalist);
+/*%<
+ * Point 'rdatalist' to the rdatalist in 'rdataset'.
+ *
+ * Requires:
+ *
+ *\li 'rdatalist' is a pointer to a NULL dns_rdatalist_t pointer.
+ *
+ *\li 'rdataset' is a valid rdataset associated with an rdatalist.
+ *
+ * Ensures,
+ * on success,
+ *
+ *\li 'rdatalist' is pointed to the rdatalist in rdataset.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_RDATALIST_H */
diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h
index 5597591..baff146 100644
--- a/lib/dns/include/dns/rdataset.h
+++ b/lib/dns/include/dns/rdataset.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataset.h,v 1.51.18.7 2006/03/03 00:56:53 marka Exp $ */
+/* $Id: rdataset.h,v 1.65.50.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/rdataset.h
* \brief
* A DNS rdataset is a handle that can be associated with a collection of
* rdata all having a common owner name, class, and type.
@@ -78,8 +78,14 @@ typedef struct dns_rdatasetmethods {
dns_name_t *name);
isc_result_t (*getnoqname)(dns_rdataset_t *rdataset,
dns_name_t *name,
- dns_rdataset_t *nsec,
- dns_rdataset_t *nsecsig);
+ dns_rdataset_t *neg,
+ dns_rdataset_t *negsig);
+ isc_result_t (*addclosest)(dns_rdataset_t *rdataset,
+ dns_name_t *name);
+ isc_result_t (*getclosest)(dns_rdataset_t *rdataset,
+ dns_name_t *name,
+ dns_rdataset_t *neg,
+ dns_rdataset_t *negsig);
isc_result_t (*getadditional)(dns_rdataset_t *rdataset,
dns_rdatasetadditional_t type,
dns_rdatatype_t qtype,
@@ -140,6 +146,11 @@ struct dns_rdataset {
* increment the counter.
*/
isc_uint32_t count;
+ /*
+ * This RRSIG RRset should be re-generated around this time.
+ * Only valid if DNS_RDATASETATTR_RESIGN is set in attributes.
+ */
+ isc_stdtime_t resign;
/*@{*/
/*%
* These are for use by the rdataset implementation, and MUST NOT
@@ -151,7 +162,9 @@ struct dns_rdataset {
unsigned int privateuint4;
void * private5;
void * private6;
+ void * private7;
/*@}*/
+
};
/*!
@@ -184,6 +197,9 @@ struct dns_rdataset {
#define DNS_RDATASETATTR_CHECKNAMES 0x00008000 /*%< Used by resolver. */
#define DNS_RDATASETATTR_REQUIREDGLUE 0x00010000
#define DNS_RDATASETATTR_LOADORDER 0x00020000
+#define DNS_RDATASETATTR_RESIGN 0x00040000
+#define DNS_RDATASETATTR_CLOSEST 0x00080000
+#define DNS_RDATASETATTR_OPTOUT 0x00100000 /*%< OPTOUT proof */
/*%
* _OMITDNSSEC:
@@ -348,8 +364,8 @@ dns_rdataset_totext(dns_rdataset_t *rdataset,
* Notes:
*\li The rdata cursor position will be changed.
*
- *\li The 'question' flag should normally be #ISC_FALSE. If it is
- * #ISC_TRUE, the TTL and rdata fields are not printed. This is
+ *\li The 'question' flag should normally be #ISC_FALSE. If it is
+ * #ISC_TRUE, the TTL and rdata fields are not printed. This is
* for use when printing an rdata representing a question section.
*
*\li This interface is deprecated; use dns_master_rdatasettottext()
@@ -411,7 +427,7 @@ dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
unsigned int *countp);
/*%<
* Like dns_rdataset_towire(), but sorting the rdatasets according to
- * the integer value returned by 'order' when called witih the rdataset
+ * the integer value returned by 'order' when called with the rdataset
* and 'order_arg' as arguments.
*
* Requires:
@@ -477,14 +493,14 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
- dns_rdataset_t *nsec, dns_rdataset_t *nsecsig);
+ dns_rdataset_t *neg, dns_rdataset_t *negsig);
/*%<
* Return the noqname proof for this record.
*
* Requires:
*\li 'rdataset' to be valid and #DNS_RDATASETATTR_NOQNAME to be set.
*\li 'name' to be valid.
- *\li 'nsec' and 'nsecsig' to be valid and not associated.
+ *\li 'neg' and 'negsig' to be valid and not associated.
*/
isc_result_t
@@ -493,11 +509,37 @@ dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name);
* Associate a noqname proof with this record.
* Sets #DNS_RDATASETATTR_NOQNAME if successful.
* Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and
- * the 'nsec' and 'rrsig(nsec)' ttl.
+ * the 'nsec'/'nsec3' and 'rrsig(nsec)'/'rrsig(nsec3)' ttl.
*
* Requires:
*\li 'rdataset' to be valid and #DNS_RDATASETATTR_NOQNAME to be set.
- *\li 'name' to be valid and have NSEC and RRSIG(NSEC) rdatasets.
+ *\li 'name' to be valid and have NSEC or NSEC3 and associated RRSIG
+ * rdatasets.
+ */
+
+isc_result_t
+dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *nsec, dns_rdataset_t *nsecsig);
+/*%<
+ * Return the closest encloser for this record.
+ *
+ * Requires:
+ *\li 'rdataset' to be valid and #DNS_RDATASETATTR_CLOSEST to be set.
+ *\li 'name' to be valid.
+ *\li 'nsec' and 'nsecsig' to be valid and not associated.
+ */
+
+isc_result_t
+dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name);
+/*%<
+ * Associate a closest encloset proof with this record.
+ * Sets #DNS_RDATASETATTR_CLOSEST if successful.
+ * Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and
+ * the 'nsec' and 'rrsig(nsec)' ttl.
+ *
+ * Requires:
+ *\li 'rdataset' to be valid and #DNS_RDATASETATTR_CLOSEST to be set.
+ *\li 'name' to be valid and have NSEC3 and RRSIG(NSEC3) rdatasets.
*/
isc_result_t
diff --git a/lib/dns/include/dns/rdatasetiter.h b/lib/dns/include/dns/rdatasetiter.h
index b2e13f8..dcde367 100644
--- a/lib/dns/include/dns/rdatasetiter.h
+++ b/lib/dns/include/dns/rdatasetiter.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatasetiter.h,v 1.15.18.2 2005/04/29 00:16:19 marka Exp $ */
+/* $Id: rdatasetiter.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_RDATASETITER_H
#define DNS_RDATASETITER_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/rdatasetiter.h
* \brief
* The DNS Rdataset Iterator interface allows iteration of all of the
* rdatasets at a node.
diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h
index b693a71..3ac44b8 100644
--- a/lib/dns/include/dns/rdataslab.h
+++ b/lib/dns/include/dns/rdataslab.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataslab.h,v 1.25.18.2 2005/04/29 00:16:19 marka Exp $ */
+/* $Id: rdataslab.h,v 1.33 2008/04/01 23:47:10 tbox Exp $ */
#ifndef DNS_RDATASLAB_H
#define DNS_RDATASLAB_H 1
-/*! \file
+/*! \file dns/rdataslab.h
* \brief
* Implements storage of rdatasets into slabs of memory.
*
@@ -57,6 +57,13 @@ ISC_LANG_BEGINDECLS
#define DNS_RDATASLAB_FORCE 0x1
#define DNS_RDATASLAB_EXACT 0x2
+#define DNS_RDATASLAB_OFFLINE 0x01 /* RRSIG is for offline DNSKEY */
+#define DNS_RDATASLAB_WARNMASK 0x0E /*%< RRSIG(DNSKEY) expired
+ * warnings number mask. */
+#define DNS_RDATASLAB_WARNSHIFT 1 /*%< How many bits to shift to find
+ * remaining expired warning number. */
+
+
/***
*** Functions
***/
@@ -146,10 +153,10 @@ dns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2,
*/
isc_boolean_t
dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
- unsigned int reservelen, dns_rdataclass_t rdclass,
+ unsigned int reservelen, dns_rdataclass_t rdclass,
dns_rdatatype_t type);
/*%<
- * Compare two rdataslabs for DNSSEC equality.
+ * Compare two rdataslabs for DNSSEC equality.
*
* Requires:
*\li 'slab1' and 'slab2' point to slabs.
diff --git a/lib/dns/include/dns/rdatatype.h b/lib/dns/include/dns/rdatatype.h
index 40a884d..ba9a92c 100644
--- a/lib/dns/include/dns/rdatatype.h
+++ b/lib/dns/include/dns/rdatatype.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatatype.h,v 1.18.18.2 2005/04/29 00:16:20 marka Exp $ */
+/* $Id: rdatatype.h,v 1.26 2008/09/25 04:02:39 tbox Exp $ */
#ifndef DNS_RDATATYPE_H
#define DNS_RDATATYPE_H 1
-/*! \file */
+/*! \file dns/rdatatype.h */
#include <isc/lang.h>
@@ -71,7 +71,8 @@ dns_rdatatype_format(dns_rdatatype_t rdtype,
* The resulting string is guaranteed to be null-terminated.
*/
-#define DNS_RDATATYPE_FORMATSIZE sizeof("TYPE65535")
+#define DNS_RDATATYPE_FORMATSIZE sizeof("NSEC3PARAM")
+
/*%<
* Minimum size of array to pass to dns_rdatatype_format().
* May need to be adjusted if a new RR type with a very long
diff --git a/lib/dns/include/dns/request.h b/lib/dns/include/dns/request.h
index b858a9e..62a83ca 100644
--- a/lib/dns/include/dns/request.h
+++ b/lib/dns/include/dns/request.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: request.h,v 1.21.18.2 2005/04/29 00:16:20 marka Exp $ */
+/* $Id: request.h,v 1.27.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_REQUEST_H
#define DNS_REQUEST_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/request.h
*
* \brief
* The request module provides simple request/response services useful for
@@ -49,7 +49,7 @@
#define DNS_REQUESTOPT_TCP 0x00000001U
typedef struct dns_requestevent {
- ISC_EVENT_COMMON(struct dns_requestevent);
+ ISC_EVENT_COMMON(struct dns_requestevent);
isc_result_t result;
dns_request_t *request;
} dns_requestevent_t;
@@ -217,7 +217,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
unsigned int udpretries, isc_task_t *task,
isc_taskaction_t action, void *arg,
dns_request_t **requestp);
-/*%<
+/*%<
* Create and send a request.
*
* Notes:
@@ -271,7 +271,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
unsigned int udptimeout, unsigned int udpretries,
isc_task_t *task, isc_taskaction_t action, void *arg,
dns_request_t **requestp);
-/*!<
+/*!<
* \brief Create and send a request.
*
* Notes:
@@ -280,7 +280,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
* #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request
* will timeout after 'timeout' seconds. UDP requests will be resent
* at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero.
- *
+ *
*\li When the request completes, successfully, due to a timeout, or
* because it was canceled, a completion event will be sent to 'task'.
*
@@ -344,7 +344,7 @@ dns_request_usedtcp(dns_request_t *request);
/*%<
* Return whether this query used TCP or not. Setting #DNS_REQUESTOPT_TCP
* in the call to dns_request_create() will cause the function to return
- * #ISC_TRUE, othewise the result is based on the query message size.
+ * #ISC_TRUE, otherwise the result is based on the query message size.
*
* Requires:
*\li 'request' is a valid request.
diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h
index 4e0e6a0..fa837c1 100644
--- a/lib/dns/include/dns/resolver.h
+++ b/lib/dns/include/dns/resolver.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.h,v 1.40.18.11 2006/02/01 22:39:17 marka Exp $ */
+/* $Id: resolver.h,v 1.60.56.3 2009/01/29 22:40:35 jinmei Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/resolver.h
*
* \brief
* This is the BIND 9 resolver, the module responsible for resolving DNS
@@ -93,13 +93,29 @@ typedef struct dns_fetchevent {
#define DNS_FETCHOPT_FORWARDONLY 0x10 /*%< Only use forwarders. */
#define DNS_FETCHOPT_NOVALIDATE 0x20 /*%< Disable validation. */
#define DNS_FETCHOPT_EDNS512 0x40 /*%< Advertise a 512 byte
- UDP buffer. */
+ UDP buffer. */
+#define DNS_FETCHOPT_WANTNSID 0x80 /*%< Request NSID */
#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000
#define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000
#define DNS_FETCHOPT_EDNSVERSIONSHIFT 24
/*
+ * Upper bounds of class of query RTT (ms). Corresponds to
+ * dns_resstatscounter_queryrttX statistics counters.
+ */
+#define DNS_RESOLVER_QRYRTTCLASS0 10
+#define DNS_RESOLVER_QRYRTTCLASS0STR "10"
+#define DNS_RESOLVER_QRYRTTCLASS1 100
+#define DNS_RESOLVER_QRYRTTCLASS1STR "100"
+#define DNS_RESOLVER_QRYRTTCLASS2 500
+#define DNS_RESOLVER_QRYRTTCLASS2STR "500"
+#define DNS_RESOLVER_QRYRTTCLASS3 800
+#define DNS_RESOLVER_QRYRTTCLASS3STR "800"
+#define DNS_RESOLVER_QRYRTTCLASS4 1600
+#define DNS_RESOLVER_QRYRTTCLASS4STR "1600"
+
+/*
* XXXRTH Should this API be made semi-private? (I.e.
* _dns_resolver_create()).
*/
@@ -126,8 +142,6 @@ dns_resolver_create(dns_view_t *view,
*\li Generally, applications should not create a resolver directly, but
* should instead call dns_view_createresolver().
*
- *\li No options are currently defined.
- *
* Requires:
*
*\li 'view' is a valid view.
@@ -348,6 +362,23 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp);
*\li *fetchp == NULL.
*/
+void
+dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
+ isc_logcategory_t *category, isc_logmodule_t *module,
+ int level, isc_boolean_t duplicateok);
+/*%<
+ * Dump a log message on internal state at the completion of given 'fetch'.
+ * 'lctx', 'category', 'module', and 'level' are used to write the log message.
+ * By default, only one log message is written even if the corresponding fetch
+ * context serves multiple clients; if 'duplicateok' is true the suppression
+ * is disabled and the message can be written every time this function is
+ * called.
+ *
+ * Requires:
+ *
+ *\li 'fetch' is a valid fetch, and has completed.
+ */
+
dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver);
@@ -470,10 +501,13 @@ dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
isc_boolean_t
dns_resolver_getzeronosoattl(dns_resolver_t *resolver);
-
+
void
dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state);
+unsigned int
+dns_resolver_getoptions(dns_resolver_t *resolver);
+
ISC_LANG_ENDDECLS
#endif /* DNS_RESOLVER_H */
diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h
index db5481b..ed29bcd 100644
--- a/lib/dns/include/dns/result.h
+++ b/lib/dns/include/dns/result.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.h,v 1.104.10.6 2005/06/17 02:04:32 marka Exp $ */
+/* $Id: result.h,v 1.116 2008/09/25 04:02:39 tbox Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
-/*! \file */
+/*! \file dns/result.h */
#include <isc/lang.h>
#include <isc/resultclass.h>
@@ -147,8 +147,9 @@
#define DNS_R_COVERINGNSEC (ISC_RESULTCLASS_DNS + 101)
#define DNS_R_MXISADDRESS (ISC_RESULTCLASS_DNS + 102)
#define DNS_R_DUPLICATE (ISC_RESULTCLASS_DNS + 103)
+#define DNS_R_INVALIDNSEC3 (ISC_RESULTCLASS_DNS + 104)
-#define DNS_R_NRESULTS 104 /*%< Number of results */
+#define DNS_R_NRESULTS 105 /*%< Number of results */
/*
* DNS wire format rcodes.
diff --git a/lib/dns/include/dns/rootns.h b/lib/dns/include/dns/rootns.h
index a3ddc48..6da3f79 100644
--- a/lib/dns/include/dns/rootns.h
+++ b/lib/dns/include/dns/rootns.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rootns.h,v 1.9.18.3 2005/04/27 05:01:38 sra Exp $ */
+/* $Id: rootns.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_ROOTNS_H
#define DNS_ROOTNS_H 1
-/*! \file */
+/*! \file dns/rootns.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/sdb.h b/lib/dns/include/dns/sdb.h
index de849f9..c850028 100644
--- a/lib/dns/include/dns/sdb.h
+++ b/lib/dns/include/dns/sdb.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdb.h,v 1.15.18.2 2005/04/29 00:16:21 marka Exp $ */
+/* $Id: sdb.h,v 1.21.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_SDB_H
#define DNS_SDB_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/sdb.h
* \brief
* Simple database API.
*/
@@ -127,12 +127,12 @@ dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
* The allnodes function, if non-NULL, fills in an opaque structure to be
* used by a database iterator. This allows the zone to be transferred.
* This may use a considerable amount of memory for large zones, and the
- * zone transfer may not be fully RFC1035 compliant if the zone is
+ * zone transfer may not be fully RFC1035 compliant if the zone is
* frequently changed.
*
* The create function will be called for each zone configured
* into the name server using this database type. It can be used
- * to create a "database object" containg zone specific data,
+ * to create a "database object" containing zone specific data,
* which can make use of the database arguments specified in the
* name server configuration.
*
diff --git a/lib/dns/include/dns/sdlz.h b/lib/dns/include/dns/sdlz.h
index 13ba14a..acb0437 100644
--- a/lib/dns/include/dns/sdlz.h
+++ b/lib/dns/include/dns/sdlz.h
@@ -1,8 +1,8 @@
/*
- * Portions Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -50,9 +50,9 @@
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdlz.h,v 1.2.2.2 2005/09/06 03:47:19 marka Exp $ */
+/* $Id: sdlz.h,v 1.7.332.2 2009/01/18 23:47:41 tbox Exp $ */
-/*! \file */
+/*! \file dns/sdlz.h */
#ifndef SDLZ_H
#define SDLZ_H 1
@@ -148,7 +148,7 @@ typedef void
/*%<
* Method prototype. Drivers implementing the SDLZ interface may
* supply a destroy method. This method is called when the DNS server
- * is shuting down and no longer needs the driver. A SDLZ driver does
+ * is shutting down and no longer needs the driver. A SDLZ driver does
* not have to implement a destroy method.
*/
@@ -173,7 +173,7 @@ typedef isc_result_t
* \li 3) we run out of domain name labels. I.E. we have tried the
* shortest domain name
*
- * \li 4) the number of labels in the domain name is less than min_lables
+ * \li 4) the number of labels in the domain name is less than min_labels
* for dns_dlzfindzone
*
* The driver's find zone method should return ISC_R_SUCCESS if the
diff --git a/lib/dns/include/dns/secalg.h b/lib/dns/include/dns/secalg.h
index 0466d91..2e4fe3e 100644
--- a/lib/dns/include/dns/secalg.h
+++ b/lib/dns/include/dns/secalg.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: secalg.h,v 1.13.18.2 2005/04/29 00:16:21 marka Exp $ */
+/* $Id: secalg.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_SECALG_H
#define DNS_SECALG_H 1
-/*! \file */
+/*! \file dns/secalg.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/secproto.h b/lib/dns/include/dns/secproto.h
index a6cfd5c..b9179c0 100644
--- a/lib/dns/include/dns/secproto.h
+++ b/lib/dns/include/dns/secproto.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: secproto.h,v 1.10.18.2 2005/04/29 00:16:21 marka Exp $ */
+/* $Id: secproto.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_SECPROTO_H
#define DNS_SECPROTO_H 1
-/*! \file */
+/*! \file dns/secproto.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/soa.h b/lib/dns/include/dns/soa.h
index 70c6725..bb56365 100644
--- a/lib/dns/include/dns/soa.h
+++ b/lib/dns/include/dns/soa.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: soa.h,v 1.3.18.2 2005/04/29 00:16:22 marka Exp $ */
+/* $Id: soa.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_SOA_H
#define DNS_SOA_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/soa.h
* \brief
* SOA utilities.
*/
diff --git a/lib/dns/include/dns/ssu.h b/lib/dns/include/dns/ssu.h
index b709030..f013bd0 100644
--- a/lib/dns/include/dns/ssu.h
+++ b/lib/dns/include/dns/ssu.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ssu.h,v 1.13.18.4 2006/02/16 23:51:32 marka Exp $ */
+/* $Id: ssu.h,v 1.24 2008/01/18 23:46:58 tbox Exp $ */
#ifndef DNS_SSU_H
#define DNS_SSU_H 1
-/*! \file */
+/*! \file dns/ssu.h */
#include <isc/lang.h>
@@ -28,14 +28,19 @@
ISC_LANG_BEGINDECLS
-#define DNS_SSUMATCHTYPE_NAME 0
-#define DNS_SSUMATCHTYPE_SUBDOMAIN 1
-#define DNS_SSUMATCHTYPE_WILDCARD 2
-#define DNS_SSUMATCHTYPE_SELF 3
-#define DNS_SSUMATCHTYPE_SELFSUB 4
-#define DNS_SSUMATCHTYPE_SELFWILD 5
-#define DNS_SSUMATCHTYPE_MAX 5 /* maximum defined value */
-
+#define DNS_SSUMATCHTYPE_NAME 0
+#define DNS_SSUMATCHTYPE_SUBDOMAIN 1
+#define DNS_SSUMATCHTYPE_WILDCARD 2
+#define DNS_SSUMATCHTYPE_SELF 3
+#define DNS_SSUMATCHTYPE_SELFSUB 4
+#define DNS_SSUMATCHTYPE_SELFWILD 5
+#define DNS_SSUMATCHTYPE_SELFKRB5 6
+#define DNS_SSUMATCHTYPE_SELFMS 7
+#define DNS_SSUMATCHTYPE_SUBDOMAINMS 8
+#define DNS_SSUMATCHTYPE_SUBDOMAINKRB5 9
+#define DNS_SSUMATCHTYPE_TCPSELF 10
+#define DNS_SSUMATCHTYPE_6TO4SELF 11
+#define DNS_SSUMATCHTYPE_MAX 11 /* max value */
isc_result_t
dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table);
@@ -91,8 +96,8 @@ dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
* at that name.
*
* Notes:
- *\li If 'matchtype' is SELF, this rule only matches if the name
- * to be updated matches the signing identity.
+ *\li If 'matchtype' is of SELF type, this rule only matches if the
+ * name to be updated matches the signing identity.
*
*\li If 'ntypes' is 0, this rule applies to all types except
* NS, SOA, RRSIG, and NSEC.
@@ -114,16 +119,35 @@ dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
isc_boolean_t
dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
- dns_name_t *name, dns_rdatatype_t type);
+ dns_name_t *name, isc_netaddr_t *tcpaddr,
+ dns_rdatatype_t type);
/*%<
* Checks that the attempted update of (name, type) is allowed according
* to the rules specified in the simple-secure-update rule table. If
- * no rules are matched, access is denied. If signer is NULL, access
- * is denied.
+ * no rules are matched, access is denied.
+ *
+ * Notes:
+ * 'tcpaddr' should only be set if the request received
+ * via TCP. This provides a weak assurance that the
+ * request was not spoofed. 'tcpaddr' is to to validate
+ * DNS_SSUMATCHTYPE_TCPSELF and DNS_SSUMATCHTYPE_6TO4SELF
+ * rules.
+ *
+ * For DNS_SSUMATCHTYPE_TCPSELF the addresses are mapped to
+ * the standard reverse names under IN-ADDR.ARPA and IP6.ARPA.
+ * RFC 1035, Section 3.5, "IN-ADDR.ARPA domain" and RFC 3596,
+ * Section 2.5, "IP6.ARPA Domain".
+ *
+ * For DNS_SSUMATCHTYPE_6TO4SELF, IPv4 address are converted
+ * to a 6to4 prefix (48 bits) per the rules in RFC 3056. Only
+ * the top 48 bits of the IPv6 address are mapped to the reverse
+ * name. This is independent of whether the most significant 16
+ * bits match 2002::/16, assigned for 6to4 prefixes, or not.
*
* Requires:
*\li 'table' is a valid SSU table
*\li 'signer' is NULL or a valid absolute name
+ *\li 'tcpaddr' is NULL or a valid network address.
*\li 'name' is a valid absolute name
*/
diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h
index 6cd95ac..0b35aa8 100644
--- a/lib/dns/include/dns/stats.h
+++ b/lib/dns/include/dns/stats.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,19 +15,77 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: stats.h,v 1.5.18.4 2005/06/27 00:20:03 marka Exp $ */
+/* $Id: stats.h,v 1.18.56.2 2009/01/29 23:47:44 tbox Exp $ */
#ifndef DNS_STATS_H
#define DNS_STATS_H 1
-/*! \file */
+/*! \file dns/stats.h */
#include <dns/types.h>
/*%
- * Query statistics counter types.
+ * Statistics counters. Used as isc_statscounter_t values.
*/
-typedef enum {
+enum {
+ /*%
+ * Resolver statistics counters.
+ */
+ dns_resstatscounter_queryv4 = 0,
+ dns_resstatscounter_queryv6 = 1,
+ dns_resstatscounter_responsev4 = 2,
+ dns_resstatscounter_responsev6 = 3,
+ dns_resstatscounter_nxdomain = 4,
+ dns_resstatscounter_servfail = 5,
+ dns_resstatscounter_formerr = 6,
+ dns_resstatscounter_othererror = 7,
+ dns_resstatscounter_edns0fail = 8,
+ dns_resstatscounter_mismatch = 9,
+ dns_resstatscounter_truncated = 10,
+ dns_resstatscounter_lame = 11,
+ dns_resstatscounter_retry = 12,
+ dns_resstatscounter_gluefetchv4 = 13,
+ dns_resstatscounter_gluefetchv6 = 14,
+ dns_resstatscounter_gluefetchv4fail = 15,
+ dns_resstatscounter_gluefetchv6fail = 16,
+ dns_resstatscounter_val = 17,
+ dns_resstatscounter_valsuccess = 18,
+ dns_resstatscounter_valnegsuccess = 19,
+ dns_resstatscounter_valfail = 20,
+ dns_resstatscounter_dispabort = 21,
+ dns_resstatscounter_dispsockfail = 22,
+ dns_resstatscounter_querytimeout = 23,
+ dns_resstatscounter_queryrtt0 = 24,
+ dns_resstatscounter_queryrtt1 = 25,
+ dns_resstatscounter_queryrtt2 = 26,
+ dns_resstatscounter_queryrtt3 = 27,
+ dns_resstatscounter_queryrtt4 = 28,
+ dns_resstatscounter_queryrtt5 = 29,
+
+ dns_resstatscounter_max = 30,
+
+ /*%
+ * Zone statistics counters.
+ */
+ dns_zonestatscounter_notifyoutv4 = 0,
+ dns_zonestatscounter_notifyoutv6 = 1,
+ dns_zonestatscounter_notifyinv4 = 2,
+ dns_zonestatscounter_notifyinv6 = 3,
+ dns_zonestatscounter_notifyrej = 4,
+ dns_zonestatscounter_soaoutv4 = 5,
+ dns_zonestatscounter_soaoutv6 = 6,
+ dns_zonestatscounter_axfrreqv4 = 7,
+ dns_zonestatscounter_axfrreqv6 = 8,
+ dns_zonestatscounter_ixfrreqv4 = 9,
+ dns_zonestatscounter_ixfrreqv6 = 10,
+ dns_zonestatscounter_xfrsuccess = 11,
+ dns_zonestatscounter_xfrfail = 12,
+
+ dns_zonestatscounter_max = 13,
+
+ /*%
+ * Query statistics counters (obsolete).
+ */
dns_statscounter_success = 0, /*%< Successful lookup */
dns_statscounter_referral = 1, /*%< Referral result */
dns_statscounter_nxrrset = 2, /*%< NXRRSET result */
@@ -35,18 +93,261 @@ typedef enum {
dns_statscounter_recursion = 4, /*%< Recursion was used */
dns_statscounter_failure = 5, /*%< Some other failure */
dns_statscounter_duplicate = 6, /*%< Duplicate query */
- dns_statscounter_dropped = 7 /*%< Duplicate query */
-} dns_statscounter_t;
+ dns_statscounter_dropped = 7 /*%< Duplicate query (dropped) */
+};
#define DNS_STATS_NCOUNTERS 8
+#if 0
+/*%<
+ * Flag(s) for dns_xxxstats_dump(). DNS_STATSDUMP_VERBOSE is obsolete.
+ * ISC_STATSDUMP_VERBOSE should be used instead. These two values are
+ * intentionally defined to be the same value to ensure binary compatibility.
+ */
+#define DNS_STATSDUMP_VERBOSE 0x00000001 /*%< dump 0-value counters */
+#endif
+
+/*%<
+ * (Obsoleted)
+ */
LIBDNS_EXTERNAL_DATA extern const char *dns_statscounter_names[];
+/*%
+ * Attributes for statistics counters of RRset and Rdatatype types.
+ *
+ * _OTHERTYPE
+ * The rdata type is not explicitly supported and the corresponding counter
+ * is counted for other such types, too. When this attribute is set,
+ * the base type is of no use.
+ *
+ * _NXRRSET
+ * RRset type counters only. Indicates the RRset is non existent.
+ *
+ * _NXDOMAIN
+ * RRset type counters only. Indicates a non existent name. When this
+ * attribute is set, the base type is of no use.
+ */
+#define DNS_RDATASTATSTYPE_ATTR_OTHERTYPE 0x0001
+#define DNS_RDATASTATSTYPE_ATTR_NXRRSET 0x0002
+#define DNS_RDATASTATSTYPE_ATTR_NXDOMAIN 0x0004
+
+/*%<
+ * Conversion macros among dns_rdatatype_t, attributes and isc_statscounter_t.
+ */
+#define DNS_RDATASTATSTYPE_BASE(type) ((dns_rdatatype_t)((type) & 0xFFFF))
+#define DNS_RDATASTATSTYPE_ATTR(type) ((type) >> 16)
+#define DNS_RDATASTATSTYPE_VALUE(b, a) (((a) << 16) | (b))
+
+/*%<
+ * Types of dump callbacks.
+ */
+typedef void (*dns_generalstats_dumper_t)(isc_statscounter_t, isc_uint64_t,
+ void *);
+typedef void (*dns_rdatatypestats_dumper_t)(dns_rdatastatstype_t, isc_uint64_t,
+ void *);
+typedef void (*dns_opcodestats_dumper_t)(dns_opcode_t, isc_uint64_t, void *);
+
+isc_result_t
+dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters);
+/*%<
+ * Create a statistics counter structure of general type. It counts a general
+ * set of counters indexed by an ID between 0 and ncounters -1.
+ * This function is obsolete. A more general function, isc_stats_create(),
+ * should be used.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+isc_result_t
+dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+/*%<
+ * Create a statistics counter structure per rdatatype.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+isc_result_t
+dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+/*%<
+ * Create a statistics counter structure per RRset.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+isc_result_t
+dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+/*%<
+ * Create a statistics counter structure per opcode.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+void
+dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp);
+/*%<
+ * Attach to a statistics set.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL
+ */
+
+void
+dns_stats_detach(dns_stats_t **statsp);
+/*%<
+ * Detaches from the statistics set.
+ *
+ * Requires:
+ *\li 'statsp' != NULL and '*statsp' is a valid dns_stats_t.
+ */
+
+void
+dns_generalstats_increment(dns_stats_t *stats, isc_statscounter_t counter);
+/*%<
+ * Increment the counter-th counter of stats. This function is obsolete.
+ * A more general function, isc_stats_increment(), should be used.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ *
+ *\li counter is less than the maximum available ID for the stats specified
+ * on creation.
+ */
+
+void
+dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type);
+/*%<
+ * Increment the statistics counter for 'type'.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_rdatatypestats_create().
+ */
+
+void
+dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype);
+/*%<
+ * Increment the statistics counter for 'rrsettype'.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_rdatasetstats_create().
+ */
+
+void
+dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype);
+/*%<
+ * Decrement the statistics counter for 'rrsettype'.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_rdatasetstats_create().
+ */
+
+void
+dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code);
+/*%<
+ * Increment the statistics counter for 'code'.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_opcodestats_create().
+ */
+
+void
+dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
+ void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with its current value and the given argument
+ * arg. By default counters that have a value of 0 is skipped; if options has
+ * the ISC_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * This function is obsolete. A more general function, isc_stats_dump(),
+ * should be used.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+ void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with the corresponding type in the form of
+ * dns_rdatastatstype_t, the current counter value and the given argument
+ * arg. By default counters that have a value of 0 is skipped; if options has
+ * the ISC_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+ void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with the corresponding type in the form of
+ * dns_rdatastatstype_t, the current counter value and the given argument
+ * arg. By default counters that have a value of 0 is skipped; if options has
+ * the ISC_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
+ void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with the corresponding opcode, the current
+ * counter value and the given argument arg. By default counters that have a
+ * value of 0 is skipped; if options has the ISC_STATSDUMP_VERBOSE flag, even
+ * such counters are dumped.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
isc_result_t
dns_stats_alloccounters(isc_mem_t *mctx, isc_uint64_t **ctrp);
/*%<
* Allocate an array of query statistics counters from the memory
* context 'mctx'.
+ *
+ * This function is obsoleted. Use dns_xxxstats_create() instead.
*/
void
@@ -54,6 +355,8 @@ dns_stats_freecounters(isc_mem_t *mctx, isc_uint64_t **ctrp);
/*%<
* Free an array of query statistics counters allocated from the memory
* context 'mctx'.
+ *
+ * This function is obsoleted. Use dns_stats_destroy() instead.
*/
ISC_LANG_ENDDECLS
diff --git a/lib/dns/include/dns/tcpmsg.h b/lib/dns/include/dns/tcpmsg.h
index 075f463..fe83c53 100644
--- a/lib/dns/include/dns/tcpmsg.h
+++ b/lib/dns/include/dns/tcpmsg.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tcpmsg.h,v 1.16.18.2 2005/04/29 00:16:22 marka Exp $ */
+/* $Id: tcpmsg.h,v 1.22 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_TCPMSG_H
#define DNS_TCPMSG_H 1
-/*! \file */
+/*! \file dns/tcpmsg.h */
#include <isc/buffer.h>
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/time.h b/lib/dns/include/dns/time.h
index 9e8f5cc..5b47d11 100644
--- a/lib/dns/include/dns/time.h
+++ b/lib/dns/include/dns/time.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: time.h,v 1.11.18.2 2005/04/29 00:16:23 marka Exp $ */
+/* $Id: time.h,v 1.17 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_TIME_H
#define DNS_TIME_H 1
-/*! \file */
+/*! \file dns/time.h */
/***
*** Imports
diff --git a/lib/dns/include/dns/timer.h b/lib/dns/include/dns/timer.h
index cd936a0..48d6d56 100644
--- a/lib/dns/include/dns/timer.h
+++ b/lib/dns/include/dns/timer.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: timer.h,v 1.3.18.2 2005/04/29 00:16:23 marka Exp $ */
+/* $Id: timer.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_TIMER_H
#define DNS_TIMER_H 1
-/*! \file */
+/*! \file dns/timer.h */
/***
*** Imports
diff --git a/lib/dns/include/dns/tkey.h b/lib/dns/include/dns/tkey.h
index 4e3e80a..3511f2f 100644
--- a/lib/dns/include/dns/tkey.h
+++ b/lib/dns/include/dns/tkey.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,18 +15,19 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tkey.h,v 1.19.18.2 2005/04/29 00:16:23 marka Exp $ */
+/* $Id: tkey.h,v 1.26.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_TKEY_H
#define DNS_TKEY_H 1
-/*! \file */
+/*! \file dns/tkey.h */
#include <isc/lang.h>
#include <dns/types.h>
#include <dst/dst.h>
+#include <dst/gssapi.h>
ISC_LANG_BEGINDECLS
@@ -40,13 +41,14 @@ ISC_LANG_BEGINDECLS
struct dns_tkeyctx {
dst_key_t *dhkey;
dns_name_t *domain;
- void *gsscred;
+ gss_cred_id_t gsscred;
isc_mem_t *mctx;
isc_entropy_t *ectx;
};
isc_result_t
-dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp);
+dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx,
+ dns_tkeyctx_t **tctxp);
/*%<
* Create an empty TKEY context.
*
@@ -119,13 +121,29 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
*/
isc_result_t
-dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name,
- dns_name_t *gname, void *cred,
- isc_uint32_t lifetime, void **context);
+dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
+ isc_buffer_t *intoken, isc_uint32_t lifetime,
+ gss_ctx_id_t *context, isc_boolean_t win2k);
/*%<
- * XXX
+ * Builds a query containing a TKEY that will generate a GSSAPI context.
+ * The key is requested to have the specified lifetime (in seconds).
+ *
+ * Requires:
+ *\li 'msg' is a valid message
+ *\li 'name' is a valid name
+ *\li 'gname' is a valid name
+ *\li 'context' is a pointer to a valid gss_ctx_id_t
+ * (which may have the value GSS_C_NO_CONTEXT)
+ *\li 'win2k' when true says to turn on some hacks to work
+ * with the non-standard GSS-TSIG of Windows 2000
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ *\li other an error occurred while building the message
*/
+
isc_result_t
dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key);
/*%<
@@ -144,7 +162,7 @@ dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key);
isc_result_t
dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
- dst_key_t *key, isc_buffer_t *nonce,
+ dst_key_t *key, isc_buffer_t *nonce,
dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring);
/*%<
* Processes a response to a query containing a TKEY that was
@@ -167,8 +185,9 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
isc_result_t
dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
- dns_name_t *gname, void *cred, void **context,
- dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring);
+ dns_name_t *gname, gss_ctx_id_t *context,
+ isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
+ dns_tsig_keyring_t *ring);
/*%<
* XXX
*/
@@ -193,6 +212,39 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
*/
+isc_result_t
+dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
+ dns_name_t *server, gss_ctx_id_t *context,
+ dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
+ isc_boolean_t win2k);
+
+/*
+ * Client side negotiation of GSS-TSIG. Process the response
+ * to a TKEY, and establish a TSIG key if negotiation was successful.
+ * Build a response to the input TKEY message. Can take multiple
+ * calls to successfully establish the context.
+ *
+ * Requires:
+ * 'qmsg' is a valid message, the original TKEY request;
+ * it will be filled with the new message to send
+ * 'rmsg' is a valid message, the incoming TKEY message
+ * 'server' is the server name
+ * 'context' is the input context handle
+ * 'outkey' receives the established key, if non-NULL;
+ * if non-NULL must point to NULL
+ * 'ring' is the keyring in which to establish the key,
+ * or NULL
+ * 'win2k' when true says to turn on some hacks to work
+ * with the non-standard GSS-TSIG of Windows 2000
+ *
+ * Returns:
+ * ISC_R_SUCCESS context was successfully established
+ * ISC_R_NOTFOUND couldn't find a needed part of the query
+ * or response
+ * DNS_R_CONTINUE additional context negotiation is required;
+ * send the new qmsg to the server
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_TKEY_H */
diff --git a/lib/dns/include/dns/tsig.h b/lib/dns/include/dns/tsig.h
index b3fd6cc..e8c0e2c 100644
--- a/lib/dns/include/dns/tsig.h
+++ b/lib/dns/include/dns/tsig.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tsig.h,v 1.43.18.4 2006/01/27 23:57:44 marka Exp $ */
+/* $Id: tsig.h,v 1.51 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_TSIG_H
#define DNS_TSIG_H 1
-/*! \file */
+/*! \file dns/tsig.h */
#include <isc/lang.h>
#include <isc/refcount.h>
@@ -59,6 +59,7 @@ LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha512_name;
struct dns_tsig_keyring {
dns_rbt_t *keys;
+ unsigned int writecount;
isc_rwlock_t lock;
isc_mem_t *mctx;
};
@@ -79,7 +80,9 @@ struct dns_tsigkey {
};
#define dns_tsigkey_identity(tsigkey) \
- ((tsigkey)->generated ? ((tsigkey)->creator) : (&((tsigkey)->name)))
+ ((tsigkey) == NULL ? NULL : \
+ (tsigkey)->generated ? ((tsigkey)->creator) : \
+ (&((tsigkey)->name)))
ISC_LANG_BEGINDECLS
diff --git a/lib/dns/include/dns/ttl.h b/lib/dns/include/dns/ttl.h
index ad01578..c252518 100644
--- a/lib/dns/include/dns/ttl.h
+++ b/lib/dns/include/dns/ttl.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ttl.h,v 1.13.18.2 2005/04/29 00:16:24 marka Exp $ */
+/* $Id: ttl.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_TTL_H
#define DNS_TTL_H 1
-/*! \file */
+/*! \file dns/ttl.h */
/***
*** Imports
diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h
index 8dcbe57..e07a796 100644
--- a/lib/dns/include/dns/types.h
+++ b/lib/dns/include/dns/types.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: types.h,v 1.109.18.12 2006/05/02 12:55:31 shane Exp $ */
+/* $Id: types.h,v 1.130.50.3 2009/01/29 22:40:35 jinmei Exp $ */
#ifndef DNS_TYPES_H
#define DNS_TYPES_H 1
-/*! \file
+/*! \file dns/types.h
* \brief
* Including this file gives you type declarations suitable for use in
* .h files, which lets us avoid circular type reference problems.
@@ -68,6 +68,8 @@ typedef struct dns_fetch dns_fetch_t;
typedef struct dns_fixedname dns_fixedname_t;
typedef struct dns_forwarders dns_forwarders_t;
typedef struct dns_fwdtable dns_fwdtable_t;
+typedef struct dns_iptable dns_iptable_t;
+typedef isc_uint32_t dns_iterations_t;
typedef isc_uint16_t dns_keyflags_t;
typedef struct dns_keynode dns_keynode_t;
typedef struct dns_keytable dns_keytable_t;
@@ -105,6 +107,8 @@ typedef isc_uint8_t dns_secproto_t;
typedef struct dns_signature dns_signature_t;
typedef struct dns_ssurule dns_ssurule_t;
typedef struct dns_ssutable dns_ssutable_t;
+typedef struct dns_stats dns_stats_t;
+typedef isc_uint32_t dns_rdatastatstype_t;
typedef struct dns_tkeyctx dns_tkeyctx_t;
typedef isc_uint16_t dns_trust_t;
typedef struct dns_tsig_keyring dns_tsig_keyring_t;
@@ -118,6 +122,19 @@ typedef ISC_LIST(dns_zone_t) dns_zonelist_t;
typedef struct dns_zonemgr dns_zonemgr_t;
typedef struct dns_zt dns_zt_t;
+/*
+ * If we are not using GSSAPI, define the types we use as opaque types here.
+ */
+#ifndef GSSAPI
+typedef struct not_defined_gss_cred_id *gss_cred_id_t;
+typedef struct not_defined_gss_ctx *gss_ctx_id_t;
+#endif
+typedef struct dst_gssapi_signverifyctx dst_gssapi_signverifyctx_t;
+
+typedef enum {
+ dns_hash_sha1 = 1
+} dns_hash_t;
+
typedef enum {
dns_fwdpolicy_none = 0,
dns_fwdpolicy_first = 1,
@@ -249,11 +266,11 @@ enum {
dns_trust_additional = 2,
#define dns_trust_additional ((dns_trust_t)dns_trust_additional)
- /* Received in a referral response. */
+ /* Received in a referral response. */
dns_trust_glue = 3,
#define dns_trust_glue ((dns_trust_t)dns_trust_glue)
- /* Answser from a non-authoritative server */
+ /* Answer from a non-authoritative server */
dns_trust_answer = 4,
#define dns_trust_answer ((dns_trust_t)dns_trust_answer)
@@ -262,11 +279,11 @@ enum {
dns_trust_authauthority = 5,
#define dns_trust_authauthority ((dns_trust_t)dns_trust_authauthority)
- /* Answser from an authoritative server */
+ /* Answer from an authoritative server */
dns_trust_authanswer = 6,
#define dns_trust_authanswer ((dns_trust_t)dns_trust_authanswer)
- /* Successfully DNSSEC validated */
+ /* Successfully DNSSEC validated */
dns_trust_secure = 7,
#define dns_trust_secure ((dns_trust_t)dns_trust_secure)
@@ -276,7 +293,7 @@ enum {
};
/*%
- * Name checking severites.
+ * Name checking severities.
*/
typedef enum {
dns_severity_ignore,
@@ -308,7 +325,7 @@ typedef void
typedef void
(*dns_updatecallback_t)(void *, isc_result_t, dns_message_t *);
-typedef int
+typedef int
(*dns_rdatasetorderfunc_t)(const dns_rdata_t *, const void *);
typedef isc_boolean_t
diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h
index c94fc3a..2555214 100644
--- a/lib/dns/include/dns/validator.h
+++ b/lib/dns/include/dns/validator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.h,v 1.27.18.10 2007/09/26 04:39:45 each Exp $ */
+/* $Id: validator.h,v 1.41.48.3 2009/01/18 23:25:17 marka Exp $ */
#ifndef DNS_VALIDATOR_H
#define DNS_VALIDATOR_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/validator.h
*
* \brief
* DNS Validator
@@ -74,7 +74,7 @@
* caller so that they may be freed.
*
* If the RESULT is ISC_R_SUCCESS and the answer is secure then
- * proofs[] will contain the the names of the NSEC records that hold the
+ * proofs[] will contain the names of the NSEC records that hold the
* various proofs. Note the same name may appear multiple times.
*/
typedef struct dns_validatorevent {
@@ -99,12 +99,17 @@ typedef struct dns_validatorevent {
/*
* Proofs to be cached.
*/
- dns_name_t * proofs[3];
+ dns_name_t * proofs[4];
+ /*
+ * Optout proof seen.
+ */
+ isc_boolean_t optout;
} dns_validatorevent_t;
#define DNS_VALIDATOR_NOQNAMEPROOF 0
#define DNS_VALIDATOR_NODATAPROOF 1
#define DNS_VALIDATOR_NOWILDCARDPROOF 2
+#define DNS_VALIDATOR_CLOSESTENCLOSER 3
/*%
* A validator object represents a validation in progress.
@@ -139,11 +144,14 @@ struct dns_validator {
dns_rdataset_t * dsset;
dns_rdataset_t * soaset;
dns_rdataset_t * nsecset;
+ dns_rdataset_t * nsec3set;
dns_name_t * soaname;
dns_rdataset_t frdataset;
dns_rdataset_t fsigrdataset;
dns_fixedname_t fname;
dns_fixedname_t wild;
+ dns_fixedname_t nearest;
+ dns_fixedname_t closest;
ISC_LINK(dns_validator_t) link;
dns_rdataset_t dlv;
dns_fixedname_t dlvsep;
@@ -202,7 +210,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
* options:
* If DNS_VALIDATOR_DLV is set the caller knows there is not a
* trusted key and the validator should immediately attempt to validate
- * the answer by looking for a appopriate DLV RRset.
+ * the answer by looking for an appropriate DLV RRset.
*/
void
diff --git a/lib/dns/include/dns/version.h b/lib/dns/include/dns/version.h
index bb254534..2a33dcf 100644
--- a/lib/dns/include/dns/version.h
+++ b/lib/dns/include/dns/version.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,9 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: version.h,v 1.3.18.2 2005/04/29 00:16:25 marka Exp $ */
+/* $Id: version.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
-/*! \file */
+/*! \file dns/version.h */
#include <isc/platform.h>
diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h
index ea3d4c7..5b53c16 100644
--- a/lib/dns/include/dns/view.h
+++ b/lib/dns/include/dns/view.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: view.h,v 1.91.18.9 2006/03/09 23:38:21 marka Exp $ */
+/* $Id: view.h,v 1.111.88.4 2009/01/29 22:40:35 jinmei Exp $ */
#ifndef DNS_VIEW_H
#define DNS_VIEW_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/view.h
* \brief
* DNS View
*
@@ -100,6 +100,9 @@ struct dns_view {
isc_event_t resevent;
isc_event_t adbevent;
isc_event_t reqevent;
+ isc_stats_t * resstats;
+ dns_stats_t * resquerystats;
+
/* Configurable data. */
dns_tsig_keyring_t * statickeys;
dns_tsig_keyring_t * dynamickeys;
@@ -116,10 +119,17 @@ struct dns_view {
isc_boolean_t acceptexpired;
dns_transfer_format_t transfer_format;
dns_acl_t * queryacl;
+ dns_acl_t * queryonacl;
dns_acl_t * recursionacl;
+ dns_acl_t * recursiononacl;
dns_acl_t * sortlist;
+ dns_acl_t * notifyacl;
+ dns_acl_t * transferacl;
+ dns_acl_t * updateacl;
+ dns_acl_t * upfwdacl;
isc_boolean_t requestixfr;
isc_boolean_t provideixfr;
+ isc_boolean_t requestnsid;
dns_ttl_t maxcachettl;
dns_ttl_t maxncachettl;
in_port_t dstport;
@@ -224,7 +234,7 @@ void
dns_view_flushanddetach(dns_view_t **viewp);
/*%<
* Detach '*viewp' from its view. If this was the last reference
- * uncommited changed in zones will be flushed to disk.
+ * uncommitted changed in zones will be flushed to disk.
*
* Requires:
*
@@ -363,7 +373,7 @@ dns_view_setdstport(dns_view_t *view, in_port_t dstport);
*\li 'dstport' is a valid TCP/UDP port number.
*
* Ensures:
- *\li External name servers will be assumed to be listning
+ *\li External name servers will be assumed to be listening
* on 'dstport'. For servers whose address has already
* obtained obtained at the time of the call, the view may
* continue to use the previously set port until the address
@@ -591,6 +601,19 @@ dns_viewlist_find(dns_viewlist_t *list, const char *name,
*/
isc_result_t
+dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, isc_boolean_t allclasses,
+ dns_rdataclass_t rdclass, dns_zone_t **zonep);
+
+/*%<
+ * Search zone with 'name' in view with 'rdclass' in viewlist 'list'
+ * If found, zone is returned in *zonep. If allclasses is set rdclass is ignored
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS A matching zone was found.
+ *\li #ISC_R_NOTFOUND No matching zone was found.
+ */
+
+isc_result_t
dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep);
/*%<
* Search for the zone 'name' in the zone table of 'view'.
@@ -615,7 +638,7 @@ dns_view_loadnew(dns_view_t *view, isc_boolean_t stop);
/*%<
* Load zones attached to this view. dns_view_load() loads
* all zones whose master file has changed since the last
- * load; dns_view_loadnew() loads only zones that have never
+ * load; dns_view_loadnew() loads only zones that have never
* been loaded.
*
* If 'stop' is ISC_TRUE, stop on the first error and return it.
@@ -633,7 +656,7 @@ dns_view_gettsig(dns_view_t *view, dns_name_t *keyname,
* Find the TSIG key configured in 'view' with name 'keyname',
* if any.
*
- * Reqires:
+ * Requires:
*\li keyp points to a NULL dns_tsigkey_t *.
*
* Returns:
@@ -649,7 +672,7 @@ dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
* Find the TSIG key configured in 'view' for the server whose
* address is 'peeraddr', if any.
*
- * Reqires:
+ * Requires:
* keyp points to a NULL dns_tsigkey_t *.
*
* Returns:
@@ -691,7 +714,7 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp);
* easily obtainable by other means.
*
* Requires:
- *
+ *
*\li 'view' is valid.
*
*\li 'fp' refers to a file open for writing.
@@ -734,7 +757,7 @@ isc_result_t
dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name);
/*%<
* Add the given name to the delegation only table.
- *
+ *
*
* Requires:
*\li 'view' is valid.
@@ -749,7 +772,7 @@ isc_result_t
dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name);
/*%<
* Add the given name to be excluded from the root-delegation-only.
- *
+ *
*
* Requires:
*\li 'view' is valid.
@@ -771,8 +794,8 @@ dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name);
*\li 'name' is valid.
*
* Returns:
- *\li #ISC_TRUE if the name is is the table.
- *\li #ISC_FALSE othewise.
+ *\li #ISC_TRUE if the name is the table.
+ *\li #ISC_FALSE otherwise.
*/
void
@@ -801,4 +824,56 @@ dns_view_freezezones(dns_view_t *view, isc_boolean_t freeze);
* Requires:
* \li 'view' is valid.
*/
+
+void
+dns_view_setresstats(dns_view_t *view, isc_stats_t *stats);
+/*%<
+ * Set a general resolver statistics counter set 'stats' for 'view'.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li stats is a valid statistics supporting resolver statistics counters
+ * (see dns/stats.h).
+ */
+
+void
+dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp);
+/*%<
+ * Get the general statistics counter set for 'view'. If a statistics set is
+ * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
+ * untouched.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li 'statsp' != NULL && '*statsp' != NULL
+ */
+
+void
+dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats);
+/*%<
+ * Set a statistics counter set of rdata type, 'stats', for 'view'. Once the
+ * statistic set is installed, view's resolver will count outgoing queries
+ * per rdata type.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li stats is a valid statistics created by dns_rdatatypestats_create().
+ */
+
+void
+dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp);
+/*%<
+ * Get the rdatatype statistics counter set for 'view'. If a statistics set is
+ * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
+ * untouched.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li 'statsp' != NULL && '*statsp' != NULL
+ */
+
#endif /* DNS_VIEW_H */
diff --git a/lib/dns/include/dns/xfrin.h b/lib/dns/include/dns/xfrin.h
index fcd482e..04866ee 100644
--- a/lib/dns/include/dns/xfrin.h
+++ b/lib/dns/include/dns/xfrin.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: xfrin.h,v 1.20.18.5 2006/07/20 01:10:30 marka Exp $ */
+/* $Id: xfrin.h,v 1.28.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DNS_XFRIN_H
#define DNS_XFRIN_H 1
@@ -24,7 +24,7 @@
***** Module Info
*****/
-/*! \file
+/*! \file dns/xfrin.h
* \brief
* Incoming zone transfers (AXFR + IXFR).
*/
@@ -90,7 +90,7 @@ dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr);
/*%<
* If the zone transfer 'xfr' has already finished,
* do nothing. Otherwise, abort it and cause it to call
- * its done callback with a status of ISC_R_CANCELLED.
+ * its done callback with a status of ISC_R_CANCELED.
*/
void
diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
index 7cb8272..e2859ae 100644
--- a/lib/dns/include/dns/zone.h
+++ b/lib/dns/include/dns/zone.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.h,v 1.126.18.19 2006/08/01 03:45:21 marka Exp $ */
+/* $Id: zone.h,v 1.160.50.4 2009/01/29 22:40:35 jinmei Exp $ */
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
-/*! \file */
+/*! \file dns/zone.h */
/***
*** Imports
@@ -33,6 +33,7 @@
#include <isc/rwlock.h>
#include <dns/masterdump.h>
+#include <dns/rdatastruct.h>
#include <dns/types.h>
typedef enum {
@@ -66,6 +67,9 @@ typedef enum {
#define DNS_ZONEOPT_WARNSRVCNAME 0x00200000U /*%< warn on SRV CNAME check */
#define DNS_ZONEOPT_IGNORESRVCNAME 0x00400000U /*%< ignore SRV CNAME check */
#define DNS_ZONEOPT_UPDATECHECKKSK 0x00800000U /*%< check dnskey KSK flag */
+#define DNS_ZONEOPT_TRYTCPREFRESH 0x01000000U /*%< try tcp refresh on udp failure */
+#define DNS_ZONEOPT_NOTIFYTOSOA 0x02000000U /*%< Notify the SOA MNAME */
+#define DNS_ZONEOPT_NSEC3TESTZONE 0x04000000U /*%< nsec3-test-zone */
#ifndef NOMINUM_PUBLIC
/*
@@ -145,6 +149,15 @@ dns_zone_getclass(dns_zone_t *zone);
*\li 'zone' to be a valid zone.
*/
+isc_uint32_t
+dns_zone_getserial(dns_zone_t *zone);
+/*%<
+ * Returns the current serial number of the zone.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
void
dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type);
/*%<
@@ -406,7 +419,7 @@ dns_zone_refresh(dns_zone_t *zone);
isc_result_t
dns_zone_flush(dns_zone_t *zone);
/*%<
- * Write the zone to database if there are uncommited changes.
+ * Write the zone to database if there are uncommitted changes.
*
* Require:
*\li 'zone' to be a valid zone.
@@ -458,7 +471,7 @@ dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd);
void
dns_zone_maintenance(dns_zone_t *zone);
/*%<
- * Perform regular maintenace on the zone. This is called as a
+ * Perform regular maintenance on the zone. This is called as a
* result of a zone being managed.
*
* Require
@@ -503,7 +516,7 @@ dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
* Require:
*\li 'zone' to be a valid zone.
*\li 'notify' to be non-NULL if count != 0.
- *\li 'count' to be the number of notifyees.
+ *\li 'count' to be the number of notifiees.
*
* Returns:
*\li #ISC_R_SUCCESS
@@ -701,6 +714,16 @@ dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl);
*/
void
+dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl);
+/*%<
+ * Sets the query-on acl list for the zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'acl' to be a valid acl.
+ */
+
+void
dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl);
/*%<
* Sets the update acl list for the zone.
@@ -757,6 +780,19 @@ dns_zone_getqueryacl(dns_zone_t *zone);
*/
dns_acl_t *
+dns_zone_getqueryonacl(dns_zone_t *zone);
+/*%<
+ * Returns the current query-on acl or NULL.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li acl a pointer to the acl.
+ *\li NULL
+ */
+
+dns_acl_t *
dns_zone_getupdateacl(dns_zone_t *zone);
/*%<
* Returns the current update acl or NULL.
@@ -832,6 +868,15 @@ dns_zone_clearqueryacl(dns_zone_t *zone);
*/
void
+dns_zone_clearqueryonacl(dns_zone_t *zone);
+/*%<
+ * Clear the current query-on acl.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
dns_zone_clearxfracl(dns_zone_t *zone);
/*%<
* Clear the current transfer acl.
@@ -844,12 +889,16 @@ isc_boolean_t
dns_zone_getupdatedisabled(dns_zone_t *zone);
/*%<
* Return update disabled.
+ * Transient unless called when running in isc_task_exclusive() mode.
*/
void
dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state);
/*%<
* Set update disabled.
+ * Should only be called only when running in isc_task_exclusive() mode.
+ * Failure to do so may result in updates being committed after the
+ * call has been made.
*/
isc_boolean_t
@@ -905,13 +954,13 @@ isc_result_t
dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
dns_message_t *msg);
/*%<
- * Tell the zone that it has recieved a NOTIFY message from another
- * server. This may cause some zone maintainence activity to occur.
+ * Tell the zone that it has received a NOTIFY message from another
+ * server. This may cause some zone maintenance activity to occur.
*
* Requires:
*\li 'zone' to be a valid zone.
*\li '*from' to contain the address of the server from which 'msg'
- * was recieved.
+ * was received.
*\li 'msg' a message with opcode NOTIFY and qr clear.
*
* Returns:
@@ -1036,7 +1085,7 @@ dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump);
* If "dump" is ISC_TRUE, then the new zone contents are dumped
* into to the zone's master file for persistence. When replacing
* a zone database by one just loaded from a master file, set
- * "dump" to ISC_FALSE to avoid a redunant redump of the data just
+ * "dump" to ISC_FALSE to avoid a redundant redump of the data just
* loaded. Otherwise, it should be set to ISC_TRUE.
*
* If the "diff-on-reload" option is enabled in the configuration file,
@@ -1048,7 +1097,7 @@ dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump);
*
* Returns:
* \li DNS_R_SUCCESS
- * \li DNS_R_BADZONE zone failed basic consistancy checks:
+ * \li DNS_R_BADZONE zone failed basic consistency checks:
* * a single SOA must exist
* * some NS records must exist.
* Others
@@ -1134,7 +1183,7 @@ dns_zone_getmgr(dns_zone_t *zone);
void
dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval);
/*%<
- * Set the zone's SIG validity interval. This is the length of time
+ * Set the zone's RRSIG validity interval. This is the length of time
* for which DNSSEC signatures created as a result of dynamic updates
* to secure zones will remain valid, in seconds.
*
@@ -1145,7 +1194,26 @@ dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval);
isc_uint32_t
dns_zone_getsigvalidityinterval(dns_zone_t *zone);
/*%<
- * Get the zone's SIG validity interval.
+ * Get the zone's RRSIG validity interval.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval);
+/*%<
+ * Set the zone's RRSIG re-signing interval. A dynamic zone's RRSIG's
+ * will be re-signed 'interval' amount of time before they expire.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+isc_uint32_t
+dns_zone_getsigresigninginterval(dns_zone_t *zone);
+/*%<
+ * Get the zone's RRSIG re-signing interval.
*
* Requires:
* \li 'zone' to be a valid zone.
@@ -1159,10 +1227,10 @@ dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype);
isc_result_t
dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
- dns_updatecallback_t callback, void *callback_arg);
+ dns_updatecallback_t callback, void *callback_arg);
/*%<
* Forward 'msg' to each master in turn until we get an answer or we
- * have exausted the list of masters. 'callback' will be called with
+ * have exhausted the list of masters. 'callback' will be called with
* ISC_R_SUCCESS if we get an answer and the returned message will be
* passed as 'answer_message', otherwise a non ISC_R_SUCCESS result code
* will be passed and answer_message will be NULL. The callback function
@@ -1195,6 +1263,8 @@ dns_zone_next(dns_zone_t *zone, dns_zone_t **next);
* (result ISC_R_NOMORE).
*/
+
+
isc_result_t
dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first);
/*%<
@@ -1267,7 +1337,7 @@ isc_result_t
dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr);
/*%<
* Force zone maintenance of all zones managed by 'zmgr' at its
- * earliest conveniene.
+ * earliest convenience.
*/
void
@@ -1336,7 +1406,7 @@ dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value);
isc_uint32_t
dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr);
/*%<
- * Return the the maximum number of simultaneous transfers in allowed.
+ * Return the maximum number of simultaneous transfers in allowed.
*
* Requires:
*\li 'zmgr' to be a valid zone manager.
@@ -1363,7 +1433,7 @@ dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr);
void
dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit);
/*%<
- * Set the number of simultaneous file descriptors available for
+ * Set the number of simultaneous file descriptors available for
* reading and writing masterfiles.
*
* Requires:
@@ -1374,7 +1444,7 @@ dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit);
isc_uint32_t
dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr);
/*%<
- * Get the number of simultaneous file descriptors available for
+ * Get the number of simultaneous file descriptors available for
* reading and writing masterfiles.
*
* Requires:
@@ -1410,6 +1480,18 @@ dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state);
*/
void
+dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
+ isc_sockaddr_t *local, isc_time_t *now);
+/*%<
+ * Add the pair of addresses to the unreachable cache.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ *\li 'remote' to be a valid sockaddr.
+ *\li 'local' to be a valid sockaddr.
+ */
+
+void
dns_zone_forcereload(dns_zone_t *zone);
/*%<
* Force a reload of specified zone.
@@ -1430,22 +1512,55 @@ dns_zone_isforced(dns_zone_t *zone);
isc_result_t
dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on);
/*%<
- * Make the zone keep or not keep an array of statistics
- * counter.
- *
- * Requires:
- * \li zone be a valid zone.
+ * This function is obsoleted by dns_zone_setrequeststats().
*/
isc_uint64_t *
dns_zone_getstatscounters(dns_zone_t *zone);
/*%<
+ * This function is obsoleted by dns_zone_getrequeststats().
+ */
+
+void
+dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats);
+/*%<
+ * Set a general zone-maintenance statistics set 'stats' for 'zone'. This
+ * function is expected to be called only on zone creation (when necessary).
+ * Once installed, it cannot be removed or replaced. Also, there is no
+ * interface to get the installed stats from the zone; the caller must keep the
+ * stats to reference (e.g. dump) it later.
+ *
* Requires:
- * zone be a valid zone.
+ * \li 'zone' to be a valid zone and does not have a statistics set already
+ * installed.
+ *
+ *\li stats is a valid statistics supporting zone statistics counters
+ * (see dns/stats.h).
+ */
+
+void
+dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats);
+/*%<
+ * Set an additional statistics set to zone. It is attached in the zone
+ * but is not counted in the zone module; only the caller updates the counters.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ *
+ *\li stats is a valid statistics.
+ */
+
+isc_stats_t *
+dns_zone_getrequeststats(dns_zone_t *zone);
+/*%<
+ * Get the additional statistics for zone, if one is installed.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
*
* Returns:
- * \li A pointer to the zone's array of statistics counters,
- * or NULL if it has none.
+ * \li when available, a pointer to the statistics set installed in zone;
+ * otherwise NULL.
*/
void
@@ -1484,7 +1599,7 @@ void
dns_zone_name(dns_zone_t *zone, char *buf, size_t len);
/*%<
* Return the name of the zone with class and view.
- *
+ *
* Requires:
*\li 'zone' to be valid.
*\li 'buf' to be non NULL.
@@ -1492,7 +1607,7 @@ dns_zone_name(dns_zone_t *zone, char *buf, size_t len);
isc_result_t
dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata);
-/*
+/*%<
* Check if this record meets the check-names policy.
*
* Requires:
@@ -1508,7 +1623,7 @@ dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata);
void
dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache);
-/*
+/*%<
* Associate the zone with an additional cache.
*
* Require:
@@ -1521,7 +1636,7 @@ dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache);
void
dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx);
-/*
+/*%<
* Set the post load integrity callback function 'checkmx'.
* 'checkmx' will be called if the MX is not within the zone.
*
@@ -1531,7 +1646,7 @@ dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx);
void
dns_zone_setchecksrv(dns_zone_t *zone, dns_checkmxfunc_t checksrv);
-/*
+/*%<
* Set the post load integrity callback function 'checksrv'.
* 'checksrv' will be called if the SRV TARGET is not within the zone.
*
@@ -1541,7 +1656,7 @@ dns_zone_setchecksrv(dns_zone_t *zone, dns_checkmxfunc_t checksrv);
void
dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns);
-/*
+/*%<
* Set the post load integrity callback function 'checkmx'.
* 'checkmx' will be called if the MX is not within the zone.
*
@@ -1551,7 +1666,7 @@ dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns);
void
dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay);
-/*
+/*%<
* Set the minimum delay between sets of notify messages.
*
* Requires:
@@ -1560,7 +1675,7 @@ dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay);
isc_uint32_t
dns_zone_getnotifydelay(dns_zone_t *zone);
-/*
+/*%<
* Get the minimum delay between sets of notify messages.
*
* Requires:
@@ -1569,7 +1684,7 @@ dns_zone_getnotifydelay(dns_zone_t *zone);
void
dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg);
-/*
+/*%<
* Set the isself callback function and argument.
*
* isc_boolean_t
@@ -1581,6 +1696,41 @@ dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg);
* delivered to 'myview'.
*/
+void
+dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes);
+/*%<
+ * Set the number of nodes that will be checked per quantum.
+ */
+
+void
+dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures);
+/*%<
+ * Set the number of signatures that will be generated per quantum.
+ */
+
+isc_result_t
+dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
+ isc_uint16_t keyid, isc_boolean_t delete);
+/*%<
+ * Initiate/resume signing of the entire zone with the zone DNSKEY(s)
+ * that match the given algorithm and keyid.
+ */
+
+isc_result_t
+dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param);
+/*%<
+ * Incrementally add a NSEC3 chain that corresponds to 'nsec3param'.
+ */
+
+void
+dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type);
+dns_rdatatype_t
+dns_zone_getprivatetype(dns_zone_t *zone);
+/*
+ * Get/Set the private record type. It is expected that these interfaces
+ * will not be permanent.
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_ZONE_H */
diff --git a/lib/dns/include/dns/zonekey.h b/lib/dns/include/dns/zonekey.h
index ba4e076..d9ba862 100644
--- a/lib/dns/include/dns/zonekey.h
+++ b/lib/dns/include/dns/zonekey.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zonekey.h,v 1.4.18.2 2005/04/29 00:16:26 marka Exp $ */
+/* $Id: zonekey.h,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_ZONEKEY_H
#define DNS_ZONEKEY_H 1
-/*! \file */
+/*! \file dns/zonekey.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dns/zt.h b/lib/dns/include/dns/zt.h
index 436ef4c..6cfe3d3 100644
--- a/lib/dns/include/dns/zt.h
+++ b/lib/dns/include/dns/zt.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zt.h,v 1.30.18.3 2005/04/27 05:01:42 sra Exp $ */
+/* $Id: zt.h,v 1.38 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_ZT_H
#define DNS_ZT_H 1
-/*! \file */
+/*! \file dns/zt.h */
#include <isc/lang.h>
diff --git a/lib/dns/include/dst/Makefile.in b/lib/dns/include/dst/Makefile.in
index deaa221..4ed4ec0 100644
--- a/lib/dns/include/dst/Makefile.in
+++ b/lib/dns/include/dst/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.1.6.1 2004/12/09 04:41:47 marka Exp $
+# $Id: Makefile.in,v 1.4 2007/12/11 20:28:55 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@
@BIND9_VERSION@
-HEADERS = dst.h lib.h result.h
+HEADERS = dst.h gssapi.h lib.h result.h
SUBDIRS =
TARGETS =
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h
index 8d99186..702ad71 100644
--- a/lib/dns/include/dst/dst.h
+++ b/lib/dns/include/dst/dst.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,17 +15,19 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst.h,v 1.1.6.5 2006/01/27 23:57:44 marka Exp $ */
+/* $Id: dst.h,v 1.12 2008/09/24 02:46:23 marka Exp $ */
#ifndef DST_DST_H
#define DST_DST_H 1
-/*! \file */
+/*! \file dst/dst.h */
#include <isc/lang.h>
#include <dns/types.h>
+#include <dst/gssapi.h>
+
ISC_LANG_BEGINDECLS
/***
@@ -49,6 +51,8 @@ typedef struct dst_context dst_context_t;
#define DST_ALG_DSA 3
#define DST_ALG_ECC 4
#define DST_ALG_RSASHA1 5
+#define DST_ALG_NSEC3DSA 6
+#define DST_ALG_NSEC3RSASHA1 7
#define DST_ALG_HMACMD5 157
#define DST_ALG_GSSAPI 160
#define DST_ALG_HMACSHA1 161 /* XXXMPA */
@@ -398,16 +402,28 @@ dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer);
*\li If successful, key will contain a valid private key.
*/
+gss_ctx_id_t
+dst_key_getgssctx(const dst_key_t *key);
+/*%<
+ * Returns the opaque key data.
+ * Be cautions when using this value unless you know what you are doing.
+ *
+ * Requires:
+ *\li "key" is not NULL.
+ *
+ * Returns:
+ *\li gssctx key data, possibly NULL.
+ */
isc_result_t
-dst_key_fromgssapi(dns_name_t *name, void *opaque, isc_mem_t *mctx,
- dst_key_t **keyp);
+dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
+ dst_key_t **keyp);
/*%<
* Converts a GSSAPI opaque context id into a DST key.
*
* Requires:
*\li "name" is a valid absolute dns name.
- *\li "opaque" is a GSSAPI context id.
+ *\li "gssctx" is a GSSAPI context id.
*\li "mctx" is a valid memory context.
*\li "keyp" is not NULL and "*keyp" is NULL.
*
@@ -421,6 +437,12 @@ dst_key_fromgssapi(dns_name_t *name, void *opaque, isc_mem_t *mctx,
*/
isc_result_t
+dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags,
+ unsigned int protocol, dns_rdataclass_t rdclass,
+ const char *engine, const char *label, const char *pin,
+ isc_mem_t *mctx, dst_key_t **keyp);
+
+isc_result_t
dst_key_generate(dns_name_t *name, unsigned int alg,
unsigned int bits, unsigned int param,
unsigned int flags, unsigned int protocol,
diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h
index e30fb0c..446b76d 100644
--- a/lib/dns/include/dst/gssapi.h
+++ b/lib/dns/include/dst/gssapi.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,16 +15,32 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gssapi.h,v 1.1.6.3 2005/04/29 00:16:28 marka Exp $ */
+/* $Id: gssapi.h,v 1.9.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef DST_GSSAPI_H
#define DST_GSSAPI_H 1
-/*! \file */
+/*! \file dst/gssapi.h */
+#include <isc/formatcheck.h>
#include <isc/lang.h>
-
+#include <isc/platform.h>
#include <isc/types.h>
+#include <dns/types.h>
+
+#ifdef GSSAPI
+#ifdef _WINDOWS
+/*
+ * MSVC does not like macros in #include lines.
+ */
+#include <gssapi/gssapi.h>
+#else
+#include ISC_PLATFORM_GSSAPIHEADER
+#endif
+#ifndef GSS_SPNEGO_MECHANISM
+#define GSS_SPNEGO_MECHANISM ((void*)0)
+#endif
+#endif
ISC_LANG_BEGINDECLS
@@ -37,20 +53,153 @@ ISC_LANG_BEGINDECLS
***/
isc_result_t
-dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, void **cred);
+dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
+ gss_cred_id_t *cred);
+/*
+ * Acquires GSS credentials.
+ *
+ * Requires:
+ * 'name' is a valid name, preferably one known by the GSS provider
+ * 'initiate' indicates whether the credentials are for initiating or
+ * accepting contexts
+ * 'cred' is a pointer to NULL, which will be allocated with the
+ * credential handle. Call dst_gssapi_releasecred to free
+ * the memory.
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
+
+isc_result_t
+dst_gssapi_releasecred(gss_cred_id_t *cred);
+/*
+ * Releases GSS credentials. Calling this function does release the
+ * memory allocated for the credential in dst_gssapi_acquirecred()
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'cred' is a pointer to the credential to be released
+ *
+ * Returns:
+ * ISC_R_SUCCESS credential was released successfully
+ * other an error occurred while releaseing
+ * the credential
+ */
+
+isc_result_t
+dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
+ isc_buffer_t *outtoken, gss_ctx_id_t *gssctx);
+/*
+ * Initiates a GSS context.
+ *
+ * Requires:
+ * 'name' is a valid name, preferably one known by the GSS
+ * provider
+ * 'intoken' is a token received from the acceptor, or NULL if
+ * there isn't one
+ * 'outtoken' is a buffer to receive the token generated by
+ * gss_init_sec_context() to be sent to the acceptor
+ * 'context' is a pointer to a valid gss_ctx_id_t
+ * (which may have the value GSS_C_NO_CONTEXT)
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
isc_result_t
-dst_gssapi_initctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context);
+dst_gssapi_acceptctx(gss_cred_id_t cred,
+ isc_region_t *intoken, isc_buffer_t **outtoken,
+ gss_ctx_id_t *context, dns_name_t *principal,
+ isc_mem_t *mctx);
+/*
+ * Accepts a GSS context.
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'cred' is the acceptor's valid GSS credential handle
+ * 'intoken' is a token received from the initiator
+ * 'outtoken' is a pointer a buffer pointer used to return the token
+ * generated by gss_accept_sec_context() to be sent to the
+ * initiator
+ * 'context' is a valid pointer to receive the generated context handle.
+ * On the initial call, it should be a pointer to NULL, which
+ * will be allocated as a gss_ctx_id_t. Subsequent calls
+ * should pass in the handle generated on the first call.
+ * Call dst_gssapi_releasecred to delete the context and free
+ * the memory.
+ *
+ * Requires:
+ * 'outtoken' to != NULL && *outtoken == NULL.
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
isc_result_t
-dst_gssapi_acceptctx(dns_name_t *name, void *cred,
- isc_region_t *intoken, isc_buffer_t *outtoken,
- void **context);
+dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx);
+/*
+ * Destroys a GSS context. This function deletes the context from the GSS
+ * provider and then frees the memory used by the context pointer.
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'context' is a valid GSS context
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ */
+
+
+void
+gss_log(int level, const char *fmt, ...)
+ISC_FORMAT_PRINTF(2, 3);
+/*
+ * Logging function for GSS.
+ *
+ * Requires
+ * 'level' is the log level to be used, as an integer
+ * 'fmt' is a printf format specifier
+ */
+
+char *
+gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
+ char *buf, size_t buflen);
+/*
+ * Render a GSS major status/minor status pair into a string
+ *
+ * Requires:
+ * 'major' is a GSS major status code
+ * 'minor' is a GSS minor status code
+ *
+ * Returns:
+ * A string containing the text representation of the error codes.
+ * Users should copy the string if they wish to keep it.
+ */
+isc_boolean_t
+dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm);
/*
- * XXX
+ * Compare a "signer" (in the format of a Kerberos-format Kerberos5
+ * principal: host/example.com@EXAMPLE.COM) to the realm name stored
+ * in "name" (which represents the realm name).
+ *
+ */
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm);
+/*
+ * Compare a "signer" (in the format of a Kerberos-format Kerberos5
+ * principal: host/example.com@EXAMPLE.COM) to the realm name stored
+ * in "name" (which represents the realm name).
+ *
*/
ISC_LANG_ENDDECLS
diff --git a/lib/dns/include/dst/lib.h b/lib/dns/include/dst/lib.h
index bd71261..886575e 100644
--- a/lib/dns/include/dst/lib.h
+++ b/lib/dns/include/dst/lib.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lib.h,v 1.1.6.3 2005/04/29 00:16:29 marka Exp $ */
+/* $Id: lib.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DST_LIB_H
#define DST_LIB_H 1
-/*! \file */
+/*! \file dst/lib.h */
#include <isc/types.h>
#include <isc/lang.h>
diff --git a/lib/dns/include/dst/result.h b/lib/dns/include/dst/result.h
index aa03b73..d77b72e 100644
--- a/lib/dns/include/dst/result.h
+++ b/lib/dns/include/dst/result.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.h,v 1.1.6.3 2005/04/29 00:16:29 marka Exp $ */
+/* $Id: result.h,v 1.9 2008/04/01 23:47:10 tbox Exp $ */
#ifndef DST_RESULT_H
#define DST_RESULT_H 1
-/*! \file */
+/*! \file dst/result.h */
#include <isc/lang.h>
#include <isc/resultclass.h>
@@ -54,8 +54,9 @@
#define DST_R_COMPUTESECRETFAILURE (ISC_RESULTCLASS_DST + 18)
#define DST_R_NORANDOMNESS (ISC_RESULTCLASS_DST + 19)
#define DST_R_BADKEYTYPE (ISC_RESULTCLASS_DST + 20)
+#define DST_R_NOENGINE (ISC_RESULTCLASS_DST + 21)
-#define DST_R_NRESULTS 21 /* Number of results */
+#define DST_R_NRESULTS 22 /* Number of results */
ISC_LANG_BEGINDECLS
diff --git a/lib/dns/iptable.c b/lib/dns/iptable.c
new file mode 100644
index 0000000..55a5351
--- /dev/null
+++ b/lib/dns/iptable.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2007-2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: iptable.c,v 1.12.44.3 2009/02/18 23:47:12 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/radix.h>
+
+#include <dns/acl.h>
+
+static void destroy_iptable(dns_iptable_t *dtab);
+
+/*
+ * Create a new IP table and the underlying radix structure
+ */
+isc_result_t
+dns_iptable_create(isc_mem_t *mctx, dns_iptable_t **target) {
+ isc_result_t result;
+ dns_iptable_t *tab;
+
+ tab = isc_mem_get(mctx, sizeof(*tab));
+ if (tab == NULL)
+ return (ISC_R_NOMEMORY);
+ tab->mctx = mctx;
+ isc_refcount_init(&tab->refcount, 1);
+ tab->radix = NULL;
+ tab->magic = DNS_IPTABLE_MAGIC;
+
+ result = isc_radix_create(mctx, &tab->radix, RADIX_MAXBITS);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ *target = tab;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_iptable_detach(&tab);
+ return (result);
+}
+
+isc_boolean_t dns_iptable_neg = ISC_FALSE;
+isc_boolean_t dns_iptable_pos = ISC_TRUE;
+
+/*
+ * Add an IP prefix to an existing IP table
+ */
+isc_result_t
+dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
+ isc_uint16_t bitlen, isc_boolean_t pos)
+{
+ isc_result_t result;
+ isc_prefix_t pfx;
+ isc_radix_node_t *node = NULL;
+ int family;
+
+ INSIST(DNS_IPTABLE_VALID(tab));
+ INSIST(tab->radix);
+
+ NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
+
+ result = isc_radix_insert(tab->radix, &node, NULL, &pfx);
+ if (result != ISC_R_SUCCESS) {
+ isc_refcount_destroy(&pfx.refcount);
+ return(result);
+ }
+
+ /* If a node already contains data, don't overwrite it */
+ family = pfx.family;
+ if (family == AF_UNSPEC) {
+ /* "any" or "none" */
+ INSIST(pfx.bitlen == 0);
+ if (pos) {
+ if (node->data[0] == NULL)
+ node->data[0] = &dns_iptable_pos;
+ if (node->data[1] == NULL)
+ node->data[1] = &dns_iptable_pos;
+ } else {
+ if (node->data[0] == NULL)
+ node->data[0] = &dns_iptable_neg;
+ if (node->data[1] == NULL)
+ node->data[1] = &dns_iptable_neg;
+ }
+ } else {
+ /* any other prefix */
+ if (node->data[ISC_IS6(family)] == NULL) {
+ if (pos)
+ node->data[ISC_IS6(family)] = &dns_iptable_pos;
+ else
+ node->data[ISC_IS6(family)] = &dns_iptable_neg;
+ }
+ }
+
+ isc_refcount_destroy(&pfx.refcount);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Merge one IP table into another one.
+ */
+isc_result_t
+dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos)
+{
+ isc_result_t result;
+ isc_radix_node_t *node, *new_node;
+ int max_node = 0;
+
+ RADIX_WALK (source->radix->head, node) {
+ new_node = NULL;
+ result = isc_radix_insert (tab->radix, &new_node, node, NULL);
+
+ if (result != ISC_R_SUCCESS)
+ return(result);
+
+ /*
+ * If we're negating a nested ACL, then we should
+ * reverse the sense of every node. However, this
+ * could lead to a negative node in a nested ACL
+ * becoming a positive match in the parent, which
+ * could be a security risk. To prevent this, we
+ * just leave the negative nodes negative.
+ */
+ if (!pos) {
+ if (node->data[0] &&
+ *(isc_boolean_t *) node->data[0] == ISC_TRUE)
+ new_node->data[0] = &dns_iptable_neg;
+
+ if (node->data[1] &&
+ *(isc_boolean_t *) node->data[1] == ISC_TRUE)
+ new_node->data[1] = &dns_iptable_neg;
+ }
+
+ if (node->node_num[0] > max_node)
+ max_node = node->node_num[0];
+ if (node->node_num[1] > max_node)
+ max_node = node->node_num[1];
+ } RADIX_WALK_END;
+
+ tab->radix->num_added_node += max_node;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_iptable_attach(dns_iptable_t *source, dns_iptable_t **target) {
+ REQUIRE(DNS_IPTABLE_VALID(source));
+ isc_refcount_increment(&source->refcount, NULL);
+ *target = source;
+}
+
+void
+dns_iptable_detach(dns_iptable_t **tabp) {
+ dns_iptable_t *tab = *tabp;
+ unsigned int refs;
+ REQUIRE(DNS_IPTABLE_VALID(tab));
+ isc_refcount_decrement(&tab->refcount, &refs);
+ if (refs == 0)
+ destroy_iptable(tab);
+ *tabp = NULL;
+}
+
+static void
+destroy_iptable(dns_iptable_t *dtab) {
+
+ REQUIRE(DNS_IPTABLE_VALID(dtab));
+
+ if (dtab->radix != NULL) {
+ isc_radix_destroy(dtab->radix, NULL);
+ dtab->radix = NULL;
+ }
+
+ isc_refcount_destroy(&dtab->refcount);
+ dtab->magic = 0;
+ isc_mem_put(dtab->mctx, dtab, sizeof(*dtab));
+}
diff --git a/lib/dns/journal.c b/lib/dns/journal.c
index 4e4010f..8c21f1e 100644
--- a/lib/dns/journal.c
+++ b/lib/dns/journal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: journal.c,v 1.86.18.14 2008/09/25 04:01:36 tbox Exp $ */
+/* $Id: journal.c,v 1.103.48.2 2009/01/18 23:47:37 tbox Exp $ */
#include <config.h>
@@ -42,7 +42,7 @@
#include <dns/soa.h>
/*! \file
- * \brief Journalling.
+ * \brief Journaling.
*
* A journal file consists of
*
@@ -172,7 +172,7 @@ dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
return (result);
}
-/* Journalling */
+/* Journaling */
/*%
* On-disk representation of a "pointer" to a journal entry.
@@ -641,7 +641,7 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
dns_rdata_init(&j->it.rdata);
/*
- * Set up empty initial buffers for uncheched and checked
+ * Set up empty initial buffers for unchecked and checked
* wire format RR data. They will be reallocated
* later.
*/
@@ -709,8 +709,35 @@ ixfr_order(const void *av, const void *bv) {
dns_difftuple_t const *a = *ap;
dns_difftuple_t const *b = *bp;
int r;
+ int bop = 0, aop = 0;
+
+ switch (a->op) {
+ case DNS_DIFFOP_DEL:
+ case DNS_DIFFOP_DELRESIGN:
+ aop = 1;
+ break;
+ case DNS_DIFFOP_ADD:
+ case DNS_DIFFOP_ADDRESIGN:
+ aop = 0;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ switch (b->op) {
+ case DNS_DIFFOP_DEL:
+ case DNS_DIFFOP_DELRESIGN:
+ bop = 1;
+ break;
+ case DNS_DIFFOP_ADD:
+ case DNS_DIFFOP_ADDRESIGN:
+ bop = 0;
+ break;
+ default:
+ INSIST(0);
+ }
- r = (b->op == DNS_DIFFOP_DEL) - (a->op == DNS_DIFFOP_DEL);
+ r = bop - aop;
if (r != 0)
return (r);
@@ -1191,7 +1218,7 @@ dns_journal_destroy(dns_journal_t **journalp) {
/* XXX Share code with incoming IXFR? */
static isc_result_t
-roll_forward(dns_journal_t *j, dns_db_t *db) {
+roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options) {
isc_buffer_t source; /* Transaction data from disk */
isc_buffer_t target; /* Ditto after _fromwire check */
isc_uint32_t db_serial; /* Database SOA serial */
@@ -1202,6 +1229,7 @@ roll_forward(dns_journal_t *j, dns_db_t *db) {
dns_diff_t diff;
unsigned int n_soa = 0;
unsigned int n_put = 0;
+ dns_diffop_t op;
REQUIRE(DNS_JOURNAL_VALID(j));
REQUIRE(DNS_DB_VALID(db));
@@ -1209,7 +1237,7 @@ roll_forward(dns_journal_t *j, dns_db_t *db) {
dns_diff_init(j->mctx, &diff);
/*
- * Set up empty initial buffers for uncheched and checked
+ * Set up empty initial buffers for unchecked and checked
* wire format transaction data. They will be reallocated
* later.
*/
@@ -1273,9 +1301,14 @@ roll_forward(dns_journal_t *j, dns_db_t *db) {
"initial SOA", j->filename);
FAIL(ISC_R_UNEXPECTED);
}
- CHECK(dns_difftuple_create(diff.mctx, n_soa == 1 ?
- DNS_DIFFOP_DEL : DNS_DIFFOP_ADD,
- name, ttl, rdata, &tuple));
+ if ((options & DNS_JOURNALOPT_RESIGN) != 0)
+ op = (n_soa == 1) ? DNS_DIFFOP_DELRESIGN :
+ DNS_DIFFOP_ADDRESIGN;
+ else
+ op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
+
+ CHECK(dns_difftuple_create(diff.mctx, op, name, ttl, rdata,
+ &tuple));
dns_diff_append(&diff, &tuple);
if (++n_put > 100) {
@@ -1317,7 +1350,9 @@ roll_forward(dns_journal_t *j, dns_db_t *db) {
}
isc_result_t
-dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, const char *filename) {
+dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db,
+ unsigned int options, const char *filename)
+{
dns_journal_t *j;
isc_result_t result;
@@ -1336,7 +1371,7 @@ dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, const char *filename) {
if (JOURNAL_EMPTY(&j->header))
result = DNS_R_UPTODATE;
else
- result = roll_forward(j, db);
+ result = roll_forward(j, db, options);
dns_journal_destroy(&j);
@@ -1374,7 +1409,7 @@ dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) {
dns_diff_init(j->mctx, &diff);
/*
- * Set up empty initial buffers for uncheched and checked
+ * Set up empty initial buffers for unchecked and checked
* wire format transaction data. They will be reallocated
* later.
*/
@@ -1852,10 +1887,10 @@ dns_db_diff(isc_mem_t *mctx,
if (result != ISC_R_SUCCESS)
return (result);
- result = dns_db_createiterator(db[0], ISC_FALSE, &dbit[0]);
+ result = dns_db_createiterator(db[0], 0, &dbit[0]);
if (result != ISC_R_SUCCESS)
goto cleanup_journal;
- result = dns_db_createiterator(db[1], ISC_FALSE, &dbit[1]);
+ result = dns_db_createiterator(db[1], 0, &dbit[1]);
if (result != ISC_R_SUCCESS)
goto cleanup_interator0;
diff --git a/lib/dns/key.c b/lib/dns/key.c
index b0f2c0a..5cf4442 100644
--- a/lib/dns/key.c
+++ b/lib/dns/key.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: key.c,v 1.1.6.6 2006/01/27 23:57:44 marka Exp $ */
+/* $Id: key.c,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
#include <config.h>
diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c
index ec0f8e4..bffd2d3 100644
--- a/lib/dns/keytable.c
+++ b/lib/dns/keytable.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keytable.c,v 1.28.18.4 2005/12/05 00:00:03 marka Exp $ */
+/* $Id: keytable.c,v 1.34 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/lib.c b/lib/dns/lib.c
index 423908a..6f98b537 100644
--- a/lib/dns/lib.c
+++ b/lib/dns/lib.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lib.c,v 1.11.18.3 2005/08/15 01:46:50 marka Exp $ */
+/* $Id: lib.c,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/log.c b/lib/dns/log.c
index 939ea36..7551e15 100644
--- a/lib/dns/log.c
+++ b/lib/dns/log.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.c,v 1.36.18.4 2005/09/05 00:18:24 marka Exp $ */
+/* $Id: log.c,v 1.45 2007/06/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -29,7 +29,7 @@
/*%
* When adding a new category, be sure to add the appropriate
- * #define to <dns/log.h>.
+ * \#define to <dns/log.h>.
*/
LIBDNS_EXTERNAL_DATA isc_logcategory_t dns_categories[] = {
{ "notify", 0 },
@@ -43,12 +43,13 @@ LIBDNS_EXTERNAL_DATA isc_logcategory_t dns_categories[] = {
{ "dispatch", 0 },
{ "lame-servers", 0 },
{ "delegation-only", 0 },
+ { "edns-disabled", 0 },
{ NULL, 0 }
};
/*%
* When adding a new module, be sure to add the appropriate
- * #define to <dns/log.h>.
+ * \#define to <dns/log.h>.
*/
LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = {
{ "dns/db", 0 },
diff --git a/lib/dns/lookup.c b/lib/dns/lookup.c
index a3ddad4..d5fc7aa 100644
--- a/lib/dns/lookup.c
+++ b/lib/dns/lookup.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lookup.c,v 1.14.18.7 2007/08/28 07:20:04 tbox Exp $ */
+/* $Id: lookup.c,v 1.21 2007/06/18 23:47:40 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/master.c b/lib/dns/master.c
index b04f2eb..462269e 100644
--- a/lib/dns/master.c
+++ b/lib/dns/master.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: master.c,v 1.148.18.21 2008/01/17 23:45:58 tbox Exp $ */
+/* $Id: master.c,v 1.171.120.2 2009/01/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -139,6 +139,7 @@ struct dns_loadctx {
/* locked by lock */
isc_uint32_t references;
dns_incctx_t *inc;
+ isc_uint32_t resign;
};
struct dns_incctx {
@@ -503,7 +504,7 @@ incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
static isc_result_t
loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
- unsigned int options, dns_name_t *top,
+ unsigned int options, isc_uint32_t resign, dns_name_t *top,
dns_rdataclass_t zclass, dns_name_t *origin,
dns_rdatacallbacks_t *callbacks, isc_task_t *task,
dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex,
@@ -580,6 +581,7 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
lctx->options = options;
lctx->seen_include = ISC_FALSE;
lctx->zclass = zclass;
+ lctx->resign = resign;
lctx->result = ISC_R_SUCCESS;
dns_fixedname_init(&lctx->fixed_top);
@@ -1738,8 +1740,7 @@ load_text(dns_loadctx_t *lctx) {
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(ictx->current, namebuf,
sizeof(namebuf));
- (*callbacks->error)(callbacks,
- "%s:%lu: SOA "
+ (*callbacks->error)(callbacks, "%s:%lu: SOA "
"record not at top of zone (%s)",
source, line, namebuf);
result = DNS_R_NOTZONETOP;
@@ -1834,7 +1835,7 @@ load_text(dns_loadctx_t *lctx) {
/*
* Find type in rdatalist.
* If it does not exist create new one and prepend to list
- * as this will mimimise list traversal.
+ * as this will minimise list traversal.
*/
if (ictx->glue != NULL)
this = ISC_LIST_HEAD(glue_list);
@@ -2324,8 +2325,8 @@ dns_master_loadfile(const char *master_file, dns_name_t *top,
dns_rdataclass_t zclass, unsigned int options,
dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
{
- return (dns_master_loadfile2(master_file, top, origin, zclass, options,
- callbacks, mctx, dns_masterformat_text));
+ return (dns_master_loadfile3(master_file, top, origin, zclass, options,
+ 0, callbacks, mctx, dns_masterformat_text));
}
isc_result_t
@@ -2335,11 +2336,23 @@ dns_master_loadfile2(const char *master_file, dns_name_t *top,
dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
dns_masterformat_t format)
{
+ return (dns_master_loadfile3(master_file, top, origin, zclass, options,
+ 0, callbacks, mctx, format));
+}
+
+isc_result_t
+dns_master_loadfile3(const char *master_file, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options, isc_uint32_t resign,
+ dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
+ dns_masterformat_t format)
+{
dns_loadctx_t *lctx = NULL;
isc_result_t result;
- result = loadctx_create(format, mctx, options, top, zclass, origin,
- callbacks, NULL, NULL, NULL, NULL, &lctx);
+ result = loadctx_create(format, mctx, options, resign, top, zclass,
+ origin, callbacks, NULL, NULL, NULL, NULL,
+ &lctx);
if (result != ISC_R_SUCCESS)
return (result);
@@ -2362,8 +2375,8 @@ dns_master_loadfileinc(const char *master_file, dns_name_t *top,
isc_task_t *task, dns_loaddonefunc_t done,
void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
{
- return (dns_master_loadfileinc2(master_file, top, origin, zclass,
- options, callbacks, task, done,
+ return (dns_master_loadfileinc3(master_file, top, origin, zclass,
+ options, 0, callbacks, task, done,
done_arg, lctxp, mctx,
dns_masterformat_text));
}
@@ -2376,14 +2389,29 @@ dns_master_loadfileinc2(const char *master_file, dns_name_t *top,
void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx,
dns_masterformat_t format)
{
+ return (dns_master_loadfileinc3(master_file, top, origin, zclass,
+ options, 0, callbacks, task, done,
+ done_arg, lctxp, mctx, format));
+}
+
+isc_result_t
+dns_master_loadfileinc3(const char *master_file, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options, isc_uint32_t resign,
+ dns_rdatacallbacks_t *callbacks, isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **lctxp, isc_mem_t *mctx,
+ dns_masterformat_t format)
+{
dns_loadctx_t *lctx = NULL;
isc_result_t result;
REQUIRE(task != NULL);
REQUIRE(done != NULL);
- result = loadctx_create(format, mctx, options, top, zclass, origin,
- callbacks, task, done, done_arg, NULL, &lctx);
+ result = loadctx_create(format, mctx, options, resign, top, zclass,
+ origin, callbacks, task, done, done_arg, NULL,
+ &lctx);
if (result != ISC_R_SUCCESS)
return (result);
@@ -2412,7 +2440,7 @@ dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
REQUIRE(stream != NULL);
- result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
zclass, origin, callbacks, NULL, NULL, NULL,
NULL, &lctx);
if (result != ISC_R_SUCCESS)
@@ -2445,7 +2473,7 @@ dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
REQUIRE(task != NULL);
REQUIRE(done != NULL);
- result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
zclass, origin, callbacks, task, done,
done_arg, NULL, &lctx);
if (result != ISC_R_SUCCESS)
@@ -2478,7 +2506,7 @@ dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
REQUIRE(buffer != NULL);
- result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
zclass, origin, callbacks, NULL, NULL, NULL,
NULL, &lctx);
if (result != ISC_R_SUCCESS)
@@ -2511,7 +2539,7 @@ dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
REQUIRE(task != NULL);
REQUIRE(done != NULL);
- result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
zclass, origin, callbacks, task, done,
done_arg, NULL, &lctx);
if (result != ISC_R_SUCCESS)
@@ -2543,7 +2571,7 @@ dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
REQUIRE(lex != NULL);
- result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
zclass, origin, callbacks, NULL, NULL, NULL,
lex, &lctx);
if (result != ISC_R_SUCCESS)
@@ -2571,7 +2599,7 @@ dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
REQUIRE(task != NULL);
REQUIRE(done != NULL);
- result = loadctx_create(dns_masterformat_text, mctx, options, top,
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
zclass, origin, callbacks, task, done,
done_arg, lex, &lctx);
if (result != ISC_R_SUCCESS)
@@ -2700,6 +2728,27 @@ grow_rdata(int new_len, dns_rdata_t *old, int old_len,
return (new);
}
+static isc_uint32_t
+resign_fromlist(dns_rdatalist_t *this, isc_uint32_t resign) {
+ dns_rdata_t *rdata;
+ dns_rdata_rrsig_t sig;
+ isc_uint32_t when;
+
+ rdata = ISC_LIST_HEAD(this->rdata);
+ INSIST(rdata != NULL);
+ (void)dns_rdata_tostruct(rdata, &sig, NULL);
+ when = sig.timeexpire - resign;
+
+ rdata = ISC_LIST_NEXT(rdata, link);
+ while (rdata != NULL) {
+ (void)dns_rdata_tostruct(rdata, &sig, NULL);
+ if (sig.timeexpire - resign < when)
+ when = sig.timeexpire - resign;
+ rdata = ISC_LIST_NEXT(rdata, link);
+ }
+ return (when);
+}
+
/*
* Convert each element from a rdatalist_t to rdataset then call commit.
* Unlink each element as we go.
@@ -2726,14 +2775,22 @@ commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
== ISC_R_SUCCESS);
dataset.trust = dns_trust_ultimate;
+ /*
+ * If this is a secure dynamic zone set the re-signing time.
+ */
+ if (dataset.type == dns_rdatatype_rrsig &&
+ (lctx->options & DNS_MASTER_RESIGN) != 0) {
+ dataset.attributes |= DNS_RDATASETATTR_RESIGN;
+ dns_name_format(owner, namebuf, sizeof(namebuf));
+ dataset.resign = resign_fromlist(this, lctx->resign);
+ }
result = ((*callbacks->add)(callbacks->add_private, owner,
&dataset));
if (result == ISC_R_NOMEMORY) {
(*error)(callbacks, "dns_master_load: %s",
dns_result_totext(result));
} else if (result != ISC_R_SUCCESS) {
- dns_name_format(owner, namebuf,
- sizeof(namebuf));
+ dns_name_format(owner, namebuf, sizeof(namebuf));
if (source != NULL) {
(*error)(callbacks, "%s: %s:%lu: %s: %s",
"dns_master_load", source, line,
diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c
index 1ffdfcb..5eac96f 100644
--- a/lib/dns/masterdump.c
+++ b/lib/dns/masterdump.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: masterdump.c,v 1.73.18.16 2008/08/13 23:46:04 tbox Exp $ */
+/* $Id: masterdump.c,v 1.94.50.2 2009/01/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -108,7 +108,8 @@ dns_master_style_default = {
LIBDNS_EXTERNAL_DATA const dns_master_style_t
dns_master_style_full = {
- DNS_STYLEFLAG_COMMENT,
+ DNS_STYLEFLAG_COMMENT |
+ DNS_STYLEFLAG_RESIGN,
46, 46, 46, 64, 120, 8
};
@@ -283,7 +284,7 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) {
/*
* Do not return ISC_R_NOSPACE if the line break string
* buffer is too small, because that would just make
- * dump_rdataset() retry indenfinitely with ever
+ * dump_rdataset() retry indefinitely with ever
* bigger target buffers. That's a different buffer,
* so it won't help. Use DNS_R_TEXTTOOLONG as a substitute.
*/
@@ -784,6 +785,13 @@ static const char *trustnames[] = {
"local" /* aka ultimate */
};
+const char *
+dns_trust_totext(dns_trust_t trust) {
+ if (trust >= sizeof(trustnames)/sizeof(*trustnames))
+ return ("bad");
+ return (trustnames[trust]);
+}
+
static isc_result_t
dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name,
dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
@@ -840,6 +848,15 @@ dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name,
if ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0)
name = NULL;
}
+ if (ctx->style.flags & DNS_STYLEFLAG_RESIGN &&
+ rds->attributes & DNS_RDATASETATTR_RESIGN) {
+ isc_buffer_t b;
+ char buf[sizeof("YYYYMMDDHHMMSS")];
+ memset(buf, 0, sizeof(buf));
+ isc_buffer_init(&b, buf, sizeof(buf) - 1);
+ dns_time64_totext((isc_uint64_t)rds->resign, &b);
+ fprintf(f, "; resign=%s\n", buf);
+ }
dns_rdataset_disassociate(rds);
}
@@ -1020,9 +1037,9 @@ dumpctx_destroy(dns_dumpctx_t *dctx) {
dctx->magic = 0;
DESTROYLOCK(&dctx->lock);
+ dns_dbiterator_destroy(&dctx->dbiter);
if (dctx->version != NULL)
dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
- dns_dbiterator_destroy(&dctx->dbiter);
dns_db_detach(&dctx->db);
if (dctx->task != NULL)
isc_task_detach(&dctx->task);
@@ -1177,7 +1194,7 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
{
dns_dumpctx_t *dctx;
isc_result_t result;
- isc_boolean_t relative;
+ unsigned int options;
dctx = isc_mem_get(mctx, sizeof(*dctx));
if (dctx == NULL)
@@ -1224,10 +1241,10 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
if (dctx->format == dns_masterformat_text &&
(dctx->tctx.style.flags & DNS_STYLEFLAG_REL_OWNER) != 0) {
- relative = ISC_TRUE;
+ options = DNS_DB_RELATIVENAMES;
} else
- relative = ISC_FALSE;
- result = dns_db_createiterator(dctx->db, relative, &dctx->dbiter);
+ options = 0;
+ result = dns_db_createiterator(dctx->db, options, &dctx->dbiter);
if (result != ISC_R_SUCCESS)
goto cleanup;
diff --git a/lib/dns/message.c b/lib/dns/message.c
index 8c56377..b541635 100644
--- a/lib/dns/message.c
+++ b/lib/dns/message.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: message.c,v 1.222.18.16 2008/07/28 23:46:20 tbox Exp $ */
+/* $Id: message.c,v 1.245.50.2 2009/01/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -24,6 +24,7 @@
***/
#include <config.h>
+#include <ctype.h>
#include <isc/buffer.h>
#include <isc/mem.h>
@@ -45,6 +46,35 @@
#include <dns/tsig.h>
#include <dns/view.h>
+#ifdef SKAN_MSG_DEBUG
+static void
+hexdump(const char *msg, const char *msg2, void *base, size_t len) {
+ unsigned char *p;
+ unsigned int cnt;
+
+ p = base;
+ cnt = 0;
+
+ printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base);
+
+ while (cnt < len) {
+ if (cnt % 16 == 0)
+ printf("%p: ", p);
+ else if (cnt % 8 == 0)
+ printf(" |");
+ printf(" %02x %c", *p, (isprint(*p) ? *p : ' '));
+ p++;
+ cnt++;
+
+ if (cnt % 16 == 0)
+ printf("\n");
+ }
+
+ if (cnt % 16 != 0)
+ printf("\n");
+}
+#endif
+
#define DNS_MESSAGE_OPCODE_MASK 0x7800U
#define DNS_MESSAGE_OPCODE_SHIFT 11
#define DNS_MESSAGE_RCODE_MASK 0x000fU
@@ -65,6 +95,8 @@
#define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
&& ((s) < DNS_PSEUDOSECTION_MAX))
+#define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
+
/*%
* This is the size of each individual scratchpad buffer, and the numbers
* of various block allocations used within the server.
@@ -138,7 +170,7 @@ static const char *rcodetext[] = {
/*%
* "helper" type, which consists of a block of some type, and is linkable.
* For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
- * size, or the allocated elements will not be alligned correctly.
+ * size, or the allocated elements will not be aligned correctly.
*/
struct dns_msgblock {
unsigned int count;
@@ -1462,14 +1494,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
rdataset->ttl = ttl;
}
- /*
- * XXXMLG Perform a totally ugly hack here to pull
- * the rdatalist out of the private field in the rdataset,
- * and append this rdata to the rdatalist's linked list
- * of rdata.
- */
- rdatalist = (dns_rdatalist_t *)(rdataset->private1);
-
+ /* Append this rdata to the rdataset. */
+ dns_rdatalist_fromrdataset(rdataset, &rdatalist);
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
/*
@@ -1934,7 +1960,7 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
*
* XXXMLG Need to change this when
* dns_rdataset_towire() can render partial
- * sets starting at some arbitary point in the
+ * sets starting at some arbitrary point in the
* set. This will include setting a bit in the
* rdataset to indicate that a partial
* rendering was done, and some state saved
@@ -1964,6 +1990,8 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
(sectionid == DNS_SECTION_ANSWER ||
sectionid == DNS_SECTION_AUTHORITY))
msg->flags &= ~DNS_MESSAGEFLAG_AD;
+ if (OPTOUT(rdataset))
+ msg->flags &= ~DNS_MESSAGEFLAG_AD;
rdataset->attributes |=
DNS_RDATASETATTR_RENDERED;
@@ -2899,6 +2927,35 @@ dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
return (dns_message_checksig(msg, view));
}
+#ifdef SKAN_MSG_DEBUG
+void
+dns_message_dumpsig(dns_message_t *msg, char *txt1) {
+ dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
+ dns_rdata_any_tsig_t querytsig;
+ isc_result_t result;
+
+ if (msg->tsig != NULL) {
+ result = dns_rdataset_first(msg->tsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(msg->tsig, &querytsigrdata);
+ result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ hexdump(txt1, "TSIG", querytsig.signature,
+ querytsig.siglen);
+ }
+
+ if (msg->querytsig != NULL) {
+ result = dns_rdataset_first(msg->querytsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(msg->querytsig, &querytsigrdata);
+ result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ hexdump(txt1, "QUERYTSIG", querytsig.signature,
+ querytsig.siglen);
+ }
+}
+#endif
+
isc_result_t
dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
isc_buffer_t b, msgb;
@@ -2907,10 +2964,14 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
return (ISC_R_SUCCESS);
+
INSIST(msg->saved.base != NULL);
isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
isc_buffer_add(&msgb, msg->saved.length);
if (msg->tsigkey != NULL || msg->tsig != NULL) {
+#ifdef SKAN_MSG_DEBUG
+ dns_message_dumpsig(msg, "dns_message_checksig#1");
+#endif
if (view != NULL)
return (dns_view_checksig(view, &msgb, msg));
else
@@ -2963,6 +3024,7 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
{
dst_key_t *key = NULL;
+ dns_rdata_reset(&rdata);
dns_rdataset_current(&keyset, &rdata);
isc_buffer_init(&b, rdata.data, rdata.length);
isc_buffer_add(&b, rdata.length);
@@ -3068,6 +3130,10 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
isc_result_t result;
char buf[sizeof("1234567890")];
isc_uint32_t mbz;
+ dns_rdata_t rdata;
+ isc_buffer_t optbuf;
+ isc_uint16_t optcode, optlen;
+ unsigned char *optdata;
REQUIRE(DNS_MESSAGE_VALID(msg));
REQUIRE(target != NULL);
@@ -3097,6 +3163,50 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
ADD_STRING(target, "; udp: ");
snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
ADD_STRING(target, buf);
+
+ result = dns_rdataset_first(ps);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+
+ /* Print EDNS info, if any */
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(ps, &rdata);
+ if (rdata.length < 4)
+ return (ISC_R_SUCCESS);
+
+ isc_buffer_init(&optbuf, rdata.data, rdata.length);
+ isc_buffer_add(&optbuf, rdata.length);
+ optcode = isc_buffer_getuint16(&optbuf);
+ optlen = isc_buffer_getuint16(&optbuf);
+
+ if (optcode == DNS_OPT_NSID) {
+ ADD_STRING(target, "; NSID");
+ } else {
+ ADD_STRING(target, "; OPT=");
+ sprintf(buf, "%u", optcode);
+ ADD_STRING(target, buf);
+ }
+
+ if (optlen != 0) {
+ int i;
+ ADD_STRING(target, ": ");
+
+ optdata = rdata.data + 4;
+ for (i = 0; i < optlen; i++) {
+ sprintf(buf, "%02x ", optdata[i]);
+ ADD_STRING(target, buf);
+ }
+ for (i = 0; i < optlen; i++) {
+ ADD_STRING(target, " (");
+ if (isprint(optdata[i]))
+ isc_buffer_putmem(target, &optdata[i],
+ 1);
+ else
+ isc_buffer_putstr(target, ".");
+ ADD_STRING(target, ")");
+ }
+ }
+ ADD_STRING(target, "\n");
return (ISC_R_SUCCESS);
case DNS_PSEUDOSECTION_TSIG:
ps = dns_message_gettsig(msg, &name);
diff --git a/lib/dns/name.c b/lib/dns/name.c
index 7f5d4e9..f4ea3e9 100644
--- a/lib/dns/name.c
+++ b/lib/dns/name.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: name.c,v 1.144.18.16 2006/12/07 07:03:10 marka Exp $ */
+/* $Id: name.c,v 1.165 2008/04/01 23:47:10 tbox Exp $ */
/*! \file */
@@ -155,7 +155,7 @@ do { \
static unsigned char root_ndata[] = { '\0' };
static unsigned char root_offsets[] = { 0 };
-static dns_name_t root =
+static dns_name_t root =
{
DNS_NAME_MAGIC,
root_ndata, 1, 1,
@@ -298,7 +298,7 @@ dns_name_ismailbox(const dns_name_t *name) {
REQUIRE(name->labels > 0);
REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
- /*
+ /*
* Root label.
*/
if (name->length == 1)
@@ -312,7 +312,7 @@ dns_name_ismailbox(const dns_name_t *name) {
if (!domainchar(ch))
return (ISC_FALSE);
}
-
+
if (ndata == name->ndata + name->length)
return (ISC_FALSE);
@@ -347,8 +347,8 @@ dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
REQUIRE(VALID_NAME(name));
REQUIRE(name->labels > 0);
REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
-
- /*
+
+ /*
* Root label.
*/
if (name->length == 1)
@@ -918,7 +918,7 @@ dns_name_getlabelsequence(const dns_name_t *source,
target->ndata = &source->ndata[firstoffset];
target->length = endoffset - firstoffset;
-
+
if (first + n == source->labels && n > 0 &&
(source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
@@ -991,7 +991,7 @@ dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
name->length = len;
} else {
name->ndata = r->base;
- name->length = (r->length <= DNS_NAME_MAXWIRE) ?
+ name->length = (r->length <= DNS_NAME_MAXWIRE) ?
r->length : DNS_NAME_MAXWIRE;
}
@@ -1049,7 +1049,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
REQUIRE(ISC_BUFFER_VALID(source));
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
-
+
downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
if (target == NULL && name->buffer != NULL) {
@@ -1297,24 +1297,25 @@ totext_filter_proc_key_init(void) {
if (result != ISC_R_SUCCESS)
return (result);
- if (!thread_key_initialized) {
+ if (!thread_key_initialized) {
LOCK(&thread_key_mutex);
if (thread_key_mctx == NULL)
result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
if (result != ISC_R_SUCCESS)
goto unlock;
+ isc_mem_setname(thread_key_mctx, "threadkey", NULL);
isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
-
+
if (!thread_key_initialized &&
isc_thread_key_create(&totext_filter_proc_key,
- free_specific) != 0) {
+ free_specific) != 0) {
result = ISC_R_FAILURE;
isc_mem_detach(&thread_key_mctx);
} else
thread_key_initialized = 1;
unlock:
UNLOCK(&thread_key_mutex);
- }
+ }
return (result);
}
#endif
@@ -1930,7 +1931,8 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
methods = dns_compress_getmethods(cctx);
- if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
+ if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
+ (methods & DNS_COMPRESS_GLOBAL14) != 0)
gf = dns_compress_findglobal(cctx, name, &gp, &go);
else
gf = ISC_FALSE;
@@ -2298,7 +2300,7 @@ dns_name_settotextfilter(dns_name_totextfilter_t proc) {
result = ISC_R_UNEXPECTED;
return (result);
}
-
+
mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
if (mem == NULL)
return (ISC_R_NOMEMORY);
diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c
index 1fdc5c8..af0450b 100644
--- a/lib/dns/ncache.c
+++ b/lib/dns/ncache.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.c,v 1.36.18.3 2005/04/29 00:15:59 marka Exp $ */
+/* $Id: ncache.c,v 1.43 2008/09/25 04:02:38 tbox Exp $ */
/*! \file */
@@ -30,6 +30,9 @@
#include <dns/rdata.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+
+#define DNS_NCACHE_RDATA 20U
/*
* The format of an ncache rdata is a sequence of one or more records of
@@ -92,6 +95,16 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
dns_rdataset_t *addedrdataset)
{
+ return (dns_ncache_addoptout(message, cache, node, covers, now, maxttl,
+ ISC_FALSE, addedrdataset));
+}
+
+isc_result_t
+dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
+ dns_dbnode_t *node, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_ttl_t maxttl,
+ isc_boolean_t optout, dns_rdataset_t *addedrdataset)
+{
isc_result_t result;
isc_buffer_t buffer;
isc_region_t r;
@@ -100,10 +113,11 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_name_t *name;
dns_ttl_t ttl;
dns_trust_t trust;
- dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t rdata[DNS_NCACHE_RDATA];
dns_rdataset_t ncrdataset;
dns_rdatalist_t ncrdatalist;
unsigned char data[4096];
+ unsigned int next = 0;
/*
* Convert the authority data from 'message' into a negative cache
@@ -118,7 +132,17 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
*/
/*
- * First, build an ncache rdata in buffer.
+ * Initialize the list.
+ */
+ ncrdatalist.rdclass = dns_db_class(cache);
+ ncrdatalist.type = 0;
+ ncrdatalist.covers = covers;
+ ncrdatalist.ttl = maxttl;
+ ISC_LIST_INIT(ncrdatalist.rdata);
+ ISC_LINK_INIT(&ncrdatalist, link);
+
+ /*
+ * Build an ncache rdatas into buffer.
*/
ttl = maxttl;
trust = 0xffff;
@@ -142,7 +166,8 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
if (type == dns_rdatatype_rrsig)
type = rdataset->covers;
if (type == dns_rdatatype_soa ||
- type == dns_rdatatype_nsec) {
+ type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3) {
if (ttl > rdataset->ttl)
ttl = rdataset->ttl;
if (trust > rdataset->trust)
@@ -171,6 +196,21 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
&buffer);
if (result != ISC_R_SUCCESS)
return (result);
+
+ if (next >= DNS_NCACHE_RDATA)
+ return (ISC_R_NOSPACE);
+ dns_rdata_init(&rdata[next]);
+ isc_buffer_remainingregion(&buffer, &r);
+ rdata[next].data = r.base;
+ rdata[next].length = r.length;
+ rdata[next].rdclass =
+ ncrdatalist.rdclass;
+ rdata[next].type = 0;
+ rdata[next].flags = 0;
+ ISC_LIST_APPEND(ncrdatalist.rdata,
+ &rdata[next], link);
+ isc_buffer_forward(&buffer, r.length);
+ next++;
}
}
}
@@ -226,27 +266,24 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
trust = dns_trust_authauthority;
} else
trust = dns_trust_additional;
+ /*
+ * Now add it to the cache.
+ */
+ if (next >= DNS_NCACHE_RDATA)
+ return (ISC_R_NOSPACE);
+ dns_rdata_init(&rdata[next]);
+ isc_buffer_remainingregion(&buffer, &r);
+ rdata[next].data = r.base;
+ rdata[next].length = r.length;
+ rdata[next].rdclass = ncrdatalist.rdclass;
+ rdata[next].type = 0;
+ rdata[next].flags = 0;
+ ISC_LIST_APPEND(ncrdatalist.rdata, &rdata[next], link);
}
- /*
- * Now add it to the cache.
- */
INSIST(trust != 0xffff);
- isc_buffer_usedregion(&buffer, &r);
- rdata.data = r.base;
- rdata.length = r.length;
- rdata.rdclass = dns_db_class(cache);
- rdata.type = 0;
- rdata.flags = 0;
-
- ncrdatalist.rdclass = rdata.rdclass;
- ncrdatalist.type = 0;
- ncrdatalist.covers = covers;
- ncrdatalist.ttl = ttl;
- ISC_LIST_INIT(ncrdatalist.rdata);
- ISC_LINK_INIT(&ncrdatalist, link);
- ISC_LIST_APPEND(ncrdatalist.rdata, &rdata, link);
+ ncrdatalist.ttl = ttl;
dns_rdataset_init(&ncrdataset);
RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
@@ -254,6 +291,8 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
ncrdataset.trust = trust;
if (message->rcode == dns_rcode_nxdomain)
ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
+ if (optout)
+ ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT;
return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset,
0, addedrdataset));
@@ -281,18 +320,14 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
REQUIRE(rdataset != NULL);
REQUIRE(rdataset->type == 0);
- result = dns_rdataset_first(rdataset);
- if (result != ISC_R_SUCCESS)
- return (result);
- dns_rdataset_current(rdataset, &rdata);
- INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
- isc_buffer_init(&source, rdata.data, rdata.length);
- isc_buffer_add(&source, rdata.length);
-
savedbuffer = *target;
-
count = 0;
- do {
+
+ result = dns_rdataset_first(rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
dns_name_init(&name, NULL);
isc_buffer_remainingregion(&source, &remaining);
dns_name_fromregion(&name, &remaining);
@@ -370,8 +405,12 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
count++;
}
- isc_buffer_remainingregion(&source, &remaining);
- } while (remaining.length > 0);
+ INSIST(isc_buffer_remaininglength(&source) == 0);
+ result = dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto rollback;
*countp = count;
@@ -478,6 +517,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
NULL,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
@@ -491,8 +532,6 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
isc_buffer_t source;
dns_name_t tname;
dns_rdatatype_t ttype;
- unsigned int i, rcount;
- isc_uint16_t length;
REQUIRE(ncacherdataset != NULL);
REQUIRE(ncacherdataset->type == 0);
@@ -501,14 +540,10 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
REQUIRE(type != dns_rdatatype_rrsig);
result = dns_rdataset_first(ncacherdataset);
- if (result != ISC_R_SUCCESS)
- return (result);
- dns_rdataset_current(ncacherdataset, &rdata);
- INSIST(dns_rdataset_next(ncacherdataset) == ISC_R_NOMORE);
- isc_buffer_init(&source, rdata.data, rdata.length);
- isc_buffer_add(&source, rdata.length);
-
- do {
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(ncacherdataset, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
dns_name_init(&tname, NULL);
isc_buffer_remainingregion(&source, &remaining);
dns_name_fromregion(&tname, &remaining);
@@ -523,21 +558,15 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
isc_buffer_remainingregion(&source, &remaining);
break;
}
-
- rcount = isc_buffer_getuint16(&source);
- for (i = 0; i < rcount; i++) {
- isc_buffer_remainingregion(&source, &remaining);
- INSIST(remaining.length >= 2);
- length = isc_buffer_getuint16(&source);
- isc_buffer_remainingregion(&source, &remaining);
- INSIST(remaining.length >= length);
- isc_buffer_forward(&source, length);
- }
- isc_buffer_remainingregion(&source, &remaining);
- } while (remaining.length > 0);
-
- if (remaining.length == 0)
+ result = dns_rdataset_next(ncacherdataset);
+ dns_rdata_reset(&rdata);
+ }
+ if (result == ISC_R_NOMORE)
return (ISC_R_NOTFOUND);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ INSIST(remaining.length != 0);
rdataset->methods = &rdataset_methods;
rdataset->rdclass = ncacherdataset->rdclass;
@@ -555,5 +584,75 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
*/
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
return (ISC_R_SUCCESS);
}
+
+void
+dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
+ dns_rdataset_t *rdataset)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t remaining, sigregion;
+ isc_buffer_t source;
+ dns_name_t tname;
+ dns_rdatatype_t type;
+ unsigned int count;
+ dns_rdata_rrsig_t rrsig;
+ unsigned char *raw;
+
+ REQUIRE(ncacherdataset != NULL);
+ REQUIRE(ncacherdataset->type == 0);
+ REQUIRE(found != NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+
+ dns_rdataset_current(ncacherdataset, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
+
+ dns_name_init(&tname, NULL);
+ isc_buffer_remainingregion(&source, &remaining);
+ dns_name_fromregion(found, &remaining);
+ INSIST(remaining.length >= found->length);
+ isc_buffer_forward(&source, found->length);
+ remaining.length -= found->length;
+
+ INSIST(remaining.length >= 4);
+ type = isc_buffer_getuint16(&source);
+ isc_buffer_remainingregion(&source, &remaining);
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = ncacherdataset->rdclass;
+ rdataset->type = type;
+ if (type == dns_rdatatype_rrsig) {
+ /*
+ * Extract covers from RRSIG.
+ */
+ raw = remaining.base;
+ count = raw[0] * 256 + raw[1];
+ INSIST(count > 0);
+ raw += 2;
+ sigregion.length = raw[0] * 256 + raw[1];
+ raw += 2;
+ sigregion.base = raw;
+ dns_rdata_reset(&rdata);
+ dns_rdata_fromregion(&rdata, rdataset->rdclass,
+ rdataset->type, &sigregion);
+ (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ rdataset->covers = rrsig.covered;
+ } else
+ rdataset->covers = 0;
+ rdataset->ttl = ncacherdataset->ttl;
+ rdataset->trust = ncacherdataset->trust;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+
+ rdataset->private3 = remaining.base;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
+}
diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c
index c1de67e..39f409c 100644
--- a/lib/dns/nsec.c
+++ b/lib/dns/nsec.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec.c,v 1.5.20.2 2005/04/29 00:15:59 marka Exp $ */
+/* $Id: nsec.c,v 1.11.48.2 2009/01/06 23:47:26 tbox Exp $ */
/*! \file */
@@ -33,6 +33,8 @@
#include <dns/rdatastruct.h>
#include <dns/result.h>
+#include <dst/dst.h>
+
#define RETERR(x) do { \
result = (x); \
if (result != ISC_R_SUCCESS) \
@@ -88,6 +90,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
*/
bm = r.base + r.length + 512;
nsec_bits = r.base + r.length;
+ set_bit(bm, dns_rdatatype_rrsig, 1);
set_bit(bm, dns_rdatatype_nsec, 1);
max_type = dns_rdatatype_nsec;
dns_rdataset_init(&rdataset);
@@ -100,7 +103,9 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
result = dns_rdatasetiter_next(rdsiter))
{
dns_rdatasetiter_current(rdsiter, &rdataset);
- if (rdataset.type != dns_rdatatype_nsec) {
+ if (rdataset.type != dns_rdatatype_nsec &&
+ rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig) {
if (rdataset.type > max_type)
max_type = rdataset.type;
set_bit(bm, rdataset.type, 1);
@@ -197,7 +202,7 @@ dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) {
/* This should never fail */
result = dns_rdata_tostruct(nsec, &nsecstruct, NULL);
INSIST(result == ISC_R_SUCCESS);
-
+
present = ISC_FALSE;
for (i = 0; i < nsecstruct.len; i += len) {
INSIST(i + 2 <= nsecstruct.len);
@@ -215,6 +220,58 @@ dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) {
type % 256));
break;
}
- dns_rdata_freestruct(&nsec);
+ dns_rdata_freestruct(&nsecstruct);
return (present);
}
+
+isc_result_t
+dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t *answer)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_dnskey_t dnskey;
+ isc_result_t result;
+
+ REQUIRE(answer != NULL);
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
+ 0, 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+
+ if (result == ISC_R_NOTFOUND) {
+ *answer = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (dnskey.algorithm == DST_ALG_RSAMD5 ||
+ dnskey.algorithm == DST_ALG_RSASHA1 ||
+ dnskey.algorithm == DST_ALG_DSA ||
+ dnskey.algorithm == DST_ALG_ECC)
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS)
+ *answer = ISC_TRUE;
+ if (result == ISC_R_NOMORE) {
+ *answer = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c
new file mode 100644
index 0000000..54a6993
--- /dev/null
+++ b/lib/dns/nsec3.c
@@ -0,0 +1,1377 @@
+/*
+ * Copyright (C) 2006, 2008 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: nsec3.c,v 1.6 2008/11/17 23:46:42 marka Exp $ */
+
+#include <config.h>
+
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/hex.h>
+#include <isc/iterated_hash.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dst/dst.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/fixedname.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+
+#define CHECK(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
+#define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
+#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
+
+static void
+set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
+ unsigned int shift, mask;
+
+ shift = 7 - (index % 8);
+ mask = 1 << shift;
+
+ if (bit != 0)
+ array[index / 8] |= mask;
+ else
+ array[index / 8] &= (~mask & 0xFF);
+}
+
+static unsigned int
+bit_isset(unsigned char *array, unsigned int index) {
+ unsigned int byte, shift, mask;
+
+ byte = array[index / 8];
+ shift = 7 - (index % 8);
+ mask = 1 << shift;
+
+ return ((byte & mask) != 0);
+}
+
+isc_result_t
+dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, unsigned int hashalg,
+ unsigned int flags, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length,
+ const unsigned char *nexthash, size_t hash_length,
+ unsigned char *buffer, dns_rdata_t *rdata)
+{
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ isc_region_t r;
+ unsigned int i, window;
+ int octet;
+ isc_boolean_t found;
+
+ unsigned char *nsec_bits, *bm;
+ unsigned int max_type;
+ dns_rdatasetiter_t *rdsiter;
+ unsigned char *p;
+
+ REQUIRE(salt_length < 256U);
+ REQUIRE(hash_length < 256U);
+ REQUIRE(flags <= 0xffU);
+ REQUIRE(hashalg <= 0xffU);
+ REQUIRE(iterations <= 0xffffU);
+
+ switch (hashalg) {
+ case dns_hash_sha1:
+ REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
+ break;
+ }
+
+ memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
+
+ p = buffer;
+
+ *p++ = hashalg;
+ *p++ = flags;
+
+ *p++ = iterations >> 8;
+ *p++ = iterations;
+
+ *p++ = salt_length;
+ memcpy(p, salt, salt_length);
+ p += salt_length;
+
+ *p++ = hash_length;
+ memcpy(p, nexthash, hash_length);
+ p += hash_length;
+
+ r.length = p - buffer;
+ r.base = buffer;
+
+ /*
+ * Use the end of the space for a raw bitmap leaving enough
+ * space for the window identifiers and length octets.
+ */
+ bm = r.base + r.length + 512;
+ nsec_bits = r.base + r.length;
+ max_type = 0;
+ if (node == NULL)
+ goto collapse_bitmap;
+ dns_rdataset_init(&rdataset);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ found = ISC_FALSE;
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter))
+ {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.type != dns_rdatatype_nsec &&
+ rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig) {
+ if (rdataset.type > max_type)
+ max_type = rdataset.type;
+ set_bit(bm, rdataset.type, 1);
+ /* Don't set RRSIG for insecure delegation. */
+ if (rdataset.type != dns_rdatatype_ns)
+ found = ISC_TRUE;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (found) {
+ if (dns_rdatatype_rrsig > max_type)
+ max_type = dns_rdatatype_rrsig;
+ set_bit(bm, dns_rdatatype_rrsig, 1);
+ }
+
+ /*
+ * At zone cuts, deny the existence of glue in the parent zone.
+ */
+ if (bit_isset(bm, dns_rdatatype_ns) &&
+ ! bit_isset(bm, dns_rdatatype_soa)) {
+ for (i = 0; i <= max_type; i++) {
+ if (bit_isset(bm, i) &&
+ ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
+ set_bit(bm, i, 0);
+ }
+ }
+
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ collapse_bitmap:
+ for (window = 0; window < 256; window++) {
+ if (window * 256 > max_type)
+ break;
+ for (octet = 31; octet >= 0; octet--)
+ if (bm[window * 32 + octet] != 0)
+ break;
+ if (octet < 0)
+ continue;
+ nsec_bits[0] = window;
+ nsec_bits[1] = octet + 1;
+ /*
+ * Note: potentially overlapping move.
+ */
+ memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
+ nsec_bits += 3 + octet;
+ }
+ r.length = nsec_bits - r.base;
+ INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
+ dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
+ dns_rdata_nsec3_t nsec3;
+ isc_result_t result;
+ isc_boolean_t present;
+ unsigned int i, len, window;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_nsec3);
+
+ /* This should never fail */
+ result = dns_rdata_tostruct(rdata, &nsec3, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+
+ present = ISC_FALSE;
+ for (i = 0; i < nsec3.len; i += len) {
+ INSIST(i + 2 <= nsec3.len);
+ window = nsec3.typebits[i];
+ len = nsec3.typebits[i + 1];
+ INSIST(len > 0 && len <= 32);
+ i += 2;
+ INSIST(i + len <= nsec3.len);
+ if (window * 256 > type)
+ break;
+ if ((window + 1) * 256 <= type)
+ continue;
+ if (type < (window * 256) + len * 8)
+ present = ISC_TF(bit_isset(&nsec3.typebits[i],
+ type % 256));
+ break;
+ }
+ dns_rdata_freestruct(&nsec3);
+ return (present);
+}
+
+isc_result_t
+dns_nsec3_hashname(dns_fixedname_t *result,
+ unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
+ size_t *hash_length, dns_name_t *name, dns_name_t *origin,
+ dns_hash_t hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t saltlength)
+{
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char nametext[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fixed;
+ dns_name_t *downcased;
+ isc_buffer_t namebuffer;
+ isc_region_t region;
+ size_t len;
+
+ if (rethash == NULL)
+ rethash = hash;
+
+ memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
+
+ dns_fixedname_init(&fixed);
+ downcased = dns_fixedname_name(&fixed);
+ dns_name_downcase(name, downcased, NULL);
+
+ /* hash the node name */
+ len = isc_iterated_hash(rethash, hashalg, iterations, salt, saltlength,
+ downcased->ndata, downcased->length);
+ if (len == 0U)
+ return (DNS_R_BADALG);
+
+ if (hash_length != NULL)
+ *hash_length = len;
+
+ /* convert the hash to base32hex */
+ region.base = rethash;
+ region.length = len;
+ isc_buffer_init(&namebuffer, nametext, sizeof nametext);
+ isc_base32hex_totext(&region, 1, "", &namebuffer);
+
+ /* convert the hex to a domain name */
+ dns_fixedname_init(result);
+ return (dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
+ origin, 0, NULL));
+}
+
+unsigned int
+dns_nsec3_hashlength(dns_hash_t hash) {
+
+ switch (hash) {
+ case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
+ }
+ return (0);
+}
+
+isc_boolean_t
+dns_nsec3_supportedhash(dns_hash_t hash) {
+ switch (hash) {
+ case dns_hash_sha1: return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+/*%
+ * Update a single RR in version 'ver' of 'db' and log the
+ * update in 'diff'.
+ *
+ * Ensures:
+ * \li '*tuple' == NULL. Either the tuple is freed, or its
+ * ownership has been transferred to the diff.
+ */
+static isc_result_t
+do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff)
+{
+ dns_diff_t temp_diff;
+ isc_result_t result;
+
+ /*
+ * Create a singleton diff.
+ */
+ dns_diff_init(diff->mctx, &temp_diff);
+ temp_diff.resign = diff->resign;
+ ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
+
+ /*
+ * Apply it to the database.
+ */
+ result = dns_diff_apply(&temp_diff, db, ver);
+ ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
+ if (result != ISC_R_SUCCESS) {
+ dns_difftuple_free(tuple);
+ return (result);
+ }
+
+ /*
+ * Merge it into the current pending journal entry.
+ */
+ dns_diff_appendminimal(diff, tuple);
+
+ /*
+ * Do not clear temp_diff.
+ */
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Set '*exists' to true iff the given name exists, to false otherwise.
+ */
+static isc_result_t
+name_exists(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ isc_boolean_t *exists)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdatasetiter_t *iter = NULL;
+
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND) {
+ *exists = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_allrdatasets(db, node, version,
+ (isc_stdtime_t) 0, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ result = dns_rdatasetiter_first(iter);
+ if (result == ISC_R_SUCCESS) {
+ *exists = ISC_TRUE;
+ } else if (result == ISC_R_NOMORE) {
+ *exists = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ } else
+ *exists = ISC_FALSE;
+ dns_rdatasetiter_destroy(&iter);
+
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+static isc_boolean_t
+match_nsec3param(const dns_rdata_nsec3_t *nsec3,
+ const dns_rdata_nsec3param_t *nsec3param)
+{
+ if (nsec3->hash == nsec3param->hash &&
+ nsec3->iterations == nsec3param->iterations &&
+ nsec3->salt_length == nsec3param->salt_length &&
+ !memcmp(nsec3->salt, nsec3param->salt, nsec3->salt_length))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+/*%
+ * Delete NSEC3 records at "name" which match "param", recording the
+ * change in "diff".
+ */
+static isc_result_t
+delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
+{
+ dns_dbnode_t *node = NULL ;
+ dns_difftuple_t *tuple = NULL;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto cleanup_node;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
+
+ if (!match_nsec3param(&nsec3, nsec3param))
+ continue;
+
+ result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata, &tuple);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ result = do_one_tuple(&tuple, db, version, diff);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ result = ISC_R_SUCCESS;
+
+ failure:
+ dns_rdataset_disassociate(&rdataset);
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+#ifndef RFC5155_STRICT
+static isc_boolean_t
+better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ if (REMOVE(param->data[1]))
+ return (ISC_TRUE);
+
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_clone(nsec3paramset, &rdataset);
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ if (rdata.length != param->length)
+ continue;
+ if (rdata.data[0] != param->data[0] ||
+ REMOVE(rdata.data[1]) ||
+ rdata.data[2] != param->data[2] ||
+ rdata.data[3] != param->data[3] ||
+ rdata.data[4] != param->data[4] ||
+ memcmp(&rdata.data[5], &param->data[5], param->data[4]))
+ continue;
+ if (CREATE(rdata.data[1]) && !CREATE(param->data[1])) {
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_TRUE);
+ }
+ }
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_FALSE);
+}
+#endif
+
+static isc_result_t
+find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
+ const dns_rdata_nsec3param_t *nsec3param)
+{
+ isc_result_t result;
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, nsec3, NULL));
+ dns_rdata_reset(&rdata);
+ if (match_nsec3param(nsec3, nsec3param))
+ break;
+ }
+ failure:
+ return (result);
+}
+
+isc_result_t
+dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
+ dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff)
+{
+ dns_dbiterator_t *dbit = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_dbnode_t *newnode = NULL;
+ dns_difftuple_t *tuple = NULL;
+ dns_fixedname_t fixed;
+ dns_fixedname_t fprev;
+ dns_hash_t hash;
+ dns_name_t *hashname;
+ dns_name_t *origin;
+ dns_name_t *prev;
+ dns_name_t empty;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ int pass;
+ isc_boolean_t exists;
+ isc_boolean_t remove_unsecure = ISC_FALSE;
+ isc_uint8_t flags;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ unsigned char *old_next;
+ unsigned char *salt;
+ unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
+ unsigned int iterations;
+ unsigned int labels;
+ size_t next_length;
+ unsigned int old_length;
+ unsigned int salt_length;
+
+ dns_fixedname_init(&fixed);
+ hashname = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&fprev);
+ prev = dns_fixedname_name(&fprev);
+
+ dns_rdataset_init(&rdataset);
+
+ origin = dns_db_origin(db);
+
+ /*
+ * Chain parameters.
+ */
+ hash = nsec3param->hash;
+ iterations = nsec3param->iterations;
+ salt_length = nsec3param->salt_length;
+ salt = nsec3param->salt;
+
+ /*
+ * Default flags for a new chain.
+ */
+ flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
+
+ /*
+ * If this is the first NSEC3 in the chain nexthash will
+ * remain pointing to itself.
+ */
+ next_length = sizeof(nexthash);
+ CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
+ name, origin, hash, iterations,
+ salt, salt_length));
+
+ /*
+ * Create the node if it doesn't exist and hold
+ * a reference to it until we have added the NSEC3.
+ */
+ CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
+
+ /*
+ * Seek the iterator to the 'newnode'.
+ */
+ CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
+ CHECK(dns_dbiterator_seek(dbit, hashname));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, newnode, version, dns_rdatatype_nsec3,
+ 0, (isc_stdtime_t) 0, &rdataset, NULL);
+ /*
+ * If we updating a existing NSEC3 then find its
+ * next field.
+ */
+ if (result == ISC_R_SUCCESS) {
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_SUCCESS) {
+ if (!CREATE(nsec3param->flags))
+ flags = nsec3.flags;
+ next_length = nsec3.next_length;
+ INSIST(next_length <= sizeof(nexthash));
+ memcpy(nexthash, nsec3.next, next_length);
+ dns_rdataset_disassociate(&rdataset);
+ /*
+ * If the NSEC3 is not for a unsecure delegation then
+ * we are just updating it. If it is for a unsecure
+ * delegation then we need find out if we need to
+ * remove the NSEC3 record or not by examining the
+ * previous NSEC3 record.
+ */
+ if (!unsecure)
+ goto addnsec3;
+ else
+ remove_unsecure = ISC_TRUE;
+ } else {
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ }
+ }
+
+ /*
+ * Find the previous NSEC3 (if any) and update it if required.
+ */
+ pass = 0;
+ do {
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ pass++;
+ CHECK(dns_dbiterator_last(dbit));
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, prev));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset,
+ NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_NOMORE) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ if (remove_unsecure) {
+ dns_rdataset_disassociate(&rdataset);
+ /*
+ * We have found the previous NSEC3 record and can now
+ * see if the existing NSEC3 record needs to be
+ * updated or deleted.
+ */
+ if (!OPTOUT(nsec3.flags)) {
+ /*
+ * Just update the NSEC3 record.
+ */
+ goto addnsec3;
+ } else {
+ /*
+ * This is actually a deletion not a add.
+ */
+ result = dns_nsec3_delnsec3(db, version, name,
+ nsec3param, diff);
+ goto failure;
+ }
+ } else {
+ /*
+ * Is this is a unsecure delegation we are adding?
+ * If so no change is required.
+ */
+ if (OPTOUT(nsec3.flags) && unsecure) {
+ dns_rdataset_disassociate(&rdataset);
+ goto failure;
+ }
+ }
+
+ old_next = nsec3.next;
+ old_length = nsec3.next_length;
+
+ /*
+ * Delete the old previous NSEC3.
+ */
+ CHECK(delete(db, version, prev, nsec3param, diff));
+
+ /*
+ * Fixup the previous NSEC3.
+ */
+ nsec3.next = nexthash;
+ nsec3.next_length = next_length;
+ isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
+ CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
+ dns_rdatatype_nsec3, &nsec3,
+ &buffer));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
+ rdataset.ttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ INSIST(old_length <= sizeof(nexthash));
+ memcpy(nexthash, old_next, old_length);
+ if (!CREATE(nsec3param->flags))
+ flags = nsec3.flags;
+ dns_rdata_reset(&rdata);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ } while (pass < 2);
+
+ addnsec3:
+ /*
+ * Create the NSEC3 RDATA.
+ */
+ CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
+ CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
+ salt, salt_length, nexthash, next_length,
+ nsec3buf, &rdata));
+ dns_db_detachnode(db, &node);
+
+ /*
+ * Delete the old NSEC3 and record the change.
+ */
+ CHECK(delete(db, version, hashname, nsec3param, diff));
+ /*
+ * Add the new NSEC3 and record the change.
+ */
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ hashname, nsecttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ INSIST(tuple == NULL);
+ dns_rdata_reset(&rdata);
+ dns_db_detachnode(db, &newnode);
+
+ /*
+ * Add missing NSEC3 records for empty nodes
+ */
+ dns_name_init(&empty, NULL);
+ dns_name_clone(name, &empty);
+ do {
+ labels = dns_name_countlabels(&empty) - 1;
+ if (labels <= dns_name_countlabels(origin))
+ break;
+ dns_name_getlabelsequence(&empty, 1, labels, &empty);
+ CHECK(name_exists(db, version, &empty, &exists));
+ if (exists)
+ break;
+ CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
+ &empty, origin, hash, iterations,
+ salt, salt_length));
+
+ /*
+ * Create the node if it doesn't exist and hold
+ * a reference to it until we have added the NSEC3
+ * or we discover we don't need to add make a change.
+ */
+ CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
+ result = dns_db_findrdataset(db, newnode, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset,
+ NULL);
+ if (result == ISC_R_SUCCESS) {
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &newnode);
+ break;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ }
+
+ /*
+ * Find the previous NSEC3 and update it.
+ */
+ CHECK(dns_dbiterator_seek(dbit, hashname));
+ pass = 0;
+ do {
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ pass++;
+ CHECK(dns_dbiterator_last(dbit));
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, prev));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_NOMORE) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ old_next = nsec3.next;
+ old_length = nsec3.next_length;
+
+ /*
+ * Delete the old previous NSEC3.
+ */
+ CHECK(delete(db, version, prev, nsec3param, diff));
+
+ /*
+ * Fixup the previous NSEC3.
+ */
+ nsec3.next = nexthash;
+ nsec3.next_length = next_length;
+ isc_buffer_init(&buffer, nsec3buf,
+ sizeof(nsec3buf));
+ CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
+ dns_rdatatype_nsec3, &nsec3,
+ &buffer));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ prev, rdataset.ttl, &rdata,
+ &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ INSIST(old_length <= sizeof(nexthash));
+ memcpy(nexthash, old_next, old_length);
+ if (!CREATE(nsec3param->flags))
+ flags = nsec3.flags;
+ dns_rdata_reset(&rdata);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ } while (pass < 2);
+
+ INSIST(pass < 2);
+
+ /*
+ * Create the NSEC3 RDATA for the empty node.
+ */
+ CHECK(dns_nsec3_buildrdata(db, version, NULL, hash, flags,
+ iterations, salt, salt_length,
+ nexthash, next_length, nsec3buf,
+ &rdata));
+ /*
+ * Delete the old NSEC3 and record the change.
+ */
+ CHECK(delete(db, version, hashname, nsec3param, diff));
+
+ /*
+ * Add the new NSEC3 and record the change.
+ */
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ hashname, nsecttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ INSIST(tuple == NULL);
+ dns_rdata_reset(&rdata);
+ dns_db_detachnode(db, &newnode);
+ } while (1);
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dbit != NULL)
+ dns_dbiterator_destroy(&dbit);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (newnode != NULL)
+ dns_db_detachnode(db, &newnode);
+ return (result);
+}
+
+/*%
+ * Add NSEC3 records for "name", recording the change in "diff".
+ * The existing NSEC3 records are removed.
+ */
+isc_result_t
+dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, dns_ttl_t nsecttl,
+ isc_boolean_t unsecure, dns_diff_t *diff)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ /*
+ * Find the NSEC3 parameters for this zone.
+ */
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3param, 0, 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Update each active NSEC3 chain.
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+
+#ifdef RFC5155_STRICT
+ if (nsec3param.flags != 0)
+ continue;
+#else
+ if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
+ continue;
+ if (better_param(&rdataset, &rdata))
+ continue;
+#endif
+
+ /*
+ * We have a active chain. Update it.
+ */
+ CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
+ nsecttl, unsecure, diff));
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+isc_result_t
+dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
+{
+ dns_dbiterator_t *dbit = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_difftuple_t *tuple = NULL;
+ dns_fixedname_t fixed;
+ dns_fixedname_t fprev;
+ dns_hash_t hash;
+ dns_name_t *hashname;
+ dns_name_t *origin;
+ dns_name_t *prev;
+ dns_name_t empty;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ int pass;
+ isc_boolean_t exists;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ unsigned char *salt;
+ unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
+ unsigned int iterations;
+ unsigned int labels;
+ size_t next_length;
+ unsigned int salt_length;
+
+ dns_fixedname_init(&fixed);
+ hashname = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&fprev);
+ prev = dns_fixedname_name(&fprev);
+
+ dns_rdataset_init(&rdataset);
+
+ origin = dns_db_origin(db);
+
+ /*
+ * Chain parameters.
+ */
+ hash = nsec3param->hash;
+ iterations = nsec3param->iterations;
+ salt_length = nsec3param->salt_length;
+ salt = nsec3param->salt;
+
+ /*
+ * If this is the first NSEC3 in the chain nexthash will
+ * remain pointing to itself.
+ */
+ next_length = sizeof(nexthash);
+ CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
+ name, origin, hash, iterations,
+ salt, salt_length));
+
+ CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
+
+ result = dns_dbiterator_seek(dbit, hashname);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ CHECK(dns_dbiterator_current(dbit, &node, NULL));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3,
+ 0, (isc_stdtime_t) 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * If we find a existing NSEC3 for this chain then save the
+ * next field.
+ */
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_SUCCESS) {
+ next_length = nsec3.next_length;
+ INSIST(next_length <= sizeof(nexthash));
+ memcpy(nexthash, nsec3.next, next_length);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_NOMORE)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Find the previous NSEC3 and update it.
+ */
+ pass = 0;
+ do {
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ pass++;
+ CHECK(dns_dbiterator_last(dbit));
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, prev));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset,
+ NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_NOMORE) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Delete the old previous NSEC3.
+ */
+ CHECK(delete(db, version, prev, nsec3param, diff));
+
+ /*
+ * Fixup the previous NSEC3.
+ */
+ nsec3.next = nexthash;
+ nsec3.next_length = next_length;
+ isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
+ CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
+ dns_rdatatype_nsec3, &nsec3,
+ &buffer));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
+ rdataset.ttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ dns_rdata_reset(&rdata);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ } while (pass < 2);
+
+ /*
+ * Delete the old NSEC3 and record the change.
+ */
+ CHECK(delete(db, version, hashname, nsec3param, diff));
+
+ /*
+ * Delete NSEC3 records for now non active nodes.
+ */
+ dns_name_init(&empty, NULL);
+ dns_name_clone(name, &empty);
+ do {
+ labels = dns_name_countlabels(&empty) - 1;
+ if (labels <= dns_name_countlabels(origin))
+ break;
+ dns_name_getlabelsequence(&empty, 1, labels, &empty);
+ CHECK(name_exists(db, version, &empty, &exists));
+ if (exists)
+ break;
+
+ CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
+ &empty, origin, hash, iterations,
+ salt, salt_length));
+ result = dns_dbiterator_seek(dbit, hashname);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ CHECK(dns_dbiterator_current(dbit, &node, NULL));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset,
+ NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_SUCCESS) {
+ next_length = nsec3.next_length;
+ INSIST(next_length <= sizeof(nexthash));
+ memcpy(nexthash, nsec3.next, next_length);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_NOMORE)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ pass = 0;
+ do {
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ pass++;
+ CHECK(dns_dbiterator_last(dbit));
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, prev));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_NOMORE) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Delete the old previous NSEC3.
+ */
+ CHECK(delete(db, version, prev, nsec3param, diff));
+
+ /*
+ * Fixup the previous NSEC3.
+ */
+ nsec3.next = nexthash;
+ nsec3.next_length = next_length;
+ isc_buffer_init(&buffer, nsec3buf,
+ sizeof(nsec3buf));
+ CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
+ dns_rdatatype_nsec3, &nsec3,
+ &buffer));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ prev, rdataset.ttl, &rdata,
+ &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ dns_rdata_reset(&rdata);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ } while (pass < 2);
+
+ INSIST(pass < 2);
+
+ /*
+ * Delete the old NSEC3 and record the change.
+ */
+ CHECK(delete(db, version, hashname, nsec3param, diff));
+ } while (1);
+
+ success:
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dbit != NULL)
+ dns_dbiterator_destroy(&dbit);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+isc_result_t
+dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_diff_t *diff)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ /*
+ * Find the NSEC3 parameters for this zone.
+ */
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3param, 0, 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Update each active NSEC3 chain.
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+
+#ifdef RFC5155_STRICT
+ if (nsec3param.flags != 0)
+ continue;
+#else
+ if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
+ continue;
+ if (better_param(&rdataset, &rdata))
+ continue;
+#endif
+
+ /*
+ * We have a active chain. Update it.
+ */
+ CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+isc_result_t
+dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t complete, isc_boolean_t *answer)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_nsec3param_t nsec3param;
+ isc_result_t result;
+
+ REQUIRE(answer != NULL);
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3param, 0, 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+
+ if (result == ISC_R_NOTFOUND) {
+ *answer = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if ((nsec3param.flags) == 0 ||
+ (!complete && CREATE(nsec3param.flags)))
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS)
+ *answer = ISC_TRUE;
+ if (result == ISC_R_NOMORE) {
+ *answer = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
+
+isc_result_t
+dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
+ isc_mem_t *mctx, unsigned int *iterationsp)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dst_key_t *key = NULL;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ isc_uint16_t bits, minbits = 4096;
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
+ 0, 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND) {
+ *iterationsp = 0;
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ isc_buffer_init(&buffer, rdata.data, rdata.length);
+ isc_buffer_add(&buffer, rdata.length);
+ CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass,
+ &buffer, mctx, &key));
+ bits = dst_key_getbits(key);
+ dst_key_free(&key);
+ if (minbits > bits)
+ minbits = bits;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ if (minbits <= 1024)
+ *iterationsp = 150;
+ else if (minbits <= 2048)
+ *iterationsp = 500;
+ else
+ *iterationsp = 2500;
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c
index bb76e0e..2dc7d7e 100644
--- a/lib/dns/openssl_link.c
+++ b/lib/dns/openssl_link.c
@@ -1,6 +1,19 @@
/*
- * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-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 AND NETWORK ASSOCIATES 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.
+ *
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -18,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: openssl_link.c,v 1.1.6.12 2007/08/28 07:20:04 tbox Exp $
+ * $Id: openssl_link.c,v 1.22.112.3 2009/02/11 03:07:01 jinmei Exp $
*/
#ifdef OPENSSL
@@ -41,22 +54,36 @@
#include <openssl/conf.h>
#include <openssl/crypto.h>
-#if defined(CRYPTO_LOCK_ENGINE) && (OPENSSL_VERSION_NUMBER != 0x00907000L)
+#if defined(CRYPTO_LOCK_ENGINE) && (OPENSSL_VERSION_NUMBER >= 0x0090707f)
#define USE_ENGINE 1
#endif
#ifdef USE_ENGINE
#include <openssl/engine.h>
+
+#ifdef ENGINE_ID
+const char *engine_id = ENGINE_ID;
+#else
+const char *engine_id;
+#endif
#endif
static RAND_METHOD *rm = NULL;
+
static isc_mutex_t *locks = NULL;
static int nlocks;
#ifdef USE_ENGINE
static ENGINE *e;
+static ENGINE *he;
#endif
+#ifdef USE_PKCS11
+static isc_result_t
+dst__openssl_load_engine(const char *name, const char *engine_id,
+ const char **pre_cmds, int pre_num,
+ const char **post_cmds, int post_num);
+#endif
static int
entropy_get(unsigned char *buf, int num) {
@@ -68,6 +95,11 @@ entropy_get(unsigned char *buf, int num) {
}
static int
+entropy_status(void) {
+ return (dst__entropy_status() > 32);
+}
+
+static int
entropy_getpseudo(unsigned char *buf, int num) {
isc_result_t result;
if (num < 0)
@@ -116,23 +148,17 @@ mem_free(void *ptr) {
static void *
mem_realloc(void *ptr, size_t size) {
- void *p;
-
INSIST(dst__memory_pool != NULL);
- p = NULL;
- if (size > 0U) {
- p = mem_alloc(size);
- if (p != NULL && ptr != NULL)
- memcpy(p, ptr, size);
- }
- if (ptr != NULL)
- mem_free(ptr);
- return (p);
+ return (isc_mem_reallocate(dst__memory_pool, ptr, size));
}
isc_result_t
dst__openssl_init() {
isc_result_t result;
+#ifdef USE_ENGINE
+ /* const char *name; */
+ ENGINE *re;
+#endif
#ifdef DNS_CRYPTO_LEAKS
CRYPTO_malloc_debug_init();
@@ -149,6 +175,7 @@ dst__openssl_init() {
goto cleanup_mutexalloc;
CRYPTO_set_locking_callback(lock_callback);
CRYPTO_set_id_callback(id_callback);
+
rm = mem_alloc(sizeof(RAND_METHOD));
if (rm == NULL) {
result = ISC_R_NOMEMORY;
@@ -159,18 +186,87 @@ dst__openssl_init() {
rm->cleanup = NULL;
rm->add = entropy_add;
rm->pseudorand = entropy_getpseudo;
- rm->status = NULL;
+ rm->status = entropy_status;
#ifdef USE_ENGINE
- e = ENGINE_new();
- if (e == NULL) {
- result = ISC_R_NOMEMORY;
- goto cleanup_rm;
+ OPENSSL_config(NULL);
+#ifdef USE_PKCS11
+#ifndef PKCS11_SO_PATH
+#define PKCS11_SO_PATH "/usr/local/lib/engines/engine_pkcs11.so"
+#endif
+#ifndef PKCS11_MODULE_PATH
+#define PKCS11_MODULE_PATH "/usr/lib/libpkcs11.so"
+#endif
+ {
+ /*
+ * to use this to config the PIN, add in openssl.cnf:
+ * - at the beginning: "openssl_conf = openssl_def"
+ * - at any place these sections:
+ * [ openssl_def ]
+ * engines = engine_section
+ * [ engine_section ]
+ * pkcs11 = pkcs11_section
+ * [ pkcs11_section ]
+ * PIN = my___pin
+ */
+
+ const char *pre_cmds[] = {
+ "SO_PATH", PKCS11_SO_PATH,
+ "LOAD", NULL,
+ "MODULE_PATH", PKCS11_MODULE_PATH
+ };
+ const char *post_cmds[] = {
+ /* "PIN", "my___pin" */
+ };
+ result = dst__openssl_load_engine("pkcs11", "pkcs11",
+ pre_cmds, 0,
+ post_cmds, /*1*/ 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rm;
}
- ENGINE_set_RAND(e, rm);
- RAND_set_rand_method(rm);
+#endif /* USE_PKCS11 */
+ if (engine_id != NULL) {
+ e = ENGINE_by_id(engine_id);
+ if (e == NULL) {
+ result = ISC_R_NOTFOUND;
+ goto cleanup_rm;
+ }
+ if (!ENGINE_init(e)) {
+ result = ISC_R_FAILURE;
+ ENGINE_free(e);
+ goto cleanup_rm;
+ }
+ ENGINE_set_default(e, ENGINE_METHOD_ALL);
+ ENGINE_free(e);
+ } else {
+ ENGINE_register_all_complete();
+ for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {
+
+ /*
+ * Something weird here. If we call ENGINE_finish()
+ * ENGINE_get_default_RAND() will fail.
+ */
+ if (ENGINE_init(e)) {
+ if (he == NULL)
+ he = e;
+ }
+ }
+ }
+ re = ENGINE_get_default_RAND();
+ if (re == NULL) {
+ re = ENGINE_new();
+ if (re == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_rm;
+ }
+ ENGINE_set_RAND(re, rm);
+ ENGINE_set_default_RAND(re);
+ ENGINE_free(re);
+ } else
+ ENGINE_finish(re);
+
#else
RAND_set_rand_method(rm);
-#endif
+#endif /* USE_ENGINE */
return (ISC_R_SUCCESS);
#ifdef USE_ENGINE
@@ -195,9 +291,15 @@ dst__openssl_destroy() {
CONF_modules_unload(1);
#endif
EVP_cleanup();
+#if defined(USE_ENGINE)
+ if (e != NULL) {
+ ENGINE_finish(e);
+ e = NULL;
+ }
#if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
ENGINE_cleanup();
#endif
+#endif
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
CRYPTO_cleanup_all_ex_data();
#endif
@@ -209,19 +311,6 @@ dst__openssl_destroy() {
CRYPTO_mem_leaks_fp(stderr);
#endif
-#if 0
- /*
- * The old error sequence that leaked. Remove for 9.4.1 if
- * there are no issues by then.
- */
- ERR_clear_error();
-#ifdef USE_ENGINE
- if (e != NULL) {
- ENGINE_free(e);
- e = NULL;
- }
-#endif
-#endif
if (rm != NULL) {
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
RAND_cleanup();
@@ -251,6 +340,93 @@ dst__openssl_toresult(isc_result_t fallback) {
return (result);
}
+ENGINE *
+dst__openssl_getengine(const char *name) {
+
+ UNUSED(name);
+
+
+#if defined(USE_ENGINE)
+ return (he);
+#else
+ return (NULL);
+#endif
+}
+
+isc_result_t
+dst__openssl_setdefault(const char *name) {
+
+ UNUSED(name);
+
+#if defined(USE_ENGINE)
+ ENGINE_set_default(e, ENGINE_METHOD_ALL);
+#endif
+ /*
+ * XXXMPA If the engine does not have a default RAND method
+ * restore our method.
+ */
+ return (ISC_R_SUCCESS);
+}
+
+#ifdef USE_PKCS11
+/*
+ * 'name' is the name the engine is known by to the dst library.
+ * This may or may not match the name the engine is known by to
+ * openssl. It is the name that is stored in the private key file.
+ *
+ * 'engine_id' is the openssl engine name.
+ *
+ * pre_cmds and post_cmds a sequence if command argument pairs
+ * pre_num and post_num are a count of those pairs.
+ *
+ * "SO_PATH", PKCS11_SO_PATH ("/usr/local/lib/engines/engine_pkcs11.so")
+ * "LOAD", NULL
+ * "MODULE_PATH", PKCS11_MODULE_PATH ("/usr/lib/libpkcs11.so")
+ */
+static isc_result_t
+dst__openssl_load_engine(const char *name, const char *engine_id,
+ const char **pre_cmds, int pre_num,
+ const char **post_cmds, int post_num)
+{
+ ENGINE *e;
+
+ UNUSED(name);
+
+ if (!strcasecmp(engine_id, "dynamic"))
+ ENGINE_load_dynamic();
+ e = ENGINE_by_id(engine_id);
+ if (e == NULL)
+ return (ISC_R_NOTFOUND);
+ while (pre_num--) {
+ if (!ENGINE_ctrl_cmd_string(e, pre_cmds[0], pre_cmds[1], 0)) {
+ ENGINE_free(e);
+ return (ISC_R_FAILURE);
+ }
+ pre_cmds += 2;
+ }
+ if (!ENGINE_init(e)) {
+ ENGINE_free(e);
+ return (ISC_R_FAILURE);
+ }
+ /*
+ * ENGINE_init() returned a functional reference, so free the
+ * structural reference from ENGINE_by_id().
+ */
+ ENGINE_free(e);
+ while (post_num--) {
+ if (!ENGINE_ctrl_cmd_string(e, post_cmds[0], post_cmds[1], 0)) {
+ ENGINE_free(e);
+ return (ISC_R_FAILURE);
+ }
+ post_cmds += 2;
+ }
+ if (he != NULL)
+ ENGINE_finish(he);
+ he = e;
+ return (ISC_R_SUCCESS);
+}
+#endif /* USE_PKCS11 */
+
#else /* OPENSSL */
#include <isc/util.h>
diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c
index 8f47482..abc3b7c 100644
--- a/lib/dns/openssldh_link.c
+++ b/lib/dns/openssldh_link.c
@@ -1,6 +1,19 @@
/*
- * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-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 AND NETWORK ASSOCIATES 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.
+ *
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -18,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: openssldh_link.c,v 1.1.6.10 2007/08/28 07:20:04 tbox Exp $
+ * $Id: openssldh_link.c,v 1.14 2008/04/01 23:47:10 tbox Exp $
*/
#ifdef OPENSSL
@@ -37,8 +50,6 @@
#include "dst_openssl.h"
#include "dst_parse.h"
-#include <openssl/dh.h>
-
#define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
"A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
"F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
@@ -71,11 +82,11 @@ openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
isc_region_t r;
unsigned int len;
- REQUIRE(pub->opaque != NULL);
- REQUIRE(priv->opaque != NULL);
+ REQUIRE(pub->keydata.dh != NULL);
+ REQUIRE(priv->keydata.dh != NULL);
- dhpub = (DH *) pub->opaque;
- dhpriv = (DH *) priv->opaque;
+ dhpub = pub->keydata.dh;
+ dhpriv = priv->keydata.dh;
len = DH_size(dhpriv);
isc_buffer_availableregion(secret, &r);
@@ -93,8 +104,8 @@ openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DH *dh1, *dh2;
- dh1 = (DH *) key1->opaque;
- dh2 = (DH *) key2->opaque;
+ dh1 = key1->keydata.dh;
+ dh2 = key2->keydata.dh;
if (dh1 == NULL && dh2 == NULL)
return (ISC_TRUE);
@@ -122,8 +133,8 @@ openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DH *dh1, *dh2;
- dh1 = (DH *) key1->opaque;
- dh2 = (DH *) key2->opaque;
+ dh1 = key1->keydata.dh;
+ dh2 = key2->keydata.dh;
if (dh1 == NULL && dh2 == NULL)
return (ISC_TRUE);
@@ -141,7 +152,7 @@ openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
static isc_result_t
openssldh_generate(dst_key_t *key, int generator) {
#if OPENSSL_VERSION_NUMBER > 0x00908000L
- BN_GENCB cb;
+ BN_GENCB cb;
#endif
DH *dh = NULL;
@@ -192,20 +203,20 @@ openssldh_generate(dst_key_t *key, int generator) {
}
dh->flags &= ~DH_FLAG_CACHE_MONT_P;
- key->opaque = dh;
+ key->keydata.dh = dh;
return (ISC_R_SUCCESS);
}
static isc_boolean_t
openssldh_isprivate(const dst_key_t *key) {
- DH *dh = (DH *) key->opaque;
+ DH *dh = key->keydata.dh;
return (ISC_TF(dh != NULL && dh->priv_key != NULL));
}
static void
openssldh_destroy(dst_key_t *key) {
- DH *dh = key->opaque;
+ DH *dh = key->keydata.dh;
if (dh == NULL)
return;
@@ -215,7 +226,7 @@ openssldh_destroy(dst_key_t *key) {
if (dh->g == &bn2)
dh->g = NULL;
DH_free(dh);
- key->opaque = NULL;
+ key->keydata.dh = NULL;
}
static void
@@ -242,9 +253,9 @@ openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
isc_region_t r;
isc_uint16_t dnslen, plen, glen, publen;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.dh != NULL);
- dh = (DH *) key->opaque;
+ dh = key->keydata.dh;
isc_buffer_availableregion(data, &r);
@@ -401,7 +412,7 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_buffer_forward(data, plen + glen + publen + 6);
- key->opaque = (void *) dh;
+ key->keydata.dh = dh;
return (ISC_R_SUCCESS);
}
@@ -414,10 +425,10 @@ openssldh_tofile(const dst_key_t *key, const char *directory) {
unsigned char *bufs[4];
isc_result_t result;
- if (key->opaque == NULL)
+ if (key->keydata.dh == NULL)
return (DST_R_NULLKEY);
- dh = (DH *) key->opaque;
+ dh = key->keydata.dh;
for (i = 0; i < 4; i++) {
bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(dh->p));
@@ -484,7 +495,7 @@ openssldh_parse(dst_key_t *key, isc_lex_t *lexer) {
if (dh == NULL)
DST_RET(ISC_R_NOMEMORY);
dh->flags &= ~DH_FLAG_CACHE_MONT_P;
- key->opaque = dh;
+ key->keydata.dh = dh;
for (i = 0; i < priv.nelements; i++) {
BIGNUM *bn;
@@ -597,6 +608,7 @@ static dst_func_t openssldh_functions = {
openssldh_tofile,
openssldh_parse,
openssldh_cleanup,
+ NULL, /*%< fromlabel */
};
isc_result_t
diff --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c
index 2ff33f32..14e89e1 100644
--- a/lib/dns/openssldsa_link.c
+++ b/lib/dns/openssldsa_link.c
@@ -1,6 +1,19 @@
/*
- * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-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 AND NETWORK ASSOCIATES 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.
+ *
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,9 +29,12 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: openssldsa_link.c,v 1.1.6.9.28.1 2008/12/24 00:21:22 marka Exp $ */
+/* $Id: openssldsa_link.c,v 1.13.120.2 2009/01/14 23:47:26 tbox Exp $ */
#ifdef OPENSSL
+#ifndef USE_EVP
+#define USE_EVP 1
+#endif
#include <config.h>
@@ -41,32 +57,68 @@ static isc_result_t openssldsa_todns(const dst_key_t *key, isc_buffer_t *data);
static isc_result_t
openssldsa_createctx(dst_key_t *key, dst_context_t *dctx) {
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx;
+
+ UNUSED(key);
+
+ evp_md_ctx = EVP_MD_CTX_create();
+ if (evp_md_ctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (!EVP_DigestInit_ex(evp_md_ctx, EVP_dss1(), NULL)) {
+ EVP_MD_CTX_destroy(evp_md_ctx);
+ return (ISC_R_FAILURE);
+ }
+
+ dctx->ctxdata.evp_md_ctx = evp_md_ctx;
+
+ return (ISC_R_SUCCESS);
+#else
isc_sha1_t *sha1ctx;
UNUSED(key);
sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
isc_sha1_init(sha1ctx);
- dctx->opaque = sha1ctx;
+ dctx->ctxdata.sha1ctx = sha1ctx;
return (ISC_R_SUCCESS);
+#endif
}
static void
openssldsa_destroyctx(dst_context_t *dctx) {
- isc_sha1_t *sha1ctx = dctx->opaque;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+
+ if (evp_md_ctx != NULL) {
+ EVP_MD_CTX_destroy(evp_md_ctx);
+ dctx->ctxdata.evp_md_ctx = NULL;
+ }
+#else
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
if (sha1ctx != NULL) {
isc_sha1_invalidate(sha1ctx);
isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
- dctx->opaque = NULL;
+ dctx->ctxdata.sha1ctx = NULL;
}
+#endif
}
static isc_result_t
openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
- isc_sha1_t *sha1ctx = dctx->opaque;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+
+ if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
+ return (ISC_R_FAILURE);
+ }
+#else
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
isc_sha1_update(sha1ctx, data->base, data->length);
+#endif
return (ISC_R_SUCCESS);
}
@@ -81,23 +133,72 @@ BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
static isc_result_t
openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
- isc_sha1_t *sha1ctx = dctx->opaque;
dst_key_t *key = dctx->key;
- DSA *dsa = key->opaque;
- DSA_SIG *dsasig;
+ DSA *dsa = key->keydata.dsa;
isc_region_t r;
+ DSA_SIG *dsasig;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+ EVP_PKEY *pkey;
+ unsigned char *sigbuf;
+ const unsigned char *sb;
+ unsigned int siglen;
+#else
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+#endif
isc_buffer_availableregion(sig, &r);
if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
return (ISC_R_NOSPACE);
+#if USE_EVP
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL)
+ return (ISC_R_NOMEMORY);
+ if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
+ EVP_PKEY_free(pkey);
+ return (ISC_R_FAILURE);
+ }
+ sigbuf = malloc(EVP_PKEY_size(pkey));
+ if (sigbuf == NULL) {
+ EVP_PKEY_free(pkey);
+ return (ISC_R_NOMEMORY);
+ }
+ if (!EVP_SignFinal(evp_md_ctx, sigbuf, &siglen, pkey)) {
+ EVP_PKEY_free(pkey);
+ free(sigbuf);
+ return (ISC_R_FAILURE);
+ }
+ INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
+ EVP_PKEY_free(pkey);
+ /* Convert from Dss-Sig-Value (RFC2459). */
+ dsasig = DSA_SIG_new();
+ if (dsasig == NULL) {
+ free(sigbuf);
+ return (ISC_R_NOMEMORY);
+ }
+ sb = sigbuf;
+ if (d2i_DSA_SIG(&dsasig, &sb, (long) siglen) == NULL) {
+ free(sigbuf);
+ return (ISC_R_FAILURE);
+ }
+ free(sigbuf);
+#elif 0
+ /* Only use EVP for the Digest */
+ if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
+ return (ISC_R_FAILURE);
+ }
+ dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
+ if (dsasig == NULL)
+ return (dst__openssl_toresult(DST_R_SIGNFAILURE));
+#else
isc_sha1_final(sha1ctx, digest);
dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
if (dsasig == NULL)
return (dst__openssl_toresult(DST_R_SIGNFAILURE));
-
+#endif
*r.base++ = (key->key_size - 512)/64;
BN_bn2bin_fixed(dsasig->r, r.base, ISC_SHA1_DIGESTLENGTH);
r.base += ISC_SHA1_DIGESTLENGTH;
@@ -111,27 +212,70 @@ openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
static isc_result_t
openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
- isc_sha1_t *sha1ctx = dctx->opaque;
dst_key_t *key = dctx->key;
- DSA *dsa = key->opaque;
- DSA_SIG *dsasig;
+ DSA *dsa = key->keydata.dsa;
int status = 0;
- unsigned char digest[ISC_SHA1_DIGESTLENGTH];
unsigned char *cp = sig->base;
+ DSA_SIG *dsasig;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+#if 0
+ EVP_PKEY *pkey;
+ unsigned char *sigbuf;
+#endif
+ unsigned int siglen;
+#else
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+#endif
+ unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+
+#if USE_EVP
+#if 1
+ /* Only use EVP for the digest */
+ if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
+ return (ISC_R_FAILURE);
+ }
+#endif
+#else
isc_sha1_final(sha1ctx, digest);
+#endif
- if (sig->length < 2 * ISC_SHA1_DIGESTLENGTH + 1)
+ if (sig->length != 2 * ISC_SHA1_DIGESTLENGTH + 1) {
return (DST_R_VERIFYFAILURE);
+ }
cp++; /*%< Skip T */
dsasig = DSA_SIG_new();
+ if (dsasig == NULL)
+ return (ISC_R_NOMEMORY);
dsasig->r = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
cp += ISC_SHA1_DIGESTLENGTH;
dsasig->s = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
cp += ISC_SHA1_DIGESTLENGTH;
+#if 0
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL)
+ return (ISC_R_NOMEMORY);
+ if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
+ EVP_PKEY_free(pkey);
+ return (ISC_R_FAILURE);
+ }
+ /* Convert to Dss-Sig-Value (RFC2459). */
+ sigbuf = malloc(EVP_PKEY_size(pkey) + 50);
+ if (sigbuf == NULL) {
+ EVP_PKEY_free(pkey);
+ return (ISC_R_NOMEMORY);
+ }
+ siglen = (unsigned) i2d_DSA_SIG(dsasig, &sigbuf);
+ INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
+ status = EVP_VerifyFinal(evp_md_ctx, sigbuf, siglen, pkey);
+ EVP_PKEY_free(pkey);
+ free(sigbuf);
+#else
status = DSA_do_verify(digest, ISC_SHA1_DIGESTLENGTH, dsasig, dsa);
+#endif
DSA_SIG_free(dsasig);
if (status != 1)
return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
@@ -144,8 +288,8 @@ openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DSA *dsa1, *dsa2;
- dsa1 = (DSA *) key1->opaque;
- dsa2 = (DSA *) key2->opaque;
+ dsa1 = key1->keydata.dsa;
+ dsa2 = key2->keydata.dsa;
if (dsa1 == NULL && dsa2 == NULL)
return (ISC_TRUE);
@@ -172,7 +316,7 @@ openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
static isc_result_t
openssldsa_generate(dst_key_t *key, int unused) {
#if OPENSSL_VERSION_NUMBER > 0x00908000L
- BN_GENCB cb;
+ BN_GENCB cb;
#endif
DSA *dsa;
unsigned char rand_array[ISC_SHA1_DIGESTLENGTH];
@@ -186,12 +330,12 @@ openssldsa_generate(dst_key_t *key, int unused) {
return (result);
#if OPENSSL_VERSION_NUMBER > 0x00908000L
- dsa = DSA_new();
+ dsa = DSA_new();
if (dsa == NULL)
return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
BN_GENCB_set_old(&cb, NULL, NULL);
-
+
if (!DSA_generate_parameters_ex(dsa, key->key_size, rand_array,
ISC_SHA1_DIGESTLENGTH, NULL, NULL,
&cb))
@@ -213,22 +357,22 @@ openssldsa_generate(dst_key_t *key, int unused) {
}
dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
- key->opaque = dsa;
+ key->keydata.dsa = dsa;
return (ISC_R_SUCCESS);
}
static isc_boolean_t
openssldsa_isprivate(const dst_key_t *key) {
- DSA *dsa = (DSA *) key->opaque;
+ DSA *dsa = key->keydata.dsa;
return (ISC_TF(dsa != NULL && dsa->priv_key != NULL));
}
static void
openssldsa_destroy(dst_key_t *key) {
- DSA *dsa = key->opaque;
+ DSA *dsa = key->keydata.dsa;
DSA_free(dsa);
- key->opaque = NULL;
+ key->keydata.dsa = NULL;
}
@@ -239,9 +383,9 @@ openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) {
int dnslen;
unsigned int t, p_bytes;
- REQUIRE(key->opaque != NULL);
+ REQUIRE(key->keydata.dsa != NULL);
- dsa = (DSA *) key->opaque;
+ dsa = key->keydata.dsa;
isc_buffer_availableregion(data, &r);
@@ -315,7 +459,7 @@ openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
- key->opaque = (void *) dsa;
+ key->keydata.dsa = dsa;
return (ISC_R_SUCCESS);
}
@@ -328,10 +472,10 @@ openssldsa_tofile(const dst_key_t *key, const char *directory) {
dst_private_t priv;
unsigned char bufs[5][128];
- if (key->opaque == NULL)
+ if (key->keydata.dsa == NULL)
return (DST_R_NULLKEY);
- dsa = (DSA *) key->opaque;
+ dsa = key->keydata.dsa;
priv.elements[cnt].tag = TAG_DSA_PRIME;
priv.elements[cnt].length = BN_num_bytes(dsa->p);
@@ -385,7 +529,7 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer) {
if (dsa == NULL)
DST_RET(ISC_R_NOMEMORY);
dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
- key->opaque = dsa;
+ key->keydata.dsa = dsa;
for (i=0; i < priv.nelements; i++) {
BIGNUM *bn;
@@ -442,6 +586,7 @@ static dst_func_t openssldsa_functions = {
openssldsa_tofile,
openssldsa_parse,
NULL, /*%< cleanup */
+ NULL, /*%< fromlabel */
};
isc_result_t
diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c
index aacba45..d557c43 100644
--- a/lib/dns/opensslrsa_link.c
+++ b/lib/dns/opensslrsa_link.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -17,9 +17,15 @@
/*
* Principal Author: Brian Wellington
- * $Id: opensslrsa_link.c,v 1.1.6.11.58.1 2008/12/24 00:21:22 marka Exp $
+ * $Id: opensslrsa_link.c,v 1.20.50.3 2009/01/18 23:25:16 marka Exp $
*/
#ifdef OPENSSL
+#ifndef USE_EVP
+#define USE_EVP 1
+#endif
+#if USE_EVP
+#define USE_EVP_RSA 1
+#endif
#include <config.h>
@@ -42,6 +48,7 @@
#if OPENSSL_VERSION_NUMBER > 0x00908000L
#include <openssl/bn.h>
#endif
+#include <openssl/engine.h>
/*
* We don't use configure for windows so enforce the OpenSSL version
@@ -57,8 +64,8 @@
/*
- * XXXMPA Temporarially disable RSA_BLINDING as it requires
- * good quality random data that cannot currently be guarenteed.
+ * XXXMPA Temporarily disable RSA_BLINDING as it requires
+ * good quality random data that cannot currently be guaranteed.
* XXXMPA Find which versions of openssl use pseudo random data
* and set RSA_FLAG_BLINDING for those.
*/
@@ -97,14 +104,38 @@
} while (0)
#endif
+#define DST_RET(a) {ret = a; goto err;}
+
static isc_result_t opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data);
static isc_result_t
opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx;
+ const EVP_MD *type;
+#endif
+
UNUSED(key);
REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
- dctx->key->key_alg == DST_ALG_RSASHA1);
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+#if USE_EVP
+ evp_md_ctx = EVP_MD_CTX_create();
+ if (evp_md_ctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (dctx->key->key_alg == DST_ALG_RSAMD5)
+ type = EVP_md5(); /* MD5 + RSA */
+ else
+ type = EVP_sha1(); /* SHA1 + RSA */
+
+ if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) {
+ EVP_MD_CTX_destroy(evp_md_ctx);
+ return (ISC_R_FAILURE);
+ }
+ dctx->ctxdata.evp_md_ctx = evp_md_ctx;
+#else
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
isc_md5_t *md5ctx;
@@ -112,7 +143,7 @@ opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
if (md5ctx == NULL)
return (ISC_R_NOMEMORY);
isc_md5_init(md5ctx);
- dctx->opaque = md5ctx;
+ dctx->ctxdata.md5ctx = md5ctx;
} else {
isc_sha1_t *sha1ctx;
@@ -120,58 +151,87 @@ opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
if (sha1ctx == NULL)
return (ISC_R_NOMEMORY);
isc_sha1_init(sha1ctx);
- dctx->opaque = sha1ctx;
+ dctx->ctxdata.sha1ctx = sha1ctx;
}
+#endif
return (ISC_R_SUCCESS);
}
static void
opensslrsa_destroyctx(dst_context_t *dctx) {
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+#endif
+
REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
- dctx->key->key_alg == DST_ALG_RSASHA1);
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+#if USE_EVP
+ if (evp_md_ctx != NULL) {
+ EVP_MD_CTX_destroy(evp_md_ctx);
+ dctx->ctxdata.evp_md_ctx = NULL;
+ }
+#else
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
- isc_md5_t *md5ctx = dctx->opaque;
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
if (md5ctx != NULL) {
isc_md5_invalidate(md5ctx);
isc_mem_put(dctx->mctx, md5ctx, sizeof(isc_md5_t));
+ dctx->ctxdata.md5ctx = NULL;
}
} else {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
if (sha1ctx != NULL) {
isc_sha1_invalidate(sha1ctx);
isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
+ dctx->ctxdata.sha1ctx = NULL;
}
}
- dctx->opaque = NULL;
+#endif
}
static isc_result_t
opensslrsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+#endif
+
REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
- dctx->key->key_alg == DST_ALG_RSASHA1);
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+#if USE_EVP
+ if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
+ return (ISC_R_FAILURE);
+ }
+#else
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
- isc_md5_t *md5ctx = dctx->opaque;
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
isc_md5_update(md5ctx, data->base, data->length);
} else {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
isc_sha1_update(sha1ctx, data->base, data->length);
}
+#endif
return (ISC_R_SUCCESS);
}
static isc_result_t
opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
dst_key_t *key = dctx->key;
- RSA *rsa = key->opaque;
isc_region_t r;
+ unsigned int siglen = 0;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+ EVP_PKEY *pkey = key->keydata.pkey;
+#else
+ RSA *rsa = key->keydata.rsa;
/* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
- unsigned int siglen = 0;
int status;
int type;
unsigned int digestlen;
@@ -179,22 +239,32 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
unsigned long err;
const char* file;
int line;
+#endif
REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
- dctx->key->key_alg == DST_ALG_RSASHA1);
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
isc_buffer_availableregion(sig, &r);
+#if USE_EVP
+ if (r.length < (unsigned int) EVP_PKEY_size(pkey))
+ return (ISC_R_NOSPACE);
+
+ if (!EVP_SignFinal(evp_md_ctx, r.base, &siglen, pkey)) {
+ return (ISC_R_FAILURE);
+ }
+#else
if (r.length < (unsigned int) RSA_size(rsa))
return (ISC_R_NOSPACE);
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
- isc_md5_t *md5ctx = dctx->opaque;
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
isc_md5_final(md5ctx, digest);
type = NID_md5;
digestlen = ISC_MD5_DIGESTLENGTH;
} else {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
isc_sha1_final(sha1ctx, digest);
type = NID_sha1;
digestlen = ISC_SHA1_DIGESTLENGTH;
@@ -205,11 +275,10 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
err = ERR_peek_error_line(&file, &line);
if (err != 0U) {
message = ERR_error_string(err, NULL);
- fprintf(stderr, "%s:%s:%d\n", message,
- file ? file : "", line);
}
return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
}
+#endif
isc_buffer_add(sig, siglen);
@@ -219,23 +288,32 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
static isc_result_t
opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
dst_key_t *key = dctx->key;
- RSA *rsa = key->opaque;
+ int status = 0;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+ EVP_PKEY *pkey = key->keydata.pkey;
+#else
/* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
- int status = 0;
int type;
unsigned int digestlen;
+ RSA *rsa = key->keydata.rsa;
+#endif
REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
- dctx->key->key_alg == DST_ALG_RSASHA1);
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+#if USE_EVP
+ status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey);
+#else
if (dctx->key->key_alg == DST_ALG_RSAMD5) {
- isc_md5_t *md5ctx = dctx->opaque;
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
isc_md5_final(md5ctx, digest);
type = NID_md5;
digestlen = ISC_MD5_DIGESTLENGTH;
} else {
- isc_sha1_t *sha1ctx = dctx->opaque;
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
isc_sha1_final(sha1ctx, digest);
type = NID_sha1;
digestlen = ISC_SHA1_DIGESTLENGTH;
@@ -246,6 +324,7 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
status = RSA_verify(type, digest, digestlen, sig->base,
RSA_size(rsa), rsa);
+#endif
if (status != 1)
return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
@@ -255,10 +334,30 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
static isc_boolean_t
opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
- RSA *rsa1, *rsa2;
+ RSA *rsa1 = NULL, *rsa2 = NULL;
+#if USE_EVP
+ EVP_PKEY *pkey1, *pkey2;
+#endif
- rsa1 = (RSA *) key1->opaque;
- rsa2 = (RSA *) key2->opaque;
+#if USE_EVP
+ pkey1 = key1->keydata.pkey;
+ pkey2 = key2->keydata.pkey;
+ /*
+ * The pkey reference will keep these around after
+ * the RSA_free() call.
+ */
+ if (pkey1 != NULL) {
+ rsa1 = EVP_PKEY_get1_RSA(pkey1);
+ RSA_free(rsa1);
+ }
+ if (pkey2 != NULL) {
+ rsa2 = EVP_PKEY_get1_RSA(pkey2);
+ RSA_free(rsa2);
+ }
+#else
+ rsa1 = key1->keydata.rsa;
+ rsa2 = key2->keydata.rsa;
+#endif
if (rsa1 == NULL && rsa2 == NULL)
return (ISC_TRUE);
@@ -271,6 +370,19 @@ opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
if (status != 0)
return (ISC_FALSE);
+#if USE_EVP
+ if ((rsa1->flags & RSA_FLAG_EXT_PKEY) != 0 ||
+ (rsa2->flags & RSA_FLAG_EXT_PKEY) != 0) {
+ if ((rsa1->flags & RSA_FLAG_EXT_PKEY) == 0 ||
+ (rsa2->flags & RSA_FLAG_EXT_PKEY) == 0)
+ return (ISC_FALSE);
+ /*
+ * Can't compare private parameters, BTW does it make sense?
+ */
+ return (ISC_TRUE);
+ }
+#endif
+
if (rsa1->d != NULL || rsa2->d != NULL) {
if (rsa1->d == NULL || rsa2->d == NULL)
return (ISC_FALSE);
@@ -290,9 +402,18 @@ opensslrsa_generate(dst_key_t *key, int exp) {
BN_GENCB cb;
RSA *rsa = RSA_new();
BIGNUM *e = BN_new();
+#if USE_EVP
+ EVP_PKEY *pkey = EVP_PKEY_new();
+#endif
if (rsa == NULL || e == NULL)
goto err;
+#if USE_EVP
+ if (pkey == NULL)
+ goto err;
+ if (!EVP_PKEY_set1_RSA(pkey, rsa))
+ goto err;
+#endif
if (exp == 0) {
/* RSA_F4 0x10001 */
@@ -309,11 +430,21 @@ opensslrsa_generate(dst_key_t *key, int exp) {
if (RSA_generate_key_ex(rsa, key->key_size, e, &cb)) {
BN_free(e);
SET_FLAGS(rsa);
- key->opaque = rsa;
+#if USE_EVP
+ key->keydata.pkey = pkey;
+
+ RSA_free(rsa);
+#else
+ key->keydata.rsa = rsa;
+#endif
return (ISC_R_SUCCESS);
}
err:
+#if USE_EVP
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+#endif
if (e != NULL)
BN_free(e);
if (rsa != NULL)
@@ -322,16 +453,36 @@ err:
#else
RSA *rsa;
unsigned long e;
+#if USE_EVP
+ EVP_PKEY *pkey = EVP_PKEY_new();
+
+ if (pkey == NULL)
+ return (ISC_R_NOMEMORY);
+#endif
if (exp == 0)
e = RSA_F4;
else
e = 0x40000003;
rsa = RSA_generate_key(key->key_size, e, NULL, NULL);
- if (rsa == NULL)
- return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ if (rsa == NULL) {
+#if USE_EVP
+ EVP_PKEY_free(pkey);
+#endif
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
SET_FLAGS(rsa);
- key->opaque = rsa;
+#if USE_EVP
+ if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
+ EVP_PKEY_free(pkey);
+ RSA_free(rsa);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+ key->keydata.pkey = pkey;
+ RSA_free(rsa);
+#else
+ key->keydata.rsa = rsa;
+#endif
return (ISC_R_SUCCESS);
#endif
@@ -339,28 +490,58 @@ err:
static isc_boolean_t
opensslrsa_isprivate(const dst_key_t *key) {
- RSA *rsa = (RSA *) key->opaque;
+#if USE_EVP
+ RSA *rsa = EVP_PKEY_get1_RSA(key->keydata.pkey);
+ INSIST(rsa != NULL);
+ RSA_free(rsa);
+ /* key->keydata.pkey still has a reference so rsa is still valid. */
+#else
+ RSA *rsa = key->keydata.rsa;
+#endif
+ if (rsa != NULL && (rsa->flags & RSA_FLAG_EXT_PKEY) != 0)
+ return (ISC_TRUE);
return (ISC_TF(rsa != NULL && rsa->d != NULL));
}
static void
opensslrsa_destroy(dst_key_t *key) {
- RSA *rsa = key->opaque;
+#if USE_EVP
+ EVP_PKEY *pkey = key->keydata.pkey;
+ EVP_PKEY_free(pkey);
+ key->keydata.pkey = NULL;
+#else
+ RSA *rsa = key->keydata.rsa;
RSA_free(rsa);
- key->opaque = NULL;
+ key->keydata.rsa = NULL;
+#endif
}
static isc_result_t
opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
- RSA *rsa;
isc_region_t r;
unsigned int e_bytes;
unsigned int mod_bytes;
+ isc_result_t ret;
+ RSA *rsa;
+#if USE_EVP
+ EVP_PKEY *pkey;
+#endif
- REQUIRE(key->opaque != NULL);
+#if USE_EVP
+ REQUIRE(key->keydata.pkey != NULL);
+#else
+ REQUIRE(key->keydata.rsa != NULL);
+#endif
- rsa = (RSA *) key->opaque;
+#if USE_EVP
+ pkey = key->keydata.pkey;
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+#else
+ rsa = key->keydata.rsa;
+#endif
isc_buffer_availableregion(data, &r);
@@ -369,11 +550,11 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */
if (r.length < 1)
- return (ISC_R_NOSPACE);
+ DST_RET(ISC_R_NOSPACE);
isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
} else {
if (r.length < 3)
- return (ISC_R_NOSPACE);
+ DST_RET(ISC_R_NOSPACE);
isc_buffer_putuint8(data, 0);
isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
}
@@ -388,7 +569,13 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
isc_buffer_add(data, e_bytes + mod_bytes);
- return (ISC_R_SUCCESS);
+ ret = ISC_R_SUCCESS;
+ err:
+#if USE_EVP
+ if (rsa != NULL)
+ RSA_free(rsa);
+#endif
+ return (ret);
}
static isc_result_t
@@ -396,6 +583,9 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
RSA *rsa;
isc_region_t r;
unsigned int e_bytes;
+#if USE_EVP
+ EVP_PKEY *pkey;
+#endif
isc_buffer_remainingregion(data, &r);
if (r.length == 0)
@@ -437,12 +627,26 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
isc_buffer_forward(data, r.length);
- key->opaque = (void *) rsa;
+#if USE_EVP
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL) {
+ RSA_free(rsa);
+ return (ISC_R_NOMEMORY);
+ }
+ if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
+ EVP_PKEY_free(pkey);
+ RSA_free(rsa);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+ key->keydata.pkey = pkey;
+ RSA_free(rsa);
+#else
+ key->keydata.rsa = rsa;
+#endif
return (ISC_R_SUCCESS);
}
-
static isc_result_t
opensslrsa_tofile(const dst_key_t *key, const char *directory) {
int i;
@@ -451,10 +655,17 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) {
unsigned char *bufs[8];
isc_result_t result;
- if (key->opaque == NULL)
+#if USE_EVP
+ if (key->keydata.pkey == NULL)
return (DST_R_NULLKEY);
-
- rsa = (RSA *) key->opaque;
+ rsa = EVP_PKEY_get1_RSA(key->keydata.pkey);
+ if (rsa == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+#else
+ if (key->keydata.rsa == NULL)
+ return (DST_R_NULLKEY);
+ rsa = key->keydata.rsa;
+#endif
for (i = 0; i < 8; i++) {
bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
@@ -478,45 +689,74 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) {
priv.elements[i].data = bufs[i];
i++;
- priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
- priv.elements[i].length = BN_num_bytes(rsa->d);
- BN_bn2bin(rsa->d, bufs[i]);
- priv.elements[i].data = bufs[i];
- i++;
+ if (rsa->d != NULL) {
+ priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
+ priv.elements[i].length = BN_num_bytes(rsa->d);
+ BN_bn2bin(rsa->d, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
- priv.elements[i].tag = TAG_RSA_PRIME1;
- priv.elements[i].length = BN_num_bytes(rsa->p);
- BN_bn2bin(rsa->p, bufs[i]);
- priv.elements[i].data = bufs[i];
- i++;
+ if (rsa->p != NULL) {
+ priv.elements[i].tag = TAG_RSA_PRIME1;
+ priv.elements[i].length = BN_num_bytes(rsa->p);
+ BN_bn2bin(rsa->p, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
- priv.elements[i].tag = TAG_RSA_PRIME2;
- priv.elements[i].length = BN_num_bytes(rsa->q);
- BN_bn2bin(rsa->q, bufs[i]);
- priv.elements[i].data = bufs[i];
- i++;
+ if (rsa->q != NULL) {
+ priv.elements[i].tag = TAG_RSA_PRIME2;
+ priv.elements[i].length = BN_num_bytes(rsa->q);
+ BN_bn2bin(rsa->q, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
- priv.elements[i].tag = TAG_RSA_EXPONENT1;
- priv.elements[i].length = BN_num_bytes(rsa->dmp1);
- BN_bn2bin(rsa->dmp1, bufs[i]);
- priv.elements[i].data = bufs[i];
- i++;
+ if (rsa->dmp1 != NULL) {
+ priv.elements[i].tag = TAG_RSA_EXPONENT1;
+ priv.elements[i].length = BN_num_bytes(rsa->dmp1);
+ BN_bn2bin(rsa->dmp1, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
- priv.elements[i].tag = TAG_RSA_EXPONENT2;
- priv.elements[i].length = BN_num_bytes(rsa->dmq1);
- BN_bn2bin(rsa->dmq1, bufs[i]);
- priv.elements[i].data = bufs[i];
- i++;
+ if (rsa->dmq1 != NULL) {
+ priv.elements[i].tag = TAG_RSA_EXPONENT2;
+ priv.elements[i].length = BN_num_bytes(rsa->dmq1);
+ BN_bn2bin(rsa->dmq1, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
- priv.elements[i].tag = TAG_RSA_COEFFICIENT;
- priv.elements[i].length = BN_num_bytes(rsa->iqmp);
- BN_bn2bin(rsa->iqmp, bufs[i]);
- priv.elements[i].data = bufs[i];
- i++;
+ if (rsa->iqmp != NULL) {
+ priv.elements[i].tag = TAG_RSA_COEFFICIENT;
+ priv.elements[i].length = BN_num_bytes(rsa->iqmp);
+ BN_bn2bin(rsa->iqmp, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
+
+ if (key->engine != NULL) {
+ priv.elements[i].tag = TAG_RSA_ENGINE;
+ priv.elements[i].length = strlen(key->engine) + 1;
+ priv.elements[i].data = (unsigned char *)key->engine;
+ i++;
+ }
+
+ if (key->label != NULL) {
+ priv.elements[i].tag = TAG_RSA_LABEL;
+ priv.elements[i].length = strlen(key->label) + 1;
+ priv.elements[i].data = (unsigned char *)key->label;
+ i++;
+ }
priv.nelements = i;
result = dst__privstruct_writefile(key, &priv, directory);
fail:
+#if USE_EVP
+ RSA_free(rsa);
+#endif
for (i = 0; i < 8; i++) {
if (bufs[i] == NULL)
break;
@@ -531,26 +771,94 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
isc_result_t ret;
int i;
RSA *rsa = NULL;
+ ENGINE *e = NULL;
isc_mem_t *mctx = key->mctx;
-#define DST_RET(a) {ret = a; goto err;}
+ const char *name = NULL, *label = NULL;
+ EVP_PKEY *pkey = NULL;
/* read private key file */
ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
if (ret != ISC_R_SUCCESS)
return (ret);
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_RSA_ENGINE:
+ name = (char *)priv.elements[i].data;
+ break;
+ case TAG_RSA_LABEL:
+ label = (char *)priv.elements[i].data;
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * Is this key is stored in a HSM?
+ * See if we can fetch it.
+ */
+ if (name != NULL || label != NULL) {
+ INSIST(name != NULL);
+ INSIST(label != NULL);
+ e = dst__openssl_getengine(name);
+ if (e == NULL)
+ DST_RET(DST_R_NOENGINE);
+ pkey = ENGINE_load_private_key(e, label, NULL, NULL);
+ if (pkey == NULL) {
+ ERR_print_errors_fp(stderr);
+ DST_RET(ISC_R_FAILURE);
+ }
+ key->engine = isc_mem_strdup(key->mctx, name);
+ if (key->engine == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ key->label = isc_mem_strdup(key->mctx, label);
+ if (key->label == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ key->key_size = EVP_PKEY_bits(pkey);
+#if USE_EVP
+ key->keydata.pkey = pkey;
+#else
+ key->keydata.rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL)
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ EVP_PKEY_free(pkey);
+#endif
+ dst__privstruct_free(&priv, mctx);
+ return (ISC_R_SUCCESS);
+ }
+
rsa = RSA_new();
if (rsa == NULL)
DST_RET(ISC_R_NOMEMORY);
SET_FLAGS(rsa);
- key->opaque = rsa;
+
+#if USE_EVP
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
+ DST_RET(ISC_R_FAILURE);
+ }
+ key->keydata.pkey = pkey;
+#else
+ key->keydata.rsa = rsa;
+#endif
for (i = 0; i < priv.nelements; i++) {
BIGNUM *bn;
- bn = BN_bin2bn(priv.elements[i].data,
- priv.elements[i].length, NULL);
- if (bn == NULL)
- DST_RET(ISC_R_NOMEMORY);
+ switch (priv.elements[i].tag) {
+ case TAG_RSA_ENGINE:
+ continue;
+ case TAG_RSA_LABEL:
+ continue;
+ case TAG_RSA_PIN:
+ continue;
+ default:
+ bn = BN_bin2bn(priv.elements[i].data,
+ priv.elements[i].length, NULL);
+ if (bn == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ }
switch (priv.elements[i].tag) {
case TAG_RSA_MODULUS:
@@ -582,16 +890,64 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
dst__privstruct_free(&priv, mctx);
key->key_size = BN_num_bits(rsa->n);
+#if USE_EVP
+ RSA_free(rsa);
+#endif
return (ISC_R_SUCCESS);
err:
+#if USE_EVP
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+#endif
+ if (rsa != NULL)
+ RSA_free(rsa);
opensslrsa_destroy(key);
dst__privstruct_free(&priv, mctx);
memset(&priv, 0, sizeof(priv));
return (ret);
}
+static isc_result_t
+opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
+ const char *pin)
+{
+ ENGINE *e = NULL;
+ isc_result_t ret;
+ EVP_PKEY *pkey = NULL;
+
+ UNUSED(pin);
+
+ e = dst__openssl_getengine(engine);
+ if (e == NULL)
+ DST_RET(DST_R_NOENGINE);
+ pkey = ENGINE_load_private_key(e, label, NULL, NULL);
+ if (pkey == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ key->engine = isc_mem_strdup(key->mctx, label);
+ if (key->engine == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ key->label = isc_mem_strdup(key->mctx, label);
+ if (key->label == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ key->key_size = EVP_PKEY_bits(pkey);
+#if USE_EVP
+ key->keydata.pkey = pkey;
+#else
+ key->keydata.rsa = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (key->keydata.rsa == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+#endif
+ return (ISC_R_SUCCESS);
+
+ err:
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ return (ret);
+}
+
static dst_func_t opensslrsa_functions = {
opensslrsa_createctx,
opensslrsa_destroyctx,
@@ -609,6 +965,7 @@ static dst_func_t opensslrsa_functions = {
opensslrsa_tofile,
opensslrsa_parse,
NULL, /*%< cleanup */
+ opensslrsa_fromlabel,
};
isc_result_t
diff --git a/lib/dns/order.c b/lib/dns/order.c
index 1d216b7..853b001 100644
--- a/lib/dns/order.c
+++ b/lib/dns/order.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: order.c,v 1.5.18.3 2005/07/12 01:22:21 marka Exp $ */
+/* $Id: order.c,v 1.10 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/peer.c b/lib/dns/peer.c
index 7d878b5..12474cb 100644
--- a/lib/dns/peer.c
+++ b/lib/dns/peer.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: peer.c,v 1.19.18.8 2006/02/28 03:10:48 marka Exp $ */
+/* $Id: peer.c,v 1.31 2008/04/03 06:09:04 tbox Exp $ */
/*! \file */
@@ -42,6 +42,7 @@
#define SUPPORT_EDNS_BIT 5
#define SERVER_UDPSIZE_BIT 6
#define SERVER_MAXUDP_BIT 7
+#define REQUEST_NSID_BIT 8
static void
peerlist_delete(dns_peerlist_t **list);
@@ -146,7 +147,7 @@ dns_peerlist_addpeer(dns_peerlist_t *peers, dns_peer_t *peer) {
ISC_LIST_INSERTBEFORE(peers->elements, p, peer, next);
else
ISC_LIST_APPEND(peers->elements, peer, next);
-
+
}
isc_result_t
@@ -213,7 +214,7 @@ dns_peer_new(isc_mem_t *mem, isc_netaddr_t *addr, dns_peer_t **peerptr) {
isc_result_t
dns_peer_newprefix(isc_mem_t *mem, isc_netaddr_t *addr, unsigned int prefixlen,
dns_peer_t **peerptr)
-{
+{
dns_peer_t *peer;
REQUIRE(peerptr != NULL);
@@ -416,6 +417,32 @@ dns_peer_getsupportedns(dns_peer_t *peer, isc_boolean_t *retval) {
}
isc_result_t
+dns_peer_setrequestnsid(dns_peer_t *peer, isc_boolean_t newval) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(REQUEST_NSID_BIT, &peer->bitflags);
+
+ peer->request_nsid = newval;
+ DNS_BIT_SET(REQUEST_NSID_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getrequestnsid(dns_peer_t *peer, isc_boolean_t *retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (DNS_BIT_CHECK(REQUEST_NSID_BIT, &peer->bitflags)) {
+ *retval = peer->request_nsid;
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
dns_peer_settransfers(dns_peer_t *peer, isc_uint32_t newval) {
isc_boolean_t existed;
@@ -544,7 +571,7 @@ dns_peer_settransfersource(dns_peer_t *peer,
}
if (transfer_source != NULL) {
peer->transfer_source = isc_mem_get(peer->mem,
- sizeof(*peer->transfer_source));
+ sizeof(*peer->transfer_source));
if (peer->transfer_source == NULL)
return (ISC_R_NOMEMORY);
@@ -577,7 +604,7 @@ dns_peer_setnotifysource(dns_peer_t *peer,
}
if (notify_source != NULL) {
peer->notify_source = isc_mem_get(peer->mem,
- sizeof(*peer->notify_source));
+ sizeof(*peer->notify_source));
if (peer->notify_source == NULL)
return (ISC_R_NOMEMORY);
@@ -608,7 +635,7 @@ dns_peer_setquerysource(dns_peer_t *peer, const isc_sockaddr_t *query_source) {
}
if (query_source != NULL) {
peer->query_source = isc_mem_get(peer->mem,
- sizeof(*peer->query_source));
+ sizeof(*peer->query_source));
if (peer->query_source == NULL)
return (ISC_R_NOMEMORY);
@@ -649,11 +676,11 @@ dns_peer_getudpsize(dns_peer_t *peer, isc_uint16_t *udpsize) {
REQUIRE(udpsize != NULL);
if (DNS_BIT_CHECK(SERVER_UDPSIZE_BIT, &peer->bitflags)) {
- *udpsize = peer->udpsize;
- return (ISC_R_SUCCESS);
- } else {
- return (ISC_R_NOTFOUND);
- }
+ *udpsize = peer->udpsize;
+ return (ISC_R_SUCCESS);
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
}
isc_result_t
@@ -677,9 +704,9 @@ dns_peer_getmaxudp(dns_peer_t *peer, isc_uint16_t *maxudp) {
REQUIRE(maxudp != NULL);
if (DNS_BIT_CHECK(SERVER_MAXUDP_BIT, &peer->bitflags)) {
- *maxudp = peer->maxudp;
- return (ISC_R_SUCCESS);
- } else {
- return (ISC_R_NOTFOUND);
- }
+ *maxudp = peer->maxudp;
+ return (ISC_R_SUCCESS);
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
}
diff --git a/lib/dns/portlist.c b/lib/dns/portlist.c
index 7e76171..5bc89f4 100644
--- a/lib/dns/portlist.c
+++ b/lib/dns/portlist.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: portlist.c,v 1.6.18.5 2006/08/25 05:25:51 marka Exp $ */
+/* $Id: portlist.c,v 1.13 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c
index 4d3ca3a..ff8b3a3 100644
--- a/lib/dns/rbt.c
+++ b/lib/dns/rbt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbt.c,v 1.128.18.10 2008/03/31 13:32:59 fdupont Exp $ */
+/* $Id: rbt.c,v 1.142.50.2 2009/01/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -37,36 +37,37 @@
#define DNS_NAME_USEINLINE 1
#include <dns/fixedname.h>
+#include <dns/log.h>
#include <dns/rbt.h>
#include <dns/result.h>
-#define RBT_MAGIC ISC_MAGIC('R', 'B', 'T', '+')
-#define VALID_RBT(rbt) ISC_MAGIC_VALID(rbt, RBT_MAGIC)
+#define RBT_MAGIC ISC_MAGIC('R', 'B', 'T', '+')
+#define VALID_RBT(rbt) ISC_MAGIC_VALID(rbt, RBT_MAGIC)
/*
* XXXDCL Since parent pointers were added in again, I could remove all of the
* chain junk, and replace with dns_rbt_firstnode, _previousnode, _nextnode,
* _lastnode. This would involve pretty major change to the API.
*/
-#define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
-#define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
+#define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
+#define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
-#define RBT_HASH_SIZE 64
+#define RBT_HASH_SIZE 64
#ifdef RBT_MEM_TEST
#undef RBT_HASH_SIZE
-#define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
+#define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
#endif
struct dns_rbt {
- unsigned int magic;
- isc_mem_t * mctx;
- dns_rbtnode_t * root;
- void (*data_deleter)(void *, void *);
- void * deleter_arg;
- unsigned int nodecount;
- unsigned int hashsize;
- dns_rbtnode_t ** hashtable;
+ unsigned int magic;
+ isc_mem_t * mctx;
+ dns_rbtnode_t * root;
+ void (*data_deleter)(void *, void *);
+ void * deleter_arg;
+ unsigned int nodecount;
+ unsigned int hashsize;
+ dns_rbtnode_t ** hashtable;
};
#define RED 0
@@ -75,51 +76,51 @@ struct dns_rbt {
/*%
* Elements of the rbtnode structure.
*/
-#define PARENT(node) ((node)->parent)
-#define LEFT(node) ((node)->left)
-#define RIGHT(node) ((node)->right)
-#define DOWN(node) ((node)->down)
-#define DATA(node) ((node)->data)
-#define HASHNEXT(node) ((node)->hashnext)
-#define HASHVAL(node) ((node)->hashval)
-#define COLOR(node) ((node)->color)
-#define NAMELEN(node) ((node)->namelen)
-#define OFFSETLEN(node) ((node)->offsetlen)
-#define ATTRS(node) ((node)->attributes)
-#define PADBYTES(node) ((node)->padbytes)
-#define IS_ROOT(node) ISC_TF((node)->is_root == 1)
-#define FINDCALLBACK(node) ISC_TF((node)->find_callback == 1)
+#define PARENT(node) ((node)->parent)
+#define LEFT(node) ((node)->left)
+#define RIGHT(node) ((node)->right)
+#define DOWN(node) ((node)->down)
+#define DATA(node) ((node)->data)
+#define HASHNEXT(node) ((node)->hashnext)
+#define HASHVAL(node) ((node)->hashval)
+#define COLOR(node) ((node)->color)
+#define NAMELEN(node) ((node)->namelen)
+#define OFFSETLEN(node) ((node)->offsetlen)
+#define ATTRS(node) ((node)->attributes)
+#define PADBYTES(node) ((node)->padbytes)
+#define IS_ROOT(node) ISC_TF((node)->is_root == 1)
+#define FINDCALLBACK(node) ISC_TF((node)->find_callback == 1)
/*%
* Structure elements from the rbtdb.c, not
* used as part of the rbt.c algorithms.
*/
-#define DIRTY(node) ((node)->dirty)
-#define WILD(node) ((node)->wild)
-#define LOCKNUM(node) ((node)->locknum)
+#define DIRTY(node) ((node)->dirty)
+#define WILD(node) ((node)->wild)
+#define LOCKNUM(node) ((node)->locknum)
/*%
* The variable length stuff stored after the node.
*/
-#define NAME(node) ((unsigned char *)((node) + 1))
-#define OFFSETS(node) (NAME(node) + NAMELEN(node))
+#define NAME(node) ((unsigned char *)((node) + 1))
+#define OFFSETS(node) (NAME(node) + NAMELEN(node))
-#define NODE_SIZE(node) (sizeof(*node) + \
+#define NODE_SIZE(node) (sizeof(*node) + \
NAMELEN(node) + OFFSETLEN(node) + PADBYTES(node))
/*%
* Color management.
*/
-#define IS_RED(node) ((node) != NULL && (node)->color == RED)
-#define IS_BLACK(node) ((node) == NULL || (node)->color == BLACK)
-#define MAKE_RED(node) ((node)->color = RED)
-#define MAKE_BLACK(node) ((node)->color = BLACK)
+#define IS_RED(node) ((node) != NULL && (node)->color == RED)
+#define IS_BLACK(node) ((node) == NULL || (node)->color == BLACK)
+#define MAKE_RED(node) ((node)->color = RED)
+#define MAKE_BLACK(node) ((node)->color = BLACK)
/*%
* Chain management.
*
* The "ancestors" member of chains were removed, with their job now
- * being wholy handled by parent pointers (which didn't exist, because
+ * being wholly handled by parent pointers (which didn't exist, because
* of memory concerns, when chains were first implemented).
*/
#define ADD_LEVEL(chain, node) \
@@ -244,6 +245,7 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
rbt->nodecount = 0;
rbt->hashtable = NULL;
rbt->hashsize = 0;
+
#ifdef DNS_RBT_USEHASH
result = inithash(rbt);
if (result != ISC_R_SUCCESS) {
@@ -251,6 +253,7 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
return (result);
}
#endif
+
rbt->magic = RBT_MAGIC;
*rbtp = rbt;
@@ -524,6 +527,7 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
* current node.
*/
new_current->is_root = current->is_root;
+ new_current->nsec3 = current->nsec3;
PARENT(new_current) = PARENT(current);
LEFT(new_current) = LEFT(current);
RIGHT(new_current) = RIGHT(current);
@@ -1142,7 +1146,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
NULL);
if (result2 == ISC_R_SUCCESS ||
result2 == DNS_R_NEWORIGIN)
- ; /* Nothing. */
+ ; /* Nothing. */
else if (result2 == ISC_R_NOMORE)
/*
* There is no predecessor.
@@ -1274,8 +1278,7 @@ dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
== ISC_R_SUCCESS);
else {
if (DATA(node) != NULL && rbt->data_deleter != NULL)
- rbt->data_deleter(DATA(node),
- rbt->deleter_arg);
+ rbt->data_deleter(DATA(node), rbt->deleter_arg);
DATA(node) = NULL;
/*
@@ -1436,11 +1439,14 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
HASHVAL(node) = 0;
#endif
+ ISC_LINK_INIT(node, deadlink);
+
LOCKNUM(node) = 0;
WILD(node) = 0;
DIRTY(node) = 0;
dns_rbtnode_refinit(node, 0);
node->find_callback = 0;
+ node->nsec3 = 0;
MAKE_BLACK(node);
@@ -1451,9 +1457,9 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
* and the name's offsets table.
*
* XXX RTH
- * The offsets table could be made smaller by eliminating the
- * first offset, which is always 0. This requires changes to
- * lib/dns/name.c.
+ * The offsets table could be made smaller by eliminating the
+ * first offset, which is always 0. This requires changes to
+ * lib/dns/name.c.
*/
NAMELEN(node) = region.length;
PADBYTES(node) = 0;
@@ -1934,7 +1940,7 @@ dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
} else {
/*
* Child is parent's right child.
- * Everything is doen the same as above,
+ * Everything is done the same as above,
* except mirrored.
*/
sibling = LEFT(parent);
@@ -2027,6 +2033,7 @@ dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
#if DNS_RBT_USEMAGIC
node->magic = 0;
#endif
+
isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
rbt->nodecount--;
return (result);
@@ -2076,6 +2083,7 @@ dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
DOWN(parent) = RIGHT(node);
} else
parent = RIGHT(node);
+
isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
rbt->nodecount--;
node = parent;
@@ -2354,6 +2362,113 @@ dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
}
isc_result_t
+dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin)
+{
+ dns_rbtnode_t *current, *successor;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t new_origin = ISC_FALSE;
+
+ REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
+
+ successor = NULL;
+
+ current = chain->end;
+
+ if (DOWN(current) != NULL) {
+ /*
+ * Don't declare an origin change when the new origin is "."
+ * at the second level tree, because "." is already declared
+ * as the origin for the top level tree.
+ */
+ if (chain->level_count > 0 ||
+ OFFSETLEN(current) > 1)
+ new_origin = ISC_TRUE;
+
+ ADD_LEVEL(chain, current);
+ current = DOWN(current);
+
+ while (LEFT(current) != NULL)
+ current = LEFT(current);
+
+ successor = current;
+ }
+
+ if (successor != NULL) {
+ chain->end = successor;
+
+ /*
+ * It is not necessary to use dns_rbtnodechain_current like
+ * the other functions because this function will never
+ * find a node in the topmost level. This is because the
+ * root level will never be more than one name, and everything
+ * in the megatree is a successor to that node, down at
+ * the second level or below.
+ */
+
+ if (name != NULL)
+ NODENAME(chain->end, name);
+
+ if (new_origin) {
+ if (origin != NULL)
+ result = chain_name(chain, origin, ISC_FALSE);
+
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_NEWORIGIN;
+
+ } else
+ result = ISC_R_SUCCESS;
+
+ } else
+ result = ISC_R_NOMORE;
+
+ return (result);
+}
+
+isc_result_t
+dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
+ dns_rbtnode_t *current, *previous, *successor;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
+
+ successor = NULL;
+
+ current = chain->end;
+
+ if (RIGHT(current) == NULL) {
+ while (! IS_ROOT(current)) {
+ previous = current;
+ current = PARENT(current);
+
+ if (LEFT(current) == previous) {
+ successor = current;
+ break;
+ }
+ }
+ } else {
+ current = RIGHT(current);
+
+ while (LEFT(current) != NULL)
+ current = LEFT(current);
+
+ successor = current;
+ }
+
+ if (successor != NULL) {
+ chain->end = successor;
+
+ if (name != NULL)
+ NODENAME(chain->end, name);
+
+ result = ISC_R_SUCCESS;
+ } else
+ result = ISC_R_NOMORE;
+
+ return (result);
+}
+
+isc_result_t
dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
dns_name_t *origin)
{
@@ -2398,7 +2513,7 @@ dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
* reached without having traversed any left links, ascend one
* level and look for either a right link off the point of
* ascent, or search for a left link upward again, repeating
- * ascents until either case is true.
+ * ascends until either case is true.
*/
do {
while (! IS_ROOT(current)) {
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index 462a718..9741c15 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.196.18.53 2008/01/31 23:46:05 tbox Exp $ */
+/* $Id: rbtdb.c,v 1.270.12.6 2009/05/06 23:34:30 jinmei Exp $ */
/*! \file */
@@ -25,13 +25,18 @@
#include <config.h>
+/* #define inline */
+
#include <isc/event.h>
+#include <isc/heap.h>
#include <isc/mem.h>
-#include <isc/print.h>
#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/print.h>
#include <isc/random.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>
+#include <isc/serial.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/time.h>
@@ -45,12 +50,16 @@
#include <dns/lib.h>
#include <dns/log.h>
#include <dns/masterdump.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
#include <dns/rbt.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/rdataslab.h>
+#include <dns/rdatastruct.h>
#include <dns/result.h>
+#include <dns/stats.h>
#include <dns/view.h>
#include <dns/zone.h>
#include <dns/zonekey.h>
@@ -62,20 +71,20 @@
#endif
#ifdef DNS_RBTDB_VERSION64
-#define RBTDB_MAGIC ISC_MAGIC('R', 'B', 'D', '8')
+#define RBTDB_MAGIC ISC_MAGIC('R', 'B', 'D', '8')
#else
-#define RBTDB_MAGIC ISC_MAGIC('R', 'B', 'D', '4')
+#define RBTDB_MAGIC ISC_MAGIC('R', 'B', 'D', '4')
#endif
/*%
* Note that "impmagic" is not the first four bytes of the struct, so
* ISC_MAGIC_VALID cannot be used.
*/
-#define VALID_RBTDB(rbtdb) ((rbtdb) != NULL && \
+#define VALID_RBTDB(rbtdb) ((rbtdb) != NULL && \
(rbtdb)->common.impmagic == RBTDB_MAGIC)
#ifdef DNS_RBTDB_VERSION64
-typedef isc_uint64_t rbtdb_serial_t;
+typedef isc_uint64_t rbtdb_serial_t;
/*%
* Make casting easier in symbolic debuggers by using different names
* for the 64 bit version.
@@ -84,17 +93,19 @@ typedef isc_uint64_t rbtdb_serial_t;
#define rdatasetheader_t rdatasetheader64_t
#define rbtdb_version_t rbtdb_version64_t
#else
-typedef isc_uint32_t rbtdb_serial_t;
+typedef isc_uint32_t rbtdb_serial_t;
#endif
-typedef isc_uint32_t rbtdb_rdatatype_t;
+typedef isc_uint32_t rbtdb_rdatatype_t;
-#define RBTDB_RDATATYPE_BASE(type) ((dns_rdatatype_t)((type) & 0xFFFF))
-#define RBTDB_RDATATYPE_EXT(type) ((dns_rdatatype_t)((type) >> 16))
-#define RBTDB_RDATATYPE_VALUE(b, e) (((e) << 16) | (b))
+#define RBTDB_RDATATYPE_BASE(type) ((dns_rdatatype_t)((type) & 0xFFFF))
+#define RBTDB_RDATATYPE_EXT(type) ((dns_rdatatype_t)((type) >> 16))
+#define RBTDB_RDATATYPE_VALUE(b, e) ((rbtdb_rdatatype_t)((e) << 16) | (b))
#define RBTDB_RDATATYPE_SIGNSEC \
RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec)
+#define RBTDB_RDATATYPE_SIGNSEC3 \
+ RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec3)
#define RBTDB_RDATATYPE_SIGNS \
RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ns)
#define RBTDB_RDATATYPE_SIGCNAME \
@@ -119,15 +130,15 @@ typedef isc_uint32_t rbtdb_rdatatype_t;
#endif
#if DNS_RBTDB_USERWLOCK
-#define RBTDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
-#define RBTDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
-#define RBTDB_LOCK(l, t) RWLOCK((l), (t))
-#define RBTDB_UNLOCK(l, t) RWUNLOCK((l), (t))
+#define RBTDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
+#define RBTDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
+#define RBTDB_LOCK(l, t) RWLOCK((l), (t))
+#define RBTDB_UNLOCK(l, t) RWUNLOCK((l), (t))
#else
-#define RBTDB_INITLOCK(l) isc_mutex_init(l)
-#define RBTDB_DESTROYLOCK(l) DESTROYLOCK(l)
-#define RBTDB_LOCK(l, t) LOCK(l)
-#define RBTDB_UNLOCK(l, t) UNLOCK(l)
+#define RBTDB_INITLOCK(l) isc_mutex_init(l)
+#define RBTDB_DESTROYLOCK(l) DESTROYLOCK(l)
+#define RBTDB_LOCK(l, t) LOCK(l)
+#define RBTDB_UNLOCK(l, t) UNLOCK(l)
#endif
/*
@@ -152,47 +163,53 @@ typedef isc_uint32_t rbtdb_rdatatype_t;
#if defined(ISC_RWLOCK_USEATOMIC) && defined(DNS_RBT_USEISCREFCOUNT)
typedef isc_rwlock_t nodelock_t;
-#define NODE_INITLOCK(l) isc_rwlock_init((l), 0, 0)
-#define NODE_DESTROYLOCK(l) isc_rwlock_destroy(l)
-#define NODE_LOCK(l, t) RWLOCK((l), (t))
-#define NODE_UNLOCK(l, t) RWUNLOCK((l), (t))
-#define NODE_TRYUPGRADE(l) isc_rwlock_tryupgrade(l)
-
-#define NODE_STRONGLOCK(l) ((void)0)
-#define NODE_STRONGUNLOCK(l) ((void)0)
-#define NODE_WEAKLOCK(l, t) NODE_LOCK(l, t)
-#define NODE_WEAKUNLOCK(l, t) NODE_UNLOCK(l, t)
-#define NODE_WEAKDOWNGRADE(l) isc_rwlock_downgrade(l)
+#define NODE_INITLOCK(l) isc_rwlock_init((l), 0, 0)
+#define NODE_DESTROYLOCK(l) isc_rwlock_destroy(l)
+#define NODE_LOCK(l, t) RWLOCK((l), (t))
+#define NODE_UNLOCK(l, t) RWUNLOCK((l), (t))
+#define NODE_TRYUPGRADE(l) isc_rwlock_tryupgrade(l)
+
+#define NODE_STRONGLOCK(l) ((void)0)
+#define NODE_STRONGUNLOCK(l) ((void)0)
+#define NODE_WEAKLOCK(l, t) NODE_LOCK(l, t)
+#define NODE_WEAKUNLOCK(l, t) NODE_UNLOCK(l, t)
+#define NODE_WEAKDOWNGRADE(l) isc_rwlock_downgrade(l)
#else
typedef isc_mutex_t nodelock_t;
-#define NODE_INITLOCK(l) isc_mutex_init(l)
-#define NODE_DESTROYLOCK(l) DESTROYLOCK(l)
-#define NODE_LOCK(l, t) LOCK(l)
-#define NODE_UNLOCK(l, t) UNLOCK(l)
-#define NODE_TRYUPGRADE(l) ISC_R_SUCCESS
-
-#define NODE_STRONGLOCK(l) LOCK(l)
-#define NODE_STRONGUNLOCK(l) UNLOCK(l)
-#define NODE_WEAKLOCK(l, t) ((void)0)
-#define NODE_WEAKUNLOCK(l, t) ((void)0)
-#define NODE_WEAKDOWNGRADE(l) ((void)0)
+#define NODE_INITLOCK(l) isc_mutex_init(l)
+#define NODE_DESTROYLOCK(l) DESTROYLOCK(l)
+#define NODE_LOCK(l, t) LOCK(l)
+#define NODE_UNLOCK(l, t) UNLOCK(l)
+#define NODE_TRYUPGRADE(l) ISC_R_SUCCESS
+
+#define NODE_STRONGLOCK(l) LOCK(l)
+#define NODE_STRONGUNLOCK(l) UNLOCK(l)
+#define NODE_WEAKLOCK(l, t) ((void)0)
+#define NODE_WEAKUNLOCK(l, t) ((void)0)
+#define NODE_WEAKDOWNGRADE(l) ((void)0)
#endif
-#ifndef DNS_RDATASET_FIXED
-#define DNS_RDATASET_FIXED 1
+/*%
+ * Whether to rate-limit updating the LRU to avoid possible thread contention.
+ * Our performance measurement has shown the cost is marginal, so it's defined
+ * to be 0 by default either with or without threads.
+ */
+#ifndef DNS_RBTDB_LIMITLRUUPDATE
+#define DNS_RBTDB_LIMITLRUUPDATE 0
#endif
/*
- * Allow clients with a virtual time of upto 5 minutes in the past to see
+ * Allow clients with a virtual time of up to 5 minutes in the past to see
* records that would have otherwise have expired.
*/
#define RBTDB_VIRTUAL 300
struct noqname {
- dns_name_t name;
- void * nsec;
- void * nsecsig;
+ dns_name_t name;
+ void * neg;
+ void * negsig;
+ dns_rdatatype_t type;
};
typedef struct acachectl acachectl_t;
@@ -201,18 +218,19 @@ typedef struct rdatasetheader {
/*%
* Locked by the owning node's lock.
*/
- rbtdb_serial_t serial;
- dns_ttl_t ttl;
- rbtdb_rdatatype_t type;
- isc_uint16_t attributes;
- dns_trust_t trust;
- struct noqname *noqname;
+ rbtdb_serial_t serial;
+ dns_ttl_t rdh_ttl;
+ rbtdb_rdatatype_t type;
+ isc_uint16_t attributes;
+ dns_trust_t trust;
+ struct noqname *noqname;
+ struct noqname *closest;
/*%<
* We don't use the LIST macros, because the LIST structure has
* both head and tail pointers, and is doubly linked.
*/
- struct rdatasetheader *next;
+ struct rdatasetheader *next;
/*%<
* If this is the top header for an rdataset, 'next' points
* to the top header for the next rdataset (i.e., the next type).
@@ -220,13 +238,13 @@ typedef struct rdatasetheader {
* at this header.
*/
- struct rdatasetheader *down;
+ struct rdatasetheader *down;
/*%<
* Points to the header for the next older version of
* this rdataset.
*/
- isc_uint32_t count;
+ isc_uint32_t count;
/*%<
* Monotonously increased every time this rdataset is bound so that
* it is used as the base of the starting point in DNS responses
@@ -235,27 +253,56 @@ typedef struct rdatasetheader {
* performance reasons.
*/
- acachectl_t *additional_auth;
- acachectl_t *additional_glue;
+ acachectl_t *additional_auth;
+ acachectl_t *additional_glue;
+
+ dns_rbtnode_t *node;
+ isc_stdtime_t last_used;
+ ISC_LINK(struct rdatasetheader) lru_link;
+ /*%<
+ * Used for LRU-based cache management. We should probably make
+ * these cache-DB specific. We might also make it a pointer and
+ * ensure only the top header has a valid link to save memory.
+ * The linked-list is locked by the rbtdb->lrulock.
+ */
+
+ /*
+ * It's possible this should not be here anymore, but instead
+ * referenced from the bucket's heap directly.
+ */
+#if 0
+ isc_heap_t *heap;
+#endif
+ unsigned int heap_index;
+ /*%<
+ * Used for TTL-based cache cleaning.
+ */
+ isc_stdtime_t resign;
} rdatasetheader_t;
-#define RDATASET_ATTR_NONEXISTENT 0x0001
-#define RDATASET_ATTR_STALE 0x0002
-#define RDATASET_ATTR_IGNORE 0x0004
-#define RDATASET_ATTR_RETAIN 0x0008
-#define RDATASET_ATTR_NXDOMAIN 0x0010
+typedef ISC_LIST(rdatasetheader_t) rdatasetheaderlist_t;
+typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
+
+#define RDATASET_ATTR_NONEXISTENT 0x0001
+#define RDATASET_ATTR_STALE 0x0002
+#define RDATASET_ATTR_IGNORE 0x0004
+#define RDATASET_ATTR_RETAIN 0x0008
+#define RDATASET_ATTR_NXDOMAIN 0x0010
+#define RDATASET_ATTR_RESIGN 0x0020
+#define RDATASET_ATTR_STATCOUNT 0x0040
+#define RDATASET_ATTR_OPTOUT 0x0080
typedef struct acache_cbarg {
- dns_rdatasetadditional_t type;
- unsigned int count;
- dns_db_t *db;
- dns_dbnode_t *node;
- rdatasetheader_t *header;
+ dns_rdatasetadditional_t type;
+ unsigned int count;
+ dns_db_t *db;
+ dns_dbnode_t *node;
+ rdatasetheader_t *header;
} acache_cbarg_t;
struct acachectl {
- dns_acacheentry_t *entry;
- acache_cbarg_t *cbarg;
+ dns_acacheentry_t *entry;
+ acache_cbarg_t *cbarg;
};
/*
@@ -266,7 +313,7 @@ struct acachectl {
* expired.
*/
-#undef IGNORE /* WIN32 winbase.h defines this. */
+#undef IGNORE /* WIN32 winbase.h defines this. */
#define EXISTS(header) \
(((header)->attributes & RDATASET_ATTR_NONEXISTENT) == 0)
@@ -278,106 +325,164 @@ struct acachectl {
(((header)->attributes & RDATASET_ATTR_RETAIN) != 0)
#define NXDOMAIN(header) \
(((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
+#define RESIGN(header) \
+ (((header)->attributes & RDATASET_ATTR_RESIGN) != 0)
+#define OPTOUT(header) \
+ (((header)->attributes & RDATASET_ATTR_OPTOUT) != 0)
+
+#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
-#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
-#define DEFAULT_CACHE_NODE_LOCK_COUNT 1009 /*%< Should be prime. */
+/*%
+ * Number of buckets for cache DB entries (locks, LRU lists, TTL heaps).
+ * There is a tradeoff issue about configuring this value: if this is too
+ * small, it may cause heavier contention between threads; if this is too large,
+ * LRU purge algorithm won't work well (entries tend to be purged prematurely).
+ * The default value should work well for most environments, but this can
+ * also be configurable at compilation time via the
+ * DNS_RBTDB_CACHE_NODE_LOCK_COUNT variable. This value must be larger than
+ * 1 due to the assumption of overmem_purge().
+ */
+#ifdef DNS_RBTDB_CACHE_NODE_LOCK_COUNT
+#if DNS_RBTDB_CACHE_NODE_LOCK_COUNT <= 1
+#error "DNS_RBTDB_CACHE_NODE_LOCK_COUNT must be larger than 1"
+#else
+#define DEFAULT_CACHE_NODE_LOCK_COUNT DNS_RBTDB_CACHE_NODE_LOCK_COUNT
+#endif
+#else
+#define DEFAULT_CACHE_NODE_LOCK_COUNT 16
+#endif /* DNS_RBTDB_CACHE_NODE_LOCK_COUNT */
typedef struct {
- nodelock_t lock;
+ nodelock_t lock;
/* Protected in the refcount routines. */
- isc_refcount_t references;
+ isc_refcount_t references;
/* Locked by lock. */
- isc_boolean_t exiting;
+ isc_boolean_t exiting;
} rbtdb_nodelock_t;
typedef struct rbtdb_changed {
- dns_rbtnode_t * node;
- isc_boolean_t dirty;
- ISC_LINK(struct rbtdb_changed) link;
+ dns_rbtnode_t * node;
+ isc_boolean_t dirty;
+ ISC_LINK(struct rbtdb_changed) link;
} rbtdb_changed_t;
-typedef ISC_LIST(rbtdb_changed_t) rbtdb_changedlist_t;
+typedef ISC_LIST(rbtdb_changed_t) rbtdb_changedlist_t;
+
+typedef enum {
+ dns_db_insecure,
+ dns_db_partial,
+ dns_db_secure
+} dns_db_secure_t;
typedef struct rbtdb_version {
/* Not locked */
- rbtdb_serial_t serial;
+ rbtdb_serial_t serial;
/*
* Protected in the refcount routines.
* XXXJT: should we change the lock policy based on the refcount
* performance?
*/
- isc_refcount_t references;
+ isc_refcount_t references;
/* Locked by database lock. */
- isc_boolean_t writer;
- isc_boolean_t commit_ok;
- rbtdb_changedlist_t changed_list;
- ISC_LINK(struct rbtdb_version) link;
+ isc_boolean_t writer;
+ isc_boolean_t commit_ok;
+ rbtdb_changedlist_t changed_list;
+ rdatasetheaderlist_t resigned_list;
+ ISC_LINK(struct rbtdb_version) link;
+ dns_db_secure_t secure;
+ isc_boolean_t havensec3;
+ /* NSEC3 parameters */
+ dns_hash_t hash;
+ isc_uint8_t flags;
+ isc_uint16_t iterations;
+ isc_uint8_t salt_length;
+ unsigned char salt[NSEC3_MAX_HASH_LENGTH];
} rbtdb_version_t;
-typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t;
+typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t;
typedef struct {
/* Unlocked. */
- dns_db_t common;
+ dns_db_t common;
#if DNS_RBTDB_USERWLOCK
- isc_rwlock_t lock;
+ isc_rwlock_t lock;
#else
- isc_mutex_t lock;
+ isc_mutex_t lock;
#endif
- isc_rwlock_t tree_lock;
- unsigned int node_lock_count;
- rbtdb_nodelock_t * node_locks;
- dns_rbtnode_t * origin_node;
+ isc_rwlock_t tree_lock;
+ unsigned int node_lock_count;
+ rbtdb_nodelock_t * node_locks;
+ dns_rbtnode_t * origin_node;
+ dns_stats_t * rrsetstats; /* cache DB only */
/* Locked by lock. */
- unsigned int active;
- isc_refcount_t references;
- unsigned int attributes;
- rbtdb_serial_t current_serial;
- rbtdb_serial_t least_serial;
- rbtdb_serial_t next_serial;
- rbtdb_version_t * current_version;
- rbtdb_version_t * future_version;
- rbtdb_versionlist_t open_versions;
- isc_boolean_t overmem;
- isc_task_t * task;
- dns_dbnode_t *soanode;
- dns_dbnode_t *nsnode;
+ unsigned int active;
+ isc_refcount_t references;
+ unsigned int attributes;
+ rbtdb_serial_t current_serial;
+ rbtdb_serial_t least_serial;
+ rbtdb_serial_t next_serial;
+ rbtdb_version_t * current_version;
+ rbtdb_version_t * future_version;
+ rbtdb_versionlist_t open_versions;
+ isc_boolean_t overmem;
+ isc_task_t * task;
+ dns_dbnode_t *soanode;
+ dns_dbnode_t *nsnode;
+
+ /*
+ * This is a linked list used to implement the LRU cache. There will
+ * be node_lock_count linked lists here. Nodes in bucket 1 will be
+ * placed on the linked list rdatasets[1].
+ */
+ rdatasetheaderlist_t *rdatasets;
+
+ /*%
+ * Temporary storage for stale cache nodes and dynamically deleted
+ * nodes that await being cleaned up.
+ */
+ rbtnodelist_t *deadnodes;
+
+ /*
+ * Heaps. Each of these is used for TTL based expiry.
+ */
+ isc_heap_t **heaps;
+
/* Locked by tree_lock. */
- dns_rbt_t * tree;
- isc_boolean_t secure;
+ dns_rbt_t * tree;
+ dns_rbt_t * nsec3;
/* Unlocked */
- unsigned int quantum;
+ unsigned int quantum;
} dns_rbtdb_t;
-#define RBTDB_ATTR_LOADED 0x01
-#define RBTDB_ATTR_LOADING 0x02
+#define RBTDB_ATTR_LOADED 0x01
+#define RBTDB_ATTR_LOADING 0x02
/*%
* Search Context
*/
typedef struct {
- dns_rbtdb_t * rbtdb;
- rbtdb_version_t * rbtversion;
- rbtdb_serial_t serial;
- unsigned int options;
- dns_rbtnodechain_t chain;
- isc_boolean_t copy_name;
- isc_boolean_t need_cleanup;
- isc_boolean_t wild;
- dns_rbtnode_t * zonecut;
- rdatasetheader_t * zonecut_rdataset;
- rdatasetheader_t * zonecut_sigrdataset;
- dns_fixedname_t zonecut_name;
- isc_stdtime_t now;
+ dns_rbtdb_t * rbtdb;
+ rbtdb_version_t * rbtversion;
+ rbtdb_serial_t serial;
+ unsigned int options;
+ dns_rbtnodechain_t chain;
+ isc_boolean_t copy_name;
+ isc_boolean_t need_cleanup;
+ isc_boolean_t wild;
+ dns_rbtnode_t * zonecut;
+ rdatasetheader_t * zonecut_rdataset;
+ rdatasetheader_t * zonecut_sigrdataset;
+ dns_fixedname_t zonecut_name;
+ isc_stdtime_t now;
} rbtdb_search_t;
/*%
* Load Context
*/
typedef struct {
- dns_rbtdb_t * rbtdb;
- isc_stdtime_t now;
+ dns_rbtdb_t * rbtdb;
+ isc_stdtime_t now;
} rbtdb_load_t;
static void rdataset_disassociate(dns_rdataset_t *rdataset);
@@ -388,8 +493,12 @@ static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
static unsigned int rdataset_count(dns_rdataset_t *rdataset);
static isc_result_t rdataset_getnoqname(dns_rdataset_t *rdataset,
dns_name_t *name,
- dns_rdataset_t *nsec,
- dns_rdataset_t *nsecsig);
+ dns_rdataset_t *neg,
+ dns_rdataset_t *negsig);
+static isc_result_t rdataset_getclosest(dns_rdataset_t *rdataset,
+ dns_name_t *name,
+ dns_rdataset_t *neg,
+ dns_rdataset_t *negsig);
static isc_result_t rdataset_getadditional(dns_rdataset_t *rdataset,
dns_rdatasetadditional_t type,
dns_rdatatype_t qtype,
@@ -414,6 +523,17 @@ static isc_result_t rdataset_putadditional(dns_acache_t *acache,
dns_rdataset_t *rdataset,
dns_rdatasetadditional_t type,
dns_rdatatype_t qtype);
+static inline isc_boolean_t need_headerupdate(rdatasetheader_t *header,
+ isc_stdtime_t now);
+static void update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_stdtime_t now);
+static void expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_boolean_t tree_locked);
+static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
+ isc_stdtime_t now, isc_boolean_t tree_locked);
+static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx,
+ rdatasetheader_t *newheader);
+static void prune_tree(isc_task_t *task, isc_event_t *event);
static dns_rdatasetmethods_t rdataset_methods = {
rdataset_disassociate,
@@ -424,6 +544,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
rdataset_count,
NULL,
rdataset_getnoqname,
+ NULL,
+ rdataset_getclosest,
rdataset_getadditional,
rdataset_setadditional,
rdataset_putadditional
@@ -443,22 +565,22 @@ static dns_rdatasetitermethods_t rdatasetiter_methods = {
};
typedef struct rbtdb_rdatasetiter {
- dns_rdatasetiter_t common;
- rdatasetheader_t * current;
+ dns_rdatasetiter_t common;
+ rdatasetheader_t * current;
} rbtdb_rdatasetiter_t;
-static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
-static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
-static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
-static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
+static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
+static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
dns_name_t *name);
-static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
-static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
-static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
+static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
dns_dbnode_t **nodep,
dns_name_t *name);
-static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
-static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
+static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
dns_name_t *name);
static dns_dbiteratormethods_t dbiterator_methods = {
@@ -479,17 +601,21 @@ static dns_dbiteratormethods_t dbiterator_methods = {
* If 'paused' is ISC_TRUE, then the tree lock is not being held.
*/
typedef struct rbtdb_dbiterator {
- dns_dbiterator_t common;
- isc_boolean_t paused;
- isc_boolean_t new_origin;
- isc_rwlocktype_t tree_locked;
- isc_result_t result;
- dns_fixedname_t name;
- dns_fixedname_t origin;
- dns_rbtnodechain_t chain;
- dns_rbtnode_t *node;
- dns_rbtnode_t *deletions[DELETION_BATCH_MAX];
- int delete;
+ dns_dbiterator_t common;
+ isc_boolean_t paused;
+ isc_boolean_t new_origin;
+ isc_rwlocktype_t tree_locked;
+ isc_result_t result;
+ dns_fixedname_t name;
+ dns_fixedname_t origin;
+ dns_rbtnodechain_t chain;
+ dns_rbtnodechain_t nsec3chain;
+ dns_rbtnodechain_t *current;
+ dns_rbtnode_t *node;
+ dns_rbtnode_t *deletions[DELETION_BATCH_MAX];
+ int delete;
+ isc_boolean_t nsec3only;
+ isc_boolean_t nonsec3;
} rbtdb_dbiterator_t;
@@ -498,17 +624,20 @@ typedef struct rbtdb_dbiterator {
static void free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log,
isc_event_t *event);
+static void overmem(dns_db_t *db, isc_boolean_t overmem);
+static void setnsec3parameters(dns_db_t *db, rbtdb_version_t *version,
+ isc_boolean_t *nsec3createflag);
/*%
* 'init_count' is used to initialize 'newheader->count' which inturn
* is used to determine where in the cycle rrset-order cyclic starts.
- * We don't lock this as we don't care about simultanious updates.
+ * We don't lock this as we don't care about simultaneous updates.
*
* Note:
- * Both init_count and header->count can be ISC_UINT32_MAX.
+ * Both init_count and header->count can be ISC_UINT32_MAX.
* The count on the returned rdataset however can't be as
- * that indicates that the database does not implement cyclic
- * processing.
+ * that indicates that the database does not implement cyclic
+ * processing.
*/
static unsigned int init_count;
@@ -518,12 +647,12 @@ static unsigned int init_count;
* If a routine is going to lock more than one lock in this module, then
* the locking must be done in the following order:
*
- * Tree Lock
+ * Tree Lock
*
- * Node Lock (Only one from the set may be locked at one time by
- * any caller)
+ * Node Lock (Only one from the set may be locked at one time by
+ * any caller)
*
- * Database Lock
+ * Database Lock
*
* Failure to follow this hierarchy can result in deadlock.
*/
@@ -531,11 +660,7 @@ static unsigned int init_count;
/*
* Deleting Nodes
*
- * Currently there is no deletion of nodes from the database, except when
- * the database is being destroyed.
- *
- * If node deletion is added in the future, then for zone databases the node
- * for the origin of the zone MUST NOT be deleted.
+ * For zone databases the node for the origin of the zone MUST NOT be deleted.
*/
@@ -563,6 +688,96 @@ free_rbtdb_callback(isc_task_t *task, isc_event_t *event) {
free_rbtdb(rbtdb, ISC_TRUE, event);
}
+static void
+update_rrsetstats(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_boolean_t increment)
+{
+ dns_rdatastatstype_t statattributes = 0;
+ dns_rdatastatstype_t base = 0;
+ dns_rdatastatstype_t type;
+
+ /* At the moment we count statistics only for cache DB */
+ INSIST(IS_CACHE(rbtdb));
+
+ if (NXDOMAIN(header))
+ statattributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN;
+ else if (RBTDB_RDATATYPE_BASE(header->type) == 0) {
+ statattributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET;
+ base = RBTDB_RDATATYPE_EXT(header->type);
+ } else
+ base = RBTDB_RDATATYPE_BASE(header->type);
+
+ type = DNS_RDATASTATSTYPE_VALUE(base, statattributes);
+ if (increment)
+ dns_rdatasetstats_increment(rbtdb->rrsetstats, type);
+ else
+ dns_rdatasetstats_decrement(rbtdb->rrsetstats, type);
+}
+
+static void
+set_ttl(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, dns_ttl_t newttl) {
+ int idx;
+ isc_heap_t *heap;
+ dns_ttl_t oldttl;
+
+ oldttl = header->rdh_ttl;
+ header->rdh_ttl = newttl;
+
+ if (!IS_CACHE(rbtdb))
+ return;
+
+ /*
+ * It's possible the rbtdb is not a cache. If this is the case,
+ * we will not have a heap, and we move on. If we do, though,
+ * we might need to adjust things.
+ */
+ if (header->heap_index == 0 || newttl == oldttl)
+ return;
+ idx = header->node->locknum;
+ if (rbtdb->heaps == NULL || rbtdb->heaps[idx] == NULL)
+ return;
+ heap = rbtdb->heaps[idx];
+
+ if (newttl < oldttl)
+ isc_heap_increased(heap, header->heap_index);
+ else
+ isc_heap_decreased(heap, header->heap_index);
+}
+
+/*%
+ * These functions allow the heap code to rank the priority of each
+ * element. It returns ISC_TRUE if v1 happens "sooner" than v2.
+ */
+static isc_boolean_t
+ttl_sooner(void *v1, void *v2) {
+ rdatasetheader_t *h1 = v1;
+ rdatasetheader_t *h2 = v2;
+
+ if (h1->rdh_ttl < h2->rdh_ttl)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+static isc_boolean_t
+resign_sooner(void *v1, void *v2) {
+ rdatasetheader_t *h1 = v1;
+ rdatasetheader_t *h2 = v2;
+
+ if (h1->resign < h2->resign)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+/*%
+ * This function sets the heap index into the header.
+ */
+static void
+set_index(void *what, unsigned int index) {
+ rdatasetheader_t *h = what;
+
+ h->heap_index = index;
+}
+
/*%
* Work out how many nodes can be deleted in the time between two
* requests to the nameserver. Smooth the resulting number and use it
@@ -571,7 +786,7 @@ free_rbtdb_callback(isc_task_t *task, isc_event_t *event) {
*/
static unsigned int
adjust_quantum(unsigned int old, isc_time_t *start) {
- unsigned int pps = dns_pps; /* packets per second */
+ unsigned int pps = dns_pps; /* packets per second */
unsigned int interval;
isc_uint64_t usecs;
isc_time_t end;
@@ -581,7 +796,7 @@ adjust_quantum(unsigned int old, isc_time_t *start) {
pps = 100;
isc_time_now(&end);
- interval = 1000000 / pps; /* interval in usec */
+ interval = 1000000 / pps; /* interval in usec */
if (interval == 0)
interval = 1;
usecs = isc_time_microdiff(&end, start);
@@ -619,6 +834,9 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
char buf[DNS_NAME_FORMATSIZE];
isc_time_t start;
+ if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
+ overmem((dns_db_t *)rbtdb, (isc_boolean_t)-1);
+
REQUIRE(rbtdb->current_version != NULL || EMPTY(rbtdb->open_versions));
REQUIRE(rbtdb->future_version == NULL);
@@ -633,6 +851,21 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
isc_mem_put(rbtdb->common.mctx, rbtdb->current_version,
sizeof(rbtdb_version_t));
}
+
+ /*
+ * We assume the number of remaining dead nodes is reasonably small;
+ * the overhead of unlinking all nodes here should be negligible.
+ */
+ for (i = 0; i < rbtdb->node_lock_count; i++) {
+ dns_rbtnode_t *node;
+
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
+ while (node != NULL) {
+ ISC_LIST_UNLINK(rbtdb->deadnodes[i], node, deadlink);
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
+ }
+ }
+
if (event == NULL)
rbtdb->quantum = (rbtdb->task != NULL) ? 100 : 0;
again:
@@ -658,6 +891,30 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
}
INSIST(result == ISC_R_SUCCESS && rbtdb->tree == NULL);
}
+
+ if (rbtdb->nsec3 != NULL) {
+ isc_time_now(&start);
+ result = dns_rbt_destroy2(&rbtdb->nsec3, rbtdb->quantum);
+ if (result == ISC_R_QUOTA) {
+ INSIST(rbtdb->task != NULL);
+ if (rbtdb->quantum != 0)
+ rbtdb->quantum = adjust_quantum(rbtdb->quantum,
+ &start);
+ if (event == NULL)
+ event = isc_event_allocate(rbtdb->common.mctx,
+ NULL,
+ DNS_EVENT_FREESTORAGE,
+ free_rbtdb_callback,
+ rbtdb,
+ sizeof(isc_event_t));
+ if (event == NULL)
+ goto again;
+ isc_task_send(rbtdb->task, &event);
+ return;
+ }
+ INSIST(result == ISC_R_SUCCESS && rbtdb->nsec3 == NULL);
+ }
+
if (event != NULL)
isc_event_free(&event);
if (log) {
@@ -676,12 +933,47 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
isc_refcount_destroy(&rbtdb->node_locks[i].references);
NODE_DESTROYLOCK(&rbtdb->node_locks[i].lock);
}
+
+ /*
+ * Clean up LRU / re-signing order lists.
+ */
+ if (rbtdb->rdatasets != NULL) {
+ for (i = 0; i < rbtdb->node_lock_count; i++)
+ INSIST(ISC_LIST_EMPTY(rbtdb->rdatasets[i]));
+ isc_mem_put(rbtdb->common.mctx, rbtdb->rdatasets,
+ rbtdb->node_lock_count *
+ sizeof(rdatasetheaderlist_t));
+ }
+ /*
+ * Clean up dead node buckets.
+ */
+ if (rbtdb->deadnodes != NULL) {
+ for (i = 0; i < rbtdb->node_lock_count; i++)
+ INSIST(ISC_LIST_EMPTY(rbtdb->deadnodes[i]));
+ isc_mem_put(rbtdb->common.mctx, rbtdb->deadnodes,
+ rbtdb->node_lock_count * sizeof(rbtnodelist_t));
+ }
+ /*
+ * Clean up heap objects.
+ */
+ if (rbtdb->heaps != NULL) {
+ for (i = 0; i < rbtdb->node_lock_count; i++)
+ isc_heap_destroy(&rbtdb->heaps[i]);
+ isc_mem_put(rbtdb->common.mctx, rbtdb->heaps,
+ rbtdb->node_lock_count *
+ sizeof(isc_heap_t *));
+ }
+
+ if (rbtdb->rrsetstats != NULL)
+ dns_stats_detach(&rbtdb->rrsetstats);
+
isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks,
rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));
isc_rwlock_destroy(&rbtdb->tree_lock);
isc_refcount_destroy(&rbtdb->references);
if (rbtdb->task != NULL)
isc_task_detach(&rbtdb->task);
+
RBTDB_DESTROYLOCK(&rbtdb->lock);
rbtdb->common.magic = 0;
rbtdb->common.impmagic = 0;
@@ -788,6 +1080,7 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial,
version->writer = writer;
version->commit_ok = ISC_FALSE;
ISC_LIST_INIT(version->changed_list);
+ ISC_LIST_INIT(version->resigned_list);
ISC_LINK_INIT(version, link);
return (version);
@@ -803,11 +1096,29 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) {
REQUIRE(rbtdb->future_version == NULL);
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
- RUNTIME_CHECK(rbtdb->next_serial != 0); /* XXX Error? */
+ RUNTIME_CHECK(rbtdb->next_serial != 0); /* XXX Error? */
version = allocate_version(rbtdb->common.mctx, rbtdb->next_serial, 1,
ISC_TRUE);
if (version != NULL) {
version->commit_ok = ISC_TRUE;
+ version->secure = rbtdb->current_version->secure;
+ version->havensec3 = rbtdb->current_version->havensec3;
+ if (version->havensec3) {
+ version->flags = rbtdb->current_version->flags;
+ version->iterations =
+ rbtdb->current_version->iterations;
+ version->hash = rbtdb->current_version->hash;
+ version->salt_length =
+ rbtdb->current_version->salt_length;
+ memcpy(version->salt, rbtdb->current_version->salt,
+ version->salt_length);
+ } else {
+ version->flags = 0;
+ version->iterations = 0;
+ version->hash = 0;
+ version->salt_length = 0;
+ memset(version->salt, 0, sizeof(version->salt));
+ }
rbtdb->next_serial++;
rbtdb->future_version = version;
}
@@ -875,7 +1186,7 @@ free_acachearray(isc_mem_t *mctx, rdatasetheader_t *header,
{
unsigned int count;
unsigned int i;
- unsigned char *raw; /* RDATASLAB */
+ unsigned char *raw; /* RDATASLAB */
/*
* The caller must be holding the corresponding node lock.
@@ -903,22 +1214,69 @@ free_noqname(isc_mem_t *mctx, struct noqname **noqname) {
if (dns_name_dynamic(&(*noqname)->name))
dns_name_free(&(*noqname)->name, mctx);
- if ((*noqname)->nsec != NULL)
- isc_mem_put(mctx, (*noqname)->nsec,
- dns_rdataslab_size((*noqname)->nsec, 0));
- if ((*noqname)->nsecsig != NULL)
- isc_mem_put(mctx, (*noqname)->nsecsig,
- dns_rdataslab_size((*noqname)->nsecsig, 0));
+ if ((*noqname)->neg != NULL)
+ isc_mem_put(mctx, (*noqname)->neg,
+ dns_rdataslab_size((*noqname)->neg, 0));
+ if ((*noqname)->negsig != NULL)
+ isc_mem_put(mctx, (*noqname)->negsig,
+ dns_rdataslab_size((*noqname)->negsig, 0));
isc_mem_put(mctx, *noqname, sizeof(**noqname));
*noqname = NULL;
}
static inline void
-free_rdataset(isc_mem_t *mctx, rdatasetheader_t *rdataset) {
+init_rdataset(dns_rbtdb_t *rbtdb, rdatasetheader_t *h)
+{
+ ISC_LINK_INIT(h, lru_link);
+ h->heap_index = 0;
+
+#if TRACE_HEADER
+ if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
+ fprintf(stderr, "initialized header: %p\n", h);
+#else
+ UNUSED(rbtdb);
+#endif
+}
+
+static inline rdatasetheader_t *
+new_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx)
+{
+ rdatasetheader_t *h;
+
+ h = isc_mem_get(mctx, sizeof(*h));
+ if (h == NULL)
+ return (NULL);
+
+#if TRACE_HEADER
+ if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
+ fprintf(stderr, "allocated header: %p\n", h);
+#endif
+ init_rdataset(rbtdb, h);
+ return (h);
+}
+
+static inline void
+free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset)
+{
unsigned int size;
+ int idx;
+
+ if (EXISTS(rdataset) &&
+ (rdataset->attributes & RDATASET_ATTR_STATCOUNT) != 0) {
+ update_rrsetstats(rbtdb, rdataset, ISC_FALSE);
+ }
+
+ idx = rdataset->node->locknum;
+ if (ISC_LINK_LINKED(rdataset, lru_link))
+ ISC_LIST_UNLINK(rbtdb->rdatasets[idx], rdataset, lru_link);
+ if (rdataset->heap_index != 0)
+ isc_heap_delete(rbtdb->heaps[idx], rdataset->heap_index);
+ rdataset->heap_index = 0;
if (rdataset->noqname != NULL)
free_noqname(mctx, &rdataset->noqname);
+ if (rdataset->closest != NULL)
+ free_noqname(mctx, &rdataset->closest);
free_acachearray(mctx, rdataset, rdataset->additional_auth);
free_acachearray(mctx, rdataset, rdataset->additional_glue);
@@ -964,12 +1322,13 @@ rollback_node(dns_rbtnode_t *node, rbtdb_serial_t serial) {
}
static inline void
-clean_stale_headers(isc_mem_t *mctx, rdatasetheader_t *top) {
+clean_stale_headers(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *top)
+{
rdatasetheader_t *d, *down_next;
for (d = top->down; d != NULL; d = down_next) {
down_next = d->down;
- free_rdataset(mctx, d);
+ free_rdataset(rbtdb, mctx, d);
}
top->down = NULL;
}
@@ -986,7 +1345,7 @@ clean_cache_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
top_prev = NULL;
for (current = node->data; current != NULL; current = top_next) {
top_next = current->next;
- clean_stale_headers(mctx, current);
+ clean_stale_headers(rbtdb, mctx, current);
/*
* If current is nonexistent or stale, we can clean it up.
*/
@@ -996,7 +1355,7 @@ clean_cache_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
top_prev->next = current->next;
else
node->data = current->next;
- free_rdataset(mctx, current);
+ free_rdataset(rbtdb, mctx, current);
} else
top_prev = current;
}
@@ -1037,7 +1396,7 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
if (down_next != NULL)
down_next->next = dparent;
dparent->down = down_next;
- free_rdataset(mctx, dcurrent);
+ free_rdataset(rbtdb, mctx, dcurrent);
} else
dparent = dcurrent;
}
@@ -1053,7 +1412,7 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
top_prev->next = current->next;
else
node->data = current->next;
- free_rdataset(mctx, current);
+ free_rdataset(rbtdb, mctx, current);
/*
* current no longer exists, so we can
* just continue with the loop.
@@ -1069,7 +1428,7 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
else
node->data = down_next;
down_next->next = top_next;
- free_rdataset(mctx, current);
+ free_rdataset(rbtdb, mctx, current);
current = down_next;
}
}
@@ -1096,7 +1455,7 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
do {
down_next = dcurrent->down;
INSIST(dcurrent->serial <= least_serial);
- free_rdataset(mctx, dcurrent);
+ free_rdataset(rbtdb, mctx, dcurrent);
dcurrent = down_next;
} while (dcurrent != NULL);
dparent->down = NULL;
@@ -1120,7 +1479,7 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
top_prev->next = current->next;
else
node->data = current->next;
- free_rdataset(mctx, current);
+ free_rdataset(rbtdb, mctx, current);
} else
top_prev = current;
}
@@ -1129,6 +1488,49 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
node->dirty = 0;
}
+/*%
+ * Clean up dead nodes. These are nodes which have no references, and
+ * have no data. They are dead but we could not or chose not to delete
+ * them when we deleted all the data at that node because we did not want
+ * to wait for the tree write lock.
+ *
+ * The caller must hold a tree write lock and bucketnum'th node (write) lock.
+ */
+static void
+cleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) {
+ dns_rbtnode_t *node;
+ isc_result_t result;
+ int count = 10; /* XXXJT: should be adjustable */
+
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[bucketnum]);
+ while (node != NULL && count > 0) {
+ ISC_LIST_UNLINK(rbtdb->deadnodes[bucketnum], node, deadlink);
+
+ /*
+ * Since we're holding a tree write lock, it should be
+ * impossible for this node to be referenced by others.
+ */
+ INSIST(dns_rbtnode_refcurrent(node) == 0 &&
+ node->data == NULL);
+
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ if (node->nsec3)
+ result = dns_rbt_deletenode(rbtdb->nsec3, node,
+ ISC_FALSE);
+ else
+ result = dns_rbt_deletenode(rbtdb->tree, node,
+ ISC_FALSE);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
+ "cleanup_dead_nodes: "
+ "dns_rbt_deletenode: %s",
+ isc_result_totext(result));
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[bucketnum]);
+ count--;
+ }
+}
+
/*
* Caller must be holding the node lock if its reference must be protected
* by the lock.
@@ -1139,7 +1541,7 @@ new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
isc_refcount_t *lockref;
dns_rbtnode_refincrement0(node, &noderefs);
- if (noderefs == 1) { /* this is the first reference to the node */
+ if (noderefs == 1) { /* this is the first reference to the node */
lockref = &rbtdb->node_locks[node->locknum].references;
isc_refcount_increment0(lockref, &lockrefs);
INSIST(lockrefs != 0);
@@ -1148,6 +1550,49 @@ new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
}
/*
+ * This function is assumed to be called when a node is newly referenced
+ * and can be in the deadnode list. In that case the node must be retrieved
+ * from the list because it is going to be used. In addition, if the caller
+ * happens to hold a write lock on the tree, it's a good chance to purge dead
+ * nodes.
+ * Note: while a new reference is gained in multiple places, there are only very
+ * few cases where the node can be in the deadnode list (only empty nodes can
+ * have been added to the list).
+ */
+static inline void
+reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
+ isc_rwlocktype_t treelocktype)
+{
+ isc_boolean_t need_relock = ISC_FALSE;
+
+ NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
+ new_reference(rbtdb, node);
+
+ NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_read);
+ if (ISC_LINK_LINKED(node, deadlink))
+ need_relock = ISC_TRUE;
+ else if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) &&
+ treelocktype == isc_rwlocktype_write)
+ need_relock = ISC_TRUE;
+ NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_read);
+ if (need_relock) {
+ NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ if (ISC_LINK_LINKED(node, deadlink))
+ ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum],
+ node, deadlink);
+ if (treelocktype == isc_rwlocktype_write)
+ cleanup_dead_nodes(rbtdb, node->locknum);
+ NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ }
+
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+}
+
+/*
* Caller must be holding the node lock; either the "strong", read or write
* lock. Note that the lock must be held even when node references are
* atomically modified; in that case the decrement operation itself does not
@@ -1160,14 +1605,17 @@ new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
static isc_boolean_t
decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
rbtdb_serial_t least_serial,
- isc_rwlocktype_t nlock, isc_rwlocktype_t tlock)
+ isc_rwlocktype_t nlock, isc_rwlocktype_t tlock,
+ isc_boolean_t pruning)
{
isc_result_t result;
isc_boolean_t write_locked;
rbtdb_nodelock_t *nodelock;
unsigned int refs, nrefs;
+ int bucket = node->locknum;
+ isc_boolean_t no_reference;
- nodelock = &rbtdb->node_locks[node->locknum];
+ nodelock = &rbtdb->node_locks[bucket];
/* Handle easy and typical case first. */
if (!node->dirty && (node->data != NULL || node->down != NULL)) {
@@ -1226,7 +1674,9 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
}
/*
- * XXXDCL need to add a deferred delete method for ISC_R_LOCKBUSY.
+ * Attempt to switch to a write lock on the tree. If this fails,
+ * we will add this node to a linked list of nodes in this locking
+ * bucket which we will free later.
*/
if (tlock != isc_rwlocktype_write) {
/*
@@ -1246,6 +1696,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
} else
write_locked = ISC_TRUE;
+ no_reference = ISC_TRUE;
if (write_locked && dns_rbtnode_refcurrent(node) == 0) {
/*
* We can now delete the node if the reference counter is
@@ -1254,26 +1705,97 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
* current thread locks the tree (e.g., in findnode()).
*/
- if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) {
- char printname[DNS_NAME_FORMATSIZE];
+ /*
+ * If this node is the only one in the level it's in, deleting
+ * this node may recursively make its parent the only node in
+ * the parent level; if so, and if no one is currently using
+ * the parent node, this is almost the only opportunity to
+ * clean it up. But the recursive cleanup is not that trivial
+ * since the child and parent may be in different lock buckets,
+ * which would cause a lock order reversal problem. To avoid
+ * the trouble, we'll dispatch a separate event for batch
+ * cleaning. We need to check whether we're deleting the node
+ * as a result of pruning to avoid infinite dispatching.
+ * Note: pruning happens only when a task has been set for the
+ * rbtdb. If the user of the rbtdb chooses not to set a task,
+ * it's their responsibility to purge stale leaves (e.g. by
+ * periodic walk-through).
+ */
+ if (!pruning && node->parent != NULL &&
+ node->parent->down == node && node->left == NULL &&
+ node->right == NULL && rbtdb->task != NULL) {
+ isc_event_t *ev;
+ dns_db_t *db;
+
+ ev = isc_event_allocate(rbtdb->common.mctx, NULL,
+ DNS_EVENT_RBTPRUNE,
+ prune_tree, node,
+ sizeof(isc_event_t));
+ if (ev != NULL) {
+ new_reference(rbtdb, node);
+ db = NULL;
+ attach((dns_db_t *)rbtdb, &db);
+ ev->ev_sender = db;
+ isc_task_send(rbtdb->task, &ev);
+ no_reference = ISC_FALSE;
+ } else {
+ /*
+ * XXX: this is a weird situation. We could
+ * ignore this error case, but then the stale
+ * node will unlikely be purged except via a
+ * rare condition such as manual cleanup. So
+ * we queue it in the deadnodes list, hoping
+ * the memory shortage is temporary and the node
+ * will be deleted later.
+ */
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_INFO,
+ "decrement_reference: failed to "
+ "allocate pruning event");
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node,
+ deadlink);
+ }
+ } else {
+ if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) {
+ char printname[DNS_NAME_FORMATSIZE];
+
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1),
+ "decrement_reference: "
+ "delete from rbt: %p %s",
+ node,
+ dns_rbt_formatnodename(node,
+ printname,
+ sizeof(printname)));
+ }
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
- "decrement_reference: "
- "delete from rbt: %p %s",
- node,
- dns_rbt_formatnodename(node, printname,
- sizeof(printname)));
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ if (node->nsec3)
+ result = dns_rbt_deletenode(rbtdb->nsec3, node,
+ ISC_FALSE);
+ else
+ result = dns_rbt_deletenode(rbtdb->tree, node,
+ ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_WARNING,
+ "decrement_reference: "
+ "dns_rbt_deletenode: %s",
+ isc_result_totext(result));
+ }
}
-
- result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
- if (result != ISC_R_SUCCESS)
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
- "decrement_reference: "
- "dns_rbt_deletenode: %s",
- isc_result_totext(result));
- }
+ } else if (dns_rbtnode_refcurrent(node) == 0) {
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, deadlink);
+ } else
+ no_reference = ISC_FALSE;
/* Restore the lock? */
if (nlock == isc_rwlocktype_read)
@@ -1290,7 +1812,71 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
if (write_locked)
isc_rwlock_downgrade(&rbtdb->tree_lock);
- return (ISC_TRUE);
+ return (no_reference);
+}
+
+/*
+ * Prune the tree by recursively cleaning-up single leaves. In the worst
+ * case, the number of iteration is the number of tree levels, which is at
+ * most the maximum number of domain name labels, i.e, 127. In practice, this
+ * should be much smaller (only a few times), and even the worst case would be
+ * acceptable for a single event.
+ */
+static void
+prune_tree(isc_task_t *task, isc_event_t *event) {
+ dns_rbtdb_t *rbtdb = event->ev_sender;
+ dns_rbtnode_t *node = event->ev_arg;
+ dns_rbtnode_t *parent;
+ unsigned int locknum;
+
+ UNUSED(task);
+
+ isc_event_free(&event);
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ locknum = node->locknum;
+ NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write);
+ do {
+ parent = node->parent;
+ decrement_reference(rbtdb, node, 0, isc_rwlocktype_write,
+ isc_rwlocktype_write, ISC_TRUE);
+
+ if (parent != NULL && parent->down == NULL) {
+ /*
+ * node was the only down child of the parent and has
+ * just been removed. We'll then need to examine the
+ * parent. Keep the lock if possible; otherwise,
+ * release the old lock and acquire one for the parent.
+ */
+ if (parent->locknum != locknum) {
+ NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+ locknum = parent->locknum;
+ NODE_LOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+ }
+
+ /*
+ * We need to gain a reference to the node before
+ * decrementing it in the next iteration. In addition,
+ * if the node is in the dead-nodes list, extract it
+ * from the list beforehand as we do in
+ * reactivate_node().
+ */
+ new_reference(rbtdb, parent);
+ if (ISC_LINK_LINKED(parent, deadlink)) {
+ ISC_LIST_UNLINK(rbtdb->deadnodes[locknum],
+ parent, deadlink);
+ }
+ } else
+ parent = NULL;
+
+ node = parent;
+ } while (node != NULL);
+ NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+
+ detach((dns_db_t **)&rbtdb);
}
static inline void
@@ -1337,17 +1923,20 @@ cleanup_nondirty(rbtdb_version_t *version, rbtdb_changedlist_t *cleanup_list) {
}
}
-static isc_boolean_t
-iszonesecure(dns_db_t *db, dns_dbnode_t *origin) {
+static void
+iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) {
dns_rdataset_t keyset;
dns_rdataset_t nsecset, signsecset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
isc_boolean_t haszonekey = ISC_FALSE;
isc_boolean_t hasnsec = ISC_FALSE;
+ isc_boolean_t hasoptbit = ISC_FALSE;
+ isc_boolean_t nsec3createflag = ISC_FALSE;
isc_result_t result;
dns_rdataset_init(&keyset);
- result = dns_db_findrdataset(db, origin, NULL, dns_rdatatype_dnskey, 0,
- 0, &keyset, NULL);
+ result = dns_db_findrdataset(db, origin, version, dns_rdatatype_dnskey,
+ 0, 0, &keyset, NULL);
if (result == ISC_R_SUCCESS) {
dns_rdata_t keyrdata = DNS_RDATA_INIT;
result = dns_rdataset_first(&keyset);
@@ -1361,21 +1950,153 @@ iszonesecure(dns_db_t *db, dns_dbnode_t *origin) {
}
dns_rdataset_disassociate(&keyset);
}
- if (!haszonekey)
- return (ISC_FALSE);
+ if (!haszonekey) {
+ version->secure = dns_db_insecure;
+ version->havensec3 = ISC_FALSE;
+ return;
+ }
dns_rdataset_init(&nsecset);
dns_rdataset_init(&signsecset);
- result = dns_db_findrdataset(db, origin, NULL, dns_rdatatype_nsec, 0,
- 0, &nsecset, &signsecset);
+ result = dns_db_findrdataset(db, origin, version, dns_rdatatype_nsec,
+ 0, 0, &nsecset, &signsecset);
if (result == ISC_R_SUCCESS) {
if (dns_rdataset_isassociated(&signsecset)) {
hasnsec = ISC_TRUE;
+ result = dns_rdataset_first(&nsecset);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&nsecset, &rdata);
+ hasoptbit = dns_nsec_typepresent(&rdata,
+ dns_rdatatype_opt);
+ }
dns_rdataset_disassociate(&signsecset);
}
dns_rdataset_disassociate(&nsecset);
}
- return (hasnsec);
+
+ setnsec3parameters(db, version, &nsec3createflag);
+
+ /*
+ * Do we have a valid NSEC/NSEC3 chain?
+ */
+ if (version->havensec3 || (hasnsec && !hasoptbit))
+ version->secure = dns_db_secure;
+ /*
+ * Do we have a NSEC/NSEC3 chain under creation?
+ */
+ else if (hasoptbit || nsec3createflag)
+ version->secure = dns_db_partial;
+ else
+ version->secure = dns_db_insecure;
+}
+
+/*%<
+ * Walk the origin node looking for NSEC3PARAM records.
+ * Cache the nsec3 parameters.
+ */
+static void
+setnsec3parameters(dns_db_t *db, rbtdb_version_t *version,
+ isc_boolean_t *nsec3createflag)
+{
+ dns_rbtnode_t *node;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t region;
+ isc_result_t result;
+ rdatasetheader_t *header, *header_next;
+ unsigned char *raw; /* RDATASLAB */
+ unsigned int count, length;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ version->havensec3 = ISC_FALSE;
+ node = rbtdb->origin_node;
+ NODE_LOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ for (header = node->data;
+ header != NULL;
+ header = header_next) {
+ header_next = header->next;
+ do {
+ if (header->serial <= version->serial &&
+ !IGNORE(header)) {
+ if (NONEXISTENT(header))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+
+ if (header != NULL &&
+ header->type == dns_rdatatype_nsec3param) {
+ /*
+ * Find A NSEC3PARAM with a supported algorithm.
+ */
+ raw = (unsigned char *)header + sizeof(*header);
+ count = raw[0] * 256 + raw[1]; /* count */
+#if DNS_RDATASET_FIXED
+ raw += count * 4 + 2;
+#else
+ raw += 2;
+#endif
+ while (count-- > 0U) {
+ length = raw[0] * 256 + raw[1];
+#if DNS_RDATASET_FIXED
+ raw += 4;
+#else
+ raw += 2;
+#endif
+ region.base = raw;
+ region.length = length;
+ raw += length;
+ dns_rdata_fromregion(&rdata,
+ rbtdb->common.rdclass,
+ dns_rdatatype_nsec3param,
+ &region);
+ result = dns_rdata_tostruct(&rdata,
+ &nsec3param,
+ NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdata_reset(&rdata);
+
+ if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG &&
+ !dns_nsec3_supportedhash(nsec3param.hash))
+ continue;
+
+#ifdef RFC5155_STRICT
+ if (nsec3param.flags != 0)
+ continue;
+#else
+ if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE)
+ != 0)
+ *nsec3createflag = ISC_TRUE;
+ if ((nsec3param.flags & ~DNS_NSEC3FLAG_OPTOUT)
+ != 0)
+ continue;
+#endif
+
+ INSIST(nsec3param.salt_length <=
+ sizeof(version->salt));
+ memcpy(version->salt, nsec3param.salt,
+ nsec3param.salt_length);
+ version->hash = nsec3param.hash;
+ version->salt_length = nsec3param.salt_length;
+ version->iterations = nsec3param.iterations;
+ version->flags = nsec3param.flags;
+ version->havensec3 = ISC_TRUE;
+ /*
+ * Look for a better algorithm than the
+ * unknown test algorithm.
+ */
+ if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG)
+ goto unlock;
+ }
+ }
+ }
+ unlock:
+ NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
}
static void
@@ -1384,10 +2105,12 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
rbtdb_version_t *version, *cleanup_version, *least_greater;
isc_boolean_t rollback = ISC_FALSE;
rbtdb_changedlist_t cleanup_list;
+ rdatasetheaderlist_t resigned_list;
rbtdb_changed_t *changed, *next_changed;
rbtdb_serial_t serial, least_serial;
dns_rbtnode_t *rbtnode;
unsigned int refs;
+ rdatasetheader_t *header;
isc_boolean_t writer;
REQUIRE(VALID_RBTDB(rbtdb));
@@ -1395,9 +2118,10 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
cleanup_version = NULL;
ISC_LIST_INIT(cleanup_list);
+ ISC_LIST_INIT(resigned_list);
isc_refcount_decrement(&version->references, &refs);
- if (refs > 0) { /* typical and easy case first */
+ if (refs > 0) { /* typical and easy case first */
if (commit) {
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
INSIST(!version->writer);
@@ -1484,12 +2208,16 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
INSIST(cur_ref == 1);
PREPEND(rbtdb->open_versions,
rbtdb->current_version, link);
+ resigned_list = version->resigned_list;
+ ISC_LIST_INIT(version->resigned_list);
} else {
/*
* We're rolling back this transaction.
*/
cleanup_list = version->changed_list;
ISC_LIST_INIT(version->changed_list);
+ resigned_list = version->resigned_list;
+ ISC_LIST_INIT(version->resigned_list);
rollback = ISC_TRUE;
cleanup_version = version;
rbtdb->future_version = NULL;
@@ -1542,7 +2270,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
* Update the zone's secure status.
*/
if (writer && commit && !IS_CACHE(rbtdb))
- rbtdb->secure = iszonesecure(db, rbtdb->origin_node);
+ iszonesecure(db, version, rbtdb->origin_node);
if (cleanup_version != NULL) {
INSIST(EMPTY(cleanup_version->changed_list));
@@ -1550,7 +2278,35 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
sizeof(*cleanup_version));
}
+ /*
+ * Commit/rollback re-signed headers.
+ */
+ for (header = HEAD(resigned_list);
+ header != NULL;
+ header = HEAD(resigned_list)) {
+ ISC_LIST_UNLINK(resigned_list, header, lru_link);
+ if (rollback) {
+ nodelock_t *lock;
+ lock = &rbtdb->node_locks[header->node->locknum].lock;
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ resign_insert(rbtdb, header->node->locknum, header);
+ NODE_UNLOCK(lock, isc_rwlocktype_write);
+ }
+ decrement_reference(rbtdb, header->node, least_serial,
+ isc_rwlocktype_write, isc_rwlocktype_none,
+ ISC_FALSE);
+ }
+
if (!EMPTY(cleanup_list)) {
+ /*
+ * We acquire a tree write lock here in order to make sure
+ * that stale nodes will be removed in decrement_reference().
+ * If we didn't have the lock, those nodes could miss the
+ * chance to be removed until the server stops. The write lock
+ * is expensive, but this event should be rare enough to justify
+ * the cost.
+ */
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
for (changed = HEAD(cleanup_list);
changed != NULL;
changed = next_changed) {
@@ -1561,19 +2317,27 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
lock = &rbtdb->node_locks[rbtnode->locknum].lock;
NODE_LOCK(lock, isc_rwlocktype_write);
+ /*
+ * This is a good opportunity to purge any dead nodes,
+ * so use it.
+ */
+ cleanup_dead_nodes(rbtdb, rbtnode->locknum);
+
if (rollback)
rollback_node(rbtnode, serial);
decrement_reference(rbtdb, rbtnode, least_serial,
isc_rwlocktype_write,
- isc_rwlocktype_none);
+ isc_rwlocktype_write, ISC_FALSE);
+
NODE_UNLOCK(lock, isc_rwlocktype_write);
isc_mem_put(rbtdb->common.mctx, changed,
sizeof(*changed));
}
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
}
- end:
+ end:
*versionp = NULL;
}
@@ -1606,6 +2370,7 @@ add_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) {
result = dns_rbt_addnode(rbtdb->tree, &foundname, &node);
if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
return (result);
+ node->nsec3 = 0;
node->find_callback = 1;
node->wild = 1;
return (ISC_R_SUCCESS);
@@ -1623,7 +2388,7 @@ add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) {
l = dns_name_countlabels(&rbtdb->common.origin);
i = l + 1;
while (i < n) {
- dns_rbtnode_t *node = NULL; /* dummy */
+ dns_rbtnode_t *node = NULL; /* dummy */
dns_name_getlabelsequence(name, n - i, i, &foundname);
if (dns_name_iswildcard(&foundname)) {
result = add_wildcard_magic(rbtdb, &foundname);
@@ -1633,6 +2398,7 @@ add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) {
&node);
if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
return (result);
+ node->nsec3 = 0;
}
i++;
}
@@ -1678,6 +2444,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
node->locknum = dns_name_hash(&nodename, ISC_TRUE) %
rbtdb->node_lock_count;
#endif
+ node->nsec3 = 0;
add_empty_wildcards(rbtdb, name);
if (dns_name_iswildcard(name)) {
@@ -1692,6 +2459,60 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
return (result);
}
}
+ reactivate_node(rbtdb, node, locktype);
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+
+ *nodep = (dns_dbnode_t *)node;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
+ dns_dbnode_t **nodep)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *node = NULL;
+ dns_name_t nodename;
+ isc_result_t result;
+ isc_rwlocktype_t locktype = isc_rwlocktype_read;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ dns_name_init(&nodename, NULL);
+ RWLOCK(&rbtdb->tree_lock, locktype);
+ result = dns_rbt_findnode(rbtdb->nsec3, name, NULL, &node, NULL,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+ if (!create) {
+ if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+ return (result);
+ }
+ /*
+ * It would be nice to try to upgrade the lock instead of
+ * unlocking then relocking.
+ */
+ locktype = isc_rwlocktype_write;
+ RWLOCK(&rbtdb->tree_lock, locktype);
+ node = NULL;
+ result = dns_rbt_addnode(rbtdb->nsec3, name, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_rbt_namefromnode(node, &nodename);
+#ifdef DNS_RBT_USEHASH
+ node->locknum = node->hashval % rbtdb->node_lock_count;
+#else
+ node->locknum = dns_name_hash(&nodename, ISC_TRUE) %
+ rbtdb->node_lock_count;
+#endif
+ node->nsec3 = 1U;
+ } else if (result != ISC_R_EXISTS) {
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+ return (result);
+ }
+ } else
+ INSIST(node->nsec3);
NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
new_reference(rbtdb, node);
NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
@@ -1846,7 +2667,7 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
rdatasetheader_t *header, isc_stdtime_t now,
dns_rdataset_t *rdataset)
{
- unsigned char *raw; /* RDATASLAB */
+ unsigned char *raw; /* RDATASLAB */
/*
* Caller must be holding the node reader lock.
@@ -1861,16 +2682,18 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
new_reference(rbtdb, node);
- INSIST(rdataset->methods == NULL); /* We must be disassociated. */
+ INSIST(rdataset->methods == NULL); /* We must be disassociated. */
rdataset->methods = &rdataset_methods;
rdataset->rdclass = rbtdb->common.rdclass;
rdataset->type = RBTDB_RDATATYPE_BASE(header->type);
rdataset->covers = RBTDB_RDATATYPE_EXT(header->type);
- rdataset->ttl = header->ttl - now;
+ rdataset->ttl = header->rdh_ttl - now;
rdataset->trust = header->trust;
if (NXDOMAIN(header))
rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
+ if (OPTOUT(header))
+ rdataset->attributes |= DNS_RDATASETATTR_OPTOUT;
rdataset->private1 = rbtdb;
rdataset->private2 = node;
raw = (unsigned char *)header + sizeof(*header);
@@ -1891,6 +2714,18 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
rdataset->private6 = header->noqname;
if (rdataset->private6 != NULL)
rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
+ rdataset->private7 = header->closest;
+ if (rdataset->private7 != NULL)
+ rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
+
+ /*
+ * Copy out re-signing information.
+ */
+ if (RESIGN(header)) {
+ rdataset->attributes |= DNS_RDATASETATTR_RESIGN;
+ rdataset->resign = header->resign;
+ } else
+ rdataset->resign = 0;
}
static inline isc_result_t
@@ -1954,7 +2789,7 @@ static inline isc_boolean_t
valid_glue(rbtdb_search_t *search, dns_name_t *name, rbtdb_rdatatype_t type,
dns_rbtnode_t *node)
{
- unsigned char *raw; /* RDATASLAB */
+ unsigned char *raw; /* RDATASLAB */
unsigned int count, size;
dns_name_t ns_name;
isc_boolean_t valid = ISC_FALSE;
@@ -2338,10 +3173,55 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
return (result);
}
+static isc_boolean_t
+matchparams(rdatasetheader_t *header, rbtdb_search_t *search)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3_t nsec3;
+ unsigned char *raw; /* RDATASLAB */
+ unsigned int rdlen, count;
+ isc_region_t region;
+ isc_result_t result;
+
+ REQUIRE(header->type == dns_rdatatype_nsec3);
+
+ raw = (unsigned char *)header + sizeof(*header);
+ count = raw[0] * 256 + raw[1]; /* count */
+#if DNS_RDATASET_FIXED
+ raw += count * 4 + 2;
+#else
+ raw += 2;
+#endif
+ while (count-- > 0) {
+ rdlen = raw[0] * 256 + raw[1];
+#if DNS_RDATASET_FIXED
+ raw += 4;
+#else
+ raw += 2;
+#endif
+ region.base = raw;
+ region.length = rdlen;
+ dns_rdata_fromregion(&rdata, search->rbtdb->common.rdclass,
+ dns_rdatatype_nsec3, &region);
+ raw += rdlen;
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ if (nsec3.hash == search->rbtversion->hash &&
+ nsec3.iterations == search->rbtversion->iterations &&
+ nsec3.salt_length == search->rbtversion->salt_length &&
+ memcmp(nsec3.salt, search->rbtversion->salt,
+ nsec3.salt_length) == 0)
+ return (ISC_TRUE);
+ dns_rdata_reset(&rdata);
+ }
+ return (ISC_FALSE);
+}
+
static inline isc_result_t
find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
dns_name_t *foundname, dns_rdataset_t *rdataset,
- dns_rdataset_t *sigrdataset, isc_boolean_t need_sig)
+ dns_rdataset_t *sigrdataset, dns_rbt_t *tree,
+ dns_db_secure_t secure)
{
dns_rbtnode_t *node;
rdatasetheader_t *header, *header_next, *found, *foundsig;
@@ -2349,7 +3229,22 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
isc_result_t result;
dns_fixedname_t fname, forigin;
dns_name_t *name, *origin;
+ dns_rdatatype_t type;
+ rbtdb_rdatatype_t sigtype;
+ isc_boolean_t wraps;
+ isc_boolean_t need_sig = ISC_TF(secure == dns_db_secure);
+ if (tree == search->rbtdb->nsec3) {
+ type = dns_rdatatype_nsec3;
+ sigtype = RBTDB_RDATATYPE_SIGNSEC3;
+ wraps = ISC_TRUE;
+ } else {
+ type = dns_rdatatype_nsec;
+ sigtype = RBTDB_RDATATYPE_SIGNSEC;
+ wraps = ISC_FALSE;
+ }
+
+ again:
do {
node = NULL;
dns_fixedname_init(&fname);
@@ -2391,12 +3286,11 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
* active rdataset at this node.
*/
empty_node = ISC_FALSE;
- if (header->type == dns_rdatatype_nsec) {
+ if (header->type == type) {
found = header;
if (foundsig != NULL)
break;
- } else if (header->type ==
- RBTDB_RDATATYPE_SIGNSEC) {
+ } else if (header->type == sigtype) {
foundsig = header;
if (found != NULL)
break;
@@ -2404,11 +3298,19 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
}
}
if (!empty_node) {
- if (found != NULL &&
- (foundsig != NULL || !need_sig))
+ if (found != NULL && search->rbtversion->havensec3 &&
+ found->type == dns_rdatatype_nsec3 &&
+ !matchparams(found, search)) {
+ empty_node = ISC_TRUE;
+ found = NULL;
+ foundsig = NULL;
+ result = dns_rbtnodechain_prev(&search->chain,
+ NULL, NULL);
+ } else if (found != NULL &&
+ (foundsig != NULL || !need_sig))
{
/*
- * We've found the right NSEC record.
+ * We've found the right NSEC/NSEC3 record.
*
* Note: for this to really be the right
* NSEC record, it's essential that the NSEC
@@ -2465,6 +3367,15 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
isc_rwlocktype_read);
} while (empty_node && result == ISC_R_SUCCESS);
+ if (result == ISC_R_NOMORE && wraps) {
+ result = dns_rbtnodechain_last(&search->chain, tree,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
+ wraps = ISC_FALSE;
+ goto again;
+ }
+ }
+
/*
* If the result is ISC_R_NOMORE, then we got to the beginning of
* the database and didn't find a NSEC record. This shouldn't
@@ -2497,7 +3408,7 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
isc_boolean_t active;
dns_rbtnodechain_t chain;
nodelock_t *lock;
-
+ dns_rbt_t *tree;
search.rbtdb = (dns_rbtdb_t *)db;
@@ -2540,7 +3451,9 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* encounter a callback node, zone_zonecut_callback() will search the
* rdatasets at the zone cut for active DNAME or NS rdatasets.
*/
- result = dns_rbt_findnode(search.rbtdb->tree, name, foundname, &node,
+ tree = (options & DNS_DBFIND_FORCENSEC3) != 0 ? search.rbtdb->nsec3 :
+ search.rbtdb->tree;
+ result = dns_rbt_findnode(tree, name, foundname, &node,
&search.chain, DNS_RBTFIND_EMPTYDATA,
zone_zonecut_callback, &search);
@@ -2578,12 +3491,14 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* If we're here, then the name does not exist, is not
* beneath a zonecut, and there's no matching wildcard.
*/
- if (search.rbtdb->secure ||
- (search.options & DNS_DBFIND_FORCENSEC) != 0)
+ if ((search.rbtversion->secure == dns_db_secure &&
+ !search.rbtversion->havensec3) ||
+ (search.options & DNS_DBFIND_FORCENSEC) != 0 ||
+ (search.options & DNS_DBFIND_FORCENSEC3) != 0)
{
result = find_closest_nsec(&search, nodep, foundname,
- rdataset, sigrdataset,
- search.rbtdb->secure);
+ rdataset, sigrdataset, tree,
+ search.rbtversion->secure);
if (result == ISC_R_SUCCESS)
result = active ? DNS_R_EMPTYNAME :
DNS_R_NXDOMAIN;
@@ -2704,6 +3619,14 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
break;
}
+
+ /*
+ * If the NSEC3 record doesn't match the chain
+ * we are using behave as if it isn't here.
+ */
+ if (header->type == dns_rdatatype_nsec3 &&
+ !matchparams(header, &search))
+ goto partial_match;
/*
* If we found a type we were looking for,
* remember it.
@@ -2748,14 +3671,16 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
*/
if (!maybe_zonecut && found != NULL)
break;
- } else if (header->type == dns_rdatatype_nsec) {
+ } else if (header->type == dns_rdatatype_nsec &&
+ !search.rbtversion->havensec3) {
/*
* Remember a NSEC rdataset even if we're
* not specifically looking for it, because
* we might need it later.
*/
nsecheader = header;
- } else if (header->type == RBTDB_RDATATYPE_SIGNSEC) {
+ } else if (header->type == RBTDB_RDATATYPE_SIGNSEC &&
+ !search.rbtversion->havensec3) {
/*
* If we need the NSEC rdataset, we'll also
* need its signature.
@@ -2807,7 +3732,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* The desired type doesn't exist.
*/
result = DNS_R_NXRRSET;
- if (search.rbtdb->secure &&
+ if (search.rbtversion->secure == dns_db_secure &&
+ !search.rbtversion->havensec3 &&
(nsecheader == NULL || nsecsig == NULL)) {
/*
* The zone is secure but there's no NSEC,
@@ -2822,7 +3748,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
NODE_UNLOCK(lock, isc_rwlocktype_read);
result = find_closest_nsec(&search, nodep, foundname,
rdataset, sigrdataset,
- search.rbtdb->secure);
+ search.rbtdb->tree,
+ search.rbtversion->secure);
if (result == ISC_R_SUCCESS)
result = DNS_R_EMPTYWILD;
goto tree_exit;
@@ -2841,7 +3768,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
new_reference(search.rbtdb, node);
*nodep = node;
}
- if (search.rbtdb->secure ||
+ if ((search.rbtversion->secure == dns_db_secure &&
+ !search.rbtversion->havensec3) ||
(search.options & DNS_DBFIND_FORCENSEC) != 0)
{
bind_rdataset(search.rbtdb, node, nsecheader,
@@ -2882,6 +3810,7 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* validated updates.
*/
if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3 ||
type == dns_rdatatype_key)
result = ISC_R_SUCCESS;
else if (type == dns_rdatatype_any)
@@ -2948,7 +3877,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
NODE_LOCK(lock, isc_rwlocktype_read);
decrement_reference(search.rbtdb, node, 0,
- isc_rwlocktype_read, isc_rwlocktype_none);
+ isc_rwlocktype_read, isc_rwlocktype_none,
+ ISC_FALSE);
NODE_UNLOCK(lock, isc_rwlocktype_read);
}
@@ -3010,7 +3940,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
header_prev = NULL;
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
- if (header->ttl <= search->now) {
+ if (header->rdh_ttl <= search->now) {
/*
* This rdataset is stale. If no one else is
* using the node, we can clean it up right
@@ -3018,7 +3948,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
* the node as dirty, so it will get cleaned
* up later.
*/
- if ((header->ttl <= search->now - RBTDB_VIRTUAL) &&
+ if ((header->rdh_ttl <= search->now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -3044,13 +3974,16 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
* stale headers first.
*/
mctx = search->rbtdb->common.mctx;
- clean_stale_headers(mctx, header);
+ clean_stale_headers(search->rbtdb,
+ mctx,
+ header);
if (header_prev != NULL)
header_prev->next =
header->next;
else
node->data = header->next;
- free_rdataset(mctx, header);
+ free_rdataset(search->rbtdb, mctx,
+ header);
} else {
header->attributes |=
RDATASET_ATTR_STALE;
@@ -3079,6 +4012,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
* search->zonecut_rdataset will still be valid later.
*/
new_reference(search->rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
search->zonecut = node;
search->zonecut_rdataset = dname_header;
search->zonecut_sigrdataset = sigdname_header;
@@ -3130,7 +4064,7 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
header != NULL;
header = header_next) {
header_next = header->next;
- if (header->ttl <= search->now) {
+ if (header->rdh_ttl <= search->now) {
/*
* This rdataset is stale. If no one else is
* using the node, we can clean it up right
@@ -3138,7 +4072,7 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
* the node as dirty, so it will get cleaned
* up later.
*/
- if ((header->ttl <= search->now -
+ if ((header->rdh_ttl <= search->now -
RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
@@ -3153,14 +4087,17 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
isc_mem_t *m;
m = search->rbtdb->common.mctx;
- clean_stale_headers(m, header);
+ clean_stale_headers(
+ search->rbtdb,
+ m, header);
if (header_prev != NULL)
header_prev->next =
header->next;
else
node->data =
header->next;
- free_rdataset(m, header);
+ free_rdataset(rbtdb, m,
+ header);
} else {
header->attributes |=
RDATASET_ATTR_STALE;
@@ -3229,6 +4166,23 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
if (foundsig != NULL)
bind_rdataset(search->rbtdb, node, foundsig,
search->now, sigrdataset);
+ if (need_headerupdate(found, search->now) ||
+ (foundsig != NULL &&
+ need_headerupdate(foundsig, search->now))) {
+ if (locktype != isc_rwlocktype_write) {
+ NODE_UNLOCK(lock, locktype);
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ locktype = isc_rwlocktype_write;
+ }
+ if (need_headerupdate(found, search->now))
+ update_header(search->rbtdb, found,
+ search->now);
+ if (foundsig != NULL &&
+ need_headerupdate(foundsig, search->now)) {
+ update_header(search->rbtdb, foundsig,
+ search->now);
+ }
+ }
}
node_exit:
@@ -3286,7 +4240,7 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
header != NULL;
header = header_next) {
header_next = header->next;
- if (header->ttl <= now) {
+ if (header->rdh_ttl <= now) {
/*
* This rdataset is stale. If no one else is
* using the node, we can clean it up right
@@ -3294,7 +4248,7 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
* node as dirty, so it will get cleaned up
* later.
*/
- if ((header->ttl <= now - RBTDB_VIRTUAL) &&
+ if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -3308,13 +4262,16 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
isc_mem_t *m;
m = search->rbtdb->common.mctx;
- clean_stale_headers(m, header);
+ clean_stale_headers(
+ search->rbtdb,
+ m, header);
if (header_prev != NULL)
header_prev->next =
header->next;
else
node->data = header->next;
- free_rdataset(m, header);
+ free_rdataset(search->rbtdb, m,
+ header);
} else {
header->attributes |=
RDATASET_ATTR_STALE;
@@ -3377,6 +4334,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
rdatasetheader_t *header, *header_prev, *header_next;
rdatasetheader_t *found, *nsheader;
rdatasetheader_t *foundsig, *nssig, *cnamesig;
+ rdatasetheader_t *update, *updatesig;
rbtdb_rdatatype_t sigtype, negtype;
UNUSED(version);
@@ -3399,6 +4357,8 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
dns_fixedname_init(&search.zonecut_name);
dns_rbtnodechain_init(&search.chain, search.rbtdb->common.mctx);
search.now = now;
+ update = NULL;
+ updatesig = NULL;
RWLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);
@@ -3462,14 +4422,14 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
header_prev = NULL;
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
- if (header->ttl <= now) {
+ if (header->rdh_ttl <= now) {
/*
* This rdataset is stale. If no one else is using the
* node, we can clean it up right now, otherwise we
* mark it as stale, and the node as dirty, so it will
* get cleaned up later.
*/
- if ((header->ttl <= now - RBTDB_VIRTUAL) &&
+ if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -3482,13 +4442,15 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
isc_mem_t *mctx;
mctx = search.rbtdb->common.mctx;
- clean_stale_headers(mctx, header);
+ clean_stale_headers(search.rbtdb, mctx,
+ header);
if (header_prev != NULL)
header_prev->next =
header->next;
else
node->data = header->next;
- free_rdataset(mctx, header);
+ free_rdataset(search.rbtdb, mctx,
+ header);
} else {
header->attributes |=
RDATASET_ATTR_STALE;
@@ -3595,13 +4557,19 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
if (nsheader != NULL) {
if (nodep != NULL) {
new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
*nodep = node;
}
bind_rdataset(search.rbtdb, node, nsheader, search.now,
rdataset);
- if (nssig != NULL)
+ if (need_headerupdate(nsheader, search.now))
+ update = nsheader;
+ if (nssig != NULL) {
bind_rdataset(search.rbtdb, node, nssig,
search.now, sigrdataset);
+ if (need_headerupdate(nssig, search.now))
+ updatesig = nssig;
+ }
result = DNS_R_DELEGATION;
goto node_exit;
}
@@ -3619,6 +4587,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
if (nodep != NULL) {
new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
*nodep = node;
}
@@ -3650,12 +4619,28 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
result == DNS_R_NCACHENXRRSET) {
bind_rdataset(search.rbtdb, node, found, search.now,
rdataset);
- if (foundsig != NULL)
+ if (need_headerupdate(found, search.now))
+ update = found;
+ if (foundsig != NULL) {
bind_rdataset(search.rbtdb, node, foundsig, search.now,
sigrdataset);
+ if (need_headerupdate(foundsig, search.now))
+ updatesig = foundsig;
+ }
}
node_exit:
+ if ((update != NULL || updatesig != NULL) &&
+ locktype != isc_rwlocktype_write) {
+ NODE_UNLOCK(lock, locktype);
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ locktype = isc_rwlocktype_write;
+ }
+ if (update != NULL && need_headerupdate(update, search.now))
+ update_header(search.rbtdb, update, search.now);
+ if (updatesig != NULL && need_headerupdate(updatesig, search.now))
+ update_header(search.rbtdb, updatesig, search.now);
+
NODE_UNLOCK(lock, locktype);
tree_exit:
@@ -3671,7 +4656,8 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
NODE_LOCK(lock, isc_rwlocktype_read);
decrement_reference(search.rbtdb, node, 0,
- isc_rwlocktype_read, isc_rwlocktype_none);
+ isc_rwlocktype_read, isc_rwlocktype_none,
+ ISC_FALSE);
NODE_UNLOCK(lock, isc_rwlocktype_read);
}
@@ -3745,14 +4731,14 @@ cache_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
header_prev = NULL;
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
- if (header->ttl <= now) {
+ if (header->rdh_ttl <= now) {
/*
* This rdataset is stale. If no one else is using the
* node, we can clean it up right now, otherwise we
* mark it as stale, and the node as dirty, so it will
* get cleaned up later.
*/
- if ((header->ttl <= now - RBTDB_VIRTUAL) &&
+ if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -3765,13 +4751,15 @@ cache_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
isc_mem_t *mctx;
mctx = search.rbtdb->common.mctx;
- clean_stale_headers(mctx, header);
+ clean_stale_headers(search.rbtdb, mctx,
+ header);
if (header_prev != NULL)
header_prev->next =
header->next;
else
node->data = header->next;
- free_rdataset(mctx, header);
+ free_rdataset(search.rbtdb, mctx,
+ header);
} else {
header->attributes |=
RDATASET_ATTR_STALE;
@@ -3814,6 +4802,7 @@ cache_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
if (nodep != NULL) {
new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
*nodep = node;
}
@@ -3822,6 +4811,21 @@ cache_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
bind_rdataset(search.rbtdb, node, foundsig, search.now,
sigrdataset);
+ if (need_headerupdate(found, search.now) ||
+ (foundsig != NULL && need_headerupdate(foundsig, search.now))) {
+ if (locktype != isc_rwlocktype_write) {
+ NODE_UNLOCK(lock, locktype);
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ locktype = isc_rwlocktype_write;
+ }
+ if (need_headerupdate(found, search.now))
+ update_header(search.rbtdb, found, search.now);
+ if (foundsig != NULL &&
+ need_headerupdate(foundsig, search.now)) {
+ update_header(search.rbtdb, foundsig, search.now);
+ }
+ }
+
NODE_UNLOCK(lock, locktype);
tree_exit:
@@ -3871,7 +4875,7 @@ detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
NODE_LOCK(&nodelock->lock, isc_rwlocktype_read);
if (decrement_reference(rbtdb, node, 0, isc_rwlocktype_read,
- isc_rwlocktype_none)) {
+ isc_rwlocktype_none, ISC_FALSE)) {
if (isc_refcount_current(&nodelock->references) == 0 &&
nodelock->exiting) {
inactive = ISC_TRUE;
@@ -3938,8 +4942,8 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
/*
* Note that 'log' can be true IFF rbtdb->overmem is also true.
- * rbtdb->ovemem can currently only be true for cache databases
- * -- hence all of the "overmem cache" log strings.
+ * rbtdb->overmem can currently only be true for cache
+ * databases -- hence all of the "overmem cache" log strings.
*/
log = ISC_TF(isc_log_wouldlog(dns_lctx, level));
if (log)
@@ -3959,7 +4963,7 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
isc_rwlocktype_write);
for (header = rbtnode->data; header != NULL; header = header->next)
- if (header->ttl <= now - RBTDB_VIRTUAL) {
+ if (header->rdh_ttl <= now - RBTDB_VIRTUAL) {
/*
* We don't check if refcurrent(rbtnode) == 0 and try
* to free like we do in cache_find(), because
@@ -3974,7 +4978,7 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
printname);
} else if (force_expire) {
if (! RETAIN(header)) {
- header->ttl = 0;
+ set_ttl(rbtdb, header, 0);
header->attributes |= RDATASET_ATTR_STALE;
rbtnode->dirty = 1;
} else if (log) {
@@ -3997,9 +5001,8 @@ static void
overmem(dns_db_t *db, isc_boolean_t overmem) {
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
- if (IS_CACHE(rbtdb)) {
+ if (IS_CACHE(rbtdb))
rbtdb->overmem = overmem;
- }
}
static void
@@ -4030,11 +5033,13 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
first = ISC_FALSE;
fprintf(out,
"\tserial = %lu, ttl = %u, "
- "trust = %u, attributes = %u\n",
+ "trust = %u, attributes = %u, "
+ "resign = %u\n",
(unsigned long)current->serial,
- current->ttl,
+ current->rdh_ttl,
current->trust,
- current->attributes);
+ current->attributes,
+ current->resign);
current = current->down;
} while (current != NULL);
}
@@ -4046,8 +5051,7 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
}
static isc_result_t
-createiterator(dns_db_t *db, isc_boolean_t relative_names,
- dns_dbiterator_t **iteratorp)
+createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
{
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
rbtdb_dbiterator_t *rbtdbiter;
@@ -4061,7 +5065,8 @@ createiterator(dns_db_t *db, isc_boolean_t relative_names,
rbtdbiter->common.methods = &dbiterator_methods;
rbtdbiter->common.db = NULL;
dns_db_attach(db, &rbtdbiter->common.db);
- rbtdbiter->common.relative_names = relative_names;
+ rbtdbiter->common.relative_names =
+ ISC_TF((options & DNS_DB_RELATIVENAMES) != 0);
rbtdbiter->common.magic = DNS_DBITERATOR_MAGIC;
rbtdbiter->common.cleaning = ISC_FALSE;
rbtdbiter->paused = ISC_TRUE;
@@ -4071,8 +5076,15 @@ createiterator(dns_db_t *db, isc_boolean_t relative_names,
dns_fixedname_init(&rbtdbiter->origin);
rbtdbiter->node = NULL;
rbtdbiter->delete = 0;
+ rbtdbiter->nsec3only = ISC_TF((options & DNS_DB_NSEC3ONLY) != 0);
+ rbtdbiter->nonsec3 = ISC_TF((options & DNS_DB_NONSEC3) != 0);
memset(rbtdbiter->deletions, 0, sizeof(rbtdbiter->deletions));
dns_rbtnodechain_init(&rbtdbiter->chain, db->mctx);
+ dns_rbtnodechain_init(&rbtdbiter->nsec3chain, db->mctx);
+ if (rbtdbiter->nsec3only)
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ else
+ rbtdbiter->current = &rbtdbiter->chain;
*iteratorp = (dns_dbiterator_t *)rbtdbiter;
@@ -4204,8 +5216,8 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
for (header = rbtnode->data; header != NULL; header = header_next) {
header_next = header->next;
- if (header->ttl <= now) {
- if ((header->ttl <= now - RBTDB_VIRTUAL) &&
+ if (header->rdh_ttl <= now) {
+ if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
/*
@@ -4355,19 +5367,15 @@ cname_and_other_data(dns_rbtnode_t *node, rbtdb_serial_t serial) {
* Look for active extant "other data".
*
* "Other data" is any rdataset whose type is not
- * KEY, RRSIG KEY, NSEC, RRSIG NSEC or RRSIG CNAME.
+ * KEY, NSEC, SIG or RRSIG.
*/
rdtype = RBTDB_RDATATYPE_BASE(header->type);
- if (rdtype == dns_rdatatype_rrsig ||
- rdtype == dns_rdatatype_sig)
- rdtype = RBTDB_RDATATYPE_EXT(header->type);
- if (rdtype != dns_rdatatype_nsec &&
- rdtype != dns_rdatatype_key &&
- rdtype != dns_rdatatype_cname) {
+ if (rdtype != dns_rdatatype_key &&
+ rdtype != dns_rdatatype_sig &&
+ rdtype != dns_rdatatype_nsec &&
+ rdtype != dns_rdatatype_rrsig) {
/*
- * We've found a type that isn't
- * NSEC, KEY, CNAME, or one of their
- * signatures. Is it active and extant?
+ * Is it active and extant?
*/
do {
if (header->serial <= serial &&
@@ -4395,6 +5403,16 @@ cname_and_other_data(dns_rbtnode_t *node, rbtdb_serial_t serial) {
}
static isc_result_t
+resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader) {
+ isc_result_t result;
+
+ INSIST(newheader->heap_index == 0);
+ INSIST(!ISC_LINK_LINKED(newheader, lru_link));
+ result = isc_heap_insert(rbtdb->heaps[idx], newheader);
+ return (result);
+}
+
+static isc_result_t
add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading,
dns_rdataset_t *addedrdataset, isc_stdtime_t now)
@@ -4409,6 +5427,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
dns_rdatatype_t rdtype, covers;
rbtdb_rdatatype_t negtype;
dns_trust_t trust;
+ int idx;
/*
* Add an rdatasetheader_t to a node.
@@ -4437,7 +5456,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
*/
changed = add_changed(rbtdb, rbtversion, rbtnode);
if (changed == NULL) {
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
return (ISC_R_NOMEMORY);
}
}
@@ -4466,7 +5485,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
for (topheader = rbtnode->data;
topheader != NULL;
topheader = topheader->next) {
- topheader->ttl = 0;
+ set_ttl(rbtdb, topheader, 0);
topheader->attributes |=
RDATASET_ATTR_STALE;
}
@@ -4489,7 +5508,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
break;
}
if (topheader != NULL && EXISTS(topheader) &&
- topheader->ttl > now) {
+ topheader->rdh_ttl > now) {
/*
* Found one.
*/
@@ -4498,8 +5517,8 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* The NXDOMAIN/NODATA(QTYPE=ANY)
* is more trusted.
*/
-
- free_rdataset(rbtdb->common.mctx,
+ free_rdataset(rbtdb,
+ rbtdb->common.mctx,
newheader);
if (addedrdataset != NULL)
bind_rdataset(rbtdb, rbtnode,
@@ -4511,7 +5530,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* The new rdataset is better. Expire the
* NXDOMAIN/NODATA(QTYPE=ANY).
*/
- topheader->ttl = 0;
+ set_ttl(rbtdb, topheader, 0);
topheader->attributes |= RDATASET_ATTR_STALE;
rbtnode->dirty = 1;
topheader = NULL;
@@ -4546,7 +5565,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* Deleting an already non-existent rdataset has no effect.
*/
if (header_nx && newheader_nx) {
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
return (DNS_R_UNCHANGED);
}
@@ -4555,8 +5574,8 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* has no effect, provided that the cache data isn't stale.
*/
if (rbtversion == NULL && trust < header->trust &&
- (header->ttl > now || header_nx)) {
- free_rdataset(rbtdb->common.mctx, newheader);
+ (header->rdh_ttl > now || header_nx)) {
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
if (addedrdataset != NULL)
bind_rdataset(rbtdb, rbtnode, header, now,
addedrdataset);
@@ -4582,9 +5601,9 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
if ((options & DNS_DBADD_EXACT) != 0)
flags |= DNS_RDATASLAB_EXACT;
if ((options & DNS_DBADD_EXACTTTL) != 0 &&
- newheader->ttl != header->ttl)
+ newheader->rdh_ttl != header->rdh_ttl)
result = DNS_R_NOTEXACT;
- else if (newheader->ttl != header->ttl)
+ else if (newheader->rdh_ttl != header->rdh_ttl)
flags |= DNS_RDATASLAB_FORCE;
if (result == ISC_R_SUCCESS)
result = dns_rdataslab_merge(
@@ -4604,10 +5623,16 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* alone. It will get cleaned up when
* clean_zone_node() runs.
*/
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx,
+ newheader);
newheader = (rdatasetheader_t *)merged;
+ if (loading && RESIGN(newheader) &&
+ RESIGN(header) &&
+ header->resign < newheader->resign)
+ newheader->resign = header->resign;
} else {
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx,
+ newheader);
return (result);
}
}
@@ -4618,7 +5643,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* Don't lower trust of existing record if the
* update is forced.
*/
- if (IS_CACHE(rbtdb) && header->ttl > now &&
+ if (IS_CACHE(rbtdb) && header->rdh_ttl > now &&
header->type == dns_rdatatype_ns &&
!header_nx && !newheader_nx &&
header->trust >= newheader->trust &&
@@ -4631,20 +5656,25 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* Honour the new ttl if it is less than the
* older one.
*/
- if (header->ttl > newheader->ttl)
- header->ttl = newheader->ttl;
+ if (header->rdh_ttl > newheader->rdh_ttl)
+ set_ttl(rbtdb, header, newheader->rdh_ttl);
if (header->noqname == NULL &&
newheader->noqname != NULL) {
header->noqname = newheader->noqname;
newheader->noqname = NULL;
}
- free_rdataset(rbtdb->common.mctx, newheader);
+ if (header->closest == NULL &&
+ newheader->closest != NULL) {
+ header->closest = newheader->closest;
+ newheader->closest = NULL;
+ }
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
if (addedrdataset != NULL)
bind_rdataset(rbtdb, rbtnode, header, now,
addedrdataset);
return (ISC_R_SUCCESS);
}
- if (IS_CACHE(rbtdb) && header->ttl > now &&
+ if (IS_CACHE(rbtdb) && header->rdh_ttl > now &&
(header->type == dns_rdatatype_a ||
header->type == dns_rdatatype_aaaa) &&
!header_nx && !newheader_nx &&
@@ -4656,14 +5686,19 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* Honour the new ttl if it is less than the
* older one.
*/
- if (header->ttl > newheader->ttl)
- header->ttl = newheader->ttl;
+ if (header->rdh_ttl > newheader->rdh_ttl)
+ set_ttl(rbtdb, header, newheader->rdh_ttl);
if (header->noqname == NULL &&
newheader->noqname != NULL) {
header->noqname = newheader->noqname;
newheader->noqname = NULL;
}
- free_rdataset(rbtdb->common.mctx, newheader);
+ if (header->closest == NULL &&
+ newheader->closest != NULL) {
+ header->closest = newheader->closest;
+ newheader->closest = NULL;
+ }
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
if (addedrdataset != NULL)
bind_rdataset(rbtdb, rbtnode, header, now,
addedrdataset);
@@ -4684,7 +5719,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* loading, we MUST clean up 'header' now.
*/
newheader->down = NULL;
- free_rdataset(rbtdb->common.mctx, header);
+ free_rdataset(rbtdb, rbtdb->common.mctx, header);
} else {
newheader->down = topheader;
topheader->next = newheader;
@@ -4692,9 +5727,23 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
if (changed != NULL)
changed->dirty = ISC_TRUE;
if (rbtversion == NULL) {
- header->ttl = 0;
+ set_ttl(rbtdb, header, 0);
header->attributes |= RDATASET_ATTR_STALE;
}
+ idx = newheader->node->locknum;
+ if (IS_CACHE(rbtdb)) {
+ ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
+ newheader, lru_link);
+ /*
+ * XXXMLG We don't check the return value
+ * here. If it fails, we will not do TTL
+ * based expiry on this node. However, we
+ * will do it on the LRU side, so memory
+ * will not leak... for long.
+ */
+ isc_heap_insert(rbtdb->heaps[idx], newheader);
+ } else if (RESIGN(newheader))
+ resign_insert(rbtdb, idx, newheader);
}
} else {
/*
@@ -4706,7 +5755,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* If we're trying to delete the type, don't bother.
*/
if (newheader_nx) {
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
return (DNS_R_UNCHANGED);
}
@@ -4740,6 +5789,14 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
newheader->down = NULL;
rbtnode->data = newheader;
}
+ idx = newheader->node->locknum;
+ if (IS_CACHE(rbtdb)) {
+ ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
+ newheader, lru_link);
+ isc_heap_insert(rbtdb->heaps[idx], newheader);
+ } else if (RESIGN(newheader)) {
+ resign_insert(rbtdb, idx, newheader);
+ }
}
/*
@@ -4778,15 +5835,15 @@ addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
struct noqname *noqname;
isc_mem_t *mctx = rbtdb->common.mctx;
dns_name_t name;
- dns_rdataset_t nsec, nsecsig;
+ dns_rdataset_t neg, negsig;
isc_result_t result;
isc_region_t r;
dns_name_init(&name, NULL);
- dns_rdataset_init(&nsec);
- dns_rdataset_init(&nsecsig);
+ dns_rdataset_init(&neg);
+ dns_rdataset_init(&negsig);
- result = dns_rdataset_getnoqname(rdataset, &name, &nsec, &nsecsig);
+ result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
noqname = isc_mem_get(mctx, sizeof(*noqname));
@@ -4795,31 +5852,84 @@ addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
goto cleanup;
}
dns_name_init(&noqname->name, NULL);
- noqname->nsec = NULL;
- noqname->nsecsig = NULL;
+ noqname->neg = NULL;
+ noqname->negsig = NULL;
+ noqname->type = neg.type;
result = dns_name_dup(&name, mctx, &noqname->name);
if (result != ISC_R_SUCCESS)
goto cleanup;
- result = dns_rdataslab_fromrdataset(&nsec, mctx, &r, 0);
+ result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
- noqname->nsec = r.base;
- result = dns_rdataslab_fromrdataset(&nsecsig, mctx, &r, 0);
+ noqname->neg = r.base;
+ result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
- noqname->nsecsig = r.base;
- dns_rdataset_disassociate(&nsec);
- dns_rdataset_disassociate(&nsecsig);
+ noqname->negsig = r.base;
+ dns_rdataset_disassociate(&neg);
+ dns_rdataset_disassociate(&negsig);
newheader->noqname = noqname;
return (ISC_R_SUCCESS);
cleanup:
- dns_rdataset_disassociate(&nsec);
- dns_rdataset_disassociate(&nsecsig);
+ dns_rdataset_disassociate(&neg);
+ dns_rdataset_disassociate(&negsig);
free_noqname(mctx, &noqname);
return(result);
}
+static inline isc_result_t
+addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
+ dns_rdataset_t *rdataset)
+{
+ struct noqname *closest;
+ isc_mem_t *mctx = rbtdb->common.mctx;
+ dns_name_t name;
+ dns_rdataset_t neg, negsig;
+ isc_result_t result;
+ isc_region_t r;
+
+ dns_name_init(&name, NULL);
+ dns_rdataset_init(&neg);
+ dns_rdataset_init(&negsig);
+
+ result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ closest = isc_mem_get(mctx, sizeof(*closest));
+ if (closest == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ dns_name_init(&closest->name, NULL);
+ closest->neg = NULL;
+ closest->negsig = NULL;
+ closest->type = neg.type;
+ result = dns_name_dup(&name, mctx, &closest->name);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ closest->neg = r.base;
+ result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ closest->negsig = r.base;
+ dns_rdataset_disassociate(&neg);
+ dns_rdataset_disassociate(&negsig);
+ newheader->closest = closest;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_rdataset_disassociate(&neg);
+ dns_rdataset_disassociate(&negsig);
+ free_noqname(mctx, &closest);
+ return(result);
+}
+
+static dns_dbmethods_t zone_methods;
+
static isc_result_t
addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
@@ -4830,11 +5940,21 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
rbtdb_version_t *rbtversion = version;
isc_region_t region;
rdatasetheader_t *newheader;
+ rdatasetheader_t *header;
isc_result_t result;
isc_boolean_t delegating;
+ isc_boolean_t tree_locked = ISC_FALSE;
REQUIRE(VALID_RBTDB(rbtdb));
+ if (rbtdb->common.methods == &zone_methods)
+ REQUIRE(((rbtnode->nsec3 &&
+ (rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->covers == dns_rdatatype_nsec3)) ||
+ (!rbtnode->nsec3 &&
+ rdataset->type != dns_rdatatype_nsec3 &&
+ rdataset->covers != dns_rdatatype_nsec3)));
+
if (rbtversion == NULL) {
if (now == 0)
isc_stdtime_get(&now);
@@ -4848,26 +5968,48 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
return (result);
newheader = (rdatasetheader_t *)region.base;
- newheader->ttl = rdataset->ttl + now;
+ init_rdataset(rbtdb, newheader);
+ set_ttl(rbtdb, newheader, rdataset->ttl + now);
newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
rdataset->covers);
newheader->attributes = 0;
newheader->noqname = NULL;
+ newheader->closest = NULL;
newheader->count = init_count++;
newheader->trust = rdataset->trust;
newheader->additional_auth = NULL;
newheader->additional_glue = NULL;
+ newheader->last_used = now;
+ newheader->node = rbtnode;
if (rbtversion != NULL) {
newheader->serial = rbtversion->serial;
now = 0;
+
+ if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
+ newheader->attributes |= RDATASET_ATTR_RESIGN;
+ newheader->resign = rdataset->resign;
+ } else
+ newheader->resign = 0;
} else {
newheader->serial = 1;
+ newheader->resign = 0;
if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
+ if ((rdataset->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
+ newheader->attributes |= RDATASET_ATTR_OPTOUT;
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
result = addnoqname(rbtdb, newheader, rdataset);
if (result != ISC_R_SUCCESS) {
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx,
+ newheader);
+ return (result);
+ }
+ }
+ if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
+ result = addclosest(rbtdb, newheader, rdataset);
+ if (result != ISC_R_SUCCESS) {
+ free_rdataset(rbtdb, rbtdb->common.mctx,
+ newheader);
return (result);
}
}
@@ -4876,18 +6018,54 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
/*
* If we're adding a delegation type (e.g. NS or DNAME for a zone,
* just DNAME for the cache), then we need to set the callback bit
- * on the node, and to do that we must be holding an exclusive lock
- * on the tree.
+ * on the node.
*/
- if (delegating_type(rbtdb, rbtnode, rdataset->type)) {
+ if (delegating_type(rbtdb, rbtnode, rdataset->type))
delegating = ISC_TRUE;
- RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
- } else
+ else
delegating = ISC_FALSE;
+ /*
+ * If we're adding a delegation type or the DB is a cache in an overmem
+ * state, hold an exclusive lock on the tree. In the latter case
+ * the lock does not necessarily have to be acquired but it will help
+ * purge stale entries more effectively.
+ */
+ if (delegating || (IS_CACHE(rbtdb) && rbtdb->overmem)) {
+ tree_locked = ISC_TRUE;
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ }
+
+ if (IS_CACHE(rbtdb) && rbtdb->overmem)
+ overmem_purge(rbtdb, rbtnode->locknum, now, tree_locked);
+
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
+ if (rbtdb->rrsetstats != NULL) {
+ newheader->attributes |= RDATASET_ATTR_STATCOUNT;
+ update_rrsetstats(rbtdb, newheader, ISC_TRUE);
+ }
+
+ if (IS_CACHE(rbtdb)) {
+ if (tree_locked)
+ cleanup_dead_nodes(rbtdb, rbtnode->locknum);
+
+ header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1);
+ if (header && header->rdh_ttl <= now - RBTDB_VIRTUAL)
+ expire_header(rbtdb, header, tree_locked);
+
+ /*
+ * If we've been holding a write lock on the tree just for
+ * cleaning, we can release it now. However, we still need the
+ * node lock.
+ */
+ if (tree_locked && !delegating) {
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ tree_locked = ISC_FALSE;
+ }
+ }
+
result = add(rbtdb, rbtnode, rbtversion, newheader, options, ISC_FALSE,
addedrdataset, now);
if (result == ISC_R_SUCCESS && delegating)
@@ -4896,15 +6074,15 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
- if (delegating)
+ if (tree_locked)
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
/*
* Update the zone's secure status. If version is non-NULL
- * this is defered until closeversion() is called.
+ * this is deferred until closeversion() is called.
*/
if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(rbtdb))
- rbtdb->secure = iszonesecure(db, rbtdb->origin_node);
+ iszonesecure(db, version, rbtdb->origin_node);
return (result);
}
@@ -4925,29 +6103,46 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
REQUIRE(VALID_RBTDB(rbtdb));
+ if (rbtdb->common.methods == &zone_methods)
+ REQUIRE(((rbtnode->nsec3 &&
+ (rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->covers == dns_rdatatype_nsec3)) ||
+ (!rbtnode->nsec3 &&
+ rdataset->type != dns_rdatatype_nsec3 &&
+ rdataset->covers != dns_rdatatype_nsec3)));
+
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
&region,
sizeof(rdatasetheader_t));
if (result != ISC_R_SUCCESS)
return (result);
newheader = (rdatasetheader_t *)region.base;
- newheader->ttl = rdataset->ttl;
+ init_rdataset(rbtdb, newheader);
+ set_ttl(rbtdb, newheader, rdataset->ttl);
newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
rdataset->covers);
newheader->attributes = 0;
newheader->serial = rbtversion->serial;
newheader->trust = 0;
newheader->noqname = NULL;
+ newheader->closest = NULL;
newheader->count = init_count++;
newheader->additional_auth = NULL;
newheader->additional_glue = NULL;
+ newheader->last_used = 0;
+ newheader->node = rbtnode;
+ if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
+ newheader->attributes |= RDATASET_ATTR_RESIGN;
+ newheader->resign = rdataset->resign;
+ } else
+ newheader->resign = 0;
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
changed = add_changed(rbtdb, rbtversion, rbtnode);
if (changed == NULL) {
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
return (ISC_R_NOMEMORY);
@@ -4975,7 +6170,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
result = ISC_R_SUCCESS;
if ((options & DNS_DBSUB_EXACT) != 0) {
flags |= DNS_RDATASLAB_EXACT;
- if (newheader->ttl != header->ttl)
+ if (newheader->rdh_ttl != header->rdh_ttl)
result = DNS_R_NOTEXACT;
}
if (result == ISC_R_SUCCESS)
@@ -4988,8 +6183,9 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
(dns_rdatatype_t)header->type,
flags, &subresult);
if (result == ISC_R_SUCCESS) {
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
newheader = (rdatasetheader_t *)subresult;
+ init_rdataset(rbtdb, newheader);
/*
* We have to set the serial since the rdataslab
* subtraction routine copies the reserved portion of
@@ -5008,24 +6204,27 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
* This subtraction would remove all of the rdata;
* add a nonexistent header instead.
*/
- free_rdataset(rbtdb->common.mctx, newheader);
- newheader = isc_mem_get(rbtdb->common.mctx,
- sizeof(*newheader));
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ newheader = new_rdataset(rbtdb, rbtdb->common.mctx);
if (newheader == NULL) {
result = ISC_R_NOMEMORY;
goto unlock;
}
- newheader->ttl = 0;
+ set_ttl(rbtdb, newheader, 0);
newheader->type = topheader->type;
newheader->attributes = RDATASET_ATTR_NONEXISTENT;
newheader->trust = 0;
newheader->serial = rbtversion->serial;
newheader->noqname = NULL;
+ newheader->closest = NULL;
newheader->count = 0;
newheader->additional_auth = NULL;
newheader->additional_glue = NULL;
+ newheader->node = rbtnode;
+ newheader->resign = 0;
+ newheader->last_used = 0;
} else {
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
goto unlock;
}
@@ -5048,7 +6247,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
* The rdataset doesn't exist, so we don't need to do anything
* to satisfy the deletion request.
*/
- free_rdataset(rbtdb->common.mctx, newheader);
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
if ((options & DNS_DBSUB_EXACT) != 0)
result = DNS_R_NOTEXACT;
else
@@ -5064,10 +6263,10 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
/*
* Update the zone's secure status. If version is non-NULL
- * this is defered until closeversion() is called.
+ * this is deferred until closeversion() is called.
*/
if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(rbtdb))
- rbtdb->secure = iszonesecure(db, rbtdb->origin_node);
+ iszonesecure(db, rbtdb->current_version, rbtdb->origin_node);
return (result);
}
@@ -5089,14 +6288,15 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
if (type == dns_rdatatype_rrsig && covers == 0)
return (ISC_R_NOTIMPLEMENTED);
- newheader = isc_mem_get(rbtdb->common.mctx, sizeof(*newheader));
+ newheader = new_rdataset(rbtdb, rbtdb->common.mctx);
if (newheader == NULL)
return (ISC_R_NOMEMORY);
- newheader->ttl = 0;
+ set_ttl(rbtdb, newheader, 0);
newheader->type = RBTDB_RDATATYPE_VALUE(type, covers);
newheader->attributes = RDATASET_ATTR_NONEXISTENT;
newheader->trust = 0;
newheader->noqname = NULL;
+ newheader->closest = NULL;
newheader->additional_auth = NULL;
newheader->additional_glue = NULL;
if (rbtversion != NULL)
@@ -5104,6 +6304,8 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
else
newheader->serial = 0;
newheader->count = 0;
+ newheader->last_used = 0;
+ newheader->node = rbtnode;
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
@@ -5116,10 +6318,10 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
/*
* Update the zone's secure status. If version is non-NULL
- * this is defered until closeversion() is called.
+ * this is deferred until closeversion() is called.
*/
if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(rbtdb))
- rbtdb->secure = iszonesecure(db, rbtdb->origin_node);
+ iszonesecure(db, rbtdb->current_version, rbtdb->origin_node);
return (result);
}
@@ -5147,7 +6349,9 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
!IS_CACHE(rbtdb) && !dns_name_equal(name, &rbtdb->common.origin))
return (DNS_R_NOTZONETOP);
- add_empty_wildcards(rbtdb, name);
+ if (rdataset->type != dns_rdatatype_nsec3 &&
+ rdataset->covers != dns_rdatatype_nsec3)
+ add_empty_wildcards(rbtdb, name);
if (dns_name_iswildcard(name)) {
/*
@@ -5155,13 +6359,27 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
*/
if (rdataset->type == dns_rdatatype_ns)
return (DNS_R_INVALIDNS);
+ /*
+ * NSEC3 record owners cannot legally be wild cards.
+ */
+ if (rdataset->type == dns_rdatatype_nsec3)
+ return (DNS_R_INVALIDNSEC3);
result = add_wildcard_magic(rbtdb, name);
if (result != ISC_R_SUCCESS)
return (result);
}
node = NULL;
- result = dns_rbt_addnode(rbtdb->tree, name, &node);
+ if (rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->covers == dns_rdatatype_nsec3) {
+ result = dns_rbt_addnode(rbtdb->nsec3, name, &node);
+ if (result == ISC_R_SUCCESS)
+ node->nsec3 = 1;
+ } else {
+ result = dns_rbt_addnode(rbtdb->tree, name, &node);
+ if (result == ISC_R_SUCCESS)
+ node->nsec3 = 0;
+ }
if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
return (result);
if (result != ISC_R_EXISTS) {
@@ -5182,16 +6400,26 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
if (result != ISC_R_SUCCESS)
return (result);
newheader = (rdatasetheader_t *)region.base;
- newheader->ttl = rdataset->ttl + loadctx->now; /* XXX overflow check */
+ init_rdataset(rbtdb, newheader);
+ set_ttl(rbtdb, newheader,
+ rdataset->ttl + loadctx->now); /* XXX overflow check */
newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
rdataset->covers);
newheader->attributes = 0;
newheader->trust = rdataset->trust;
newheader->serial = 1;
newheader->noqname = NULL;
+ newheader->closest = NULL;
newheader->count = init_count++;
newheader->additional_auth = NULL;
newheader->additional_glue = NULL;
+ newheader->last_used = 0;
+ newheader->node = node;
+ if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
+ newheader->attributes |= RDATASET_ATTR_RESIGN;
+ newheader->resign = rdataset->resign;
+ } else
+ newheader->resign = 0;
result = add(rbtdb, node, rbtdb->current_version, newheader,
DNS_DBADD_MERGE, ISC_TRUE, NULL, 0);
@@ -5262,7 +6490,7 @@ endload(dns_db_t *db, dns_dbload_t **dbloadp) {
* zone key, we consider the zone secure.
*/
if (! IS_CACHE(rbtdb))
- rbtdb->secure = iszonesecure(db, rbtdb->origin_node);
+ iszonesecure(db, rbtdb->current_version, rbtdb->origin_node);
*dbloadp = NULL;
@@ -5292,7 +6520,7 @@ delete_callback(void *data, void *arg) {
for (current = data; current != NULL; current = next) {
next = current->next;
- free_rdataset(rbtdb->common.mctx, current);
+ free_rdataset(rbtdb, rbtdb->common.mctx, current);
}
}
@@ -5306,12 +6534,28 @@ issecure(dns_db_t *db) {
REQUIRE(VALID_RBTDB(rbtdb));
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
- secure = rbtdb->secure;
+ secure = ISC_TF(rbtdb->current_version->secure == dns_db_secure);
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
return (secure);
}
+static isc_boolean_t
+isdnssec(dns_db_t *db) {
+ dns_rbtdb_t *rbtdb;
+ isc_boolean_t dnssec;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ dnssec = ISC_TF(rbtdb->current_version->secure != dns_db_insecure);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ return (dnssec);
+}
+
static unsigned int
nodecount(dns_db_t *db) {
dns_rbtdb_t *rbtdb;
@@ -5368,13 +6612,180 @@ getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
*nodep = rbtdb->origin_node;
} else {
- INSIST(!IS_CACHE(rbtdb));
+ INSIST(IS_CACHE(rbtdb));
result = ISC_R_NOTFOUND;
}
return (result);
}
+static isc_result_t
+getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash,
+ isc_uint8_t *flags, isc_uint16_t *iterations,
+ unsigned char *salt, size_t *salt_length)
+{
+ dns_rbtdb_t *rbtdb;
+ isc_result_t result = ISC_R_NOTFOUND;
+ rbtdb_version_t *rbtversion = version;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ if (rbtversion == NULL)
+ rbtversion = rbtdb->current_version;
+
+ if (rbtversion->havensec3) {
+ if (hash != NULL)
+ *hash = rbtversion->hash;
+ if (salt != NULL && salt_length != 0) {
+ REQUIRE(*salt_length > rbtversion->salt_length);
+ memcpy(salt, rbtversion->salt, rbtversion->salt_length);
+ }
+ if (salt_length != NULL)
+ *salt_length = rbtversion->salt_length;
+ if (iterations != NULL)
+ *iterations = rbtversion->iterations;
+ if (flags != NULL)
+ *flags = rbtversion->flags;
+ result = ISC_R_SUCCESS;
+ }
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+static isc_result_t
+setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ isc_stdtime_t oldresign;
+ isc_result_t result = ISC_R_SUCCESS;
+ rdatasetheader_t *header;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(!IS_CACHE(rbtdb));
+ REQUIRE(rdataset != NULL);
+
+ header = rdataset->private3;
+ header--;
+
+ NODE_LOCK(&rbtdb->node_locks[header->node->locknum].lock,
+ isc_rwlocktype_write);
+
+ oldresign = header->resign;
+ header->resign = resign;
+ if (header->heap_index != 0) {
+ INSIST(RESIGN(header));
+ if (resign == 0) {
+ isc_heap_delete(rbtdb->heaps[header->node->locknum],
+ header->heap_index);
+ header->heap_index = 0;
+ } else if (resign < oldresign)
+ isc_heap_increased(rbtdb->heaps[header->node->locknum],
+ header->heap_index);
+ else
+ isc_heap_decreased(rbtdb->heaps[header->node->locknum],
+ header->heap_index);
+ } else if (resign && header->heap_index == 0) {
+ header->attributes |= RDATASET_ATTR_RESIGN;
+ result = resign_insert(rbtdb, header->node->locknum, header);
+ }
+ NODE_UNLOCK(&rbtdb->node_locks[header->node->locknum].lock,
+ isc_rwlocktype_write);
+ return (result);
+}
+
+static isc_result_t
+getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
+ dns_name_t *foundname)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ rdatasetheader_t *header = NULL, *this;
+ unsigned int i;
+ isc_result_t result = ISC_R_NOTFOUND;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
+
+ for (i = 0; i < rbtdb->node_lock_count; i++) {
+ this = isc_heap_element(rbtdb->heaps[i], 1);
+ if (this == NULL)
+ continue;
+ if (header == NULL)
+ header = this;
+ else if (isc_serial_lt(this->resign, header->resign))
+ header = this;
+ }
+
+ if (header == NULL)
+ goto unlock;
+
+ NODE_LOCK(&rbtdb->node_locks[header->node->locknum].lock,
+ isc_rwlocktype_read);
+
+ bind_rdataset(rbtdb, header->node, header, 0, rdataset);
+
+ if (foundname != NULL)
+ dns_rbt_fullnamefromnode(header->node, foundname);
+
+ NODE_UNLOCK(&rbtdb->node_locks[header->node->locknum].lock,
+ isc_rwlocktype_read);
+
+ result = ISC_R_SUCCESS;
+
+ unlock:
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+static void
+resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
+{
+ rbtdb_version_t *rbtversion = (rbtdb_version_t *)version;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *node;
+ rdatasetheader_t *header;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(rdataset != NULL);
+ REQUIRE(rbtdb->future_version == rbtversion);
+ REQUIRE(rbtversion->writer);
+
+ node = rdataset->private2;
+ header = rdataset->private3;
+ header--;
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
+ NODE_LOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ /*
+ * Delete from heap and save to re-signed list so that it can
+ * be restored if we backout of this change.
+ */
+ new_reference(rbtdb, node);
+ isc_heap_delete(rbtdb->heaps[node->locknum], header->heap_index);
+ header->heap_index = 0;
+ ISC_LIST_APPEND(rbtversion->resigned_list, header, lru_link);
+
+ NODE_UNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
+}
+
+static dns_stats_t *
+getrrsetstats(dns_db_t *db) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(IS_CACHE(rbtdb)); /* current restriction */
+
+ return (rbtdb->rrsetstats);
+}
+
static dns_dbmethods_t zone_methods = {
attach,
detach,
@@ -5403,7 +6814,15 @@ static dns_dbmethods_t zone_methods = {
ispersistent,
overmem,
settask,
- getoriginnode
+ getoriginnode,
+ NULL,
+ getnsec3parameters,
+ findnsec3node,
+ setsigningtime,
+ getsigningtime,
+ resigned,
+ isdnssec,
+ NULL
};
static dns_dbmethods_t cache_methods = {
@@ -5434,7 +6853,15 @@ static dns_dbmethods_t cache_methods = {
ispersistent,
overmem,
settask,
- getoriginnode
+ getoriginnode,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ isdnssec,
+ getrrsetstats
};
isc_result_t
@@ -5451,6 +6878,7 @@ dns_rbtdb_create
isc_result_t result;
int i;
dns_name_t name;
+ isc_boolean_t (*sooner)(void *, void *);
/* Keep the compiler happy. */
UNUSED(argc);
@@ -5483,11 +6911,20 @@ dns_rbtdb_create
if (result != ISC_R_SUCCESS)
goto cleanup_lock;
+ /*
+ * Initialize node_lock_count in a generic way to support future
+ * extension which allows the user to specify this value on creation.
+ * Note that when specified for a cache DB it must be larger than 1
+ * as commented with the definition of DEFAULT_CACHE_NODE_LOCK_COUNT.
+ */
if (rbtdb->node_lock_count == 0) {
if (IS_CACHE(rbtdb))
rbtdb->node_lock_count = DEFAULT_CACHE_NODE_LOCK_COUNT;
else
rbtdb->node_lock_count = DEFAULT_NODE_LOCK_COUNT;
+ } else if (rbtdb->node_lock_count < 2 && IS_CACHE(rbtdb)) {
+ result = ISC_R_RANGE;
+ goto cleanup_tree_lock;
}
INSIST(rbtdb->node_lock_count < (1 << DNS_RBT_LOCKLENGTH));
rbtdb->node_locks = isc_mem_get(mctx, rbtdb->node_lock_count *
@@ -5497,6 +6934,53 @@ dns_rbtdb_create
goto cleanup_tree_lock;
}
+ rbtdb->rrsetstats = NULL;
+ if (IS_CACHE(rbtdb)) {
+ result = dns_rdatasetstats_create(mctx, &rbtdb->rrsetstats);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node_locks;
+ rbtdb->rdatasets = isc_mem_get(mctx, rbtdb->node_lock_count *
+ sizeof(rdatasetheaderlist_t));
+ if (rbtdb->rdatasets == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_rrsetstats;
+ }
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++)
+ ISC_LIST_INIT(rbtdb->rdatasets[i]);
+ } else
+ rbtdb->rdatasets = NULL;
+
+ /*
+ * Create the heaps.
+ */
+ rbtdb->heaps = isc_mem_get(mctx, rbtdb->node_lock_count *
+ sizeof(isc_heap_t *));
+ if (rbtdb->heaps == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_rdatasets;
+ }
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++)
+ rbtdb->heaps[i] = NULL;
+ sooner = IS_CACHE(rbtdb) ? ttl_sooner : resign_sooner;
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++) {
+ result = isc_heap_create(mctx, sooner, set_index, 0,
+ &rbtdb->heaps[i]);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_heaps;
+ }
+
+ /*
+ * Create deadnode lists.
+ */
+ rbtdb->deadnodes = isc_mem_get(mctx, rbtdb->node_lock_count *
+ sizeof(rbtnodelist_t));
+ if (rbtdb->deadnodes == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_heaps;
+ }
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++)
+ ISC_LIST_INIT(rbtdb->deadnodes[i]);
+
rbtdb->active = rbtdb->node_lock_count;
for (i = 0; i < (int)(rbtdb->node_lock_count); i++) {
@@ -5512,7 +6996,7 @@ dns_rbtdb_create
isc_refcount_decrement(&rbtdb->node_locks[i].references, NULL);
isc_refcount_destroy(&rbtdb->node_locks[i].references);
}
- goto cleanup_node_locks;
+ goto cleanup_deadnodes;
}
rbtdb->node_locks[i].exiting = ISC_FALSE;
}
@@ -5525,7 +7009,7 @@ dns_rbtdb_create
isc_mem_attach(mctx, &rbtdb->common.mctx);
/*
- * Must be initalized before free_rbtdb() is called.
+ * Must be initialized before free_rbtdb() is called.
*/
isc_ondestroy_init(&rbtdb->common.ondest);
@@ -5539,13 +7023,20 @@ dns_rbtdb_create
}
/*
- * Make the Red-Black Tree.
+ * Make the Red-Black Trees.
*/
result = dns_rbt_create(mctx, delete_callback, rbtdb, &rbtdb->tree);
if (result != ISC_R_SUCCESS) {
free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (result);
}
+
+ result = dns_rbt_create(mctx, delete_callback, rbtdb, &rbtdb->nsec3);
+ if (result != ISC_R_SUCCESS) {
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
+ return (result);
+ }
+
/*
* In order to set the node callback bit correctly in zone databases,
* we need to know if the node has the origin name of the zone.
@@ -5568,6 +7059,7 @@ dns_rbtdb_create
free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (result);
}
+ rbtdb->origin_node->nsec3 = 0;
/*
* We need to give the origin node the right locknum.
*/
@@ -5593,7 +7085,6 @@ dns_rbtdb_create
return (result);
}
rbtdb->attributes = 0;
- rbtdb->secure = ISC_FALSE;
rbtdb->overmem = ISC_FALSE;
rbtdb->task = NULL;
@@ -5610,6 +7101,14 @@ dns_rbtdb_create
free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (ISC_R_NOMEMORY);
}
+ rbtdb->current_version->secure = dns_db_insecure;
+ rbtdb->current_version->havensec3 = ISC_FALSE;
+ rbtdb->current_version->flags = 0;
+ rbtdb->current_version->iterations = 0;
+ rbtdb->current_version->hash = 0;
+ rbtdb->current_version->salt_length = 0;
+ memset(rbtdb->current_version->salt, 0,
+ sizeof(rbtdb->current_version->salt));
rbtdb->future_version = NULL;
ISC_LIST_INIT(rbtdb->open_versions);
/*
@@ -5625,6 +7124,27 @@ dns_rbtdb_create
return (ISC_R_SUCCESS);
+ cleanup_deadnodes:
+ isc_mem_put(mctx, rbtdb->deadnodes,
+ rbtdb->node_lock_count * sizeof(rbtnodelist_t));
+
+ cleanup_heaps:
+ if (rbtdb->heaps != NULL) {
+ for (i = 0 ; i < (int)rbtdb->node_lock_count ; i++)
+ if (rbtdb->heaps[i] != NULL)
+ isc_heap_destroy(&rbtdb->heaps[i]);
+ isc_mem_put(mctx, rbtdb->heaps,
+ rbtdb->node_lock_count * sizeof(isc_heap_t *));
+ }
+
+ cleanup_rdatasets:
+ if (rbtdb->rdatasets != NULL)
+ isc_mem_put(mctx, rbtdb->rdatasets, rbtdb->node_lock_count *
+ sizeof(rdatasetheaderlist_t));
+ cleanup_rrsetstats:
+ if (rbtdb->rrsetstats != NULL)
+ dns_stats_detach(&rbtdb->rrsetstats);
+
cleanup_node_locks:
isc_mem_put(mctx, rbtdb->node_locks,
rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));
@@ -5655,7 +7175,7 @@ rdataset_disassociate(dns_rdataset_t *rdataset) {
static isc_result_t
rdataset_first(dns_rdataset_t *rdataset) {
- unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
unsigned int count;
count = raw[0] * 256 + raw[1];
@@ -5691,7 +7211,7 @@ static isc_result_t
rdataset_next(dns_rdataset_t *rdataset) {
unsigned int count;
unsigned int length;
- unsigned char *raw; /* RDATASLAB */
+ unsigned char *raw; /* RDATASLAB */
count = rdataset->privateuint4;
if (count == 0)
@@ -5710,9 +7230,9 @@ rdataset_next(dns_rdataset_t *rdataset) {
raw += length;
#if DNS_RDATASET_FIXED
}
- rdataset->private5 = raw + 4; /* length(2) + order(2) */
+ rdataset->private5 = raw + 4; /* length(2) + order(2) */
#else
- rdataset->private5 = raw + 2; /* length(2) */
+ rdataset->private5 = raw + 2; /* length(2) */
#endif
return (ISC_R_SUCCESS);
@@ -5720,11 +7240,13 @@ rdataset_next(dns_rdataset_t *rdataset) {
static void
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
- unsigned char *raw = rdataset->private5; /* RDATASLAB */
+ unsigned char *raw = rdataset->private5; /* RDATASLAB */
#if DNS_RDATASET_FIXED
unsigned int offset;
#endif
+ unsigned int length;
isc_region_t r;
+ unsigned int flags = 0;
REQUIRE(raw != NULL);
@@ -5740,15 +7262,22 @@ rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
raw += offset;
}
#endif
- r.length = raw[0] * 256 + raw[1];
-
+ length = raw[0] * 256 + raw[1];
#if DNS_RDATASET_FIXED
raw += 4;
#else
raw += 2;
#endif
+ if (rdataset->type == dns_rdatatype_rrsig) {
+ if (*raw & DNS_RDATASLAB_OFFLINE)
+ flags |= DNS_RDATA_OFFLINE;
+ length--;
+ raw++;
+ }
+ r.length = length;
r.base = raw;
dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
+ rdata->flags |= flags;
}
static void
@@ -5769,7 +7298,7 @@ rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
static unsigned int
rdataset_count(dns_rdataset_t *rdataset) {
- unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
unsigned int count;
count = raw[0] * 256 + raw[1];
@@ -5790,37 +7319,85 @@ rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
attachnode(db, node, &cloned_node);
nsec->methods = &rdataset_methods;
nsec->rdclass = db->rdclass;
- nsec->type = dns_rdatatype_nsec;
+ nsec->type = noqname->type;
nsec->covers = 0;
nsec->ttl = rdataset->ttl;
nsec->trust = rdataset->trust;
nsec->private1 = rdataset->private1;
nsec->private2 = rdataset->private2;
- nsec->private3 = noqname->nsec;
+ nsec->private3 = noqname->neg;
nsec->privateuint4 = 0;
nsec->private5 = NULL;
nsec->private6 = NULL;
+ nsec->private7 = NULL;
cloned_node = NULL;
attachnode(db, node, &cloned_node);
nsecsig->methods = &rdataset_methods;
nsecsig->rdclass = db->rdclass;
nsecsig->type = dns_rdatatype_rrsig;
- nsecsig->covers = dns_rdatatype_nsec;
+ nsecsig->covers = noqname->type;
nsecsig->ttl = rdataset->ttl;
nsecsig->trust = rdataset->trust;
nsecsig->private1 = rdataset->private1;
nsecsig->private2 = rdataset->private2;
- nsecsig->private3 = noqname->nsecsig;
+ nsecsig->private3 = noqname->negsig;
nsecsig->privateuint4 = 0;
nsecsig->private5 = NULL;
nsec->private6 = NULL;
+ nsec->private7 = NULL;
dns_name_clone(&noqname->name, name);
return (ISC_R_SUCCESS);
}
+static isc_result_t
+rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
+{
+ dns_db_t *db = rdataset->private1;
+ dns_dbnode_t *node = rdataset->private2;
+ dns_dbnode_t *cloned_node;
+ struct noqname *closest = rdataset->private7;
+
+ cloned_node = NULL;
+ attachnode(db, node, &cloned_node);
+ nsec->methods = &rdataset_methods;
+ nsec->rdclass = db->rdclass;
+ nsec->type = closest->type;
+ nsec->covers = 0;
+ nsec->ttl = rdataset->ttl;
+ nsec->trust = rdataset->trust;
+ nsec->private1 = rdataset->private1;
+ nsec->private2 = rdataset->private2;
+ nsec->private3 = closest->neg;
+ nsec->privateuint4 = 0;
+ nsec->private5 = NULL;
+ nsec->private6 = NULL;
+ nsec->private7 = NULL;
+
+ cloned_node = NULL;
+ attachnode(db, node, &cloned_node);
+ nsecsig->methods = &rdataset_methods;
+ nsecsig->rdclass = db->rdclass;
+ nsecsig->type = dns_rdatatype_rrsig;
+ nsecsig->covers = closest->type;
+ nsecsig->ttl = rdataset->ttl;
+ nsecsig->trust = rdataset->trust;
+ nsecsig->private1 = rdataset->private1;
+ nsecsig->private2 = rdataset->private2;
+ nsecsig->private3 = closest->negsig;
+ nsecsig->privateuint4 = 0;
+ nsecsig->private5 = NULL;
+ nsec->private6 = NULL;
+ nsec->private7 = NULL;
+
+ dns_name_clone(&closest->name, name);
+
+ return (ISC_R_SUCCESS);
+}
+
/*
* Rdataset Iterator Methods
*/
@@ -5871,13 +7448,13 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator) {
* record? Or is it too old in the cache?
*
* Note: unlike everywhere else, we
- * check for now > header->ttl instead
- * of now >= header->ttl. This allows
+ * check for now > header->rdh_ttl instead
+ * of now >= header->rdh_ttl. This allows
* ANY and RRSIG queries for 0 TTL
* rdatasets to work.
*/
if (NONEXISTENT(header) ||
- (now != 0 && now > header->ttl))
+ (now != 0 && now > header->rdh_ttl))
header = NULL;
break;
} else
@@ -5953,7 +7530,7 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) {
*/
if ((header->attributes &
RDATASET_ATTR_NONEXISTENT) != 0 ||
- (now != 0 && now > header->ttl))
+ (now != 0 && now > header->rdh_ttl))
header = NULL;
break;
} else
@@ -6009,9 +7586,7 @@ reference_iter_node(rbtdb_dbiterator_t *rbtdbiter) {
return;
INSIST(rbtdbiter->tree_locked != isc_rwlocktype_none);
- NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
- new_reference(rbtdb, node);
- NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+ reactivate_node(rbtdb, node, rbtdbiter->tree_locked);
}
static inline void
@@ -6026,7 +7601,7 @@ dereference_iter_node(rbtdb_dbiterator_t *rbtdbiter) {
lock = &rbtdb->node_locks[node->locknum].lock;
NODE_LOCK(lock, isc_rwlocktype_read);
decrement_reference(rbtdb, node, 0, isc_rwlocktype_read,
- rbtdbiter->tree_locked);
+ rbtdbiter->tree_locked, ISC_FALSE);
NODE_UNLOCK(lock, isc_rwlocktype_read);
rbtdbiter->node = NULL;
@@ -6067,7 +7642,7 @@ flush_deletions(rbtdb_dbiterator_t *rbtdbiter) {
NODE_LOCK(lock, isc_rwlocktype_read);
decrement_reference(rbtdb, node, 0,
isc_rwlocktype_read,
- rbtdbiter->tree_locked);
+ rbtdbiter->tree_locked, ISC_FALSE);
NODE_UNLOCK(lock, isc_rwlocktype_read);
}
@@ -6117,6 +7692,7 @@ dbiterator_destroy(dns_dbiterator_t **iteratorp) {
dns_db_detach(&rbtdbiter->common.db);
dns_rbtnodechain_reset(&rbtdbiter->chain);
+ dns_rbtnodechain_reset(&rbtdbiter->nsec3chain);
isc_mem_put(db->mctx, rbtdbiter, sizeof(*rbtdbiter));
dns_db_detach(&db);
@@ -6142,12 +7718,25 @@ dbiterator_first(dns_dbiterator_t *iterator) {
name = dns_fixedname_name(&rbtdbiter->name);
origin = dns_fixedname_name(&rbtdbiter->origin);
dns_rbtnodechain_reset(&rbtdbiter->chain);
+ dns_rbtnodechain_reset(&rbtdbiter->nsec3chain);
- result = dns_rbtnodechain_first(&rbtdbiter->chain, rbtdb->tree, name,
- origin);
-
+ if (rbtdbiter->nsec3only) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ result = dns_rbtnodechain_first(rbtdbiter->current,
+ rbtdb->nsec3, name, origin);
+ } else {
+ rbtdbiter->current = &rbtdbiter->chain;
+ result = dns_rbtnodechain_first(rbtdbiter->current,
+ rbtdb->tree, name, origin);
+ if (!rbtdbiter->nonsec3 && result == ISC_R_NOTFOUND) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ result = dns_rbtnodechain_first(rbtdbiter->current,
+ rbtdb->nsec3, name,
+ origin);
+ }
+ }
if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
- result = dns_rbtnodechain_current(&rbtdbiter->chain, NULL,
+ result = dns_rbtnodechain_current(rbtdbiter->current, NULL,
NULL, &rbtdbiter->node);
if (result == ISC_R_SUCCESS) {
rbtdbiter->new_origin = ISC_TRUE;
@@ -6182,11 +7771,21 @@ dbiterator_last(dns_dbiterator_t *iterator) {
name = dns_fixedname_name(&rbtdbiter->name);
origin = dns_fixedname_name(&rbtdbiter->origin);
dns_rbtnodechain_reset(&rbtdbiter->chain);
+ dns_rbtnodechain_reset(&rbtdbiter->nsec3chain);
- result = dns_rbtnodechain_last(&rbtdbiter->chain, rbtdb->tree, name,
- origin);
+ result = ISC_R_NOTFOUND;
+ if (rbtdbiter->nsec3only && !rbtdbiter->nonsec3) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ result = dns_rbtnodechain_last(rbtdbiter->current,
+ rbtdb->nsec3, name, origin);
+ }
+ if (!rbtdbiter->nsec3only && result == ISC_R_NOTFOUND) {
+ rbtdbiter->current = &rbtdbiter->chain;
+ result = dns_rbtnodechain_last(rbtdbiter->current, rbtdb->tree,
+ name, origin);
+ }
if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
- result = dns_rbtnodechain_current(&rbtdbiter->chain, NULL,
+ result = dns_rbtnodechain_current(rbtdbiter->current, NULL,
NULL, &rbtdbiter->node);
if (result == ISC_R_SUCCESS) {
rbtdbiter->new_origin = ISC_TRUE;
@@ -6210,6 +7809,7 @@ dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
dns_name_t *iname, *origin;
if (rbtdbiter->result != ISC_R_SUCCESS &&
+ rbtdbiter->result != ISC_R_NOTFOUND &&
rbtdbiter->result != ISC_R_NOMORE)
return (rbtdbiter->result);
@@ -6221,22 +7821,74 @@ dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
iname = dns_fixedname_name(&rbtdbiter->name);
origin = dns_fixedname_name(&rbtdbiter->origin);
dns_rbtnodechain_reset(&rbtdbiter->chain);
+ dns_rbtnodechain_reset(&rbtdbiter->nsec3chain);
+
+ if (rbtdbiter->nsec3only) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ result = dns_rbt_findnode(rbtdb->nsec3, name, NULL,
+ &rbtdbiter->node,
+ rbtdbiter->current,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ } else if (rbtdbiter->nonsec3) {
+ rbtdbiter->current = &rbtdbiter->chain;
+ result = dns_rbt_findnode(rbtdb->tree, name, NULL,
+ &rbtdbiter->node,
+ rbtdbiter->current,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ } else {
+ /*
+ * Stay on main chain if not found on either chain.
+ */
+ rbtdbiter->current = &rbtdbiter->chain;
+ result = dns_rbt_findnode(rbtdb->tree, name, NULL,
+ &rbtdbiter->node,
+ rbtdbiter->current,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ if (result == DNS_R_PARTIALMATCH) {
+ dns_rbtnode_t *node = NULL;
+ result = dns_rbt_findnode(rbtdb->nsec3, name, NULL,
+ &node, &rbtdbiter->nsec3chain,
+ DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS) {
+ rbtdbiter->node = node;
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ }
+ }
+ }
- result = dns_rbt_findnode(rbtdb->tree, name, NULL, &rbtdbiter->node,
- &rbtdbiter->chain, DNS_RBTFIND_EMPTYDATA,
- NULL, NULL);
+#if 1
if (result == ISC_R_SUCCESS) {
- result = dns_rbtnodechain_current(&rbtdbiter->chain, iname,
+ result = dns_rbtnodechain_current(rbtdbiter->current, iname,
origin, NULL);
if (result == ISC_R_SUCCESS) {
rbtdbiter->new_origin = ISC_TRUE;
reference_iter_node(rbtdbiter);
}
-
- } else if (result == DNS_R_PARTIALMATCH)
+ } else if (result == DNS_R_PARTIALMATCH) {
result = ISC_R_NOTFOUND;
+ rbtdbiter->node = NULL;
+ }
rbtdbiter->result = result;
+#else
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
+ isc_result_t tresult;
+ tresult = dns_rbtnodechain_current(rbtdbiter->current, iname,
+ origin, NULL);
+ if (tresult == ISC_R_SUCCESS) {
+ rbtdbiter->new_origin = ISC_TRUE;
+ reference_iter_node(rbtdbiter);
+ } else {
+ result = tresult;
+ rbtdbiter->node = NULL;
+ }
+ } else
+ rbtdbiter->node = NULL;
+
+ rbtdbiter->result = (result == DNS_R_PARTIALMATCH) ?
+ ISC_R_SUCCESS : result;
+#endif
return (result);
}
@@ -6246,6 +7898,7 @@ dbiterator_prev(dns_dbiterator_t *iterator) {
isc_result_t result;
rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
dns_name_t *name, *origin;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
REQUIRE(rbtdbiter->node != NULL);
@@ -6257,13 +7910,23 @@ dbiterator_prev(dns_dbiterator_t *iterator) {
name = dns_fixedname_name(&rbtdbiter->name);
origin = dns_fixedname_name(&rbtdbiter->origin);
- result = dns_rbtnodechain_prev(&rbtdbiter->chain, name, origin);
+ result = dns_rbtnodechain_prev(rbtdbiter->current, name, origin);
+ if (result == ISC_R_NOMORE && !rbtdbiter->nsec3only &&
+ !rbtdbiter->nonsec3 &&
+ &rbtdbiter->nsec3chain == rbtdbiter->current) {
+ rbtdbiter->current = &rbtdbiter->chain;
+ dns_rbtnodechain_reset(rbtdbiter->current);
+ result = dns_rbtnodechain_last(rbtdbiter->current, rbtdb->tree,
+ name, origin);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_NOMORE;
+ }
dereference_iter_node(rbtdbiter);
if (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
rbtdbiter->new_origin = ISC_TF(result == DNS_R_NEWORIGIN);
- result = dns_rbtnodechain_current(&rbtdbiter->chain, NULL,
+ result = dns_rbtnodechain_current(rbtdbiter->current, NULL,
NULL, &rbtdbiter->node);
}
@@ -6280,6 +7943,7 @@ dbiterator_next(dns_dbiterator_t *iterator) {
isc_result_t result;
rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
dns_name_t *name, *origin;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
REQUIRE(rbtdbiter->node != NULL);
@@ -6291,13 +7955,22 @@ dbiterator_next(dns_dbiterator_t *iterator) {
name = dns_fixedname_name(&rbtdbiter->name);
origin = dns_fixedname_name(&rbtdbiter->origin);
- result = dns_rbtnodechain_next(&rbtdbiter->chain, name, origin);
+ result = dns_rbtnodechain_next(rbtdbiter->current, name, origin);
+ if (result == ISC_R_NOMORE && !rbtdbiter->nsec3only &&
+ !rbtdbiter->nonsec3 && &rbtdbiter->chain == rbtdbiter->current) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ dns_rbtnodechain_reset(rbtdbiter->current);
+ result = dns_rbtnodechain_first(rbtdbiter->current,
+ rbtdb->nsec3, name, origin);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_NOMORE;
+ }
dereference_iter_node(rbtdbiter);
if (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
rbtdbiter->new_origin = ISC_TF(result == DNS_R_NEWORIGIN);
- result = dns_rbtnodechain_current(&rbtdbiter->chain, NULL,
+ result = dns_rbtnodechain_current(rbtdbiter->current, NULL,
NULL, &rbtdbiter->node);
}
if (result == ISC_R_SUCCESS)
@@ -6421,7 +8094,7 @@ rdataset_getadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
{
dns_rbtdb_t *rbtdb = rdataset->private1;
dns_rbtnode_t *rbtnode = rdataset->private2;
- unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
unsigned int current_count = rdataset->privateuint4;
unsigned int count;
rdatasetheader_t *header;
@@ -6567,7 +8240,7 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
{
dns_rbtdb_t *rbtdb = rdataset->private1;
dns_rbtnode_t *rbtnode = rdataset->private2;
- unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
unsigned int current_count = rdataset->privateuint4;
rdatasetheader_t *header;
unsigned int total_count, count;
@@ -6673,7 +8346,7 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
return (ISC_R_SUCCESS);
- fail:
+ fail:
if (newcbarg != NULL) {
if (newentry != NULL) {
acache_cancelentry(rbtdb->common.mctx, newentry,
@@ -6696,7 +8369,7 @@ rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset,
{
dns_rbtdb_t *rbtdb = rdataset->private1;
dns_rbtnode_t *rbtnode = rdataset->private2;
- unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
unsigned int current_count = rdataset->privateuint4;
rdatasetheader_t *header;
nodelock_t *nodelock;
@@ -6705,7 +8378,7 @@ rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset,
dns_acacheentry_t *entry;
acache_cbarg_t *cbarg;
- UNUSED(qtype); /* we do not use this value at least for now */
+ UNUSED(qtype); /* we do not use this value at least for now */
UNUSED(acache);
if (type == dns_rdatasetadditional_fromcache)
@@ -6752,9 +8425,159 @@ rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset,
NODE_UNLOCK(nodelock, isc_rwlocktype_write);
if (entry != NULL) {
- acache_cancelentry(rbtdb->common.mctx, entry, &cbarg);
+ if (cbarg != NULL)
+ acache_cancelentry(rbtdb->common.mctx, entry, &cbarg);
dns_acache_detachentry(&entry);
}
return (ISC_R_SUCCESS);
}
+
+/*%
+ * Routines for LRU-based cache management.
+ */
+
+/*%
+ * See if a given cache entry that is being reused needs to be updated
+ * in the LRU-list. From the LRU management point of view, this function is
+ * expected to return true for almost all cases. When used with threads,
+ * however, this may cause a non-negligible performance penalty because a
+ * writer lock will have to be acquired before updating the list.
+ * If DNS_RBTDB_LIMITLRUUPDATE is defined to be non 0 at compilation time, this
+ * function returns true if the entry has not been updated for some period of
+ * time. We differentiate the NS or glue address case and the others since
+ * experiments have shown that the former tends to be accessed relatively
+ * infrequently and the cost of cache miss is higher (e.g., a missing NS records
+ * may cause external queries at a higher level zone, involving more
+ * transactions).
+ *
+ * Caller must hold the node (read or write) lock.
+ */
+static inline isc_boolean_t
+need_headerupdate(rdatasetheader_t *header, isc_stdtime_t now) {
+ if ((header->attributes &
+ (RDATASET_ATTR_NONEXISTENT|RDATASET_ATTR_STALE)) != 0)
+ return (ISC_FALSE);
+
+#if DNS_RBTDB_LIMITLRUUPDATE
+ if (header->type == dns_rdatatype_ns ||
+ (header->trust == dns_trust_glue &&
+ (header->type == dns_rdatatype_a ||
+ header->type == dns_rdatatype_aaaa))) {
+ /*
+ * Glue records are updated if at least 60 seconds have passed
+ * since the previous update time.
+ */
+ return (header->last_used + 60 <= now);
+ }
+
+ /* Other records are updated if 5 minutes have passed. */
+ return (header->last_used + 300 <= now);
+#else
+ UNUSED(now);
+
+ return (ISC_TRUE);
+#endif
+}
+
+/*%
+ * Update the timestamp of a given cache entry and move it to the head
+ * of the corresponding LRU list.
+ *
+ * Caller must hold the node (write) lock.
+ *
+ * Note that the we do NOT touch the heap here, as the TTL has not changed.
+ */
+static void
+update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_stdtime_t now)
+{
+ INSIST(IS_CACHE(rbtdb));
+
+ /* To be checked: can we really assume this? XXXMLG */
+ INSIST(ISC_LINK_LINKED(header, lru_link));
+
+ ISC_LIST_UNLINK(rbtdb->rdatasets[header->node->locknum],
+ header, lru_link);
+ header->last_used = now;
+ ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum],
+ header, lru_link);
+}
+
+/*%
+ * Purge some expired and/or stale (i.e. unused for some period) cache entries
+ * under an overmem condition. To recover from this condition quickly, up to
+ * 2 entries will be purged. This process is triggered while adding a new
+ * entry, and we specifically avoid purging entries in the same LRU bucket as
+ * the one to which the new entry will belong. Otherwise, we might purge
+ * entries of the same name of different RR types while adding RRsets from a
+ * single response (consider the case where we're adding A and AAAA glue records
+ * of the same NS name).
+ */
+static void
+overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
+ isc_stdtime_t now, isc_boolean_t tree_locked)
+{
+ rdatasetheader_t *header, *header_prev;
+ unsigned int locknum;
+ int purgecount = 2;
+
+ for (locknum = (locknum_start + 1) % rbtdb->node_lock_count;
+ locknum != locknum_start && purgecount > 0;
+ locknum = (locknum + 1) % rbtdb->node_lock_count) {
+ NODE_LOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+
+ header = isc_heap_element(rbtdb->heaps[locknum], 1);
+ if (header && header->rdh_ttl <= now - RBTDB_VIRTUAL) {
+ expire_header(rbtdb, header, tree_locked);
+ purgecount--;
+ }
+
+ for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
+ header != NULL && purgecount > 0;
+ header = header_prev) {
+ header_prev = ISC_LIST_PREV(header, lru_link);
+ /*
+ * Unlink the entry at this point to avoid checking it
+ * again even if it's currently used someone else and
+ * cannot be purged at this moment. This entry won't be
+ * referenced any more (so unlinking is safe) since the
+ * TTL was reset to 0.
+ */
+ ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header,
+ lru_link);
+ expire_header(rbtdb, header, tree_locked);
+ purgecount--;
+ }
+
+ NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+ }
+}
+
+static void
+expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_boolean_t tree_locked)
+{
+ set_ttl(rbtdb, header, 0);
+ header->attributes |= RDATASET_ATTR_STALE;
+ header->node->dirty = 1;
+
+ /*
+ * Caller must hold the node (write) lock.
+ */
+
+ if (dns_rbtnode_refcurrent(header->node) == 0) {
+ /*
+ * If no one else is using the node, we can clean it up now.
+ * We first need to gain a new reference to the node to meet a
+ * requirement of decrement_reference().
+ */
+ new_reference(rbtdb, header->node);
+ decrement_reference(rbtdb, header->node, 0,
+ isc_rwlocktype_write,
+ tree_locked ? isc_rwlocktype_write :
+ isc_rwlocktype_none, ISC_FALSE);
+ }
+}
diff --git a/lib/dns/rbtdb.h b/lib/dns/rbtdb.h
index f9fb50b..b024d13 100644
--- a/lib/dns/rbtdb.h
+++ b/lib/dns/rbtdb.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.h,v 1.14.18.2 2005/04/29 00:16:02 marka Exp $ */
+/* $Id: rbtdb.h,v 1.18 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_RBTDB_H
#define DNS_RBTDB_H 1
diff --git a/lib/dns/rbtdb64.c b/lib/dns/rbtdb64.c
index 773fe91..5e325fa 100644
--- a/lib/dns/rbtdb64.c
+++ b/lib/dns/rbtdb64.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb64.c,v 1.7.18.2 2005/04/29 00:16:02 marka Exp $ */
+/* $Id: rbtdb64.c,v 1.11 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/rbtdb64.h b/lib/dns/rbtdb64.h
index e2de45c..fe11622 100644
--- a/lib/dns/rbtdb64.h
+++ b/lib/dns/rbtdb64.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb64.h,v 1.13.18.2 2005/04/29 00:16:02 marka Exp $ */
+/* $Id: rbtdb64.h,v 1.17 2007/06/19 23:47:16 tbox Exp $ */
#ifndef DNS_RBTDB64_H
#define DNS_RBTDB64_H 1
diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c
index f61aa35..58ade85 100644
--- a/lib/dns/rcode.c
+++ b/lib/dns/rcode.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rcode.c,v 1.2.18.2 2006/01/27 23:57:44 marka Exp $ */
+/* $Id: rcode.c,v 1.8 2008/09/25 04:02:38 tbox Exp $ */
#include <config.h>
#include <ctype.h>
@@ -66,7 +66,7 @@
#define ERCODENAMES \
/* extended rcodes */ \
{ dns_rcode_badvers, "BADVERS", 0}, \
- { 0, NULL, 0 }
+ { 0, NULL, 0 }
#define TSIGRCODENAMES \
/* extended rcodes */ \
@@ -96,8 +96,10 @@
{ DNS_KEYALG_RSAMD5, "RSA", 0 }, \
{ DNS_KEYALG_DH, "DH", 0 }, \
{ DNS_KEYALG_DSA, "DSA", 0 }, \
+ { DNS_KEYALG_NSEC3DSA, "NSEC3DSA", 0 }, \
{ DNS_KEYALG_ECC, "ECC", 0 }, \
{ DNS_KEYALG_RSASHA1, "RSASHA1", 0 }, \
+ { DNS_KEYALG_NSEC3RSASHA1, "NSEC3RSASHA1", 0 }, \
{ DNS_KEYALG_INDIRECT, "INDIRECT", 0 }, \
{ DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \
{ DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, \
@@ -114,6 +116,10 @@
{ 255, "ALL", 0 }, \
{ 0, NULL, 0}
+#define HASHALGNAMES \
+ { 1, "SHA-1", 0 }, \
+ { 0, NULL, 0 }
+
struct tbl {
unsigned int value;
const char *name;
@@ -125,6 +131,7 @@ static struct tbl tsigrcodes[] = { RCODENAMES TSIGRCODENAMES };
static struct tbl certs[] = { CERTNAMES };
static struct tbl secalgs[] = { SECALGNAMES };
static struct tbl secprotos[] = { SECPROTONAMES };
+static struct tbl hashalgs[] = { HASHALGNAMES };
static struct keyflag {
const char *name;
@@ -238,7 +245,7 @@ dns_mnemonic_fromtext(unsigned int *valuep, isc_textregion_t *source,
static isc_result_t
dns_mnemonic_totext(unsigned int value, isc_buffer_t *target,
- struct tbl *table)
+ struct tbl *table)
{
int i = 0;
char buf[sizeof("4294967296")];
@@ -271,7 +278,7 @@ dns_tsigrcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
RETERR(dns_mnemonic_fromtext(&value, source, tsigrcodes, 0xffff));
*rcodep = value;
return (ISC_R_SUCCESS);
-}
+}
isc_result_t
dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
@@ -318,6 +325,14 @@ dns_secproto_totext(dns_secproto_t secproto, isc_buffer_t *target) {
}
isc_result_t
+dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source) {
+ unsigned int value;
+ RETERR(dns_mnemonic_fromtext(&value, source, hashalgs, 0xff));
+ *hashalg = value;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source)
{
isc_result_t result;
diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c
index 5641777..ab9df8b 100644
--- a/lib/dns/rdata.c
+++ b/lib/dns/rdata.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdata.c,v 1.184.18.9 2006/07/21 02:05:57 marka Exp $ */
+/* $Id: rdata.c,v 1.199.50.2 2009/02/16 23:47:15 tbox Exp $ */
/*! \file */
@@ -111,7 +111,7 @@ typedef struct dns_rdata_textctx {
dns_name_t *origin; /*%< Current origin, or NULL. */
unsigned int flags; /*%< DNS_STYLEFLAG_* */
unsigned int width; /*%< Width of rdata column. */
- const char *linebreak; /*%< Line break string. */
+ const char *linebreak; /*%< Line break string. */
} dns_rdata_textctx_t;
static isc_result_t
@@ -162,6 +162,9 @@ uint16_fromregion(isc_region_t *region);
static isc_uint8_t
uint8_fromregion(isc_region_t *region);
+static isc_uint8_t
+uint8_consume_fromregion(isc_region_t *region);
+
static isc_result_t
mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
@@ -201,6 +204,9 @@ static void
warn_badmx(isc_token_t *token, isc_lex_t *lexer,
dns_rdatacallbacks_t *callbacks);
+static isc_uint16_t
+uint16_consume_fromregion(isc_region_t *region);
+
static inline int
getquad(const void *src, struct in_addr *dst,
isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks)
@@ -269,7 +275,7 @@ dns_rdata_init(dns_rdata_t *rdata) {
/* ISC_LIST_INIT(rdata->list); */
}
-#if 0
+#if 1
#define DNS_RDATA_INITIALIZED(rdata) \
((rdata)->data == NULL && (rdata)->length == 0 && \
(rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \
@@ -282,8 +288,9 @@ dns_rdata_init(dns_rdata_t *rdata) {
#define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE
#endif
#endif
+
#define DNS_RDATA_VALIDFLAGS(rdata) \
- (((rdata)->flags & ~DNS_RDATA_UPDATE) == 0)
+ (((rdata)->flags & ~(DNS_RDATA_UPDATE|DNS_RDATA_OFFLINE)) == 0)
void
dns_rdata_reset(dns_rdata_t *rdata) {
@@ -532,7 +539,7 @@ unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type,
result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong);
if (result != ISC_R_SUCCESS)
return (result);
-
+
result = isc_hex_tobuffer(lexer, buf,
(unsigned int)token.value.as_ulong);
if (result != ISC_R_SUCCESS)
@@ -728,7 +735,7 @@ dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target)
isc_result_t
dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin,
unsigned int flags, unsigned int width,
- char *linebreak, isc_buffer_t *target)
+ const char *linebreak, isc_buffer_t *target)
{
dns_rdata_textctx_t tctx;
@@ -901,7 +908,7 @@ dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
hash = ((a + n) * b) % 256;
/*
- * This switch block is inlined via #define, and will use "return"
+ * This switch block is inlined via \#define, and will use "return"
* to return a result to the caller if it is a valid (known)
* rdatatype name.
*/
@@ -1234,6 +1241,14 @@ uint32_fromregion(isc_region_t *region) {
}
static isc_uint16_t
+uint16_consume_fromregion(isc_region_t *region) {
+ isc_uint16_t r = uint16_fromregion(region);
+
+ isc_region_consume(region, 2);
+ return r;
+}
+
+static isc_uint16_t
uint16_fromregion(isc_region_t *region) {
REQUIRE(region->length >= 2);
@@ -1249,6 +1264,14 @@ uint8_fromregion(isc_region_t *region) {
return (region->base[0]);
}
+static isc_uint8_t
+uint8_consume_fromregion(isc_region_t *region) {
+ isc_uint8_t r = uint8_fromregion(region);
+
+ isc_region_consume(region, 1);
+ return r;
+}
+
static isc_result_t
mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
isc_region_t tr;
@@ -1504,16 +1527,16 @@ byte_btoa(int c, isc_buffer_t *target, struct state *state) {
/*
* Because some don't support u_long.
*/
- tmp = 32;
- tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
+ tmp = 32;
+ tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
}
if (tmpword < 0) {
- tmp = 64;
- tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
+ tmp = 64;
+ tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
}
if (tr.length < 5)
return (ISC_R_NOSPACE);
- tr.base[0] = atob_digits[(tmpword /
+ tr.base[0] = atob_digits[(tmpword /
(isc_int32_t)(85 * 85 * 85 * 85))
+ tmp];
tmpword %= (isc_int32_t)(85 * 85 * 85 * 85);
@@ -1596,7 +1619,7 @@ warn_badmx(isc_token_t *token, isc_lex_t *lexer,
if (lexer != NULL) {
file = isc_lex_getsourcename(lexer);
line = isc_lex_getsourceline(lexer);
- (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s",
+ (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s",
file, line, DNS_AS_STR(*token),
dns_result_totext(DNS_R_MXISADDRESS));
}
@@ -1609,12 +1632,12 @@ warn_badname(dns_name_t *name, isc_lex_t *lexer,
const char *file;
unsigned long line;
char namebuf[DNS_NAME_FORMATSIZE];
-
+
if (lexer != NULL) {
file = isc_lex_getsourcename(lexer);
line = isc_lex_getsourceline(lexer);
dns_name_format(name, namebuf, sizeof(namebuf));
- (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
+ (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
file, line, namebuf,
dns_result_totext(DNS_R_BADNAME));
}
diff --git a/lib/dns/rdata/any_255/tsig_250.c b/lib/dns/rdata/any_255/tsig_250.c
index 4fdadd3..3121f78 100644
--- a/lib/dns/rdata/any_255/tsig_250.c
+++ b/lib/dns/rdata/any_255/tsig_250.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tsig_250.c,v 1.59.18.2 2005/03/20 22:34:32 marka Exp $ */
+/* $Id: tsig_250.c,v 1.63 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 13:39:43 PST 2000 by gson */
diff --git a/lib/dns/rdata/any_255/tsig_250.h b/lib/dns/rdata/any_255/tsig_250.h
index b84a715..0c01667 100644
--- a/lib/dns/rdata/any_255/tsig_250.h
+++ b/lib/dns/rdata/any_255/tsig_250.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tsig_250.h,v 1.21.18.2 2005/04/29 00:16:29 marka Exp $ */
+/* $Id: tsig_250.h,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
#ifndef ANY_255_TSIG_250_H
#define ANY_255_TSIG_250_H 1
diff --git a/lib/dns/rdata/ch_3/a_1.c b/lib/dns/rdata/ch_3/a_1.c
index 6a9b70c..78d4ecd 100644
--- a/lib/dns/rdata/ch_3/a_1.c
+++ b/lib/dns/rdata/ch_3/a_1.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: a_1.c,v 1.2.2.3 2005/08/23 04:10:09 marka Exp $ */
+/* $Id: a_1.c,v 1.6 2007/06/19 23:47:17 tbox Exp $ */
/* by Bjorn.Victor@it.uu.se, 2005-05-07 */
/* Based on generic/soa_6.c and generic/mx_15.c */
diff --git a/lib/dns/rdata/ch_3/a_1.h b/lib/dns/rdata/ch_3/a_1.h
index 9f67977..a279d0e 100644
--- a/lib/dns/rdata/ch_3/a_1.h
+++ b/lib/dns/rdata/ch_3/a_1.h
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: a_1.h,v 1.2.2.2 2005/06/05 00:02:22 marka Exp $ */
+/* $Id: a_1.h,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
/* by Bjorn.Victor@it.uu.se, 2005-05-07 */
/* Based on generic/mx_15.h */
diff --git a/lib/dns/rdata/generic/afsdb_18.c b/lib/dns/rdata/generic/afsdb_18.c
index 24a63e6..2230efb 100644
--- a/lib/dns/rdata/generic/afsdb_18.c
+++ b/lib/dns/rdata/generic/afsdb_18.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: afsdb_18.c,v 1.43.18.2 2005/04/29 00:16:30 marka Exp $ */
+/* $Id: afsdb_18.c,v 1.47 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Wed Mar 15 14:59:00 PST 2000 by explorer */
diff --git a/lib/dns/rdata/generic/afsdb_18.h b/lib/dns/rdata/generic/afsdb_18.h
index 1532da1..ccccc11 100644
--- a/lib/dns/rdata/generic/afsdb_18.h
+++ b/lib/dns/rdata/generic/afsdb_18.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_AFSDB_18_H
#define GENERIC_AFSDB_18_H 1
-/* $Id: afsdb_18.h,v 1.16.18.2 2005/04/29 00:16:30 marka Exp $ */
+/* $Id: afsdb_18.h,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1183 */
diff --git a/lib/dns/rdata/generic/cert_37.c b/lib/dns/rdata/generic/cert_37.c
index c6ba3a8..2c45230 100644
--- a/lib/dns/rdata/generic/cert_37.c
+++ b/lib/dns/rdata/generic/cert_37.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cert_37.c,v 1.46.18.2 2005/04/29 00:16:30 marka Exp $ */
+/* $Id: cert_37.c,v 1.50 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Wed Mar 15 21:14:32 EST 2000 by tale */
diff --git a/lib/dns/rdata/generic/cert_37.h b/lib/dns/rdata/generic/cert_37.h
index 2af25b7..ddfaa4f 100644
--- a/lib/dns/rdata/generic/cert_37.h
+++ b/lib/dns/rdata/generic/cert_37.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cert_37.h,v 1.16.18.2 2005/04/29 00:16:31 marka Exp $ */
+/* $Id: cert_37.h,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
#ifndef GENERIC_CERT_37_H
#define GENERIC_CERT_37_H 1
diff --git a/lib/dns/rdata/generic/cname_5.c b/lib/dns/rdata/generic/cname_5.c
index 6ea1db1..28c3d60 100644
--- a/lib/dns/rdata/generic/cname_5.c
+++ b/lib/dns/rdata/generic/cname_5.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cname_5.c,v 1.45 2004/03/05 05:10:10 marka Exp $ */
+/* $Id: cname_5.c,v 1.47 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Wed Mar 15 16:48:45 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/cname_5.h b/lib/dns/rdata/generic/cname_5.h
index dc24383..516f8d3 100644
--- a/lib/dns/rdata/generic/cname_5.h
+++ b/lib/dns/rdata/generic/cname_5.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cname_5.h,v 1.24 2004/03/05 05:10:10 marka Exp $ */
+/* $Id: cname_5.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
#ifndef GENERIC_CNAME_5_H
#define GENERIC_CNAME_5_H 1
diff --git a/lib/dns/rdata/generic/dlv_32769.c b/lib/dns/rdata/generic/dlv_32769.c
index c0bb348..957f038 100644
--- a/lib/dns/rdata/generic/dlv_32769.c
+++ b/lib/dns/rdata/generic/dlv_32769.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dlv_32769.c,v 1.2.2.5 2007/08/28 07:20:06 tbox Exp $ */
+/* $Id: dlv_32769.c,v 1.6 2007/06/18 23:47:43 tbox Exp $ */
/* draft-ietf-dnsext-delegation-signer-05.txt */
diff --git a/lib/dns/rdata/generic/dlv_32769.h b/lib/dns/rdata/generic/dlv_32769.h
index bd03c73..2313c57 100644
--- a/lib/dns/rdata/generic/dlv_32769.h
+++ b/lib/dns/rdata/generic/dlv_32769.h
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dlv_32769.h,v 1.2.2.2 2006/02/19 06:50:47 marka Exp $ */
+/* $Id: dlv_32769.h,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
/* draft-ietf-dnsext-delegation-signer-05.txt */
#ifndef GENERIC_DLV_32769_H
diff --git a/lib/dns/rdata/generic/dname_39.c b/lib/dns/rdata/generic/dname_39.c
index ed3133c..c399f1e 100644
--- a/lib/dns/rdata/generic/dname_39.c
+++ b/lib/dns/rdata/generic/dname_39.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dname_39.c,v 1.36 2004/03/05 05:10:10 marka Exp $ */
+/* $Id: dname_39.c,v 1.38 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Wed Mar 15 16:52:38 PST 2000 by explorer */
diff --git a/lib/dns/rdata/generic/dname_39.h b/lib/dns/rdata/generic/dname_39.h
index 93ec709..f8aca27 100644
--- a/lib/dns/rdata/generic/dname_39.h
+++ b/lib/dns/rdata/generic/dname_39.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_DNAME_39_H
#define GENERIC_DNAME_39_H 1
-/* $Id: dname_39.h,v 1.17.18.2 2005/04/29 00:16:31 marka Exp $ */
+/* $Id: dname_39.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief per RFC2672 */
diff --git a/lib/dns/rdata/generic/dnskey_48.c b/lib/dns/rdata/generic/dnskey_48.c
index 5a4e453..2e11cba 100644
--- a/lib/dns/rdata/generic/dnskey_48.c
+++ b/lib/dns/rdata/generic/dnskey_48.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnskey_48.c,v 1.4.20.2 2005/04/29 00:16:31 marka Exp $ */
+/* $Id: dnskey_48.c,v 1.8 2007/06/19 23:47:17 tbox Exp $ */
/*
* Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
diff --git a/lib/dns/rdata/generic/dnskey_48.h b/lib/dns/rdata/generic/dnskey_48.h
index 9b3d262..ce88cd1 100644
--- a/lib/dns/rdata/generic/dnskey_48.h
+++ b/lib/dns/rdata/generic/dnskey_48.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_DNSKEY_48_H
#define GENERIC_DNSKEY_48_H 1
-/* $Id: dnskey_48.h,v 1.3.20.2 2005/04/29 00:16:32 marka Exp $ */
+/* $Id: dnskey_48.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief per RFC2535 */
diff --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c
index 212a56f..08e5d5f 100644
--- a/lib/dns/rdata/generic/ds_43.c
+++ b/lib/dns/rdata/generic/ds_43.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ds_43.c,v 1.7.18.5 2007/08/28 07:20:06 tbox Exp $ */
+/* $Id: ds_43.c,v 1.12 2007/06/18 23:47:43 tbox Exp $ */
/* draft-ietf-dnsext-delegation-signer-05.txt */
diff --git a/lib/dns/rdata/generic/ds_43.h b/lib/dns/rdata/generic/ds_43.h
index dae7bef..3a409a1 100644
--- a/lib/dns/rdata/generic/ds_43.h
+++ b/lib/dns/rdata/generic/ds_43.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ds_43.h,v 1.3.20.2 2005/04/29 00:16:32 marka Exp $ */
+/* $Id: ds_43.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
#ifndef GENERIC_DS_43_H
#define GENERIC_DS_43_H 1
diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c
index 9b37905..18effb5 100644
--- a/lib/dns/rdata/generic/gpos_27.c
+++ b/lib/dns/rdata/generic/gpos_27.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gpos_27.c,v 1.37.18.2 2005/04/29 00:16:32 marka Exp $ */
+/* $Id: gpos_27.c,v 1.41 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Wed Mar 15 16:48:45 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/gpos_27.h b/lib/dns/rdata/generic/gpos_27.h
index 4949bde..f5df4fa 100644
--- a/lib/dns/rdata/generic/gpos_27.h
+++ b/lib/dns/rdata/generic/gpos_27.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_GPOS_27_H
#define GENERIC_GPOS_27_H 1
-/* $Id: gpos_27.h,v 1.13.18.2 2005/04/29 00:16:32 marka Exp $ */
+/* $Id: gpos_27.h,v 1.17 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief per RFC1712 */
diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c
index 70c433c..5321357 100644
--- a/lib/dns/rdata/generic/hinfo_13.c
+++ b/lib/dns/rdata/generic/hinfo_13.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hinfo_13.c,v 1.42 2004/03/05 05:10:11 marka Exp $ */
+/* $Id: hinfo_13.c,v 1.44 2007/06/19 23:47:17 tbox Exp $ */
/*
* Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
diff --git a/lib/dns/rdata/generic/hinfo_13.h b/lib/dns/rdata/generic/hinfo_13.h
index e542c48..66766df 100644
--- a/lib/dns/rdata/generic/hinfo_13.h
+++ b/lib/dns/rdata/generic/hinfo_13.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_HINFO_13_H
#define GENERIC_HINFO_13_H 1
-/* $Id: hinfo_13.h,v 1.23 2004/03/05 05:10:12 marka Exp $ */
+/* $Id: hinfo_13.h,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_hinfo {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/ipseckey_45.c b/lib/dns/rdata/generic/ipseckey_45.c
index 3c3736e..bc2b4e8 100644
--- a/lib/dns/rdata/generic/ipseckey_45.c
+++ b/lib/dns/rdata/generic/ipseckey_45.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ipseckey_45.c,v 1.2.2.1 2005/07/07 03:17:36 marka Exp $ */
+/* $Id: ipseckey_45.c,v 1.4.332.2 2009/01/18 23:47:41 tbox Exp $ */
#ifndef RDATA_GENERIC_IPSECKEY_45_C
#define RDATA_GENERIC_IPSECKEY_45_C
@@ -131,15 +131,15 @@ totext_ipseckey(ARGS_TOTEXT) {
dns_name_init(&name, NULL);
dns_name_init(&prefix, NULL);
-
+
if (rdata->data[1] > 3U)
return (ISC_R_NOTIMPLEMENTED);
- if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
- RETERR(str_totext("( ", target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext("( ", target));
/*
- * Precendence.
+ * Precedence.
*/
dns_rdata_toregion(rdata, &region);
num = uint8_fromregion(&region);
@@ -198,14 +198,14 @@ totext_ipseckey(ARGS_TOTEXT) {
tctx->linebreak, target));
}
- if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
- RETERR(str_totext(" )", target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
return (ISC_R_SUCCESS);
}
static inline isc_result_t
fromwire_ipseckey(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
isc_region_t region;
REQUIRE(type == 45);
@@ -215,7 +215,7 @@ fromwire_ipseckey(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
- dns_name_init(&name, NULL);
+ dns_name_init(&name, NULL);
isc_buffer_activeregion(source, &region);
if (region.length < 3)
diff --git a/lib/dns/rdata/generic/ipseckey_45.h b/lib/dns/rdata/generic/ipseckey_45.h
index b766fa0..2a6201f 100644
--- a/lib/dns/rdata/generic/ipseckey_45.h
+++ b/lib/dns/rdata/generic/ipseckey_45.h
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ipseckey_45.h,v 1.2.2.1 2005/07/07 03:17:36 marka Exp $ */
+/* $Id: ipseckey_45.h,v 1.4 2007/06/19 23:47:17 tbox Exp $ */
#ifndef GENERIC_IPSECKEY_45_H
#define GENERIC_IPSECKEY_45_H 1
diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c
index 1813759..d7333d1 100644
--- a/lib/dns/rdata/generic/isdn_20.c
+++ b/lib/dns/rdata/generic/isdn_20.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: isdn_20.c,v 1.34.18.2 2005/04/29 00:16:33 marka Exp $ */
+/* $Id: isdn_20.c,v 1.38 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Wed Mar 15 16:53:11 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/generic/isdn_20.h b/lib/dns/rdata/generic/isdn_20.h
index 6a51317..a1f65ca 100644
--- a/lib/dns/rdata/generic/isdn_20.h
+++ b/lib/dns/rdata/generic/isdn_20.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_ISDN_20_H
#define GENERIC_ISDN_20_H 1
-/* $Id: isdn_20.h,v 1.14.18.2 2005/04/29 00:16:33 marka Exp $ */
+/* $Id: isdn_20.h,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1183 */
diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c
index 24dc10f..9acfe95 100644
--- a/lib/dns/rdata/generic/key_25.c
+++ b/lib/dns/rdata/generic/key_25.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: key_25.c,v 1.47.18.2 2005/04/29 00:16:33 marka Exp $ */
+/* $Id: key_25.c,v 1.51 2007/06/19 23:47:17 tbox Exp $ */
/*
* Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
diff --git a/lib/dns/rdata/generic/key_25.h b/lib/dns/rdata/generic/key_25.h
index 03400db..bcf9cb6 100644
--- a/lib/dns/rdata/generic/key_25.h
+++ b/lib/dns/rdata/generic/key_25.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_KEY_25_H
#define GENERIC_KEY_25_H 1
-/* $Id: key_25.h,v 1.15.18.2 2005/04/29 00:16:33 marka Exp $ */
+/* $Id: key_25.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC2535 */
diff --git a/lib/dns/rdata/generic/loc_29.c b/lib/dns/rdata/generic/loc_29.c
index c93ac90..a5d7f72 100644
--- a/lib/dns/rdata/generic/loc_29.c
+++ b/lib/dns/rdata/generic/loc_29.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: loc_29.c,v 1.41.18.2 2005/04/29 00:16:34 marka Exp $ */
+/* $Id: loc_29.c,v 1.45.332.4 2009/02/17 05:54:12 marka Exp $ */
/* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
@@ -482,16 +482,19 @@ totext_loc(ARGS_TOTEXT) {
/* version = sr.base[0]; */
size = sr.base[1];
+ INSIST((size&0x0f) < 10 && (size>>4) < 10);
if ((size&0x0f)> 1)
sprintf(sbuf, "%lum", (size>>4) * poweroften[(size&0x0f)-2]);
else
sprintf(sbuf, "0.%02lum", (size>>4) * poweroften[(size&0x0f)]);
hp = sr.base[2];
+ INSIST((hp&0x0f) < 10 && (hp>>4) < 10);
if ((hp&0x0f)> 1)
sprintf(hbuf, "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]);
else
sprintf(hbuf, "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]);
vp = sr.base[3];
+ INSIST((vp&0x0f) < 10 && (vp>>4) < 10);
if ((vp&0x0f)> 1)
sprintf(vbuf, "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]);
else
@@ -514,6 +517,7 @@ totext_loc(ARGS_TOTEXT) {
m1 = (int)(latitude % 60);
latitude /= 60;
d1 = (int)latitude;
+ INSIST(latitude <= 90U);
longitude = uint32_fromregion(&sr);
isc_region_consume(&sr, 4);
@@ -531,6 +535,7 @@ totext_loc(ARGS_TOTEXT) {
m2 = (int)(longitude % 60);
longitude /= 60;
d2 = (int)longitude;
+ INSIST(longitude <= 180U);
altitude = uint32_fromregion(&sr);
isc_region_consume(&sr, 4);
@@ -616,7 +621,7 @@ fromwire_loc(ARGS_FROMWIRE) {
return (ISC_R_RANGE);
/*
- * Altitiude.
+ * Altitude.
* All values possible.
*/
diff --git a/lib/dns/rdata/generic/loc_29.h b/lib/dns/rdata/generic/loc_29.h
index d8eae16..f053c60 100644
--- a/lib/dns/rdata/generic/loc_29.h
+++ b/lib/dns/rdata/generic/loc_29.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_LOC_29_H
#define GENERIC_LOC_29_H 1
-/* $Id: loc_29.h,v 1.15.18.2 2005/04/29 00:16:34 marka Exp $ */
+/* $Id: loc_29.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1876 */
diff --git a/lib/dns/rdata/generic/mb_7.c b/lib/dns/rdata/generic/mb_7.c
index 94c622d..fc3a7b6 100644
--- a/lib/dns/rdata/generic/mb_7.c
+++ b/lib/dns/rdata/generic/mb_7.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mb_7.c,v 1.43 2004/03/05 05:10:13 marka Exp $ */
+/* $Id: mb_7.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Wed Mar 15 17:31:26 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/generic/mb_7.h b/lib/dns/rdata/generic/mb_7.h
index f6a8b35..b427ee9 100644
--- a/lib/dns/rdata/generic/mb_7.h
+++ b/lib/dns/rdata/generic/mb_7.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_MB_7_H
#define GENERIC_MB_7_H 1
-/* $Id: mb_7.h,v 1.23.18.2 2005/04/29 00:16:34 marka Exp $ */
+/* $Id: mb_7.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_mb {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/md_3.c b/lib/dns/rdata/generic/md_3.c
index 75e4970..0f8560f 100644
--- a/lib/dns/rdata/generic/md_3.c
+++ b/lib/dns/rdata/generic/md_3.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: md_3.c,v 1.45 2004/03/05 05:10:13 marka Exp $ */
+/* $Id: md_3.c,v 1.47 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Wed Mar 15 17:48:20 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/generic/md_3.h b/lib/dns/rdata/generic/md_3.h
index 578ce66..ba70d18 100644
--- a/lib/dns/rdata/generic/md_3.h
+++ b/lib/dns/rdata/generic/md_3.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_MD_3_H
#define GENERIC_MD_3_H 1
-/* $Id: md_3.h,v 1.24.18.2 2005/04/29 00:16:35 marka Exp $ */
+/* $Id: md_3.h,v 1.28 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_md {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/mf_4.c b/lib/dns/rdata/generic/mf_4.c
index 362d300..dffcec2 100644
--- a/lib/dns/rdata/generic/mf_4.c
+++ b/lib/dns/rdata/generic/mf_4.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mf_4.c,v 1.43 2004/03/05 05:10:14 marka Exp $ */
+/* $Id: mf_4.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Wed Mar 15 17:47:33 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/mf_4.h b/lib/dns/rdata/generic/mf_4.h
index 2be0eec..32d2493 100644
--- a/lib/dns/rdata/generic/mf_4.h
+++ b/lib/dns/rdata/generic/mf_4.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_MF_4_H
#define GENERIC_MF_4_H 1
-/* $Id: mf_4.h,v 1.22.18.2 2005/04/29 00:16:35 marka Exp $ */
+/* $Id: mf_4.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_mf {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/mg_8.c b/lib/dns/rdata/generic/mg_8.c
index 602d820..e4dca1d 100644
--- a/lib/dns/rdata/generic/mg_8.c
+++ b/lib/dns/rdata/generic/mg_8.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mg_8.c,v 1.41 2004/03/05 05:10:14 marka Exp $ */
+/* $Id: mg_8.c,v 1.43 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Wed Mar 15 17:49:21 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/mg_8.h b/lib/dns/rdata/generic/mg_8.h
index 5679c17..8fa143a 100644
--- a/lib/dns/rdata/generic/mg_8.h
+++ b/lib/dns/rdata/generic/mg_8.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_MG_8_H
#define GENERIC_MG_8_H 1
-/* $Id: mg_8.h,v 1.22.18.2 2005/04/29 00:16:35 marka Exp $ */
+/* $Id: mg_8.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_mg {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/minfo_14.c b/lib/dns/rdata/generic/minfo_14.c
index b757480..6645bbc 100644
--- a/lib/dns/rdata/generic/minfo_14.c
+++ b/lib/dns/rdata/generic/minfo_14.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: minfo_14.c,v 1.43 2004/03/05 05:10:14 marka Exp $ */
+/* $Id: minfo_14.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Wed Mar 15 17:45:32 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/minfo_14.h b/lib/dns/rdata/generic/minfo_14.h
index 754fe20..76195c5 100644
--- a/lib/dns/rdata/generic/minfo_14.h
+++ b/lib/dns/rdata/generic/minfo_14.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_MINFO_14_H
#define GENERIC_MINFO_14_H 1
-/* $Id: minfo_14.h,v 1.23.18.2 2005/04/29 00:16:35 marka Exp $ */
+/* $Id: minfo_14.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_minfo {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/mr_9.c b/lib/dns/rdata/generic/mr_9.c
index ab4c6e0..289d739 100644
--- a/lib/dns/rdata/generic/mr_9.c
+++ b/lib/dns/rdata/generic/mr_9.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mr_9.c,v 1.40 2004/03/05 05:10:15 marka Exp $ */
+/* $Id: mr_9.c,v 1.42 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Wed Mar 15 21:30:35 EST 2000 by tale */
diff --git a/lib/dns/rdata/generic/mr_9.h b/lib/dns/rdata/generic/mr_9.h
index e255d70..3d81bdd 100644
--- a/lib/dns/rdata/generic/mr_9.h
+++ b/lib/dns/rdata/generic/mr_9.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_MR_9_H
#define GENERIC_MR_9_H 1
-/* $Id: mr_9.h,v 1.22.18.2 2005/04/29 00:16:36 marka Exp $ */
+/* $Id: mr_9.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_mr {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/mx_15.c b/lib/dns/rdata/generic/mx_15.c
index fd77ec8..086c043 100644
--- a/lib/dns/rdata/generic/mx_15.c
+++ b/lib/dns/rdata/generic/mx_15.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mx_15.c,v 1.52.18.2 2005/05/20 01:10:11 marka Exp $ */
+/* $Id: mx_15.c,v 1.56 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Wed Mar 15 18:05:46 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/mx_15.h b/lib/dns/rdata/generic/mx_15.h
index 4d81b90..25d5ac5 100644
--- a/lib/dns/rdata/generic/mx_15.h
+++ b/lib/dns/rdata/generic/mx_15.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_MX_15_H
#define GENERIC_MX_15_H 1
-/* $Id: mx_15.h,v 1.25.18.2 2005/04/29 00:16:36 marka Exp $ */
+/* $Id: mx_15.h,v 1.29 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_mx {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/ns_2.c b/lib/dns/rdata/generic/ns_2.c
index 2379433..9a2ee8c 100644
--- a/lib/dns/rdata/generic/ns_2.c
+++ b/lib/dns/rdata/generic/ns_2.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ns_2.c,v 1.44 2004/03/05 05:10:15 marka Exp $ */
+/* $Id: ns_2.c,v 1.46 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Wed Mar 15 18:15:00 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/generic/ns_2.h b/lib/dns/rdata/generic/ns_2.h
index ec8e771..546e71a 100644
--- a/lib/dns/rdata/generic/ns_2.h
+++ b/lib/dns/rdata/generic/ns_2.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_NS_2_H
#define GENERIC_NS_2_H 1
-/* $Id: ns_2.h,v 1.23.18.2 2005/04/29 00:16:37 marka Exp $ */
+/* $Id: ns_2.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_ns {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/nsec3_50.c b/lib/dns/rdata/generic/nsec3_50.c
new file mode 100644
index 0000000..c5f0acb
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3_50.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: nsec3_50.c,v 1.4.48.2 2009/01/18 23:47:41 tbox Exp $ */
+
+/*
+ * Copyright (C) 2004 Nominet, Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* RFC 5155 */
+
+#ifndef RDATA_GENERIC_NSEC3_50_C
+#define RDATA_GENERIC_NSEC3_50_C
+
+#include <isc/iterated_hash.h>
+#include <isc/base32.h>
+
+#define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
+
+static inline isc_result_t
+fromtext_nsec3(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char bm[8*1024]; /* 64k bits */
+ dns_rdatatype_t covered;
+ int octet;
+ int window;
+ unsigned int flags;
+ unsigned char hashalg;
+ isc_buffer_t b;
+
+ REQUIRE(type == 50);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+ UNUSED(origin);
+ UNUSED(options);
+
+ /* Hash. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
+ RETERR(uint8_tobuffer(hashalg, target));
+
+ /* Flags. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ flags = token.value.as_ulong;
+ if (flags > 255U)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(flags, target));
+
+ /* Iterations. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /* salt */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (token.value.as_textregion.length > (255*2))
+ RETTOK(DNS_R_TEXTTOOLONG);
+ if (strcmp(DNS_AS_STR(token), "-") == 0) {
+ RETERR(uint8_tobuffer(0, target));
+ } else {
+ RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
+ RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
+ }
+
+ /*
+ * Next hash a single base32hex word.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ isc_buffer_init(&b, bm, sizeof(bm));
+ RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token), &b));
+ if (isc_buffer_usedlength(&b) > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
+ RETERR(mem_tobuffer(target, &bm, isc_buffer_usedlength(&b)));
+
+ memset(bm, 0, sizeof(bm));
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, ISC_TRUE));
+ if (token.type != isc_tokentype_string)
+ break;
+ RETTOK(dns_rdatatype_fromtext(&covered,
+ &token.value.as_textregion));
+ bm[covered/8] |= (0x80>>(covered%8));
+ } while (1);
+ isc_lex_ungettoken(lexer, &token);
+ for (window = 0; window < 256 ; window++) {
+ /*
+ * Find if we have a type in this window.
+ */
+ for (octet = 31; octet >= 0; octet--)
+ if (bm[window * 32 + octet] != 0)
+ break;
+ if (octet < 0)
+ continue;
+ RETERR(uint8_tobuffer(window, target));
+ RETERR(uint8_tobuffer(octet + 1, target));
+ RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_nsec3(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j, k;
+ unsigned int window, len;
+ unsigned char hash;
+ unsigned char flags;
+ char buf[sizeof("65535 ")];
+ isc_uint32_t iterations;
+
+ REQUIRE(rdata->type == 50);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ hash = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ flags = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ iterations = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ sprintf(buf, "%u ", hash);
+ RETERR(str_totext(buf, target));
+
+ sprintf(buf, "%u ", flags);
+ RETERR(str_totext(buf, target));
+
+ sprintf(buf, "%u ", iterations);
+ RETERR(str_totext(buf, target));
+
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ if (j != 0) {
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_hex_totext(&sr, 1, "", target));
+ sr.length = i - j;
+ RETERR(str_totext(" ", target));
+ } else
+ RETERR(str_totext("- ", target));
+
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_base32hex_totext(&sr, 1, "", target));
+ sr.length = i - j;
+
+ for (i = 0; i < sr.length; i += len) {
+ INSIST(i + 2 <= sr.length);
+ window = sr.base[i];
+ len = sr.base[i + 1];
+ INSIST(len > 0 && len <= 32);
+ i += 2;
+ INSIST(i + len <= sr.length);
+ for (j = 0; j < len; j++) {
+ dns_rdatatype_t t;
+ if (sr.base[i + j] == 0)
+ continue;
+ for (k = 0; k < 8; k++) {
+ if ((sr.base[i + j] & (0x80 >> k)) == 0)
+ continue;
+ t = window * 256 + j * 8 + k;
+ RETERR(str_totext(" ", target));
+ if (dns_rdatatype_isknown(t)) {
+ RETERR(dns_rdatatype_totext(t, target));
+ } else {
+ char buf[sizeof("TYPE65535")];
+ sprintf(buf, "TYPE%u", t);
+ RETERR(str_totext(buf, target));
+ }
+ }
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_nsec3(ARGS_FROMWIRE) {
+ isc_region_t sr, rr;
+ unsigned int window, lastwindow = 0;
+ unsigned int len;
+ unsigned int saltlen, hashlen;
+ isc_boolean_t first = ISC_TRUE;
+ unsigned int i;
+
+ REQUIRE(type == 50);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(options);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sr);
+ rr = sr;
+
+ /* hash(1), flags(1), iteration(2), saltlen(1) */
+ if (sr.length < 5U)
+ RETERR(DNS_R_FORMERR);
+ saltlen = sr.base[4];
+ isc_region_consume(&sr, 5);
+
+ if (sr.length < saltlen)
+ RETERR(DNS_R_FORMERR);
+ isc_region_consume(&sr, saltlen);
+
+ if (sr.length < 1U)
+ RETERR(DNS_R_FORMERR);
+ hashlen = sr.base[0];
+ isc_region_consume(&sr, 1);
+
+ if (sr.length < hashlen)
+ RETERR(DNS_R_FORMERR);
+ isc_region_consume(&sr, hashlen);
+
+ for (i = 0; i < sr.length; i += len) {
+ /*
+ * Check for overflow.
+ */
+ if (i + 2 > sr.length)
+ RETERR(DNS_R_FORMERR);
+ window = sr.base[i];
+ len = sr.base[i + 1];
+ i += 2;
+ /*
+ * Check that bitmap windows are in the correct order.
+ */
+ if (!first && window <= lastwindow)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * Check for legal lengths.
+ */
+ if (len < 1 || len > 32)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * Check for overflow.
+ */
+ if (i + len > sr.length)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * The last octet of the bitmap must be non zero.
+ */
+ if (sr.base[i + len - 1] == 0)
+ RETERR(DNS_R_FORMERR);
+ lastwindow = window;
+ first = ISC_FALSE;
+ }
+ if (i != sr.length)
+ return (DNS_R_EXTRADATA);
+ RETERR(mem_tobuffer(target, rr.base, rr.length));
+ isc_buffer_forward(source, rr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_nsec3(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 50);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_nsec3(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 50);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_nsec3(ARGS_FROMSTRUCT) {
+ dns_rdata_nsec3_t *nsec3 = source;
+ unsigned int i, len, window, lastwindow = 0;
+ isc_boolean_t first = ISC_TRUE;
+
+ REQUIRE(type == 50);
+ REQUIRE(source != NULL);
+ REQUIRE(nsec3->common.rdtype == type);
+ REQUIRE(nsec3->common.rdclass == rdclass);
+ REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
+ REQUIRE(nsec3->hash == dns_hash_sha1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(nsec3->hash, target));
+ RETERR(uint8_tobuffer(nsec3->flags, target));
+ RETERR(uint16_tobuffer(nsec3->iterations, target));
+ RETERR(uint8_tobuffer(nsec3->salt_length, target));
+ RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
+ RETERR(uint8_tobuffer(nsec3->next_length, target));
+ RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
+
+ /*
+ * Perform sanity check.
+ */
+ for (i = 0; i < nsec3->len ; i += len) {
+ INSIST(i + 2 <= nsec3->len);
+ window = nsec3->typebits[i];
+ len = nsec3->typebits[i+1];
+ i += 2;
+ INSIST(first || window > lastwindow);
+ INSIST(len > 0 && len <= 32);
+ INSIST(i + len <= nsec3->len);
+ INSIST(nsec3->typebits[i + len - 1] != 0);
+ lastwindow = window;
+ first = ISC_FALSE;
+ }
+ return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
+}
+
+static inline isc_result_t
+tostruct_nsec3(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nsec3_t *nsec3 = target;
+
+ REQUIRE(rdata->type == 50);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsec3->common.rdclass = rdata->rdclass;
+ nsec3->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsec3->common, link);
+
+ region.base = rdata->data;
+ region.length = rdata->length;
+ nsec3->hash = uint8_consume_fromregion(&region);
+ nsec3->flags = uint8_consume_fromregion(&region);
+ nsec3->iterations = uint16_consume_fromregion(&region);
+
+ nsec3->salt_length = uint8_consume_fromregion(&region);
+ nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
+ if (nsec3->salt == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_region_consume(&region, nsec3->salt_length);
+
+ nsec3->next_length = uint8_consume_fromregion(&region);
+ nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
+ if (nsec3->next == NULL)
+ goto cleanup;
+ isc_region_consume(&region, nsec3->next_length);
+
+ nsec3->len = region.length;
+ nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
+ if (nsec3->typebits == NULL)
+ goto cleanup;
+
+ nsec3->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (nsec3->next != NULL)
+ isc_mem_free(mctx, nsec3->next);
+ isc_mem_free(mctx, nsec3->salt);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_nsec3(ARGS_FREESTRUCT) {
+ dns_rdata_nsec3_t *nsec3 = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(nsec3->common.rdtype == 50);
+
+ if (nsec3->mctx == NULL)
+ return;
+
+ if (nsec3->salt != NULL)
+ isc_mem_free(nsec3->mctx, nsec3->salt);
+ if (nsec3->next != NULL)
+ isc_mem_free(nsec3->mctx, nsec3->next);
+ if (nsec3->typebits != NULL)
+ isc_mem_free(nsec3->mctx, nsec3->typebits);
+ nsec3->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_nsec3(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 50);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_nsec3(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 50);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_nsec3(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 50);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_nsec3(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 50);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_NSEC3_50_C */
diff --git a/lib/dns/rdata/generic/nsec3_50.h b/lib/dns/rdata/generic/nsec3_50.h
new file mode 100644
index 0000000..658dd9d
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3_50.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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_NSEC3_50_H
+#define GENERIC_NSEC3_50_H 1
+
+/* $Id: nsec3_50.h,v 1.4 2008/09/25 04:02:39 tbox Exp $ */
+
+/*!
+ * \brief Per RFC 5155 */
+
+#include <isc/iterated_hash.h>
+
+typedef struct dns_rdata_nsec3 {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_hash_t hash;
+ unsigned char flags;
+ dns_iterations_t iterations;
+ unsigned char salt_length;
+ unsigned char next_length;
+ isc_uint16_t len;
+ unsigned char *salt;
+ unsigned char *next;
+ unsigned char *typebits;
+} dns_rdata_nsec3_t;
+
+/*
+ * The corresponding NSEC3 interval is OPTOUT indicating possible
+ * insecure delegations.
+ */
+#define DNS_NSEC3FLAG_OPTOUT 0x01U
+
+/*%
+ * Non-standard, NSEC3PARAM only.
+ *
+ * Create a corresponding NSEC3 chain.
+ * Once the NSEC3 chain is complete this flag will be removed to signal
+ * that there is a complete chain.
+ *
+ * This flag is automatically set when a NSEC3PARAM record is added to
+ * the zone via UPDATE.
+ *
+ * NSEC3PARAM records with this flag set are supposed to be ignored by
+ * RFC 5155 compliant nameservers.
+ */
+#define DNS_NSEC3FLAG_CREATE 0x80U
+
+/*%
+ * Non-standard, NSEC3PARAM only.
+ *
+ * The corresponding NSEC3 set is to be removed once the NSEC chain
+ * has been generated.
+ *
+ * This flag is automatically set when the last active NSEC3PARAM record
+ * is removed from the zone via UPDATE.
+ *
+ * NSEC3PARAM records with this flag set are supposed to be ignored by
+ * RFC 5155 compliant nameservers.
+ */
+#define DNS_NSEC3FLAG_REMOVE 0x40U
+
+/*%
+ * Non-standard, NSEC3PARAM only.
+ *
+ * Used to identify NSEC3PARAM records added in this UPDATE request.
+ */
+#define DNS_NSEC3FLAG_UPDATE 0x20U
+
+/*%
+ * Non-standard, NSEC3PARAM only.
+ *
+ * Prevent the creation of a NSEC chain before the last NSEC3 chain
+ * is removed. This will normally only be set when the zone is
+ * transitioning from secure with NSEC3 chains to insecure.
+ */
+#define DNS_NSEC3FLAG_NONSEC 0x10U
+
+#endif /* GENERIC_NSEC3_50_H */
diff --git a/lib/dns/rdata/generic/nsec3param_51.c b/lib/dns/rdata/generic/nsec3param_51.c
new file mode 100644
index 0000000..607ce6a
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3param_51.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: nsec3param_51.c,v 1.4.48.2 2009/01/18 23:47:41 tbox Exp $ */
+
+/*
+ * Copyright (C) 2004 Nominet, Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* RFC 5155 */
+
+#ifndef RDATA_GENERIC_NSEC3PARAM_51_C
+#define RDATA_GENERIC_NSEC3PARAM_51_C
+
+#include <isc/iterated_hash.h>
+#include <isc/base32.h>
+
+#define RRTYPE_NSEC3PARAM_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_nsec3param(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned int flags = 0;
+ unsigned char hashalg;
+
+ REQUIRE(type == 51);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+ UNUSED(origin);
+ UNUSED(options);
+
+ /* Hash. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
+ RETERR(uint8_tobuffer(hashalg, target));
+
+ /* Flags. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ flags = token.value.as_ulong;
+ if (flags > 255U)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(flags, target));
+
+ /* Iterations. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /* Salt. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (token.value.as_textregion.length > (255*2))
+ RETTOK(DNS_R_TEXTTOOLONG);
+ if (strcmp(DNS_AS_STR(token), "-") == 0) {
+ RETERR(uint8_tobuffer(0, target));
+ } else {
+ RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
+ RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_nsec3param(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j;
+ unsigned char hash;
+ unsigned char flags;
+ char buf[sizeof("65535 ")];
+ isc_uint32_t iterations;
+
+ REQUIRE(rdata->type == 51);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ hash = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ flags = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ iterations = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ sprintf(buf, "%u ", hash);
+ RETERR(str_totext(buf, target));
+
+ sprintf(buf, "%u ", flags);
+ RETERR(str_totext(buf, target));
+
+ sprintf(buf, "%u ", iterations);
+ RETERR(str_totext(buf, target));
+
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ if (j != 0) {
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_hex_totext(&sr, 1, "", target));
+ sr.length = i - j;
+ } else
+ RETERR(str_totext("-", target));
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_nsec3param(ARGS_FROMWIRE) {
+ isc_region_t sr, rr;
+ unsigned int saltlen;
+
+ REQUIRE(type == 51);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(options);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sr);
+ rr = sr;
+
+ /* hash(1), flags(1), iterations(2), saltlen(1) */
+ if (sr.length < 5U)
+ RETERR(DNS_R_FORMERR);
+ saltlen = sr.base[4];
+ isc_region_consume(&sr, 5);
+
+ if (sr.length < saltlen)
+ RETERR(DNS_R_FORMERR);
+ isc_region_consume(&sr, saltlen);
+ RETERR(mem_tobuffer(target, rr.base, rr.length));
+ isc_buffer_forward(source, rr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_nsec3param(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 51);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_nsec3param(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 51);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_nsec3param(ARGS_FROMSTRUCT) {
+ dns_rdata_nsec3param_t *nsec3param = source;
+
+ REQUIRE(type == 51);
+ REQUIRE(source != NULL);
+ REQUIRE(nsec3param->common.rdtype == type);
+ REQUIRE(nsec3param->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(nsec3param->hash, target));
+ RETERR(uint8_tobuffer(nsec3param->flags, target));
+ RETERR(uint16_tobuffer(nsec3param->iterations, target));
+ RETERR(uint8_tobuffer(nsec3param->salt_length, target));
+ RETERR(mem_tobuffer(target, nsec3param->salt,
+ nsec3param->salt_length));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+tostruct_nsec3param(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nsec3param_t *nsec3param = target;
+
+ REQUIRE(rdata->type == 51);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsec3param->common.rdclass = rdata->rdclass;
+ nsec3param->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsec3param->common, link);
+
+ region.base = rdata->data;
+ region.length = rdata->length;
+ nsec3param->hash = uint8_consume_fromregion(&region);
+ nsec3param->flags = uint8_consume_fromregion(&region);
+ nsec3param->iterations = uint16_consume_fromregion(&region);
+
+ nsec3param->salt_length = uint8_consume_fromregion(&region);
+ nsec3param->salt = mem_maybedup(mctx, region.base,
+ nsec3param->salt_length);
+ if (nsec3param->salt == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_region_consume(&region, nsec3param->salt_length);
+
+ nsec3param->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_nsec3param(ARGS_FREESTRUCT) {
+ dns_rdata_nsec3param_t *nsec3param = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(nsec3param->common.rdtype == 51);
+
+ if (nsec3param->mctx == NULL)
+ return;
+
+ if (nsec3param->salt != NULL)
+ isc_mem_free(nsec3param->mctx, nsec3param->salt);
+ nsec3param->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_nsec3param(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 51);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_nsec3param(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 51);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_nsec3param(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 51);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_nsec3param(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 51);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_NSEC3PARAM_51_C */
diff --git a/lib/dns/rdata/generic/nsec3param_51.h b/lib/dns/rdata/generic/nsec3param_51.h
new file mode 100644
index 0000000..2efd7e6
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3param_51.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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_NSEC3PARAM_51_H
+#define GENERIC_NSEC3PARAM_51_H 1
+
+/* $Id: nsec3param_51.h,v 1.4 2008/09/25 04:02:39 tbox Exp $ */
+
+/*!
+ * \brief Per RFC 5155 */
+
+#include <isc/iterated_hash.h>
+
+typedef struct dns_rdata_nsec3param {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_hash_t hash;
+ unsigned char flags; /* DNS_NSEC3FLAG_* */
+ dns_iterations_t iterations;
+ unsigned char salt_length;
+ unsigned char *salt;
+} dns_rdata_nsec3param_t;
+
+#endif /* GENERIC_NSEC3PARAM_51_H */
diff --git a/lib/dns/rdata/generic/nsec_47.c b/lib/dns/rdata/generic/nsec_47.c
index dd39105..7e443d9 100644
--- a/lib/dns/rdata/generic/nsec_47.c
+++ b/lib/dns/rdata/generic/nsec_47.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec_47.c,v 1.7.20.2 2008/07/15 23:46:14 tbox Exp $ */
+/* $Id: nsec_47.c,v 1.11 2008/07/15 23:47:21 tbox Exp $ */
/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/nsec_47.h b/lib/dns/rdata/generic/nsec_47.h
index 5c52447..2b3c6b6 100644
--- a/lib/dns/rdata/generic/nsec_47.h
+++ b/lib/dns/rdata/generic/nsec_47.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -18,7 +18,7 @@
#ifndef GENERIC_NSEC_47_H
#define GENERIC_NSEC_47_H 1
-/* $Id: nsec_47.h,v 1.4.20.4 2008/07/15 23:46:14 tbox Exp $ */
+/* $Id: nsec_47.h,v 1.10 2008/07/15 23:47:21 tbox Exp $ */
/*!
* \brief Per RFC 3845 */
diff --git a/lib/dns/rdata/generic/null_10.c b/lib/dns/rdata/generic/null_10.c
index a6f8f9f4..00bb542 100644
--- a/lib/dns/rdata/generic/null_10.c
+++ b/lib/dns/rdata/generic/null_10.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: null_10.c,v 1.40 2004/03/05 05:10:16 marka Exp $ */
+/* $Id: null_10.c,v 1.42 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 13:57:50 PST 2000 by explorer */
diff --git a/lib/dns/rdata/generic/null_10.h b/lib/dns/rdata/generic/null_10.h
index 5afb1ae..ceeb018 100644
--- a/lib/dns/rdata/generic/null_10.h
+++ b/lib/dns/rdata/generic/null_10.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_NULL_10_H
#define GENERIC_NULL_10_H 1
-/* $Id: null_10.h,v 1.21.18.2 2005/04/29 00:16:37 marka Exp $ */
+/* $Id: null_10.h,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_null {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/nxt_30.c b/lib/dns/rdata/generic/nxt_30.c
index b7358e0..7ffb86c 100644
--- a/lib/dns/rdata/generic/nxt_30.c
+++ b/lib/dns/rdata/generic/nxt_30.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nxt_30.c,v 1.59.18.2 2005/04/29 00:16:38 marka Exp $ */
+/* $Id: nxt_30.c,v 1.63 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/nxt_30.h b/lib/dns/rdata/generic/nxt_30.h
index 3700fb1..e2e8688 100644
--- a/lib/dns/rdata/generic/nxt_30.h
+++ b/lib/dns/rdata/generic/nxt_30.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_NXT_30_H
#define GENERIC_NXT_30_H 1
-/* $Id: nxt_30.h,v 1.21.18.2 2005/04/29 00:16:38 marka Exp $ */
+/* $Id: nxt_30.h,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief RFC2535 */
diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c
index e8f4816..d2cfc2e 100644
--- a/lib/dns/rdata/generic/opt_41.c
+++ b/lib/dns/rdata/generic/opt_41.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: opt_41.c,v 1.29.18.2 2005/04/29 00:16:38 marka Exp $ */
+/* $Id: opt_41.c,v 1.33 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 14:06:44 PST 2000 by gson */
diff --git a/lib/dns/rdata/generic/opt_41.h b/lib/dns/rdata/generic/opt_41.h
index 827936e..d6539cf 100644
--- a/lib/dns/rdata/generic/opt_41.h
+++ b/lib/dns/rdata/generic/opt_41.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_OPT_41_H
#define GENERIC_OPT_41_H 1
-/* $Id: opt_41.h,v 1.14.18.2 2005/04/29 00:16:38 marka Exp $ */
+/* $Id: opt_41.h,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC2671 */
diff --git a/lib/dns/rdata/generic/proforma.c b/lib/dns/rdata/generic/proforma.c
index bf8b2fd..879b761 100644
--- a/lib/dns/rdata/generic/proforma.c
+++ b/lib/dns/rdata/generic/proforma.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: proforma.c,v 1.34 2004/03/05 05:10:17 marka Exp $ */
+/* $Id: proforma.c,v 1.36 2007/06/19 23:47:17 tbox Exp $ */
#ifndef RDATA_GENERIC_#_#_C
#define RDATA_GENERIC_#_#_C
diff --git a/lib/dns/rdata/generic/proforma.h b/lib/dns/rdata/generic/proforma.h
index 89d1606..e5c420a 100644
--- a/lib/dns/rdata/generic/proforma.h
+++ b/lib/dns/rdata/generic/proforma.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_PROFORMA_H
#define GENERIC_PROFORMA_H 1
-/* $Id: proforma.h,v 1.19.18.2 2005/04/29 00:16:39 marka Exp $ */
+/* $Id: proforma.h,v 1.23 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_# {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/ptr_12.c b/lib/dns/rdata/generic/ptr_12.c
index 16d5706..fbabcbf 100644
--- a/lib/dns/rdata/generic/ptr_12.c
+++ b/lib/dns/rdata/generic/ptr_12.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ptr_12.c,v 1.41 2004/03/05 05:10:17 marka Exp $ */
+/* $Id: ptr_12.c,v 1.43 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 14:05:12 PST 2000 by explorer */
diff --git a/lib/dns/rdata/generic/ptr_12.h b/lib/dns/rdata/generic/ptr_12.h
index 4eb8fa7..304dcc4 100644
--- a/lib/dns/rdata/generic/ptr_12.h
+++ b/lib/dns/rdata/generic/ptr_12.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_PTR_12_H
#define GENERIC_PTR_12_H 1
-/* $Id: ptr_12.h,v 1.23.18.2 2005/04/29 00:16:39 marka Exp $ */
+/* $Id: ptr_12.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_ptr {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/rp_17.c b/lib/dns/rdata/generic/rp_17.c
index b153643..557cb04 100644
--- a/lib/dns/rdata/generic/rp_17.c
+++ b/lib/dns/rdata/generic/rp_17.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rp_17.c,v 1.38.18.2 2005/04/29 00:16:39 marka Exp $ */
+/* $Id: rp_17.c,v 1.42 2007/06/19 23:47:17 tbox Exp $ */
/* RFC1183 */
diff --git a/lib/dns/rdata/generic/rp_17.h b/lib/dns/rdata/generic/rp_17.h
index 533c7e7..6223038 100644
--- a/lib/dns/rdata/generic/rp_17.h
+++ b/lib/dns/rdata/generic/rp_17.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_RP_17_H
#define GENERIC_RP_17_H 1
-/* $Id: rp_17.h,v 1.17.18.2 2005/04/29 00:16:39 marka Exp $ */
+/* $Id: rp_17.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1183 */
diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c
index 6561f28..a9af4bd 100644
--- a/lib/dns/rdata/generic/rrsig_46.c
+++ b/lib/dns/rdata/generic/rrsig_46.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rrsig_46.c,v 1.5.18.3 2005/04/29 00:16:39 marka Exp $ */
+/* $Id: rrsig_46.c,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */
diff --git a/lib/dns/rdata/generic/rrsig_46.h b/lib/dns/rdata/generic/rrsig_46.h
index b8b35a2..8e8dc4e 100644
--- a/lib/dns/rdata/generic/rrsig_46.h
+++ b/lib/dns/rdata/generic/rrsig_46.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_DNSSIG_46_H
#define GENERIC_DNSSIG_46_H 1
-/* $Id: rrsig_46.h,v 1.3.20.2 2005/04/29 00:16:39 marka Exp $ */
+/* $Id: rrsig_46.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC2535 */
diff --git a/lib/dns/rdata/generic/rt_21.c b/lib/dns/rdata/generic/rt_21.c
index 6977e98..6444102 100644
--- a/lib/dns/rdata/generic/rt_21.c
+++ b/lib/dns/rdata/generic/rt_21.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rt_21.c,v 1.41.18.3 2005/04/27 05:01:52 sra Exp $ */
+/* $Id: rt_21.c,v 1.46 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Thu Mar 16 15:02:31 PST 2000 by brister */
diff --git a/lib/dns/rdata/generic/rt_21.h b/lib/dns/rdata/generic/rt_21.h
index b8ec969..2c0e9fc 100644
--- a/lib/dns/rdata/generic/rt_21.h
+++ b/lib/dns/rdata/generic/rt_21.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_RT_21_H
#define GENERIC_RT_21_H 1
-/* $Id: rt_21.h,v 1.17.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: rt_21.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1183 */
diff --git a/lib/dns/rdata/generic/sig_24.c b/lib/dns/rdata/generic/sig_24.c
index 9842953..e79e1e4 100644
--- a/lib/dns/rdata/generic/sig_24.c
+++ b/lib/dns/rdata/generic/sig_24.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sig_24.c,v 1.62.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: sig_24.c,v 1.66 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */
diff --git a/lib/dns/rdata/generic/sig_24.h b/lib/dns/rdata/generic/sig_24.h
index 96ed767..7212d4d 100644
--- a/lib/dns/rdata/generic/sig_24.h
+++ b/lib/dns/rdata/generic/sig_24.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_SIG_24_H
#define GENERIC_SIG_24_H 1
-/* $Id: sig_24.h,v 1.22.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: sig_24.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC2535 */
diff --git a/lib/dns/rdata/generic/soa_6.c b/lib/dns/rdata/generic/soa_6.c
index 8de678c..921aead 100644
--- a/lib/dns/rdata/generic/soa_6.c
+++ b/lib/dns/rdata/generic/soa_6.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: soa_6.c,v 1.59 2004/03/05 05:10:18 marka Exp $ */
+/* $Id: soa_6.c,v 1.61.332.2 2009/02/16 23:47:15 tbox Exp $ */
/* Reviewed: Thu Mar 16 15:18:32 PST 2000 by explorer */
@@ -101,7 +101,11 @@ totext_soa(ARGS_TOTEXT) {
REQUIRE(rdata->length != 0);
multiline = ISC_TF((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0);
- comment = ISC_TF((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0);
+ if (multiline)
+ comment = ISC_TF((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0);
+ else
+ comment = ISC_FALSE;
+
dns_name_init(&mname, NULL);
dns_name_init(&rname, NULL);
@@ -128,16 +132,13 @@ totext_soa(ARGS_TOTEXT) {
RETERR(str_totext(tctx->linebreak, target));
for (i = 0; i < 5; i++) {
- char buf[sizeof("2147483647")];
+ char buf[sizeof("0123456789 ; ")];
unsigned long num;
- unsigned int numlen;
num = uint32_fromregion(&dregion);
isc_region_consume(&dregion, 4);
- numlen = sprintf(buf, "%lu", num);
- INSIST(numlen > 0 && numlen < sizeof("2147483647"));
+ sprintf(buf, comment ? "%-10lu ; " : "%lu", num);
RETERR(str_totext(buf, target));
- if (multiline && comment) {
- RETERR(str_totext(" ; " + numlen, target));
+ if (comment) {
RETERR(str_totext(soa_fieldnames[i], target));
/* Print times in week/day/hour/minute/second form */
if (i >= 1) {
@@ -147,7 +148,7 @@ totext_soa(ARGS_TOTEXT) {
}
RETERR(str_totext(tctx->linebreak, target));
} else if (i < 4) {
- RETERR(str_totext(tctx->linebreak, target));
+ RETERR(str_totext(tctx->linebreak, target));
}
}
@@ -159,8 +160,8 @@ totext_soa(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_soa(ARGS_FROMWIRE) {
- dns_name_t mname;
- dns_name_t rname;
+ dns_name_t mname;
+ dns_name_t rname;
isc_region_t sregion;
isc_region_t tregion;
@@ -171,11 +172,11 @@ fromwire_soa(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&mname, NULL);
- dns_name_init(&rname, NULL);
+ dns_name_init(&mname, NULL);
+ dns_name_init(&rname, NULL);
- RETERR(dns_name_fromwire(&mname, source, dctx, options, target));
- RETERR(dns_name_fromwire(&rname, source, dctx, options, target));
+ RETERR(dns_name_fromwire(&mname, source, dctx, options, target));
+ RETERR(dns_name_fromwire(&rname, source, dctx, options, target));
isc_buffer_activeregion(source, &sregion);
isc_buffer_availableregion(target, &tregion);
diff --git a/lib/dns/rdata/generic/soa_6.h b/lib/dns/rdata/generic/soa_6.h
index 4211786..7443b04 100644
--- a/lib/dns/rdata/generic/soa_6.h
+++ b/lib/dns/rdata/generic/soa_6.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_SOA_6_H
#define GENERIC_SOA_6_H 1
-/* $Id: soa_6.h,v 1.28.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: soa_6.h,v 1.32 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_soa {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c
index b65f580..12e813e 100644
--- a/lib/dns/rdata/generic/spf_99.c
+++ b/lib/dns/rdata/generic/spf_99.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: spf_99.c,v 1.1.2.2 2005/07/16 00:40:54 marka Exp $ */
+/* $Id: spf_99.c,v 1.4 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/generic/spf_99.h b/lib/dns/rdata/generic/spf_99.h
index afe77ec..be5e978 100644
--- a/lib/dns/rdata/generic/spf_99.h
+++ b/lib/dns/rdata/generic/spf_99.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_SPF_99_H
#define GENERIC_SPF_99_H 1
-/* $Id: spf_99.h,v 1.1.2.2 2005/07/16 00:40:54 marka Exp $ */
+/* $Id: spf_99.h,v 1.4 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_spf_string {
isc_uint8_t length;
diff --git a/lib/dns/rdata/generic/sshfp_44.c b/lib/dns/rdata/generic/sshfp_44.c
index 64b51c7..570a3b7 100644
--- a/lib/dns/rdata/generic/sshfp_44.c
+++ b/lib/dns/rdata/generic/sshfp_44.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sshfp_44.c,v 1.3.18.1 2006/03/10 04:04:32 marka Exp $ */
+/* $Id: sshfp_44.c,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
/* RFC 4255 */
diff --git a/lib/dns/rdata/generic/sshfp_44.h b/lib/dns/rdata/generic/sshfp_44.h
index 513eeac..daea74c 100644
--- a/lib/dns/rdata/generic/sshfp_44.h
+++ b/lib/dns/rdata/generic/sshfp_44.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sshfp_44.h,v 1.2.18.3 2006/03/10 04:04:32 marka Exp $ */
+/* $Id: sshfp_44.h,v 1.8 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC 4255 */
diff --git a/lib/dns/rdata/generic/tkey_249.c b/lib/dns/rdata/generic/tkey_249.c
index cee16ab..2412c85 100644
--- a/lib/dns/rdata/generic/tkey_249.c
+++ b/lib/dns/rdata/generic/tkey_249.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tkey_249.c,v 1.55 2004/03/05 05:10:18 marka Exp $ */
+/* $Id: tkey_249.c,v 1.57 2007/06/19 23:47:17 tbox Exp $ */
/*
* Reviewed: Thu Mar 16 17:35:30 PST 2000 by halley.
diff --git a/lib/dns/rdata/generic/tkey_249.h b/lib/dns/rdata/generic/tkey_249.h
index c1d2f06..34d5646 100644
--- a/lib/dns/rdata/generic/tkey_249.h
+++ b/lib/dns/rdata/generic/tkey_249.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_TKEY_249_H
#define GENERIC_TKEY_249_H 1
-/* $Id: tkey_249.h,v 1.20.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: tkey_249.h,v 1.24 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per draft-ietf-dnsind-tkey-00.txt */
diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c
index 01ca87a..a158a59 100644
--- a/lib/dns/rdata/generic/txt_16.c
+++ b/lib/dns/rdata/generic/txt_16.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: txt_16.c,v 1.41.18.2 2008/02/15 23:45:53 tbox Exp $ */
+/* $Id: txt_16.c,v 1.45 2008/02/15 23:46:51 tbox Exp $ */
/* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/generic/txt_16.h b/lib/dns/rdata/generic/txt_16.h
index 57d986a..fc46486 100644
--- a/lib/dns/rdata/generic/txt_16.h
+++ b/lib/dns/rdata/generic/txt_16.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_TXT_16_H
#define GENERIC_TXT_16_H 1
-/* $Id: txt_16.h,v 1.24.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: txt_16.h,v 1.28 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_txt_string {
isc_uint8_t length;
diff --git a/lib/dns/rdata/generic/unspec_103.c b/lib/dns/rdata/generic/unspec_103.c
index f316ad9..384863e 100644
--- a/lib/dns/rdata/generic/unspec_103.c
+++ b/lib/dns/rdata/generic/unspec_103.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: unspec_103.c,v 1.33 2004/03/05 05:10:18 marka Exp $ */
+/* $Id: unspec_103.c,v 1.35 2007/06/19 23:47:17 tbox Exp $ */
#ifndef RDATA_GENERIC_UNSPEC_103_C
#define RDATA_GENERIC_UNSPEC_103_C
diff --git a/lib/dns/rdata/generic/unspec_103.h b/lib/dns/rdata/generic/unspec_103.h
index 6575c1a..4b2d310 100644
--- a/lib/dns/rdata/generic/unspec_103.h
+++ b/lib/dns/rdata/generic/unspec_103.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef GENERIC_UNSPEC_103_H
#define GENERIC_UNSPEC_103_H 1
-/* $Id: unspec_103.h,v 1.13.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: unspec_103.h,v 1.17 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_unspec_t {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c
index 1199195..c496aaf 100644
--- a/lib/dns/rdata/generic/x25_19.c
+++ b/lib/dns/rdata/generic/x25_19.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: x25_19.c,v 1.35.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: x25_19.c,v 1.39 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 16:15:57 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/generic/x25_19.h b/lib/dns/rdata/generic/x25_19.h
index 32320d0..5ebc230 100644
--- a/lib/dns/rdata/generic/x25_19.h
+++ b/lib/dns/rdata/generic/x25_19.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef GENERIC_X25_19_H
#define GENERIC_X25_19_H 1
-/* $Id: x25_19.h,v 1.14.18.2 2005/04/29 00:16:40 marka Exp $ */
+/* $Id: x25_19.h,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1183 */
diff --git a/lib/dns/rdata/hs_4/a_1.c b/lib/dns/rdata/hs_4/a_1.c
index 5d3ddae..487e8bc 100644
--- a/lib/dns/rdata/hs_4/a_1.c
+++ b/lib/dns/rdata/hs_4/a_1.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: a_1.c,v 1.29 2004/03/05 05:10:20 marka Exp $ */
+/* $Id: a_1.c,v 1.31 2007/06/19 23:47:17 tbox Exp $ */
/* reviewed: Thu Mar 16 15:58:36 PST 2000 by brister */
diff --git a/lib/dns/rdata/hs_4/a_1.h b/lib/dns/rdata/hs_4/a_1.h
index 59f54b5..dee812f 100644
--- a/lib/dns/rdata/hs_4/a_1.h
+++ b/lib/dns/rdata/hs_4/a_1.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef HS_4_A_1_H
#define HS_4_A_1_H 1
-/* $Id: a_1.h,v 1.8.18.2 2005/04/29 00:16:41 marka Exp $ */
+/* $Id: a_1.h,v 1.12 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_hs_a {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/in_1/a6_38.c b/lib/dns/rdata/in_1/a6_38.c
index 50017e1..d4d42bb 100644
--- a/lib/dns/rdata/in_1/a6_38.c
+++ b/lib/dns/rdata/in_1/a6_38.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: a6_38.c,v 1.52 2004/03/05 05:10:23 marka Exp $ */
+/* $Id: a6_38.c,v 1.54 2007/06/19 23:47:17 tbox Exp $ */
/* RFC2874 */
diff --git a/lib/dns/rdata/in_1/a6_38.h b/lib/dns/rdata/in_1/a6_38.h
index bb15dad..75e53f1 100644
--- a/lib/dns/rdata/in_1/a6_38.h
+++ b/lib/dns/rdata/in_1/a6_38.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_A6_38_H
#define IN_1_A6_38_H 1
-/* $Id: a6_38.h,v 1.20.18.2 2005/04/29 00:16:41 marka Exp $ */
+/* $Id: a6_38.h,v 1.24 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC2874 */
diff --git a/lib/dns/rdata/in_1/a_1.c b/lib/dns/rdata/in_1/a_1.c
index e8cb8ce..d7644bc 100644
--- a/lib/dns/rdata/in_1/a_1.c
+++ b/lib/dns/rdata/in_1/a_1.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: a_1.c,v 1.51 2004/03/05 05:10:23 marka Exp $ */
+/* $Id: a_1.c,v 1.53 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/in_1/a_1.h b/lib/dns/rdata/in_1/a_1.h
index d92a973..c192d1a 100644
--- a/lib/dns/rdata/in_1/a_1.h
+++ b/lib/dns/rdata/in_1/a_1.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef IN_1_A_1_H
#define IN_1_A_1_H 1
-/* $Id: a_1.h,v 1.24.18.2 2005/04/29 00:16:41 marka Exp $ */
+/* $Id: a_1.h,v 1.28 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_in_a {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/in_1/aaaa_28.c b/lib/dns/rdata/in_1/aaaa_28.c
index 1dd32cf..d0503a9 100644
--- a/lib/dns/rdata/in_1/aaaa_28.c
+++ b/lib/dns/rdata/in_1/aaaa_28.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: aaaa_28.c,v 1.41.18.2 2005/04/29 00:16:41 marka Exp $ */
+/* $Id: aaaa_28.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/in_1/aaaa_28.h b/lib/dns/rdata/in_1/aaaa_28.h
index 31ad6a6..54a0cb3 100644
--- a/lib/dns/rdata/in_1/aaaa_28.h
+++ b/lib/dns/rdata/in_1/aaaa_28.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_AAAA_28_H
#define IN_1_AAAA_28_H 1
-/* $Id: aaaa_28.h,v 1.17.18.2 2005/04/29 00:16:42 marka Exp $ */
+/* $Id: aaaa_28.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1886 */
diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c
index 2fce328..28ca68e 100644
--- a/lib/dns/rdata/in_1/apl_42.c
+++ b/lib/dns/rdata/in_1/apl_42.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: apl_42.c,v 1.8.18.4 2008/01/22 23:27:06 tbox Exp $ */
+/* $Id: apl_42.c,v 1.14 2008/01/22 23:28:04 tbox Exp $ */
/* RFC3123 */
diff --git a/lib/dns/rdata/in_1/apl_42.h b/lib/dns/rdata/in_1/apl_42.h
index d434ace..2d01040 100644
--- a/lib/dns/rdata/in_1/apl_42.h
+++ b/lib/dns/rdata/in_1/apl_42.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -19,7 +19,7 @@
#ifndef IN_1_APL_42_H
#define IN_1_APL_42_H 1
-/* $Id: apl_42.h,v 1.2.18.2 2005/04/29 00:16:42 marka Exp $ */
+/* $Id: apl_42.h,v 1.6 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_apl_ent {
isc_boolean_t negative;
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..27c4e4e
--- /dev/null
+++ b/lib/dns/rdata/in_1/dhcid_49.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: dhcid_49.c,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
+
+/* RFC 4701 */
+
+#ifndef RDATA_IN_1_DHCID_49_C
+#define RDATA_IN_1_DHCID_49_C 1
+
+#define RRTYPE_DHCID_ATTRIBUTES 0
+
+static inline isc_result_t
+fromtext_in_dhcid(ARGS_FROMTEXT) {
+
+ REQUIRE(type == 49);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_in_dhcid(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof(" ; 64000 255 64000")];
+ size_t n;
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext("( " /*)*/, target));
+ RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak,
+ target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(/* ( */ " )", target));
+ if (rdata->length > 2) {
+ n = snprintf(buf, sizeof(buf), " ; %u %u %u",
+ sr.base[0] * 256 + sr.base[1],
+ sr.base[2], rdata->length - 3);
+ INSIST(n < sizeof(buf));
+ RETERR(str_totext(buf, target));
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_in_dhcid(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 49);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length == 0)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_in_dhcid(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_in_dhcid(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 49);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_in_dhcid(ARGS_FROMSTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = source;
+
+ REQUIRE(type == 49);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(dhcid->common.rdtype == type);
+ REQUIRE(dhcid->common.rdclass == rdclass);
+ REQUIRE(dhcid->length != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, dhcid->dhcid, dhcid->length));
+}
+
+static inline isc_result_t
+tostruct_in_dhcid(ARGS_TOSTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ dhcid->common.rdclass = rdata->rdclass;
+ dhcid->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dhcid->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dhcid->dhcid = mem_maybedup(mctx, region.base, region.length);
+ if (dhcid->dhcid == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dhcid->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_dhcid(ARGS_FREESTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = source;
+
+ REQUIRE(dhcid != NULL);
+ REQUIRE(dhcid->common.rdtype == 49);
+ REQUIRE(dhcid->common.rdclass == 1);
+
+ if (dhcid->mctx == NULL)
+ return;
+
+ if (dhcid->dhcid != NULL)
+ isc_mem_free(dhcid->mctx, dhcid->dhcid);
+ dhcid->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_dhcid(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_dhcid(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_in_dhcid(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 49);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_in_dhcid(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#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..2797192
--- /dev/null
+++ b/lib/dns/rdata/in_1/dhcid_49.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 IN_1_DHCID_49_H
+#define IN_1_DHCID_49_H 1
+
+/* $Id: dhcid_49.h,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_in_dhcid {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *dhcid;
+ unsigned int length;
+} dns_rdata_in_dhcid_t;
+
+#endif /* IN_1_DHCID_49_H */
diff --git a/lib/dns/rdata/in_1/kx_36.c b/lib/dns/rdata/in_1/kx_36.c
index 8a64aac..9df2e5e 100644
--- a/lib/dns/rdata/in_1/kx_36.c
+++ b/lib/dns/rdata/in_1/kx_36.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: kx_36.c,v 1.41.18.2 2005/04/29 00:16:42 marka Exp $ */
+/* $Id: kx_36.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Thu Mar 16 17:24:54 PST 2000 by explorer */
diff --git a/lib/dns/rdata/in_1/kx_36.h b/lib/dns/rdata/in_1/kx_36.h
index c44883d..391ae27 100644
--- a/lib/dns/rdata/in_1/kx_36.h
+++ b/lib/dns/rdata/in_1/kx_36.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_KX_36_H
#define IN_1_KX_36_H 1
-/* $Id: kx_36.h,v 1.16.18.2 2005/04/29 00:16:42 marka Exp $ */
+/* $Id: kx_36.h,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC2230 */
diff --git a/lib/dns/rdata/in_1/naptr_35.c b/lib/dns/rdata/in_1/naptr_35.c
index 9a880ea..21ab44c 100644
--- a/lib/dns/rdata/in_1/naptr_35.c
+++ b/lib/dns/rdata/in_1/naptr_35.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: naptr_35.c,v 1.47.18.4 2008/02/15 23:45:53 tbox Exp $ */
+/* $Id: naptr_35.c,v 1.53 2008/02/15 23:46:51 tbox Exp $ */
/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/in_1/naptr_35.h b/lib/dns/rdata/in_1/naptr_35.h
index 2578b48..503f7a8 100644
--- a/lib/dns/rdata/in_1/naptr_35.h
+++ b/lib/dns/rdata/in_1/naptr_35.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_NAPTR_35_H
#define IN_1_NAPTR_35_H 1
-/* $Id: naptr_35.h,v 1.19.18.2 2005/04/29 00:16:42 marka Exp $ */
+/* $Id: naptr_35.h,v 1.23 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC2915 */
diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.c b/lib/dns/rdata/in_1/nsap-ptr_23.c
index 1a65cbe..2da7869 100644
--- a/lib/dns/rdata/in_1/nsap-ptr_23.c
+++ b/lib/dns/rdata/in_1/nsap-ptr_23.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsap-ptr_23.c,v 1.34.18.2 2005/04/29 00:16:42 marka Exp $ */
+/* $Id: nsap-ptr_23.c,v 1.38 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Fri Mar 17 10:16:02 PST 2000 by gson */
diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.h b/lib/dns/rdata/in_1/nsap-ptr_23.h
index bd8e025..14a8b19 100644
--- a/lib/dns/rdata/in_1/nsap-ptr_23.h
+++ b/lib/dns/rdata/in_1/nsap-ptr_23.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_NSAP_PTR_23_H
#define IN_1_NSAP_PTR_23_H 1
-/* $Id: nsap-ptr_23.h,v 1.15.18.2 2005/04/29 00:16:43 marka Exp $ */
+/* $Id: nsap-ptr_23.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1348. Obsoleted in RFC 1706 - use PTR instead. */
diff --git a/lib/dns/rdata/in_1/nsap_22.c b/lib/dns/rdata/in_1/nsap_22.c
index a348a30..c25f560 100644
--- a/lib/dns/rdata/in_1/nsap_22.c
+++ b/lib/dns/rdata/in_1/nsap_22.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsap_22.c,v 1.38.18.2 2005/04/29 00:16:43 marka Exp $ */
+/* $Id: nsap_22.c,v 1.42 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Fri Mar 17 10:41:07 PST 2000 by gson */
diff --git a/lib/dns/rdata/in_1/nsap_22.h b/lib/dns/rdata/in_1/nsap_22.h
index 583fbac..11e3f66 100644
--- a/lib/dns/rdata/in_1/nsap_22.h
+++ b/lib/dns/rdata/in_1/nsap_22.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_NSAP_22_H
#define IN_1_NSAP_22_H 1
-/* $Id: nsap_22.h,v 1.14.18.2 2005/04/29 00:16:43 marka Exp $ */
+/* $Id: nsap_22.h,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC1706 */
diff --git a/lib/dns/rdata/in_1/px_26.c b/lib/dns/rdata/in_1/px_26.c
index 3df9b99..1d17f2f 100644
--- a/lib/dns/rdata/in_1/px_26.c
+++ b/lib/dns/rdata/in_1/px_26.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: px_26.c,v 1.39.18.2 2005/04/29 00:16:43 marka Exp $ */
+/* $Id: px_26.c,v 1.43 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Mon Mar 20 10:44:27 PST 2000 */
diff --git a/lib/dns/rdata/in_1/px_26.h b/lib/dns/rdata/in_1/px_26.h
index a38d5f81..69a7bae 100644
--- a/lib/dns/rdata/in_1/px_26.h
+++ b/lib/dns/rdata/in_1/px_26.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_PX_26_H
#define IN_1_PX_26_H 1
-/* $Id: px_26.h,v 1.15.18.2 2005/04/29 00:16:43 marka Exp $ */
+/* $Id: px_26.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
/*!
* \brief Per RFC2163 */
diff --git a/lib/dns/rdata/in_1/srv_33.c b/lib/dns/rdata/in_1/srv_33.c
index 2925a77..7bc85cd 100644
--- a/lib/dns/rdata/in_1/srv_33.c
+++ b/lib/dns/rdata/in_1/srv_33.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: srv_33.c,v 1.41.18.2 2005/04/29 00:16:43 marka Exp $ */
+/* $Id: srv_33.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Fri Mar 17 13:01:00 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/in_1/srv_33.h b/lib/dns/rdata/in_1/srv_33.h
index 7d9fef6..e019698 100644
--- a/lib/dns/rdata/in_1/srv_33.h
+++ b/lib/dns/rdata/in_1/srv_33.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_SRV_33_H
#define IN_1_SRV_33_H 1
-/* $Id: srv_33.h,v 1.15.18.2 2005/04/29 00:16:43 marka Exp $ */
+/* $Id: srv_33.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
/* Reviewed: Fri Mar 17 13:01:00 PST 2000 by bwelling */
diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c
index 749b8fd..55859c4 100644
--- a/lib/dns/rdata/in_1/wks_11.c
+++ b/lib/dns/rdata/in_1/wks_11.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: wks_11.c,v 1.51.18.1 2004/09/16 01:02:19 marka Exp $ */
+/* $Id: wks_11.c,v 1.54.332.2 2009/02/16 23:47:15 tbox Exp $ */
/* Reviewed: Fri Mar 17 15:01:49 PST 2000 by explorer */
@@ -158,6 +158,7 @@ totext_in_wks(ARGS_TOTEXT) {
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++)
@@ -242,7 +243,8 @@ fromstruct_in_wks(ARGS_FROMSTRUCT) {
REQUIRE(source != NULL);
REQUIRE(wks->common.rdtype == type);
REQUIRE(wks->common.rdclass == rdclass);
- REQUIRE(wks->map != NULL || wks->map_len == 0);
+ REQUIRE((wks->map != NULL && wks->map_len <= 8*1024) ||
+ wks->map_len == 0);
UNUSED(type);
UNUSED(rdclass);
diff --git a/lib/dns/rdata/in_1/wks_11.h b/lib/dns/rdata/in_1/wks_11.h
index a0093b9..2fd26e8 100644
--- a/lib/dns/rdata/in_1/wks_11.h
+++ b/lib/dns/rdata/in_1/wks_11.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
#ifndef IN_1_WKS_11_H
#define IN_1_WKS_11_H 1
-/* $Id: wks_11.h,v 1.20 2004/03/05 05:10:25 marka Exp $ */
+/* $Id: wks_11.h,v 1.22 2007/06/19 23:47:17 tbox Exp $ */
typedef struct dns_rdata_in_wks {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/rdatastructpre.h b/lib/dns/rdata/rdatastructpre.h
index d641ef5..ab7e051 100644
--- a/lib/dns/rdata/rdatastructpre.h
+++ b/lib/dns/rdata/rdatastructpre.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatastructpre.h,v 1.14 2004/03/05 05:10:04 marka Exp $ */
+/* $Id: rdatastructpre.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
#ifndef DNS_RDATASTRUCT_H
#define DNS_RDATASTRUCT_H 1
diff --git a/lib/dns/rdata/rdatastructsuf.h b/lib/dns/rdata/rdatastructsuf.h
index 1ab1b0a..3ba1275 100644
--- a/lib/dns/rdata/rdatastructsuf.h
+++ b/lib/dns/rdata/rdatastructsuf.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatastructsuf.h,v 1.8 2004/03/05 05:10:04 marka Exp $ */
+/* $Id: rdatastructsuf.h,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
ISC_LANG_ENDDECLS
diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c
index 7229fa3..d6f11ae 100644
--- a/lib/dns/rdatalist.c
+++ b/lib/dns/rdatalist.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatalist.c,v 1.28.18.3 2005/04/29 00:16:02 marka Exp $ */
+/* $Id: rdatalist.c,v 1.36 2008/09/24 02:46:22 marka Exp $ */
/*! \file */
@@ -26,6 +26,7 @@
#include <isc/util.h>
#include <dns/name.h>
+#include <dns/nsec3.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
@@ -41,6 +42,8 @@ static dns_rdatasetmethods_t methods = {
isc__rdatalist_count,
isc__rdatalist_addnoqname,
isc__rdatalist_getnoqname,
+ isc__rdatalist_addclosest,
+ isc__rdatalist_getclosest,
NULL,
NULL,
NULL
@@ -63,8 +66,8 @@ dns_rdatalist_init(dns_rdatalist_t *rdatalist) {
isc_result_t
dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
- dns_rdataset_t *rdataset) {
-
+ dns_rdataset_t *rdataset)
+{
/*
* Make 'rdataset' refer to the rdata in 'rdatalist'.
*/
@@ -88,6 +91,16 @@ dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
return (ISC_R_SUCCESS);
}
+isc_result_t
+dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
+ dns_rdatalist_t **rdatalist)
+{
+ REQUIRE(rdatalist != NULL && rdataset != NULL);
+ *rdatalist = rdataset->private1;
+
+ return (ISC_R_SUCCESS);
+}
+
void
isc__rdatalist_disassociate(dns_rdataset_t *rdataset) {
UNUSED(rdataset);
@@ -161,8 +174,8 @@ isc__rdatalist_count(dns_rdataset_t *rdataset) {
isc_result_t
isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
- dns_rdataset_t *nsec = NULL;
- dns_rdataset_t *nsecsig = NULL;
+ dns_rdataset_t *neg = NULL;
+ dns_rdataset_t *negsig = NULL;
dns_rdataset_t *rdset;
dns_ttl_t ttl;
@@ -172,24 +185,33 @@ isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
{
if (rdset->rdclass != rdataset->rdclass)
continue;
- if (rdset->type == dns_rdatatype_nsec)
- nsec = rdset;
+ if (rdset->type == dns_rdatatype_nsec ||
+ rdset->type == dns_rdatatype_nsec3)
+ neg = rdset;
+ }
+ if (neg == NULL)
+ return (ISC_R_NOTFOUND);
+
+ for (rdset = ISC_LIST_HEAD(name->list);
+ rdset != NULL;
+ rdset = ISC_LIST_NEXT(rdset, link))
+ {
if (rdset->type == dns_rdatatype_rrsig &&
- rdset->covers == dns_rdatatype_nsec)
- nsecsig = rdset;
+ rdset->covers == neg->type)
+ negsig = rdset;
}
- if (nsec == NULL || nsecsig == NULL)
+ if (negsig == NULL)
return (ISC_R_NOTFOUND);
/*
* Minimise ttl.
*/
ttl = rdataset->ttl;
- if (nsec->ttl < ttl)
- ttl = nsec->ttl;
- if (nsecsig->ttl < ttl)
- ttl = nsecsig->ttl;
- rdataset->ttl = nsec->ttl = nsecsig->ttl = ttl;
+ if (neg->ttl < ttl)
+ ttl = neg->ttl;
+ if (negsig->ttl < ttl)
+ ttl = negsig->ttl;
+ rdataset->ttl = neg->ttl = negsig->ttl = ttl;
rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
rdataset->private6 = name;
return (ISC_R_SUCCESS);
@@ -197,11 +219,11 @@ isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
isc_result_t
isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
- dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
+ dns_rdataset_t *neg, dns_rdataset_t *negsig)
{
dns_rdataclass_t rdclass = rdataset->rdclass;
- dns_rdataset_t *tnsec = NULL;
- dns_rdataset_t *tnsecsig = NULL;
+ dns_rdataset_t *tneg = NULL;
+ dns_rdataset_t *tnegsig = NULL;
dns_name_t *noqname = rdataset->private6;
REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0);
@@ -213,17 +235,113 @@ isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
{
if (rdataset->rdclass != rdclass)
continue;
- if (rdataset->type == dns_rdatatype_nsec)
- tnsec = rdataset;
+ if (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3)
+ tneg = rdataset;
+ }
+ if (tneg == NULL)
+ return (ISC_R_NOTFOUND);
+
+ for (rdataset = ISC_LIST_HEAD(noqname->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
if (rdataset->type == dns_rdatatype_rrsig &&
- rdataset->covers == dns_rdatatype_nsec)
- tnsecsig = rdataset;
+ rdataset->covers == tneg->type)
+ tnegsig = rdataset;
}
- if (tnsec == NULL || tnsecsig == NULL)
+ if (tnegsig == NULL)
return (ISC_R_NOTFOUND);
dns_name_clone(noqname, name);
- dns_rdataset_clone(tnsec, nsec);
- dns_rdataset_clone(tnsecsig, nsecsig);
+ dns_rdataset_clone(tneg, neg);
+ dns_rdataset_clone(tnegsig, negsig);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
+ dns_rdataset_t *neg = NULL;
+ dns_rdataset_t *negsig = NULL;
+ dns_rdataset_t *rdset;
+ dns_ttl_t ttl;
+
+ for (rdset = ISC_LIST_HEAD(name->list);
+ rdset != NULL;
+ rdset = ISC_LIST_NEXT(rdset, link))
+ {
+ if (rdset->rdclass != rdataset->rdclass)
+ continue;
+ if (rdset->type == dns_rdatatype_nsec ||
+ rdset->type == dns_rdatatype_nsec3)
+ neg = rdset;
+ }
+ if (neg == NULL)
+ return (ISC_R_NOTFOUND);
+
+ for (rdset = ISC_LIST_HEAD(name->list);
+ rdset != NULL;
+ rdset = ISC_LIST_NEXT(rdset, link))
+ {
+ if (rdset->type == dns_rdatatype_rrsig &&
+ rdset->covers == neg->type)
+ negsig = rdset;
+ }
+
+ if (negsig == NULL)
+ return (ISC_R_NOTFOUND);
+ /*
+ * Minimise ttl.
+ */
+ ttl = rdataset->ttl;
+ if (neg->ttl < ttl)
+ ttl = neg->ttl;
+ if (negsig->ttl < ttl)
+ ttl = negsig->ttl;
+ rdataset->ttl = neg->ttl = negsig->ttl = ttl;
+ rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
+ rdataset->private7 = name;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig)
+{
+ dns_rdataclass_t rdclass = rdataset->rdclass;
+ dns_rdataset_t *tneg = NULL;
+ dns_rdataset_t *tnegsig = NULL;
+ dns_name_t *closest = rdataset->private7;
+
+ REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0);
+ (void)dns_name_dynamic(closest); /* Sanity Check. */
+
+ for (rdataset = ISC_LIST_HEAD(closest->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->rdclass != rdclass)
+ continue;
+ if (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3)
+ tneg = rdataset;
+ }
+ if (tneg == NULL)
+ return (ISC_R_NOTFOUND);
+
+ for (rdataset = ISC_LIST_HEAD(closest->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type == dns_rdatatype_rrsig &&
+ rdataset->covers == tneg->type)
+ tnegsig = rdataset;
+ }
+ if (tnegsig == NULL)
+ return (ISC_R_NOTFOUND);
+
+ dns_name_clone(closest, name);
+ dns_rdataset_clone(tneg, neg);
+ dns_rdataset_clone(tnegsig, negsig);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/rdatalist_p.h b/lib/dns/rdatalist_p.h
index d697fec..3e73e20 100644
--- a/lib/dns/rdatalist_p.h
+++ b/lib/dns/rdatalist_p.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatalist_p.h,v 1.5.18.2 2005/04/29 00:16:03 marka Exp $ */
+/* $Id: rdatalist_p.h,v 1.11 2008/09/25 04:02:38 tbox Exp $ */
#ifndef DNS_RDATALIST_P_H
#define DNS_RDATALIST_P_H
@@ -50,7 +50,14 @@ isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name);
isc_result_t
isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
- dns_rdataset_t *nsec, dns_rdataset_t *nsecsig);
+ dns_rdataset_t *neg, dns_rdataset_t *negsig);
+
+isc_result_t
+isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name);
+
+isc_result_t
+isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig);
ISC_LANG_ENDDECLS
diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c
index c86b3c5..6088a06 100644
--- a/lib/dns/rdataset.c
+++ b/lib/dns/rdataset.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataset.c,v 1.72.18.5 2006/03/02 00:37:21 marka Exp $ */
+/* $Id: rdataset.c,v 1.82.50.2 2009/01/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -59,6 +59,7 @@ dns_rdataset_init(dns_rdataset_t *rdataset) {
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
rdataset->private6 = NULL;
+ rdataset->resign = 0;
}
void
@@ -137,7 +138,7 @@ question_disassociate(dns_rdataset_t *rdataset) {
static isc_result_t
question_cursor(dns_rdataset_t *rdataset) {
UNUSED(rdataset);
-
+
return (ISC_R_NOMORE);
}
@@ -148,7 +149,7 @@ question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
*/
UNUSED(rdataset);
UNUSED(rdata);
-
+
REQUIRE(0);
}
@@ -179,6 +180,8 @@ static dns_rdatasetmethods_t question_methods = {
NULL,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
@@ -339,7 +342,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
}
/*
- * Do we want to shuffle this anwer?
+ * Do we want to shuffle this answer?
*/
if (!question && count > 1 &&
(!WANT_FIXED(rdataset) || order != NULL) &&
@@ -445,7 +448,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
/*
* Copy out the name, type, class, ttl.
*/
-
+
rrbuffer = *target;
dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
result = dns_name_towire(owner_name, cctx, target);
@@ -620,14 +623,36 @@ dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
- dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
+ dns_rdataset_t *neg, dns_rdataset_t *negsig)
{
REQUIRE(DNS_RDATASET_VALID(rdataset));
REQUIRE(rdataset->methods != NULL);
if (rdataset->methods->getnoqname == NULL)
return (ISC_R_NOTIMPLEMENTED);
- return((rdataset->methods->getnoqname)(rdataset, name, nsec, nsecsig));
+ return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig));
+}
+
+isc_result_t
+dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+ if (rdataset->methods->addclosest == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+ return((rdataset->methods->addclosest)(rdataset, name));
+}
+
+isc_result_t
+dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig)
+{
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ if (rdataset->methods->getclosest == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+ return((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
}
/*
diff --git a/lib/dns/rdatasetiter.c b/lib/dns/rdatasetiter.c
index 8089e04..7ed3030 100644
--- a/lib/dns/rdatasetiter.c
+++ b/lib/dns/rdatasetiter.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatasetiter.c,v 1.12.18.2 2005/04/29 00:16:03 marka Exp $ */
+/* $Id: rdatasetiter.c,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c
index 5d89d01..b22868d 100644
--- a/lib/dns/rdataslab.c
+++ b/lib/dns/rdataslab.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataslab.c,v 1.35.18.8 2007/08/28 07:20:05 tbox Exp $ */
+/* $Id: rdataslab.c,v 1.48.50.2 2009/01/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -33,10 +33,6 @@
#include <dns/rdataset.h>
#include <dns/rdataslab.h>
-#ifndef DNS_RDATASET_FIXED
-#define DNS_RDATASET_FIXED 1
-#endif
-
/*
* The rdataslab structure allows iteration to occur in both load order
* and DNSSEC order. The structure is as follows:
@@ -47,6 +43,7 @@
* data records
* data length (2 bytes)
* order (2 bytes)
+ * meta data (1 byte for RRSIG's)
* data (data length bytes)
*
* If DNS_RDATASET_FIXED is defined to be zero (0) the format of a
@@ -65,7 +62,7 @@
*
* DNSSEC order traversal is performed by walking the data records.
*
- * The order is stored with record to allow for efficient reconstuction of
+ * The order is stored with record to allow for efficient reconstruction
* of the offset table following a merge or subtraction.
*
* The iterator methods here currently only support DNSSEC order iteration.
@@ -141,6 +138,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
#if DNS_RDATASET_FIXED
unsigned int *offsettable;
#endif
+ unsigned int length;
buflen = reservelen + 2;
@@ -209,12 +207,18 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
x[i].order = x[i-1].order;
#endif
nitems--;
- } else
+ } else {
#if DNS_RDATASET_FIXED
buflen += (8 + x[i-1].rdata.length);
#else
buflen += (2 + x[i-1].rdata.length);
#endif
+ /*
+ * Provide space to store the per RR meta data.
+ */
+ if (rdataset->type == dns_rdatatype_rrsig)
+ buflen++;
+ }
}
/*
* Don't forget the last item!
@@ -224,6 +228,11 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
#else
buflen += (2 + x[i-1].rdata.length);
#endif
+ /*
+ * Provide space to store the per RR meta data.
+ */
+ if (rdataset->type == dns_rdatatype_rrsig)
+ buflen++;
/*
* Ensure that singleton types are actually singletons.
@@ -246,7 +255,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
result = ISC_R_NOMEMORY;
goto free_rdatas;
}
-
+
#if DNS_RDATASET_FIXED
/* Allocate temporary offset table. */
offsettable = isc_mem_get(mctx, nalloc * sizeof(unsigned int));
@@ -280,15 +289,25 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
#if DNS_RDATASET_FIXED
offsettable[x[i].order] = rawbuf - offsetbase;
#endif
- *rawbuf++ = (x[i].rdata.length & 0xff00) >> 8;
- *rawbuf++ = (x[i].rdata.length & 0x00ff);
+ length = x[i].rdata.length;
+ if (rdataset->type == dns_rdatatype_rrsig)
+ length++;
+ *rawbuf++ = (length & 0xff00) >> 8;
+ *rawbuf++ = (length & 0x00ff);
#if DNS_RDATASET_FIXED
rawbuf += 2; /* filled in later */
#endif
+ /*
+ * Store the per RR meta data.
+ */
+ if (rdataset->type == dns_rdatatype_rrsig) {
+ *rawbuf++ |= (x[i].rdata.flags & DNS_RDATA_OFFLINE) ?
+ DNS_RDATASLAB_OFFLINE : 0;
+ }
memcpy(rawbuf, x[i].rdata.data, x[i].rdata.length);
rawbuf += x[i].rdata.length;
}
-
+
#if DNS_RDATASET_FIXED
fillin_offsets(offsetbase, offsettable, nalloc);
isc_mem_put(mctx, offsettable, nalloc * sizeof(unsigned int));
@@ -360,17 +379,27 @@ static void
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
unsigned char *raw = rdataset->private5;
isc_region_t r;
+ unsigned int length;
+ unsigned int flags = 0;
REQUIRE(raw != NULL);
- r.length = raw[0] * 256 + raw[1];
+ length = raw[0] * 256 + raw[1];
#if DNS_RDATASET_FIXED
raw += 4;
#else
raw += 2;
-#endif
+#endif
+ if (rdataset->type == dns_rdatatype_rrsig) {
+ if (*raw & DNS_RDATASLAB_OFFLINE)
+ flags |= DNS_RDATA_OFFLINE;
+ length--;
+ raw++;
+ }
+ r.length = length;
r.base = raw;
dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
+ rdata->flags |= flags;
}
static void
@@ -405,6 +434,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
NULL,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
@@ -474,15 +505,27 @@ rdata_from_slab(unsigned char **current,
{
unsigned char *tcurrent = *current;
isc_region_t region;
+ unsigned int length;
+ isc_boolean_t offline = ISC_FALSE;
- region.length = *tcurrent++ * 256;
- region.length += *tcurrent++;
+ length = *tcurrent++ * 256;
+ length += *tcurrent++;
+
+ if (type == dns_rdatatype_rrsig) {
+ if ((*tcurrent & DNS_RDATASLAB_OFFLINE) != 0)
+ offline = ISC_TRUE;
+ length--;
+ tcurrent++;
+ }
+ region.length = length;
#if DNS_RDATASET_FIXED
tcurrent += 2;
#endif
region.base = tcurrent;
tcurrent += region.length;
dns_rdata_fromregion(rdata, rdclass, type, &region);
+ if (offline)
+ rdata->flags |= DNS_RDATA_OFFLINE;
*current = tcurrent;
}
@@ -511,7 +554,7 @@ rdata_in_slab(unsigned char *slab, unsigned int reservelen,
for (i = 0; i < count; i++) {
rdata_from_slab(&current, rdclass, type, &trdata);
-
+
n = dns_rdata_compare(&trdata, rdata);
if (n == 0)
return (ISC_TRUE);
@@ -528,9 +571,8 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
dns_rdataclass_t rdclass, dns_rdatatype_t type,
unsigned int flags, unsigned char **tslabp)
{
- unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent;
+ unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data;
unsigned int ocount, ncount, count, olength, tlength, tcount, length;
- isc_region_t nregion;
dns_rdata_t ordata = DNS_RDATA_INIT;
dns_rdata_t nrdata = DNS_RDATA_INIT;
isc_boolean_t added_something = ISC_FALSE;
@@ -603,29 +645,24 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
* the old slab.
*/
do {
- nregion.length = *ncurrent++ * 256;
- nregion.length += *ncurrent++;
-#if DNS_RDATASET_FIXED
- ncurrent += 2; /* Skip order. */
-#endif
- nregion.base = ncurrent;
dns_rdata_init(&nrdata);
- dns_rdata_fromregion(&nrdata, rdclass, type, &nregion);
+ rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata))
{
/*
* This rdata isn't in the old slab.
*/
#if DNS_RDATASET_FIXED
- tlength += nregion.length + 8;
+ tlength += nrdata.length + 8;
#else
- tlength += nregion.length + 2;
+ tlength += nrdata.length + 2;
#endif
+ if (type == dns_rdatatype_rrsig)
+ tlength++;
tcount++;
nncount++;
added_something = ISC_TRUE;
}
- ncurrent += nregion.length;
ncount--;
} while (ncount > 0);
ncount = nncount;
@@ -726,12 +763,17 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
offsettable[oorder] = tcurrent - offsetbase;
#endif
length = ordata.length;
+ data = ordata.data;
+ if (type == dns_rdatatype_rrsig) {
+ length++;
+ data--;
+ }
*tcurrent++ = (length & 0xff00) >> 8;
*tcurrent++ = (length & 0x00ff);
#if DNS_RDATASET_FIXED
tcurrent += 2; /* fill in later */
#endif
- memcpy(tcurrent, ordata.data, length);
+ memcpy(tcurrent, data, length);
tcurrent += length;
oadded++;
if (oadded < ocount) {
@@ -748,12 +790,17 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
offsettable[ocount + norder] = tcurrent - offsetbase;
#endif
length = nrdata.length;
+ data = nrdata.data;
+ if (type == dns_rdatatype_rrsig) {
+ length++;
+ data--;
+ }
*tcurrent++ = (length & 0xff00) >> 8;
*tcurrent++ = (length & 0x00ff);
#if DNS_RDATASET_FIXED
tcurrent += 2; /* fill in later */
#endif
- memcpy(tcurrent, nrdata.data, length);
+ memcpy(tcurrent, data, length);
tcurrent += length;
nadded++;
if (nadded < ncount) {
@@ -799,8 +846,8 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
#if DNS_RDATASET_FIXED
unsigned char *offsetbase;
unsigned int *offsettable;
-#endif
unsigned int order;
+#endif
REQUIRE(tslabp != NULL && *tslabp == NULL);
REQUIRE(mslab != NULL && sslab != NULL);
diff --git a/lib/dns/request.c b/lib/dns/request.c
index 64a3a4e..ac844e1 100644
--- a/lib/dns/request.c
+++ b/lib/dns/request.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: request.c,v 1.72.18.8 2008/07/22 03:51:44 marka Exp $ */
+/* $Id: request.c,v 1.82.72.2 2009/01/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -95,7 +95,7 @@ struct dns_request {
#define DNS_REQUEST_F_SENDING 0x0002
#define DNS_REQUEST_F_CANCELED 0x0004 /*%< ctlevent received, or otherwise
synchronously canceled */
-#define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< cancelled due to a timeout */
+#define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< canceled due to a timeout */
#define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */
#define DNS_REQUEST_CANCELED(r) \
(((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
@@ -197,7 +197,7 @@ dns_requestmgr_create(isc_mem_t *mctx,
dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
requestmgr->mctx = NULL;
isc_mem_attach(mctx, &requestmgr->mctx);
- requestmgr->eref = 1; /* implict attach */
+ requestmgr->eref = 1; /* implicit attach */
requestmgr->iref = 0;
ISC_LIST_INIT(requestmgr->whenshutdown);
ISC_LIST_INIT(requestmgr->requests);
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index dc648c9..a1c263e 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,15 +15,18 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.284.18.79 2008/10/17 22:02:13 jinmei Exp $ */
+/* $Id: resolver.c,v 1.384.14.12 2009/05/11 02:38:03 tbox Exp $ */
/*! \file */
#include <config.h>
+#include <isc/platform.h>
#include <isc/print.h>
#include <isc/string.h>
+#include <isc/random.h>
#include <isc/task.h>
+#include <isc/stats.h>
#include <isc/timer.h>
#include <isc/util.h>
@@ -52,22 +55,23 @@
#include <dns/resolver.h>
#include <dns/result.h>
#include <dns/rootns.h>
+#include <dns/stats.h>
#include <dns/tsig.h>
#include <dns/validator.h>
#define DNS_RESOLVER_TRACE
#ifdef DNS_RESOLVER_TRACE
-#define RTRACE(m) isc_log_write(dns_lctx, \
+#define RTRACE(m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
"res %p: %s", res, (m))
-#define RRTRACE(r, m) isc_log_write(dns_lctx, \
+#define RRTRACE(r, m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
"res %p: %s", (r), (m))
-#define FCTXTRACE(m) isc_log_write(dns_lctx, \
+#define FCTXTRACE(m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
@@ -79,14 +83,14 @@
ISC_LOG_DEBUG(3), \
"fctx %p(%s): %s %s", \
fctx, fctx->info, (m1), (m2))
-#define FTRACE(m) isc_log_write(dns_lctx, \
+#define FTRACE(m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
"fetch %p (fctx %p(%s)): %s", \
fetch, fetch->private, \
fetch->private->info, (m))
-#define QTRACE(m) isc_log_write(dns_lctx, \
+#define QTRACE(m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
@@ -104,13 +108,13 @@
/*%
* Maximum EDNS0 input packet size.
*/
-#define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
+#define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
/*%
* This defines the maximum number of timeouts we will permit before we
* disable EDNS0 on the query.
*/
-#define MAX_EDNS0_TIMEOUTS 3
+#define MAX_EDNS0_TIMEOUTS 3
typedef struct fetchctx fetchctx_t;
@@ -141,19 +145,25 @@ typedef struct query {
#define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
#define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
-#define RESQUERY_ATTR_CANCELED 0x02
+#define RESQUERY_ATTR_CANCELED 0x02
-#define RESQUERY_CONNECTING(q) ((q)->connects > 0)
-#define RESQUERY_CANCELED(q) (((q)->attributes & \
+#define RESQUERY_CONNECTING(q) ((q)->connects > 0)
+#define RESQUERY_CANCELED(q) (((q)->attributes & \
RESQUERY_ATTR_CANCELED) != 0)
-#define RESQUERY_SENDING(q) ((q)->sends > 0)
+#define RESQUERY_SENDING(q) ((q)->sends > 0)
typedef enum {
- fetchstate_init = 0, /*%< Start event has not run yet. */
+ fetchstate_init = 0, /*%< Start event has not run yet. */
fetchstate_active,
- fetchstate_done /*%< FETCHDONE events posted. */
+ fetchstate_done /*%< FETCHDONE events posted. */
} fetchstate;
+typedef enum {
+ badns_unreachable = 0,
+ badns_response,
+ badns_validation
+} badnstype_t;
+
struct fetchctx {
/*% Not locked. */
unsigned int magic;
@@ -162,7 +172,7 @@ struct fetchctx {
dns_rdatatype_t type;
unsigned int options;
unsigned int bucketnum;
- char * info;
+ char * info;
/*% Locked by appropriate bucket lock. */
fetchstate state;
isc_boolean_t want_shutdown;
@@ -170,8 +180,8 @@ struct fetchctx {
isc_boolean_t spilled;
unsigned int references;
isc_event_t control_event;
- ISC_LINK(struct fetchctx) link;
- ISC_LIST(dns_fetchevent_t) events;
+ ISC_LINK(struct fetchctx) link;
+ ISC_LIST(dns_fetchevent_t) events;
/*% Locked by task event serialization. */
dns_name_t domain;
dns_rdataset_t nameservers;
@@ -194,7 +204,7 @@ struct fetchctx {
isc_sockaddrlist_t edns;
isc_sockaddrlist_t edns512;
dns_validator_t *validator;
- ISC_LIST(dns_validator_t) validators;
+ ISC_LIST(dns_validator_t) validators;
dns_db_t * cache;
dns_adb_t * adb;
@@ -219,6 +229,7 @@ struct fetchctx {
* is used for EDNS0 black hole detection.
*/
unsigned int timeouts;
+
/*%
* Look aside state for DS lookups.
*/
@@ -230,34 +241,65 @@ struct fetchctx {
* Number of queries that reference this context.
*/
unsigned int nqueries;
+
+ /*%
+ * The reason to print when logging a successful
+ * response to a query.
+ */
+ const char * reason;
+
+ /*%
+ * Random numbers to use for mixing up server addresses.
+ */
+ isc_uint32_t rand_buf;
+ isc_uint32_t rand_bits;
+
+ /*%
+ * Fetch-local statistics for detailed logging.
+ */
+ isc_result_t result; /*%< fetch result */
+ isc_result_t vresult; /*%< validation result */
+ int exitline;
+ isc_time_t start;
+ isc_uint64_t duration;
+ isc_boolean_t logged;
+ unsigned int querysent;
+ unsigned int referrals;
+ unsigned int lamecount;
+ unsigned int neterr;
+ unsigned int badresp;
+ unsigned int adberr;
+ unsigned int findfail;
+ unsigned int valfail;
+ isc_boolean_t timeout;
};
#define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
#define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
-#define FCTX_ATTR_HAVEANSWER 0x0001
-#define FCTX_ATTR_GLUING 0x0002
-#define FCTX_ATTR_ADDRWAIT 0x0004
-#define FCTX_ATTR_SHUTTINGDOWN 0x0008
-#define FCTX_ATTR_WANTCACHE 0x0010
-#define FCTX_ATTR_WANTNCACHE 0x0020
-#define FCTX_ATTR_NEEDEDNS0 0x0040
-#define FCTX_ATTR_TRIEDFIND 0x0080
-#define FCTX_ATTR_TRIEDALT 0x0100
-
-#define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
+#define FCTX_ATTR_HAVEANSWER 0x0001
+#define FCTX_ATTR_GLUING 0x0002
+#define FCTX_ATTR_ADDRWAIT 0x0004
+#define FCTX_ATTR_SHUTTINGDOWN 0x0008
+#define FCTX_ATTR_WANTCACHE 0x0010
+#define FCTX_ATTR_WANTNCACHE 0x0020
+#define FCTX_ATTR_NEEDEDNS0 0x0040
+#define FCTX_ATTR_TRIEDFIND 0x0080
+#define FCTX_ATTR_TRIEDALT 0x0100
+
+#define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
0)
-#define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
+#define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
0)
-#define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
+#define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
0)
-#define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
+#define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
!= 0)
-#define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
-#define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
-#define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
-#define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
-#define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
+#define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
+#define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
+#define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
+#define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
+#define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
typedef struct {
dns_adbaddrinfo_t * addrinfo;
@@ -282,14 +324,14 @@ typedef struct fctxbucket {
typedef struct alternate {
isc_boolean_t isaddress;
- union {
+ union {
isc_sockaddr_t addr;
struct {
- dns_name_t name;
- in_port_t port;
+ dns_name_t name;
+ in_port_t port;
} _n;
} _u;
- ISC_LINK(struct alternate) link;
+ ISC_LINK(struct alternate) link;
} alternate_t;
struct dns_resolver {
@@ -311,6 +353,7 @@ struct dns_resolver {
isc_boolean_t exclusivev4;
dns_dispatch_t * dispatchv6;
isc_boolean_t exclusivev6;
+ unsigned int ndisps;
unsigned int nbuckets;
fctxbucket_t * buckets;
isc_uint32_t lame_ttl;
@@ -328,6 +371,7 @@ struct dns_resolver {
unsigned int spillatmin;
isc_timer_t * spillattimer;
isc_boolean_t zero_no_soa_ttl;
+
/* Locked by lock. */
unsigned int references;
isc_boolean_t exiting;
@@ -335,6 +379,7 @@ struct dns_resolver {
unsigned int activebuckets;
isc_boolean_t priming;
unsigned int spillat; /* clients-per-query */
+ unsigned int nextdisp;
/* Locked by primelock. */
dns_fetch_t * primefetch;
/* Locked by nlock. */
@@ -348,34 +393,45 @@ struct dns_resolver {
* Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
* which we also use as an addrinfo flag.
*/
-#define FCTX_ADDRINFO_MARK 0x0001
-#define FCTX_ADDRINFO_FORWARDER 0x1000
-#define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
+#define FCTX_ADDRINFO_MARK 0x0001
+#define FCTX_ADDRINFO_FORWARDER 0x1000
+#define FCTX_ADDRINFO_TRIED 0x2000
+#define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
== 0)
-#define ISFORWARDER(a) (((a)->flags & \
+#define ISFORWARDER(a) (((a)->flags & \
FCTX_ADDRINFO_FORWARDER) != 0)
+#define TRIED(a) (((a)->flags & \
+ FCTX_ADDRINFO_TRIED) != 0)
#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
-#define dns_db_transfernode(a,b,c) do { (*c) = (*b); (*b) = NULL; } while (0)
-
static void destroy(dns_resolver_t *res);
static void empty_bucket(dns_resolver_t *res);
static isc_result_t resquery_send(resquery_t *query);
static void resquery_response(isc_task_t *task, isc_event_t *event);
static void resquery_connected(isc_task_t *task, isc_event_t *event);
-static void fctx_try(fetchctx_t *fctx);
+static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying);
static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
static isc_result_t ncache_adderesult(dns_message_t *message,
dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers,
isc_stdtime_t now, dns_ttl_t maxttl,
+ isc_boolean_t optout,
dns_rdataset_t *ardataset,
isc_result_t *eresultp);
static void validated(isc_task_t *task, isc_event_t *event);
static void maybe_destroy(fetchctx_t *fctx);
static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
- isc_result_t reason);
+ isc_result_t reason, badnstype_t badtype);
+
+/*%
+ * Increment resolver-related statistics counters.
+ */
+static inline void
+inc_stats(dns_resolver_t *res, isc_statscounter_t counter) {
+ if (res->view->resstats != NULL)
+ isc_stats_increment(res->view->resstats, counter);
+}
static isc_result_t
valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
@@ -403,6 +459,7 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
valoptions, task, validated, valarg,
&validator);
if (result == ISC_R_SUCCESS) {
+ inc_stats(fctx->res, dns_resstatscounter_val);
if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
INSIST(fctx->validator == NULL);
fctx->validator = validator;
@@ -522,21 +579,20 @@ fctx_stoptimer(fetchctx_t *fctx) {
static inline isc_result_t
-fctx_startidletimer(fetchctx_t *fctx) {
+fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
/*
* Start the idle timer for fctx. The lifetime timer continues
* to be in effect.
*/
return (isc_timer_reset(fctx->timer, isc_timertype_once,
- &fctx->expires, &fctx->interval,
- ISC_FALSE));
+ &fctx->expires, interval, ISC_FALSE));
}
/*
* Stopping the idle timer is equivalent to calling fctx_starttimer(), but
* we use fctx_stopidletimer for readability in the code below.
*/
-#define fctx_stopidletimer fctx_starttimer
+#define fctx_stopidletimer fctx_starttimer
static inline void
@@ -551,7 +607,7 @@ resquery_destroy(resquery_t **queryp) {
query->fctx->nqueries--;
if (SHUTTINGDOWN(query->fctx))
- maybe_destroy(query->fctx); /* Locks bucket. */
+ maybe_destroy(query->fctx); /* Locks bucket. */
query->magic = 0;
isc_mem_put(query->mctx, query, sizeof(*query));
*queryp = NULL;
@@ -563,7 +619,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
{
fetchctx_t *fctx;
resquery_t *query;
- unsigned int rtt;
+ unsigned int rtt, rttms;
unsigned int factor;
dns_adbfind_t *find;
dns_adbaddrinfo_t *addrinfo;
@@ -590,6 +646,27 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
rtt = (unsigned int)isc_time_microdiff(finish,
&query->start);
factor = DNS_ADB_RTTADJDEFAULT;
+
+ rttms = rtt / 1000;
+ if (rttms < DNS_RESOLVER_QRYRTTCLASS0) {
+ inc_stats(fctx->res,
+ dns_resstatscounter_queryrtt0);
+ } else if (rttms < DNS_RESOLVER_QRYRTTCLASS1) {
+ inc_stats(fctx->res,
+ dns_resstatscounter_queryrtt1);
+ } else if (rttms < DNS_RESOLVER_QRYRTTCLASS2) {
+ inc_stats(fctx->res,
+ dns_resstatscounter_queryrtt2);
+ } else if (rttms < DNS_RESOLVER_QRYRTTCLASS3) {
+ inc_stats(fctx->res,
+ dns_resstatscounter_queryrtt3);
+ } else if (rttms < DNS_RESOLVER_QRYRTTCLASS4) {
+ inc_stats(fctx->res,
+ dns_resstatscounter_queryrtt4);
+ } else {
+ inc_stats(fctx->res,
+ dns_resstatscounter_queryrtt5);
+ }
} else {
/*
* We don't have an RTT for this query. Maybe the
@@ -608,6 +685,12 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
}
+ /* Remember that the server has been tried. */
+ if (!TRIED(query->addrinfo)) {
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
+ FCTX_ADDRINFO_TRIED, FCTX_ADDRINFO_TRIED);
+ }
+
/*
* Age RTTs of servers not tried.
*/
@@ -790,14 +873,16 @@ fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
}
static inline void
-fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
+fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
dns_fetchevent_t *event, *next_event;
isc_task_t *task;
unsigned int count = 0;
isc_interval_t i;
isc_boolean_t logit = ISC_FALSE;
+ isc_time_t now;
unsigned int old_spillat;
- unsigned int new_spillat = 0; /* initialized to silence compiler warnings */
+ unsigned int new_spillat = 0; /* initialized to silence
+ compiler warnings */
/*
* Caller must be holding the appropriate bucket lock.
@@ -806,6 +891,14 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
FCTXTRACE("sendevents");
+ /*
+ * Keep some record of fetch result for logging later (if required).
+ */
+ fctx->result = result;
+ fctx->exitline = line;
+ TIME_NOW(&now);
+ fctx->duration = isc_time_microdiff(&now, &fctx->start);
+
for (event = ISC_LIST_HEAD(fctx->events);
event != NULL;
event = next_event) {
@@ -864,26 +957,50 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
}
}
+static inline void
+log_edns(fetchctx_t *fctx) {
+ char domainbuf[DNS_NAME_FORMATSIZE];
+
+ if (fctx->reason == NULL)
+ return;
+
+ dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
+ "success resolving '%s' (in '%s'?) after %s",
+ fctx->info, domainbuf, fctx->reason);
+
+ fctx->reason = NULL;
+}
+
static void
-fctx_done(fetchctx_t *fctx, isc_result_t result) {
+fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
dns_resolver_t *res;
isc_boolean_t no_response;
+ REQUIRE(line >= 0);
+
FCTXTRACE("done");
res = fctx->res;
- if (result == ISC_R_SUCCESS)
+ if (result == ISC_R_SUCCESS) {
+ /*%
+ * Log any deferred EDNS timeout messages.
+ */
+ log_edns(fctx);
no_response = ISC_TRUE;
- else
+ } else
no_response = ISC_FALSE;
+
+ fctx->reason = NULL;
fctx_stopeverything(fctx, no_response);
LOCK(&res->buckets[fctx->bucketnum].lock);
fctx->state = fetchstate_done;
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
- fctx_sendevents(fctx, result);
+ fctx_sendevents(fctx, result, line);
UNLOCK(&res->buckets[fctx->bucketnum].lock);
}
@@ -921,7 +1038,8 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
/*
* No route to remote.
*/
- add_bad(fctx, query->addrinfo, sevent->result);
+ add_bad(fctx, query->addrinfo, sevent->result,
+ badns_unreachable);
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
retry = ISC_TRUE;
break;
@@ -942,9 +1060,9 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
else
- fctx_try(fctx);
+ fctx_try(fctx, ISC_TRUE);
}
}
@@ -991,7 +1109,8 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
}
static inline isc_result_t
-fctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
+fctx_addopt(dns_message_t *message, unsigned int version,
+ isc_uint16_t udpsize, isc_boolean_t request_nsid)
{
dns_rdataset_t *rdataset;
dns_rdatalist_t *rdatalist;
@@ -1027,10 +1146,23 @@ fctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
/*
- * No EDNS options.
+ * Set EDNS options if applicable
*/
- rdata->data = NULL;
- rdata->length = 0;
+ if (request_nsid) {
+ /* Send empty NSID option (RFC5001) */
+ unsigned char data[4];
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, data, sizeof(data));
+ isc_buffer_putuint16(&buf, DNS_OPT_NSID);
+ isc_buffer_putuint16(&buf, 0);
+ rdata->data = data;
+ rdata->length = sizeof(data);
+ } else {
+ rdata->data = NULL;
+ rdata->length = 0;
+ }
+
rdata->rdclass = rdatalist->rdclass;
rdata->type = rdatalist->type;
rdata->flags = 0;
@@ -1048,7 +1180,7 @@ fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
unsigned int us;
/*
- * We retry every .5 seconds the first two times through the address
+ * We retry every .8 seconds the first two times through the address
* list, and then we do exponential back-off.
*/
if (fctx->restarts < 3)
@@ -1088,14 +1220,19 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
resquery_t *query;
isc_sockaddr_t addr;
isc_boolean_t have_addr = ISC_FALSE;
+ unsigned int srtt;
FCTXTRACE("query");
res = fctx->res;
task = res->buckets[fctx->bucketnum].task;
- fctx_setretryinterval(fctx, addrinfo->srtt);
- result = fctx_startidletimer(fctx);
+ srtt = addrinfo->srtt;
+ if (ISFORWARDER(addrinfo) && srtt < 1000000)
+ srtt = 1000000;
+
+ fctx_setretryinterval(fctx, srtt);
+ result = fctx_startidletimer(fctx, &fctx->interval);
if (result != ISC_R_SUCCESS)
return (result);
@@ -1262,9 +1399,17 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
if (result != ISC_R_SUCCESS)
goto cleanup_dispatch;
}
+ fctx->querysent++;
ISC_LIST_APPEND(fctx->queries, query, link);
query->fctx->nqueries++;
+ if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
+ inc_stats(res, dns_resstatscounter_queryv4);
+ else
+ inc_stats(res, dns_resstatscounter_queryv6);
+ if (res->view->resquerystats != NULL)
+ dns_rdatatypestats_increment(res->view->resquerystats,
+ fctx->type);
return (ISC_R_SUCCESS);
@@ -1486,34 +1631,55 @@ resquery_send(resquery_t *query) {
!useedns)
{
query->options |= DNS_FETCHOPT_NOEDNS0;
- dns_adb_changeflags(fctx->adb,
- query->addrinfo,
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
DNS_FETCHOPT_NOEDNS0,
DNS_FETCHOPT_NOEDNS0);
}
+ /* Sync NOEDNS0 flag in addrinfo->flags and options now. */
+ if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
+ query->options |= DNS_FETCHOPT_NOEDNS0;
+
+ /*
+ * Handle timeouts by reducing the UDP response size to 512 bytes
+ * then if that doesn't work disabling EDNS (includes DO) and CD.
+ *
+ * These timeout can be due to:
+ * * broken nameservers that don't respond to EDNS queries.
+ * * broken/misconfigured firewalls and NAT implementations
+ * that don't handle IP fragmentation.
+ * * broken/misconfigured firewalls that don't handle responses
+ * greater than 512 bytes.
+ * * broken/misconfigured firewalls that don't handle EDNS, DO
+ * or CD.
+ * * packet loss / link outage.
+ */
+ if (fctx->timeout) {
+ if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
+ fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ query->options |= DNS_FETCHOPT_NOEDNS0;
+ fctx->reason = "disabling EDNS";
+ } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
+ fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ query->options |= DNS_FETCHOPT_EDNS512;
+ fctx->reason = "reducing the advertised EDNS UDP "
+ "packet size to 512 octets";
+ }
+ fctx->timeout = ISC_FALSE;
+ }
+
/*
* Use EDNS0, unless the caller doesn't want it, or we know that
* the remote server doesn't like it.
*/
-
- if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
- fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
- (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
- query->options |= DNS_FETCHOPT_NOEDNS0;
- FCTXTRACE("too many timeouts, disabling EDNS0");
- } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
- fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
- (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
- query->options |= DNS_FETCHOPT_EDNS512;
- FCTXTRACE("too many timeouts, setting EDNS size to 512");
- }
-
if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
- unsigned int version = 0; /* Default version. */
+ unsigned int version = 0; /* Default version. */
unsigned int flags;
isc_uint16_t udpsize = res->udpsize;
+ isc_boolean_t reqnsid = res->view->requestnsid;
flags = query->addrinfo->flags;
if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
@@ -1524,8 +1690,15 @@ resquery_send(resquery_t *query) {
udpsize = 512;
else if (peer != NULL)
(void)dns_peer_getudpsize(peer, &udpsize);
- result = fctx_addopt(fctx->qmessage, version, udpsize);
- if (result != ISC_R_SUCCESS) {
+
+ /* request NSID for current view or peer? */
+ if (peer != NULL)
+ (void) dns_peer_getrequestnsid(peer, &reqnsid);
+ result = fctx_addopt(fctx->qmessage, version,
+ udpsize, reqnsid);
+ if (reqnsid && result == ISC_R_SUCCESS) {
+ query->options |= DNS_FETCHOPT_WANTNSID;
+ } else if (result != ISC_R_SUCCESS) {
/*
* We couldn't add the OPT, but we'll press on.
* We're not using EDNS0, so set the NOEDNS0
@@ -1636,13 +1809,15 @@ resquery_send(resquery_t *query) {
/*
* XXXRTH Make sure we don't send to ourselves! We should probably
- * prune out these addresses when we get them from the ADB.
+ * prune out these addresses when we get them from the ADB.
*/
result = isc_socket_sendto(socket, &r, task, resquery_senddone,
query, address, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup_message;
+
query->sends++;
+
QTRACE("sent");
return (ISC_R_SUCCESS);
@@ -1672,6 +1847,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
resquery_t *query = event->ev_arg;
isc_boolean_t retry = ISC_FALSE;
+ isc_interval_t interval;
isc_result_t result;
unsigned int attrs;
fetchctx_t *fctx;
@@ -1704,6 +1880,20 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
} else {
switch (sevent->result) {
case ISC_R_SUCCESS:
+
+ /*
+ * Extend the idle timer for TCP. 20 seconds
+ * should be long enough for a TCP connection to be
+ * established, a single DNS request to be sent,
+ * and the response received.
+ */
+ isc_interval_set(&interval, 20, 0);
+ result = fctx_startidletimer(query->fctx, &interval);
+ if (result != ISC_R_SUCCESS) {
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ fctx_done(fctx, result, __LINE__);
+ break;
+ }
/*
* We are connected. Create a dispatcher and
* send the query.
@@ -1736,9 +1926,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
result = resquery_send(query);
if (result != ISC_R_SUCCESS) {
- fctx_cancelquery(&query, NULL, NULL,
- ISC_FALSE);
- fctx_done(fctx, result);
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ fctx_done(fctx, result, __LINE__);
}
break;
@@ -1773,9 +1962,9 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
else
- fctx_try(fctx);
+ fctx_try(fctx, ISC_TRUE);
}
}
@@ -1809,13 +1998,16 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
want_try = ISC_TRUE;
- else if (fctx->pending == 0) {
- /*
- * We've got nothing else to wait for and don't
- * know the answer. There's nothing to do but
- * fail the fctx.
- */
- want_done = ISC_TRUE;
+ else {
+ fctx->findfail++;
+ if (fctx->pending == 0) {
+ /*
+ * We've got nothing else to wait for and don't
+ * know the answer. There's nothing to do but
+ * fail the fctx.
+ */
+ want_done = ISC_TRUE;
+ }
}
} else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
@@ -1834,9 +2026,9 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
dns_adb_destroyfind(&find);
if (want_try)
- fctx_try(fctx);
+ fctx_try(fctx, ISC_TRUE);
else if (want_done)
- fctx_done(fctx, ISC_R_FAILURE);
+ fctx_done(fctx, ISC_R_FAILURE, __LINE__);
else if (bucket_empty)
empty_bucket(res);
}
@@ -1924,7 +2116,9 @@ mark_bad(fetchctx_t *fctx) {
}
static void
-add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason) {
+add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
+ badnstype_t badtype)
+{
char namebuf[DNS_NAME_FORMATSIZE];
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
char classbuf[64];
@@ -1935,6 +2129,21 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason) {
const char *sep1, *sep2;
isc_sockaddr_t *address = &addrinfo->sockaddr;
+ if (reason == DNS_R_LAME)
+ fctx->lamecount++;
+ else {
+ switch (badtype) {
+ case badns_unreachable:
+ fctx->neterr++;
+ break;
+ case badns_response:
+ fctx->badresp++;
+ break;
+ case badns_validation:
+ break; /* counted as 'valfail' */
+ }
+ }
+
if (bad_server(fctx, address)) {
/*
* We already know this server is bad.
@@ -1951,7 +2160,7 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason) {
*sa = *address;
ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
- if (reason == DNS_R_LAME) /* already logged */
+ if (reason == DNS_R_LAME) /* already logged */
return;
if (reason == DNS_R_UNEXPECTEDRCODE &&
@@ -1987,15 +2196,79 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason) {
namebuf, typebuf, classbuf, addrbuf);
}
+/*
+ * Return 'bits' bits of random entropy from fctx->rand_buf,
+ * refreshing it by calling isc_random_get() whenever the requested
+ * number of bits is greater than the number in the buffer.
+ */
+static inline isc_uint32_t
+random_bits(fetchctx_t *fctx, isc_uint32_t bits) {
+ isc_uint32_t ret = 0;
+
+ REQUIRE(VALID_FCTX(fctx));
+ REQUIRE(bits <= 32);
+ if (bits == 0)
+ return (0);
+
+ if (bits >= fctx->rand_bits) {
+ /* if rand_bits == 0, this is unnecessary but harmless */
+ bits -= fctx->rand_bits;
+ ret = fctx->rand_buf << bits;
+
+ /* refresh random buffer now */
+ isc_random_get(&fctx->rand_buf);
+ fctx->rand_bits = sizeof(fctx->rand_buf) * CHAR_BIT;
+ }
+
+ if (bits > 0) {
+ isc_uint32_t mask = 0xffffffff;
+ if (bits < 32) {
+ mask = (1 << bits) - 1;
+ }
+
+ ret |= fctx->rand_buf & mask;
+ fctx->rand_buf >>= bits;
+ fctx->rand_bits -= bits;
+ }
+
+ return (ret);
+}
+
+/*
+ * Add some random jitter to a server's RTT value so that the
+ * order of queries will be unpredictable.
+ *
+ * RTT values of servers which have been tried are fuzzed by 128 ms.
+ * Servers that haven't been tried yet have their RTT set to a random
+ * value between 0 ms and 7 ms; they should get to go first, but in
+ * unpredictable order.
+ */
+static inline void
+randomize_srtt(fetchctx_t *fctx, dns_adbaddrinfo_t *ai) {
+ if (TRIED(ai)) {
+ ai->srtt >>= 10; /* convert to milliseconds, near enough */
+ ai->srtt |= (ai->srtt & 0x80) | random_bits(fctx, 7);
+ ai->srtt <<= 10; /* now back to microseconds */
+ } else
+ ai->srtt = random_bits(fctx, 3) << 10;
+}
+
+/*
+ * Sort addrinfo list by RTT (with random jitter)
+ */
static void
-sort_adbfind(dns_adbfind_t *find) {
+sort_adbfind(fetchctx_t *fctx, dns_adbfind_t *find) {
dns_adbaddrinfo_t *best, *curr;
dns_adbaddrinfolist_t sorted;
- /*
- * Lame N^2 bubble sort.
- */
+ /* Add jitter to SRTT values */
+ curr = ISC_LIST_HEAD(find->list);
+ while (curr != NULL) {
+ randomize_srtt(fctx, curr);
+ curr = ISC_LIST_NEXT(curr, publink);
+ }
+ /* Lame N^2 bubble sort. */
ISC_LIST_INIT(sorted);
while (!ISC_LIST_EMPTY(find->list)) {
best = ISC_LIST_HEAD(find->list);
@@ -2011,39 +2284,25 @@ sort_adbfind(dns_adbfind_t *find) {
find->list = sorted;
}
+/*
+ * Sort a list of finds by server RTT (with random jitter)
+ */
static void
-sort_finds(fetchctx_t *fctx) {
+sort_finds(fetchctx_t *fctx, dns_adbfindlist_t *findlist) {
dns_adbfind_t *best, *curr;
dns_adbfindlist_t sorted;
dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
- /*
- * Lame N^2 bubble sort.
- */
-
- ISC_LIST_INIT(sorted);
- while (!ISC_LIST_EMPTY(fctx->finds)) {
- best = ISC_LIST_HEAD(fctx->finds);
- bestaddrinfo = ISC_LIST_HEAD(best->list);
- INSIST(bestaddrinfo != NULL);
- curr = ISC_LIST_NEXT(best, publink);
- while (curr != NULL) {
- addrinfo = ISC_LIST_HEAD(curr->list);
- INSIST(addrinfo != NULL);
- if (addrinfo->srtt < bestaddrinfo->srtt) {
- best = curr;
- bestaddrinfo = addrinfo;
- }
- curr = ISC_LIST_NEXT(curr, publink);
- }
- ISC_LIST_UNLINK(fctx->finds, best, publink);
- ISC_LIST_APPEND(sorted, best, publink);
- }
- fctx->finds = sorted;
+ /* Sort each find's addrinfo list by SRTT (after adding jitter) */
+ for (curr = ISC_LIST_HEAD(*findlist);
+ curr != NULL;
+ curr = ISC_LIST_NEXT(curr, publink))
+ sort_adbfind(fctx, curr);
+ /* Lame N^2 bubble sort. */
ISC_LIST_INIT(sorted);
- while (!ISC_LIST_EMPTY(fctx->altfinds)) {
- best = ISC_LIST_HEAD(fctx->altfinds);
+ while (!ISC_LIST_EMPTY(*findlist)) {
+ best = ISC_LIST_HEAD(*findlist);
bestaddrinfo = ISC_LIST_HEAD(best->list);
INSIST(bestaddrinfo != NULL);
curr = ISC_LIST_NEXT(best, publink);
@@ -2056,10 +2315,10 @@ sort_finds(fetchctx_t *fctx) {
}
curr = ISC_LIST_NEXT(curr, publink);
}
- ISC_LIST_UNLINK(fctx->altfinds, best, publink);
+ ISC_LIST_UNLINK(*findlist, best, publink);
ISC_LIST_APPEND(sorted, best, publink);
}
- fctx->altfinds = sorted;
+ *findlist = sorted;
}
static void
@@ -2103,6 +2362,7 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
* XXXRTH Follow the CNAME/DNAME chain?
*/
dns_adb_destroyfind(&find);
+ fctx->adberr++;
}
} else if (!ISC_LIST_EMPTY(find->list)) {
/*
@@ -2110,7 +2370,6 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
* name.
*/
INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
- sort_adbfind(find);
if (flags != 0 || port != 0) {
for (ai = ISC_LIST_HEAD(find->list);
ai != NULL;
@@ -2147,6 +2406,11 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
find->result_v4 != DNS_R_NXDOMAIN)))
*need_alternate = ISC_TRUE;
} else {
+ if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0)
+ fctx->lamecount++; /* cached lame server */
+ else
+ fctx->adberr++; /* unreachable server, etc. */
+
/*
* If we know there are no addresses for
* the family we are using then try to add
@@ -2188,7 +2452,7 @@ fctx_getaddresses(fetchctx_t *fctx) {
}
res = fctx->res;
- stdoptions = 0; /* Keep compiler happy. */
+ stdoptions = 0; /* Keep compiler happy. */
/*
* Forwarders.
@@ -2379,7 +2643,8 @@ fctx_getaddresses(fetchctx_t *fctx) {
* We've found some addresses. We might still be looking
* for more addresses.
*/
- sort_finds(fctx);
+ sort_finds(fctx, &fctx->finds);
+ sort_finds(fctx, &fctx->altfinds);
result = ISC_R_SUCCESS;
}
@@ -2593,7 +2858,7 @@ fctx_nextaddress(fetchctx_t *fctx) {
}
static void
-fctx_try(fetchctx_t *fctx) {
+fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) {
isc_result_t result;
dns_adbaddrinfo_t *addrinfo;
@@ -2623,7 +2888,7 @@ fctx_try(fetchctx_t *fctx) {
/*
* Something bad happened.
*/
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
return;
}
@@ -2633,14 +2898,16 @@ fctx_try(fetchctx_t *fctx) {
* might be bad ones. In this case, return SERVFAIL.
*/
if (addrinfo == NULL) {
- fctx_done(fctx, DNS_R_SERVFAIL);
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
}
result = fctx_query(fctx, addrinfo, fctx->options);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
+ else if (retrying)
+ inc_stats(fctx->res, dns_resstatscounter_retry);
}
static isc_boolean_t
@@ -2738,12 +3005,16 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
FCTXTRACE("timeout");
+ inc_stats(fctx->res, dns_resstatscounter_querytimeout);
+
if (event->ev_type == ISC_TIMEREVENT_LIFE) {
- fctx_done(fctx, ISC_R_TIMEDOUT);
+ fctx->reason = NULL;
+ fctx_done(fctx, ISC_R_TIMEDOUT, __LINE__);
} else {
isc_result_t result;
fctx->timeouts++;
+ fctx->timeout = ISC_TRUE;
/*
* We could cancel the running queries here, or we could let
* them keep going. Since we normally use separate sockets for
@@ -2765,12 +3036,12 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
*/
result = fctx_starttimer(fctx);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
else
/*
* Keep trying.
*/
- fctx_try(fctx);
+ fctx_try(fctx, ISC_TRUE);
}
isc_event_free(&event);
@@ -2860,7 +3131,7 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
if (fctx->state != fetchstate_done) {
fctx->state = fetchstate_done;
- fctx_sendevents(fctx, ISC_R_CANCELED);
+ fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
}
if (fctx->references == 0 && fctx->pending == 0 &&
@@ -2899,7 +3170,7 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
*/
fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
fctx->state = fetchstate_done;
- fctx_sendevents(fctx, ISC_R_CANCELED);
+ fctx_sendevents(fctx, ISC_R_CANCELED, __LINE__);
/*
* Since we haven't started, we INSIST that we have no
* pending ADB finds and no pending validations.
@@ -2938,9 +3209,9 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
*/
result = fctx_starttimer(fctx);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
else
- fctx_try(fctx);
+ fctx_try(fctx, ISC_FALSE);
} else if (bucket_empty)
empty_bucket(res);
}
@@ -3026,8 +3297,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
return (ISC_R_NOMEMORY);
dns_name_format(name, buf, sizeof(buf));
dns_rdatatype_format(type, typebuf, sizeof(typebuf));
- strcat(buf, "/"); /* checked */
- strcat(buf, typebuf); /* checked */
+ strcat(buf, "/"); /* checked */
+ strcat(buf, typebuf); /* checked */
fctx->info = isc_mem_strdup(res->buckets[bucketnum].mctx, buf);
if (fctx->info == NULL) {
result = ISC_R_NOMEMORY;
@@ -3070,10 +3341,27 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx->altfind = NULL;
fctx->pending = 0;
fctx->restarts = 0;
+ fctx->querysent = 0;
+ fctx->referrals = 0;
+ TIME_NOW(&fctx->start);
fctx->timeouts = 0;
+ fctx->lamecount = 0;
+ fctx->adberr = 0;
+ fctx->neterr = 0;
+ fctx->badresp = 0;
+ fctx->findfail = 0;
+ fctx->valfail = 0;
+ fctx->result = ISC_R_FAILURE;
+ fctx->vresult = ISC_R_SUCCESS;
+ fctx->exitline = -1; /* sentinel */
+ fctx->logged = ISC_FALSE;
fctx->attributes = 0;
fctx->spilled = ISC_FALSE;
fctx->nqueries = 0;
+ fctx->reason = NULL;
+ fctx->rand_buf = 0;
+ fctx->rand_bits = 0;
+ fctx->timeout = ISC_FALSE;
dns_name_init(&fctx->nsname, NULL);
fctx->nsfetch = NULL;
@@ -3162,7 +3450,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
/*
* Compute an expiration time for the entire fetch.
*/
- isc_interval_set(&interval, 30, 0); /* XXXRTH constant */
+ isc_interval_set(&interval, 30, 0); /* XXXRTH constant */
iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
if (iresult != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -3382,13 +3670,13 @@ clone_results(fetchctx_t *fctx) {
}
}
-#define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
-#define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
-#define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
-#define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
-#define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
-#define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
-#define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
+#define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
+#define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
+#define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
+#define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
+#define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
+#define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
+#define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
/*
@@ -3397,7 +3685,7 @@ clone_results(fetchctx_t *fctx) {
* was the last fctx in the resolver, destroy the resolver.
*
* Requires:
- * '*fctx' is shutting down.
+ * '*fctx' is shutting down.
*/
static void
maybe_destroy(fetchctx_t *fctx) {
@@ -3494,7 +3782,7 @@ validated(isc_task_t *task, isc_event_t *event) {
* so, destroy the fctx.
*/
if (SHUTTINGDOWN(fctx) && !sentresponse) {
- maybe_destroy(fctx); /* Locks bucket. */
+ maybe_destroy(fctx); /* Locks bucket. */
goto cleanup_event;
}
@@ -3543,6 +3831,9 @@ validated(isc_task_t *task, isc_event_t *event) {
if (vevent->result != ISC_R_SUCCESS) {
FCTXTRACE("validation failed");
+ inc_stats(fctx->res, dns_resstatscounter_valfail);
+ fctx->valfail++;
+ fctx->vresult = vevent->result;
result = ISC_R_NOTFOUND;
if (vevent->rdataset != NULL)
result = dns_db_findnode(fctx->cache, vevent->name,
@@ -3557,7 +3848,7 @@ validated(isc_task_t *task, isc_event_t *event) {
if (result == ISC_R_SUCCESS)
dns_db_detachnode(fctx->cache, &node);
result = vevent->result;
- add_bad(fctx, addrinfo, result);
+ add_bad(fctx, addrinfo, result, badns_validation);
isc_event_free(&event);
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
INSIST(fctx->validator == NULL);
@@ -3565,9 +3856,9 @@ validated(isc_task_t *task, isc_event_t *event) {
if (fctx->validator != NULL) {
dns_validator_send(fctx->validator);
} else if (sentresponse)
- fctx_done(fctx, result); /* Locks bucket. */
+ fctx_done(fctx, result, __LINE__); /* Locks bucket. */
else
- fctx_try(fctx); /* Locks bucket. */
+ fctx_try(fctx, ISC_TRUE); /* Locks bucket. */
return;
}
@@ -3577,6 +3868,8 @@ validated(isc_task_t *task, isc_event_t *event) {
dns_rdatatype_t covers;
FCTXTRACE("nonexistence validation OK");
+ inc_stats(fctx->res, dns_resstatscounter_valnegsuccess);
+
if (fctx->rmessage->rcode == dns_rcode_nxdomain)
covers = dns_rdatatype_any;
else
@@ -3590,7 +3883,7 @@ validated(isc_task_t *task, isc_event_t *event) {
/*
* If we are asking for a SOA record set the cache time
* to zero to facilitate locating the containing zone of
- * a arbitary zone.
+ * a arbitrary zone.
*/
ttl = fctx->res->view->maxncachettl;
if (fctx->type == dns_rdatatype_soa &&
@@ -3599,12 +3892,13 @@ validated(isc_task_t *task, isc_event_t *event) {
ttl = 0;
result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
- covers, now, ttl,
+ covers, now, ttl, vevent->optout,
ardataset, &eresult);
if (result != ISC_R_SUCCESS)
goto noanswer_response;
goto answer_response;
- }
+ } else
+ inc_stats(fctx->res, dns_resstatscounter_valsuccess);
FCTXTRACE("validation OK");
@@ -3615,6 +3909,11 @@ validated(isc_task_t *task, isc_event_t *event) {
RUNTIME_CHECK(result == ISC_R_SUCCESS);
INSIST(vevent->sigrdataset != NULL);
vevent->sigrdataset->ttl = vevent->rdataset->ttl;
+ if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
+ result = dns_rdataset_addclosest(vevent->rdataset,
+ vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
}
/*
@@ -3654,7 +3953,7 @@ validated(isc_task_t *task, isc_event_t *event) {
dns_db_detachnode(fctx->cache, &node);
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
if (SHUTTINGDOWN(fctx))
- maybe_destroy(fctx); /* Locks bucket. */
+ maybe_destroy(fctx); /* Locks bucket. */
goto cleanup_event;
}
@@ -3744,7 +4043,7 @@ validated(isc_task_t *task, isc_event_t *event) {
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
- fctx_done(fctx, result); /* Locks bucket. */
+ fctx_done(fctx, result, __LINE__); /* Locks bucket. */
cleanup_event:
INSIST(node == NULL);
@@ -3929,53 +4228,53 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
rdataset->trust = dns_trust_pending;
if (sigrdataset != NULL)
sigrdataset->trust = dns_trust_pending;
- if (!need_validation)
+ if (!need_validation || !ANSWER(rdataset)) {
addedrdataset = ardataset;
- else
- addedrdataset = NULL;
- result = dns_db_addrdataset(fctx->cache, node, NULL,
- now, rdataset, 0,
- addedrdataset);
- if (result == DNS_R_UNCHANGED) {
- result = ISC_R_SUCCESS;
- if (!need_validation &&
- ardataset != NULL &&
- ardataset->type == 0) {
- /*
- * The answer in the cache is better
- * than the answer we found, and is
- * a negative cache entry, so we
- * must set eresult appropriately.
- */
- if (NXDOMAIN(ardataset))
- eresult = DNS_R_NCACHENXDOMAIN;
- else
- eresult = DNS_R_NCACHENXRRSET;
- /*
- * We have a negative response from
- * the cache so don't attempt to
- * add the RRSIG rrset.
- */
- continue;
- }
- }
- if (result != ISC_R_SUCCESS)
- break;
- if (sigrdataset != NULL) {
- if (!need_validation)
- addedrdataset = asigrdataset;
- else
- addedrdataset = NULL;
- result = dns_db_addrdataset(fctx->cache,
- node, NULL, now,
- sigrdataset, 0,
- addedrdataset);
- if (result == DNS_R_UNCHANGED)
+ result = dns_db_addrdataset(fctx->cache, node,
+ NULL, now, rdataset,
+ 0, addedrdataset);
+ if (result == DNS_R_UNCHANGED) {
result = ISC_R_SUCCESS;
+ if (!need_validation &&
+ ardataset != NULL &&
+ ardataset->type == 0) {
+ /*
+ * The answer in the cache is
+ * better than the answer we
+ * found, and is a negative
+ * cache entry, so we must set
+ * eresult appropriately.
+ */
+ if (NXDOMAIN(ardataset))
+ eresult =
+ DNS_R_NCACHENXDOMAIN;
+ else
+ eresult =
+ DNS_R_NCACHENXRRSET;
+ /*
+ * We have a negative response
+ * from the cache so don't
+ * attempt to add the RRSIG
+ * rrset.
+ */
+ continue;
+ }
+ }
if (result != ISC_R_SUCCESS)
break;
- } else if (!ANSWER(rdataset))
- continue;
+ if (sigrdataset != NULL) {
+ addedrdataset = asigrdataset;
+ result = dns_db_addrdataset(fctx->cache,
+ node, NULL, now,
+ sigrdataset, 0,
+ addedrdataset);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS)
+ break;
+ } else if (!ANSWER(rdataset))
+ continue;
+ }
if (ANSWER(rdataset) && need_validation) {
if (fctx->type != dns_rdatatype_any &&
@@ -4011,7 +4310,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
* Defer any further validations.
* This prevents multiple validators
* from manipulating fctx->rmessage
- * simultaniously.
+ * simultaneously.
*/
valoptions |= DNS_VALIDATOR_DEFER;
}
@@ -4155,12 +4454,12 @@ cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
}
/*
- * Do what dns_ncache_add() does, and then compute an appropriate eresult.
+ * Do what dns_ncache_addoptout() does, and then compute an appropriate eresult.
*/
static isc_result_t
ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
- dns_rdataset_t *ardataset,
+ isc_boolean_t optout, dns_rdataset_t *ardataset,
isc_result_t *eresultp)
{
isc_result_t result;
@@ -4170,8 +4469,8 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_rdataset_init(&rdataset);
ardataset = &rdataset;
}
- result = dns_ncache_add(message, cache, node, covers, now,
- maxttl, ardataset);
+ result = dns_ncache_addoptout(message, cache, node, covers, now,
+ maxttl, optout, ardataset);
if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
/*
* If the cache now contains a negative entry and we
@@ -4327,15 +4626,17 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
/*
* If we are asking for a SOA record set the cache time
* to zero to facilitate locating the containing zone of
- * a arbitary zone.
+ * a arbitrary zone.
*/
ttl = fctx->res->view->maxncachettl;
if (fctx->type == dns_rdatatype_soa &&
- covers == dns_rdatatype_any)
+ covers == dns_rdatatype_any &&
+ fctx->res->zero_no_soa_ttl)
ttl = 0;
result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
- covers, now, ttl, ardataset, &eresult);
+ covers, now, ttl, ISC_FALSE,
+ ardataset, &eresult);
if (result != ISC_R_SUCCESS)
goto unlock;
@@ -4710,7 +5011,8 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
type = rdataset->type;
if (type == dns_rdatatype_rrsig)
type = rdataset->covers;
- if (type == dns_rdatatype_nsec) {
+ if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3) {
/*
* NSEC or RRSIG NSEC.
*/
@@ -4719,7 +5021,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
DNS_NAMEATTR_NCACHE;
rdataset->attributes |=
DNS_RDATASETATTR_NCACHE;
- } else {
+ } else if (type == dns_rdatatype_nsec) {
name->attributes |=
DNS_NAMEATTR_CACHE;
rdataset->attributes |=
@@ -4855,7 +5157,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
* Set the current query domain to the referral name.
*
* XXXRTH We should check if we're in forward-only mode, and
- * if so we should bail out.
+ * if so we should bail out.
*/
INSIST(dns_name_countlabels(&fctx->domain) > 0);
dns_name_free(&fctx->domain,
@@ -4931,6 +5233,13 @@ answer_response(fetchctx_t *fctx) {
found = ISC_FALSE;
want_chaining = ISC_FALSE;
aflag = 0;
+ if (rdataset->type == dns_rdatatype_nsec3) {
+ /*
+ * NSEC3 records are not allowed to
+ * appear in the answer section.
+ */
+ return (DNS_R_FORMERR);
+ }
if (rdataset->type == type && !found_cname) {
/*
* We've found an ordinary answer.
@@ -5157,7 +5466,7 @@ answer_response(fetchctx_t *fctx) {
*/
if (found_dname) {
/*
- * Copy the the dname into the
+ * Copy the dname into the
* qname fixed name.
*
* Although we check for
@@ -5311,7 +5620,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
bucketnum = fctx->bucketnum;
if (fevent->result == ISC_R_CANCELED) {
dns_resolver_destroyfetch(&fctx->nsfetch);
- fctx_done(fctx, ISC_R_CANCELED);
+ fctx_done(fctx, ISC_R_CANCELED, __LINE__);
} else if (fevent->result == ISC_R_SUCCESS) {
FCTXTRACE("resuming DS lookup");
@@ -5327,13 +5636,13 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
fctx->res->buckets[bucketnum].mctx,
&fctx->domain);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, DNS_R_SERVFAIL);
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
goto cleanup;
}
/*
* Try again.
*/
- fctx_try(fctx);
+ fctx_try(fctx, ISC_TRUE);
} else {
unsigned int n;
dns_rdataset_t *nsrdataset = NULL;
@@ -5345,7 +5654,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
domain = dns_fixedname_name(&fixed);
dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
if (dns_name_equal(&fctx->nsname, domain)) {
- fctx_done(fctx, DNS_R_SERVFAIL);
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
dns_resolver_destroyfetch(&fctx->nsfetch);
goto cleanup;
}
@@ -5372,7 +5681,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
&fctx->nsrrset, NULL,
&fctx->nsfetch);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
else {
LOCK(&res->buckets[bucketnum].lock);
locked = ISC_TRUE;
@@ -5439,6 +5748,65 @@ checknames(dns_message_t *message) {
checknamessection(message, DNS_SECTION_ADDITIONAL);
}
+/*
+ * Log server NSID at log level 'level'
+ */
+static isc_result_t
+log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx)
+{
+ static const char hex[17] = "0123456789abcdef";
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_uint16_t optcode, nsid_len, buflen, i;
+ isc_result_t result;
+ isc_buffer_t nsidbuf;
+ dns_rdata_t rdata;
+ unsigned char *p, *buf, *nsid;
+
+ /* Extract rdata from OPT rdataset */
+ result = dns_rdataset_first(opt);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(opt, &rdata);
+ if (rdata.length < 4)
+ return (ISC_R_FAILURE);
+
+ /* Check for NSID */
+ isc_buffer_init(&nsidbuf, rdata.data, rdata.length);
+ isc_buffer_add(&nsidbuf, rdata.length);
+ optcode = isc_buffer_getuint16(&nsidbuf);
+ nsid_len = isc_buffer_getuint16(&nsidbuf);
+ if (optcode != DNS_OPT_NSID || nsid_len == 0)
+ return (ISC_R_FAILURE);
+
+ /* Allocate buffer for storing hex version of the NSID */
+ buflen = nsid_len * 2 + 1;
+ buf = isc_mem_get(mctx, buflen);
+ if (buf == NULL)
+ return (ISC_R_NOSPACE);
+
+ /* Convert to hex */
+ p = buf;
+ nsid = rdata.data + 4;
+ for (i = 0; i < nsid_len; i++) {
+ *p++ = hex[(nsid[0] >> 4) & 0xf];
+ *p++ = hex[nsid[0] & 0xf];
+ nsid++;
+ }
+ *p = '\0';
+
+ isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
+ sizeof(addrbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, level,
+ "received NSID '%s' from %s", buf, addrbuf);
+
+ /* Clean up */
+ isc_mem_put(mctx, buf, buflen);
+ return (ISC_R_SUCCESS);
+}
+
static void
log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
isc_buffer_t buffer;
@@ -5484,6 +5852,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
isc_boolean_t keep_trying, get_nameservers, resend;
isc_boolean_t truncated;
dns_message_t *message;
+ dns_rdataset_t *opt;
fetchctx_t *fctx;
dns_name_t *fname;
dns_fixedname_t foundname;
@@ -5493,6 +5862,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
unsigned int options;
unsigned int findoptions;
isc_result_t broken_server;
+ badnstype_t broken_type = badns_response;
REQUIRE(VALID_QUERY(query));
fctx = query->fctx;
@@ -5502,6 +5872,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
QTRACE("response");
+ if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
+ inc_stats(fctx->res, dns_resstatscounter_responsev4);
+ else
+ inc_stats(fctx->res, dns_resstatscounter_responsev6);
+
(void)isc_timer_touch(fctx->timer);
keep_trying = ISC_FALSE;
@@ -5517,11 +5892,12 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
}
fctx->timeouts = 0;
+ fctx->timeout = ISC_FALSE;
/*
* XXXRTH We should really get the current time just once. We
- * need a routine to convert from an isc_time_t to an
- * isc_stdtime_t.
+ * need a routine to convert from an isc_time_t to an
+ * isc_stdtime_t.
*/
TIME_NOW(&tnow);
finish = &tnow;
@@ -5564,6 +5940,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
devent->result == ISC_R_CONNREFUSED ||
devent->result == ISC_R_CANCELED)) {
broken_server = devent->result;
+ broken_type = badns_unreachable;
}
}
goto done;
@@ -5616,6 +5993,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
query->addrinfo,
DNS_FETCHOPT_NOEDNS0,
DNS_FETCHOPT_NOEDNS0);
+ inc_stats(fctx->res,
+ dns_resstatscounter_edns0fail);
} else {
broken_server = result;
keep_trying = ISC_TRUE;
@@ -5644,6 +6023,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
query->addrinfo,
DNS_FETCHOPT_NOEDNS0,
DNS_FETCHOPT_NOEDNS0);
+ inc_stats(fctx->res,
+ dns_resstatscounter_edns0fail);
} else {
broken_server = DNS_R_UNEXPECTEDRCODE;
keep_trying = ISC_TRUE;
@@ -5657,12 +6038,21 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
}
}
+
/*
* Log the incoming packet.
*/
log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
/*
+ * Did we request NSID? If so, and if the response contains
+ * NSID data, log it at INFO level.
+ */
+ opt = dns_message_getopt(message);
+ if (opt != NULL && (query->options & DNS_FETCHOPT_WANTNSID) != 0)
+ log_nsid(opt, query, ISC_LOG_INFO, fctx->res->mctx);
+
+ /*
* If the message is signed, check the signature. If not, this
* returns success anyway.
*/
@@ -5690,6 +6080,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
truncated = ISC_TRUE;
if (truncated) {
+ inc_stats(fctx->res, dns_resstatscounter_truncated);
if ((options & DNS_FETCHOPT_TCP) != 0) {
broken_server = DNS_R_TRUNCATEDTCP;
keep_trying = ISC_TRUE;
@@ -5711,6 +6102,26 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
}
/*
+ * Update statistics about erroneous responses.
+ */
+ if (message->rcode != dns_rcode_noerror) {
+ switch (message->rcode) {
+ case dns_rcode_nxdomain:
+ inc_stats(fctx->res, dns_resstatscounter_nxdomain);
+ break;
+ case dns_rcode_servfail:
+ inc_stats(fctx->res, dns_resstatscounter_servfail);
+ break;
+ case dns_rcode_formerr:
+ inc_stats(fctx->res, dns_resstatscounter_formerr);
+ break;
+ default:
+ inc_stats(fctx->res, dns_resstatscounter_othererror);
+ break;
+ }
+ }
+
+ /*
* Is the remote server broken, or does it dislike us?
*/
if (message->rcode != dns_rcode_noerror &&
@@ -5728,8 +6139,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* reasons.
*
* XXXRTH We should check if the question
- * we're asking requires EDNS0, and
- * if so, we should bail out.
+ * we're asking requires EDNS0, and
+ * if so, we should bail out.
*/
options |= DNS_FETCHOPT_NOEDNS0;
resend = ISC_TRUE;
@@ -5740,6 +6151,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
dns_adb_changeflags(fctx->adb, query->addrinfo,
DNS_FETCHOPT_NOEDNS0,
DNS_FETCHOPT_NOEDNS0);
+ inc_stats(fctx->res, dns_resstatscounter_edns0fail);
} else if (message->rcode == dns_rcode_formerr) {
if (ISFORWARDER(query->addrinfo)) {
/*
@@ -5767,12 +6179,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
result = DNS_R_YXDOMAIN;
} else if (message->rcode == dns_rcode_badvers) {
- dns_rdataset_t *opt;
unsigned int flags, mask;
unsigned int version;
resend = ISC_TRUE;
- opt = dns_message_getopt(message);
version = (opt->ttl >> 16) & 0xff;
flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
DNS_FETCHOPT_EDNSVERSIONSET;
@@ -5815,6 +6225,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
is_lame(fctx)) {
+ inc_stats(fctx->res, dns_resstatscounter_lame);
log_lame(fctx, query->addrinfo);
result = dns_adb_marklame(fctx->adb, query->addrinfo,
&fctx->name, fctx->type,
@@ -5928,6 +6339,18 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* has not experienced any restarts yet.
*/
fctx->restarts = 0;
+
+ /*
+ * Update local statistics counters collected for each
+ * new zone.
+ */
+ fctx->referrals++;
+ fctx->querysent = 0;
+ fctx->lamecount = 0;
+ fctx->neterr = 0;
+ fctx->badresp = 0;
+ fctx->adberr = 0;
+
result = ISC_R_SUCCESS;
} else if (result != ISC_R_SUCCESS) {
/*
@@ -6001,7 +6424,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* Add this server to the list of bad servers for
* this fctx.
*/
- add_bad(fctx, addrinfo, broken_server);
+ add_bad(fctx, addrinfo, broken_server, broken_type);
}
if (get_nameservers) {
@@ -6009,7 +6432,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
dns_fixedname_init(&foundname);
fname = dns_fixedname_name(&foundname);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, DNS_R_SERVFAIL);
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
findoptions = 0;
@@ -6027,7 +6450,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
NULL);
if (result != ISC_R_SUCCESS) {
FCTXTRACE("couldn't find a zonecut");
- fctx_done(fctx, DNS_R_SERVFAIL);
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
if (!dns_name_issubdomain(fname, &fctx->domain)) {
@@ -6036,7 +6459,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* QDOMAIN.
*/
FCTXTRACE("nameservers now above QDOMAIN");
- fctx_done(fctx, DNS_R_SERVFAIL);
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
dns_name_free(&fctx->domain,
@@ -6046,7 +6469,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
fctx->res->buckets[fctx->bucketnum].mctx,
&fctx->domain);
if (result != ISC_R_SUCCESS) {
- fctx_done(fctx, DNS_R_SERVFAIL);
+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
fctx_cancelqueries(fctx, ISC_TRUE);
@@ -6058,15 +6481,16 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
/*
* Try again.
*/
- fctx_try(fctx);
+ fctx_try(fctx, !get_nameservers);
} else if (resend) {
/*
* Resend (probably with changed options).
*/
FCTXTRACE("resend");
+ inc_stats(fctx->res, dns_resstatscounter_retry);
result = fctx_query(fctx, addrinfo, options);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
} else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
/*
* All has gone well so far, but we are waiting for the
@@ -6080,10 +6504,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
} else if (result == DNS_R_CHASEDSSERVERS) {
unsigned int n;
- add_bad(fctx, addrinfo, result);
+ add_bad(fctx, addrinfo, result, broken_type);
fctx_cancelqueries(fctx, ISC_TRUE);
fctx_cleanupfinds(fctx);
fctx_cleanupforwaddrs(fctx);
@@ -6100,18 +6524,18 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
&fctx->nsrrset, NULL,
&fctx->nsfetch);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
fctx->references++;
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
} else {
/*
* We're done.
*/
- fctx_done(fctx, result);
+ fctx_done(fctx, result, __LINE__);
}
}
@@ -6284,7 +6708,8 @@ dns_resolver_create(dns_view_t *view,
res->spillatmax = 100;
res->spillattimer = NULL;
res->zero_no_soa_ttl = ISC_FALSE;
-
+ res->ndisps = 0;
+ res->nextdisp = 0; /* meaningless at this point, but init it */
res->nbuckets = ntasks;
res->activebuckets = ntasks;
res->buckets = isc_mem_get(view->mctx,
@@ -6304,13 +6729,23 @@ dns_resolver_create(dns_view_t *view,
goto cleanup_buckets;
}
res->buckets[i].mctx = NULL;
+ snprintf(name, sizeof(name), "res%u", i);
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Use a separate memory context for each bucket to reduce
+ * contention among multiple threads. Do this only when
+ * enabling threads because it will be require more memory.
+ */
result = isc_mem_create(0, 0, &res->buckets[i].mctx);
if (result != ISC_R_SUCCESS) {
isc_task_detach(&res->buckets[i].task);
DESTROYLOCK(&res->buckets[i].lock);
goto cleanup_buckets;
}
- snprintf(name, sizeof(name), "res%u", i);
+ isc_mem_setname(res->buckets[i].mctx, name, NULL);
+#else
+ isc_mem_attach(view->mctx, &res->buckets[i].mctx);
+#endif
isc_task_setname(res->buckets[i].task, name, res);
ISC_LIST_INIT(res->buckets[i].fctxs);
res->buckets[i].exiting = ISC_FALSE;
@@ -6356,14 +6791,14 @@ dns_resolver_create(dns_view_t *view,
task = NULL;
result = isc_task_create(taskmgr, 0, &task);
if (result != ISC_R_SUCCESS)
- goto cleanup_primelock;
+ goto cleanup_primelock;
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
task, spillattimer_countdown, res,
&res->spillattimer);
isc_task_detach(&task);
if (result != ISC_R_SUCCESS)
- goto cleanup_primelock;
+ goto cleanup_primelock;
#if USE_ALGLOCK
result = isc_rwlock_init(&res->alglock, 0, 0);
@@ -6973,6 +7408,47 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
empty_bucket(res);
}
+void
+dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
+ isc_logcategory_t *category, isc_logmodule_t *module,
+ int level, isc_boolean_t duplicateok)
+{
+ fetchctx_t *fctx;
+ dns_resolver_t *res;
+ char domainbuf[DNS_NAME_FORMATSIZE];
+
+ REQUIRE(DNS_FETCH_VALID(fetch));
+ fctx = fetch->private;
+ REQUIRE(VALID_FCTX(fctx));
+ res = fctx->res;
+
+ LOCK(&res->buckets[fctx->bucketnum].lock);
+
+ INSIST(fctx->exitline >= 0);
+ if (!fctx->logged || duplicateok) {
+ dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
+ isc_log_write(lctx, category, module, level,
+ "fetch completed at %s:%d for %s in "
+ "%" ISC_PRINT_QUADFORMAT "u."
+ "%06" ISC_PRINT_QUADFORMAT "u: %s/%s "
+ "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
+ "timeout:%u,lame:%u,neterr:%u,badresp:%u,"
+ "adberr:%u,findfail:%u,valfail:%u]",
+ __FILE__, fctx->exitline, fctx->info,
+ fctx->duration / 1000000,
+ fctx->duration % 1000000,
+ isc_result_totext(fctx->result),
+ isc_result_totext(fctx->vresult), domainbuf,
+ fctx->referrals, fctx->restarts,
+ fctx->querysent, fctx->timeouts, fctx->lamecount,
+ fctx->neterr, fctx->badresp, fctx->adberr,
+ fctx->findfail, fctx->valfail);
+ fctx->logged = ISC_TRUE;
+ }
+
+ UNLOCK(&res->buckets[fctx->bucketnum].lock);
+}
+
dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
@@ -7296,3 +7772,10 @@ dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
resolver->zero_no_soa_ttl = state;
}
+
+unsigned int
+dns_resolver_getoptions(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+
+ return (resolver->options);
+}
diff --git a/lib/dns/result.c b/lib/dns/result.c
index fdb58e0..54c70e0 100644
--- a/lib/dns/result.c
+++ b/lib/dns/result.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.c,v 1.115.10.7 2005/06/17 02:04:31 marka Exp $ */
+/* $Id: result.c,v 1.125 2008/09/25 04:02:38 tbox Exp $ */
/*! \file */
@@ -155,7 +155,8 @@ static const char *text[DNS_R_NRESULTS] = {
"must-be-secure", /*%< 100 DNS_R_MUSTBESECURE */
"covering NSEC record returned", /*%< 101 DNS_R_COVERINGNSEC */
"MX is an address", /*%< 102 DNS_R_MXISADDRESS */
- "duplicate query" /*%< 103 DNS_R_DUPLICATE */
+ "duplicate query", /*%< 103 DNS_R_DUPLICATE */
+ "invalid NSEC3 owner name (wildcard)", /*%< 104 DNS_R_INVALIDNSEC3 */
};
static const char *rcode_text[DNS_R_NRCODERESULTS] = {
diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c
index a988bea..3c50a18 100644
--- a/lib/dns/rootns.c
+++ b/lib/dns/rootns.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rootns.c,v 1.26.18.7 2008/02/05 23:46:09 tbox Exp $ */
+/* $Id: rootns.c,v 1.36 2008/09/24 02:46:22 marka Exp $ */
/*! \file */
@@ -97,6 +97,7 @@ in_rootns(dns_rdataset_t *rootns, dns_name_t *name) {
if (dns_name_compare(name, &ns.name) == 0)
return (ISC_R_SUCCESS);
result = dns_rdataset_next(rootns);
+ dns_rdata_reset(&rdata);
}
if (result == ISC_R_NOMORE)
result = ISC_R_NOTFOUND;
@@ -158,7 +159,7 @@ check_hints(dns_db_t *db) {
dns_rdataset_init(&rootns);
(void)dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0,
now, NULL, name, &rootns, NULL);
- result = dns_db_createiterator(db, ISC_FALSE, &dbiter);
+ result = dns_db_createiterator(db, 0, &dbiter);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_dbiterator_first(dbiter);
@@ -338,6 +339,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
dns_rdataset_current(&rootrrset, &rdata);
if (!inrrset(&hintrrset, &rdata))
report(view, name, ISC_TRUE, &rdata);
@@ -345,6 +347,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
}
result = dns_rdataset_first(&hintrrset);
while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
dns_rdataset_current(&hintrrset, &rdata);
if (!inrrset(&rootrrset, &rdata))
report(view, name, ISC_FALSE, &rdata);
@@ -355,6 +358,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
dns_rdataset_current(&rootrrset, &rdata);
report(view, name, ISC_TRUE, &rdata);
result = dns_rdataset_next(&rootrrset);
@@ -377,6 +381,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
dns_rdataset_current(&rootrrset, &rdata);
if (!inrrset(&hintrrset, &rdata))
report(view, name, ISC_TRUE, &rdata);
@@ -385,6 +390,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
}
result = dns_rdataset_first(&hintrrset);
while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
dns_rdataset_current(&hintrrset, &rdata);
if (!inrrset(&rootrrset, &rdata))
report(view, name, ISC_FALSE, &rdata);
@@ -396,6 +402,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
dns_rdataset_current(&rootrrset, &rdata);
report(view, name, ISC_TRUE, &rdata);
dns_rdata_reset(&rdata);
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
index effb2bf..03fca9e 100644
--- a/lib/dns/sdb.c
+++ b/lib/dns/sdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdb.c,v 1.45.18.16 2008/01/17 23:45:58 tbox Exp $ */
+/* $Id: sdb.c,v 1.66.48.2 2009/04/21 23:47:18 tbox Exp $ */
/*! \file */
@@ -880,9 +880,12 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
{
result = DNS_R_ZONECUT;
dns_rdataset_disassociate(rdataset);
- if (sigrdataset != NULL)
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated
+ (sigrdataset)) {
dns_rdataset_disassociate
(sigrdataset);
+ }
} else
result = DNS_R_DELEGATION;
break;
@@ -1035,8 +1038,7 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
}
static isc_result_t
-createiterator(dns_db_t *db, isc_boolean_t relative_names,
- dns_dbiterator_t **iteratorp)
+createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
{
dns_sdb_t *sdb = (dns_sdb_t *)db;
sdb_dbiterator_t *sdbiter;
@@ -1048,6 +1050,10 @@ createiterator(dns_db_t *db, isc_boolean_t relative_names,
if (imp->methods->allnodes == NULL)
return (ISC_R_NOTIMPLEMENTED);
+ if ((options & DNS_DB_NSEC3ONLY) != 0 ||
+ (options & DNS_DB_NONSEC3) != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
if (sdbiter == NULL)
return (ISC_R_NOMEMORY);
@@ -1055,7 +1061,7 @@ createiterator(dns_db_t *db, isc_boolean_t relative_names,
sdbiter->common.methods = &dbiterator_methods;
sdbiter->common.db = NULL;
dns_db_attach(db, &sdbiter->common.db);
- sdbiter->common.relative_names = relative_names;
+ sdbiter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
ISC_LIST_INIT(sdbiter->nodelist);
sdbiter->current = NULL;
@@ -1246,6 +1252,14 @@ static dns_dbmethods_t sdb_methods = {
ispersistent,
overmem,
settask,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
NULL
};
@@ -1371,6 +1385,8 @@ static dns_rdatasetmethods_t methods = {
isc__rdatalist_getnoqname,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c
index b91f825..89cd0ee 100644
--- a/lib/dns/sdlz.c
+++ b/lib/dns/sdlz.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005-2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -50,7 +50,7 @@
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdlz.c,v 1.2.2.11 2007/08/28 07:20:05 tbox Exp $ */
+/* $Id: sdlz.c,v 1.18.50.2 2009/04/21 23:47:18 tbox Exp $ */
/*! \file */
@@ -667,8 +667,7 @@ printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
}
static isc_result_t
-createiterator(dns_db_t *db, isc_boolean_t relative_names,
- dns_dbiterator_t **iteratorp)
+createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
{
dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
sdlz_dbiterator_t *sdlziter;
@@ -681,6 +680,10 @@ createiterator(dns_db_t *db, isc_boolean_t relative_names,
if (sdlz->dlzimp->methods->allnodes == NULL)
return (ISC_R_NOTIMPLEMENTED);
+ if ((options & DNS_DB_NSEC3ONLY) != 0 ||
+ (options & DNS_DB_NONSEC3) != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
isc_buffer_init(&b, zonestr, sizeof(zonestr));
result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b);
if (result != ISC_R_SUCCESS)
@@ -694,7 +697,7 @@ createiterator(dns_db_t *db, isc_boolean_t relative_names,
sdlziter->common.methods = &dbiterator_methods;
sdlziter->common.db = NULL;
dns_db_attach(db, &sdlziter->common.db);
- sdlziter->common.relative_names = relative_names;
+ sdlziter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
ISC_LIST_INIT(sdlziter->nodelist);
sdlziter->current = NULL;
@@ -841,9 +844,12 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
{
result = DNS_R_ZONECUT;
dns_rdataset_disassociate(rdataset);
- if (sigrdataset != NULL)
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated
+ (sigrdataset)) {
dns_rdataset_disassociate
(sigrdataset);
+ }
} else
result = DNS_R_DELEGATION;
break;
@@ -1051,6 +1057,14 @@ static dns_dbmethods_t sdlzdb_methods = {
overmem,
settask,
NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
/*
@@ -1193,6 +1207,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
isc__rdatalist_getnoqname,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
@@ -1327,7 +1343,7 @@ dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
return (result);
isc_buffer_putuint8(&b2, 0);
- /* make sure strings are always lowercase */
+ /* make sure strings are always lowercase */
dns_sdlz_tolower(namestr);
dns_sdlz_tolower(clientstr);
@@ -1440,7 +1456,7 @@ dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
return (result);
isc_buffer_putuint8(&b, 0);
- /* make sure strings are always lowercase */
+ /* make sure strings are always lowercase */
dns_sdlz_tolower(namestr);
/* Call SDLZ driver's find zone method */
@@ -1571,7 +1587,7 @@ dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
return (ISC_R_SUCCESS);
failure:
- if (rdatabuf != NULL)
+ if (rdatabuf != NULL)
isc_buffer_free(&rdatabuf);
if (lex != NULL)
isc_lex_destroy(&lex);
diff --git a/lib/dns/soa.c b/lib/dns/soa.c
index 20198c0..83a1c17 100644
--- a/lib/dns/soa.c
+++ b/lib/dns/soa.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: soa.c,v 1.4.18.2 2005/04/29 00:16:05 marka Exp $ */
+/* $Id: soa.c,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/spnego.asn1 b/lib/dns/spnego.asn1
new file mode 100644
index 0000000..43d152b
--- /dev/null
+++ b/lib/dns/spnego.asn1
@@ -0,0 +1,52 @@
+-- Copyright (C) The Internet Society 2005. This version of
+-- this module is part of RFC 4178; see the RFC itself for
+-- full legal notices.
+
+-- (The above copyright notice is per RFC 3978 5.6 (a), q.v.)
+
+-- $Id: spnego.asn1,v 1.2 2006/12/04 01:52:46 marka Exp $
+
+-- This is the SPNEGO ASN.1 module from RFC 4178, tweaked
+-- to get the Heimdal ASN.1 compiler to accept it.
+
+SPNEGOASNOneSpec DEFINITIONS ::= BEGIN
+
+MechType ::= OBJECT IDENTIFIER
+
+MechTypeList ::= SEQUENCE OF MechType
+
+ContextFlags ::= BIT STRING {
+ delegFlag (0),
+ mutualFlag (1),
+ replayFlag (2),
+ sequenceFlag (3),
+ anonFlag (4),
+ confFlag (5),
+ integFlag (6)
+}
+
+NegTokenInit ::= SEQUENCE {
+ mechTypes [0] MechTypeList,
+ reqFlags [1] ContextFlags OPTIONAL,
+ mechToken [2] OCTET STRING OPTIONAL,
+ mechListMIC [3] OCTET STRING OPTIONAL
+}
+
+NegTokenResp ::= SEQUENCE {
+ negState [0] ENUMERATED {
+ accept-completed (0),
+ accept-incomplete (1),
+ reject (2),
+ request-mic (3)
+ } OPTIONAL,
+ supportedMech [1] MechType OPTIONAL,
+ responseToken [2] OCTET STRING OPTIONAL,
+ mechListMIC [3] OCTET STRING OPTIONAL
+}
+
+NegotiationToken ::= CHOICE {
+ negTokenInit [0] NegTokenInit,
+ negTokenResp [1] NegTokenResp
+}
+
+END
diff --git a/lib/dns/spnego.c b/lib/dns/spnego.c
new file mode 100644
index 0000000..0ae6ea2
--- /dev/null
+++ b/lib/dns/spnego.c
@@ -0,0 +1,1792 @@
+/*
+ * Copyright (C) 2006-2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: spnego.c,v 1.8.118.2 2009/01/18 23:47:40 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Portable SPNEGO implementation.
+ *
+ * This is part of a portable implementation of the SPNEGO protocol
+ * (RFCs 2478 and 4178). This implementation uses the RFC 4178 ASN.1
+ * module but is not a full implementation of the RFC 4178 protocol;
+ * at the moment, we only support GSS-TSIG with Kerberos
+ * authentication, so we only need enough of the SPNEGO protocol to
+ * support that.
+ *
+ * The files that make up this portable SPNEGO implementation are:
+ * \li spnego.c (this file)
+ * \li spnego.h (API SPNEGO exports to the rest of lib/dns)
+ * \li spnego.asn1 (SPNEGO ASN.1 module)
+ * \li spnego_asn1.c (routines generated from spngo.asn1)
+ * \li spnego_asn1.pl (perl script to generate spnego_asn1.c)
+ *
+ * Everything but the functions exported in spnego.h is static, to
+ * avoid possible conflicts with other libraries (particularly Heimdal,
+ * since much of this code comes from Heimdal by way of mod_auth_kerb).
+ *
+ * spnego_asn1.c is shipped as part of lib/dns because generating it
+ * requires both Perl and the Heimdal ASN.1 compiler. See
+ * spnego_asn1.pl for further details. We've tried to eliminate all
+ * compiler warnings from the generated code, but you may see a few
+ * when using a compiler version we haven't tested yet.
+ */
+
+/*
+ * Portions of this code were derived from mod_auth_kerb and Heimdal.
+ * These packages are available from:
+ *
+ * http://modauthkerb.sourceforge.net/
+ * http://www.pdc.kth.se/heimdal/
+ *
+ * and were released under the following licenses:
+ *
+ * ----------------------------------------------------------------
+ *
+ * Copyright (c) 2004 Masarykova universita
+ * (Masaryk University, Brno, Czech Republic)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------
+ *
+ * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * XXXSRA We should omit this file entirely in Makefile.in via autoconf,
+ * but this will keep it from generating errors until that's written.
+ */
+
+#ifdef GSSAPI
+
+/*
+ * XXXSRA Some of the following files are almost certainly unnecessary,
+ * but using this list (borrowed from gssapictx.c) gets rid of some
+ * whacky compilation errors when building with MSVC and should be
+ * harmless in any case.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/buffer.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/types.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+
+#include <dst/gssapi.h>
+#include <dst/result.h>
+
+#include "dst_internal.h"
+
+/*
+ * The API we export
+ */
+#include "spnego.h"
+
+/* asn1_err.h */
+/* Generated from ../../../lib/asn1/asn1_err.et */
+
+typedef enum asn1_error_number {
+ ASN1_BAD_TIMEFORMAT = 1859794432,
+ ASN1_MISSING_FIELD = 1859794433,
+ ASN1_MISPLACED_FIELD = 1859794434,
+ ASN1_TYPE_MISMATCH = 1859794435,
+ ASN1_OVERFLOW = 1859794436,
+ ASN1_OVERRUN = 1859794437,
+ ASN1_BAD_ID = 1859794438,
+ ASN1_BAD_LENGTH = 1859794439,
+ ASN1_BAD_FORMAT = 1859794440,
+ ASN1_PARSE_ERROR = 1859794441
+} asn1_error_number;
+
+#define ERROR_TABLE_BASE_asn1 1859794432
+
+#define __asn1_common_definitions__
+
+typedef struct octet_string {
+ size_t length;
+ void *data;
+} octet_string;
+
+typedef char *general_string;
+
+typedef char *utf8_string;
+
+typedef struct oid {
+ size_t length;
+ unsigned *components;
+} oid;
+
+/* der.h */
+
+typedef enum {
+ ASN1_C_UNIV = 0, ASN1_C_APPL = 1,
+ ASN1_C_CONTEXT = 2, ASN1_C_PRIVATE = 3
+} Der_class;
+
+typedef enum {
+ PRIM = 0, CONS = 1
+} Der_type;
+
+/* Universal tags */
+
+enum {
+ UT_Boolean = 1,
+ UT_Integer = 2,
+ UT_BitString = 3,
+ UT_OctetString = 4,
+ UT_Null = 5,
+ UT_OID = 6,
+ UT_Enumerated = 10,
+ UT_Sequence = 16,
+ UT_Set = 17,
+ UT_PrintableString = 19,
+ UT_IA5String = 22,
+ UT_UTCTime = 23,
+ UT_GeneralizedTime = 24,
+ UT_VisibleString = 26,
+ UT_GeneralString = 27
+};
+
+#define ASN1_INDEFINITE 0xdce0deed
+
+static int
+der_get_length(const unsigned char *p, size_t len,
+ size_t * val, size_t * size);
+
+static int
+der_get_octet_string(const unsigned char *p, size_t len,
+ octet_string * data, size_t * size);
+static int
+der_get_oid(const unsigned char *p, size_t len,
+ oid * data, size_t * size);
+static int
+der_get_tag(const unsigned char *p, size_t len,
+ Der_class * class, Der_type * type,
+ int *tag, size_t * size);
+
+static int
+der_match_tag(const unsigned char *p, size_t len,
+ Der_class class, Der_type type,
+ int tag, size_t * size);
+static int
+der_match_tag_and_length(const unsigned char *p, size_t len,
+ Der_class class, Der_type type, int tag,
+ size_t * length_ret, size_t * size);
+
+static int
+decode_oid(const unsigned char *p, size_t len,
+ oid * k, size_t * size);
+
+static int
+decode_enumerated(const unsigned char *p, size_t len,
+ unsigned *num, size_t *size);
+
+static int
+decode_octet_string(const unsigned char *, size_t, octet_string *, size_t *);
+
+static int
+der_put_int(unsigned char *p, size_t len, int val, size_t *);
+
+static int
+der_put_length(unsigned char *p, size_t len, size_t val, size_t *);
+
+static int
+der_put_octet_string(unsigned char *p, size_t len,
+ const octet_string * data, size_t *);
+static int
+der_put_oid(unsigned char *p, size_t len,
+ const oid * data, size_t * size);
+static int
+der_put_tag(unsigned char *p, size_t len, Der_class class, Der_type type,
+ int tag, size_t *);
+static int
+der_put_length_and_tag(unsigned char *, size_t, size_t,
+ Der_class, Der_type, int, size_t *);
+
+static int
+encode_enumerated(unsigned char *p, size_t len,
+ const unsigned *data, size_t *);
+
+static int
+encode_octet_string(unsigned char *p, size_t len,
+ const octet_string * k, size_t *);
+static int
+encode_oid(unsigned char *p, size_t len,
+ const oid * k, size_t *);
+
+static void
+free_octet_string(octet_string * k);
+
+static void
+free_oid (oid * k);
+
+static size_t
+length_len(size_t len);
+
+static int
+fix_dce(size_t reallen, size_t * len);
+
+/*
+ * Include stuff generated by the ASN.1 compiler.
+ */
+
+#include "spnego_asn1.c"
+
+static unsigned char gss_krb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+static gss_OID_desc gss_krb5_mech_oid_desc = {
+ sizeof(gss_krb5_mech_oid_bytes),
+ gss_krb5_mech_oid_bytes
+};
+
+static gss_OID GSS_KRB5_MECH = &gss_krb5_mech_oid_desc;
+
+static unsigned char gss_mskrb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+static gss_OID_desc gss_mskrb5_mech_oid_desc = {
+ sizeof(gss_mskrb5_mech_oid_bytes),
+ gss_mskrb5_mech_oid_bytes
+};
+
+static gss_OID GSS_MSKRB5_MECH = &gss_mskrb5_mech_oid_desc;
+
+static unsigned char gss_spnego_mech_oid_bytes[] = {
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
+};
+
+static gss_OID_desc gss_spnego_mech_oid_desc = {
+ sizeof(gss_spnego_mech_oid_bytes),
+ gss_spnego_mech_oid_bytes
+};
+
+static gss_OID GSS_SPNEGO_MECH = &gss_spnego_mech_oid_desc;
+
+/* spnegokrb5_locl.h */
+
+static OM_uint32
+gssapi_spnego_encapsulate(OM_uint32 *,
+ unsigned char *,
+ size_t,
+ gss_buffer_t,
+ const gss_OID);
+
+static OM_uint32
+gssapi_spnego_decapsulate(OM_uint32 *,
+ gss_buffer_t,
+ unsigned char **,
+ size_t *,
+ const gss_OID);
+
+/* mod_auth_kerb.c */
+
+static int
+cmp_gss_type(gss_buffer_t token, gss_OID oid)
+{
+ unsigned char *p;
+ size_t len;
+
+ if (token->length == 0)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ p = token->value;
+ if (*p++ != 0x60)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ len = *p++;
+ if (len & 0x80) {
+ if ((len & 0x7f) > 4)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += len & 0x7f;
+ }
+ if (*p++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ if (((OM_uint32) *p++) != oid->length)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ return (memcmp(p, oid->elements, oid->length));
+}
+
+/* accept_sec_context.c */
+/*
+ * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
+ * based on Heimdal code)
+ */
+
+static OM_uint32
+code_NegTokenArg(OM_uint32 * minor_status,
+ const NegTokenResp * resp,
+ unsigned char **outbuf,
+ size_t * outbuf_size)
+{
+ OM_uint32 ret;
+ u_char *buf;
+ size_t buf_size, buf_len;
+
+ buf_size = 1024;
+ buf = malloc(buf_size);
+ if (buf == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ do {
+ ret = encode_NegTokenResp(buf + buf_size - 1,
+ buf_size,
+ resp, &buf_len);
+ if (ret == 0) {
+ size_t tmp;
+
+ ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
+ buf_size - buf_len,
+ buf_len,
+ ASN1_C_CONTEXT,
+ CONS,
+ 1,
+ &tmp);
+ if (ret == 0)
+ buf_len += tmp;
+ }
+ if (ret) {
+ if (ret == ASN1_OVERFLOW) {
+ u_char *tmp;
+
+ buf_size *= 2;
+ tmp = realloc(buf, buf_size);
+ if (tmp == NULL) {
+ *minor_status = ENOMEM;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ buf = tmp;
+ } else {
+ *minor_status = ret;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ }
+ } while (ret == ASN1_OVERFLOW);
+
+ *outbuf = malloc(buf_len);
+ if (*outbuf == NULL) {
+ *minor_status = ENOMEM;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ memcpy(*outbuf, buf + buf_size - buf_len, buf_len);
+ *outbuf_size = buf_len;
+
+ free(buf);
+
+ return (GSS_S_COMPLETE);
+}
+
+static OM_uint32
+send_reject(OM_uint32 * minor_status,
+ gss_buffer_t output_token)
+{
+ NegTokenResp resp;
+ OM_uint32 ret;
+
+ resp.negState = malloc(sizeof(*resp.negState));
+ if (resp.negState == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ *(resp.negState) = reject;
+
+ resp.supportedMech = NULL;
+ resp.responseToken = NULL;
+ resp.mechListMIC = NULL;
+
+ ret = code_NegTokenArg(minor_status, &resp,
+ (unsigned char **)&output_token->value,
+ &output_token->length);
+ free_NegTokenResp(&resp);
+ if (ret)
+ return (ret);
+
+ return (GSS_S_BAD_MECH);
+}
+
+static OM_uint32
+send_accept(OM_uint32 * minor_status,
+ gss_buffer_t output_token,
+ gss_buffer_t mech_token,
+ const gss_OID pref)
+{
+ NegTokenResp resp;
+ OM_uint32 ret;
+
+ memset(&resp, 0, sizeof(resp));
+ resp.negState = malloc(sizeof(*resp.negState));
+ if (resp.negState == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ *(resp.negState) = accept_completed;
+
+ resp.supportedMech = malloc(sizeof(*resp.supportedMech));
+ if (resp.supportedMech == NULL) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ ret = der_get_oid(pref->elements,
+ pref->length,
+ resp.supportedMech,
+ NULL);
+ if (ret) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ if (mech_token != NULL && mech_token->length != 0) {
+ resp.responseToken = malloc(sizeof(*resp.responseToken));
+ if (resp.responseToken == NULL) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ resp.responseToken->length = mech_token->length;
+ resp.responseToken->data = mech_token->value;
+ }
+
+ ret = code_NegTokenArg(minor_status, &resp,
+ (unsigned char **)&output_token->value,
+ &output_token->length);
+ if (resp.responseToken != NULL) {
+ free(resp.responseToken);
+ resp.responseToken = NULL;
+ }
+ free_NegTokenResp(&resp);
+ if (ret)
+ return (ret);
+
+ return (GSS_S_COMPLETE);
+}
+
+OM_uint32
+gss_accept_sec_context_spnego(OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ const gss_cred_id_t acceptor_cred_handle,
+ const gss_buffer_t input_token_buffer,
+ const gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle)
+{
+ NegTokenInit init_token;
+ OM_uint32 major_status;
+ OM_uint32 minor_status2;
+ gss_buffer_desc ibuf, obuf;
+ gss_buffer_t ot = NULL;
+ gss_OID pref = GSS_KRB5_MECH;
+ unsigned char *buf;
+ size_t buf_size;
+ size_t len, taglen, ni_len;
+ int found = 0;
+ int ret;
+ unsigned i;
+
+ /*
+ * Before doing anything else, see whether this is a SPNEGO
+ * PDU. If not, dispatch to the GSSAPI library and get out.
+ */
+
+ if (cmp_gss_type(input_token_buffer, GSS_SPNEGO_MECH))
+ return (gss_accept_sec_context(minor_status,
+ context_handle,
+ acceptor_cred_handle,
+ input_token_buffer,
+ input_chan_bindings,
+ src_name,
+ mech_type,
+ output_token,
+ ret_flags,
+ time_rec,
+ delegated_cred_handle));
+
+ /*
+ * If we get here, it's SPNEGO.
+ */
+
+ memset(&init_token, 0, sizeof(init_token));
+
+ ret = gssapi_spnego_decapsulate(minor_status, input_token_buffer,
+ &buf, &buf_size, GSS_SPNEGO_MECH);
+ if (ret)
+ return (ret);
+
+ ret = der_match_tag_and_length(buf, buf_size, ASN1_C_CONTEXT, CONS,
+ 0, &len, &taglen);
+ if (ret)
+ return (ret);
+
+ ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);
+ if (ret) {
+ *minor_status = EINVAL; /* XXX */
+ return (GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ for (i = 0; !found && i < init_token.mechTypes.len; ++i) {
+ char mechbuf[17];
+ size_t mech_len;
+
+ ret = der_put_oid(mechbuf + sizeof(mechbuf) - 1,
+ sizeof(mechbuf),
+ &init_token.mechTypes.val[i],
+ &mech_len);
+ if (ret)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ if (mech_len == GSS_KRB5_MECH->length &&
+ memcmp(GSS_KRB5_MECH->elements,
+ mechbuf + sizeof(mechbuf) - mech_len,
+ mech_len) == 0) {
+ found = 1;
+ break;
+ }
+ if (mech_len == GSS_MSKRB5_MECH->length &&
+ memcmp(GSS_MSKRB5_MECH->elements,
+ mechbuf + sizeof(mechbuf) - mech_len,
+ mech_len) == 0) {
+ found = 1;
+ if (i == 0)
+ pref = GSS_MSKRB5_MECH;
+ break;
+ }
+ }
+
+ if (!found)
+ return (send_reject(minor_status, output_token));
+
+ if (i == 0 && init_token.mechToken != NULL) {
+ ibuf.length = init_token.mechToken->length;
+ ibuf.value = init_token.mechToken->data;
+
+ major_status = gss_accept_sec_context(minor_status,
+ context_handle,
+ acceptor_cred_handle,
+ &ibuf,
+ input_chan_bindings,
+ src_name,
+ mech_type,
+ &obuf,
+ ret_flags,
+ time_rec,
+ delegated_cred_handle);
+ if (GSS_ERROR(major_status)) {
+ send_reject(&minor_status2, output_token);
+ return (major_status);
+ }
+ ot = &obuf;
+ }
+ ret = send_accept(&minor_status2, output_token, ot, pref);
+ if (ot != NULL && ot->length != 0)
+ gss_release_buffer(&minor_status2, ot);
+
+ return (ret);
+}
+
+/* decapsulate.c */
+
+static OM_uint32
+gssapi_verify_mech_header(u_char ** str,
+ size_t total_len,
+ const gss_OID mech)
+{
+ size_t len, len_len, mech_len, foo;
+ int e;
+ u_char *p = *str;
+
+ if (total_len < 1)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ if (*p++ != 0x60)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ e = der_get_length(p, total_len - 1, &len, &len_len);
+ if (e || 1 + len_len + len != total_len)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += len_len;
+ if (*p++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ e = der_get_length(p, total_len - 1 - len_len - 1,
+ &mech_len, &foo);
+ if (e)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += foo;
+ if (mech_len != mech->length)
+ return (GSS_S_BAD_MECH);
+ if (memcmp(p, mech->elements, mech->length) != 0)
+ return (GSS_S_BAD_MECH);
+ p += mech_len;
+ *str = p;
+ return (GSS_S_COMPLETE);
+}
+
+/*
+ * Remove the GSS-API wrapping from `in_token' giving `buf and buf_size' Does
+ * not copy data, so just free `in_token'.
+ */
+
+static OM_uint32
+gssapi_spnego_decapsulate(OM_uint32 *minor_status,
+ gss_buffer_t input_token_buffer,
+ unsigned char **buf,
+ size_t *buf_len,
+ const gss_OID mech)
+{
+ u_char *p;
+ OM_uint32 ret;
+
+ p = input_token_buffer->value;
+ ret = gssapi_verify_mech_header(&p,
+ input_token_buffer->length,
+ mech);
+ if (ret) {
+ *minor_status = ret;
+ return (GSS_S_FAILURE);
+ }
+ *buf_len = input_token_buffer->length -
+ (p - (u_char *) input_token_buffer->value);
+ *buf = p;
+ return (GSS_S_COMPLETE);
+}
+
+/* der_free.c */
+
+static void
+free_octet_string(octet_string *k)
+{
+ free(k->data);
+ k->data = NULL;
+}
+
+static void
+free_oid(oid *k)
+{
+ free(k->components);
+ k->components = NULL;
+}
+
+/* der_get.c */
+
+/*
+ * All decoding functions take a pointer `p' to first position in which to
+ * read, from the left, `len' which means the maximum number of characters we
+ * are able to read, `ret' were the value will be returned and `size' where
+ * the number of used bytes is stored. Either 0 or an error code is returned.
+ */
+
+static int
+der_get_unsigned(const unsigned char *p, size_t len,
+ unsigned *ret, size_t *size)
+{
+ unsigned val = 0;
+ size_t oldlen = len;
+
+ while (len--)
+ val = val * 256 + *p++;
+ *ret = val;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_int(const unsigned char *p, size_t len,
+ int *ret, size_t *size)
+{
+ int val = 0;
+ size_t oldlen = len;
+
+ if (len > 0) {
+ val = (signed char)*p++;
+ while (--len)
+ val = val * 256 + *p++;
+ }
+ *ret = val;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_length(const unsigned char *p, size_t len,
+ size_t *val, size_t *size)
+{
+ size_t v;
+
+ if (len <= 0)
+ return (ASN1_OVERRUN);
+ --len;
+ v = *p++;
+ if (v < 128) {
+ *val = v;
+ if (size)
+ *size = 1;
+ } else {
+ int e;
+ size_t l;
+ unsigned tmp;
+
+ if (v == 0x80) {
+ *val = ASN1_INDEFINITE;
+ if (size)
+ *size = 1;
+ return (0);
+ }
+ v &= 0x7F;
+ if (len < v)
+ return (ASN1_OVERRUN);
+ e = der_get_unsigned(p, v, &tmp, &l);
+ if (e)
+ return (e);
+ *val = tmp;
+ if (size)
+ *size = l + 1;
+ }
+ return (0);
+}
+
+static int
+der_get_octet_string(const unsigned char *p, size_t len,
+ octet_string *data, size_t *size)
+{
+ data->length = len;
+ data->data = malloc(len);
+ if (data->data == NULL && data->length != 0)
+ return (ENOMEM);
+ memcpy(data->data, p, len);
+ if (size)
+ *size = len;
+ return (0);
+}
+
+static int
+der_get_oid(const unsigned char *p, size_t len,
+ oid *data, size_t *size)
+{
+ int n;
+ size_t oldlen = len;
+
+ if (len < 1)
+ return (ASN1_OVERRUN);
+
+ data->components = malloc(len * sizeof(*data->components));
+ if (data->components == NULL && len != 0)
+ return (ENOMEM);
+ data->components[0] = (*p) / 40;
+ data->components[1] = (*p) % 40;
+ --len;
+ ++p;
+ for (n = 2; len > 0; ++n) {
+ unsigned u = 0;
+
+ do {
+ --len;
+ u = u * 128 + (*p++ % 128);
+ } while (len > 0 && p[-1] & 0x80);
+ data->components[n] = u;
+ }
+ if (p[-1] & 0x80) {
+ free_oid(data);
+ return (ASN1_OVERRUN);
+ }
+ data->length = n;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_tag(const unsigned char *p, size_t len,
+ Der_class *class, Der_type *type,
+ int *tag, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERRUN);
+ *class = (Der_class) (((*p) >> 6) & 0x03);
+ *type = (Der_type) (((*p) >> 5) & 0x01);
+ *tag = (*p) & 0x1F;
+ if (size)
+ *size = 1;
+ return (0);
+}
+
+static int
+der_match_tag(const unsigned char *p, size_t len,
+ Der_class class, Der_type type,
+ int tag, size_t *size)
+{
+ size_t l;
+ Der_class thisclass;
+ Der_type thistype;
+ int thistag;
+ int e;
+
+ e = der_get_tag(p, len, &thisclass, &thistype, &thistag, &l);
+ if (e)
+ return (e);
+ if (class != thisclass || type != thistype)
+ return (ASN1_BAD_ID);
+ if (tag > thistag)
+ return (ASN1_MISPLACED_FIELD);
+ if (tag < thistag)
+ return (ASN1_MISSING_FIELD);
+ if (size)
+ *size = l;
+ return (0);
+}
+
+static int
+der_match_tag_and_length(const unsigned char *p, size_t len,
+ Der_class class, Der_type type, int tag,
+ size_t *length_ret, size_t *size)
+{
+ size_t l, ret = 0;
+ int e;
+
+ e = der_match_tag(p, len, class, type, tag, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, length_ret, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_enumerated(const unsigned char *p, size_t len,
+ unsigned *num, size_t *size)
+{
+ size_t ret = 0;
+ size_t l, reallen;
+ int e;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &reallen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_int(p, reallen, num, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_octet_string(const unsigned char *p, size_t len,
+ octet_string *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+ size_t slen;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+
+ e = der_get_length(p, len, &slen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (len < slen)
+ return (ASN1_OVERRUN);
+
+ e = der_get_octet_string(p, slen, k, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_oid(const unsigned char *p, size_t len,
+ oid *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+ size_t slen;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OID, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+
+ e = der_get_length(p, len, &slen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (len < slen)
+ return (ASN1_OVERRUN);
+
+ e = der_get_oid(p, slen, k, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+fix_dce(size_t reallen, size_t *len)
+{
+ if (reallen == ASN1_INDEFINITE)
+ return (1);
+ if (*len < reallen)
+ return (-1);
+ *len = reallen;
+ return (0);
+}
+
+/* der_length.c */
+
+static size_t
+len_unsigned(unsigned val)
+{
+ size_t ret = 0;
+
+ do {
+ ++ret;
+ val /= 256;
+ } while (val);
+ return (ret);
+}
+
+static size_t
+length_len(size_t len)
+{
+ if (len < 128)
+ return (1);
+ else
+ return (len_unsigned(len) + 1);
+}
+
+
+/* der_put.c */
+
+/*
+ * All encoding functions take a pointer `p' to first position in which to
+ * write, from the right, `len' which means the maximum number of characters
+ * we are able to write. The function returns the number of characters
+ * written in `size' (if non-NULL). The return value is 0 or an error.
+ */
+
+static int
+der_put_unsigned(unsigned char *p, size_t len, unsigned val, size_t *size)
+{
+ unsigned char *base = p;
+
+ if (val) {
+ while (len > 0 && val) {
+ *p-- = val % 256;
+ val /= 256;
+ --len;
+ }
+ if (val != 0)
+ return (ASN1_OVERFLOW);
+ else {
+ *size = base - p;
+ return (0);
+ }
+ } else if (len < 1)
+ return (ASN1_OVERFLOW);
+ else {
+ *p = 0;
+ *size = 1;
+ return (0);
+ }
+}
+
+static int
+der_put_int(unsigned char *p, size_t len, int val, size_t *size)
+{
+ unsigned char *base = p;
+
+ if (val >= 0) {
+ do {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = val % 256;
+ len--;
+ val /= 256;
+ } while (val);
+ if (p[1] >= 128) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 0;
+ len--;
+ }
+ } else {
+ val = ~val;
+ do {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = ~(val % 256);
+ len--;
+ val /= 256;
+ } while (val);
+ if (p[1] < 128) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 0xff;
+ len--;
+ }
+ }
+ *size = base - p;
+ return (0);
+}
+
+static int
+der_put_length(unsigned char *p, size_t len, size_t val, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ if (val < 128) {
+ *p = val;
+ *size = 1;
+ return (0);
+ } else {
+ size_t l;
+ int e;
+
+ e = der_put_unsigned(p, len - 1, val, &l);
+ if (e)
+ return (e);
+ p -= l;
+ *p = 0x80 | l;
+ *size = l + 1;
+ return (0);
+ }
+}
+
+static int
+der_put_octet_string(unsigned char *p, size_t len,
+ const octet_string *data, size_t *size)
+{
+ if (len < data->length)
+ return (ASN1_OVERFLOW);
+ p -= data->length;
+ len -= data->length;
+ memcpy(p + 1, data->data, data->length);
+ *size = data->length;
+ return (0);
+}
+
+static int
+der_put_oid(unsigned char *p, size_t len,
+ const oid *data, size_t *size)
+{
+ unsigned char *base = p;
+ int n;
+
+ for (n = data->length - 1; n >= 2; --n) {
+ unsigned u = data->components[n];
+
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = u % 128;
+ u /= 128;
+ --len;
+ while (u > 0) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 128 + u % 128;
+ u /= 128;
+ --len;
+ }
+ }
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 40 * data->components[0] + data->components[1];
+ *size = base - p;
+ return (0);
+}
+
+static int
+der_put_tag(unsigned char *p, size_t len, Der_class class, Der_type type,
+ int tag, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p = (class << 6) | (type << 5) | tag; /* XXX */
+ *size = 1;
+ return (0);
+}
+
+static int
+der_put_length_and_tag(unsigned char *p, size_t len, size_t len_val,
+ Der_class class, Der_type type, int tag, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_length(p, len, len_val, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_tag(p, len, class, type, tag, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_enumerated(unsigned char *p, size_t len, const unsigned *data,
+ size_t *size)
+{
+ unsigned num = *data;
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_int(p, len, num, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_octet_string(unsigned char *p, size_t len,
+ const octet_string *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_octet_string(p, len, k, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_oid(unsigned char *p, size_t len,
+ const oid *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_oid(p, len, k, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OID, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+
+/* encapsulate.c */
+
+static void
+gssapi_encap_length(size_t data_len,
+ size_t *len,
+ size_t *total_len,
+ const gss_OID mech)
+{
+ size_t len_len;
+
+ *len = 1 + 1 + mech->length + data_len;
+
+ len_len = length_len(*len);
+
+ *total_len = 1 + len_len + *len;
+}
+
+static u_char *
+gssapi_mech_make_header(u_char *p,
+ size_t len,
+ const gss_OID mech)
+{
+ int e;
+ size_t len_len, foo;
+
+ *p++ = 0x60;
+ len_len = length_len(len);
+ e = der_put_length(p + len_len - 1, len_len, len, &foo);
+ if (e || foo != len_len)
+ return (NULL);
+ p += len_len;
+ *p++ = 0x06;
+ *p++ = mech->length;
+ memcpy(p, mech->elements, mech->length);
+ p += mech->length;
+ return (p);
+}
+
+/*
+ * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
+ */
+
+static OM_uint32
+gssapi_spnego_encapsulate(OM_uint32 * minor_status,
+ unsigned char *buf,
+ size_t buf_size,
+ gss_buffer_t output_token,
+ const gss_OID mech)
+{
+ size_t len, outer_len;
+ u_char *p;
+
+ gssapi_encap_length(buf_size, &len, &outer_len, mech);
+
+ output_token->length = outer_len;
+ output_token->value = malloc(outer_len);
+ if (output_token->value == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ p = gssapi_mech_make_header(output_token->value, len, mech);
+ if (p == NULL) {
+ if (output_token->length != 0)
+ gss_release_buffer(minor_status, output_token);
+ return (GSS_S_FAILURE);
+ }
+ memcpy(p, buf, buf_size);
+ return (GSS_S_COMPLETE);
+}
+
+/* init_sec_context.c */
+/*
+ * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
+ * based on Heimdal code)
+ */
+
+static int
+add_mech(MechTypeList * mech_list, gss_OID mech)
+{
+ MechType *tmp;
+ int ret;
+
+ tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
+ if (tmp == NULL)
+ return (ENOMEM);
+ mech_list->val = tmp;
+
+ ret = der_get_oid(mech->elements, mech->length,
+ &mech_list->val[mech_list->len], NULL);
+ if (ret)
+ return (ret);
+
+ mech_list->len++;
+ return (0);
+}
+
+/*
+ * return the length of the mechanism in token or -1
+ * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
+ */
+
+static ssize_t
+gssapi_krb5_get_mech(const u_char *ptr,
+ size_t total_len,
+ const u_char **mech_ret)
+{
+ size_t len, len_len, mech_len, foo;
+ const u_char *p = ptr;
+ int e;
+
+ if (total_len < 1)
+ return (-1);
+ if (*p++ != 0x60)
+ return (-1);
+ e = der_get_length (p, total_len - 1, &len, &len_len);
+ if (e || 1 + len_len + len != total_len)
+ return (-1);
+ p += len_len;
+ if (*p++ != 0x06)
+ return (-1);
+ e = der_get_length (p, total_len - 1 - len_len - 1,
+ &mech_len, &foo);
+ if (e)
+ return (-1);
+ p += foo;
+ *mech_ret = p;
+ return (mech_len);
+}
+
+static OM_uint32
+spnego_initial(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ NegTokenInit token_init;
+ OM_uint32 major_status, minor_status2;
+ gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
+ unsigned char *buf = NULL;
+ size_t buf_size;
+ size_t len;
+ int ret;
+
+ (void)mech_type;
+
+ memset(&token_init, 0, sizeof(token_init));
+
+ ret = add_mech(&token_init.mechTypes, GSS_KRB5_MECH);
+ if (ret) {
+ *minor_status = ret;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+
+ major_status = gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ &krb5_output_token,
+ ret_flags,
+ time_rec);
+ if (GSS_ERROR(major_status)) {
+ ret = major_status;
+ goto end;
+ }
+ if (krb5_output_token.length > 0) {
+ token_init.mechToken = malloc(sizeof(*token_init.mechToken));
+ if (token_init.mechToken == NULL) {
+ *minor_status = ENOMEM;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ token_init.mechToken->data = krb5_output_token.value;
+ token_init.mechToken->length = krb5_output_token.length;
+ }
+ /*
+ * The MS implementation of SPNEGO seems to not like the mechListMIC
+ * field, so we omit it (it's optional anyway)
+ */
+
+ buf_size = 1024;
+ buf = malloc(buf_size);
+
+ do {
+ ret = encode_NegTokenInit(buf + buf_size - 1,
+ buf_size,
+ &token_init, &len);
+ if (ret == 0) {
+ size_t tmp;
+
+ ret = der_put_length_and_tag(buf + buf_size - len - 1,
+ buf_size - len,
+ len,
+ ASN1_C_CONTEXT,
+ CONS,
+ 0,
+ &tmp);
+ if (ret == 0)
+ len += tmp;
+ }
+ if (ret) {
+ if (ret == ASN1_OVERFLOW) {
+ u_char *tmp;
+
+ buf_size *= 2;
+ tmp = realloc(buf, buf_size);
+ if (tmp == NULL) {
+ *minor_status = ENOMEM;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ buf = tmp;
+ } else {
+ *minor_status = ret;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ }
+ } while (ret == ASN1_OVERFLOW);
+
+ ret = gssapi_spnego_encapsulate(minor_status,
+ buf + buf_size - len, len,
+ output_token, GSS_SPNEGO_MECH);
+ if (ret == GSS_S_COMPLETE)
+ ret = major_status;
+
+end:
+ if (token_init.mechToken != NULL) {
+ free(token_init.mechToken);
+ token_init.mechToken = NULL;
+ }
+ free_NegTokenInit(&token_init);
+ if (krb5_output_token.length != 0)
+ gss_release_buffer(&minor_status2, &krb5_output_token);
+ if (buf)
+ free(buf);
+
+ return (ret);
+}
+
+static OM_uint32
+spnego_reply(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ OM_uint32 ret;
+ NegTokenResp resp;
+ unsigned char *buf;
+ size_t buf_size;
+ u_char oidbuf[17];
+ size_t oidlen;
+ gss_buffer_desc sub_token;
+ ssize_t mech_len;
+ const u_char *p;
+ size_t len, taglen;
+
+ (void)mech_type;
+
+ output_token->length = 0;
+ output_token->value = NULL;
+
+ /*
+ * SPNEGO doesn't include gss wrapping on SubsequentContextToken
+ * like the Kerberos 5 mech does. But lets check for it anyway.
+ */
+
+ mech_len = gssapi_krb5_get_mech(input_token->value,
+ input_token->length,
+ &p);
+
+ if (mech_len < 0) {
+ buf = input_token->value;
+ buf_size = input_token->length;
+ } else if ((size_t)mech_len == GSS_KRB5_MECH->length &&
+ memcmp(GSS_KRB5_MECH->elements, p, mech_len) == 0)
+ return (gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+ else if ((size_t)mech_len == GSS_SPNEGO_MECH->length &&
+ memcmp(GSS_SPNEGO_MECH->elements, p, mech_len) == 0) {
+ ret = gssapi_spnego_decapsulate(minor_status,
+ input_token,
+ &buf,
+ &buf_size,
+ GSS_SPNEGO_MECH);
+ if (ret)
+ return (ret);
+ } else
+ return (GSS_S_BAD_MECH);
+
+ ret = der_match_tag_and_length(buf, buf_size,
+ ASN1_C_CONTEXT, CONS, 1, &len, &taglen);
+ if (ret)
+ return (ret);
+
+ if(len > buf_size - taglen)
+ return (ASN1_OVERRUN);
+
+ ret = decode_NegTokenResp(buf + taglen, len, &resp, NULL);
+ if (ret) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+
+ if (resp.negState == NULL ||
+ *(resp.negState) == reject ||
+ resp.supportedMech == NULL) {
+ free_NegTokenResp(&resp);
+ return (GSS_S_BAD_MECH);
+ }
+
+ ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1,
+ sizeof(oidbuf),
+ resp.supportedMech,
+ &oidlen);
+ if (ret || oidlen != GSS_KRB5_MECH->length ||
+ memcmp(oidbuf + sizeof(oidbuf) - oidlen,
+ GSS_KRB5_MECH->elements,
+ oidlen) != 0) {
+ free_NegTokenResp(&resp);
+ return GSS_S_BAD_MECH;
+ }
+
+ if (resp.responseToken != NULL) {
+ sub_token.length = resp.responseToken->length;
+ sub_token.value = resp.responseToken->data;
+ } else {
+ sub_token.length = 0;
+ sub_token.value = NULL;
+ }
+
+ ret = gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ &sub_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec);
+ if (ret) {
+ free_NegTokenResp(&resp);
+ return (ret);
+ }
+
+ /*
+ * XXXSRA I don't think this limited implementation ever needs
+ * to check the MIC -- our preferred mechanism (Kerberos)
+ * authenticates its own messages and is the only mechanism
+ * we'll accept, so if the mechanism negotiation completes
+ * successfully, we don't need the MIC. See RFC 4178.
+ */
+
+ free_NegTokenResp(&resp);
+ return (ret);
+}
+
+
+
+OM_uint32
+gss_init_sec_context_spnego(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ /* Dirty trick to suppress compiler warnings */
+
+ /* Figure out whether we're starting over or processing a reply */
+
+ if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
+ return (spnego_initial(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+ else
+ return (spnego_reply(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+}
+
+#endif /* GSSAPI */
diff --git a/lib/dns/spnego.h b/lib/dns/spnego.h
new file mode 100644
index 0000000..c44614b
--- /dev/null
+++ b/lib/dns/spnego.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: spnego.h,v 1.4 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Entry points into portable SPNEGO implementation.
+ * See spnego.c for information on the SPNEGO implementation itself.
+ */
+
+#ifndef _SPNEGO_H_
+#define _SPNEGO_H_
+
+/*%
+ * Wrapper for GSSAPI gss_init_sec_context(), using portable SPNEGO
+ * implementation instead of the one that's part of the GSSAPI
+ * library. Takes arguments identical to the standard GSSAPI
+ * function, uses standard gss_init_sec_context() to handle
+ * everything inside the SPNEGO wrapper.
+ */
+OM_uint32
+gss_init_sec_context_spnego(OM_uint32 *,
+ const gss_cred_id_t,
+ gss_ctx_id_t *,
+ const gss_name_t,
+ const gss_OID,
+ OM_uint32,
+ OM_uint32,
+ const gss_channel_bindings_t,
+ const gss_buffer_t,
+ gss_OID *,
+ gss_buffer_t,
+ OM_uint32 *,
+ OM_uint32 *);
+
+/*%
+ * Wrapper for GSSAPI gss_accept_sec_context(), using portable SPNEGO
+ * implementation instead of the one that's part of the GSSAPI
+ * library. Takes arguments identical to the standard GSSAPI
+ * function. Checks the OID of the input token to see if it's SPNEGO;
+ * if so, processes it, otherwise hands the call off to the standard
+ * gss_accept_sec_context() function.
+ */
+OM_uint32 gss_accept_sec_context_spnego(OM_uint32 *,
+ gss_ctx_id_t *,
+ const gss_cred_id_t,
+ const gss_buffer_t,
+ const gss_channel_bindings_t,
+ gss_name_t *,
+ gss_OID *,
+ gss_buffer_t,
+ OM_uint32 *,
+ OM_uint32 *,
+ gss_cred_id_t *);
+
+
+#endif
diff --git a/lib/dns/spnego_asn1.c b/lib/dns/spnego_asn1.c
new file mode 100644
index 0000000..75c2304
--- /dev/null
+++ b/lib/dns/spnego_asn1.c
@@ -0,0 +1,885 @@
+/*
+ * Copyright (C) 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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: spnego_asn1.c,v 1.4 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file
+ * \brief Method routines generated from SPNEGO ASN.1 module.
+ * See spnego_asn1.pl for details. Do not edit.
+ */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+#ifndef __asn1_h__
+#define __asn1_h__
+
+
+#ifndef __asn1_common_definitions__
+#define __asn1_common_definitions__
+
+typedef struct octet_string {
+ size_t length;
+ void *data;
+} octet_string;
+
+typedef char *general_string;
+
+typedef char *utf8_string;
+
+typedef struct oid {
+ size_t length;
+ unsigned *components;
+} oid;
+
+#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \
+ do { \
+ (BL) = length_##T((S)); \
+ (B) = malloc((BL)); \
+ if((B) == NULL) { \
+ (R) = ENOMEM; \
+ } else { \
+ (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \
+ (S), (L)); \
+ if((R) != 0) { \
+ free((B)); \
+ (B) = NULL; \
+ } \
+ } \
+ } while (0)
+
+#endif
+
+/*
+ * MechType ::= OBJECT IDENTIFIER
+ */
+
+typedef oid MechType;
+
+static int encode_MechType(unsigned char *, size_t, const MechType *, size_t *);
+static int decode_MechType(const unsigned char *, size_t, MechType *, size_t *);
+static void free_MechType(MechType *);
+/* unused declaration: length_MechType */
+/* unused declaration: copy_MechType */
+
+
+/*
+ * MechTypeList ::= SEQUENCE OF MechType
+ */
+
+typedef struct MechTypeList {
+ unsigned int len;
+ MechType *val;
+} MechTypeList;
+
+static int encode_MechTypeList(unsigned char *, size_t, const MechTypeList *, size_t *);
+static int decode_MechTypeList(const unsigned char *, size_t, MechTypeList *, size_t *);
+static void free_MechTypeList(MechTypeList *);
+/* unused declaration: length_MechTypeList */
+/* unused declaration: copy_MechTypeList */
+
+
+/*
+ * ContextFlags ::= BIT STRING { delegFlag(0), mutualFlag(1), replayFlag(2),
+ * sequenceFlag(3), anonFlag(4), confFlag(5), integFlag(6) }
+ */
+
+typedef struct ContextFlags {
+ unsigned int delegFlag:1;
+ unsigned int mutualFlag:1;
+ unsigned int replayFlag:1;
+ unsigned int sequenceFlag:1;
+ unsigned int anonFlag:1;
+ unsigned int confFlag:1;
+ unsigned int integFlag:1;
+} ContextFlags;
+
+
+static int encode_ContextFlags(unsigned char *, size_t, const ContextFlags *, size_t *);
+static int decode_ContextFlags(const unsigned char *, size_t, ContextFlags *, size_t *);
+static void free_ContextFlags(ContextFlags *);
+/* unused declaration: length_ContextFlags */
+/* unused declaration: copy_ContextFlags */
+/* unused declaration: ContextFlags2int */
+/* unused declaration: int2ContextFlags */
+/* unused declaration: asn1_ContextFlags_units */
+
+/*
+ * NegTokenInit ::= SEQUENCE { mechTypes[0] MechTypeList, reqFlags[1]
+ * ContextFlags OPTIONAL, mechToken[2] OCTET STRING OPTIONAL,
+ * mechListMIC[3] OCTET STRING OPTIONAL }
+ */
+
+typedef struct NegTokenInit {
+ MechTypeList mechTypes;
+ ContextFlags *reqFlags;
+ octet_string *mechToken;
+ octet_string *mechListMIC;
+} NegTokenInit;
+
+static int encode_NegTokenInit(unsigned char *, size_t, const NegTokenInit *, size_t *);
+static int decode_NegTokenInit(const unsigned char *, size_t, NegTokenInit *, size_t *);
+static void free_NegTokenInit(NegTokenInit *);
+/* unused declaration: length_NegTokenInit */
+/* unused declaration: copy_NegTokenInit */
+
+
+/*
+ * NegTokenResp ::= SEQUENCE { negState[0] ENUMERATED {
+ * accept-completed(0), accept-incomplete(1), reject(2), request-mic(3) }
+ * OPTIONAL, supportedMech[1] MechType OPTIONAL, responseToken[2] OCTET
+ * STRING OPTIONAL, mechListMIC[3] OCTET STRING OPTIONAL }
+ */
+
+typedef struct NegTokenResp {
+ enum {
+ accept_completed = 0,
+ accept_incomplete = 1,
+ reject = 2,
+ request_mic = 3
+ } *negState;
+
+ MechType *supportedMech;
+ octet_string *responseToken;
+ octet_string *mechListMIC;
+} NegTokenResp;
+
+static int encode_NegTokenResp(unsigned char *, size_t, const NegTokenResp *, size_t *);
+static int decode_NegTokenResp(const unsigned char *, size_t, NegTokenResp *, size_t *);
+static void free_NegTokenResp(NegTokenResp *);
+/* unused declaration: length_NegTokenResp */
+/* unused declaration: copy_NegTokenResp */
+
+
+
+
+#endif /* __asn1_h__ */
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_MechType(unsigned char *p, size_t len, const MechType * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ e = encode_oid(p, len, data, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_MechType(const unsigned char *p, size_t len, MechType * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = decode_oid(p, len, data, &l);
+ FORW;
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_MechType(data);
+ return e;
+}
+
+static void
+free_MechType(MechType * data)
+{
+ free_oid(data);
+}
+
+/* unused function: length_MechType */
+
+
+/* unused function: copy_MechType */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_MechTypeList(unsigned char *p, size_t len, const MechTypeList * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ for (i = (data)->len - 1; i >= 0; --i) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechType(p, len, &(data)->val[i], &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_MechTypeList(const unsigned char *p, size_t len, MechTypeList * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ if (len < reallen)
+ return ASN1_OVERRUN;
+ len = reallen;
+ {
+ size_t origlen = len;
+ int oldret = ret;
+ ret = 0;
+ (data)->len = 0;
+ (data)->val = NULL;
+ while (ret < origlen) {
+ (data)->len++;
+ (data)->val = realloc((data)->val, sizeof(*((data)->val)) * (data)->len);
+ e = decode_MechType(p, len, &(data)->val[(data)->len - 1], &l);
+ FORW;
+ len = origlen - ret;
+ }
+ ret += oldret;
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_MechTypeList(data);
+ return e;
+}
+
+static void
+free_MechTypeList(MechTypeList * data)
+{
+ while ((data)->len) {
+ free_MechType(&(data)->val[(data)->len - 1]);
+ (data)->len--;
+ }
+ free((data)->val);
+ (data)->val = NULL;
+}
+
+/* unused function: length_MechTypeList */
+
+
+/* unused function: copy_MechTypeList */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_ContextFlags(unsigned char *p, size_t len, const ContextFlags * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ {
+ unsigned char c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ if (data->integFlag)
+ c |= 1 << 1;
+ if (data->confFlag)
+ c |= 1 << 2;
+ if (data->anonFlag)
+ c |= 1 << 3;
+ if (data->sequenceFlag)
+ c |= 1 << 4;
+ if (data->replayFlag)
+ c |= 1 << 5;
+ if (data->mutualFlag)
+ c |= 1 << 6;
+ if (data->delegFlag)
+ c |= 1 << 7;
+ *p-- = c;
+ *p-- = 0;
+ len -= 2;
+ ret += 2;
+ }
+
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, PRIM, UT_BitString, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_ContextFlags(const unsigned char *p, size_t len, ContextFlags * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, PRIM, UT_BitString, &reallen, &l);
+ FORW;
+ if (len < reallen)
+ return ASN1_OVERRUN;
+ p++;
+ len--;
+ reallen--;
+ ret++;
+ data->delegFlag = (*p >> 7) & 1;
+ data->mutualFlag = (*p >> 6) & 1;
+ data->replayFlag = (*p >> 5) & 1;
+ data->sequenceFlag = (*p >> 4) & 1;
+ data->anonFlag = (*p >> 3) & 1;
+ data->confFlag = (*p >> 2) & 1;
+ data->integFlag = (*p >> 1) & 1;
+ p += reallen;
+ len -= reallen;
+ ret += reallen;
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_ContextFlags(data);
+ return e;
+}
+
+static void
+free_ContextFlags(ContextFlags * data)
+{
+ (void)data;
+}
+
+/* unused function: length_ContextFlags */
+
+
+/* unused function: copy_ContextFlags */
+
+
+/* unused function: ContextFlags2int */
+
+
+/* unused function: int2ContextFlags */
+
+
+/* unused variable: ContextFlags_units */
+
+/* unused function: asn1_ContextFlags_units */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_NegTokenInit(unsigned char *p, size_t len, const NegTokenInit * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ if ((data)->mechListMIC) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechListMIC, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 3, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->mechToken) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechToken, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 2, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->reqFlags) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_ContextFlags(p, len, (data)->reqFlags, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 1, &l);
+ BACK;
+ ret += oldret;
+ } {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechTypeList(p, len, &(data)->mechTypes, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 0, &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_NegTokenInit(const unsigned char *p, size_t len, NegTokenInit * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ {
+ int dce_fix;
+ if ((dce_fix = fix_dce(reallen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 0, &l);
+ if (e)
+ return e;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ e = decode_MechTypeList(p, len, &(data)->mechTypes, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 1, &l);
+ if (e)
+ (data)->reqFlags = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->reqFlags = malloc(sizeof(*(data)->reqFlags));
+ if ((data)->reqFlags == NULL)
+ return ENOMEM;
+ e = decode_ContextFlags(p, len, (data)->reqFlags, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 2, &l);
+ if (e)
+ (data)->mechToken = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechToken = malloc(sizeof(*(data)->mechToken));
+ if ((data)->mechToken == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechToken, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 3, &l);
+ if (e)
+ (data)->mechListMIC = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC));
+ if ((data)->mechListMIC == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechListMIC, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ }
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_NegTokenInit(data);
+ return e;
+}
+
+static void
+free_NegTokenInit(NegTokenInit * data)
+{
+ free_MechTypeList(&(data)->mechTypes);
+ if ((data)->reqFlags) {
+ free_ContextFlags((data)->reqFlags);
+ free((data)->reqFlags);
+ (data)->reqFlags = NULL;
+ }
+ if ((data)->mechToken) {
+ free_octet_string((data)->mechToken);
+ free((data)->mechToken);
+ (data)->mechToken = NULL;
+ }
+ if ((data)->mechListMIC) {
+ free_octet_string((data)->mechListMIC);
+ free((data)->mechListMIC);
+ (data)->mechListMIC = NULL;
+ }
+}
+
+/* unused function: length_NegTokenInit */
+
+
+/* unused function: copy_NegTokenInit */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_NegTokenResp(unsigned char *p, size_t len, const NegTokenResp * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ if ((data)->mechListMIC) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechListMIC, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 3, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->responseToken) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->responseToken, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 2, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->supportedMech) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechType(p, len, (data)->supportedMech, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 1, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->negState) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_enumerated(p, len, (data)->negState, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 0, &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_NegTokenResp(const unsigned char *p, size_t len, NegTokenResp * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ {
+ int dce_fix;
+ if ((dce_fix = fix_dce(reallen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 0, &l);
+ if (e)
+ (data)->negState = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->negState = malloc(sizeof(*(data)->negState));
+ if ((data)->negState == NULL)
+ return ENOMEM;
+ e = decode_enumerated(p, len, (data)->negState, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 1, &l);
+ if (e)
+ (data)->supportedMech = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->supportedMech = malloc(sizeof(*(data)->supportedMech));
+ if ((data)->supportedMech == NULL)
+ return ENOMEM;
+ e = decode_MechType(p, len, (data)->supportedMech, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 2, &l);
+ if (e)
+ (data)->responseToken = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->responseToken = malloc(sizeof(*(data)->responseToken));
+ if ((data)->responseToken == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->responseToken, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 3, &l);
+ if (e)
+ (data)->mechListMIC = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC));
+ if ((data)->mechListMIC == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechListMIC, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ }
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_NegTokenResp(data);
+ return e;
+}
+
+static void
+free_NegTokenResp(NegTokenResp * data)
+{
+ if ((data)->negState) {
+ free((data)->negState);
+ (data)->negState = NULL;
+ }
+ if ((data)->supportedMech) {
+ free_MechType((data)->supportedMech);
+ free((data)->supportedMech);
+ (data)->supportedMech = NULL;
+ }
+ if ((data)->responseToken) {
+ free_octet_string((data)->responseToken);
+ free((data)->responseToken);
+ (data)->responseToken = NULL;
+ }
+ if ((data)->mechListMIC) {
+ free_octet_string((data)->mechListMIC);
+ free((data)->mechListMIC);
+ (data)->mechListMIC = NULL;
+ }
+}
+
+/* unused function: length_NegTokenResp */
+
+
+/* unused function: copy_NegTokenResp */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+/* CHOICE */
+/* unused variable: asn1_NegotiationToken_dummy_holder */
diff --git a/lib/dns/spnego_asn1.pl b/lib/dns/spnego_asn1.pl
new file mode 100755
index 0000000..93dd676
--- /dev/null
+++ b/lib/dns/spnego_asn1.pl
@@ -0,0 +1,200 @@
+#!/bin/bin/perl -w
+#
+# Copyright (C) 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+#
+# 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: spnego_asn1.pl,v 1.4 2007/06/19 23:47:16 tbox Exp $
+
+# Our SPNEGO implementation uses some functions generated by the
+# Heimdal ASN.1 compiler, which this script then whacks a bit to make
+# them work properly in this stripped down implementation. We don't
+# want to require our users to have a copy of the compiler, so we ship
+# the output of this script, but we need to keep the script around in
+# any case to cope with future changes to the SPNEGO ASN.1 code, so we
+# might as well supply the script for users who want it.
+
+# Overall plan: run the ASN.1 compiler, run each of its output files
+# through indent, fix up symbols and whack everything to be static.
+# We use indent for two reasons: (1) to whack the Heimdal compiler's
+# output into something closer to ISC's coding standard, and (2) to
+# make it easier for this script to parse the result.
+
+# Output from this script is C code which we expect to be #included
+# into another C file, which is why everything generated by this
+# script is marked "static". The intent is to minimize the number of
+# extern symbols exported by the SPNEGO implementation, to avoid
+# potential conflicts with the GSSAPI libraries.
+
+###
+
+# Filename of the ASN.1 specification. Hardcoded for the moment
+# since this script is intended for compiling exactly one module.
+
+my $asn1_source = $ENV{ASN1_SOURCE} || "spnego.asn1";
+
+# Heimdal ASN.1 compiler. This script was written using the version
+# from Heimdal 0.7.1. To build this, download a copy of
+# heimdal-0.7.1.tar.gz, configure and build with the default options,
+# then look for the compiler in heimdal-0.7.1/lib/asn1/asn1_compile.
+
+my $asn1_compile = $ENV{ASN1_COMPILE} || "asn1_compile";
+
+# BSD indent program. This script was written using the version of
+# indent that comes with FreeBSD 4.11-STABLE. The GNU project, as
+# usual, couldn't resist the temptation to monkey with indent's
+# command line syntax, so this probably won't work with GNU indent.
+
+my $indent = $ENV{INDENT} || "indent";
+
+###
+
+# Step 1: run the compiler. Input is the ASN.1 file. Outputs are a
+# header file (name specified on command line without the .h suffix),
+# a file called "asn1_files" listing the names of the other output
+# files, and a set of files containing C code generated by the
+# compiler for each data type that the compiler found.
+
+if (! -r $asn1_source || system($asn1_compile, $asn1_source, "asn1")) {
+ die("Couldn't compile ASN.1 source file $asn1_source\n");
+}
+
+my @files = ("asn1.h");
+
+open(F, "asn1_files")
+ or die("Couldn't open asn1_files: $!\n");
+push(@files, split)
+ while (<F>);
+close(F);
+
+unlink("asn1_files");
+
+###
+
+# Step 2: generate header block.
+
+print(q~/*
+ * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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: spnego_asn1.pl,v 1.4 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file
+ * \brief Method routines generated from SPNEGO ASN.1 module.
+ * See spnego_asn1.pl for details. Do not edit.
+ */
+
+~);
+
+###
+
+# Step 3: read and process each generated file, then delete it.
+
+my $output;
+
+for my $file (@files) {
+
+ my $is_static = 0;
+
+ system($indent, "-di1", "-ldi1", $file) == 0
+ or die("Couldn't indent $file");
+
+ unlink("$file.BAK");
+
+ open(F, $file)
+ or die("Couldn't open $file: $!");
+
+ while (<F>) {
+
+ # Symbol name fixups
+
+ s/heim_general_string/general_string/g;
+ s/heim_octet_string/octet_string/g;
+ s/heim_oid/oid/g;
+ s/heim_utf8_string/utf8_string/g;
+
+ # Convert all externs to statics
+
+ if (/^static/) {
+ $is_static = 1;
+ }
+
+ if (!/^typedef/ &&
+ !$is_static &&
+ /^[A-Za-z_][0-9A-Za-z_]*[ \t]*($|[^:0-9A-Za-z_])/) {
+ $_ = "static " . $_;
+ $is_static = 1;
+ }
+
+ if (/[{};]/) {
+ $is_static = 0;
+ }
+
+ # Suppress file inclusion, pass anything else through
+
+ if (!/#include/) {
+ $output .= $_;
+ }
+ }
+
+ close(F);
+ unlink($file);
+}
+
+# Step 4: Delete unused stuff to avoid code bloat and compiler warnings.
+
+my @unused_functions = qw(ContextFlags2int
+ int2ContextFlags
+ asn1_ContextFlags_units
+ length_NegTokenInit
+ copy_NegTokenInit
+ length_NegTokenResp
+ copy_NegTokenResp
+ length_MechTypeList
+ length_MechType
+ copy_MechTypeList
+ length_ContextFlags
+ copy_ContextFlags
+ copy_MechType);
+
+$output =~ s<^static [^\n]+\n$_\(.+?^}></* unused function: $_ */\n>ms
+ foreach (@unused_functions);
+
+$output =~ s<^static .+$_\(.*\);$></* unused declaration: $_ */>m
+ foreach (@unused_functions);
+
+$output =~ s<^static struct units ContextFlags_units\[\].+?^};>
+ </* unused variable: ContextFlags_units */>ms;
+
+$output =~ s<^static int asn1_NegotiationToken_dummy_holder = 1;>
+ </* unused variable: asn1_NegotiationToken_dummy_holder */>ms;
+
+$output =~ s<^static void\nfree_ContextFlags\(ContextFlags \* data\)\n{\n>
+ <$&\t(void)data;\n>ms;
+
+# Step 5: Write the result.
+
+print($output);
+
diff --git a/lib/dns/ssu.c b/lib/dns/ssu.c
index fa3011c..ab69242 100644
--- a/lib/dns/ssu.c
+++ b/lib/dns/ssu.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -17,7 +17,7 @@
/*! \file */
/*
- * $Id: ssu.c,v 1.24.18.4 2006/02/16 23:51:32 marka Exp $
+ * $Id: ssu.c,v 1.34 2008/01/18 23:46:58 tbox Exp $
* Principal Author: Brian Wellington
*/
@@ -25,14 +25,17 @@
#include <isc/magic.h>
#include <isc/mem.h>
+#include <isc/netaddr.h>
#include <isc/result.h>
-#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/string.h>
#include <isc/util.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/ssu.h>
+#include <dst/gssapi.h>
+
#define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
#define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
@@ -245,50 +248,178 @@ isusertype(dns_rdatatype_t type) {
type != dns_rdatatype_rrsig));
}
+static void
+reverse_from_address(dns_name_t *tcpself, isc_netaddr_t *tcpaddr) {
+ char buf[16 * 4 + sizeof("IP6.ARPA.")];
+ isc_result_t result;
+ unsigned char *ap;
+ isc_buffer_t b;
+ unsigned long l;
+
+ switch (tcpaddr->family) {
+ case AF_INET:
+ l = ntohl(tcpaddr->type.in.s_addr);
+ result = isc_string_printf(buf, sizeof(buf),
+ "%lu.%lu.%lu.%lu.IN-ADDR.ARPA.",
+ (l >> 0) & 0xff, (l >> 8) & 0xff,
+ (l >> 16) & 0xff, (l >> 24) & 0xff);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ break;
+ case AF_INET6:
+ ap = tcpaddr->type.in6.s6_addr;
+ result = isc_string_printf(buf, sizeof(buf),
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "IP6.ARPA.",
+ ap[15] & 0x0f, (ap[15] >> 4) & 0x0f,
+ ap[14] & 0x0f, (ap[14] >> 4) & 0x0f,
+ ap[13] & 0x0f, (ap[13] >> 4) & 0x0f,
+ ap[12] & 0x0f, (ap[12] >> 4) & 0x0f,
+ ap[11] & 0x0f, (ap[11] >> 4) & 0x0f,
+ ap[10] & 0x0f, (ap[10] >> 4) & 0x0f,
+ ap[9] & 0x0f, (ap[9] >> 4) & 0x0f,
+ ap[8] & 0x0f, (ap[8] >> 4) & 0x0f,
+ ap[7] & 0x0f, (ap[7] >> 4) & 0x0f,
+ ap[6] & 0x0f, (ap[6] >> 4) & 0x0f,
+ ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
+ ap[4] & 0x0f, (ap[4] >> 4) & 0x0f,
+ ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
+ ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
+ ap[1] & 0x0f, (ap[1] >> 4) & 0x0f,
+ ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ break;
+ default:
+ INSIST(0);
+ }
+ isc_buffer_init(&b, buf, strlen(buf));
+ isc_buffer_add(&b, strlen(buf));
+ result = dns_name_fromtext(tcpself, &b, dns_rootname, 0, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+static void
+stf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) {
+ char buf[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")];
+ isc_result_t result;
+ unsigned char *ap;
+ isc_buffer_t b;
+ unsigned long l;
+
+ switch(tcpaddr->family) {
+ case AF_INET:
+ l = ntohl(tcpaddr->type.in.s_addr);
+ result = isc_string_printf(buf, sizeof(buf),
+ "%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx"
+ "2.0.0.2.IP6.ARPA.",
+ l & 0xf, (l >> 4) & 0xf,
+ (l >> 8) & 0xf, (l >> 12) & 0xf,
+ (l >> 16) & 0xf, (l >> 20) & 0xf,
+ (l >> 24) & 0xf, (l >> 28) & 0xf);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ break;
+ case AF_INET6:
+ ap = tcpaddr->type.in6.s6_addr;
+ result = isc_string_printf(buf, sizeof(buf),
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "%x.%x.%x.%x.IP6.ARPA.",
+ ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
+ ap[4] & 0x0f, (ap[4] >> 4) & 0x0f,
+ ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
+ ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
+ ap[1] & 0x0f, (ap[1] >> 4) & 0x0f,
+ ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ break;
+ default:
+ INSIST(0);
+ }
+ isc_buffer_init(&b, buf, strlen(buf));
+ isc_buffer_add(&b, strlen(buf));
+ result = dns_name_fromtext(stfself, &b, dns_rootname, 0, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
isc_boolean_t
dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
- dns_name_t *name, dns_rdatatype_t type)
+ dns_name_t *name, isc_netaddr_t *tcpaddr,
+ dns_rdatatype_t type)
{
dns_ssurule_t *rule;
unsigned int i;
dns_fixedname_t fixed;
dns_name_t *wildcard;
+ dns_name_t *tcpself;
+ dns_name_t *stfself;
isc_result_t result;
REQUIRE(VALID_SSUTABLE(table));
REQUIRE(signer == NULL || dns_name_isabsolute(signer));
REQUIRE(dns_name_isabsolute(name));
- if (signer == NULL)
+ if (signer == NULL && tcpaddr == NULL)
return (ISC_FALSE);
- rule = ISC_LIST_HEAD(table->rules);
- rule = ISC_LIST_NEXT(rule, link);
+
for (rule = ISC_LIST_HEAD(table->rules);
rule != NULL;
rule = ISC_LIST_NEXT(rule, link))
{
- if (dns_name_iswildcard(rule->identity)) {
- if (!dns_name_matcheswildcard(signer, rule->identity))
+ switch (rule->matchtype) {
+ case DNS_SSUMATCHTYPE_NAME:
+ case DNS_SSUMATCHTYPE_SUBDOMAIN:
+ case DNS_SSUMATCHTYPE_WILDCARD:
+ case DNS_SSUMATCHTYPE_SELF:
+ case DNS_SSUMATCHTYPE_SELFSUB:
+ case DNS_SSUMATCHTYPE_SELFWILD:
+ if (signer == NULL)
continue;
- } else if (!dns_name_equal(signer, rule->identity))
+ if (dns_name_iswildcard(rule->identity)) {
+ if (!dns_name_matcheswildcard(signer,
+ rule->identity))
+ continue;
+ } else {
+ if (!dns_name_equal(signer, rule->identity))
+ continue;
+ }
+ break;
+ case DNS_SSUMATCHTYPE_SELFKRB5:
+ case DNS_SSUMATCHTYPE_SELFMS:
+ case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
+ case DNS_SSUMATCHTYPE_SUBDOMAINMS:
+ if (signer == NULL)
continue;
+ break;
+ case DNS_SSUMATCHTYPE_TCPSELF:
+ case DNS_SSUMATCHTYPE_6TO4SELF:
+ if (tcpaddr == NULL)
+ continue;
+ break;
+ }
- if (rule->matchtype == DNS_SSUMATCHTYPE_NAME) {
+ switch (rule->matchtype) {
+ case DNS_SSUMATCHTYPE_NAME:
if (!dns_name_equal(name, rule->name))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_SUBDOMAIN) {
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAIN:
if (!dns_name_issubdomain(name, rule->name))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_WILDCARD) {
+ break;
+ case DNS_SSUMATCHTYPE_WILDCARD:
if (!dns_name_matcheswildcard(name, rule->name))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELF) {
+ break;
+ case DNS_SSUMATCHTYPE_SELF:
if (!dns_name_equal(signer, name))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELFSUB) {
+ break;
+ case DNS_SSUMATCHTYPE_SELFSUB:
if (!dns_name_issubdomain(name, signer))
continue;
- } else if (rule->matchtype == DNS_SSUMATCHTYPE_SELFWILD) {
+ break;
+ case DNS_SSUMATCHTYPE_SELFWILD:
dns_fixedname_init(&fixed);
wildcard = dns_fixedname_name(&fixed);
result = dns_name_concatenate(dns_wildcardname, signer,
@@ -297,6 +428,61 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
continue;
if (!dns_name_matcheswildcard(name, wildcard))
continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELFKRB5:
+ if (!dst_gssapi_identitymatchesrealmkrb5(signer, name,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELFMS:
+ if (!dst_gssapi_identitymatchesrealmms(signer, name,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
+ if (!dns_name_issubdomain(name, rule->name))
+ continue;
+ if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAINMS:
+ if (!dns_name_issubdomain(name, rule->name))
+ continue;
+ if (!dst_gssapi_identitymatchesrealmms(signer, NULL,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_TCPSELF:
+ dns_fixedname_init(&fixed);
+ tcpself = dns_fixedname_name(&fixed);
+ reverse_from_address(tcpself, tcpaddr);
+ if (dns_name_iswildcard(rule->identity)) {
+ if (!dns_name_matcheswildcard(tcpself,
+ rule->identity))
+ continue;
+ } else {
+ if (!dns_name_equal(tcpself, rule->identity))
+ continue;
+ }
+ if (!dns_name_equal(tcpself, name))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_6TO4SELF:
+ dns_fixedname_init(&fixed);
+ stfself = dns_fixedname_name(&fixed);
+ stf_from_address(stfself, tcpaddr);
+ if (dns_name_iswildcard(rule->identity)) {
+ if (!dns_name_matcheswildcard(stfself,
+ rule->identity))
+ continue;
+ } else {
+ if (!dns_name_equal(stfself, rule->identity))
+ continue;
+ }
+ if (!dns_name_equal(stfself, name))
+ continue;
+ break;
}
if (rule->ntypes == 0) {
diff --git a/lib/dns/stats.c b/lib/dns/stats.c
index 660046f..60fed35 100644
--- a/lib/dns/stats.c
+++ b/lib/dns/stats.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,16 +15,363 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: stats.c,v 1.6.18.4 2005/06/27 00:20:02 marka Exp $ */
+/* $Id: stats.c,v 1.16.118.2 2009/01/29 23:47:44 tbox Exp $ */
/*! \file */
#include <config.h>
+#include <isc/magic.h>
#include <isc/mem.h>
+#include <isc/stats.h>
+#include <isc/util.h>
+#include <dns/opcode.h>
+#include <dns/rdatatype.h>
#include <dns/stats.h>
+#define DNS_STATS_MAGIC ISC_MAGIC('D', 's', 't', 't')
+#define DNS_STATS_VALID(x) ISC_MAGIC_VALID(x, DNS_STATS_MAGIC)
+
+/*%
+ * Statistics types.
+ */
+typedef enum {
+ dns_statstype_general = 0,
+ dns_statstype_rdtype = 1,
+ dns_statstype_rdataset = 2,
+ dns_statstype_opcode = 3
+} dns_statstype_t;
+
+/*%
+ * It doesn't make sense to have 2^16 counters for all possible types since
+ * most of them won't be used. We have counters for the first 256 types and
+ * those explicitly supported in the rdata implementation.
+ * XXXJT: this introduces tight coupling with the rdata implementation.
+ * Ideally, we should have rdata handle this type of details.
+ */
+enum {
+ /* For 0-255, we use the rdtype value as counter indices */
+ rdtypecounter_dlv = 256, /* for dns_rdatatype_dlv */
+ rdtypecounter_others = 257, /* anything else */
+ rdtypecounter_max = 258,
+ /* The following are used for rdataset */
+ rdtypenxcounter_max = rdtypecounter_max * 2,
+ rdtypecounter_nxdomain = rdtypenxcounter_max,
+ rdatasettypecounter_max = rdtypecounter_nxdomain + 1
+};
+
+struct dns_stats {
+ /*% Unlocked */
+ unsigned int magic;
+ dns_statstype_t type;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ isc_stats_t *counters;
+
+ /*% Locked by lock */
+ unsigned int references;
+};
+
+typedef struct rdatadumparg {
+ dns_rdatatypestats_dumper_t fn;
+ void *arg;
+} rdatadumparg_t;
+
+typedef struct opcodedumparg {
+ dns_opcodestats_dumper_t fn;
+ void *arg;
+} opcodedumparg_t;
+
+void
+dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) {
+ REQUIRE(DNS_STATS_VALID(stats));
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ LOCK(&stats->lock);
+ stats->references++;
+ UNLOCK(&stats->lock);
+
+ *statsp = stats;
+}
+
+void
+dns_stats_detach(dns_stats_t **statsp) {
+ dns_stats_t *stats;
+
+ REQUIRE(statsp != NULL && DNS_STATS_VALID(*statsp));
+
+ stats = *statsp;
+ *statsp = NULL;
+
+ LOCK(&stats->lock);
+ stats->references--;
+ UNLOCK(&stats->lock);
+
+ if (stats->references == 0) {
+ isc_stats_detach(&stats->counters);
+ DESTROYLOCK(&stats->lock);
+ isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
+ }
+}
+
+/*%
+ * Create methods
+ */
+static isc_result_t
+create_stats(isc_mem_t *mctx, dns_statstype_t type, int ncounters,
+ dns_stats_t **statsp)
+{
+ dns_stats_t *stats;
+ isc_result_t result;
+
+ stats = isc_mem_get(mctx, sizeof(*stats));
+ if (stats == NULL)
+ return (ISC_R_NOMEMORY);
+
+ stats->counters = NULL;
+ stats->references = 1;
+
+ result = isc_mutex_init(&stats->lock);
+ if (result != ISC_R_SUCCESS)
+ goto clean_stats;
+
+ result = isc_stats_create(mctx, &stats->counters, ncounters);
+ if (result != ISC_R_SUCCESS)
+ goto clean_mutex;
+
+ stats->magic = DNS_STATS_MAGIC;
+ stats->type = type;
+ stats->mctx = NULL;
+ isc_mem_attach(mctx, &stats->mctx);
+ *statsp = stats;
+
+ return (ISC_R_SUCCESS);
+
+ clean_mutex:
+ DESTROYLOCK(&stats->lock);
+ clean_stats:
+ isc_mem_put(mctx, stats, sizeof(*stats));
+
+ return (result);
+}
+
+isc_result_t
+dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters) {
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ return (create_stats(mctx, dns_statstype_general, ncounters, statsp));
+}
+
+isc_result_t
+dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ return (create_stats(mctx, dns_statstype_rdtype, rdtypecounter_max,
+ statsp));
+}
+
+isc_result_t
+dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ return (create_stats(mctx, dns_statstype_rdataset,
+ (rdtypecounter_max * 2) + 1, statsp));
+}
+
+isc_result_t
+dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ return (create_stats(mctx, dns_statstype_opcode, 16, statsp));
+}
+
+/*%
+ * Increment/Decrement methods
+ */
+void
+dns_generalstats_increment(dns_stats_t *stats, isc_statscounter_t counter) {
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
+
+ isc_stats_increment(stats->counters, counter);
+}
+
+void
+dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type) {
+ int counter;
+
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
+
+ if (type == dns_rdatatype_dlv)
+ counter = rdtypecounter_dlv;
+ else if (type > dns_rdatatype_any)
+ counter = rdtypecounter_others;
+ else
+ counter = (int)type;
+
+ isc_stats_increment(stats->counters, (isc_statscounter_t)counter);
+}
+
+static inline void
+update_rdatasetstats(dns_stats_t *stats, dns_rdatastatstype_t rrsettype,
+ isc_boolean_t increment)
+{
+ int counter;
+ dns_rdatatype_t rdtype;
+
+ if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
+ DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0) {
+ counter = rdtypecounter_nxdomain;
+ } else {
+ rdtype = DNS_RDATASTATSTYPE_BASE(rrsettype);
+ if (rdtype == dns_rdatatype_dlv)
+ counter = (int)rdtypecounter_dlv;
+ else if (rdtype > dns_rdatatype_any)
+ counter = (int)rdtypecounter_others;
+ else
+ counter = (int)rdtype;
+
+ if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
+ DNS_RDATASTATSTYPE_ATTR_NXRRSET) != 0)
+ counter += rdtypecounter_max;
+ }
+
+ if (increment)
+ isc_stats_increment(stats->counters, counter);
+ else
+ isc_stats_decrement(stats->counters, counter);
+}
+
+void
+dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
+{
+ REQUIRE(DNS_STATS_VALID(stats) &&
+ stats->type == dns_statstype_rdataset);
+
+ update_rdatasetstats(stats, rrsettype, ISC_TRUE);
+}
+
+void
+dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
+{
+ REQUIRE(DNS_STATS_VALID(stats) &&
+ stats->type == dns_statstype_rdataset);
+
+ update_rdatasetstats(stats, rrsettype, ISC_FALSE);
+}
+void
+dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code) {
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
+
+ isc_stats_increment(stats->counters, (isc_statscounter_t)code);
+}
+
+/*%
+ * Dump methods
+ */
+void
+dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
+ void *arg, unsigned int options)
+{
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
+
+ isc_stats_dump(stats->counters, (isc_stats_dumper_t)dump_fn,
+ arg, options);
+}
+
+static void
+dump_rdentry(int rdcounter, isc_uint64_t value, dns_rdatastatstype_t attributes,
+ dns_rdatatypestats_dumper_t dump_fn, void * arg)
+{
+ dns_rdatatype_t rdtype = dns_rdatatype_none; /* sentinel */
+ dns_rdatastatstype_t type;
+
+ if (rdcounter == rdtypecounter_others)
+ attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
+ else {
+ if (rdcounter == rdtypecounter_dlv)
+ rdtype = dns_rdatatype_dlv;
+ else
+ rdtype = (dns_rdatatype_t)rdcounter;
+ }
+ type = DNS_RDATASTATSTYPE_VALUE((dns_rdatastatstype_t)rdtype,
+ attributes);
+ dump_fn(type, value, arg);
+}
+
+static void
+rdatatype_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
+ rdatadumparg_t *rdatadumparg = arg;
+
+ dump_rdentry(counter, value, 0, rdatadumparg->fn, rdatadumparg->arg);
+}
+
+void
+dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+ void *arg0, unsigned int options)
+{
+ rdatadumparg_t arg;
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
+
+ arg.fn = dump_fn;
+ arg.arg = arg0;
+ isc_stats_dump(stats->counters, rdatatype_dumpcb, &arg, options);
+}
+
+static void
+rdataset_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
+ rdatadumparg_t *rdatadumparg = arg;
+
+ if (counter < rdtypecounter_max) {
+ dump_rdentry(counter, value, 0, rdatadumparg->fn,
+ rdatadumparg->arg);
+ } else if (counter < rdtypenxcounter_max) {
+ dump_rdentry(counter - rdtypecounter_max, value,
+ DNS_RDATASTATSTYPE_ATTR_NXRRSET,
+ rdatadumparg->fn, rdatadumparg->arg);
+ } else {
+ dump_rdentry(0, value, DNS_RDATASTATSTYPE_ATTR_NXDOMAIN,
+ rdatadumparg->fn, rdatadumparg->arg);
+ }
+}
+
+void
+dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+ void *arg0, unsigned int options)
+{
+ rdatadumparg_t arg;
+
+ REQUIRE(DNS_STATS_VALID(stats) &&
+ stats->type == dns_statstype_rdataset);
+
+ arg.fn = dump_fn;
+ arg.arg = arg0;
+ isc_stats_dump(stats->counters, rdataset_dumpcb, &arg, options);
+}
+
+static void
+opcode_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
+ opcodedumparg_t *opcodearg = arg;
+
+ opcodearg->fn((dns_opcode_t)counter, value, opcodearg->arg);
+}
+
+void
+dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
+ void *arg0, unsigned int options)
+{
+ opcodedumparg_t arg;
+
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
+
+ arg.fn = dump_fn;
+ arg.arg = arg0;
+ isc_stats_dump(stats->counters, opcode_dumpcb, &arg, options);
+}
+
+/***
+ *** Obsolete variables and functions follow:
+ ***/
LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] =
{
"success",
diff --git a/lib/dns/tcpmsg.c b/lib/dns/tcpmsg.c
index 018c4ce..49add56 100644
--- a/lib/dns/tcpmsg.c
+++ b/lib/dns/tcpmsg.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tcpmsg.c,v 1.25.18.4 2006/08/10 23:59:29 marka Exp $ */
+/* $Id: tcpmsg.c,v 1.31 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/time.c b/lib/dns/time.c
index b4e7bee..62414dd 100644
--- a/lib/dns/time.c
+++ b/lib/dns/time.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: time.c,v 1.26.18.3 2005/04/29 00:16:06 marka Exp $ */
+/* $Id: time.c,v 1.31.332.2 2009/01/18 23:47:40 tbox Exp $ */
/*! \file */
@@ -145,7 +145,7 @@ dns_time64_fromtext(const char *source, isc_int64_t *target) {
RANGE(0, 60, second); /* 60 == leap second. */
/*
- * Calulate seconds since epoch.
+ * Calculate seconds since epoch.
*/
value = second + (60 * minute) + (3600 * hour) + ((day - 1) * 86400);
for (i = 0; i < (month - 1); i++)
diff --git a/lib/dns/timer.c b/lib/dns/timer.c
index b225722..39e4551 100644
--- a/lib/dns/timer.c
+++ b/lib/dns/timer.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: timer.c,v 1.3.18.2 2005/04/29 00:16:06 marka Exp $ */
+/* $Id: timer.c,v 1.7 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
index 998ea36..9e59dfa 100644
--- a/lib/dns/tkey.c
+++ b/lib/dns/tkey.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +16,7 @@
*/
/*
- * $Id: tkey.c,v 1.76.18.7 2008/01/02 23:46:02 tbox Exp $
+ * $Id: tkey.c,v 1.90 2008/04/03 00:45:23 marka Exp $
*/
/*! \file */
#include <config.h>
@@ -66,6 +66,20 @@ tkey_log(const char *fmt, ...) {
va_end(ap);
}
+static void
+_dns_tkey_dumpmessage(dns_message_t *msg) {
+ isc_buffer_t outbuf;
+ unsigned char output[4096];
+ isc_result_t result;
+
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(msg, &dns_master_style_debug, 0,
+ &outbuf);
+ /* XXXMLG ignore result */
+ fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+}
+
isc_result_t
dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
{
@@ -107,6 +121,8 @@ dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) {
dns_name_free(tctx->domain, mctx);
isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t));
}
+ if (tctx->gsscred != NULL)
+ dst_gssapi_releasecred(&tctx->gsscred);
isc_entropy_detach(&tctx->ectx);
isc_mem_put(mctx, tctx, sizeof(dns_tkeyctx_t));
isc_mem_detach(&mctx);
@@ -280,8 +296,7 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
*/
for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
result == ISC_R_SUCCESS && !found_key;
- result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL))
- {
+ result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) {
keyname = NULL;
dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
keyset = NULL;
@@ -292,8 +307,7 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
for (result = dns_rdataset_first(keyset);
result == ISC_R_SUCCESS && !found_key;
- result = dns_rdataset_next(keyset))
- {
+ result = dns_rdataset_next(keyset)) {
dns_rdataset_current(keyset, &keyrdata);
pubkey = NULL;
result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
@@ -410,13 +424,15 @@ process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
{
isc_result_t result = ISC_R_SUCCESS;
dst_key_t *dstkey = NULL;
- void *gssctx = NULL;
+ dns_tsigkey_t *tsigkey = NULL;
+ dns_fixedname_t principal;
isc_stdtime_t now;
isc_region_t intoken;
- unsigned char array[1024];
- isc_buffer_t outtoken;
+ isc_buffer_t *outtoken = NULL;
+ gss_ctx_id_t gss_ctx = NULL;
UNUSED(namelist);
+ UNUSED(signer);
if (tctx->gsscred == NULL)
return (ISC_R_NOPERM);
@@ -424,55 +440,95 @@ process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
tkeyout->error = dns_tsigerror_badalg;
+ tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */
return (ISC_R_SUCCESS);
}
+ /*
+ * XXXDCL need to check for key expiry per 4.1.1
+ * XXXDCL need a way to check fully established, perhaps w/key_flags
+ */
+
intoken.base = tkeyin->key;
intoken.length = tkeyin->keylen;
- isc_buffer_init(&outtoken, array, sizeof(array));
- RETERR(dst_gssapi_acceptctx(name, tctx->gsscred, &intoken,
- &outtoken, &gssctx));
+ result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
+ if (result == ISC_R_SUCCESS)
+ gss_ctx = dst_key_getgssctx(tsigkey->key);
- dstkey = NULL;
- RETERR(dst_key_fromgssapi(name, gssctx, msg->mctx, &dstkey));
- result = dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
- dstkey, ISC_TRUE, signer,
- tkeyin->inception, tkeyin->expire,
- ring->mctx, ring, NULL);
-#if 1
- if (result != ISC_R_SUCCESS)
- goto failure;
-#else
- if (result == ISC_R_NOTFOUND) {
- tkeyout->error = dns_tsigerror_badalg;
+ dns_fixedname_init(&principal);
+
+ result = dst_gssapi_acceptctx(tctx->gsscred, &intoken,
+ &outtoken, &gss_ctx,
+ dns_fixedname_name(&principal),
+ tctx->mctx);
+
+ if (tsigkey != NULL)
+ dns_tsigkey_detach(&tsigkey);
+
+ if (result == DNS_R_INVALIDTKEY) {
+ tkeyout->error = dns_tsigerror_badkey;
+ tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
return (ISC_R_SUCCESS);
- }
- if (result != ISC_R_SUCCESS)
+ } else if (result == ISC_R_FAILURE)
goto failure;
-#endif
+ ENSURE(result == DNS_R_CONTINUE || result == ISC_R_SUCCESS);
+ /*
+ * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
+ */
+
+ if (tsigkey == NULL) {
+ RETERR(dst_key_fromgssapi(name, gss_ctx, msg->mctx, &dstkey));
+ RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
+ dstkey, ISC_TRUE,
+ dns_fixedname_name(&principal),
+ tkeyin->inception,
+ tkeyin->expire,
+ ring->mctx, ring, NULL));
+ }
- /* This key is good for a long time */
isc_stdtime_get(&now);
tkeyout->inception = tkeyin->inception;
tkeyout->expire = tkeyin->expire;
- tkeyout->key = isc_mem_get(msg->mctx,
- isc_buffer_usedlength(&outtoken));
- if (tkeyout->key == NULL) {
- result = ISC_R_NOMEMORY;
- goto failure;
+ if (outtoken) {
+ tkeyout->key = isc_mem_get(tkeyout->mctx,
+ isc_buffer_usedlength(outtoken));
+ if (tkeyout->key == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ tkeyout->keylen = isc_buffer_usedlength(outtoken);
+ memcpy(tkeyout->key, isc_buffer_base(outtoken),
+ isc_buffer_usedlength(outtoken));
+ isc_buffer_free(&outtoken);
+ } else {
+ tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen);
+ if (tkeyout->key == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ tkeyout->keylen = tkeyin->keylen;
+ memcpy(tkeyout->key, tkeyin->key, tkeyin->keylen);
}
- tkeyout->keylen = isc_buffer_usedlength(&outtoken);
- memcpy(tkeyout->key, isc_buffer_base(&outtoken), tkeyout->keylen);
+
+ tkeyout->error = dns_rcode_noerror;
+
+ tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */
return (ISC_R_SUCCESS);
- failure:
+failure:
if (dstkey != NULL)
dst_key_free(&dstkey);
+ if (outtoken != NULL)
+ isc_buffer_free(&outtoken);
+
+ tkey_log("process_gsstkey(): %s",
+ isc_result_totext(result)); /* XXXSRA */
+
return (result);
}
@@ -564,8 +620,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
*/
if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
dns_rdatatype_tkey, 0, &name,
- &tkeyset) != ISC_R_SUCCESS)
- {
+ &tkeyset) != ISC_R_SUCCESS) {
result = DNS_R_FORMERR;
tkey_log("dns_tkey_processquery: couldn't find a TKEY "
"matching the question");
@@ -632,7 +687,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
if (tkeyin.mode != DNS_TKEYMODE_DELETE) {
dns_tsigkey_t *tsigkey = NULL;
- if (tctx->domain == NULL) {
+ if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) {
tkey_log("dns_tkey_processquery: tkey-domain not set");
result = DNS_R_REFUSED;
goto failure;
@@ -674,12 +729,22 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
if (result != ISC_R_SUCCESS)
goto failure;
}
- result = dns_name_concatenate(keyname, tctx->domain,
- keyname, NULL);
- if (result != ISC_R_SUCCESS)
- goto failure;
+
+ if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) {
+ /* Yup. This is a hack */
+ result = dns_name_concatenate(keyname, dns_rootname,
+ keyname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ } else {
+ result = dns_name_concatenate(keyname, tctx->domain,
+ keyname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);
+
if (result == ISC_R_SUCCESS) {
tkeyout.error = dns_tsigerror_badname;
dns_tsigkey_detach(&tsigkey);
@@ -701,6 +766,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
RETERR(process_gsstkey(msg, signer, keyname, &tkeyin,
tctx, &tkeyout, ring,
&namelist));
+
break;
case DNS_TKEYMODE_DELETE:
tkeyout.error = dns_rcode_noerror;
@@ -729,9 +795,9 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
}
if (tkeyout.key != NULL)
- isc_mem_put(msg->mctx, tkeyout.key, tkeyout.keylen);
+ isc_mem_put(tkeyout.mctx, tkeyout.key, tkeyout.keylen);
if (tkeyout.other != NULL)
- isc_mem_put(msg->mctx, tkeyout.other, tkeyout.otherlen);
+ isc_mem_put(tkeyout.mctx, tkeyout.other, tkeyout.otherlen);
if (result != ISC_R_SUCCESS)
goto failure;
@@ -759,7 +825,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
static isc_result_t
buildquery(dns_message_t *msg, dns_name_t *name,
- dns_rdata_tkey_t *tkey)
+ dns_rdata_tkey_t *tkey, isc_boolean_t win2k)
{
dns_name_t *qname = NULL, *aname = NULL;
dns_rdataset_t *question = NULL, *tkeyset = NULL;
@@ -780,8 +846,9 @@ buildquery(dns_message_t *msg, dns_name_t *name,
dns_rdataset_makequestion(question, dns_rdataclass_any,
dns_rdatatype_tkey);
- RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 512));
+ RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 4096));
RETERR(dns_message_gettemprdata(msg, &rdata));
+
RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
dns_rdatatype_tkey, tkey, dynbuf));
dns_message_takebuffer(msg, &dynbuf);
@@ -808,7 +875,15 @@ buildquery(dns_message_t *msg, dns_name_t *name,
ISC_LIST_APPEND(aname->list, tkeyset, link);
dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
- dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL);
+
+ /*
+ * Windows 2000 needs this in the answer section, not the additional
+ * section where the RFC specifies.
+ */
+ if (win2k)
+ dns_message_addname(msg, aname, DNS_SECTION_ANSWER);
+ else
+ dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL);
return (ISC_R_SUCCESS);
@@ -823,6 +898,7 @@ buildquery(dns_message_t *msg, dns_name_t *name,
}
if (dynbuf != NULL)
isc_buffer_free(&dynbuf);
+ printf("buildquery error\n");
return (result);
}
@@ -869,7 +945,7 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
tkey.other = NULL;
tkey.otherlen = 0;
- RETERR(buildquery(msg, name, &tkey));
+ RETERR(buildquery(msg, name, &tkey, ISC_FALSE));
if (nonce == NULL)
isc_mem_put(msg->mctx, r.base, 0);
@@ -900,23 +976,25 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
}
isc_result_t
-dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name,
- dns_name_t *gname, void *cred,
- isc_uint32_t lifetime, void **context)
+dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
+ isc_buffer_t *intoken, isc_uint32_t lifetime,
+ gss_ctx_id_t *context, isc_boolean_t win2k)
{
dns_rdata_tkey_t tkey;
isc_result_t result;
isc_stdtime_t now;
isc_buffer_t token;
- unsigned char array[1024];
+ unsigned char array[4096];
+
+ UNUSED(intoken);
REQUIRE(msg != NULL);
REQUIRE(name != NULL);
REQUIRE(gname != NULL);
- REQUIRE(context != NULL && *context == NULL);
+ REQUIRE(context != NULL);
isc_buffer_init(&token, array, sizeof(array));
- result = dst_gssapi_initctx(gname, cred, NULL, &token, context);
+ result = dst_gssapi_initctx(gname, NULL, &token, context);
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
return (result);
@@ -925,7 +1003,12 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name,
ISC_LINK_INIT(&tkey.common, link);
tkey.mctx = NULL;
dns_name_init(&tkey.algorithm, NULL);
- dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
+
+ if (win2k)
+ dns_name_clone(DNS_TSIG_GSSAPIMS_NAME, &tkey.algorithm);
+ else
+ dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
+
isc_stdtime_get(&now);
tkey.inception = now;
tkey.expire = now + lifetime;
@@ -936,7 +1019,7 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name,
tkey.other = NULL;
tkey.otherlen = 0;
- RETERR(buildquery(msg, name, &tkey));
+ RETERR(buildquery(msg, name, &tkey, win2k));
return (ISC_R_SUCCESS);
@@ -963,7 +1046,7 @@ dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key) {
tkey.keylen = tkey.otherlen = 0;
tkey.key = tkey.other = NULL;
- return (buildquery(msg, &key->name, &tkey));
+ return (buildquery(msg, &key->name, &tkey, ISC_FALSE));
}
static isc_result_t
@@ -1034,10 +1117,9 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
rtkey.mode != DNS_TKEYMODE_DIFFIEHELLMAN ||
rtkey.mode != qtkey.mode ||
!dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
- rmsg->rcode != dns_rcode_noerror)
- {
+ rmsg->rcode != dns_rcode_noerror) {
tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
- "or error set");
+ "or error set(1)");
result = DNS_R_INVALIDTKEY;
dns_rdata_freestruct(&qtkey);
goto failure;
@@ -1106,7 +1188,7 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
result = dns_tsigkey_create(tkeyname, &rtkey.algorithm,
r.base, r.length, ISC_TRUE,
NULL, rtkey.inception, rtkey.expire,
- ring->mctx, ring, outkey);
+ rmsg->mctx, ring, outkey);
isc_buffer_free(&shared);
dns_rdata_freestruct(&rtkey);
dst_key_free(&theirkey);
@@ -1127,18 +1209,19 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
isc_result_t
dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
- dns_name_t *gname, void *cred, void **context,
- dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring)
+ dns_name_t *gname, gss_ctx_id_t *context,
+ isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
+ dns_tsig_keyring_t *ring)
{
dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
dns_name_t *tkeyname;
dns_rdata_tkey_t rtkey, qtkey;
- isc_buffer_t outtoken;
dst_key_t *dstkey = NULL;
- isc_region_t r;
+ isc_buffer_t intoken;
isc_result_t result;
unsigned char array[1024];
+ REQUIRE(outtoken != NULL);
REQUIRE(qmsg != NULL);
REQUIRE(rmsg != NULL);
REQUIRE(gname != NULL);
@@ -1150,31 +1233,42 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
- RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
- DNS_SECTION_ADDITIONAL));
+ /*
+ * Win2k puts the item in the ANSWER section, while the RFC
+ * specifies it should be in the ADDITIONAL section. Check first
+ * where it should be, and then where it may be.
+ */
+ result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ADDITIONAL);
+ if (result == ISC_R_NOTFOUND)
+ result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ANSWER);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
if (rtkey.error != dns_rcode_noerror ||
rtkey.mode != DNS_TKEYMODE_GSSAPI ||
- !dns_name_equal(&rtkey.algorithm, &rtkey.algorithm))
- {
- tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
- "or error set");
+ !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm)) {
+ tkey_log("dns_tkey_processgssresponse: tkey mode invalid "
+ "or error set(2) %d", rtkey.error);
+ _dns_tkey_dumpmessage(qmsg);
+ _dns_tkey_dumpmessage(rmsg);
result = DNS_R_INVALIDTKEY;
goto failure;
}
- isc_buffer_init(&outtoken, array, sizeof(array));
- r.base = rtkey.key;
- r.length = rtkey.keylen;
- RETERR(dst_gssapi_initctx(gname, cred, &r, &outtoken, context));
+ isc_buffer_init(outtoken, array, sizeof(array));
+ isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
+ RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context));
dstkey = NULL;
RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
&dstkey));
RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME,
- dstkey, ISC_TRUE, NULL,
+ dstkey, ISC_FALSE, NULL,
rtkey.inception, rtkey.expire,
ring->mctx, ring, outkey));
@@ -1182,6 +1276,9 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
return (result);
failure:
+ /*
+ * XXXSRA This probably leaks memory from rtkey and qtkey.
+ */
return (result);
}
@@ -1212,10 +1309,9 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
rtkey.mode != DNS_TKEYMODE_DELETE ||
rtkey.mode != qtkey.mode ||
!dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
- rmsg->rcode != dns_rcode_noerror)
- {
+ rmsg->rcode != dns_rcode_noerror) {
tkey_log("dns_tkey_processdeleteresponse: tkey mode invalid "
- "or error set");
+ "or error set(3)");
result = DNS_R_INVALIDTKEY;
dns_rdata_freestruct(&qtkey);
dns_rdata_freestruct(&rtkey);
@@ -1240,3 +1336,84 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
failure:
return (result);
}
+
+isc_result_t
+dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
+ dns_name_t *server, gss_ctx_id_t *context,
+ dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
+ isc_boolean_t win2k)
+{
+ dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
+ dns_name_t *tkeyname;
+ dns_rdata_tkey_t rtkey, qtkey;
+ isc_buffer_t intoken, outtoken;
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+ unsigned char array[1024];
+
+ REQUIRE(qmsg != NULL);
+ REQUIRE(rmsg != NULL);
+ REQUIRE(server != NULL);
+ if (outkey != NULL)
+ REQUIRE(*outkey == NULL);
+
+ if (rmsg->rcode != dns_rcode_noerror)
+ return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
+
+ RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
+ RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
+
+ if (win2k == ISC_TRUE)
+ RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ANSWER));
+ else
+ RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ADDITIONAL));
+
+ RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
+
+ if (rtkey.error != dns_rcode_noerror ||
+ rtkey.mode != DNS_TKEYMODE_GSSAPI ||
+ !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm))
+ {
+ tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
+ "or error set(4)");
+ result = DNS_R_INVALIDTKEY;
+ goto failure;
+ }
+
+ isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
+ isc_buffer_init(&outtoken, array, sizeof(array));
+
+ result = dst_gssapi_initctx(server, &intoken, &outtoken, context);
+ if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
+ return (result);
+
+ dstkey = NULL;
+ RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
+ &dstkey));
+
+ /*
+ * XXXSRA This seems confused. If we got CONTINUE from initctx,
+ * the GSS negotiation hasn't completed yet, so we can't sign
+ * anything yet.
+ */
+
+ RETERR(dns_tsigkey_createfromkey(tkeyname,
+ (win2k
+ ? DNS_TSIG_GSSAPIMS_NAME
+ : DNS_TSIG_GSSAPI_NAME),
+ dstkey, ISC_TRUE, NULL,
+ rtkey.inception, rtkey.expire,
+ ring->mctx, ring, outkey));
+
+ dns_rdata_freestruct(&rtkey);
+ return (result);
+
+ failure:
+ /*
+ * XXXSRA This probably leaks memory from qtkey.
+ */
+ dns_rdata_freestruct(&rtkey);
+ return (result);
+}
diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c
index f21832f..74a7af3 100644
--- a/lib/dns/tsig.c
+++ b/lib/dns/tsig.c
@@ -16,7 +16,7 @@
*/
/*
- * $Id: tsig.c,v 1.117.18.14 2008/01/17 23:46:03 tbox Exp $
+ * $Id: tsig.c,v 1.136 2008/11/04 21:23:14 marka Exp $
*/
/*! \file */
#include <config.h>
@@ -28,10 +28,12 @@
#include <isc/refcount.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/util.h>
+#include <isc/time.h>
#include <dns/keyvalues.h>
#include <dns/log.h>
#include <dns/message.h>
+#include <dns/fixedname.h>
#include <dns/rbt.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
@@ -74,7 +76,6 @@ dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
static unsigned char gsstsig_ndata[] = "\010gss-tsig";
static unsigned char gsstsig_offsets[] = { 0, 9 };
-
static dns_name_t gsstsig = {
DNS_NAME_MAGIC,
gsstsig_ndata, 10, 2,
@@ -83,13 +84,14 @@ static dns_name_t gsstsig = {
{(void *)-1, (void *)-1},
{NULL, NULL}
};
-
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
-/* It's nice of Microsoft to conform to their own standard. */
+/*
+ * Since Microsoft doesn't follow its own standard, we will use this
+ * alternate name as a second guess.
+ */
static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
-
static dns_name_t gsstsigms = {
DNS_NAME_MAGIC,
gsstsigms_ndata, 19, 4,
@@ -98,7 +100,6 @@ static dns_name_t gsstsigms = {
{(void *)-1, (void *)-1},
{NULL, NULL}
};
-
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
@@ -179,10 +180,16 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
ISC_FORMAT_PRINTF(3, 4);
static void
+cleanup_ring(dns_tsig_keyring_t *ring);
+static void
+tsigkey_free(dns_tsigkey_t *key);
+
+static void
tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
va_list ap;
char message[4096];
char namestr[DNS_NAME_FORMATSIZE];
+ char creatorstr[DNS_NAME_FORMATSIZE];
if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
return;
@@ -190,11 +197,22 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
dns_name_format(&key->name, namestr, sizeof(namestr));
else
strcpy(namestr, "<null>");
+
+ if (key != NULL && key->generated)
+ dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
+
va_start(ap, fmt);
vsnprintf(message, sizeof(message), fmt, ap);
va_end(ap);
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
- level, "tsig key '%s': %s", namestr, message);
+ if (key != NULL && key->generated)
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
+ level, "tsig key '%s' (%s): %s",
+ namestr, creatorstr, message);
+ else
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
+ level, "tsig key '%s': %s", namestr, message);
}
isc_result_t
@@ -330,6 +348,16 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
if (ring != NULL) {
RWLOCK(&ring->lock, isc_rwlocktype_write);
+ ring->writecount++;
+
+ /*
+ * Do on the fly cleaning. Find some nodes we might not
+ * want around any more.
+ */
+ if (ring->writecount > 10) {
+ cleanup_ring(ring);
+ ring->writecount = 0;
+ }
ret = dns_rbt_addname(ring->keys, name, tkey);
if (ret != ISC_R_SUCCESS) {
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
@@ -338,7 +366,12 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
}
- if (dstkey != NULL && dst_key_size(dstkey) < 64) {
+ /*
+ * Ignore this if it's a GSS key, since the key size is meaningless.
+ */
+ if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
+ !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
+ !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
char namestr[DNS_NAME_FORMATSIZE];
dns_name_format(name, namestr, sizeof(namestr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
@@ -375,6 +408,66 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
return (ret);
}
+/*
+ * Find a few nodes to destroy if possible.
+ */
+static void
+cleanup_ring(dns_tsig_keyring_t *ring)
+{
+ isc_result_t result;
+ dns_rbtnodechain_t chain;
+ dns_name_t foundname;
+ dns_fixedname_t fixedorigin;
+ dns_name_t *origin;
+ isc_stdtime_t now;
+ dns_rbtnode_t *node;
+ dns_tsigkey_t *tkey;
+
+ /*
+ * Start up a new iterator each time.
+ */
+ isc_stdtime_get(&now);
+ dns_name_init(&foundname, NULL);
+ dns_fixedname_init(&fixedorigin);
+ origin = dns_fixedname_name(&fixedorigin);
+
+ again:
+ dns_rbtnodechain_init(&chain, ring->mctx);
+ result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
+ origin);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return;
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+ if (tkey != NULL) {
+ if (tkey->generated
+ && isc_refcount_current(&tkey->refs) == 1
+ && tkey->inception != tkey->expire
+ && tkey->expire < now) {
+ tsig_log(tkey, 2, "tsig expire: deleting");
+ /* delete the key */
+ dns_rbtnodechain_invalidate(&chain);
+ (void)dns_rbt_deletename(ring->keys,
+ &tkey->name,
+ ISC_FALSE);
+ goto again;
+ }
+ }
+ result = dns_rbtnodechain_next(&chain, &foundname,
+ origin);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return;
+ }
+
+ }
+}
+
isc_result_t
dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
unsigned char *secret, int length, isc_boolean_t generated,
@@ -540,17 +633,6 @@ dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
}
-static void
-buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
- isc_uint16_t valhi;
- isc_uint32_t vallo;
-
- valhi = (isc_uint16_t)(val >> 32);
- vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
- isc_buffer_putuint16(b, valhi);
- isc_buffer_putuint32(b, vallo);
-}
-
isc_result_t
dns_tsig_sign(dns_message_t *msg) {
dns_tsigkey_t *key;
@@ -613,7 +695,7 @@ dns_tsig_sign(dns_message_t *msg) {
tsig.otherlen = BADTIMELEN;
tsig.other = badtimedata;
isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
- buffer_putuint48(&otherbuf, tsig.timesigned);
+ isc_buffer_putuint48(&otherbuf, tsig.timesigned);
}
if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
@@ -641,8 +723,7 @@ dns_tsig_sign(dns_message_t *msg) {
goto cleanup_context;
isc_buffer_putuint16(&databuf, querytsig.siglen);
if (isc_buffer_availablelength(&databuf) <
- querytsig.siglen)
- {
+ querytsig.siglen) {
ret = ISC_R_NOSPACE;
goto cleanup_context;
}
@@ -700,7 +781,7 @@ dns_tsig_sign(dns_message_t *msg) {
isc_buffer_clear(&databuf);
if (tsig.error == dns_tsigerror_badtime)
tsig.timesigned = querytsig.timesigned;
- buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
isc_buffer_putuint16(&databuf, tsig.fudge);
isc_buffer_usedregion(&databuf, &r);
ret = dst_context_adddata(ctx, &r);
@@ -852,6 +933,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
REQUIRE(source != NULL);
REQUIRE(DNS_MESSAGE_VALID(msg));
tsigkey = dns_message_gettsigkey(msg);
+
REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
msg->verify_attempted = 1;
@@ -907,8 +989,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
*/
if (is_response(msg) &&
(!dns_name_equal(keyname, &tsigkey->name) ||
- !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)))
- {
+ !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
msg->tsigstatus = dns_tsigerror_badkey;
tsig_log(msg->tsigkey, 2,
"key name and algorithm do not match");
@@ -1084,7 +1165,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
goto cleanup_context;
isc_buffer_clear(&databuf);
- buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
isc_buffer_putuint16(&databuf, tsig.fudge);
isc_buffer_putuint16(&databuf, tsig.error);
isc_buffer_putuint16(&databuf, tsig.otherlen);
@@ -1106,15 +1187,14 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
msg->tsigstatus = dns_tsigerror_badsig;
ret = DNS_R_TSIGVERIFYFAILURE;
tsig_log(msg->tsigkey, 2,
- "signature failed to verify");
+ "signature failed to verify(1)");
goto cleanup_context;
} else if (ret != ISC_R_SUCCESS)
goto cleanup_context;
dst_context_destroy(&ctx);
} else if (tsig.error != dns_tsigerror_badsig &&
- tsig.error != dns_tsigerror_badkey)
- {
+ tsig.error != dns_tsigerror_badkey) {
msg->tsigstatus = dns_tsigerror_badsig;
tsig_log(msg->tsigkey, 2, "signature was empty");
return (DNS_R_TSIGVERIFYFAILURE);
@@ -1201,8 +1281,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
* Do the key name and algorithm match that of the query?
*/
if (!dns_name_equal(keyname, &tsigkey->name) ||
- !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
- {
+ !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
msg->tsigstatus = dns_tsigerror_badkey;
ret = DNS_R_TSIGVERIFYFAILURE;
tsig_log(msg->tsigkey, 2,
@@ -1221,8 +1300,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
ret = DNS_R_CLOCKSKEW;
goto cleanup_querystruct;
} else if (now + msg->timeadjust <
- tsig.timesigned - tsig.fudge)
- {
+ tsig.timesigned - tsig.fudge) {
msg->tsigstatus = dns_tsigerror_badtime;
tsig_log(msg->tsigkey, 2,
"signature is in the future");
@@ -1312,7 +1390,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
*/
if (has_tsig) {
isc_buffer_init(&databuf, data, sizeof(data));
- buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
isc_buffer_putuint16(&databuf, tsig.fudge);
isc_buffer_usedregion(&databuf, &r);
ret = dst_context_adddata(msg->tsigctx, &r);
@@ -1339,7 +1417,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
if (ret == DST_R_VERIFYFAILURE) {
msg->tsigstatus = dns_tsigerror_badsig;
tsig_log(msg->tsigkey, 2,
- "signature failed to verify");
+ "signature failed to verify(2)");
ret = DNS_R_TSIGVERIFYFAILURE;
goto cleanup_context;
}
@@ -1375,6 +1453,10 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
REQUIRE(name != NULL);
REQUIRE(ring != NULL);
+ RWLOCK(&ring->lock, isc_rwlocktype_write);
+ cleanup_ring(ring);
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+
isc_stdtime_get(&now);
RWLOCK(&ring->lock, isc_rwlocktype_read);
key = NULL;
@@ -1393,7 +1475,7 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
*/
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
RWLOCK(&ring->lock, isc_rwlocktype_write);
- (void) dns_rbt_deletename(ring->keys, name, ISC_FALSE);
+ (void)dns_rbt_deletename(ring->keys, name, ISC_FALSE);
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
return (ISC_R_NOTFOUND);
}
@@ -1443,6 +1525,7 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
return (result);
}
+ ring->writecount = 0;
ring->mctx = NULL;
isc_mem_attach(mctx, &ring->mctx);
diff --git a/lib/dns/ttl.c b/lib/dns/ttl.c
index 39d2ac3..9d0dec5 100644
--- a/lib/dns/ttl.c
+++ b/lib/dns/ttl.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ttl.c,v 1.25.18.2 2005/04/29 00:16:07 marka Exp $ */
+/* $Id: ttl.c,v 1.29 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
index 685434b..c62b714 100644
--- a/lib/dns/validator.c
+++ b/lib/dns/validator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,18 +15,17 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.119.18.41.2.1 2009/03/17 02:23:49 marka Exp $ */
-
-/*! \file */
+/* $Id: validator.c,v 1.164.12.9 2009/05/07 23:47:12 tbox Exp $ */
#include <config.h>
+#include <isc/base32.h>
#include <isc/mem.h>
#include <isc/print.h>
+#include <isc/sha2.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/util.h>
-#include <isc/sha2.h>
#include <dns/db.h>
#include <dns/ds.h>
@@ -37,6 +36,7 @@
#include <dns/message.h>
#include <dns/ncache.h>
#include <dns/nsec.h>
+#include <dns/nsec3.h>
#include <dns/rdata.h>
#include <dns/rdatastruct.h>
#include <dns/rdataset.h>
@@ -89,7 +89,7 @@
#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
#define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */
-#define VALATTR_CANCELED 0x0002 /*%< Cancelled. */
+#define VALATTR_CANCELED 0x0002 /*%< Canceled. */
#define VALATTR_TRIEDVERIFY 0x0004 /*%< We have found a key and
* have attempted a verify. */
#define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */
@@ -98,16 +98,23 @@
/*!
* NSEC proofs to be looked for.
*/
-#define VALATTR_NEEDNOQNAME 0x0100
-#define VALATTR_NEEDNOWILDCARD 0x0200
-#define VALATTR_NEEDNODATA 0x0400
+#define VALATTR_NEEDNOQNAME 0x00000100
+#define VALATTR_NEEDNOWILDCARD 0x00000200
+#define VALATTR_NEEDNODATA 0x00000400
/*!
* NSEC proofs that have been found.
*/
-#define VALATTR_FOUNDNOQNAME 0x1000
-#define VALATTR_FOUNDNOWILDCARD 0x2000
-#define VALATTR_FOUNDNODATA 0x4000
+#define VALATTR_FOUNDNOQNAME 0x00001000
+#define VALATTR_FOUNDNOWILDCARD 0x00002000
+#define VALATTR_FOUNDNODATA 0x00004000
+#define VALATTR_FOUNDCLOSEST 0x00008000
+
+/*
+ *
+ */
+#define VALATTR_FOUNDOPTOUT 0x00010000
+#define VALATTR_FOUNDUNKNOWN 0x00020000
#define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
#define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
@@ -250,10 +257,20 @@ static isc_boolean_t
isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
isc_result_t dbresult)
{
- dns_rdataset_t set;
+ dns_fixedname_t fixed;
+ dns_label_t hashlabel;
+ dns_name_t nsec3name;
+ dns_rdata_nsec3_t nsec3;
dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t set;
+ int order;
+ int scope;
isc_boolean_t found;
+ isc_buffer_t buffer;
isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char owner[NSEC3_MAX_HASH_LENGTH];
+ unsigned int length;
REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
@@ -263,6 +280,8 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
else {
result = dns_ncache_getrdataset(rdataset, name,
dns_rdatatype_nsec, &set);
+ if (result == ISC_R_NOTFOUND)
+ goto trynsec3;
if (result != ISC_R_SUCCESS)
return (ISC_FALSE);
}
@@ -274,9 +293,78 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
if (result == ISC_R_SUCCESS) {
dns_rdataset_current(&set, &rdata);
found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
+ dns_rdata_reset(&rdata);
}
dns_rdataset_disassociate(&set);
return (found);
+
+ trynsec3:
+ /*
+ * Iterate over the ncache entry.
+ */
+ found = ISC_FALSE;
+ dns_name_init(&nsec3name, NULL);
+ dns_fixedname_init(&fixed);
+ dns_name_downcase(name, dns_fixedname_name(&fixed), NULL);
+ name = dns_fixedname_name(&fixed);
+ result = dns_rdataset_first(rdataset);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ dns_ncache_current(rdataset, &nsec3name, &set);
+ if (set.type != dns_rdatatype_nsec3) {
+ dns_rdataset_disassociate(&set);
+ continue;
+ }
+ dns_name_getlabel(&nsec3name, 0, &hashlabel);
+ isc_region_consume(&hashlabel, 1);
+ isc_buffer_init(&buffer, owner, sizeof(owner));
+ result = isc_base32hex_decoderegion(&hashlabel, &buffer);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&set);
+ continue;
+ }
+ for (result = dns_rdataset_first(&set);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&set))
+ {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&set, &rdata);
+ (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ if (nsec3.hash != 1)
+ continue;
+ length = isc_iterated_hash(hash, nsec3.hash,
+ nsec3.iterations, nsec3.salt,
+ nsec3.salt_length,
+ name->ndata, name->length);
+ if (length != isc_buffer_usedlength(&buffer))
+ continue;
+ order = memcmp(hash, owner, length);
+ if (order == 0) {
+ found = dns_nsec3_typepresent(&rdata,
+ dns_rdatatype_ns);
+ dns_rdataset_disassociate(&set);
+ return (found);
+ }
+ if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0)
+ continue;
+ /*
+ * Does this optout span cover the name?
+ */
+ scope = memcmp(owner, nsec3.next, nsec3.next_length);
+ if ((scope < 0 && order > 0 &&
+ memcmp(hash, nsec3.next, length) < 0) ||
+ (scope >= 0 && (order > 0 ||
+ memcmp(hash, nsec3.next, length) < 0)))
+ {
+ dns_rdataset_disassociate(&set);
+ return (ISC_TRUE);
+ }
+ }
+ dns_rdataset_disassociate(&set);
+ }
+ return (found);
}
/*%
@@ -767,10 +855,317 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
return (ISC_R_SUCCESS);
}
+static isc_result_t
+nsec3noexistnodata(dns_validator_t *val, dns_name_t* name,
+ dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
+ dns_name_t *zonename, isc_boolean_t *exists,
+ isc_boolean_t *data, isc_boolean_t *optout,
+ isc_boolean_t *unknown, isc_boolean_t *setclosest,
+ isc_boolean_t *setnearest, dns_name_t *closest,
+ dns_name_t *nearest)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fzone;
+ dns_fixedname_t qfixed;
+ dns_label_t hashlabel;
+ dns_name_t *qname;
+ dns_name_t *zone;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ int order;
+ int scope;
+ isc_boolean_t atparent;
+ isc_boolean_t first;
+ isc_boolean_t ns;
+ isc_boolean_t soa;
+ isc_buffer_t buffer;
+ isc_result_t answer = ISC_R_IGNORE;
+ isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char owner[NSEC3_MAX_HASH_LENGTH];
+ unsigned int length;
+ unsigned int qlabels;
+ unsigned int zlabels;
+
+ REQUIRE((exists == NULL && data == NULL) ||
+ (exists != NULL && data != NULL));
+ REQUIRE(nsec3set != NULL && nsec3set->type == dns_rdatatype_nsec3);
+ REQUIRE((setclosest == NULL && closest == NULL) ||
+ (setclosest != NULL && closest != NULL));
+ REQUIRE((setnearest == NULL && nearest == NULL) ||
+ (setnearest != NULL && nearest != NULL));
+
+ result = dns_rdataset_first(nsec3set);
+ if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "failure processing NSEC3 set");
+ return (result);
+ }
+
+ dns_rdataset_current(nsec3set, &rdata);
+
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
+
+ dns_fixedname_init(&fzone);
+ zone = dns_fixedname_name(&fzone);
+ zlabels = dns_name_countlabels(nsec3name);
+
+ /*
+ * NSEC3 records must have two or more labels to be valid.
+ */
+ if (zlabels < 2)
+ return (ISC_R_IGNORE);
+
+ /*
+ * Strip off the NSEC3 hash to get the zone.
+ */
+ zlabels--;
+ dns_name_split(nsec3name, zlabels, NULL, zone);
+
+ /*
+ * If not below the zone name we can ignore this record.
+ */
+ if (!dns_name_issubdomain(name, zone))
+ return (ISC_R_IGNORE);
+
+ /*
+ * Is this zone the same or deeper than the current zone?
+ */
+ if (dns_name_countlabels(zonename) == 0 ||
+ dns_name_issubdomain(zone, zonename))
+ dns_name_copy(zone, zonename, NULL);
+
+ if (!dns_name_equal(zone, zonename))
+ return (ISC_R_IGNORE);
+
+ /*
+ * Are we only looking for the most enclosing zone?
+ */
+ if (exists == NULL || data == NULL)
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Only set unknown once we are sure that this NSEC3 is from
+ * the deepest covering zone.
+ */
+ if (!dns_nsec3_supportedhash(nsec3.hash)) {
+ if (unknown != NULL)
+ *unknown = ISC_TRUE;
+ return (ISC_R_IGNORE);
+ }
+
+ /*
+ * Recover the hash from the first label.
+ */
+ dns_name_getlabel(nsec3name, 0, &hashlabel);
+ isc_region_consume(&hashlabel, 1);
+ isc_buffer_init(&buffer, owner, sizeof(owner));
+ result = isc_base32hex_decoderegion(&hashlabel, &buffer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * The hash lengths should match. If not ignore the record.
+ */
+ if (isc_buffer_usedlength(&buffer) != nsec3.next_length)
+ return (ISC_R_IGNORE);
+
+ /*
+ * Work out what this NSEC3 covers.
+ * Inside (<0) or outside (>=0).
+ */
+ scope = memcmp(owner, nsec3.next, nsec3.next_length);
+
+ /*
+ * Prepare to compute all the hashes.
+ */
+ dns_fixedname_init(&qfixed);
+ qname = dns_fixedname_name(&qfixed);
+ dns_name_downcase(name, qname, NULL);
+ qlabels = dns_name_countlabels(qname);
+ first = ISC_TRUE;
+
+ while (qlabels >= zlabels) {
+ length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
+ nsec3.salt, nsec3.salt_length,
+ qname->ndata, qname->length);
+ /*
+ * The computed hash length should match.
+ */
+ if (length != nsec3.next_length) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring NSEC bad length %u vs %u",
+ length, nsec3.next_length);
+ return (ISC_R_IGNORE);
+ }
+
+ order = memcmp(hash, owner, length);
+ if (first && order == 0) {
+ /*
+ * The hashes are the same.
+ */
+ atparent = dns_rdatatype_atparent(val->event->type);
+ ns = dns_nsec3_typepresent(&rdata, dns_rdatatype_ns);
+ soa = dns_nsec3_typepresent(&rdata, dns_rdatatype_soa);
+ if (ns && !soa) {
+ if (!atparent) {
+ /*
+ * This NSEC record is from somewhere
+ * higher in the DNS, and at the
+ * parent of a delegation. It can not
+ * be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring parent NSEC3");
+ return (ISC_R_IGNORE);
+ }
+ } else if (atparent && ns && soa) {
+ /*
+ * This NSEC record is from the child.
+ * It can not be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring child NSEC3");
+ return (ISC_R_IGNORE);
+ }
+ if (val->event->type == dns_rdatatype_cname ||
+ val->event->type == dns_rdatatype_nxt ||
+ val->event->type == dns_rdatatype_nsec ||
+ val->event->type == dns_rdatatype_key ||
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_cname)) {
+ *exists = ISC_TRUE;
+ *data = dns_nsec3_typepresent(&rdata,
+ val->event->type);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 proves name exists (owner) "
+ "data=%d", *data);
+ return (ISC_R_SUCCESS);
+ }
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 proves CNAME exists");
+ return (ISC_R_IGNORE);
+ }
+
+ if (order == 0 &&
+ dns_nsec3_typepresent(&rdata, dns_rdatatype_ns) &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_soa))
+ {
+ /*
+ * This NSEC3 record is from somewhere higher in
+ * the DNS, and at the parent of a delegation.
+ * It can not be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring parent NSEC3");
+ return (ISC_R_IGNORE);
+ }
+
+ /*
+ * Potential closest encloser.
+ */
+ if (order == 0) {
+ if (closest != NULL &&
+ (dns_name_countlabels(closest) == 0 ||
+ dns_name_issubdomain(qname, closest)) &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
+ (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
+ {
+
+ dns_name_format(qname, namebuf,
+ sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 indicates potential "
+ "closest encloser: '%s'",
+ namebuf);
+ dns_name_copy(qname, closest, NULL);
+ *setclosest = ISC_TRUE;
+ }
+ dns_name_format(qname, namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 at super-domain %s", namebuf);
+ return (answer);
+ }
+
+ /*
+ * Find if the name does not exist.
+ *
+ * We continue as we need to find the name closest to the
+ * closest encloser that doesn't exist.
+ *
+ * We also need to continue to ensure that we are not
+ * proving the non-existence of a record in a sub-zone.
+ * If that would be the case we will return ISC_R_IGNORE
+ * above.
+ */
+ if ((scope < 0 && order > 0 &&
+ memcmp(hash, nsec3.next, length) < 0) ||
+ (scope >= 0 && (order > 0 ||
+ memcmp(hash, nsec3.next, length) < 0)))
+ {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(qname, namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3), "NSEC3 proves "
+ "name does not exist: '%s'", namebuf);
+ if (nearest != NULL &&
+ (dns_name_countlabels(nearest) == 0 ||
+ dns_name_issubdomain(nearest, qname))) {
+ dns_name_copy(qname, nearest, NULL);
+ *setnearest = ISC_TRUE;
+ }
+#if 0
+ /*
+ * The closest encloser may be the zone name.
+ */
+ if (closest != NULL &&
+ dns_name_countlabels(closest) == 0 &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
+ (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
+ {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(zone, namebuf,
+ sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 potential closest "
+ "encloser from zone name: '%s'",
+ namebuf);
+ dns_name_copy(zone, closest, NULL);
+ *setclosest = ISC_TRUE;
+ }
+#endif
+ *exists = ISC_FALSE;
+ *data = ISC_FALSE;
+ if (optout != NULL) {
+ if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0)
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 indicates optout");
+ *optout =
+ ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
+ }
+ answer = ISC_R_SUCCESS;
+ }
+
+ qlabels--;
+ if (qlabels > 0)
+ dns_name_split(qname, qlabels, NULL, qname);
+ first = ISC_FALSE;
+ }
+ return (answer);
+}
+
/*%
* Callback for when NSEC records have been validated.
*
- * Looks for NOQNAME and NODATA proofs.
+ * Looks for NOQNAME, NODATA and OPTOUT proofs.
*
* Resumes nsecvalidate.
*/
@@ -779,6 +1174,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
dns_validatorevent_t *devent;
dns_validator_t *val;
dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
isc_boolean_t want_destroy;
isc_result_t result;
isc_boolean_t exists, data;
@@ -788,6 +1184,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
devent = (dns_validatorevent_t *)event;
rdataset = devent->rdataset;
+ sigrdataset = devent->sigrdataset;
val = devent->ev_arg;
result = devent->result;
dns_validator_destroy(&val->subvalidator);
@@ -834,11 +1231,18 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
}
if (!exists) {
val->attributes |= VALATTR_FOUNDNOQNAME;
+ val->attributes |= VALATTR_FOUNDCLOSEST;
+ /*
+ * The NSEC noqname proof also contains
+ * the closest encloser.
+
+ */
if (NEEDNOQNAME(val))
proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
devent->name;
}
}
+
result = nsecvalidate(val, ISC_TRUE);
if (result != DNS_R_WAIT)
validator_done(val, result);
@@ -992,13 +1396,25 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
* the validation process will stall if looping was to occur.
*/
static inline isc_boolean_t
-check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
+check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
dns_validator_t *parent;
for (parent = val; parent != NULL; parent = parent->parent) {
if (parent->event != NULL &&
parent->event->type == type &&
- dns_name_equal(parent->event->name, name))
+ dns_name_equal(parent->event->name, name) &&
+ /*
+ * As NSEC3 records are meta data you sometimes
+ * need to prove a NSEC3 record which says that
+ * itself doesn't exist.
+ */
+ (parent->event->type != dns_rdatatype_nsec3 ||
+ rdataset == NULL || sigrdataset == NULL ||
+ parent->event->message == NULL ||
+ parent->event->rdataset != NULL ||
+ parent->event->sigrdataset != NULL))
{
validator_log(val, ISC_LOG_DEBUG(3),
"continuing validation would lead to "
@@ -1021,7 +1437,7 @@ create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
if (dns_rdataset_isassociated(&val->fsigrdataset))
dns_rdataset_disassociate(&val->fsigrdataset);
- if (check_deadlock(val, name, type))
+ if (check_deadlock(val, name, type, NULL, NULL))
return (DNS_R_NOVALIDSIG);
validator_logcreate(val, name, type, caller, "fetch");
@@ -1044,7 +1460,7 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
{
isc_result_t result;
- if (check_deadlock(val, name, type))
+ if (check_deadlock(val, name, type, rdataset, sigrdataset))
return (DNS_R_NOVALIDSIG);
validator_logcreate(val, name, type, caller, "validator");
@@ -1128,7 +1544,7 @@ get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
}
/*%
- * Get the key that genertated this signature.
+ * Get the key that generated this signature.
*/
static isc_result_t
get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
@@ -1141,7 +1557,7 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
* Is the signer name appropriate for this signature?
*
* The signer name must be at the same level as the owner name
- * or closer to the the DNS root.
+ * or closer to the DNS root.
*/
namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
&order, &nlabels);
@@ -1163,6 +1579,23 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
*/
if (dns_rdatatype_atparent(val->event->rdataset->type))
return (DNS_R_CONTINUE);
+ } else {
+ /*
+ * SOA and NS RRsets can only be signed by a key with
+ * the same name.
+ */
+ if (val->event->rdataset->type == dns_rdatatype_soa ||
+ val->event->rdataset->type == dns_rdatatype_ns) {
+ const char *typename;
+
+ if (val->event->rdataset->type == dns_rdatatype_soa)
+ typename = "SOA";
+ else
+ typename = "NS";
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "%s signer mismatch", typename);
+ return (DNS_R_CONTINUE);
+ }
}
/*
@@ -1620,6 +2053,7 @@ dlv_validatezonekey(dns_validator_t *val) {
break;
}
if (result != ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&trdataset);
validator_log(val, ISC_LOG_DEBUG(3),
"no DNSKEY matching DLV");
continue;
@@ -1734,6 +2168,10 @@ validatezonekey(dns_validator_t *val) {
&sigrdata);
result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (!dns_name_equal(val->event->name, &sig.signer))
+ continue;
+
result = dns_keytable_findkeynode(val->keytable,
val->event->name,
sig.algorithm,
@@ -1957,6 +2395,7 @@ validatezonekey(dns_validator_t *val) {
break;
}
if (result != ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&trdataset);
validator_log(val, ISC_LOG_DEBUG(3),
"no DNSKEY matching DS");
continue;
@@ -1974,7 +2413,11 @@ validatezonekey(dns_validator_t *val) {
if (ds.key_tag != sig.keyid ||
ds.algorithm != sig.algorithm)
continue;
-
+ if (!dns_name_equal(val->event->name, &sig.signer)) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "DNSKEY signer mismatch");
+ continue;
+ }
dstkey = NULL;
result = dns_dnssec_keyfromrdata(val->event->name,
&keyrdata,
@@ -2044,7 +2487,8 @@ start_positive_validation(dns_validator_t *val) {
* \li ISC_R_SUCCESS
*/
static isc_result_t
-checkwildcard(dns_validator_t *val) {
+checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
+{
dns_name_t *name, *wild;
dns_message_t *message = val->event->message;
isc_result_t result;
@@ -2052,6 +2496,13 @@ checkwildcard(dns_validator_t *val) {
char namebuf[DNS_NAME_FORMATSIZE];
wild = dns_fixedname_name(&val->wild);
+
+ if (dns_name_countlabels(wild) == 0) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "in checkwildcard: no wildcard to check");
+ return (ISC_R_SUCCESS);
+ }
+
dns_name_format(wild, namebuf, sizeof(namebuf));
validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
@@ -2068,9 +2519,8 @@ checkwildcard(dns_validator_t *val) {
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link))
{
- if (rdataset->type != dns_rdatatype_nsec)
+ if (rdataset->type != type)
continue;
- val->nsecset = rdataset;
for (sigrdataset = ISC_LIST_HEAD(name->list);
sigrdataset != NULL;
@@ -2086,7 +2536,8 @@ checkwildcard(dns_validator_t *val) {
if (rdataset->trust != dns_trust_secure)
continue;
- if (((val->attributes & VALATTR_NEEDNODATA) != 0 ||
+ if (rdataset->type == dns_rdatatype_nsec &&
+ ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
(val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
(val->attributes & VALATTR_FOUNDNODATA) == 0 &&
(val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
@@ -2108,6 +2559,31 @@ checkwildcard(dns_validator_t *val) {
name;
return (ISC_R_SUCCESS);
}
+
+ if (rdataset->type == dns_rdatatype_nsec3 &&
+ ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
+ (val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
+ (val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
+ nsec3noexistnodata(val, wild, name, rdataset,
+ zonename, &exists, &data,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL) == ISC_R_SUCCESS)
+ {
+ dns_name_t **proofs = val->event->proofs;
+ if (exists && !data)
+ val->attributes |= VALATTR_FOUNDNODATA;
+ if (exists && !data && NEEDNODATA(val))
+ proofs[DNS_VALIDATOR_NODATAPROOF] =
+ name;
+ if (!exists)
+ val->attributes |=
+ VALATTR_FOUNDNOWILDCARD;
+ if (!exists && NEEDNOQNAME(val))
+ proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
+ name;
+ return (ISC_R_SUCCESS);
+ }
}
}
if (result == ISC_R_NOMORE)
@@ -2115,6 +2591,170 @@ checkwildcard(dns_validator_t *val) {
return (result);
}
+
+static isc_result_t
+findnsec3proofs(dns_validator_t *val) {
+ dns_name_t *name;
+ dns_message_t *message = val->event->message;
+ isc_result_t result;
+ isc_boolean_t exists, data, optout, unknown;
+ isc_boolean_t setclosest, setnearest;
+ dns_fixedname_t fclosest, fnearest, fzonename;
+ dns_name_t *closest, *nearest, *zonename;
+ dns_name_t **proofs = val->event->proofs;
+
+ dns_fixedname_init(&fclosest);
+ dns_fixedname_init(&fnearest);
+ dns_fixedname_init(&fzonename);
+ closest = dns_fixedname_name(&fclosest);
+ nearest = dns_fixedname_name(&fnearest);
+ zonename = dns_fixedname_name(&fzonename);
+
+ for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
+ {
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type != dns_rdatatype_nsec3)
+ continue;
+
+ for (sigrdataset = ISC_LIST_HEAD(name->list);
+ sigrdataset != NULL;
+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
+ {
+ if (sigrdataset->type == dns_rdatatype_rrsig &&
+ sigrdataset->covers == dns_rdatatype_nsec3)
+ break;
+ }
+ if (sigrdataset == NULL)
+ continue;
+
+ if (rdataset->trust != dns_trust_secure)
+ continue;
+
+ result = nsec3noexistnodata(val, val->event->name,
+ name, rdataset,
+ zonename, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS)
+ return (result);
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ if (dns_name_countlabels(zonename) == 0)
+ return (ISC_R_SUCCESS);
+
+ for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
+ {
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type != dns_rdatatype_nsec3)
+ continue;
+
+ for (sigrdataset = ISC_LIST_HEAD(name->list);
+ sigrdataset != NULL;
+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
+ {
+ if (sigrdataset->type == dns_rdatatype_rrsig &&
+ sigrdataset->covers == dns_rdatatype_nsec3)
+ break;
+ }
+ if (sigrdataset == NULL)
+ continue;
+
+ if (rdataset->trust != dns_trust_secure)
+ continue;
+
+ /*
+ * We process all NSEC3 records to find the closest
+ * encloser and nearest name to the closest encloser.
+ */
+ setclosest = setnearest = ISC_FALSE;
+ optout = ISC_FALSE;
+ unknown = ISC_FALSE;
+ result = nsec3noexistnodata(val, val->event->name,
+ name, rdataset,
+ zonename, &exists,
+ &data, &optout, &unknown,
+ &setclosest, &setnearest,
+ closest, nearest);
+ if (setclosest)
+ proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
+ if (unknown)
+ val->attributes |= VALATTR_FOUNDUNKNOWN;
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (exists && !data && NEEDNODATA(val)) {
+ val->attributes |= VALATTR_FOUNDNODATA;
+ proofs[DNS_VALIDATOR_NODATAPROOF] = name;
+ }
+ if (!exists && setnearest) {
+ val->attributes |= VALATTR_FOUNDNOQNAME;
+ proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
+ if (optout)
+ val->attributes |= VALATTR_FOUNDOPTOUT;
+ }
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ /*
+ * To know we have a valid noqname and optout proofs we need to also
+ * have a valid closest encloser. Otherwise we could still be looking
+ * at proofs from the parent zone.
+ */
+ if (dns_name_countlabels(closest) > 0 &&
+ dns_name_countlabels(nearest) ==
+ dns_name_countlabels(closest) + 1 &&
+ dns_name_issubdomain(nearest, closest))
+ {
+ val->attributes |= VALATTR_FOUNDCLOSEST;
+ result = dns_name_concatenate(dns_wildcardname, closest,
+ dns_fixedname_name(&val->wild),
+ NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ } else {
+ val->attributes &= ~VALATTR_FOUNDNOQNAME;
+ val->attributes &= ~VALATTR_FOUNDOPTOUT;
+ proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
+ }
+
+ /*
+ * Do we need to check for the wildcard?
+ */
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
+ (val->attributes & VALATTR_FOUNDCLOSEST) != 0 &&
+ (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0) ||
+ (val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
+ result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ return (result);
+}
+
/*%
* Prove a negative answer is good or that there is a NOQNAME when the
* answer is from a wildcard.
@@ -2220,7 +2860,10 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
if ((val->attributes & VALATTR_NEEDNODATA) == 0 &&
(val->attributes & VALATTR_NEEDNOWILDCARD) == 0 &&
(val->attributes & VALATTR_NEEDNOQNAME) != 0) {
- if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0) {
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) == 0)
+ findnsec3proofs(val);
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
+ (val->attributes & VALATTR_FOUNDCLOSEST) != 0) {
validator_log(val, ISC_LOG_DEBUG(3),
"noqname proof found");
validator_log(val, ISC_LOG_DEBUG(3),
@@ -2228,34 +2871,57 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
val->event->rdataset->trust = dns_trust_secure;
val->event->sigrdataset->trust = dns_trust_secure;
return (ISC_R_SUCCESS);
+ } else if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0 &&
+ dns_name_countlabels(dns_fixedname_name(&val->wild))
+ != 0) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "optout proof found");
+ val->event->optout = ISC_TRUE;
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "unknown NSEC3 hash algorithm found");
+ markanswer(val);
+ return (ISC_R_SUCCESS);
}
validator_log(val, ISC_LOG_DEBUG(3),
"noqname proof not found");
return (DNS_R_NOVALIDNSEC);
}
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0)
+ findnsec3proofs(val);
+
/*
* Do we need to check for the wildcard?
*/
if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
+ (val->attributes & VALATTR_FOUNDCLOSEST) != 0 &&
(((val->attributes & VALATTR_NEEDNODATA) != 0 &&
(val->attributes & VALATTR_FOUNDNODATA) == 0) ||
(val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
- result = checkwildcard(val);
+ result = checkwildcard(val, dns_rdatatype_nsec, NULL);
if (result != ISC_R_SUCCESS)
return (result);
}
if (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
- (val->attributes & VALATTR_FOUNDNODATA) != 0) ||
+ ((val->attributes & VALATTR_FOUNDNODATA) != 0 ||
+ (val->attributes & VALATTR_FOUNDOPTOUT) != 0)) ||
((val->attributes & VALATTR_NEEDNOQNAME) != 0 &&
(val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
(val->attributes & VALATTR_NEEDNOWILDCARD) != 0 &&
- (val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)) {
+ (val->attributes & VALATTR_FOUNDNOWILDCARD) != 0 &&
+ (val->attributes & VALATTR_FOUNDCLOSEST) != 0)) {
+ if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
+ val->event->optout = ISC_TRUE;
validator_log(val, ISC_LOG_DEBUG(3),
"nonexistence proof(s) found");
return (ISC_R_SUCCESS);
}
+ findnsec3proofs(val);
validator_log(val, ISC_LOG_DEBUG(3),
"nonexistence proof(s) not found");
@@ -2380,7 +3046,7 @@ dlvfetched(isc_task_t *task, isc_event_t *event) {
}
/*%
- * Start the DLV lookup proccess.
+ * Start the DLV lookup process.
*
* Returns
* \li ISC_R_SUCCESS
@@ -2424,7 +3090,7 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
dlv_validator_start(val);
return (DNS_R_WAIT);
- }
+ }
validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
"algorithms", namebuf);
markanswer(val);
@@ -2566,9 +3232,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
dns_name_t *secroot;
dns_name_t *tname;
char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_t *found;
+ dns_fixedname_t fixedfound;
dns_fixedname_init(&fixedsecroot);
secroot = dns_fixedname_name(&fixedsecroot);
+ dns_fixedname_init(&fixedfound);
+ found = dns_fixedname_name(&fixedfound);
if (val->havedlvsep)
dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
else {
@@ -2676,6 +3346,28 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
goto out;
return (DNS_R_WAIT);
}
+ /*
+ * Zones using NSEC3 don't return a NSEC RRset so
+ * we need to use dns_view_findzonecut2 to find
+ * the zone cut.
+ */
+ if (result == DNS_R_NXRRSET &&
+ !dns_rdataset_isassociated(&val->frdataset) &&
+ dns_view_findzonecut2(val->view, tname, found,
+ 0, 0, ISC_FALSE, ISC_FALSE,
+ NULL, NULL) == ISC_R_SUCCESS &&
+ dns_name_equal(tname, found)) {
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure");
+ return (DNS_R_MUSTBESECURE);
+ }
+ if (val->view->dlv == NULL || DLVTRIED(val)) {
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ }
+ return (startfinddlvsep(val, tname));
+ }
if (val->frdataset.trust < dns_trust_secure) {
/*
* This shouldn't happen, since the negative
@@ -2775,6 +3467,15 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
return (DNS_R_WAIT);
}
}
+
+/*
+ if ((val->attributes & VALATTR_NEEDOPTOUT) == 0 &&
+ val->event->message != NULL) {
+ val->attributes |= VALATTR_NEEDOPTOUT;
+ return (nsecvalidate(val, ISC_FALSE));
+ }
+*/
+
validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
@@ -2808,7 +3509,7 @@ dlv_validator_start(dns_validator_t *val) {
/*%
* Start the validation process.
*
- * Attempt to valididate the answer based on the category it appears to
+ * Attempt to validate the answer based on the category it appears to
* fall in.
* \li 1. secure positive answer.
* \li 2. unsecure positive answer.
@@ -2829,7 +3530,7 @@ validator_start(isc_task_t *task, isc_event_t *event) {
vevent = (dns_validatorevent_t *)event;
val = vevent->validator;
- /* If the validator has been cancelled, val->event == NULL */
+ /* If the validator has been canceled, val->event == NULL */
if (val->event == NULL)
return;
@@ -2955,6 +3656,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
event->sigrdataset = sigrdataset;
event->message = message;
memset(event->proofs, 0, sizeof(event->proofs));
+ event->optout = ISC_FALSE;
result = isc_mutex_init(&val->lock);
if (result != ISC_R_SUCCESS)
goto cleanup_event;
@@ -2984,6 +3686,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
dns_rdataset_init(&val->frdataset);
dns_rdataset_init(&val->fsigrdataset);
dns_fixedname_init(&val->wild);
+ dns_fixedname_init(&val->nearest);
+ dns_fixedname_init(&val->closest);
ISC_LINK_INIT(val, link);
val->magic = VALIDATOR_MAGIC;
diff --git a/lib/dns/version.c b/lib/dns/version.c
index 1c03774..fbc8889 100644
--- a/lib/dns/version.c
+++ b/lib/dns/version.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: version.c,v 1.11.18.2 2005/04/29 00:16:07 marka Exp $ */
+/* $Id: version.c,v 1.15 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/view.c b/lib/dns/view.c
index 4851cf0..5f1447a 100644
--- a/lib/dns/view.c
+++ b/lib/dns/view.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,15 +15,16 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: view.c,v 1.126.18.16 2008/06/17 23:46:03 tbox Exp $ */
+/* $Id: view.c,v 1.150.84.2 2009/01/29 23:47:44 tbox Exp $ */
/*! \file */
#include <config.h>
#include <isc/hash.h>
-#include <isc/task.h>
+#include <isc/stats.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/task.h>
#include <isc/util.h>
#include <dns/acache.h>
@@ -43,6 +44,7 @@
#include <dns/request.h>
#include <dns/resolver.h>
#include <dns/result.h>
+#include <dns/stats.h>
#include <dns/tsig.h>
#include <dns/zone.h>
#include <dns/zt.h>
@@ -151,6 +153,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->delonly = NULL;
view->rootdelonly = ISC_FALSE;
view->rootexclude = NULL;
+ view->resstats = NULL;
+ view->resquerystats = NULL;
/*
* Initialize configuration data with default values.
@@ -165,8 +169,14 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->minimalresponses = ISC_FALSE;
view->transfer_format = dns_one_answer;
view->queryacl = NULL;
+ view->queryonacl = NULL;
view->recursionacl = NULL;
+ view->recursiononacl = NULL;
view->sortlist = NULL;
+ view->transferacl = NULL;
+ view->notifyacl = NULL;
+ view->updateacl = NULL;
+ view->upfwdacl = NULL;
view->requestixfr = ISC_TRUE;
view->provideixfr = ISC_TRUE;
view->maxcachettl = 7 * 24 * 3600;
@@ -286,10 +296,22 @@ destroy(dns_view_t *view) {
dns_acl_detach(&view->matchdestinations);
if (view->queryacl != NULL)
dns_acl_detach(&view->queryacl);
+ if (view->queryonacl != NULL)
+ dns_acl_detach(&view->queryonacl);
if (view->recursionacl != NULL)
dns_acl_detach(&view->recursionacl);
+ if (view->recursiononacl != NULL)
+ dns_acl_detach(&view->recursiononacl);
if (view->sortlist != NULL)
dns_acl_detach(&view->sortlist);
+ if (view->transferacl != NULL)
+ dns_acl_detach(&view->transferacl);
+ if (view->notifyacl != NULL)
+ dns_acl_detach(&view->notifyacl);
+ if (view->updateacl != NULL)
+ dns_acl_detach(&view->updateacl);
+ if (view->upfwdacl != NULL)
+ dns_acl_detach(&view->upfwdacl);
if (view->delonly != NULL) {
dns_name_t *name;
int i;
@@ -325,6 +347,10 @@ destroy(dns_view_t *view) {
sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
view->rootexclude = NULL;
}
+ if (view->resstats != NULL)
+ isc_stats_detach(&view->resstats);
+ if (view->resquerystats != NULL)
+ dns_stats_detach(&view->resquerystats);
dns_keytable_detach(&view->trustedkeys);
dns_keytable_detach(&view->secroots);
dns_fwdtable_destroy(&view->fwdtable);
@@ -571,6 +597,7 @@ dns_view_createresolver(dns_view_t *view,
}
result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
+ isc_mem_setname(mctx, "ADB", NULL);
isc_mem_detach(&mctx);
if (result != ISC_R_SUCCESS) {
dns_resolver_shutdown(view->resolver);
@@ -1129,6 +1156,55 @@ dns_viewlist_find(dns_viewlist_t *list, const char *name,
}
isc_result_t
+dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
+ isc_boolean_t allclasses, dns_rdataclass_t rdclass,
+ dns_zone_t **zonep)
+{
+ dns_view_t *view;
+ isc_result_t result;
+ dns_zone_t *zone1 = NULL, *zone2 = NULL;
+ dns_zone_t **zp = NULL;;
+
+ REQUIRE(list != NULL);
+ for (view = ISC_LIST_HEAD(*list);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (allclasses == ISC_FALSE && view->rdclass != rdclass)
+ continue;
+
+ /*
+ * If the zone is defined in more than one view,
+ * treat it as not found.
+ */
+ zp = (zone1 == NULL) ? &zone1 : &zone2;
+ result = dns_zt_find(view->zonetable, name, 0, NULL, zp);
+ INSIST(result == ISC_R_SUCCESS ||
+ result == ISC_R_NOTFOUND ||
+ result == DNS_R_PARTIALMATCH);
+
+ /* Treat a partial match as no match */
+ if (result == DNS_R_PARTIALMATCH) {
+ dns_zone_detach(zp);
+ result = ISC_R_NOTFOUND;
+ }
+
+ if (zone2 != NULL) {
+ dns_zone_detach(&zone1);
+ dns_zone_detach(&zone2);
+ return (ISC_R_NOTFOUND);
+ }
+ }
+
+ if (zone1 != NULL) {
+ dns_zone_attach(zone1, zonep);
+ dns_zone_detach(&zone1);
+ return (ISC_R_SUCCESS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
dns_view_load(dns_view_t *view, isc_boolean_t stop) {
REQUIRE(DNS_VIEW_VALID(view));
@@ -1354,3 +1430,39 @@ dns_view_freezezones(dns_view_t *view, isc_boolean_t value) {
REQUIRE(DNS_VIEW_VALID(view));
return (dns_zt_freezezones(view->zonetable, value));
}
+
+void
+dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+ REQUIRE(view->resstats == NULL);
+
+ isc_stats_attach(stats, &view->resstats);
+}
+
+void
+dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ if (view->resstats != NULL)
+ isc_stats_attach(view->resstats, statsp);
+}
+
+void
+dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+ REQUIRE(view->resquerystats == NULL);
+
+ dns_stats_attach(stats, &view->resquerystats);
+}
+
+void
+dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ if (view->resquerystats != NULL)
+ dns_stats_attach(view->resquerystats, statsp);
+}
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
index 7171a37..4e3d2c3 100644
--- a/lib/dns/xfrin.c
+++ b/lib/dns/xfrin.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: xfrin.c,v 1.135.18.23 2008/09/25 04:15:52 marka Exp $ */
+/* $Id: xfrin.c,v 1.166 2008/09/25 04:12:39 marka Exp $ */
/*! \file */
@@ -142,6 +142,11 @@ struct dns_xfrin_ctx {
isc_boolean_t is_ixfr;
unsigned int nmsg; /*%< Number of messages recvd */
+ unsigned int nrecs; /*%< Number of records recvd */
+ isc_uint64_t nbytes; /*%< Number of bytes received */
+
+ isc_time_t start; /*%< Start time of the transfer */
+ isc_time_t end; /*%< End time of the transfer */
dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */
isc_buffer_t *lasttsig; /*%< The last TSIG */
@@ -426,6 +431,8 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
{
isc_result_t result;
+ xfr->nrecs++;
+
if (rdata->type == dns_rdatatype_none ||
dns_rdatatype_ismeta(rdata->type))
FAIL(DNS_R_FORMERR);
@@ -804,6 +811,9 @@ xfrin_create(isc_mem_t *mctx,
/* end_serial */
xfr->nmsg = 0;
+ xfr->nrecs = 0;
+ xfr->nbytes = 0;
+ isc_time_now(&xfr->start);
xfr->tsigkey = NULL;
if (tsigkey != NULL)
@@ -865,6 +875,7 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
isc_sockaddr_pf(&xfr->sourceaddr),
isc_sockettype_tcp,
&xfr->socket));
+ isc_socket_setname(xfr->socket, "xfrin", NULL);
#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr,
ISC_SOCKET_REUSEADDRESS));
@@ -908,8 +919,7 @@ static void
xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
- isc_result_t evresult = cev->result;
- isc_result_t result;
+ isc_result_t result = cev->result;
char sourcetext[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_t sockaddr;
@@ -926,7 +936,18 @@ xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
return;
}
- CHECK(evresult);
+ if (result != ISC_R_SUCCESS) {
+ dns_zonemgr_t * zmgr = dns_zone_getmgr(xfr->zone);
+ isc_time_t now;
+
+ if (zmgr != NULL) {
+ TIME_NOW(&now);
+ dns_zonemgr_unreachableadd(zmgr, &xfr->masteraddr,
+ &xfr->sourceaddr, &now);
+ }
+ goto failure;
+ }
+
result = isc_socket_getsockname(xfr->socket, &sockaddr);
if (result == ISC_R_SUCCESS) {
isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
@@ -1054,6 +1075,9 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
xfr->checkid = ISC_TRUE;
xfr->id++;
xfr->nmsg = 0;
+ xfr->nrecs = 0;
+ xfr->nbytes = 0;
+ isc_time_now(&xfr->start);
msg->id = xfr->id;
if (xfr->tsigctx != NULL)
dst_context_destroy(&xfr->tsigctx);
@@ -1308,6 +1332,11 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
xfr->nmsg++;
/*
+ * Update the number of bytes received.
+ */
+ xfr->nbytes += tcpmsg->buffer.used;
+
+ /*
* Take the context back.
*/
INSIST(xfr->tsigctx == NULL);
@@ -1373,6 +1402,9 @@ xfrin_timeout(isc_task_t *task, isc_event_t *event) {
static void
maybe_free(dns_xfrin_ctx_t *xfr) {
+ isc_uint64_t msecs;
+ isc_uint64_t persec;
+
REQUIRE(VALID_XFRIN(xfr));
if (! xfr->shuttingdown || xfr->refcount != 0 ||
@@ -1380,7 +1412,22 @@ maybe_free(dns_xfrin_ctx_t *xfr) {
xfr->recvs != 0)
return;
- xfrin_log(xfr, ISC_LOG_INFO, "end of transfer");
+ /*
+ * Calculate the length of time the transfer took,
+ * and print a log message with the bytes and rate.
+ */
+ isc_time_now(&xfr->end);
+ msecs = isc_time_microdiff(&xfr->end, &xfr->start) / 1000;
+ if (msecs == 0)
+ msecs = 1;
+ persec = (xfr->nbytes * 1000) / msecs;
+ xfrin_log(xfr, ISC_LOG_INFO,
+ "Transfer completed: %d messages, %d records, "
+ "%" ISC_PRINT_QUADFORMAT "u bytes, "
+ "%u.%03u secs (%u bytes/sec)",
+ xfr->nmsg, xfr->nrecs, xfr->nbytes,
+ (unsigned int) (msecs / 1000), (unsigned int) (msecs % 1000),
+ (unsigned int) persec);
if (xfr->socket != NULL)
isc_socket_detach(&xfr->socket);
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 36f303c..423b005 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,11 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.410.18.55 2008/10/24 01:43:17 tbox Exp $ */
+/* $Id: zone.c,v 1.483.36.6 2009/03/26 22:57:07 marka Exp $ */
/*! \file */
#include <config.h>
+#include <errno.h>
#include <isc/file.h>
#include <isc/mutex.h>
@@ -29,6 +30,9 @@
#include <isc/refcount.h>
#include <isc/rwlock.h>
#include <isc/serial.h>
+#include <isc/strerror.h>
+#include <isc/stats.h>
+#include <isc/stdtime.h>
#include <isc/string.h>
#include <isc/taskpool.h>
#include <isc/timer.h>
@@ -40,29 +44,37 @@
#include <dns/callbacks.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
+#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/journal.h>
+#include <dns/keyvalues.h>
#include <dns/log.h>
#include <dns/master.h>
#include <dns/masterdump.h>
#include <dns/message.h>
#include <dns/name.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
#include <dns/peer.h>
#include <dns/rcode.h>
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/request.h>
#include <dns/resolver.h>
#include <dns/result.h>
-#include <dns/stats.h>
+#include <dns/soa.h>
#include <dns/ssu.h>
+#include <dns/stats.h>
#include <dns/tsig.h>
#include <dns/xfrin.h>
#include <dns/zone.h>
+#include <dst/dst.h>
+
#define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
#define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
@@ -90,6 +102,8 @@
#define RANGE(a, min, max) \
(((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
+#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
+
/*
* Default values.
*/
@@ -111,6 +125,10 @@ typedef struct dns_load dns_load_t;
typedef struct dns_forward dns_forward_t;
typedef struct dns_io dns_io_t;
typedef ISC_LIST(dns_io_t) dns_iolist_t;
+typedef struct dns_signing dns_signing_t;
+typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
+typedef struct dns_nsec3chain dns_nsec3chain_t;
+typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
#define DNS_ZONE_CHECKLOCK
#ifdef DNS_ZONE_CHECKLOCK
@@ -178,11 +196,16 @@ struct dns_zone {
isc_time_t dumptime;
isc_time_t loadtime;
isc_time_t notifytime;
+ isc_time_t resigntime;
+ isc_time_t keywarntime;
+ isc_time_t signingtime;
+ isc_time_t nsec3chaintime;
isc_uint32_t serial;
isc_uint32_t refresh;
isc_uint32_t retry;
isc_uint32_t expire;
isc_uint32_t minimum;
+ isc_stdtime_t key_expiry;
char *keydirectory;
isc_uint32_t maxrefresh;
@@ -215,6 +238,7 @@ struct dns_zone {
dns_acl_t *forward_acl;
dns_acl_t *notify_acl;
dns_acl_t *query_acl;
+ dns_acl_t *queryon_acl;
dns_acl_t *xfr_acl;
isc_boolean_t update_disabled;
isc_boolean_t zero_no_soa_ttl;
@@ -232,6 +256,7 @@ struct dns_zone {
isc_event_t ctlevent;
dns_ssutable_t *ssutable;
isc_uint32_t sigvalidityinterval;
+ isc_uint32_t sigresigninginterval;
dns_view_t *view;
dns_acache_t *acache;
dns_checkmxfunc_t checkmx;
@@ -247,17 +272,39 @@ struct dns_zone {
ISC_LINK(dns_zone_t) statelink;
dns_zonelist_t *statelist;
/*%
- * Optional per-zone statistics counters (NULL if not present).
+ * Statistics counters about zone management.
*/
- isc_uint64_t *counters;
+ isc_stats_t *stats;
+ /*%
+ * Optional per-zone statistics counters. Counted outside of this
+ * module.
+ */
+ isc_boolean_t requeststats_on;
+ isc_stats_t *requeststats;
isc_uint32_t notifydelay;
dns_isselffunc_t isself;
void *isselfarg;
+ char * strnamerd;
+ char * strname;
+ char * strrdclass;
+ char * strviewname;
+
/*%
* Serial number for deferred journal compaction.
*/
isc_uint32_t compact_serial;
+ /*%
+ * Keys that are signing the zone for the first time.
+ */
+ dns_signinglist_t signing;
+ dns_nsec3chainlist_t nsec3chain;
+ /*%
+ * Signing / re-signing quantum stopping parameters.
+ */
+ isc_uint32_t signatures;
+ isc_uint32_t nodes;
+ dns_rdatatype_t privatetype;
};
#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
@@ -287,7 +334,7 @@ struct dns_zone {
* reload */
#define DNS_ZONEFLG_NOMASTERS 0x00001000U /*%< an attempt to refresh a
* zone with no masters
- * occured */
+ * occurred */
#define DNS_ZONEFLG_LOADING 0x00002000U /*%< load from disk in progress*/
#define DNS_ZONEFLG_HAVETIMERS 0x00004000U /*%< timer values have been set
* from SOA (if not set, we
@@ -310,6 +357,21 @@ struct dns_zone {
/* Flags for zone_load() */
#define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
+#define UNREACH_CHACHE_SIZE 10U
+#define UNREACH_HOLD_TIME 600 /* 10 minutes */
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+struct dns_unreachable {
+ isc_sockaddr_t remote;
+ isc_sockaddr_t local;
+ isc_uint32_t expire;
+ isc_uint32_t last;
+};
+
struct dns_zonemgr {
unsigned int magic;
isc_mem_t * mctx;
@@ -338,6 +400,10 @@ struct dns_zonemgr {
isc_uint32_t ioactive;
dns_iolist_t high;
dns_iolist_t low;
+
+ /* Locked by rwlock. */
+ /* LRU cache */
+ struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
};
/*%
@@ -410,6 +476,56 @@ struct dns_io {
isc_event_t *event;
};
+/*%
+ * Hold state for when we are signing a zone with a new
+ * DNSKEY as result of an update.
+ */
+struct dns_signing {
+ unsigned int magic;
+ dns_db_t *db;
+ dns_dbiterator_t *dbiterator;
+ dns_secalg_t algorithm;
+ isc_uint16_t keyid;
+ isc_boolean_t delete;
+ isc_boolean_t done;
+ ISC_LINK(dns_signing_t) link;
+};
+
+struct dns_nsec3chain {
+ unsigned int magic;
+ dns_db_t *db;
+ dns_dbiterator_t *dbiterator;
+ dns_rdata_nsec3param_t nsec3param;
+ unsigned char salt[255];
+ isc_boolean_t done;
+ isc_boolean_t seen_nsec;
+ isc_boolean_t delete_nsec;
+ isc_boolean_t save_delete_nsec;
+ ISC_LINK(dns_nsec3chain_t) link;
+};
+/*%<
+ * 'dbiterator' contains a iterator for the database. If we are creating
+ * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
+ * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
+ * iterated.
+ *
+ * 'nsec3param' contains the parameters of the NSEC3 chain being created
+ * or removed.
+ *
+ * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
+ *
+ * 'seen_nsec' will be set to true if, while iterating the zone to create a
+ * NSEC3 chain, a NSEC record is seen.
+ *
+ * 'delete_nsec' will be set to true if, at the completion of the creation
+ * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
+ * are in the process of deleting the NSEC chain.
+ *
+ * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
+ * so it can be recovered in the event of a error.
+ */
+
+
#define SEND_BUFFER_SIZE 2048
static void zone_settimer(dns_zone_t *, isc_time_t *);
@@ -436,6 +552,10 @@ static void zone_shutdown(isc_task_t *, isc_event_t *);
static void zone_loaddone(void *arg, isc_result_t result);
static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
isc_time_t loadtime);
+static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
+static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
+static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
+static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
#if 0
/* ondestroy example */
@@ -484,6 +604,12 @@ static void zone_saveunique(dns_zone_t *zone, const char *path,
static void zone_maintenance(dns_zone_t *zone);
static void zone_notify(dns_zone_t *zone, isc_time_t *now);
static void dump_done(void *arg, isc_result_t result);
+static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
+ isc_sockaddr_t *remote,
+ isc_sockaddr_t *local,
+ isc_time_t *now);
+static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
+ isc_uint16_t keyid, isc_boolean_t delete);
#define ENTER zone_debuglog(zone, me, 1, "enter")
@@ -518,6 +644,15 @@ static const char *dbargv_default[] = { "rbt" };
} \
} while (0)
+/*%
+ * Increment resolver-related statistics counters. Zone must be locked.
+ */
+static inline void
+inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
+ if (zone->stats != NULL)
+ isc_stats_increment(zone->stats, counter);
+}
+
/***
*** Public functions.
***/
@@ -559,8 +694,12 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
goto free_dblock;
zone->irefs = 0;
dns_name_init(&zone->origin, NULL);
+ zone->strnamerd = NULL;
+ zone->strname = NULL;
+ zone->strrdclass = NULL;
+ zone->strviewname = NULL;
zone->masterfile = NULL;
- zone->masterformat = dns_masterformat_none;
+ zone->masterformat = dns_masterformat_none;
zone->keydirectory = NULL;
zone->journalsize = -1;
zone->journal = NULL;
@@ -575,6 +714,10 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
isc_time_settoepoch(&zone->dumptime);
isc_time_settoepoch(&zone->loadtime);
zone->notifytime = now;
+ isc_time_settoepoch(&zone->resigntime);
+ isc_time_settoepoch(&zone->keywarntime);
+ isc_time_settoepoch(&zone->signingtime);
+ isc_time_settoepoch(&zone->nsec3chaintime);
zone->serial = 0;
zone->refresh = DNS_ZONE_DEFAULTREFRESH;
zone->retry = DNS_ZONE_DEFAULTRETRY;
@@ -597,6 +740,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->forward_acl = NULL;
zone->notify_acl = NULL;
zone->query_acl = NULL;
+ zone->queryon_acl = NULL;
zone->xfr_acl = NULL;
zone->update_disabled = ISC_FALSE;
zone->zero_no_soa_ttl = ISC_TRUE;
@@ -622,6 +766,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->maxxfrout = MAX_XFER_TIME;
zone->ssutable = NULL;
zone->sigvalidityinterval = 30 * 24 * 3600;
+ zone->sigresigninginterval = 7 * 24 * 3600;
zone->view = NULL;
zone->acache = NULL;
zone->checkmx = NULL;
@@ -629,10 +774,17 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->checkns = NULL;
ISC_LINK_INIT(zone, statelink);
zone->statelist = NULL;
- zone->counters = NULL;
+ zone->stats = NULL;
+ zone->requeststats_on = ISC_FALSE;
+ zone->requeststats = NULL;
zone->notifydelay = 5;
zone->isself = NULL;
zone->isselfarg = NULL;
+ ISC_LIST_INIT(zone->signing);
+ ISC_LIST_INIT(zone->nsec3chain);
+ zone->signatures = 10;
+ zone->nodes = 100;
+ zone->privatetype = (dns_rdatatype_t)0xffffU;
zone->magic = ZONE_MAGIC;
@@ -669,6 +821,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
static void
zone_free(dns_zone_t *zone) {
isc_mem_t *mctx = NULL;
+ dns_signing_t *signing;
+ dns_nsec3chain_t *nsec3chain;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(isc_refcount_current(&zone->erefs) == 0);
@@ -687,10 +841,26 @@ zone_free(dns_zone_t *zone) {
if (zone->task != NULL)
isc_task_detach(&zone->task);
- if (zone->zmgr)
+ if (zone->zmgr != NULL)
dns_zonemgr_releasezone(zone->zmgr, zone);
/* Unmanaged objects */
+ for (signing = ISC_LIST_HEAD(zone->signing);
+ signing != NULL;
+ signing = ISC_LIST_HEAD(zone->signing)) {
+ ISC_LIST_UNLINK(zone->signing, signing, link);
+ dns_db_detach(&signing->db);
+ dns_dbiterator_destroy(&signing->dbiterator);
+ isc_mem_put(zone->mctx, signing, sizeof *signing);
+ }
+ for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ nsec3chain != NULL;
+ nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
+ dns_db_detach(&nsec3chain->db);
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ }
if (zone->masterfile != NULL)
isc_mem_free(zone->mctx, zone->masterfile);
zone->masterfile = NULL;
@@ -701,8 +871,10 @@ zone_free(dns_zone_t *zone) {
if (zone->journal != NULL)
isc_mem_free(zone->mctx, zone->journal);
zone->journal = NULL;
- if (zone->counters != NULL)
- dns_stats_freecounters(zone->mctx, &zone->counters);
+ if (zone->stats != NULL)
+ isc_stats_detach(&zone->stats);
+ if (zone->requeststats != NULL)
+ isc_stats_detach(&zone->requeststats);
if (zone->db != NULL)
zone_detachdb(zone);
if (zone->acache != NULL)
@@ -721,10 +893,20 @@ zone_free(dns_zone_t *zone) {
dns_acl_detach(&zone->notify_acl);
if (zone->query_acl != NULL)
dns_acl_detach(&zone->query_acl);
+ if (zone->queryon_acl != NULL)
+ dns_acl_detach(&zone->queryon_acl);
if (zone->xfr_acl != NULL)
dns_acl_detach(&zone->xfr_acl);
if (dns_name_dynamic(&zone->origin))
dns_name_free(&zone->origin, zone->mctx);
+ if (zone->strnamerd != NULL)
+ isc_mem_free(zone->mctx, zone->strnamerd);
+ if (zone->strname != NULL)
+ isc_mem_free(zone->mctx, zone->strname);
+ if (zone->strrdclass != NULL)
+ isc_mem_free(zone->mctx, zone->strrdclass);
+ if (zone->strviewname != NULL)
+ isc_mem_free(zone->mctx, zone->strviewname);
if (zone->ssutable != NULL)
dns_ssutable_detach(&zone->ssutable);
@@ -743,6 +925,7 @@ zone_free(dns_zone_t *zone) {
*/
void
dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
+ char namebuf[1024];
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(rdclass != dns_rdataclass_none);
@@ -754,11 +937,22 @@ dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
REQUIRE(zone->rdclass == dns_rdataclass_none ||
zone->rdclass == rdclass);
zone->rdclass = rdclass;
+
+ if (zone->strnamerd != NULL)
+ isc_mem_free(zone->mctx, zone->strnamerd);
+ if (zone->strrdclass != NULL)
+ isc_mem_free(zone->mctx, zone->strrdclass);
+
+ zone_namerd_tostr(zone, namebuf, sizeof namebuf);
+ zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
+ zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
+ zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
+
UNLOCK_ZONE(zone);
}
dns_rdataclass_t
-dns_zone_getclass(dns_zone_t *zone){
+dns_zone_getclass(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
return (zone->rdclass);
@@ -773,6 +967,19 @@ dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
UNLOCK_ZONE(zone);
}
+isc_uint32_t
+dns_zone_getserial(dns_zone_t *zone) {
+ isc_uint32_t serial;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ serial = zone->serial;
+ UNLOCK_ZONE(zone);
+
+ return (serial);
+}
+
/*
* Single shot.
*/
@@ -888,12 +1095,24 @@ dns_zone_setdbtype(dns_zone_t *zone,
void
dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
+ char namebuf[1024];
REQUIRE(DNS_ZONE_VALID(zone));
LOCK_ZONE(zone);
if (zone->view != NULL)
dns_view_weakdetach(&zone->view);
dns_view_weakattach(view, &zone->view);
+
+ if (zone->strviewname != NULL)
+ isc_mem_free(zone->mctx, zone->strviewname);
+ if (zone->strnamerd != NULL)
+ isc_mem_free(zone->mctx, zone->strnamerd);
+
+ zone_namerd_tostr(zone, namebuf, sizeof namebuf);
+ zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
+ zone_viewname_tostr(zone, namebuf, sizeof namebuf);
+ zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
+
UNLOCK_ZONE(zone);
}
@@ -909,6 +1128,7 @@ dns_zone_getview(dns_zone_t *zone) {
isc_result_t
dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
isc_result_t result;
+ char namebuf[1024];
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(origin != NULL);
@@ -919,6 +1139,17 @@ dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
dns_name_init(&zone->origin, NULL);
}
result = dns_name_dup(origin, zone->mctx, &zone->origin);
+
+ if (zone->strnamerd != NULL)
+ isc_mem_free(zone->mctx, zone->strnamerd);
+ if (zone->strname != NULL)
+ isc_mem_free(zone->mctx, zone->strname);
+
+ zone_namerd_tostr(zone, namebuf, sizeof namebuf);
+ zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
+ zone_name_tostr(zone, namebuf, sizeof namebuf);
+ zone->strname = isc_mem_strdup(zone->mctx, namebuf);
+
UNLOCK_ZONE(zone);
return (result);
}
@@ -1064,11 +1295,7 @@ zone_isdynamic(dns_zone_t *zone) {
zone->type == dns_zone_stub ||
(!zone->update_disabled && zone->ssutable != NULL) ||
(!zone->update_disabled && zone->update_acl != NULL &&
- ! (zone->update_acl->length == 1 &&
- zone->update_acl->elements[0].negative == ISC_TRUE
- &&
- zone->update_acl->elements[0].type ==
- dns_aclelementtype_any))));
+ !dns_acl_isnone(zone->update_acl))));
}
@@ -1243,6 +1470,33 @@ dns_zone_loadnew(dns_zone_t *zone) {
return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
}
+static unsigned int
+get_master_options(dns_zone_t *zone) {
+ unsigned int options;
+
+ options = DNS_MASTER_ZONE;
+ if (zone->type == dns_zone_slave)
+ options |= DNS_MASTER_SLAVE;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
+ options |= DNS_MASTER_CHECKNS;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
+ options |= DNS_MASTER_FATALNS;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
+ options |= DNS_MASTER_CHECKNAMES;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
+ options |= DNS_MASTER_CHECKNAMESFAIL;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
+ options |= DNS_MASTER_CHECKMX;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
+ options |= DNS_MASTER_CHECKMXFAIL;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
+ options |= DNS_MASTER_CHECKWILDCARD;
+ if (zone->type == dns_zone_master &&
+ (zone->update_acl != NULL || zone->ssutable != NULL))
+ options |= DNS_MASTER_RESIGN;
+ return (options);
+}
+
static void
zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
dns_load_t *load = event->ev_arg;
@@ -1257,28 +1511,14 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
if (result == ISC_R_CANCELED)
goto fail;
- options = DNS_MASTER_ZONE;
- if (load->zone->type == dns_zone_slave)
- options |= DNS_MASTER_SLAVE;
- if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNS))
- options |= DNS_MASTER_CHECKNS;
- if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_FATALNS))
- options |= DNS_MASTER_FATALNS;
- if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMES))
- options |= DNS_MASTER_CHECKNAMES;
- if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMESFAIL))
- options |= DNS_MASTER_CHECKNAMESFAIL;
- if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKMX))
- options |= DNS_MASTER_CHECKMX;
- if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKMXFAIL))
- options |= DNS_MASTER_CHECKMXFAIL;
- if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKWILDCARD))
- options |= DNS_MASTER_CHECKWILDCARD;
- result = dns_master_loadfileinc2(load->zone->masterfile,
+ options = get_master_options(load->zone);
+
+ result = dns_master_loadfileinc3(load->zone->masterfile,
dns_db_origin(load->db),
dns_db_origin(load->db),
load->zone->rdclass,
options,
+ load->zone->sigresigninginterval,
&load->callbacks, task,
zone_loaddone, load,
&load->zone->lctx, load->zone->mctx,
@@ -1334,25 +1574,10 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
isc_result_t tresult;
unsigned int options;
- options = DNS_MASTER_ZONE;
+ options = get_master_options(zone);
+
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
options |= DNS_MASTER_MANYERRORS;
- if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
- options |= DNS_MASTER_CHECKNS;
- if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
- options |= DNS_MASTER_FATALNS;
- if (zone->type == dns_zone_slave)
- options |= DNS_MASTER_SLAVE;
- if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
- options |= DNS_MASTER_CHECKNAMES;
- if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
- options |= DNS_MASTER_CHECKNAMESFAIL;
- if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
- options |= DNS_MASTER_CHECKMX;
- if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
- options |= DNS_MASTER_CHECKMXFAIL;
- if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
- options |= DNS_MASTER_CHECKWILDCARD;
if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
load = isc_mem_get(zone->mctx, sizeof(*load));
@@ -1394,9 +1619,10 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
&callbacks.add_private);
if (result != ISC_R_SUCCESS)
return (result);
- result = dns_master_loadfile2(zone->masterfile, &zone->origin,
+ result = dns_master_loadfile3(zone->masterfile, &zone->origin,
&zone->origin, zone->rdclass,
- options, &callbacks, zone->mctx,
+ options, zone->sigresigninginterval,
+ &callbacks, zone->mctx,
zone->masterformat);
tresult = dns_db_endload(db, &callbacks.add_private);
if (result == ISC_R_SUCCESS)
@@ -1727,7 +1953,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
dns_rdataset_init(&rdataset);
dns_rdata_init(&rdata);
- result = dns_db_createiterator(db, ISC_FALSE, &dbiterator);
+ result = dns_db_createiterator(db, 0, &dbiterator);
if (result != ISC_R_SUCCESS)
return (ISC_TRUE);
@@ -1890,6 +2116,292 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
}
+static void
+resume_signingwithkey(dns_zone_t *zone) {
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_db_currentversion(zone->db, &version);
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(zone->db, node, version,
+ zone->privatetype,
+ dns_rdatatype_none, 0,
+ &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdataset_current(&rdataset, &rdata);
+ if (rdata.length != 5 || rdata.data[4] != 0) {
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+
+ result = zone_signwithkey(zone, rdata.data[0],
+ (rdata.data[1] << 8) | rdata.data[2], ISC_TF(rdata.data[3]));
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_signwithkey failed: %s",
+ dns_result_totext(result));
+ }
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ cleanup:
+ if (node != NULL)
+ dns_db_detachnode(zone->db, &node);
+ if (version != NULL)
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+
+}
+
+static isc_result_t
+zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
+ dns_nsec3chain_t *nsec3chain, *current;
+ isc_result_t result;
+ isc_time_t now;
+ unsigned int options = 0;
+
+ nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
+ if (nsec3chain == NULL)
+ return (ISC_R_NOMEMORY);
+
+ nsec3chain->magic = 0;
+ nsec3chain->done = ISC_FALSE;
+ nsec3chain->db = NULL;
+ nsec3chain->dbiterator = NULL;
+ nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
+ nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
+ nsec3chain->nsec3param.hash = nsec3param->hash;
+ nsec3chain->nsec3param.iterations = nsec3param->iterations;
+ nsec3chain->nsec3param.flags = nsec3param->flags;
+ nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
+ memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
+ nsec3chain->nsec3param.salt = nsec3chain->salt;
+ nsec3chain->seen_nsec = ISC_FALSE;
+ nsec3chain->delete_nsec = ISC_FALSE;
+ nsec3chain->save_delete_nsec = ISC_FALSE;
+
+ for (current = ISC_LIST_HEAD(zone->nsec3chain);
+ current != NULL;
+ current = ISC_LIST_NEXT(current, link)) {
+ if (current->db == zone->db &&
+ current->nsec3param.hash == nsec3param->hash &&
+ current->nsec3param.iterations == nsec3param->iterations &&
+ current->nsec3param.salt_length == nsec3param->salt_length
+ && !memcmp(current->nsec3param.salt, nsec3param->salt,
+ nsec3param->salt_length))
+ current->done = ISC_TRUE;
+ }
+
+ if (zone->db != NULL) {
+ dns_db_attach(zone->db, &nsec3chain->db);
+ if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
+ options = DNS_DB_NONSEC3;
+ result = dns_db_createiterator(nsec3chain->db, options,
+ &nsec3chain->dbiterator);
+ if (result == ISC_R_SUCCESS)
+ dns_dbiterator_first(nsec3chain->dbiterator);
+ if (result == ISC_R_SUCCESS) {
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ ISC_LIST_INITANDAPPEND(zone->nsec3chain,
+ nsec3chain, link);
+ nsec3chain = NULL;
+ if (isc_time_isepoch(&zone->nsec3chaintime)) {
+ TIME_NOW(&now);
+ zone->nsec3chaintime = now;
+ if (zone->task != NULL)
+ zone_settimer(zone, &now);
+ }
+ }
+ } else
+ result = ISC_R_NOTFOUND;
+
+ if (nsec3chain != NULL) {
+ if (nsec3chain->db != NULL)
+ dns_db_detach(&nsec3chain->db);
+ if (nsec3chain->dbiterator != NULL)
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ }
+ return (result);
+}
+
+static void
+resume_addnsec3chain(dns_zone_t *zone) {
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ dns_rdata_nsec3param_t nsec3param;
+
+ result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_db_currentversion(zone->db, &version);
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(zone->db, node, version,
+ dns_rdatatype_nsec3param,
+ dns_rdatatype_none, 0,
+ &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
+ (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
+ result = zone_addnsec3chain(zone, &nsec3param);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_addnsec3chain failed: %s",
+ dns_result_totext(result));
+ }
+ }
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ cleanup:
+ if (node != NULL)
+ dns_db_detachnode(zone->db, &node);
+ if (version != NULL)
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+}
+
+static void
+set_resigntime(dns_zone_t *zone) {
+ dns_rdataset_t rdataset;
+ dns_fixedname_t fixed;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ unsigned int resign;
+ isc_result_t result;
+ isc_uint32_t nanosecs;
+
+ dns_rdataset_init(&rdataset);
+ dns_fixedname_init(&fixed);
+ result = dns_db_getsigningtime(zone->db, &rdataset,
+ dns_fixedname_name(&fixed));
+ if (result != ISC_R_SUCCESS) {
+ isc_time_settoepoch(&zone->resigntime);
+ return;
+ }
+ resign = rdataset.resign;
+ dns_name_format(dns_fixedname_name(&fixed), namebuf, sizeof(namebuf));
+ dns_rdataset_disassociate(&rdataset);
+ isc_random_get(&nanosecs);
+ nanosecs %= 1000000000;
+ isc_time_set(&zone->resigntime, resign, nanosecs);
+}
+
+static isc_result_t
+check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_dbversion_t *version = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ isc_boolean_t ok = ISC_FALSE;
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
+ zone_isdynamic(zone) : ISC_FALSE;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "nsec3param lookup failure: %s",
+ dns_result_totext(result));
+ return (result);
+ }
+ dns_db_currentversion(db, &version);
+
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3param,
+ dns_rdatatype_none, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "nsec3param lookup failure: %s",
+ dns_result_totext(result));
+ goto cleanup;
+ }
+
+ /*
+ * For dynamic zones we must support every algorithm so we can
+ * regenerate all the NSEC3 chains.
+ * For non-dynamic zones we only need to find a supported algorithm.
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ dns_rdata_reset(&rdata);
+ INSIST(result == ISC_R_SUCCESS);
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
+ nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
+ {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "nsec3 test \"unknown\" hash algorithm found: %u",
+ nsec3param.hash);
+ ok = ISC_TRUE;
+ } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
+ if (dynamic) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "unsupported nsec3 hash algorithm"
+ " in dynamic zone: %u",
+ nsec3param.hash);
+ result = DNS_R_BADZONE;
+ /* Stop second error message. */
+ ok = ISC_TRUE;
+ break;
+ } else
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "unsupported nsec3 hash algorithm: %u",
+ nsec3param.hash);
+ } else
+ ok = ISC_TRUE;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ if (!ok) {
+ result = DNS_R_BADZONE;
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "no supported nsec3 hash algorithm");
+ }
+
+ cleanup:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
static isc_result_t
zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
isc_result_t result)
@@ -1901,6 +2413,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
isc_time_t now;
isc_boolean_t needdump = ISC_FALSE;
isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
+ unsigned int options;
TIME_NOW(&now);
@@ -1945,7 +2458,12 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
{
- result = dns_journal_rollforward(zone->mctx, db,
+ if (zone->type == dns_zone_master &&
+ (zone->update_acl != NULL || zone->ssutable != NULL))
+ options = DNS_JOURNALOPT_RESIGN;
+ else
+ options = 0;
+ result = dns_journal_rollforward(zone->mctx, db, options,
zone->journal);
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
@@ -1972,7 +2490,6 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
zone->loadtime = loadtime;
dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
-
/*
* Obtain ns, soa and cname counts for top of zone.
*/
@@ -2010,6 +2527,11 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
result = DNS_R_BADZONE;
goto cleanup;
}
+ if (zone->type != dns_zone_stub) {
+ result = check_nsec3param(zone, db);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
if (zone->type == dns_zone_master &&
DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
!integrity_checks(zone, db)) {
@@ -2047,6 +2569,17 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
"zone may fail to transfer "
"to slaves.");
}
+
+ if (zone->type == dns_zone_master &&
+ (zone->update_acl != NULL || zone->ssutable != NULL) &&
+ zone->sigresigninginterval < (3 * refresh) &&
+ dns_db_issecure(db))
+ {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "sig-re-signing-interval less than "
+ "3 * refresh.");
+ }
+
zone->serial = serial;
zone->refresh = RANGE(refresh,
zone->minrefresh, zone->maxrefresh);
@@ -2121,8 +2654,14 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
result = ISC_R_SUCCESS;
if (needdump)
zone_needdump(zone, DNS_DUMP_DELAY);
- if (zone->task != NULL)
+ if (zone->task != NULL) {
+ if (zone->type == dns_zone_master) {
+ set_resigntime(zone);
+ resume_signingwithkey(zone);
+ resume_addnsec3chain(zone);
+ }
zone_settimer(zone, &now);
+ }
if (! dns_db_ispersistent(db))
dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s",
@@ -2809,7 +3348,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
goto unlock;
/*
- * masters must countain count elements!
+ * masters must contain count elements!
*/
new = isc_mem_get(zone->mctx, count * sizeof(*new));
if (new == NULL) {
@@ -2935,6 +3474,2432 @@ was_dumping(dns_zone_t *zone) {
return (dumping);
}
+#define MAXZONEKEYS 10
+
+static isc_result_t
+do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff)
+{
+ dns_diff_t temp_diff;
+ isc_result_t result;
+
+ /*
+ * Create a singleton diff.
+ */
+ dns_diff_init(diff->mctx, &temp_diff);
+ temp_diff.resign = diff->resign;
+ ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
+
+ /*
+ * Apply it to the database.
+ */
+ result = dns_diff_apply(&temp_diff, db, ver);
+ ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
+ if (result != ISC_R_SUCCESS) {
+ dns_difftuple_free(tuple);
+ return (result);
+ }
+
+ /*
+ * Merge it into the current pending journal entry.
+ */
+ dns_diff_appendminimal(diff, tuple);
+
+ /*
+ * Do not clear temp_diff.
+ */
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff, isc_mem_t *mctx)
+{
+ dns_difftuple_t *deltuple = NULL;
+ dns_difftuple_t *addtuple = NULL;
+ isc_uint32_t serial;
+ isc_result_t result;
+
+ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
+ CHECK(dns_difftuple_copy(deltuple, &addtuple));
+ addtuple->op = DNS_DIFFOP_ADD;
+
+ serial = dns_soa_getserial(&addtuple->rdata);
+
+ /* RFC1982 */
+ serial = (serial + 1) & 0xFFFFFFFF;
+ if (serial == 0)
+ serial = 1;
+
+ dns_soa_setserial(serial, &addtuple->rdata);
+ CHECK(do_one_tuple(&deltuple, db, ver, diff));
+ CHECK(do_one_tuple(&addtuple, db, ver, diff));
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (addtuple != NULL)
+ dns_difftuple_free(&addtuple);
+ if (deltuple != NULL)
+ dns_difftuple_free(&deltuple);
+ return (result);
+}
+
+static isc_result_t
+update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
+ dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
+ dns_rdata_t *rdata)
+{
+ dns_difftuple_t *tuple = NULL;
+ isc_result_t result;
+ result = dns_difftuple_create(diff->mctx, op,
+ name, ttl, rdata, &tuple);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (do_one_tuple(&tuple, db, ver, diff));
+}
+
+static isc_boolean_t
+ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) {
+ isc_boolean_t ret = ISC_FALSE;
+ isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE;
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_dnskey_t dnskey;
+
+ dns_rdataset_init(&rdataset);
+ CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
+ CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
+ &rdataset, NULL));
+ CHECK(dns_rdataset_first(&rdataset));
+ while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) {
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
+ if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
+ == DNS_KEYOWNER_ZONE) {
+ if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0)
+ have_ksk = ISC_TRUE;
+ else
+ have_nonksk = ISC_TRUE;
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rdataset);
+ }
+ if (have_ksk && have_nonksk)
+ ret = ISC_TRUE;
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (ret);
+}
+
+static isc_result_t
+find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
+ isc_mem_t *mctx, unsigned int maxkeys,
+ dst_key_t **keys, unsigned int *nkeys)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ const char *directory = dns_zone_getkeydirectory(zone);
+ CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
+ result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
+ directory, mctx, maxkeys, keys,
+ nkeys);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+static isc_result_t
+offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
+ dns_ttl_t ttl, dns_rdata_t *rdata)
+{
+ isc_result_t result;
+
+ if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
+ return (ISC_R_SUCCESS);
+ result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
+ name, ttl, rdata);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rdata->flags |= DNS_RDATA_OFFLINE;
+ result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
+ name, ttl, rdata);
+ return (result);
+}
+
+static void
+set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
+{
+ unsigned int delta;
+
+ zone->key_expiry = when;
+ if (when <= now) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "DNSKEY RRSIG(s) have expired");
+ isc_time_settoepoch(&zone->keywarntime);
+ } else if (when < now + 7 * 24 * 3600) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "DNSKEY RRSIG(s) will expire at %u",
+ when); /* XXXMPA convert to date. */
+ delta = when - now;
+ delta--; /* loop prevention */
+ delta /= 24 * 3600; /* to whole days */
+ delta *= 24 * 3600; /* to seconds */
+ isc_time_set(&zone->keywarntime, when - delta, 0);
+ } else {
+ dns_zone_log(zone, ISC_LOG_NOTICE, /* XXMPA ISC_LOG_DEBUG(1) */
+ "setting keywarntime to %u - 7 days",
+ when); /* XXXMPA convert to date. */
+ isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
+ }
+}
+
+/*
+ * Delete expired RRsigs and any RRsigs we are about to re-sign.
+ * See also update.c:del_keysigs().
+ */
+static isc_result_t
+del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
+ unsigned int nkeys, isc_stdtime_t now)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int i;
+ dns_rdata_rrsig_t rrsig;
+ isc_boolean_t found;
+ isc_stdtime_t warn = 0, maybe = 0;
+
+ dns_rdataset_init(&rdataset);
+
+ if (type == dns_rdatatype_nsec3)
+ result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
+ else
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (type != dns_rdatatype_dnskey) {
+ result = update_one_rr(db, ver, diff,
+ DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS)
+ break;
+ continue;
+ }
+
+ /*
+ * RRSIG(DNSKEY) requires special processing.
+ */
+ found = ISC_FALSE;
+ for (i = 0; i < nkeys; i++) {
+ if (rrsig.algorithm == dst_key_alg(keys[i]) &&
+ rrsig.keyid == dst_key_id(keys[i])) {
+ found = ISC_TRUE;
+ /*
+ * Mark offline RRSIG(DNSKEY).
+ * We want the earliest offline expire time
+ * iff there is a new offline signature.
+ */
+ if (!dst_key_isprivate(keys[i])) {
+ if (warn != 0 &&
+ warn > rrsig.timeexpire)
+ warn = rrsig.timeexpire;
+ if (rdata.flags & DNS_RDATA_OFFLINE) {
+ if (maybe == 0 ||
+ maybe > rrsig.timeexpire)
+ maybe =
+ rrsig.timeexpire;
+ break;
+ }
+ if (warn == 0)
+ warn = maybe;
+ if (warn == 0 ||
+ warn > rrsig.timeexpire)
+ warn = rrsig.timeexpire;
+ result = offline(db, ver, diff, name,
+ rdataset.ttl, &rdata);
+ break;
+ }
+ result = update_one_rr(db, ver, diff,
+ DNS_DIFFOP_DEL,
+ name, rdataset.ttl,
+ &rdata);
+ break;
+ }
+ }
+ /*
+ * If there is not a matching DNSKEY then
+ * delete the RRSIG.
+ */
+ if (!found)
+ result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
+ name, rdataset.ttl, &rdata);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (warn != 0)
+ set_key_expiry_warning(zone, warn, now);
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+static isc_result_t
+add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
+ unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
+ isc_stdtime_t expire, isc_boolean_t check_ksk)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t sig_rdata = DNS_RDATA_INIT;
+ unsigned char data[1024]; /* XXX */
+ isc_buffer_t buffer;
+ unsigned int i;
+
+ dns_rdataset_init(&rdataset);
+ isc_buffer_init(&buffer, data, sizeof(data));
+
+ if (type == dns_rdatatype_nsec3)
+ result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
+ else
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ result = dns_db_findrdataset(db, node, ver, type, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ for (i = 0; i < nkeys; i++) {
+ if (check_ksk && type != dns_rdatatype_dnskey &&
+ (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
+ continue;
+ if (!dst_key_isprivate(keys[i]))
+ continue;
+ /* Calculate the signature, creating a RRSIG RDATA. */
+ CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
+ &inception, &expire,
+ mctx, &buffer, &sig_rdata));
+ /* Update the database and journal with the RRSIG. */
+ /* XXX inefficient - will cause dataset merging */
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
+ name, rdataset.ttl, &sig_rdata));
+ dns_rdata_reset(&sig_rdata);
+ }
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+static void
+zone_resigninc(dns_zone_t *zone) {
+ const char *journalfile;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_diff_t sig_diff;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t covers;
+ dst_key_t *zone_keys[MAXZONEKEYS];
+ isc_boolean_t check_ksk;
+ isc_result_t result;
+ isc_stdtime_t now, inception, soaexpire, expire, stop;
+ isc_uint32_t jitter;
+ unsigned int i;
+ unsigned int nkeys = 0;
+ unsigned int resign;
+
+ dns_rdataset_init(&rdataset);
+ dns_fixedname_init(&fixed);
+ dns_diff_init(zone->mctx, &sig_diff);
+ sig_diff.resign = zone->sigresigninginterval;
+
+ /*
+ * Updates are disabled. Pause for 5 minutes.
+ */
+ if (zone->update_disabled) {
+ result = ISC_R_FAILURE;
+ goto failure;
+ }
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ result = dns_db_newversion(db, &version);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = find_zone_keys(zone, db, version, zone->mctx, MAXZONEKEYS,
+ zone_keys, &nkeys);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:find_zone_keys -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ isc_stdtime_get(&now);
+ inception = now - 3600; /* Allow for clock skew. */
+ soaexpire = now + dns_zone_getsigvalidityinterval(zone);
+ /*
+ * Spread out signatures over time if they happen to be
+ * clumped. We don't do this for each add_sigs() call as
+ * we still want some clustering to occur.
+ */
+ isc_random_get(&jitter);
+ expire = soaexpire - jitter % 3600;
+ stop = now + 5;
+
+ check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
+ if (check_ksk)
+ check_ksk = ksk_sanity(db, version);
+
+ name = dns_fixedname_name(&fixed);
+ result = dns_db_getsigningtime(db, &rdataset, name);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:dns_db_getsigningtime -> %s\n",
+ dns_result_totext(result));
+ }
+
+ i = 0;
+ while (result == ISC_R_SUCCESS) {
+ resign = rdataset.resign;
+ covers = rdataset.covers;
+ /*
+ * Stop if we hit the SOA as that means we have walked the
+ * entire zone. The SOA record should always be the most
+ * recent signature.
+ */
+ /* XXXMPA increase number of RRsets signed pre call */
+ if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
+ resign > stop) {
+ /*
+ * Ensure that we don't loop resigning the SOA.
+ */
+ if (covers == dns_rdatatype_soa)
+ dns_db_resigned(db, &rdataset, version);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ }
+
+ dns_db_resigned(db, &rdataset, version);
+ dns_rdataset_disassociate(&rdataset);
+
+ result = del_sigs(zone, db, version, name, covers, &sig_diff,
+ zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:del_sigs -> %s\n",
+ dns_result_totext(result));
+ break;
+ }
+ result = add_sigs(db, version, name, covers, &sig_diff,
+ zone_keys, nkeys, zone->mctx, inception,
+ expire, check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:add_sigs -> %s\n",
+ dns_result_totext(result));
+ break;
+ }
+ result = dns_db_getsigningtime(db, &rdataset,
+ dns_fixedname_name(&fixed));
+ if (nkeys == 0 && result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ break;
+ }
+ if (result != ISC_R_SUCCESS)
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:dns_db_getsigningtime -> %s\n",
+ dns_result_totext(result));
+ }
+
+ if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
+ &sig_diff, zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:del_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:increment_soa_serial -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ /*
+ * Generate maximum life time signatures so that the above loop
+ * termination is sensible.
+ */
+ result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
+ &sig_diff, zone_keys, nkeys, zone->mctx, inception,
+ soaexpire, check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:add_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ journalfile = dns_zone_getjournal(zone);
+ if (journalfile != NULL) {
+ dns_journal_t *journal = NULL;
+ result = dns_journal_open(zone->mctx, journalfile,
+ ISC_TRUE, &journal);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:dns_journal_open -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = dns_journal_write_transaction(journal, &sig_diff);
+ dns_journal_destroy(&journal);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:dns_journal_write_transaction -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+
+ /*
+ * Everything has succeeded. Commit the changes.
+ */
+ dns_db_closeversion(db, &version, ISC_TRUE);
+
+ failure:
+ dns_diff_clear(&sig_diff);
+ for (i = 0; i < nkeys; i++)
+ dst_key_free(&zone_keys[i]);
+ if (version != NULL) {
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+ } else if (db != NULL)
+ dns_db_detach(&db);
+ if (result == ISC_R_SUCCESS) {
+ set_resigntime(zone);
+ LOCK_ZONE(zone);
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
+ UNLOCK_ZONE(zone);
+ } else {
+ /*
+ * Something failed. Retry in 5 minutes.
+ */
+ isc_interval_t ival;
+ isc_interval_set(&ival, 300, 0);
+ isc_time_nowplusinterval(&zone->resigntime, &ival);
+ }
+}
+
+static isc_result_t
+next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
+ dns_name_t *newname, isc_boolean_t bottom)
+{
+ isc_result_t result;
+ dns_dbiterator_t *dbit = NULL;
+ dns_rdatasetiter_t *rdsit = NULL;
+ dns_dbnode_t *node = NULL;
+
+ CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
+ CHECK(dns_dbiterator_seek(dbit, oldname));
+ do {
+ result = dns_dbiterator_next(dbit);
+ if (result == ISC_R_NOMORE)
+ CHECK(dns_dbiterator_first(dbit));
+ CHECK(dns_dbiterator_current(dbit, &node, newname));
+ if (bottom && dns_name_issubdomain(newname, oldname) &&
+ !dns_name_equal(newname, oldname)) {
+ dns_db_detachnode(db, &node);
+ continue;
+ }
+ /*
+ * Is this node empty?
+ */
+ CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
+ result = dns_rdatasetiter_first(rdsit);
+ dns_db_detachnode(db, &node);
+ dns_rdatasetiter_destroy(&rdsit);
+ if (result != ISC_R_NOMORE)
+ break;
+ } while (1);
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (dbit != NULL)
+ dns_dbiterator_destroy(&dbit);
+ return (result);
+}
+
+static void
+set_bit(unsigned char *array, unsigned int index) {
+ unsigned int shift, mask;
+
+ shift = 7 - (index % 8);
+ mask = 1 << shift;
+
+ array[index / 8] |= mask;
+}
+
+static isc_boolean_t
+signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dst_key_t *key)
+{
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t rrsig;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
+ type, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ if (rrsig.algorithm == dst_key_alg(key) &&
+ rrsig.keyid == dst_key_id(key)) {
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_TRUE);
+ }
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
+ dns_diff_t *diff)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *next;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
+
+ dns_fixedname_init(&fixed);
+ next = dns_fixedname_name(&fixed);
+
+ CHECK(next_active(db, version, name, next, bottom));
+ CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
+ &rdata));
+ if (dns_name_equal(dns_db_origin(db), name)) {
+ /*
+ * Set the OPT bit to indicate that this is a
+ * partially secure zone.
+ */
+ isc_region_t region;
+
+ dns_rdata_toregion(&rdata, &region);
+ dns_name_fromregion(next, &region);
+ isc_region_consume(&region, next->length);
+ INSIST(region.length > (2 + dns_rdatatype_opt / 8) &&
+ region.base[0] == 0 &&
+ region.base[1] > dns_rdatatype_opt / 8);
+ set_bit(region.base + 2, dns_rdatatype_opt);
+ }
+ CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
+ &rdata));
+ failure:
+ return (result);
+}
+
+static isc_result_t
+sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
+ dns_dbversion_t *version, isc_boolean_t build_nsec3,
+ isc_boolean_t build_nsec, dst_key_t *key,
+ isc_stdtime_t inception, isc_stdtime_t expire,
+ unsigned int minimum, isc_boolean_t is_ksk,
+ isc_boolean_t *delegation, dns_diff_t *diff,
+ isc_int32_t *signatures, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdatasetiter_t *iterator = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t buffer;
+ unsigned char data[1024];
+ isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
+ seen_nsec3, seen_ds;
+ isc_boolean_t bottom;
+
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+ return (result);
+ }
+ dns_rdataset_init(&rdataset);
+ isc_buffer_init(&buffer, data, sizeof(data));
+ seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
+ seen_nsec3 = seen_ds = ISC_FALSE;
+ for (result = dns_rdatasetiter_first(iterator);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iterator)) {
+ dns_rdatasetiter_current(iterator, &rdataset);
+ if (rdataset.type == dns_rdatatype_soa)
+ seen_soa = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ns)
+ seen_ns = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ds)
+ seen_ds = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_dname)
+ seen_dname = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec)
+ seen_nsec = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec3)
+ seen_nsec3 = ISC_TRUE;
+ seen_rr = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ if (seen_ns && !seen_soa)
+ *delegation = ISC_TRUE;
+ /*
+ * Going from insecure to NSEC3.
+ * Don't generate NSEC3 records for NSEC3 records.
+ */
+ if (build_nsec3 && !seen_nsec3 && seen_rr) {
+ isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
+ CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
+ unsecure, diff));
+ (*signatures)--;
+ }
+ /*
+ * Going from insecure to NSEC.
+ * Don't generate NSEC records for NSEC3 records.
+ */
+ if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
+ /* Build and add NSEC. */
+ bottom = (seen_ns && !seen_soa) || seen_dname;
+ CHECK(add_nsec(db, version, name, node, minimum, bottom, diff));
+ /* Count a NSEC generation as a signature generation. */
+ (*signatures)--;
+ }
+ result = dns_rdatasetiter_first(iterator);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(iterator, &rdataset);
+ if (rdataset.type == dns_rdatatype_soa ||
+ rdataset.type == dns_rdatatype_rrsig)
+ goto next_rdataset;
+ if (is_ksk && rdataset.type != dns_rdatatype_dnskey)
+ goto next_rdataset;
+ if (*delegation &&
+ rdataset.type != dns_rdatatype_ds &&
+ rdataset.type != dns_rdatatype_nsec)
+ goto next_rdataset;
+ if (signed_with_key(db, node, version, rdataset.type, key))
+ goto next_rdataset;
+ /* Calculate the signature, creating a RRSIG RDATA. */
+ CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
+ &expire, mctx, &buffer, &rdata));
+ /* Update the database and journal with the RRSIG. */
+ /* XXX inefficient - will cause dataset merging */
+ CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
+ name, rdataset.ttl, &rdata));
+ dns_rdata_reset(&rdata);
+ (*signatures)--;
+ next_rdataset:
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(iterator);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (seen_dname)
+ *delegation = ISC_TRUE;
+failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (iterator != NULL)
+ dns_rdatasetiter_destroy(&iterator);
+ return (result);
+}
+
+static isc_result_t
+updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_ttl_t minimum, isc_boolean_t *secureupdated, dns_diff_t *diff)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
+ dns_rdataset_t rdataset;
+ dns_rdata_nsec_t nsec;
+ dns_dbnode_t *node = NULL;
+
+ /*
+ * Check to see if the OPT bit has already been cleared.
+ */
+ CHECK(dns_db_getoriginnode(db, &node));
+ dns_rdataset_init(&rdataset);
+ CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec,
+ dns_rdatatype_none, 0, &rdataset, NULL));
+ CHECK(dns_rdataset_first(&rdataset));
+ dns_rdataset_current(&rdataset, &rdata);
+
+ /*
+ * Find the NEXT name for building the new record.
+ */
+ CHECK(dns_rdata_tostruct(&rdata, &nsec, NULL));
+
+ /*
+ * Delete the old NSEC record.
+ */
+ CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_DEL, name, minimum,
+ &rdata));
+ dns_rdata_reset(&rdata);
+
+ /*
+ * Add the new NSEC record.
+ */
+ CHECK(dns_nsec_buildrdata(db, version, node, &nsec.next, nsecbuffer,
+ &rdata));
+ CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, minimum,
+ &rdata));
+ dns_rdata_reset(&rdata);
+
+ if (secureupdated != NULL)
+ *secureupdated = ISC_TRUE;
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+static isc_result_t
+updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version,
+ dns_name_t *name, dns_rdatatype_t privatetype,
+ dns_diff_t *diff)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned char data[5];
+ isc_boolean_t seen_done = ISC_FALSE;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_getoriginnode(signing->db, &node);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = dns_db_findrdataset(signing->db, node, version, privatetype,
+ dns_rdatatype_none, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto failure;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdataset_current(&rdataset, &rdata);
+ if (rdata.length != 5 ||
+ rdata.data[0] != signing->algorithm ||
+ rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
+ rdata.data[2] != (signing->keyid & 0xff)) {
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+ if (!signing->delete && rdata.data[4] != 0)
+ seen_done = ISC_TRUE;
+ else
+ CHECK(update_one_rr(signing->db, version, diff,
+ DNS_DIFFOP_DEL, name, rdataset.ttl, &rdata));
+ dns_rdata_reset(&rdata);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (!signing->delete && !seen_done) {
+
+ data[0] = signing->algorithm;
+ data[1] = (signing->keyid >> 8) & 0xff;
+ data[2] = signing->keyid & 0xff;
+ data[3] = 0;
+ data[4] = 1;
+ rdata.length = sizeof(data);
+ rdata.data = data;
+ rdata.type = privatetype;
+ rdata.rdclass = dns_db_class(signing->db);
+ CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
+ name, rdataset.ttl, &rdata));
+ }
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(signing->db, &node);
+ return (result);
+}
+
+static isc_result_t
+fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
+ isc_boolean_t active, dns_diff_t *diff)
+{
+ dns_dbnode_t *node = NULL;
+ dns_name_t *name = dns_db_origin(db);
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ dns_rdata_nsec3param_t nsec3param;
+ isc_result_t result;
+ isc_buffer_t buffer;
+ unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_ttl_t ttl = 0;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto add;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Preserve the existing ttl.
+ */
+ ttl = rdataset.ttl;
+
+ /*
+ * Delete all NSEC3PARAM records which match that in nsec3chain.
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
+
+ if (nsec3param.hash != chain->nsec3param.hash ||
+ (active && nsec3param.flags != 0) ||
+ nsec3param.iterations != chain->nsec3param.iterations ||
+ nsec3param.salt_length != chain->nsec3param.salt_length ||
+ memcmp(nsec3param.salt, chain->nsec3param.salt,
+ nsec3param.salt_length)) {
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
+ name, rdataset.ttl, &rdata));
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ add:
+ if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
+ result = ISC_R_SUCCESS;
+ goto failure;
+ }
+
+ /*
+ * Add a NSEC3PARAM record which matches that in nsec3chain but
+ * with all flags bits cleared.
+ *
+ * Note: we do not clear chain->nsec3param.flags as this change
+ * may be reversed.
+ */
+ isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
+ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
+ dns_rdatatype_nsec3param,
+ &chain->nsec3param, &buffer));
+ rdata.data[1] = 0; /* Clear flag bits. */
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
+
+ failure:
+ dns_db_detachnode(db, &node);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+static isc_result_t
+delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
+ dns_name_t *name, dns_diff_t *diff)
+{
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata));
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ failure:
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+static isc_result_t
+deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
+ dns_name_t *name, const dns_rdata_nsec3param_t *param,
+ dns_diff_t *diff)
+{
+ dns_rdataset_t rdataset;
+ dns_rdata_nsec3_t nsec3;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
+ if (nsec3.hash != param->hash ||
+ nsec3.iterations != param->iterations ||
+ nsec3.salt_length != param->salt_length ||
+ memcmp(nsec3.salt, param->salt, nsec3.salt_length))
+ continue;
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata));
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ failure:
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+static isc_result_t
+need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
+ const dns_rdata_nsec3param_t *param,
+ isc_boolean_t *answer, isc_boolean_t *updatensec)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3param_t myparam;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ *answer = ISC_FALSE;
+
+ result = dns_db_getoriginnode(db, &node);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto check_nsec3param;
+
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ CHECK(dns_rdataset_first(&rdataset));
+ dns_rdataset_current(&rdataset, &rdata);
+
+ if (!dns_nsec_typepresent(&rdata, dns_rdatatype_opt)) {
+ /*
+ * We have a complete NSEC chain. Signal to update
+ * the apex NSEC record.
+ */
+ *updatensec = ISC_TRUE;
+ goto failure;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ dns_rdata_reset(&rdata);
+
+ check_nsec3param:
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ *answer = ISC_TRUE;
+ dns_db_detachnode(db, &node);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &node);
+ return (result);
+ }
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
+ dns_rdata_reset(&rdata);
+ /*
+ * Ignore any NSEC3PARAM removals.
+ */
+ if (NSEC3REMOVE(myparam.flags))
+ continue;
+ /*
+ * Ignore the chain that we are in the process of deleting.
+ */
+ if (myparam.hash == param->hash &&
+ myparam.iterations == param->iterations &&
+ myparam.salt_length == param->salt_length &&
+ !memcmp(myparam.salt, param->salt, myparam.salt_length))
+ continue;
+ /*
+ * Found an active NSEC3 chain.
+ */
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ *answer = ISC_TRUE;
+ result = ISC_R_SUCCESS;
+ }
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+/*
+ * Incrementally build and sign a new NSEC3 chain using the parameters
+ * requested.
+ */
+static void
+zone_nsec3chain(dns_zone_t *zone) {
+ const char *journalfile;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_diff_t sig_diff;
+ dns_diff_t nsec_diff;
+ dns_diff_t nsec3_diff;
+ dns_diff_t param_diff;
+ dns_fixedname_t fixed;
+ dns_fixedname_t nextfixed;
+ dns_name_t *name, *nextname;
+ dns_rdataset_t rdataset;
+ dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
+ dns_nsec3chainlist_t cleanup;
+ dst_key_t *zone_keys[MAXZONEKEYS];
+ isc_int32_t signatures;
+ isc_boolean_t check_ksk, is_ksk;
+ isc_boolean_t delegation;
+ isc_boolean_t first;
+ isc_result_t result;
+ isc_stdtime_t now, inception, soaexpire, expire, stop;
+ isc_uint32_t jitter;
+ unsigned int i;
+ unsigned int nkeys = 0;
+ isc_uint32_t nodes;
+ isc_boolean_t unsecure = ISC_FALSE;
+ isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
+ isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
+ dns_rdatasetiter_t *iterator = NULL;
+ dns_difftuple_t *tuple;
+ isc_boolean_t buildnsecchain;
+ isc_boolean_t updatensec = ISC_FALSE;
+
+ dns_rdataset_init(&rdataset);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&nextfixed);
+ nextname = dns_fixedname_name(&nextfixed);
+ dns_diff_init(zone->mctx, &param_diff);
+ dns_diff_init(zone->mctx, &nsec3_diff);
+ dns_diff_init(zone->mctx, &nsec_diff);
+ dns_diff_init(zone->mctx, &sig_diff);
+ sig_diff.resign = zone->sigresigninginterval;
+ ISC_LIST_INIT(cleanup);
+
+ /*
+ * Updates are disabled. Pause for 5 minutes.
+ */
+ if (zone->update_disabled) {
+ result = ISC_R_FAILURE;
+ goto failure;
+ }
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ result = dns_db_newversion(db, &version);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = find_zone_keys(zone, db, version, zone->mctx,
+ MAXZONEKEYS, zone_keys, &nkeys);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:find_zone_keys -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ isc_stdtime_get(&now);
+ inception = now - 3600; /* Allow for clock skew. */
+ soaexpire = now + dns_zone_getsigvalidityinterval(zone);
+
+ /*
+ * Spread out signatures over time if they happen to be
+ * clumped. We don't do this for each add_sigs() call as
+ * we still want some clustering to occur.
+ */
+ isc_random_get(&jitter);
+ expire = soaexpire - jitter % 3600;
+ stop = now + 5;
+
+ check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
+ if (check_ksk)
+ check_ksk = ksk_sanity(db, version);
+
+ /*
+ * We keep pulling nodes off each iterator in turn until
+ * we have no more nodes to pull off or we reach the limits
+ * for this quantum.
+ */
+ nodes = zone->nodes;
+ signatures = zone->signatures;
+ LOCK_ZONE(zone);
+ nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ UNLOCK_ZONE(zone);
+ first = ISC_TRUE;
+
+ if (nsec3chain != NULL)
+ nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
+ /*
+ * Generate new NSEC3 chains first.
+ */
+ while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
+ LOCK_ZONE(zone);
+ nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (nsec3chain->done || nsec3chain->db != zone->db) {
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
+ ISC_LIST_APPEND(cleanup, nsec3chain, link);
+ }
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ UNLOCK_ZONE(zone);
+ if (ISC_LIST_TAIL(cleanup) == nsec3chain)
+ goto next_addchain;
+
+ /*
+ * Possible future db.
+ */
+ if (nsec3chain->db != db) {
+ goto next_addchain;
+ }
+
+ if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
+ goto next_addchain;
+
+ is_ksk = ISC_FALSE;
+ delegation = ISC_FALSE;
+ dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
+
+ if (nsec3chain->delete_nsec) {
+ delegation = ISC_FALSE;
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ CHECK(delete_nsec(db, version, node, name, &nsec_diff));
+ goto next_addnode;
+ }
+ /*
+ * On the first pass we need to check if the current node
+ * has not been obscured.
+ */
+ delegation = ISC_FALSE;
+ unsecure = ISC_FALSE;
+ if (first) {
+ dns_fixedname_t ffound;
+ dns_name_t *found;
+ dns_fixedname_init(&ffound);
+ found = dns_fixedname_name(&ffound);
+ result = dns_db_find(db, name, version,
+ dns_rdatatype_soa,
+ DNS_DBFIND_NOWILD, 0, NULL, found,
+ NULL, NULL);
+ if ((result == DNS_R_DELEGATION ||
+ result == DNS_R_DNAME) &&
+ !dns_name_equal(name, found)) {
+ /*
+ * Remember the obscuring name so that
+ * we skip all obscured names.
+ */
+ dns_name_copy(found, name, NULL);
+ delegation = ISC_TRUE;
+ goto next_addnode;
+ }
+ }
+
+ /*
+ * Check to see if this is a bottom of zone node.
+ */
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result == ISC_R_NOTFOUND) /* Empty node? */
+ goto next_addnode;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
+ ISC_FALSE;
+ for (result = dns_rdatasetiter_first(iterator);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iterator)) {
+ dns_rdatasetiter_current(iterator, &rdataset);
+ INSIST(rdataset.type != dns_rdatatype_nsec3);
+ if (rdataset.type == dns_rdatatype_soa)
+ seen_soa = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ns)
+ seen_ns = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_dname)
+ seen_dname = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ds)
+ seen_ds = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec)
+ seen_nsec = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ dns_rdatasetiter_destroy(&iterator);
+ /*
+ * Is there a NSEC chain than needs to be cleaned up?
+ */
+ if (seen_nsec)
+ nsec3chain->seen_nsec = ISC_TRUE;
+ if (seen_ns && !seen_soa && !seen_ds)
+ unsecure = ISC_TRUE;
+ if ((seen_ns && !seen_soa) || seen_dname)
+ delegation = ISC_TRUE;
+
+ /*
+ * Process one node.
+ */
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ CHECK(dns_nsec3_addnsec3(db, version, name,
+ &nsec3chain->nsec3param,
+ zone->minimum, unsecure, &nsec3_diff));
+ /*
+ * Treat each call to dns_nsec3_addnsec3() as if it's cost is
+ * two signatures. Additionally there will, in general, be
+ * two signature generated below.
+ *
+ * If we are only changing the optout flag the cost is half
+ * that of the cost of generating a completely new chain.
+ */
+ signatures -= 4;
+
+ /*
+ * Go onto next node.
+ */
+ next_addnode:
+ first = ISC_FALSE;
+ dns_db_detachnode(db, &node);
+ do {
+ result = dns_dbiterator_next(nsec3chain->dbiterator);
+
+ if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
+ CHECK(fixup_nsec3param(db, version, nsec3chain,
+ ISC_FALSE, &param_diff));
+ LOCK_ZONE(zone);
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
+ link);
+ UNLOCK_ZONE(zone);
+ ISC_LIST_APPEND(cleanup, nsec3chain, link);
+ goto next_addchain;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ if (nsec3chain->seen_nsec) {
+ CHECK(fixup_nsec3param(db, version,
+ nsec3chain,
+ ISC_TRUE,
+ &param_diff));
+ nsec3chain->delete_nsec = ISC_TRUE;
+ goto same_addchain;
+ }
+ CHECK(fixup_nsec3param(db, version, nsec3chain,
+ ISC_FALSE, &param_diff));
+ LOCK_ZONE(zone);
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
+ link);
+ UNLOCK_ZONE(zone);
+ ISC_LIST_APPEND(cleanup, nsec3chain, link);
+ goto next_addchain;
+ } else if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "dns_dbiterator_next -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ } else if (delegation) {
+ dns_dbiterator_current(nsec3chain->dbiterator,
+ &node, nextname);
+ dns_db_detachnode(db, &node);
+ if (!dns_name_issubdomain(nextname, name))
+ break;
+ } else
+ break;
+ } while (1);
+ continue;
+
+ same_addchain:
+ CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
+ first = ISC_TRUE;
+ continue;
+
+ next_addchain:
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ nsec3chain = nextnsec3chain;
+ first = ISC_TRUE;
+ if (nsec3chain != NULL)
+ nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
+ }
+
+ /*
+ * Process removals.
+ */
+ LOCK_ZONE(zone);
+ nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ UNLOCK_ZONE(zone);
+ first = ISC_TRUE;
+ buildnsecchain = ISC_FALSE;
+ while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
+ LOCK_ZONE(zone);
+ nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
+ UNLOCK_ZONE(zone);
+
+ if (nsec3chain->db != db)
+ goto next_removechain;
+
+ if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
+ goto next_removechain;
+
+ /*
+ * Work out if we need to build a NSEC chain as a consequence
+ * of removing this NSEC3 chain.
+ */
+ if (first && !updatensec &&
+ (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
+ CHECK(need_nsec_chain(db, version,
+ &nsec3chain->nsec3param,
+ &buildnsecchain, &updatensec));
+
+ dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
+ delegation = ISC_FALSE;
+
+ if (!buildnsecchain) {
+ /*
+ * Delete the NSECPARAM record that matches this chain.
+ */
+ if (first)
+ CHECK(fixup_nsec3param(db, version, nsec3chain,
+ ISC_TRUE, &param_diff));
+
+ /*
+ * Delete the NSEC3 records.
+ */
+ CHECK(deletematchingnsec3(db, version, node, name,
+ &nsec3chain->nsec3param,
+ &nsec3_diff));
+ goto next_removenode;
+ }
+
+ if (first) {
+ dns_fixedname_t ffound;
+ dns_name_t *found;
+ dns_fixedname_init(&ffound);
+ found = dns_fixedname_name(&ffound);
+ result = dns_db_find(db, name, version,
+ dns_rdatatype_soa,
+ DNS_DBFIND_NOWILD, 0, NULL, found,
+ NULL, NULL);
+ if ((result == DNS_R_DELEGATION ||
+ result == DNS_R_DNAME) &&
+ !dns_name_equal(name, found)) {
+ /*
+ * Remember the obscuring name so that
+ * we skip all obscured names.
+ */
+ dns_name_copy(found, name, NULL);
+ delegation = ISC_TRUE;
+ goto next_removenode;
+ }
+ }
+
+ /*
+ * Check to see if this is a bottom of zone node.
+ */
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result == ISC_R_NOTFOUND) /* Empty node? */
+ goto next_removenode;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
+ seen_rr = ISC_FALSE;
+ for (result = dns_rdatasetiter_first(iterator);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iterator)) {
+ dns_rdatasetiter_current(iterator, &rdataset);
+ if (rdataset.type == dns_rdatatype_soa)
+ seen_soa = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ns)
+ seen_ns = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_dname)
+ seen_dname = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec)
+ seen_nsec = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec3)
+ seen_nsec3 = ISC_TRUE;
+ seen_rr = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ dns_rdatasetiter_destroy(&iterator);
+
+ if (!seen_rr || seen_nsec3 || seen_nsec)
+ goto next_removenode;
+ if ((seen_ns && !seen_soa) || seen_dname)
+ delegation = ISC_TRUE;
+
+ CHECK(add_nsec(db, version, name, node, zone->minimum,
+ delegation, &nsec_diff));
+
+ next_removenode:
+ first = ISC_FALSE;
+ dns_db_detachnode(db, &node);
+ do {
+ result = dns_dbiterator_next(nsec3chain->dbiterator);
+ if (result == ISC_R_NOMORE && buildnsecchain) {
+ /*
+ * The NSEC chain should now be built.
+ * We can now remove the NSEC3 chain.
+ */
+ updatensec = ISC_TRUE;
+ goto same_removechain;
+ }
+ if (result == ISC_R_NOMORE) {
+ LOCK_ZONE(zone);
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
+ link);
+ UNLOCK_ZONE(zone);
+ ISC_LIST_APPEND(cleanup, nsec3chain, link);
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ CHECK(fixup_nsec3param(db, version, nsec3chain,
+ ISC_FALSE, &param_diff));
+ goto next_removechain;
+ } else if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "dns_dbiterator_next -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ } else if (delegation) {
+ dns_dbiterator_current(nsec3chain->dbiterator,
+ &node, nextname);
+ dns_db_detachnode(db, &node);
+ if (!dns_name_issubdomain(nextname, name))
+ break;
+ } else
+ break;
+ } while (1);
+ continue;
+
+ same_removechain:
+ CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
+ buildnsecchain = ISC_FALSE;
+ first = ISC_TRUE;
+ continue;
+
+ next_removechain:
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ nsec3chain = nextnsec3chain;
+ first = ISC_TRUE;
+ }
+
+ /*
+ * Add / update signatures for the NSEC3 records.
+ */
+ for (tuple = ISC_LIST_HEAD(nsec3_diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_HEAD(nsec3_diff.tuples)) {
+ /*
+ * We have changed the NSEC3 RRset above so we need to update
+ * the signatures.
+ */
+ result = del_sigs(zone, db, version, &tuple->name,
+ dns_rdatatype_nsec3, &sig_diff,
+ zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:del_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ result = add_sigs(db, version, &tuple->name,
+ dns_rdatatype_nsec3, &sig_diff, zone_keys,
+ nkeys, zone->mctx, inception, expire,
+ check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:add_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ do {
+ dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
+ while (next != NULL &&
+ !dns_name_equal(&tuple->name, &next->name))
+ next = ISC_LIST_NEXT(next, link);
+ ISC_LIST_UNLINK(nsec3_diff.tuples, tuple, link);
+ dns_diff_appendminimal(&sig_diff, &tuple);
+ INSIST(tuple == NULL);
+ tuple = next;
+ } while (tuple != NULL);
+ }
+
+ for (tuple = ISC_LIST_HEAD(param_diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_HEAD(param_diff.tuples)) {
+ /*
+ * We have changed the NSEC3PARAM RRset above so we need to
+ * update the signatures.
+ */
+ result = del_sigs(zone, db, version, &tuple->name,
+ dns_rdatatype_nsec3param, &sig_diff,
+ zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:del_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ result = add_sigs(db, version, &tuple->name,
+ dns_rdatatype_nsec3param, &sig_diff,
+ zone_keys, nkeys, zone->mctx, inception,
+ expire, check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:add_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ ISC_LIST_UNLINK(param_diff.tuples, tuple, link);
+ dns_diff_appendminimal(&sig_diff, &tuple);
+ INSIST(tuple == NULL);
+ }
+
+ if (updatensec)
+ CHECK(updatesecure(db, version, &zone->origin, zone->minimum,
+ NULL, &nsec_diff));
+
+ for (tuple = ISC_LIST_HEAD(nsec_diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_HEAD(nsec_diff.tuples)) {
+ result = del_sigs(zone, db, version, &tuple->name,
+ dns_rdatatype_nsec, &sig_diff,
+ zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:del_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ result = add_sigs(db, version, &tuple->name,
+ dns_rdatatype_nsec, &sig_diff,
+ zone_keys, nkeys, zone->mctx, inception,
+ expire, check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:add_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ ISC_LIST_UNLINK(nsec_diff.tuples, tuple, link);
+ dns_diff_appendminimal(&sig_diff, &tuple);
+ INSIST(tuple == NULL);
+ }
+
+ /*
+ * If we made no effective changes to the zone then we can just
+ * cleanup otherwise we need to increment the serial.
+ */
+ if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
+ goto done;
+
+ result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
+ &sig_diff, zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "del_sigs -> %s\n", dns_result_totext(result));
+ goto failure;
+ }
+
+ result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "increment_soa_serial -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
+ &sig_diff, zone_keys, nkeys, zone->mctx, inception,
+ soaexpire, check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "add_sigs -> %s\n", dns_result_totext(result));
+ goto failure;
+ }
+
+ journalfile = dns_zone_getjournal(zone);
+ if (journalfile != NULL) {
+ dns_journal_t *journal = NULL;
+ result = dns_journal_open(zone->mctx, journalfile,
+ ISC_TRUE, &journal);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "dns_journal_open -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = dns_journal_write_transaction(journal, &sig_diff);
+ dns_journal_destroy(&journal);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "dns_journal_write_transaction -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+
+ LOCK_ZONE(zone);
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ UNLOCK_ZONE(zone);
+
+ done:
+ /*
+ * Pause all iterators so that dns_db_closeversion() can succeed.
+ */
+ LOCK_ZONE(zone);
+ for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ nsec3chain != NULL;
+ nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ UNLOCK_ZONE(zone);
+
+ /*
+ * Everything has succeeded. Commit the changes.
+ */
+ dns_db_closeversion(db, &version, ISC_TRUE);
+
+ /*
+ * Everything succeeded so we can clean these up now.
+ */
+ nsec3chain = ISC_LIST_HEAD(cleanup);
+ while (nsec3chain != NULL) {
+ ISC_LIST_UNLINK(cleanup, nsec3chain, link);
+ dns_db_detach(&nsec3chain->db);
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ nsec3chain = ISC_LIST_HEAD(cleanup);
+ }
+
+ set_resigntime(zone);
+
+ failure:
+ /*
+ * On error roll back the current nsec3chain.
+ */
+ if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
+ if (nsec3chain->done) {
+ dns_db_detach(&nsec3chain->db);
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ } else {
+ result = dns_dbiterator_first(nsec3chain->dbiterator);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
+ }
+ }
+
+ /*
+ * Rollback the cleanup list.
+ */
+ nsec3chain = ISC_LIST_TAIL(cleanup);
+ while (nsec3chain != NULL) {
+ ISC_LIST_UNLINK(cleanup, nsec3chain, link);
+ if (nsec3chain->done) {
+ dns_db_detach(&nsec3chain->db);
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ } else {
+ LOCK_ZONE(zone);
+ ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
+ UNLOCK_ZONE(zone);
+ result = dns_dbiterator_first(nsec3chain->dbiterator);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
+ }
+ nsec3chain = ISC_LIST_TAIL(cleanup);
+ }
+
+ LOCK_ZONE(zone);
+ for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ nsec3chain != NULL;
+ nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ UNLOCK_ZONE(zone);
+
+ dns_diff_clear(&param_diff);
+ dns_diff_clear(&nsec3_diff);
+ dns_diff_clear(&nsec_diff);
+ dns_diff_clear(&sig_diff);
+
+ if (iterator != NULL)
+ dns_rdatasetiter_destroy(&iterator);
+
+ for (i = 0; i < nkeys; i++)
+ dst_key_free(&zone_keys[i]);
+
+ if (version != NULL) {
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+ } else if (db != NULL)
+ dns_db_detach(&db);
+
+ LOCK_ZONE(zone);
+ if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
+ isc_interval_t i;
+ if (zone->update_disabled || result != ISC_R_SUCCESS)
+ isc_interval_set(&i, 60, 0); /* 1 minute */
+ else
+ isc_interval_set(&i, 0, 10000000); /* 10 ms */
+ isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
+ } else
+ isc_time_settoepoch(&zone->nsec3chaintime);
+ UNLOCK_ZONE(zone);
+}
+
+static isc_result_t
+del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
+ isc_uint16_t keyid, dns_diff_t *diff)
+{
+ dns_rdata_rrsig_t rrsig;
+ dns_rdataset_t rdataset;
+ dns_rdatasetiter_t *iterator = NULL;
+ isc_result_t result;
+
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+ return (result);
+ }
+
+ dns_rdataset_init(&rdataset);
+ for (result = dns_rdatasetiter_first(iterator);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iterator)) {
+ dns_rdatasetiter_current(iterator, &rdataset);
+ if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(update_one_rr(db, version, diff,
+ DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata));
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (rdataset.type != dns_rdatatype_rrsig) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
+ if (rrsig.algorithm != algorithm ||
+ rrsig.keyid != keyid)
+ continue;
+ CHECK(update_one_rr(db, version, diff,
+ DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata));
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOMORE)
+ break;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ dns_rdatasetiter_destroy(&iterator);
+ return (result);
+}
+
+/*
+ * Incrementally sign the zone using the keys requested.
+ * Builds the NSEC chain if required.
+ */
+static void
+zone_sign(dns_zone_t *zone) {
+ const char *journalfile;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_diff_t sig_diff;
+ dns_fixedname_t fixed;
+ dns_fixedname_t nextfixed;
+ dns_name_t *name, *nextname;
+ dns_rdataset_t rdataset;
+ dns_signing_t *signing, *nextsigning;
+ dns_signinglist_t cleanup;
+ dst_key_t *zone_keys[MAXZONEKEYS];
+ isc_int32_t signatures;
+ isc_boolean_t check_ksk, is_ksk;
+ isc_boolean_t delegation;
+ isc_boolean_t finishedakey = ISC_FALSE;
+ isc_boolean_t secureupdated = ISC_FALSE;
+ isc_boolean_t build_nsec3 = ISC_FALSE, build_nsec = ISC_FALSE;
+ isc_boolean_t first;
+ isc_result_t result;
+ isc_stdtime_t now, inception, soaexpire, expire, stop;
+ isc_uint32_t jitter;
+ unsigned int i;
+ unsigned int nkeys = 0;
+ isc_uint32_t nodes;
+
+ dns_rdataset_init(&rdataset);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&nextfixed);
+ nextname = dns_fixedname_name(&nextfixed);
+ dns_diff_init(zone->mctx, &sig_diff);
+ sig_diff.resign = zone->sigresigninginterval;
+ ISC_LIST_INIT(cleanup);
+
+ /*
+ * Updates are disabled. Pause for 5 minutes.
+ */
+ if (zone->update_disabled) {
+ result = ISC_R_FAILURE;
+ goto failure;
+ }
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ result = dns_db_newversion(db, &version);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = find_zone_keys(zone, db, version, zone->mctx,
+ MAXZONEKEYS, zone_keys, &nkeys);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:find_zone_keys -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ isc_stdtime_get(&now);
+ inception = now - 3600; /* Allow for clock skew. */
+ soaexpire = now + dns_zone_getsigvalidityinterval(zone);
+
+ /*
+ * Spread out signatures over time if they happen to be
+ * clumped. We don't do this for each add_sigs() call as
+ * we still want some clustering to occur.
+ */
+ isc_random_get(&jitter);
+ expire = soaexpire - jitter % 3600;
+ stop = now + 5;
+
+ check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
+ if (check_ksk)
+ check_ksk = ksk_sanity(db, version);
+
+ /*
+ * We keep pulling nodes off each iterator in turn until
+ * we have no more nodes to pull off or we reach the limits
+ * for this quantum.
+ */
+ nodes = zone->nodes;
+ signatures = zone->signatures;
+ signing = ISC_LIST_HEAD(zone->signing);
+ first = ISC_TRUE;
+ /*
+ * See if we have a NSEC chain.
+ */
+ result = dns_db_getoriginnode(db, &node);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec,
+ dns_rdatatype_none, 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_SUCCESS) {
+ build_nsec = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ } else if (result != ISC_R_NOTFOUND) {
+ goto failure;
+ } else {
+ /*
+ * No NSEC chain present.
+ * See if we need to build a NSEC3 chain?
+ */
+ result = dns_nsec3_active(db, version, ISC_TRUE, &build_nsec3);
+ if (result == ISC_R_SUCCESS) {
+ if (build_nsec3)
+ build_nsec3 = ISC_FALSE;
+ else {
+ result = dns_nsec3_active(db, version,
+ ISC_FALSE,
+ &build_nsec3);
+ if (build_nsec3)
+ secureupdated = ISC_TRUE;
+ else
+ build_nsec = ISC_TRUE;
+ }
+ }
+ }
+
+ while (signing != NULL && nodes-- > 0 && signatures > 0) {
+ nextsigning = ISC_LIST_NEXT(signing, link);
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (signing->done || signing->db != zone->db) {
+ /*
+ * The zone has been reloaded. We will have
+ * created new signings as part of the reload
+ * process so we can destroy this one.
+ */
+ ISC_LIST_UNLINK(zone->signing, signing, link);
+ ISC_LIST_APPEND(cleanup, signing, link);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ goto next_signing;
+ }
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ if (signing->db != db)
+ goto next_signing;
+
+ is_ksk = ISC_FALSE;
+ delegation = ISC_FALSE;
+
+ dns_dbiterator_current(signing->dbiterator, &node, name);
+
+ if (signing->delete) {
+ dns_dbiterator_pause(signing->dbiterator);
+ CHECK(del_sig(db, version, name, node, nkeys,
+ signing->algorithm, signing->keyid,
+ &sig_diff));
+ goto next_node;
+ }
+ /*
+ * On the first pass we need to check if the current node
+ * has not been obscured.
+ */
+ if (first) {
+ dns_fixedname_t ffound;
+ dns_name_t *found;
+ dns_fixedname_init(&ffound);
+ found = dns_fixedname_name(&ffound);
+ result = dns_db_find(db, name, version,
+ dns_rdatatype_soa,
+ DNS_DBFIND_NOWILD, 0, NULL, found,
+ NULL, NULL);
+ if ((result == DNS_R_DELEGATION ||
+ result == DNS_R_DNAME) &&
+ !dns_name_equal(name, found)) {
+ /*
+ * Remember the obscuring name so that
+ * we skip all obscured names.
+ */
+ dns_name_copy(found, name, NULL);
+ delegation = ISC_TRUE;
+ goto next_node;
+ }
+ }
+
+ /*
+ * Process one node.
+ */
+ dns_dbiterator_pause(signing->dbiterator);
+ for (i = 0; i < nkeys; i++) {
+ /*
+ * Find the key we want to sign with.
+ */
+ if (dst_key_alg(zone_keys[i]) != signing->algorithm ||
+ dst_key_id(zone_keys[i]) != signing->keyid ||
+ !dst_key_isprivate(zone_keys[i]))
+ continue;
+ /*
+ * Do we do KSK processing?
+ */
+ if (check_ksk &&
+ (dst_key_flags(zone_keys[i]) & DNS_KEYFLAG_KSK) != 0)
+ is_ksk = ISC_TRUE;
+ CHECK(sign_a_node(db, name, node, version, build_nsec3,
+ build_nsec, zone_keys[i], inception,
+ expire, zone->minimum, is_ksk,
+ &delegation, &sig_diff, &signatures,
+ zone->mctx));
+ break;
+ }
+ /*
+ * Go onto next node.
+ */
+ next_node:
+ first = ISC_FALSE;
+ dns_db_detachnode(db, &node);
+ do {
+ result = dns_dbiterator_next(signing->dbiterator);
+ if (result == ISC_R_NOMORE) {
+ ISC_LIST_UNLINK(zone->signing, signing, link);
+ ISC_LIST_APPEND(cleanup, signing, link);
+ dns_dbiterator_pause(signing->dbiterator);
+ finishedakey = ISC_TRUE;
+ if (!is_ksk && !secureupdated && nkeys != 0 &&
+ build_nsec) {
+ /*
+ * We have finished regenerating the
+ * zone with a zone signing key.
+ * The NSEC chain is now complete and
+ * there is a full set of signatures
+ * for the zone. We can now clear the
+ * OPT bit from the NSEC record.
+ */
+ result = updatesecure(db, version,
+ &zone->origin,
+ zone->minimum,
+ &secureupdated,
+ &sig_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone,
+ ISC_LOG_ERROR,
+ "updatesecure -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+ result = updatesignwithkey(signing, version,
+ &zone->origin,
+ zone->privatetype,
+ &sig_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "updatesignwithkey -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ goto next_signing;
+ } else if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:dns_dbiterator_next -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ } else if (delegation) {
+ dns_dbiterator_current(signing->dbiterator,
+ &node, nextname);
+ dns_db_detachnode(db, &node);
+ if (!dns_name_issubdomain(nextname, name))
+ break;
+ } else
+ break;
+ } while (1);
+ continue;
+
+ next_signing:
+ dns_dbiterator_pause(signing->dbiterator);
+ signing = nextsigning;
+ first = ISC_TRUE;
+ }
+
+ if (secureupdated) {
+ /*
+ * We have changed the NSEC RRset above so we need to update
+ * the signatures.
+ */
+ result = del_sigs(zone, db, version, &zone->origin,
+ dns_rdatatype_nsec, &sig_diff, zone_keys,
+ nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:del_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ result = add_sigs(db, version, &zone->origin,
+ dns_rdatatype_nsec, &sig_diff, zone_keys,
+ nkeys, zone->mctx, inception, soaexpire,
+ check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:add_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+ if (finishedakey) {
+ /*
+ * We have changed the RRset above so we need to update
+ * the signatures.
+ */
+ result = del_sigs(zone, db, version, &zone->origin,
+ zone->privatetype, &sig_diff,
+ zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:del_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ result = add_sigs(db, version, &zone->origin,
+ zone->privatetype, &sig_diff,
+ zone_keys, nkeys, zone->mctx, inception,
+ soaexpire, check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:add_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+ result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
+ &sig_diff, zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:del_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:increment_soa_serial -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ /*
+ * Generate maximum life time signatures so that the above loop
+ * termination is sensible.
+ */
+ result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
+ &sig_diff, zone_keys, nkeys, zone->mctx, inception,
+ soaexpire, check_ksk);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:add_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ journalfile = dns_zone_getjournal(zone);
+ if (journalfile != NULL) {
+ dns_journal_t *journal = NULL;
+ result = dns_journal_open(zone->mctx, journalfile,
+ ISC_TRUE, &journal);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:dns_journal_open -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = dns_journal_write_transaction(journal, &sig_diff);
+ dns_journal_destroy(&journal);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:dns_journal_write_transaction -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+
+
+ /*
+ * Pause all iterators so that dns_db_closeversion() can succeed.
+ */
+ for (signing = ISC_LIST_HEAD(zone->signing);
+ signing != NULL;
+ signing = ISC_LIST_NEXT(signing, link))
+ dns_dbiterator_pause(signing->dbiterator);
+
+ for (signing = ISC_LIST_HEAD(cleanup);
+ signing != NULL;
+ signing = ISC_LIST_NEXT(signing, link))
+ dns_dbiterator_pause(signing->dbiterator);
+
+ /*
+ * Everything has succeeded. Commit the changes.
+ */
+ dns_db_closeversion(db, &version, ISC_TRUE);
+
+ /*
+ * Everything succeeded so we can clean these up now.
+ */
+ signing = ISC_LIST_HEAD(cleanup);
+ while (signing != NULL) {
+ ISC_LIST_UNLINK(cleanup, signing, link);
+ dns_db_detach(&signing->db);
+ dns_dbiterator_destroy(&signing->dbiterator);
+ isc_mem_put(zone->mctx, signing, sizeof *signing);
+ signing = ISC_LIST_HEAD(cleanup);
+ }
+
+ set_resigntime(zone);
+
+ LOCK_ZONE(zone);
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ UNLOCK_ZONE(zone);
+
+ failure:
+ /*
+ * Rollback the cleanup list.
+ */
+ signing = ISC_LIST_HEAD(cleanup);
+ while (signing != NULL) {
+ ISC_LIST_UNLINK(cleanup, signing, link);
+ ISC_LIST_APPEND(zone->signing, signing, link);
+ dns_dbiterator_first(signing->dbiterator);
+ dns_dbiterator_pause(signing->dbiterator);
+ signing = ISC_LIST_HEAD(cleanup);
+ }
+
+ for (signing = ISC_LIST_HEAD(zone->signing);
+ signing != NULL;
+ signing = ISC_LIST_NEXT(signing, link))
+ dns_dbiterator_pause(signing->dbiterator);
+
+ dns_diff_clear(&sig_diff);
+
+ for (i = 0; i < nkeys; i++)
+ dst_key_free(&zone_keys[i]);
+
+ if (version != NULL) {
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+ } else if (db != NULL)
+ dns_db_detach(&db);
+
+ if (ISC_LIST_HEAD(zone->signing) != NULL) {
+ isc_interval_t i;
+ if (zone->update_disabled || result != ISC_R_SUCCESS)
+ isc_interval_set(&i, 60, 0); /* 1 minute */
+ else
+ isc_interval_set(&i, 0, 10000000); /* 10 ms */
+ isc_time_nowplusinterval(&zone->signingtime, &i);
+ } else
+ isc_time_settoepoch(&zone->signingtime);
+}
+
static void
zone_maintenance(dns_zone_t *zone) {
const char me[] = "zone_maintenance";
@@ -3016,15 +5981,34 @@ zone_maintenance(dns_zone_t *zone) {
break;
}
- /*
- * Do we need to send out notify messages?
- */
switch (zone->type) {
case dns_zone_master:
case dns_zone_slave:
+ /*
+ * Do we need to send out notify messages?
+ */
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
isc_time_compare(&now, &zone->notifytime) >= 0)
zone_notify(zone, &now);
+ /*
+ * Do we need to sign/resign some RRsets?
+ */
+ if (!isc_time_isepoch(&zone->signingtime) &&
+ isc_time_compare(&now, &zone->signingtime) >= 0)
+ zone_sign(zone);
+ else if (!isc_time_isepoch(&zone->resigntime) &&
+ isc_time_compare(&now, &zone->resigntime) >= 0)
+ zone_resigninc(zone);
+ else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
+ isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
+ zone_nsec3chain(zone);
+ /*
+ * Do we need to issue a key expiry warning.
+ */
+ if (!isc_time_isepoch(&zone->keywarntime) &&
+ isc_time_compare(&now, &zone->keywarntime) >= 0)
+ set_key_expiry_warning(zone, zone->key_expiry,
+ isc_time_seconds(&now));
break;
default:
break;
@@ -3036,6 +6020,7 @@ void
dns_zone_markdirty(dns_zone_t *zone) {
LOCK_ZONE(zone);
+ set_resigntime(zone); /* XXXMPA make separate call back */
zone_needdump(zone, DNS_DUMP_DELAY);
UNLOCK_ZONE(zone);
}
@@ -3776,6 +6761,16 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
timeout * 3, timeout,
notify->zone->task, notify_done,
notify, &notify->request);
+ if (result == ISC_R_SUCCESS) {
+ if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
+ inc_stats(notify->zone,
+ dns_zonestatscounter_notifyoutv4);
+ } else {
+ inc_stats(notify->zone,
+ dns_zonestatscounter_notifyoutv6);
+ }
+ }
+
cleanup_key:
if (key != NULL)
dns_tsigkey_detach(&key);
@@ -3975,9 +6970,11 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) {
RUNTIME_CHECK(result == ISC_R_SUCCESS);
dns_rdata_reset(&rdata);
/*
- * don't notify the master server.
+ * Don't notify the master server unless explicitly
+ * configured to do so.
*/
- if (dns_name_compare(&master, &ns.name) == 0) {
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
+ dns_name_compare(&master, &ns.name) == 0) {
result = dns_rdataset_next(&nsrdset);
continue;
}
@@ -4163,6 +7160,8 @@ stub_callback(isc_task_t *task, isc_event_t *event) {
master, source);
goto same_master;
}
+ dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
+ &zone->sourceaddr, &now);
dns_zone_log(zone, ISC_LOG_INFO,
"could not refresh stub from master %s"
" (source %s): %s", master, source,
@@ -4424,12 +7423,23 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
"master %s exceeded (source %s)",
master, source);
/* Try with slave with TCP. */
- if (zone->type == dns_zone_slave) {
- LOCK_ZONE(zone);
- DNS_ZONE_SETFLAG(zone,
- DNS_ZONEFLG_SOABEFOREAXFR);
- UNLOCK_ZONE(zone);
- goto tcp_transfer;
+ if (zone->type == dns_zone_slave &&
+ DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
+ if (!dns_zonemgr_unreachable(zone->zmgr,
+ &zone->masteraddr,
+ &zone->sourceaddr,
+ &now)) {
+ LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone,
+ DNS_ZONEFLG_SOABEFOREAXFR);
+ UNLOCK_ZONE(zone);
+ goto tcp_transfer;
+ }
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "refresh: skipped tcp fallback"
+ "as master %s (source %s) is "
+ "unreachable (cached)",
+ master, source);
}
} else
dns_zone_log(zone, ISC_LOG_INFO,
@@ -4479,7 +7489,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
"master %s (source %s)", (int)rb.used, rcode,
master, source);
/*
- * Perhaps AXFR/IXFR is allowed even if SOA queries arn't.
+ * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
*/
if (msg->rcode == dns_rcode_refused &&
zone->type == dns_zone_slave)
@@ -4605,6 +7615,16 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
isc_serial_gt(serial, zone->serial)) {
+ if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
+ &zone->sourceaddr, &now)) {
+ dns_zone_log(zone, ISC_LOG_INFO,
+ "refresh: skipping %s as master %s "
+ "(source %s) is unreachable (cached)",
+ zone->type == dns_zone_slave ?
+ "zone transfer" : "NS query",
+ master, source);
+ goto next_master;
+ }
tcp_transfer:
isc_event_free(&event);
LOCK_ZONE(zone);
@@ -4820,7 +7840,7 @@ create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
}
static isc_result_t
-add_opt(dns_message_t *message, isc_uint16_t udpsize) {
+add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
dns_rdataset_t *rdataset = NULL;
dns_rdatalist_t *rdatalist = NULL;
dns_rdata_t *rdata = NULL;
@@ -4850,11 +7870,21 @@ add_opt(dns_message_t *message, isc_uint16_t udpsize) {
*/
rdatalist->ttl = 0;
- /*
- * No EDNS options.
- */
- rdata->data = NULL;
- rdata->length = 0;
+ /* Set EDNS options if applicable */
+ if (reqnsid) {
+ unsigned char data[4];
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, data, sizeof(data));
+ isc_buffer_putuint16(&buf, DNS_OPT_NSID);
+ isc_buffer_putuint16(&buf, 0);
+ rdata->data = data;
+ rdata->length = sizeof(data);
+ } else {
+ rdata->data = NULL;
+ rdata->length = 0;
+ }
+
rdata->rdclass = rdatalist->rdclass;
rdata->type = rdatalist->type;
rdata->flags = 0;
@@ -4889,7 +7919,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
isc_uint32_t options;
isc_boolean_t cancel = ISC_TRUE;
int timeout;
- isc_boolean_t have_xfrsource;
+ isc_boolean_t have_xfrsource, reqnsid;
isc_uint16_t udpsize = SEND_BUFFER_SIZE;
REQUIRE(DNS_ZONE_VALID(zone));
@@ -4941,6 +7971,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
(void)dns_view_getpeertsig(zone->view, &masterip, &key);
have_xfrsource = ISC_FALSE;
+ reqnsid = zone->view->requestnsid;
if (zone->view->peers != NULL) {
dns_peer_t *peer = NULL;
isc_boolean_t edns;
@@ -4958,6 +7989,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
udpsize =
dns_resolver_getudpsize(zone->view->resolver);
(void)dns_peer_getudpsize(peer, &udpsize);
+ (void)dns_peer_getrequestnsid(peer, &reqnsid);
}
}
@@ -4989,7 +8021,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
DNS_REQUESTOPT_TCP : 0;
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
- result = add_opt(message, udpsize);
+ result = add_opt(message, udpsize, reqnsid);
if (result != ISC_R_SUCCESS)
zone_debuglog(zone, me, 1,
"unable to add opt record: %s",
@@ -5011,6 +8043,11 @@ soa_query(isc_task_t *task, isc_event_t *event) {
"dns_request_createvia2() failed: %s",
dns_result_totext(result));
goto cleanup;
+ } else {
+ if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
+ inc_stats(zone, dns_zonestatscounter_soaoutv4);
+ else
+ inc_stats(zone, dns_zonestatscounter_soaoutv6);
}
cancel = ISC_FALSE;
@@ -5053,7 +8090,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
dns_tsigkey_t *key = NULL;
dns_dbnode_t *node = NULL;
int timeout;
- isc_boolean_t have_xfrsource = ISC_FALSE;
+ isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
isc_uint16_t udpsize = SEND_BUFFER_SIZE;
REQUIRE(DNS_ZONE_VALID(zone));
@@ -5165,6 +8202,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
if (key == NULL)
(void)dns_view_getpeertsig(zone->view, &masterip, &key);
+ reqnsid = zone->view->requestnsid;
if (zone->view->peers != NULL) {
dns_peer_t *peer = NULL;
isc_boolean_t edns;
@@ -5182,11 +8220,12 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
udpsize =
dns_resolver_getudpsize(zone->view->resolver);
(void)dns_peer_getudpsize(peer, &udpsize);
+ (void)dns_peer_getrequestnsid(peer, &reqnsid);
}
}
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
- result = add_opt(message, udpsize);
+ result = add_opt(message, udpsize, reqnsid);
if (result != ISC_R_SUCCESS)
zone_debuglog(zone, me, 1,
"unable to add opt record: %s",
@@ -5382,6 +8421,26 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) {
isc_time_compare(&zone->dumptime, &next) < 0)
next = zone->dumptime;
}
+ if (!isc_time_isepoch(&zone->resigntime)) {
+ if (isc_time_isepoch(&next) ||
+ isc_time_compare(&zone->resigntime, &next) < 0)
+ next = zone->resigntime;
+ }
+ if (!isc_time_isepoch(&zone->keywarntime)) {
+ if (isc_time_isepoch(&next) ||
+ isc_time_compare(&zone->keywarntime, &next) < 0)
+ next = zone->keywarntime;
+ }
+ if (!isc_time_isepoch(&zone->signingtime)) {
+ if (isc_time_isepoch(&next) ||
+ isc_time_compare(&zone->signingtime, &next) < 0)
+ next = zone->signingtime;
+ }
+ if (!isc_time_isepoch(&zone->nsec3chaintime)) {
+ if (isc_time_isepoch(&next) ||
+ isc_time_compare(&zone->nsec3chaintime, &next) < 0)
+ next = zone->nsec3chaintime;
+ }
break;
case dns_zone_slave:
@@ -5651,6 +8710,10 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
* We only handle NOTIFY (SOA) at the present.
*/
LOCK_ZONE(zone);
+ if (isc_sockaddr_pf(from) == PF_INET)
+ inc_stats(zone, dns_zonestatscounter_notifyinv4);
+ else
+ inc_stats(zone, dns_zonestatscounter_notifyinv6);
if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
dns_rdatatype_soa, dns_rdatatype_none,
@@ -5705,6 +8768,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
UNLOCK_ZONE(zone);
dns_zone_log(zone, ISC_LOG_INFO,
"refused notify from non-master: %s", fromtext);
+ inc_stats(zone, dns_zonestatscounter_notifyrej);
return (DNS_R_REFUSED);
}
@@ -5788,6 +8852,18 @@ dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
}
void
+dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->queryon_acl != NULL)
+ dns_acl_detach(&zone->queryon_acl);
+ dns_acl_attach(acl, &zone->queryon_acl);
+ UNLOCK_ZONE(zone);
+}
+
+void
dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
REQUIRE(DNS_ZONE_VALID(zone));
@@ -5840,6 +8916,14 @@ dns_zone_getqueryacl(dns_zone_t *zone) {
}
dns_acl_t *
+dns_zone_getqueryonacl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->queryon_acl);
+}
+
+dns_acl_t *
dns_zone_getupdateacl(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
@@ -5908,6 +8992,17 @@ dns_zone_clearqueryacl(dns_zone_t *zone) {
}
void
+dns_zone_clearqueryonacl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->queryon_acl != NULL)
+ dns_acl_detach(&zone->queryon_acl);
+ UNLOCK_ZONE(zone);
+}
+
+void
dns_zone_clearxfracl(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
@@ -5977,7 +9072,7 @@ dns_zone_getjournalsize(dns_zone_t *zone) {
}
static void
-zone_tostr(dns_zone_t *zone, char *buf, size_t length) {
+zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
isc_result_t result = ISC_R_FAILURE;
isc_buffer_t buffer;
@@ -6008,29 +9103,88 @@ zone_tostr(dns_zone_t *zone, char *buf, size_t length) {
buf[isc_buffer_usedlength(&buffer)] = '\0';
}
+static void
+zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
+ isc_result_t result = ISC_R_FAILURE;
+ isc_buffer_t buffer;
+
+ REQUIRE(buf != NULL);
+ REQUIRE(length > 1U);
+
+ /*
+ * Leave space for terminating '\0'.
+ */
+ isc_buffer_init(&buffer, buf, length - 1);
+ if (dns_name_dynamic(&zone->origin))
+ result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
+ if (result != ISC_R_SUCCESS &&
+ isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
+ isc_buffer_putstr(&buffer, "<UNKNOWN>");
+
+ buf[isc_buffer_usedlength(&buffer)] = '\0';
+}
+
+static void
+zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
+ isc_buffer_t buffer;
+
+ REQUIRE(buf != NULL);
+ REQUIRE(length > 1U);
+
+ /*
+ * Leave space for terminating '\0'.
+ */
+ isc_buffer_init(&buffer, buf, length - 1);
+ (void)dns_rdataclass_totext(zone->rdclass, &buffer);
+
+ buf[isc_buffer_usedlength(&buffer)] = '\0';
+}
+
+static void
+zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
+ isc_buffer_t buffer;
+
+ REQUIRE(buf != NULL);
+ REQUIRE(length > 1U);
+
+
+ /*
+ * Leave space for terminating '\0'.
+ */
+ isc_buffer_init(&buffer, buf, length - 1);
+
+ if (zone->view == NULL) {
+ isc_buffer_putstr(&buffer, "_none");
+ } else if (strlen(zone->view->name)
+ < isc_buffer_availablelength(&buffer)) {
+ isc_buffer_putstr(&buffer, zone->view->name);
+ } else {
+ isc_buffer_putstr(&buffer, "_toolong");
+ }
+
+ buf[isc_buffer_usedlength(&buffer)] = '\0';
+}
+
void
dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(buf != NULL);
- zone_tostr(zone, buf, length);
+ zone_namerd_tostr(zone, buf, length);
}
static void
notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
va_list ap;
char message[4096];
- char namebuf[1024+32];
if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
return;
- zone_tostr(zone, namebuf, sizeof(namebuf));
-
va_start(ap, fmt);
vsnprintf(message, sizeof(message), fmt, ap);
va_end(ap);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
- level, "zone %s: %s", namebuf, message);
+ level, "zone %s: %s", zone->strnamerd, message);
}
void
@@ -6038,36 +9192,30 @@ dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
int level, const char *fmt, ...) {
va_list ap;
char message[4096];
- char namebuf[1024+32];
if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
return;
- zone_tostr(zone, namebuf, sizeof(namebuf));
-
va_start(ap, fmt);
vsnprintf(message, sizeof(message), fmt, ap);
va_end(ap);
isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
- level, "zone %s: %s", namebuf, message);
+ level, "zone %s: %s", zone->strnamerd, message);
}
void
dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
va_list ap;
char message[4096];
- char namebuf[1024+32];
if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
return;
- zone_tostr(zone, namebuf, sizeof(namebuf));
-
va_start(ap, fmt);
vsnprintf(message, sizeof(message), fmt, ap);
va_end(ap);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
- level, "zone %s: %s", namebuf, message);
+ level, "zone %s: %s", zone->strnamerd, message);
}
static void
@@ -6076,19 +9224,16 @@ zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
{
va_list ap;
char message[4096];
- char namebuf[1024+32];
int level = ISC_LOG_DEBUG(debuglevel);
if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
return;
- zone_tostr(zone, namebuf, sizeof(namebuf));
-
va_start(ap, fmt);
vsnprintf(message, sizeof(message), fmt, ap);
va_end(ap);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
- level, "%s: zone %s: %s", me, namebuf, message);
+ level, "%s: zone %s: %s", me, zone->strnamerd, message);
}
static int
@@ -6313,12 +9458,16 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
return (result);
}
+ result = check_nsec3param(zone, db);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
ver = NULL;
dns_db_currentversion(db, &ver);
/*
* The initial version of a slave zone is always dumped;
- * subsequent versions may be journalled instead if this
+ * subsequent versions may be journaled instead if this
* is enabled in the configuration.
*/
if (zone->db != NULL && zone->journal != NULL &&
@@ -6401,7 +9550,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
* The in-memory database just changed, and
* because 'dump' is set, it didn't change by
* being loaded from disk. Also, we have not
- * journalled diffs for this change.
+ * journaled diffs for this change.
* Therefore, the on-disk journal is missing
* the deltas for this change. Since it can
* no longer be used to bring the zone
@@ -6411,7 +9560,17 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
"removing journal file");
- (void)remove(zone->journal);
+ if (remove(zone->journal) < 0 && errno != ENOENT) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_ZONE,
+ ISC_LOG_WARNING,
+ "unable to remove journal "
+ "'%s': '%s'",
+ zone->journal, strbuf);
+ }
}
}
@@ -6568,7 +9727,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
}
/*
- * This is not neccessary if we just performed a AXFR
+ * This is not necessary if we just performed a AXFR
* however it is necessary for an IXFR / UPTODATE and
* won't hurt with an AXFR.
*/
@@ -6592,6 +9751,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
dns_result_totext(result));
}
+ inc_stats(zone, dns_zonestatscounter_xfrsuccess);
break;
case DNS_R_BADIXFR:
@@ -6626,6 +9786,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
again = ISC_TRUE;
}
+ inc_stats(zone, dns_zonestatscounter_xfrfail);
break;
}
zone_settimer(zone, &now);
@@ -6760,6 +9921,20 @@ dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
return (zone->sigvalidityinterval);
}
+void
+dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ zone->sigresigninginterval = interval;
+}
+
+isc_uint32_t
+dns_zone_getsigresigninginterval(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->sigresigninginterval);
+}
+
static void
queue_xfrin(dns_zone_t *zone) {
const char me[] = "queue_xfrin";
@@ -6798,12 +9973,14 @@ static void
got_transfer_quota(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
dns_peer_t *peer = NULL;
- char mastertext[256];
+ char master[ISC_SOCKADDR_FORMATSIZE];
+ char source[ISC_SOCKADDR_FORMATSIZE];
dns_rdatatype_t xfrtype;
dns_zone_t *zone = event->ev_arg;
isc_netaddr_t masterip;
isc_sockaddr_t sourceaddr;
isc_sockaddr_t masteraddr;
+ isc_time_t now;
UNUSED(task);
@@ -6814,34 +9991,44 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
goto cleanup;
}
- isc_sockaddr_format(&zone->masteraddr, mastertext, sizeof(mastertext));
+ TIME_NOW(&now);
+
+ isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
+ if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
+ &zone->sourceaddr, &now)) {
+ isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
+ dns_zone_log(zone, ISC_LOG_INFO,
+ "got_transfer_quota: skipping zone transfer as "
+ "master %s (source %s) is unreachable (cached)",
+ master, source);
+ result = ISC_R_CANCELED;
+ goto cleanup;
+ }
isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
- (void)dns_peerlist_peerbyaddr(zone->view->peers,
- &masterip, &peer);
+ (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
/*
* Decide whether we should request IXFR or AXFR.
*/
if (zone->db == NULL) {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
- "no database exists yet, "
- "requesting AXFR of "
- "initial version from %s", mastertext);
+ "no database exists yet, requesting AXFR of "
+ "initial version from %s", master);
xfrtype = dns_rdatatype_axfr;
} else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
- "set, requesting AXFR from %s", mastertext);
+ "set, requesting AXFR from %s", master);
xfrtype = dns_rdatatype_axfr;
} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"forced reload, requesting AXFR of "
- "initial version from %s", mastertext);
+ "initial version from %s", master);
xfrtype = dns_rdatatype_axfr;
} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"retrying with AXFR from %s due to "
- "previous IXFR failure", mastertext);
+ "previous IXFR failure", master);
xfrtype = dns_rdatatype_axfr;
LOCK_ZONE(zone);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
@@ -6857,17 +10044,15 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
}
if (use_ixfr == ISC_FALSE) {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
- "IXFR disabled, "
- "requesting AXFR from %s",
- mastertext);
+ "IXFR disabled, requesting AXFR from %s",
+ master);
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
xfrtype = dns_rdatatype_soa;
else
xfrtype = dns_rdatatype_axfr;
} else {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
- "requesting IXFR from %s",
- mastertext);
+ "requesting IXFR from %s", master);
xfrtype = dns_rdatatype_ixfr;
}
}
@@ -6892,8 +10077,7 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
dns_zone_log(zone, ISC_LOG_ERROR,
- "could not get TSIG key "
- "for zone transfer: %s",
+ "could not get TSIG key for zone transfer: %s",
isc_result_totext(result));
}
@@ -6906,6 +10090,21 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
zone->tsigkey, zone->mctx,
zone->zmgr->timermgr, zone->zmgr->socketmgr,
zone->task, zone_xfrdone, &zone->xfr);
+ if (result == ISC_R_SUCCESS) {
+ LOCK_ZONE(zone);
+ if (xfrtype == dns_rdatatype_axfr) {
+ if (isc_sockaddr_pf(&masteraddr) == PF_INET)
+ inc_stats(zone, dns_zonestatscounter_axfrreqv4);
+ else
+ inc_stats(zone, dns_zonestatscounter_axfrreqv6);
+ } else if (xfrtype == dns_rdatatype_ixfr) {
+ if (isc_sockaddr_pf(&masteraddr) == PF_INET)
+ inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
+ else
+ inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
+ }
+ UNLOCK_ZONE(zone);
+ }
cleanup:
/*
* Any failure in this function is handled like a failed
@@ -7175,6 +10374,7 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
ISC_LIST_INIT(zmgr->zones);
ISC_LIST_INIT(zmgr->waiting_for_xfrin);
ISC_LIST_INIT(zmgr->xfrin_in_progress);
+ memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
if (result != ISC_R_SUCCESS)
goto free_mem;
@@ -7264,8 +10464,10 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
NULL, NULL,
zone->task, zone_timer, zone,
&zone->timer);
+
if (result != ISC_R_SUCCESS)
goto cleanup_task;
+
/*
* The timer "holds" a iref.
*/
@@ -7735,7 +10937,7 @@ zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
}
#if 0
-/* Hook for ondestroy notifcation from a database. */
+/* Hook for ondestroy notification from a database. */
static void
dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
@@ -7791,6 +10993,87 @@ dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
return (zmgr->serialqueryrate);
}
+static isc_boolean_t
+dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
+ isc_sockaddr_t *local, isc_time_t *now)
+{
+ unsigned int i;
+ isc_rwlocktype_t locktype;
+ isc_result_t result;
+ isc_uint32_t seconds = isc_time_seconds(now);
+
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ locktype = isc_rwlocktype_read;
+ RWLOCK(&zmgr->rwlock, locktype);
+ for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
+ if (zmgr->unreachable[i].expire >= seconds &&
+ isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
+ isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
+ result = isc_rwlock_tryupgrade(&zmgr->rwlock);
+ if (result == ISC_R_SUCCESS) {
+ locktype = isc_rwlocktype_write;
+ zmgr->unreachable[i].last = seconds;
+ }
+ break;
+ }
+ }
+ RWUNLOCK(&zmgr->rwlock, locktype);
+ return (ISC_TF(i < UNREACH_CHACHE_SIZE));
+}
+
+void
+dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
+ isc_sockaddr_t *local, isc_time_t *now)
+{
+ isc_uint32_t seconds = isc_time_seconds(now);
+ isc_uint32_t last = seconds;
+ unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
+
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
+ for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
+ /* Existing entry? */
+ if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
+ isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
+ break;
+ /* Empty slot? */
+ if (zmgr->unreachable[i].expire < seconds)
+ slot = i;
+ /* Least recently used slot? */
+ if (zmgr->unreachable[i].last < last) {
+ last = zmgr->unreachable[i].last;
+ oldest = i;
+ }
+ }
+ if (i < UNREACH_CHACHE_SIZE) {
+ /*
+ * Found a existing entry. Update the expire timer and
+ * last usage timestamps.
+ */
+ zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
+ zmgr->unreachable[i].last = seconds;
+ } else if (slot != UNREACH_CHACHE_SIZE) {
+ /*
+ * Found a empty slot. Add a new entry to the cache.
+ */
+ zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
+ zmgr->unreachable[slot].last = seconds;
+ zmgr->unreachable[slot].remote = *remote;
+ zmgr->unreachable[slot].local = *local;
+ } else {
+ /*
+ * Replace the least recently used entry in the cache.
+ */
+ zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
+ zmgr->unreachable[oldest].last = seconds;
+ zmgr->unreachable[oldest].remote = *remote;
+ zmgr->unreachable[oldest].local = *local;
+ }
+ RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
+}
+
void
dns_zone_forcereload(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
@@ -7813,26 +11096,66 @@ dns_zone_isforced(dns_zone_t *zone) {
isc_result_t
dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
- isc_result_t result = ISC_R_SUCCESS;
+ /*
+ * This function is obsoleted.
+ */
+ UNUSED(zone);
+ UNUSED(on);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_uint64_t *
+dns_zone_getstatscounters(dns_zone_t *zone) {
+ /*
+ * This function is obsoleted.
+ */
+ UNUSED(zone);
+ return (NULL);
+}
+
+void
+dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(zone->stats == NULL);
LOCK_ZONE(zone);
- if (on) {
- if (zone->counters != NULL)
- goto done;
- result = dns_stats_alloccounters(zone->mctx, &zone->counters);
- } else {
- if (zone->counters == NULL)
- goto done;
- dns_stats_freecounters(zone->mctx, &zone->counters);
+ zone->stats = NULL;
+ isc_stats_attach(stats, &zone->stats);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->requeststats_on && stats == NULL)
+ zone->requeststats_on = ISC_FALSE;
+ else if (!zone->requeststats_on && stats != NULL) {
+ if (zone->requeststats == NULL) {
+ isc_stats_attach(stats, &zone->requeststats);
+ zone->requeststats_on = ISC_TRUE;
+ }
}
- done:
UNLOCK_ZONE(zone);
- return (result);
+
+ return;
}
-isc_uint64_t *
-dns_zone_getstatscounters(dns_zone_t *zone) {
- return (zone->counters);
+isc_stats_t *
+dns_zone_getrequeststats(dns_zone_t *zone) {
+ /*
+ * We don't lock zone for efficiency reason. This is not catastrophic
+ * because requeststats must always be valid when requeststats_on is
+ * true.
+ * Some counters may be incremented while requeststats_on is becoming
+ * false, or some cannot be incremented just after the statistics are
+ * installed, but it shouldn't matter much in practice.
+ */
+ if (zone->requeststats_on)
+ return (zone->requeststats);
+ else
+ return (NULL);
}
void
@@ -8043,3 +11366,152 @@ dns_zone_getnotifydelay(dns_zone_t *zone) {
return (zone->notifydelay);
}
+
+isc_result_t
+dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
+ isc_uint16_t keyid, isc_boolean_t delete)
+{
+ isc_result_t result;
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ dns_zone_log(zone, ISC_LOG_NOTICE,
+ "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
+ algorithm, keyid);
+ LOCK_ZONE(zone);
+ result = zone_signwithkey(zone, algorithm, keyid, delete);
+ UNLOCK_ZONE(zone);
+
+ return (result);
+}
+
+static const char *hex = "0123456789ABCDEF";
+
+isc_result_t
+dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
+ isc_result_t result;
+ char salt[255*2+1];
+ unsigned int i, j;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ if (nsec3param->salt_length != 0) {
+ INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
+ for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
+ salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
+ salt[j++] = hex[nsec3param->salt[i] & 0xf];
+ }
+ salt[j] = '\0';
+ } else
+ strcpy(salt, "-");
+ dns_zone_log(zone, ISC_LOG_NOTICE,
+ "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
+ nsec3param->hash, nsec3param->iterations,
+ salt);
+ LOCK_ZONE(zone);
+ result = zone_addnsec3chain(zone, nsec3param);
+ UNLOCK_ZONE(zone);
+
+ return (result);
+}
+
+void
+dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ if (nodes == 0)
+ nodes = 1;
+ zone->nodes = nodes;
+}
+
+void
+dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ /*
+ * We treat signatures as a signed value so explicitly
+ * limit its range here.
+ */
+ if (signatures > ISC_INT32_MAX)
+ signatures = ISC_INT32_MAX;
+ else if (signatures == 0)
+ signatures = 1;
+ zone->signatures = signatures;
+}
+
+void
+dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ zone->privatetype = type;
+}
+
+dns_rdatatype_t
+dns_zone_getprivatetype(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ return (zone->privatetype);
+}
+
+static isc_result_t
+zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
+ isc_boolean_t delete)
+{
+ dns_signing_t *signing;
+ dns_signing_t *current;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_time_t now;
+
+ signing = isc_mem_get(zone->mctx, sizeof *signing);
+ if (signing == NULL)
+ return (ISC_R_NOMEMORY);
+
+ signing->magic = 0;
+ signing->db = NULL;
+ signing->dbiterator = NULL;
+ signing->algorithm = algorithm;
+ signing->keyid = keyid;
+ signing->delete = delete;
+ signing->done = ISC_FALSE;
+
+ TIME_NOW(&now);
+
+ for (current = ISC_LIST_HEAD(zone->signing);
+ current != NULL;
+ current = ISC_LIST_NEXT(current, link)) {
+ if (current->db == zone->db &&
+ current->algorithm == signing->algorithm &&
+ current->keyid == signing->keyid) {
+ if (current->delete != signing->delete)
+ current->done = ISC_TRUE;
+ else
+ goto cleanup;
+ }
+ }
+
+ if (zone->db != NULL) {
+ dns_db_attach(zone->db, &signing->db);
+ result = dns_db_createiterator(signing->db, 0,
+ &signing->dbiterator);
+
+ if (result == ISC_R_SUCCESS)
+ result = dns_dbiterator_first(signing->dbiterator);
+ if (result == ISC_R_SUCCESS) {
+ dns_dbiterator_pause(signing->dbiterator);
+ ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
+ signing = NULL;
+ if (isc_time_isepoch(&zone->signingtime)) {
+ zone->signingtime = now;
+ if (zone->task != NULL)
+ zone_settimer(zone, &now);
+ }
+ }
+ } else
+ result = ISC_R_NOTFOUND;
+
+ cleanup:
+ if (signing != NULL) {
+ dns_db_detach(&signing->db);
+ if (signing->dbiterator != NULL)
+ dns_dbiterator_destroy(&signing->dbiterator);
+ isc_mem_put(zone->mctx, signing, sizeof *signing);
+ }
+ return (result);
+}
diff --git a/lib/dns/zonekey.c b/lib/dns/zonekey.c
index 0ed63bb..bf7474b 100644
--- a/lib/dns/zonekey.c
+++ b/lib/dns/zonekey.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zonekey.c,v 1.5.18.2 2005/04/29 00:16:08 marka Exp $ */
+/* $Id: zonekey.c,v 1.9 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
diff --git a/lib/dns/zt.c b/lib/dns/zt.c
index 4cb8f3f..ed7f28a 100644
--- a/lib/dns/zt.c
+++ b/lib/dns/zt.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zt.c,v 1.38.18.5 2005/11/30 03:44:39 marka Exp $ */
+/* $Id: zt.c,v 1.47 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
@@ -63,7 +63,8 @@ static isc_result_t
freezezones(dns_zone_t *zone, void *uap);
isc_result_t
-dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) {
+dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp)
+{
dns_zt_t *zt;
isc_result_t result;
OpenPOWER on IntegriCloud