summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib
diff options
context:
space:
mode:
authordougb <dougb@FreeBSD.org>2011-07-16 11:12:09 +0000
committerdougb <dougb@FreeBSD.org>2011-07-16 11:12:09 +0000
commitf4894c219c9f0fee1e1d5d793748161bba7d4111 (patch)
tree7873e6a2dac5f9ddbfefa3b07f3cf0570f682321 /contrib/bind9/lib
parent1fab7143c5a0cf07ad84fe178bb29590f5cd2733 (diff)
parent387965661eaa775833b1e35b917f8e568ab7f5c6 (diff)
downloadFreeBSD-src-f4894c219c9f0fee1e1d5d793748161bba7d4111.zip
FreeBSD-src-f4894c219c9f0fee1e1d5d793748161bba7d4111.tar.gz
Upgrade to version 9.8.0-P4
This version has many new features, see /usr/share/doc/bind9/README for details.
Diffstat (limited to 'contrib/bind9/lib')
-rw-r--r--contrib/bind9/lib/bind9/Makefile.in4
-rw-r--r--contrib/bind9/lib/bind9/api4
-rw-r--r--contrib/bind9/lib/bind9/check.c549
-rw-r--r--contrib/bind9/lib/bind9/include/bind9/getaddresses.h2
-rw-r--r--contrib/bind9/lib/dns/Makefile.in44
-rw-r--r--contrib/bind9/lib/dns/acl.c2
-rw-r--r--contrib/bind9/lib/dns/adb.c581
-rw-r--r--contrib/bind9/lib/dns/api4
-rw-r--r--contrib/bind9/lib/dns/byaddr.c47
-rw-r--r--contrib/bind9/lib/dns/cache.c78
-rw-r--r--contrib/bind9/lib/dns/client.c3019
-rw-r--r--contrib/bind9/lib/dns/db.c46
-rw-r--r--contrib/bind9/lib/dns/diff.c19
-rw-r--r--contrib/bind9/lib/dns/dispatch.c93
-rw-r--r--contrib/bind9/lib/dns/dlz.c154
-rw-r--r--contrib/bind9/lib/dns/dns64.c299
-rw-r--r--contrib/bind9/lib/dns/dnssec.c804
-rw-r--r--contrib/bind9/lib/dns/ds.c72
-rw-r--r--contrib/bind9/lib/dns/dst_api.c489
-rw-r--r--contrib/bind9/lib/dns/dst_internal.h40
-rw-r--r--contrib/bind9/lib/dns/dst_openssl.h9
-rw-r--r--contrib/bind9/lib/dns/dst_parse.c193
-rw-r--r--contrib/bind9/lib/dns/dst_parse.h21
-rw-r--r--contrib/bind9/lib/dns/ecdb.c810
-rw-r--r--contrib/bind9/lib/dns/forward.c22
-rw-r--r--contrib/bind9/lib/dns/gen-unix.h2
-rw-r--r--contrib/bind9/lib/dns/gen.c6
-rw-r--r--contrib/bind9/lib/dns/gssapi_link.c91
-rw-r--r--contrib/bind9/lib/dns/gssapictx.c96
-rw-r--r--contrib/bind9/lib/dns/hmac_link.c211
-rw-r--r--contrib/bind9/lib/dns/include/dns/Makefile.in20
-rw-r--r--contrib/bind9/lib/dns/include/dns/acl.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/cache.h39
-rw-r--r--contrib/bind9/lib/dns/include/dns/client.h621
-rw-r--r--contrib/bind9/lib/dns/include/dns/compress.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/db.h49
-rw-r--r--contrib/bind9/lib/dns/include/dns/diff.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/dispatch.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/dlz.h62
-rw-r--r--contrib/bind9/lib/dns/include/dns/dns64.h175
-rw-r--r--contrib/bind9/lib/dns/include/dns/dnssec.h137
-rw-r--r--contrib/bind9/lib/dns/include/dns/ds.h9
-rw-r--r--contrib/bind9/lib/dns/include/dns/ecdb.h52
-rw-r--r--contrib/bind9/lib/dns/include/dns/events.h7
-rw-r--r--contrib/bind9/lib/dns/include/dns/forward.h19
-rw-r--r--contrib/bind9/lib/dns/include/dns/journal.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/keydata.h55
-rw-r--r--contrib/bind9/lib/dns/include/dns/keytable.h212
-rw-r--r--contrib/bind9/lib/dns/include/dns/keyvalues.h8
-rw-r--r--contrib/bind9/lib/dns/include/dns/lib.h18
-rw-r--r--contrib/bind9/lib/dns/include/dns/log.h3
-rw-r--r--contrib/bind9/lib/dns/include/dns/lookup.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/master.h5
-rw-r--r--contrib/bind9/lib/dns/include/dns/masterdump.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/message.h20
-rw-r--r--contrib/bind9/lib/dns/include/dns/name.h84
-rw-r--r--contrib/bind9/lib/dns/include/dns/ncache.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/nsec3.h61
-rw-r--r--contrib/bind9/lib/dns/include/dns/peer.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/private.h55
-rw-r--r--contrib/bind9/lib/dns/include/dns/rbt.h19
-rw-r--r--contrib/bind9/lib/dns/include/dns/rdata.h55
-rw-r--r--contrib/bind9/lib/dns/include/dns/rdataset.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/request.h11
-rw-r--r--contrib/bind9/lib/dns/include/dns/resolver.h28
-rw-r--r--contrib/bind9/lib/dns/include/dns/result.h9
-rw-r--r--contrib/bind9/lib/dns/include/dns/rpz.h189
-rw-r--r--contrib/bind9/lib/dns/include/dns/rriterator.h103
-rw-r--r--contrib/bind9/lib/dns/include/dns/sdb.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/sdlz.h130
-rw-r--r--contrib/bind9/lib/dns/include/dns/secalg.h11
-rw-r--r--contrib/bind9/lib/dns/include/dns/soa.h26
-rw-r--r--contrib/bind9/lib/dns/include/dns/ssu.h31
-rw-r--r--contrib/bind9/lib/dns/include/dns/stats.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/tkey.h14
-rw-r--r--contrib/bind9/lib/dns/include/dns/tsec.h135
-rw-r--r--contrib/bind9/lib/dns/include/dns/tsig.h32
-rw-r--r--contrib/bind9/lib/dns/include/dns/types.h18
-rw-r--r--contrib/bind9/lib/dns/include/dns/validator.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/view.h211
-rw-r--r--contrib/bind9/lib/dns/include/dns/xfrin.h2
-rw-r--r--contrib/bind9/lib/dns/include/dns/zone.h109
-rw-r--r--contrib/bind9/lib/dns/include/dst/dst.h241
-rw-r--r--contrib/bind9/lib/dns/include/dst/gssapi.h13
-rw-r--r--contrib/bind9/lib/dns/iptable.c2
-rw-r--r--contrib/bind9/lib/dns/journal.c8
-rw-r--r--contrib/bind9/lib/dns/keydata.c89
-rw-r--r--contrib/bind9/lib/dns/keytable.c389
-rw-r--r--contrib/bind9/lib/dns/lib.c109
-rw-r--r--contrib/bind9/lib/dns/log.c5
-rw-r--r--contrib/bind9/lib/dns/master.c113
-rw-r--r--contrib/bind9/lib/dns/masterdump.c65
-rw-r--r--contrib/bind9/lib/dns/message.c59
-rw-r--r--contrib/bind9/lib/dns/name.c77
-rw-r--r--contrib/bind9/lib/dns/ncache.c57
-rw-r--r--contrib/bind9/lib/dns/nsec.c2
-rw-r--r--contrib/bind9/lib/dns/nsec3.c490
-rw-r--r--contrib/bind9/lib/dns/openssl_link.c231
-rw-r--r--contrib/bind9/lib/dns/openssldh_link.c45
-rw-r--r--contrib/bind9/lib/dns/openssldsa_link.c47
-rw-r--r--contrib/bind9/lib/dns/opensslgost_link.c418
-rw-r--r--contrib/bind9/lib/dns/opensslrsa_link.c166
-rw-r--r--contrib/bind9/lib/dns/peer.c6
-rw-r--r--contrib/bind9/lib/dns/private.c295
-rw-r--r--contrib/bind9/lib/dns/rbt.c9
-rw-r--r--contrib/bind9/lib/dns/rbtdb.c826
-rw-r--r--contrib/bind9/lib/dns/rcode.c27
-rw-r--r--contrib/bind9/lib/dns/rdata.c143
-rw-r--r--contrib/bind9/lib/dns/rdata/any_255/tsig_250.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/ch_3/a_1.c12
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/afsdb_18.c8
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/cert_37.c10
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/cname_5.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/dlv_32769.c36
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/dname_39.c8
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/dnskey_48.c41
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/ds_43.c32
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/gpos_27.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/hinfo_13.c8
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/hip_55.c506
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/hip_55.h47
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c41
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/isdn_20.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/key_25.c37
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/keydata_65533.c377
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/keydata_65533.h35
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/loc_29.c7
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/mb_7.c15
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/md_3.c15
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/mf_4.c15
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/mg_8.c15
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/minfo_14.c21
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/mr_9.c15
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/mx_15.c13
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/ns_2.c15
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/nsec3_50.c7
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/nsec3param_51.c7
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/nsec_47.c36
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/null_10.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/nxt_30.c8
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/opt_41.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/proforma.c21
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/ptr_12.c14
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/rp_17.c20
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/rrsig_46.c47
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/rt_21.c13
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/sig_24.c8
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/soa_6.c7
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/spf_99.c8
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/sshfp_44.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/tkey_249.c8
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/txt_16.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/unspec_103.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/generic/x25_19.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/hs_4/a_1.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/a6_38.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/a_1.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/aaaa_28.c8
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/apl_42.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c11
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/kx_36.c13
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/naptr_35.c136
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/nsap-ptr_23.c15
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/nsap_22.c9
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/px_26.c13
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/srv_33.c13
-rw-r--r--contrib/bind9/lib/dns/rdata/in_1/wks_11.c7
-rw-r--r--contrib/bind9/lib/dns/rdatalist.c2
-rw-r--r--contrib/bind9/lib/dns/rdataset.c2
-rw-r--r--contrib/bind9/lib/dns/rdataslab.c28
-rw-r--r--contrib/bind9/lib/dns/request.c10
-rw-r--r--contrib/bind9/lib/dns/resolver.c630
-rw-r--r--contrib/bind9/lib/dns/result.c7
-rw-r--r--contrib/bind9/lib/dns/rootns.c2
-rw-r--r--contrib/bind9/lib/dns/rpz.c1168
-rw-r--r--contrib/bind9/lib/dns/rriterator.c202
-rw-r--r--contrib/bind9/lib/dns/sdb.c8
-rw-r--r--contrib/bind9/lib/dns/sdlz.c413
-rw-r--r--contrib/bind9/lib/dns/soa.c40
-rw-r--r--contrib/bind9/lib/dns/spnego.c9
-rw-r--r--contrib/bind9/lib/dns/ssu.c68
-rw-r--r--contrib/bind9/lib/dns/ssu_external.c265
-rw-r--r--contrib/bind9/lib/dns/stats.c2
-rw-r--r--contrib/bind9/lib/dns/time.c2
-rw-r--r--contrib/bind9/lib/dns/tkey.c53
-rw-r--r--contrib/bind9/lib/dns/tsec.c160
-rw-r--r--contrib/bind9/lib/dns/tsig.c367
-rw-r--r--contrib/bind9/lib/dns/validator.c428
-rw-r--r--contrib/bind9/lib/dns/view.c421
-rw-r--r--contrib/bind9/lib/dns/xfrin.c43
-rw-r--r--contrib/bind9/lib/dns/zone.c3909
-rw-r--r--contrib/bind9/lib/export/Makefile.in27
-rw-r--r--contrib/bind9/lib/export/dns/Makefile.in179
-rw-r--r--contrib/bind9/lib/export/dns/include/Makefile.in23
-rw-r--r--contrib/bind9/lib/export/dns/include/dns/Makefile.in56
-rw-r--r--contrib/bind9/lib/export/dns/include/dst/Makefile.in36
-rw-r--r--contrib/bind9/lib/export/irs/Makefile.in86
-rw-r--r--contrib/bind9/lib/export/irs/include/Makefile.in24
-rw-r--r--contrib/bind9/lib/export/irs/include/irs/Makefile.in46
-rw-r--r--contrib/bind9/lib/export/isc/Makefile.in139
-rw-r--r--contrib/bind9/lib/export/isc/include/Makefile.in24
-rw-r--r--contrib/bind9/lib/export/isc/include/isc/Makefile.in66
-rw-r--r--contrib/bind9/lib/export/isc/include/isc/bind9.h30
-rw-r--r--contrib/bind9/lib/export/isc/nls/Makefile.in35
-rw-r--r--contrib/bind9/lib/export/isc/nothreads/Makefile.in40
-rw-r--r--contrib/bind9/lib/export/isc/nothreads/include/Makefile.in24
-rw-r--r--contrib/bind9/lib/export/isc/nothreads/include/isc/Makefile.in36
-rw-r--r--contrib/bind9/lib/export/isc/pthreads/Makefile.in38
-rw-r--r--contrib/bind9/lib/export/isc/pthreads/include/Makefile.in24
-rw-r--r--contrib/bind9/lib/export/isc/pthreads/include/isc/Makefile.in36
-rw-r--r--contrib/bind9/lib/export/isc/unix/Makefile.in57
-rw-r--r--contrib/bind9/lib/export/isc/unix/include/Makefile.in24
-rw-r--r--contrib/bind9/lib/export/isc/unix/include/isc/Makefile.in37
-rw-r--r--contrib/bind9/lib/export/isccfg/Makefile.in83
-rw-r--r--contrib/bind9/lib/export/isccfg/include/Makefile.in24
-rw-r--r--contrib/bind9/lib/export/isccfg/include/isccfg/Makefile.in42
-rw-r--r--contrib/bind9/lib/export/samples/Makefile-postinstall.in78
-rw-r--r--contrib/bind9/lib/export/samples/Makefile.in98
-rw-r--r--contrib/bind9/lib/export/samples/nsprobe.c1220
-rw-r--r--contrib/bind9/lib/export/samples/sample-async.c402
-rw-r--r--contrib/bind9/lib/export/samples/sample-gai.c77
-rw-r--r--contrib/bind9/lib/export/samples/sample-request.c263
-rw-r--r--contrib/bind9/lib/export/samples/sample-update.c755
-rw-r--r--contrib/bind9/lib/export/samples/sample.c378
-rw-r--r--contrib/bind9/lib/irs/Makefile.in80
-rw-r--r--contrib/bind9/lib/irs/api3
-rw-r--r--contrib/bind9/lib/irs/context.c396
-rw-r--r--contrib/bind9/lib/irs/dnsconf.c269
-rw-r--r--contrib/bind9/lib/irs/gai_strerror.c93
-rw-r--r--contrib/bind9/lib/irs/getaddrinfo.c1295
-rw-r--r--contrib/bind9/lib/irs/getnameinfo.c410
-rw-r--r--contrib/bind9/lib/irs/include/Makefile.in24
-rw-r--r--contrib/bind9/lib/irs/include/irs/Makefile.in44
-rw-r--r--contrib/bind9/lib/irs/include/irs/context.h159
-rw-r--r--contrib/bind9/lib/irs/include/irs/dnsconf.h94
-rw-r--r--contrib/bind9/lib/irs/include/irs/netdb.h.in167
-rw-r--r--contrib/bind9/lib/irs/include/irs/platform.h.in45
-rw-r--r--contrib/bind9/lib/irs/include/irs/resconf.h113
-rw-r--r--contrib/bind9/lib/irs/include/irs/types.h31
-rw-r--r--contrib/bind9/lib/irs/include/irs/version.h27
-rw-r--r--contrib/bind9/lib/irs/resconf.c636
-rw-r--r--contrib/bind9/lib/irs/version.c27
-rw-r--r--contrib/bind9/lib/isc/Makefile.in38
-rw-r--r--contrib/bind9/lib/isc/alpha/include/isc/atomic.h2
-rw-r--r--contrib/bind9/lib/isc/api6
-rw-r--r--contrib/bind9/lib/isc/app_api.c136
-rw-r--r--contrib/bind9/lib/isc/assertions.c64
-rw-r--r--contrib/bind9/lib/isc/backtrace-emptytbl.c34
-rw-r--r--contrib/bind9/lib/isc/backtrace.c285
-rw-r--r--contrib/bind9/lib/isc/base32.c2
-rw-r--r--contrib/bind9/lib/isc/base64.c2
-rw-r--r--contrib/bind9/lib/isc/entropy.c2
-rw-r--r--contrib/bind9/lib/isc/hash.c20
-rw-r--r--contrib/bind9/lib/isc/heap.c2
-rw-r--r--contrib/bind9/lib/isc/hmacmd5.c35
-rw-r--r--contrib/bind9/lib/isc/hmacsha.c269
-rw-r--r--contrib/bind9/lib/isc/httpd.c2
-rw-r--r--contrib/bind9/lib/isc/ia64/include/isc/atomic.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/Makefile.in10
-rw-r--r--contrib/bind9/lib/isc/include/isc/app.h173
-rw-r--r--contrib/bind9/lib/isc/include/isc/assertions.h8
-rw-r--r--contrib/bind9/lib/isc/include/isc/backtrace.h131
-rw-r--r--contrib/bind9/lib/isc/include/isc/bind9.h30
-rw-r--r--contrib/bind9/lib/isc/include/isc/buffer.h4
-rw-r--r--contrib/bind9/lib/isc/include/isc/entropy.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/error.h9
-rw-r--r--contrib/bind9/lib/isc/include/isc/file.h31
-rw-r--r--contrib/bind9/lib/isc/include/isc/fsaccess.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/hash.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/heap.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/hmacmd5.h13
-rw-r--r--contrib/bind9/lib/isc/include/isc/hmacsha.h17
-rw-r--r--contrib/bind9/lib/isc/include/isc/lib.h13
-rw-r--r--contrib/bind9/lib/isc/include/isc/log.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/md5.h14
-rw-r--r--contrib/bind9/lib/isc/include/isc/mem.h161
-rw-r--r--contrib/bind9/lib/isc/include/isc/msgs.h6
-rw-r--r--contrib/bind9/lib/isc/include/isc/namespace.h164
-rw-r--r--contrib/bind9/lib/isc/include/isc/netaddr.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/netscope.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/platform.h.in24
-rw-r--r--contrib/bind9/lib/isc/include/isc/portset.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/radix.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/random.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/ratelimiter.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/refcount.h12
-rw-r--r--contrib/bind9/lib/isc/include/isc/result.h5
-rw-r--r--contrib/bind9/lib/isc/include/isc/resultclass.h5
-rw-r--r--contrib/bind9/lib/isc/include/isc/serial.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/sha1.h13
-rw-r--r--contrib/bind9/lib/isc/include/isc/sha2.h17
-rw-r--r--contrib/bind9/lib/isc/include/isc/sockaddr.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/socket.h149
-rw-r--r--contrib/bind9/lib/isc/include/isc/stats.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/symtab.h2
-rw-r--r--contrib/bind9/lib/isc/include/isc/task.h108
-rw-r--r--contrib/bind9/lib/isc/include/isc/timer.h93
-rw-r--r--contrib/bind9/lib/isc/include/isc/types.h9
-rw-r--r--contrib/bind9/lib/isc/include/isc/util.h2
-rw-r--r--contrib/bind9/lib/isc/inet_aton.c4
-rw-r--r--contrib/bind9/lib/isc/inet_ntop.c2
-rw-r--r--contrib/bind9/lib/isc/iterated_hash.c2
-rw-r--r--contrib/bind9/lib/isc/lib.c34
-rw-r--r--contrib/bind9/lib/isc/log.c2
-rw-r--r--contrib/bind9/lib/isc/md5.c30
-rw-r--r--contrib/bind9/lib/isc/mem.c573
-rw-r--r--contrib/bind9/lib/isc/mem_api.c303
-rw-r--r--contrib/bind9/lib/isc/netaddr.c24
-rw-r--r--contrib/bind9/lib/isc/nls/Makefile.in4
-rw-r--r--contrib/bind9/lib/isc/nothreads/Makefile.in8
-rw-r--r--contrib/bind9/lib/isc/powerpc/include/isc/atomic.h2
-rw-r--r--contrib/bind9/lib/isc/print.c2
-rw-r--r--contrib/bind9/lib/isc/pthreads/Makefile.in4
-rw-r--r--contrib/bind9/lib/isc/pthreads/mutex.c2
-rw-r--r--contrib/bind9/lib/isc/radix.c2
-rw-r--r--contrib/bind9/lib/isc/random.c4
-rw-r--r--contrib/bind9/lib/isc/rwlock.c2
-rw-r--r--contrib/bind9/lib/isc/sha1.c41
-rw-r--r--contrib/bind9/lib/isc/sha2.c429
-rw-r--r--contrib/bind9/lib/isc/sockaddr.c8
-rw-r--r--contrib/bind9/lib/isc/socket_api.c216
-rw-r--r--contrib/bind9/lib/isc/stats.c2
-rw-r--r--contrib/bind9/lib/isc/task.c517
-rw-r--r--contrib/bind9/lib/isc/task_api.c216
-rw-r--r--contrib/bind9/lib/isc/task_p.h8
-rw-r--r--contrib/bind9/lib/isc/timer.c346
-rw-r--r--contrib/bind9/lib/isc/timer_api.c144
-rw-r--r--contrib/bind9/lib/isc/timer_p.h8
-rw-r--r--contrib/bind9/lib/isc/unix/Makefile.in4
-rw-r--r--contrib/bind9/lib/isc/unix/app.c540
-rw-r--r--contrib/bind9/lib/isc/unix/dir.c4
-rw-r--r--contrib/bind9/lib/isc/unix/entropy.c4
-rw-r--r--contrib/bind9/lib/isc/unix/file.c90
-rw-r--r--contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c2
-rw-r--r--contrib/bind9/lib/isc/unix/ifiter_ioctl.c2
-rw-r--r--contrib/bind9/lib/isc/unix/include/isc/net.h4
-rw-r--r--contrib/bind9/lib/isc/unix/include/isc/offset.h4
-rw-r--r--contrib/bind9/lib/isc/unix/include/isc/strerror.h4
-rw-r--r--contrib/bind9/lib/isc/unix/include/isc/time.h2
-rw-r--r--contrib/bind9/lib/isc/unix/interfaceiter.c4
-rw-r--r--contrib/bind9/lib/isc/unix/resource.c2
-rw-r--r--contrib/bind9/lib/isc/unix/socket.c952
-rw-r--r--contrib/bind9/lib/isc/unix/socket_p.h9
-rw-r--r--contrib/bind9/lib/isc/unix/strerror.c2
-rw-r--r--contrib/bind9/lib/isccc/Makefile.in6
-rw-r--r--contrib/bind9/lib/isccc/api4
-rw-r--r--contrib/bind9/lib/isccfg/Makefile.in8
-rw-r--r--contrib/bind9/lib/isccfg/aclconf.c25
-rw-r--r--contrib/bind9/lib/isccfg/api6
-rw-r--r--contrib/bind9/lib/isccfg/dnsconf.c69
-rw-r--r--contrib/bind9/lib/isccfg/include/isccfg/aclconf.h14
-rw-r--r--contrib/bind9/lib/isccfg/include/isccfg/cfg.h38
-rw-r--r--contrib/bind9/lib/isccfg/include/isccfg/dnsconf.h35
-rw-r--r--contrib/bind9/lib/isccfg/include/isccfg/grammar.h24
-rw-r--r--contrib/bind9/lib/isccfg/include/isccfg/log.h2
-rw-r--r--contrib/bind9/lib/isccfg/include/isccfg/namedconf.h16
-rw-r--r--contrib/bind9/lib/isccfg/namedconf.c588
-rw-r--r--contrib/bind9/lib/isccfg/parser.c92
-rw-r--r--contrib/bind9/lib/lwres/api4
-rw-r--r--contrib/bind9/lib/lwres/context.c2
-rw-r--r--contrib/bind9/lib/lwres/context_p.h2
-rw-r--r--contrib/bind9/lib/lwres/getaddrinfo.c4
-rw-r--r--contrib/bind9/lib/lwres/getipnode.c2
-rw-r--r--contrib/bind9/lib/lwres/include/lwres/context.h2
-rw-r--r--contrib/bind9/lib/lwres/include/lwres/netdb.h.in2
-rw-r--r--contrib/bind9/lib/lwres/lwconfig.c2
-rw-r--r--contrib/bind9/lib/lwres/man/lwres.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres.html14
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_buffer.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_buffer.html6
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_config.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_config.html12
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_context.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_context.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_gabn.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_gabn.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_gai_strerror.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_gai_strerror.html8
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_getaddrinfo.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_gethostent.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_gethostent.html12
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_getipnode.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_getipnode.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_getnameinfo.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_getnameinfo.html12
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_gnba.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_gnba.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_hstrerror.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_hstrerror.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_inetntop.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_inetntop.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_noop.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_noop.html10
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_packet.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_packet.html8
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_resutil.32
-rw-r--r--contrib/bind9/lib/lwres/man/lwres_resutil.html10
-rw-r--r--contrib/bind9/lib/lwres/print_p.h2
401 files changed, 36976 insertions, 4055 deletions
diff --git a/contrib/bind9/lib/bind9/Makefile.in b/contrib/bind9/lib/bind9/Makefile.in
index e37d524..ffc2ad9 100644
--- a/contrib/bind9/lib/bind9/Makefile.in
+++ b/contrib/bind9/lib/bind9/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -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.11 2007-06-19 23:47:16 tbox Exp $
+# $Id: Makefile.in,v 1.14 2009-12-05 23:31:40 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
diff --git a/contrib/bind9/lib/bind9/api b/contrib/bind9/lib/bind9/api
index f3b0f9f..78dd0b4 100644
--- a/contrib/bind9/lib/bind9/api
+++ b/contrib/bind9/lib/bind9/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 50
-LIBREVISION = 4
+LIBINTERFACE = 80
+LIBREVISION = 1
LIBAGE = 0
diff --git a/contrib/bind9/lib/bind9/check.c b/contrib/bind9/lib/bind9/check.c
index 76ca510..6fa9aa9 100644
--- a/contrib/bind9/lib/bind9/check.c
+++ b/contrib/bind9/lib/bind9/check.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 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: check.c,v 1.95.12.6 2010-03-04 23:47:53 tbox Exp $ */
+/* $Id: check.c,v 1.125 2011-01-07 23:47:07 tbox Exp $ */
/*! \file */
@@ -103,7 +103,7 @@ check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) {
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"rrset-order: invalid name '%s'", str);
@@ -202,7 +202,7 @@ check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) {
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
tresult = dns_name_fromtext(name, &buffer, dns_rootname,
- ISC_FALSE, NULL);
+ 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad name '%s'", str);
@@ -265,7 +265,7 @@ disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) {
str = cfg_obj_asstring(obj);
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
- tresult = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'", str);
@@ -352,7 +352,7 @@ mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
str = cfg_obj_asstring(obj);
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
- result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'", str);
@@ -407,7 +407,7 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
static const char *acls[] = { "allow-query", "allow-query-on",
"allow-query-cache", "allow-query-cache-on",
"blackhole", "match-clients", "match-destinations",
- "sortlist", NULL };
+ "sortlist", "filter-aaaa", NULL };
while (acls[i] != NULL) {
tresult = checkacl(acls[i++], actx, NULL, voptions, config,
@@ -418,6 +418,106 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
return (result);
}
+static const unsigned char zeros[16];
+
+static isc_result_t
+check_dns64(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
+ const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ const cfg_obj_t *dns64 = NULL;
+ const cfg_obj_t *options;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *map, *obj;
+ isc_netaddr_t na, sa;
+ unsigned int prefixlen;
+ int nbytes;
+ int i;
+
+ static const char *acls[] = { "client", "exclude", "mapped", NULL};
+
+ if (voptions != NULL)
+ cfg_map_get(voptions, "dns64", &dns64);
+ if (config != NULL && dns64 == NULL) {
+ options = NULL;
+ cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ cfg_map_get(options, "dns64", &dns64);
+ }
+ if (dns64 == NULL)
+ return (ISC_R_SUCCESS);
+
+ for (element = cfg_list_first(dns64);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ map = cfg_listelt_value(element);
+ obj = cfg_map_getname(map);
+
+ cfg_obj_asnetprefix(obj, &na, &prefixlen);
+ if (na.family != AF_INET6) {
+ cfg_obj_log(map, logctx, ISC_LOG_ERROR,
+ "dns64 requires a IPv6 prefix");
+ result = ISC_R_FAILURE;
+ continue;
+ }
+
+ if (prefixlen != 32 && prefixlen != 40 && prefixlen != 48 &&
+ prefixlen != 56 && prefixlen != 64 && prefixlen != 96) {
+ cfg_obj_log(map, logctx, ISC_LOG_ERROR,
+ "bad prefix length %u [32/40/48/56/64/96]",
+ prefixlen);
+ result = ISC_R_FAILURE;
+ continue;
+ }
+
+ for (i = 0; acls[i] != NULL; i++) {
+ obj = NULL;
+ (void)cfg_map_get(map, acls[i], &obj);
+ if (obj != NULL) {
+ dns_acl_t *acl = NULL;
+ isc_result_t tresult;
+
+ tresult = cfg_acl_fromconfig(obj, config,
+ logctx, actx,
+ mctx, 0, &acl);
+ if (acl != NULL)
+ dns_acl_detach(&acl);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(map, "suffix", &obj);
+ if (obj != NULL) {
+ isc_netaddr_fromsockaddr(&sa, cfg_obj_assockaddr(obj));
+ if (sa.family != AF_INET6) {
+ cfg_obj_log(map, logctx, ISC_LOG_ERROR,
+ "dns64 requires a IPv6 suffix");
+ result = ISC_R_FAILURE;
+ continue;
+ }
+ nbytes = prefixlen / 8 + 4;
+ if (prefixlen >= 32 && prefixlen <= 64)
+ nbytes++;
+ if (memcmp(sa.type.in6.s6_addr, zeros, nbytes) != 0) {
+ char netaddrbuf[ISC_NETADDR_FORMATSIZE];
+ isc_netaddr_format(&sa, netaddrbuf,
+ sizeof(netaddrbuf));
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "bad suffix '%s' leading "
+ "%u octets not zeros",
+ netaddrbuf, nbytes);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+
+ return (result);
+}
+
+
/*
* Check allow-recursion and allow-recursion-on acls, and also log a
* warning if they're inconsistent with the "recursion" option.
@@ -493,6 +593,78 @@ check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
return (result);
}
+static isc_result_t
+check_filteraaaa(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
+ const char *viewname, const cfg_obj_t *config,
+ isc_log_t *logctx, isc_mem_t *mctx)
+{
+ const cfg_obj_t *options, *aclobj, *obj = NULL;
+ dns_acl_t *acl = NULL;
+ isc_result_t result = ISC_R_SUCCESS, tresult;
+ dns_v4_aaaa_t filter;
+ const char *forview = " for view ";
+
+ if (voptions != NULL)
+ cfg_map_get(voptions, "filter-aaaa-on-v4", &obj);
+ if (obj == NULL && config != NULL) {
+ options = NULL;
+ cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ cfg_map_get(options, "filter-aaaa-on-v4", &obj);
+ }
+
+ if (obj == NULL)
+ filter = dns_v4_aaaa_ok; /* default */
+ else if (cfg_obj_isboolean(obj))
+ filter = cfg_obj_asboolean(obj) ? dns_v4_aaaa_filter :
+ dns_v4_aaaa_ok;
+ else
+ filter = dns_v4_aaaa_break_dnssec; /* break-dnssec */
+
+ if (viewname == NULL) {
+ viewname = "";
+ forview = "";
+ }
+
+ aclobj = options = NULL;
+ acl = NULL;
+
+ if (voptions != NULL)
+ cfg_map_get(voptions, "filter-aaaa", &aclobj);
+ if (config != NULL && aclobj == NULL) {
+ options = NULL;
+ cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ cfg_map_get(options, "filter-aaaa", &aclobj);
+ }
+ if (aclobj == NULL)
+ return (result);
+
+ tresult = cfg_acl_fromconfig(aclobj, config, logctx,
+ actx, mctx, 0, &acl);
+
+ if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ } else if (filter != dns_v4_aaaa_ok && dns_acl_isnone(acl)) {
+ cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
+ "both \"filter-aaaa-on-v4 %s;\" and "
+ "\"filter-aaaa\" is 'none;'%s%s",
+ filter == dns_v4_aaaa_break_dnssec ?
+ "break-dnssec" : "yes", forview, viewname);
+ result = ISC_R_FAILURE;
+ } else if (filter == dns_v4_aaaa_ok && !dns_acl_isnone(acl)) {
+ cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
+ "both \"filter-aaaa-on-v4 no;\" and "
+ "\"filter-aaaa\" is set%s%s", forview, viewname);
+ result = ISC_R_FAILURE;
+ }
+
+ if (acl != NULL)
+ dns_acl_detach(&acl);
+
+ return (result);
+}
+
typedef struct {
const char *name;
unsigned int scale;
@@ -524,6 +696,12 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
{ "statistics-interval", 60, 28 * 24 * 60 }, /* 28 days */
};
+ static const char *server_contact[] = {
+ "empty-server", "empty-contact",
+ "dns64-server", "dns64-contact",
+ NULL
+ };
+
/*
* Check that fields specified in units of time other than seconds
* have reasonable values.
@@ -620,7 +798,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
isc_buffer_add(&b, strlen(str));
tresult = dns_name_fromtext(name, &b,
dns_rootname,
- ISC_FALSE, NULL);
+ 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'",
@@ -666,14 +844,24 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
element = cfg_list_next(element))
{
const char *dlv;
+ const cfg_obj_t *anchor;
obj = cfg_listelt_value(element);
dlv = cfg_obj_asstring(cfg_tuple_get(obj, "domain"));
+ anchor = cfg_tuple_get(obj, "trust-anchor");
+
+ /*
+ * If domain is "auto" and trust anchor is missing,
+ * skip remaining tests
+ */
+ if (!strcmp(dlv, "auto") && cfg_obj_isvoid(anchor))
+ continue;
+
isc_buffer_init(&b, dlv, strlen(dlv));
isc_buffer_add(&b, strlen(dlv));
tresult = dns_name_fromtext(name, &b, dns_rootname,
- ISC_TRUE, NULL);
+ 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'", dlv);
@@ -701,19 +889,32 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
if (result == ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
- dlv = cfg_obj_asstring(cfg_tuple_get(obj,
- "trust-anchor"));
- isc_buffer_init(&b, dlv, strlen(dlv));
- isc_buffer_add(&b, strlen(dlv));
- tresult = dns_name_fromtext(name, &b, dns_rootname,
- ISC_TRUE, NULL);
- if (tresult != ISC_R_SUCCESS) {
+
+ if (!cfg_obj_isvoid(anchor)) {
+ dlv = cfg_obj_asstring(anchor);
+ isc_buffer_init(&b, dlv, strlen(dlv));
+ isc_buffer_add(&b, strlen(dlv));
+ tresult = dns_name_fromtext(name, &b,
+ dns_rootname,
+ DNS_NAME_DOWNCASE,
+ NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "bad domain name '%s'",
+ dlv);
+ if (result == ISC_R_SUCCESS)
+ result = tresult;
+ }
+ } else {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
- "bad domain name '%s'", dlv);
+ "dnssec-lookaside requires "
+ "either 'auto' or a domain and "
+ "trust anchor");
if (result == ISC_R_SUCCESS)
- result = tresult;
+ result = ISC_R_FAILURE;
}
}
+
if (symtab != NULL)
isc_symtab_destroy(&symtab);
}
@@ -743,38 +944,29 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
}
/*
- * Check empty zone configuration.
+ * Check server/contacts for syntactic validity.
*/
- obj = NULL;
- (void)cfg_map_get(options, "empty-server", &obj);
- if (obj != NULL) {
- str = cfg_obj_asstring(obj);
- isc_buffer_init(&b, str, strlen(str));
- isc_buffer_add(&b, strlen(str));
- tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
- dns_rootname, ISC_FALSE, NULL);
- if (tresult != ISC_R_SUCCESS) {
- cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
- "empty-server: invalid name '%s'", str);
- result = ISC_R_FAILURE;
- }
- }
-
- obj = NULL;
- (void)cfg_map_get(options, "empty-contact", &obj);
- if (obj != NULL) {
- str = cfg_obj_asstring(obj);
- isc_buffer_init(&b, str, strlen(str));
- isc_buffer_add(&b, strlen(str));
- tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
- dns_rootname, ISC_FALSE, NULL);
- if (tresult != ISC_R_SUCCESS) {
- cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
- "empty-contact: invalid name '%s'", str);
- result = ISC_R_FAILURE;
+ for (i= 0; server_contact[i] != NULL; i++) {
+ obj = NULL;
+ (void)cfg_map_get(options, server_contact[i], &obj);
+ if (obj != NULL) {
+ str = cfg_obj_asstring(obj);
+ isc_buffer_init(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ tresult = dns_name_fromtext(dns_fixedname_name(&fixed),
+ &b, dns_rootname, 0, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "%s: invalid name '%s'",
+ server_contact[i], str);
+ result = ISC_R_FAILURE;
+ }
}
}
+ /*
+ * Check empty zone configuration.
+ */
obj = NULL;
(void)cfg_map_get(options, "disable-empty-zone", &obj);
for (element = cfg_list_first(obj);
@@ -786,7 +978,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"disable-empty-zone: invalid name '%s'",
@@ -950,6 +1142,12 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
const char *str;
isc_buffer_t b;
+ /* Check for "update-policy local;" */
+ if (cfg_obj_isstring(policy) &&
+ strcmp("local", cfg_obj_asstring(policy)) == 0)
+ return (ISC_R_SUCCESS);
+
+ /* Now check the grant policy */
for (element = cfg_list_first(policy);
element != NULL;
element = cfg_list_next(element))
@@ -965,24 +1163,28 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
"'%s' is not a valid name", str);
result = tresult;
}
- dns_fixedname_init(&fixed);
- str = cfg_obj_asstring(dname);
- isc_buffer_init(&b, str, strlen(str));
- isc_buffer_add(&b, strlen(str));
- tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
- dns_rootname, ISC_FALSE, NULL);
- if (tresult != ISC_R_SUCCESS) {
- cfg_obj_log(dname, logctx, ISC_LOG_ERROR,
- "'%s' is not a valid name", str);
- result = tresult;
+ if (tresult == ISC_R_SUCCESS &&
+ strcasecmp(cfg_obj_asstring(matchtype), "zonesub") != 0) {
+ dns_fixedname_init(&fixed);
+ str = cfg_obj_asstring(dname);
+ isc_buffer_init(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ tresult = dns_name_fromtext(dns_fixedname_name(&fixed),
+ &b, dns_rootname, 0, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(dname, logctx, ISC_LOG_ERROR,
+ "'%s' is not a valid name", str);
+ result = tresult;
+ }
}
+
if (tresult == ISC_R_SUCCESS &&
strcasecmp(cfg_obj_asstring(matchtype), "wildcard") == 0 &&
!dns_name_iswildcard(dns_fixedname_name(&fixed))) {
@@ -1020,7 +1222,8 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
#define HINTZONE 8
#define FORWARDZONE 16
#define DELEGATIONZONE 32
-#define CHECKACL 64
+#define STATICSTUBZONE 64
+#define CHECKACL 128
typedef struct {
const char *name;
@@ -1033,7 +1236,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
dns_rdataclass_t defclass, cfg_aclconfctx_t *actx,
isc_log_t *logctx, isc_mem_t *mctx)
{
- const char *zname;
+ const char *znamestr;
const char *typestr;
unsigned int ztype;
const cfg_obj_t *zoptions;
@@ -1043,11 +1246,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
unsigned int i;
dns_rdataclass_t zclass;
dns_fixedname_t fixedname;
+ dns_name_t *zname = NULL;
isc_buffer_t b;
isc_boolean_t root = ISC_FALSE;
+ const cfg_listelt_t *element;
static optionstable options[] = {
- { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL },
+ { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL |
+ STATICSTUBZONE },
{ "allow-notify", SLAVEZONE | CHECKACL },
{ "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL },
{ "notify", MASTERZONE | SLAVEZONE },
@@ -1070,12 +1276,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
{ "min-retry-time", SLAVEZONE | STUBZONE },
{ "max-refresh-time", SLAVEZONE | STUBZONE },
{ "min-refresh-time", SLAVEZONE | STUBZONE },
+ { "dnssec-secure-to-insecure", MASTERZONE },
{ "sig-validity-interval", MASTERZONE },
{ "sig-re-signing-interval", MASTERZONE },
{ "sig-signing-nodes", MASTERZONE },
{ "sig-signing-type", MASTERZONE },
{ "sig-signing-signatures", MASTERZONE },
- { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE },
+ { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE |
+ STATICSTUBZONE},
{ "allow-update", MASTERZONE | CHECKACL },
{ "allow-update-forwarding", SLAVEZONE | CHECKACL },
{ "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
@@ -1089,12 +1297,17 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
{ "key-directory", MASTERZONE },
{ "check-wildcard", MASTERZONE },
{ "check-mx", MASTERZONE },
+ { "check-dup-records", MASTERZONE },
{ "integrity-check", MASTERZONE },
{ "check-mx-cname", MASTERZONE },
{ "check-srv-cname", MASTERZONE },
{ "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
{ "update-check-ksk", MASTERZONE },
+ { "dnssec-dnskey-kskonly", MASTERZONE },
+ { "auto-dnssec", MASTERZONE },
{ "try-tcp-refresh", SLAVEZONE },
+ { "server-addresses", STATICSTUBZONE },
+ { "server-names", STATICSTUBZONE },
};
static optionstable dialups[] = {
@@ -1104,7 +1317,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
{ "passive", SLAVEZONE | STUBZONE },
};
- zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+ znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
zoptions = cfg_tuple_get(zconfig, "options");
@@ -1112,7 +1325,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
(void)cfg_map_get(zoptions, "type", &obj);
if (obj == NULL) {
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
- "zone '%s': type not present", zname);
+ "zone '%s': type not present", znamestr);
return (ISC_R_FAILURE);
}
@@ -1123,6 +1336,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
ztype = SLAVEZONE;
else if (strcasecmp(typestr, "stub") == 0)
ztype = STUBZONE;
+ else if (strcasecmp(typestr, "static-stub") == 0)
+ ztype = STATICSTUBZONE;
else if (strcasecmp(typestr, "forward") == 0)
ztype = FORWARDZONE;
else if (strcasecmp(typestr, "hint") == 0)
@@ -1132,7 +1347,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
else {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"zone '%s': invalid type %s",
- zname, typestr);
+ znamestr, typestr);
return (ISC_R_FAILURE);
}
@@ -1146,14 +1361,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
if (result != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"zone '%s': invalid class %s",
- zname, r.base);
+ znamestr, r.base);
return (ISC_R_FAILURE);
}
if (zclass != defclass) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"zone '%s': class '%s' does not "
"match view/default class",
- zname, r.base);
+ znamestr, r.base);
return (ISC_R_FAILURE);
}
}
@@ -1164,26 +1379,25 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
* deals with strings.
*/
dns_fixedname_init(&fixedname);
- isc_buffer_init(&b, zname, strlen(zname));
- isc_buffer_add(&b, strlen(zname));
+ isc_buffer_init(&b, znamestr, strlen(znamestr));
+ isc_buffer_add(&b, strlen(znamestr));
tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
- dns_rootname, ISC_TRUE, NULL);
+ dns_rootname, DNS_NAME_DOWNCASE, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
- "zone '%s': is not a valid name", zname);
+ "zone '%s': is not a valid name", znamestr);
result = ISC_R_FAILURE;
} else {
char namebuf[DNS_NAME_FORMATSIZE];
- dns_name_format(dns_fixedname_name(&fixedname),
- namebuf, sizeof(namebuf));
+ zname = dns_fixedname_name(&fixedname);
+ dns_name_format(zname, namebuf, sizeof(namebuf));
tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : 2,
symtab, "zone '%s': already exists "
"previous definition: %s:%u", logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
- if (dns_name_equal(dns_fixedname_name(&fixedname),
- dns_rootname))
+ if (dns_name_equal(zname, dns_rootname))
root = ISC_TRUE;
}
@@ -1202,13 +1416,15 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"option '%s' is not allowed "
"in '%s' zone '%s'",
- options[i].name, typestr, zname);
+ options[i].name, typestr,
+ znamestr);
result = ISC_R_FAILURE;
} else
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
"option '%s' is not allowed "
"in '%s' zone '%s'",
- options[i].name, typestr, zname);
+ options[i].name, typestr,
+ znamestr);
}
obj = NULL;
if ((options[i].allowed & ztype) != 0 &&
@@ -1230,7 +1446,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) {
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
"zone '%s': missing 'masters' entry",
- zname);
+ znamestr);
result = ISC_R_FAILURE;
} else {
isc_uint32_t count;
@@ -1241,7 +1457,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
if (tresult == ISC_R_SUCCESS && count == 0) {
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
"zone '%s': empty 'masters' entry",
- zname);
+ znamestr);
result = ISC_R_FAILURE;
}
}
@@ -1251,7 +1467,10 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
* Master zones can't have both "allow-update" and "update-policy".
*/
if (ztype == MASTERZONE) {
- isc_result_t res1, res2;
+ isc_result_t res1, res2, res3;
+ const char *arg;
+ isc_boolean_t ddns;
+
obj = NULL;
res1 = cfg_map_get(zoptions, "allow-update", &obj);
obj = NULL;
@@ -1260,11 +1479,32 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"zone '%s': 'allow-update' is ignored "
"when 'update-policy' is present",
- zname);
+ znamestr);
result = ISC_R_FAILURE;
} else if (res2 == ISC_R_SUCCESS &&
check_update_policy(obj, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
+ ddns = ISC_TF(res1 == ISC_R_SUCCESS || res2 == ISC_R_SUCCESS);
+
+ obj = NULL;
+ arg = "off";
+ res3 = cfg_map_get(zoptions, "auto-dnssec", &obj);
+ if (res3 == ISC_R_SUCCESS)
+ arg = cfg_obj_asstring(obj);
+ if (strcasecmp(arg, "off") != 0 && !ddns) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "'auto-dnssec %s;' requires "
+ "dynamic DNS to be configured in the zone",
+ arg);
+ result = ISC_R_FAILURE;
+ }
+ if (strcasecmp(arg, "create") == 0) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "'auto-dnssec create;' is not "
+ "yet implemented");
+ result = ISC_R_FAILURE;
+ }
+
obj = NULL;
res1 = cfg_map_get(zoptions, "sig-signing-type", &obj);
if (res1 == ISC_R_SUCCESS) {
@@ -1298,7 +1538,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
"dialup type '%s' is not "
"allowed in '%s' "
"zone '%s'",
- str, typestr, zname);
+ str, typestr, znamestr);
result = ISC_R_FAILURE;
}
break;
@@ -1306,7 +1546,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
if (i == sizeof(dialups) / sizeof(dialups[0])) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"invalid dialup type '%s' in zone "
- "'%s'", str, zname);
+ "'%s'", str, znamestr);
result = ISC_R_FAILURE;
}
}
@@ -1330,6 +1570,78 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
result = ISC_R_FAILURE;
/*
+ * Check validity of static stub server addresses.
+ */
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "server-addresses", &obj);
+ if (ztype == STATICSTUBZONE && obj != NULL) {
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ isc_sockaddr_t sa;
+ isc_netaddr_t na;
+ obj = cfg_listelt_value(element);
+ sa = *cfg_obj_assockaddr(obj);
+
+ if (isc_sockaddr_getport(&sa) != 0) {
+ result = ISC_R_FAILURE;
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "port is not configurable for "
+ "static stub server-addresses");
+ }
+
+ isc_netaddr_fromsockaddr(&na, &sa);
+ if (isc_netaddr_getzone(&na) != 0) {
+ result = ISC_R_FAILURE;
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "scoped address is not allowed "
+ "for static stub "
+ "server-addresses");
+ }
+ }
+ }
+
+ /*
+ * Check validity of static stub server names.
+ */
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "server-names", &obj);
+ if (zname != NULL && ztype == STATICSTUBZONE && obj != NULL) {
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const char *snamestr;
+ dns_fixedname_t fixed_sname;
+ isc_buffer_t b2;
+ dns_name_t *sname;
+
+ obj = cfg_listelt_value(element);
+ snamestr = cfg_obj_asstring(obj);
+
+ dns_fixedname_init(&fixed_sname);
+ isc_buffer_init(&b2, snamestr, strlen(snamestr));
+ isc_buffer_add(&b2, strlen(snamestr));
+ sname = dns_fixedname_name(&fixed_sname);
+ tresult = dns_name_fromtext(sname, &b2, dns_rootname,
+ 0, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
+ "server-name '%s' is not a valid "
+ "name", snamestr);
+ result = ISC_R_FAILURE;
+ } else if (dns_name_issubdomain(sname, zname)) {
+ cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
+ "server-name '%s' must not be a "
+ "subdomain of zone name '%s'",
+ snamestr, znamestr);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+
+ /*
* Check various options.
*/
tresult = check_options(zoptions, logctx, mctx);
@@ -1352,7 +1664,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
(ztype == MASTERZONE || ztype == HINTZONE)) {
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
"zone '%s': missing 'file' entry",
- zname);
+ znamestr);
result = tresult;
}
}
@@ -1374,6 +1686,9 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
const char *algorithm;
int i;
size_t len = 0;
+ isc_result_t result;
+ isc_buffer_t buf;
+ unsigned char secretbuf[1024];
static const algorithmtable algorithms[] = {
{ "hmac-md5", 128 },
{ "hmac-md5.sig-alg.reg.int", 0 },
@@ -1396,6 +1711,14 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
return (ISC_R_FAILURE);
}
+ isc_buffer_init(&buf, secretbuf, sizeof(secretbuf));
+ result = isc_base64_decodestring(cfg_obj_asstring(secretobj), &buf);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(secretobj, logctx, ISC_LOG_ERROR,
+ "bad secret '%s'", isc_result_totext(result));
+ return (result);
+ }
+
algorithm = cfg_obj_asstring(algobj);
for (i = 0; algorithms[i].name != NULL; i++) {
len = strlen(algorithms[i].name);
@@ -1480,7 +1803,7 @@ check_keylist(const cfg_obj_t *keys, isc_symtab_t *symtab,
isc_buffer_init(&b, keyid, strlen(keyid));
isc_buffer_add(&b, strlen(keyid));
tresult = dns_name_fromtext(name, &b, dns_rootname,
- ISC_FALSE, NULL);
+ 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"key '%s': bad key name", keyid);
@@ -1650,7 +1973,7 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions,
isc_buffer_add(&b, strlen(keyval));
keyname = dns_fixedname_name(&fname);
tresult = dns_name_fromtext(keyname, &b, dns_rootname,
- ISC_FALSE, NULL);
+ 0, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(keys, logctx, ISC_LOG_ERROR,
"bad key name '%s'", keyval);
@@ -1670,7 +1993,8 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions,
}
static isc_result_t
-check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx)
+check_trusted_key(const cfg_obj_t *key, isc_boolean_t managed,
+ isc_log_t *logctx)
{
const char *keystr, *keynamestr;
dns_fixedname_t fkeyname;
@@ -1704,6 +2028,19 @@ check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx)
result = ISC_R_FAILURE;
}
+ if (managed) {
+ const char *initmethod;
+ initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
+
+ if (strcasecmp(initmethod, "initial-key") != 0) {
+ cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+ "managed key '%s': "
+ "invalid initialization method '%s'",
+ keynamestr, initmethod);
+ result = ISC_R_FAILURE;
+ }
+ }
+
isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
@@ -1719,7 +2056,8 @@ check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx)
if ((alg == DST_ALG_RSASHA1 || alg == DST_ALG_RSAMD5) &&
r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
- "trusted key '%s' has a weak exponent",
+ "%s key '%s' has a weak exponent",
+ managed ? "managed" : "trusted",
keynamestr);
}
@@ -1892,12 +2230,32 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
element2 != NULL;
element2 = cfg_list_next(element2)) {
obj = cfg_listelt_value(element2);
- tresult = check_trusted_key(obj, logctx);
+ tresult = check_trusted_key(obj, ISC_FALSE, logctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
}
}
+ keys = NULL;
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "managed-keys", &keys);
+ if (keys == NULL)
+ (void)cfg_map_get(config, "managed-keys", &keys);
+
+ for (element = cfg_list_first(keys);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *keylist = cfg_listelt_value(element);
+ for (element2 = cfg_list_first(keylist);
+ element2 != NULL;
+ element2 = cfg_list_next(element2)) {
+ obj = cfg_listelt_value(element2);
+ tresult = check_trusted_key(obj, ISC_TRUE, logctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ }
/*
* Check options.
*/
@@ -1917,7 +2275,16 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
if (tresult != ISC_R_SUCCESS)
result = tresult;
- cfg_aclconfctx_destroy(&actx);
+ tresult = check_filteraaaa(&actx, voptions, viewname, config,
+ logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+
+ tresult = check_dns64(&actx, voptions, config, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+
+ cfg_aclconfctx_clear(&actx);
return (result);
}
@@ -2162,7 +2529,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
result = tresult;
}
}
- cfg_aclconfctx_destroy(&actx);
+ cfg_aclconfctx_clear(&actx);
return (result);
}
diff --git a/contrib/bind9/lib/bind9/include/bind9/getaddresses.h b/contrib/bind9/lib/bind9/include/bind9/getaddresses.h
index 677ced2..9ad8045 100644
--- a/contrib/bind9/lib/bind9/include/bind9/getaddresses.h
+++ b/contrib/bind9/lib/bind9/include/bind9/getaddresses.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: getaddresses.h,v 1.9.332.2 2009-01-18 23:47:35 tbox Exp $ */
+/* $Id: getaddresses.h,v 1.11 2009-01-17 23:47:42 tbox Exp $ */
#ifndef BIND9_GETADDRESSES_H
#define BIND9_GETADDRESSES_H 1
diff --git a/contrib/bind9/lib/dns/Makefile.in b/contrib/bind9/lib/dns/Makefile.in
index dfb8d7f..45c5c2a 100644
--- a/contrib/bind9/lib/dns/Makefile.in
+++ b/contrib/bind9/lib/dns/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2003 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -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.163.50.2 2010-06-09 23:48:16 tbox Exp $
+# $Id: Makefile.in,v 1.176 2011-01-13 01:59:27 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -34,8 +34,7 @@ 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_PKCS11@ @USE_GSSAPI@ \
- ${USE_ISC_SPNEGO}
+CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@ ${USE_ISC_SPNEGO}
CWARNINGS =
@@ -48,7 +47,7 @@ LIBS = @LIBS@
# Alphabetically
OPENSSLLINKOBJS = openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \
- opensslrsa_link.@O@
+ opensslgost_link.@O@ opensslrsa_link.@O@
DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \
dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
@@ -58,24 +57,26 @@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \
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@ iptable.@O@ journal.@O@ \
- keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
+ dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ \
+ journal.@O@ keydata.@O@ keytable.@O@ \
+ lib.@O@ log.@O@ lookup.@O@ \
master.@O@ masterdump.@O@ message.@O@ \
- name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ portlist.@O@ \
+ name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \
+ portlist.@O@ private.@O@ \
rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@O@ \
- rdatalist.@O@ \
- rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ request.@O@ \
- resolver.@O@ result.@O@ rootns.@O@ sdb.@O@ sdlz.@O@ \
- soa.@O@ ssu.@O@ \
+ rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \
+ request.@O@ resolver.@O@ result.@O@ rootns.@O@ rpz.@O@ \
+ rriterator.@O@ sdb.@O@ \
+ sdlz.@O@ soa.@O@ ssu.@O@ ssu_external.@O@ \
stats.@O@ tcpmsg.@O@ time.@O@ timer.@O@ tkey.@O@ \
- tsig.@O@ ttl.@O@ validator.@O@ \
+ tsec.@O@ tsig.@O@ ttl.@O@ validator.@O@ \
version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ zt.@O@
OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS}
# Alphabetically
-OPENSSLLINKSRCS = openssl_link.c openssldh_link.c \
- openssldsa_link.c opensslrsa_link.c
+OPENSSLLINKSRCS = openssl_link.c openssldh_link.c openssldsa_link.c \
+ opensslgost_link.c opensslrsa_link.c
DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \
dst_api.c dst_lib.c dst_parse.c \
@@ -85,17 +86,16 @@ DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \
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 iptable.c journal.c \
- keytable.c lib.c log.c lookup.c \
+ dlz.c dns64.c dnssec.c ds.c forward.c iptable.c journal.c \
+ keydata.c keytable.c lib.c log.c lookup.c \
master.c masterdump.c message.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 \
+ rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \
rdataset.c rdatasetiter.c rdataslab.c request.c \
- resolver.c result.c rootns.c sdb.c sdlz.c \
- soa.c ssu.c \
+ resolver.c result.c rootns.c rpz.c rriterator.c \
+ sdb.c sdlz.c soa.c ssu.c ssu_external.c \
stats.c tcpmsg.c time.c timer.c tkey.c \
- tsig.c ttl.c validator.c \
+ tsec.c tsig.c ttl.c validator.c \
version.c view.c xfrin.c zone.c zonekey.c zt.c ${OTHERSRCS}
SRCS = ${DSTSRCS} ${DNSSRCS}
diff --git a/contrib/bind9/lib/dns/acl.c b/contrib/bind9/lib/dns/acl.c
index cfb7fd8..118e394 100644
--- a/contrib/bind9/lib/dns/acl.c
+++ b/contrib/bind9/lib/dns/acl.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acl.c,v 1.50.44.3 2009-01-18 23:47:35 tbox Exp $ */
+/* $Id: acl.c,v 1.53 2009-01-17 23:47:42 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/dns/adb.c b/contrib/bind9/lib/dns/adb.c
index cd9cadf..fcc2dd8 100644
--- a/contrib/bind9/lib/dns/adb.c
+++ b/contrib/bind9/lib/dns/adb.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.c,v 1.243.42.6 2010-08-11 23:45:49 tbox Exp $ */
+/* $Id: adb.c,v 1.254 2010-12-21 23:47:08 tbox Exp $ */
/*! \file
*
@@ -66,13 +66,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 */
-
-/*!
* For type 3 negative cache entries, we will remember that the address is
* broken for this long. XXXMLG This is also used for actual addresses, too.
* The intent is to keep us from constantly asking about A/AAAA records
@@ -139,30 +132,37 @@ struct dns_adb {
*
* XXXRTH Have a per-bucket structure that contains all of these?
*/
- dns_adbnamelist_t names[NBUCKETS];
- dns_adbnamelist_t deadnames[NBUCKETS];
- /*% See dns_adbnamelist_t */
- isc_mutex_t namelocks[NBUCKETS];
- /*% See dns_adbnamelist_t */
- isc_boolean_t name_sd[NBUCKETS];
- /*% See dns_adbnamelist_t */
- unsigned int name_refcnt[NBUCKETS];
+ unsigned int nnames;
+ isc_mutex_t namescntlock;
+ unsigned int namescnt;
+ dns_adbnamelist_t *names;
+ dns_adbnamelist_t *deadnames;
+ isc_mutex_t *namelocks;
+ isc_boolean_t *name_sd;
+ unsigned int *name_refcnt;
/*!
- * Bucketized locks for entries.
+ * Bucketized locks and lists for entries.
*
* XXXRTH Have a per-bucket structure that contains all of these?
*/
- 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];
+ unsigned int nentries;
+ isc_mutex_t entriescntlock;
+ unsigned int entriescnt;
+ dns_adbentrylist_t *entries;
+ dns_adbentrylist_t *deadentries;
+ isc_mutex_t *entrylocks;
+ isc_boolean_t *entry_sd; /*%< shutting down */
+ unsigned int *entry_refcnt;
isc_event_t cevent;
isc_boolean_t cevent_sent;
isc_boolean_t shutting_down;
isc_eventlist_t whenshutdown;
+ isc_event_t growentries;
+ isc_boolean_t growentries_sent;
+ isc_event_t grownames;
+ isc_boolean_t grownames_sent;
};
/*
@@ -484,6 +484,322 @@ ttlclamp(dns_ttl_t ttl) {
}
/*
+ * Hashing is most efficient if the number of buckets is prime.
+ * The sequence below is the closest previous primes to 2^n and
+ * 1.5 * 2^n, for values of n from 10 to 28. (The tables will
+ * no longer grow beyond 2^28 entries.)
+ */
+static const unsigned nbuckets[] = { 1021, 1531, 2039, 3067, 4093, 6143,
+ 8191, 12281, 16381, 24571, 32749,
+ 49193, 65521, 98299, 131071, 199603,
+ 262139, 393209, 524287, 768431, 1048573,
+ 1572853, 2097143, 3145721, 4194301,
+ 6291449, 8388593, 12582893, 16777213,
+ 25165813, 33554393, 50331599, 67108859,
+ 100663291, 134217689, 201326557,
+ 268535431, 0 };
+
+static void
+grow_entries(isc_task_t *task, isc_event_t *ev) {
+ dns_adb_t *adb;
+ dns_adbentry_t *e;
+ dns_adbentrylist_t *newdeadentries = NULL;
+ dns_adbentrylist_t *newentries = NULL;
+ isc_boolean_t *newentry_sd = NULL;
+ isc_mutex_t *newentrylocks = NULL;
+ isc_result_t result;
+ unsigned int *newentry_refcnt = NULL;
+ unsigned int i, n, bucket;
+
+ adb = ev->ev_arg;
+ INSIST(DNS_ADB_VALID(adb));
+
+ isc_event_free(&ev);
+
+ isc_task_beginexclusive(task);
+
+ i = 0;
+ while (nbuckets[i] != 0 && adb->nentries >= nbuckets[i])
+ i++;
+ if (nbuckets[i] != 0)
+ n = nbuckets[i];
+ else
+ goto done;
+
+ DP(ISC_LOG_INFO, "adb: grow_entries to %u starting", n);
+
+ /*
+ * Are we shutting down?
+ */
+ for (i = 0; i < adb->nentries; i++)
+ if (adb->entry_sd[i])
+ goto cleanup;
+
+ /*
+ * Grab all the resources we need.
+ */
+ newentries = isc_mem_get(adb->mctx, sizeof(*newentries) * n);
+ newdeadentries = isc_mem_get(adb->mctx, sizeof(*newdeadentries) * n);
+ newentrylocks = isc_mem_get(adb->mctx, sizeof(*newentrylocks) * n);
+ newentry_sd = isc_mem_get(adb->mctx, sizeof(*newentry_sd) * n);
+ newentry_refcnt = isc_mem_get(adb->mctx, sizeof(*newentry_refcnt) * n);
+ if (newentries == NULL || newdeadentries == NULL ||
+ newentrylocks == NULL || newentry_sd == NULL ||
+ newentry_refcnt == NULL)
+ goto cleanup;
+
+ /*
+ * Initialise the new resources.
+ */
+ result = isc_mutexblock_init(newentrylocks, n);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ for (i = 0; i < n; i++) {
+ ISC_LIST_INIT(newentries[i]);
+ ISC_LIST_INIT(newdeadentries[i]);
+ newentry_sd[i] = ISC_FALSE;
+ newentry_refcnt[i] = 0;
+ adb->irefcnt++;
+ }
+
+ /*
+ * Move entries to new arrays.
+ */
+ for (i = 0; i < adb->nentries; i++) {
+ e = ISC_LIST_HEAD(adb->entries[i]);
+ while (e != NULL) {
+ ISC_LIST_UNLINK(adb->entries[i], e, plink);
+ bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
+ e->lock_bucket = bucket;
+ ISC_LIST_APPEND(newentries[bucket], e, plink);
+ INSIST(adb->entry_refcnt[i] > 0);
+ adb->entry_refcnt[i]--;
+ newentry_refcnt[bucket]++;
+ e = ISC_LIST_HEAD(adb->entries[i]);
+ }
+ e = ISC_LIST_HEAD(adb->deadentries[i]);
+ while (e != NULL) {
+ ISC_LIST_UNLINK(adb->deadentries[i], e, plink);
+ bucket = isc_sockaddr_hash(&e->sockaddr, ISC_TRUE) % n;
+ e->lock_bucket = bucket;
+ ISC_LIST_APPEND(newdeadentries[bucket], e, plink);
+ INSIST(adb->entry_refcnt[i] > 0);
+ adb->entry_refcnt[i]--;
+ newentry_refcnt[bucket]++;
+ e = ISC_LIST_HEAD(adb->deadentries[i]);
+ }
+ INSIST(adb->entry_refcnt[i] == 0);
+ adb->irefcnt--;
+ }
+
+ /*
+ * Cleanup old resources.
+ */
+ DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
+ isc_mem_put(adb->mctx, adb->entries,
+ sizeof(*adb->entries) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->deadentries,
+ sizeof(*adb->deadentries) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entrylocks,
+ sizeof(*adb->entrylocks) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entry_sd,
+ sizeof(*adb->entry_sd) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entry_refcnt,
+ sizeof(*adb->entry_refcnt) * adb->nentries);
+
+ /*
+ * Install new resources.
+ */
+ adb->entries = newentries;
+ adb->deadentries = newdeadentries;
+ adb->entrylocks = newentrylocks;
+ adb->entry_sd = newentry_sd;
+ adb->entry_refcnt = newentry_refcnt;
+ adb->nentries = n;
+
+ /*
+ * Only on success do we set adb->growentries_sent to ISC_FALSE.
+ * This will prevent us being continuously being called on error.
+ */
+ adb->growentries_sent = ISC_FALSE;
+ goto done;
+
+ cleanup:
+ if (newentries != NULL)
+ isc_mem_put(adb->mctx, newentries,
+ sizeof(*newentries) * n);
+ if (newdeadentries != NULL)
+ isc_mem_put(adb->mctx, newdeadentries,
+ sizeof(*newdeadentries) * n);
+ if (newentrylocks != NULL)
+ isc_mem_put(adb->mctx, newentrylocks,
+ sizeof(*newentrylocks) * n);
+ if (newentry_sd != NULL)
+ isc_mem_put(adb->mctx, newentry_sd,
+ sizeof(*newentry_sd) * n);
+ if (newentry_refcnt != NULL)
+ isc_mem_put(adb->mctx, newentry_refcnt,
+ sizeof(*newentry_refcnt) * n);
+ done:
+ isc_task_endexclusive(task);
+
+ LOCK(&adb->lock);
+ if (dec_adb_irefcnt(adb))
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+ DP(ISC_LOG_INFO, "adb: grow_entries finished");
+}
+
+static void
+grow_names(isc_task_t *task, isc_event_t *ev) {
+ dns_adb_t *adb;
+ dns_adbname_t *name;
+ dns_adbnamelist_t *newdeadnames = NULL;
+ dns_adbnamelist_t *newnames = NULL;
+ isc_boolean_t *newname_sd = NULL;
+ isc_mutex_t *newnamelocks = NULL;
+ isc_result_t result;
+ unsigned int *newname_refcnt = NULL;
+ unsigned int i, n, bucket;
+
+ adb = ev->ev_arg;
+ INSIST(DNS_ADB_VALID(adb));
+
+ isc_event_free(&ev);
+
+ isc_task_beginexclusive(task);
+
+ i = 0;
+ while (nbuckets[i] != 0 && adb->nnames >= nbuckets[i])
+ i++;
+ if (nbuckets[i] != 0)
+ n = nbuckets[i];
+ else
+ goto done;
+
+ DP(ISC_LOG_INFO, "adb: grow_names to %u starting", n);
+
+ /*
+ * Are we shutting down?
+ */
+ for (i = 0; i < adb->nnames; i++)
+ if (adb->name_sd[i])
+ goto cleanup;
+
+ /*
+ * Grab all the resources we need.
+ */
+ newnames = isc_mem_get(adb->mctx, sizeof(*newnames) * n);
+ newdeadnames = isc_mem_get(adb->mctx, sizeof(*newdeadnames) * n);
+ newnamelocks = isc_mem_get(adb->mctx, sizeof(*newnamelocks) * n);
+ newname_sd = isc_mem_get(adb->mctx, sizeof(*newname_sd) * n);
+ newname_refcnt = isc_mem_get(adb->mctx, sizeof(*newname_refcnt) * n);
+ if (newnames == NULL || newdeadnames == NULL ||
+ newnamelocks == NULL || newname_sd == NULL ||
+ newname_refcnt == NULL)
+ goto cleanup;
+
+ /*
+ * Initialise the new resources.
+ */
+ result = isc_mutexblock_init(newnamelocks, n);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ for (i = 0; i < n; i++) {
+ ISC_LIST_INIT(newnames[i]);
+ ISC_LIST_INIT(newdeadnames[i]);
+ newname_sd[i] = ISC_FALSE;
+ newname_refcnt[i] = 0;
+ adb->irefcnt++;
+ }
+
+ /*
+ * Move names to new arrays.
+ */
+ for (i = 0; i < adb->nnames; i++) {
+ name = ISC_LIST_HEAD(adb->names[i]);
+ while (name != NULL) {
+ ISC_LIST_UNLINK(adb->names[i], name, plink);
+ bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
+ name->lock_bucket = bucket;
+ ISC_LIST_APPEND(newnames[bucket], name, plink);
+ INSIST(adb->name_refcnt[i] > 0);
+ adb->name_refcnt[i]--;
+ newname_refcnt[bucket]++;
+ name = ISC_LIST_HEAD(adb->names[i]);
+ }
+ name = ISC_LIST_HEAD(adb->deadnames[i]);
+ while (name != NULL) {
+ ISC_LIST_UNLINK(adb->deadnames[i], name, plink);
+ bucket = dns_name_fullhash(&name->name, ISC_TRUE) % n;
+ name->lock_bucket = bucket;
+ ISC_LIST_APPEND(newdeadnames[bucket], name, plink);
+ INSIST(adb->name_refcnt[i] > 0);
+ adb->name_refcnt[i]--;
+ newname_refcnt[bucket]++;
+ name = ISC_LIST_HEAD(adb->deadnames[i]);
+ }
+ INSIST(adb->name_refcnt[i] == 0);
+ adb->irefcnt--;
+ }
+
+ /*
+ * Cleanup old resources.
+ */
+ DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
+ isc_mem_put(adb->mctx, adb->names,
+ sizeof(*adb->names) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->deadnames,
+ sizeof(*adb->deadnames) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->namelocks,
+ sizeof(*adb->namelocks) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->name_sd,
+ sizeof(*adb->name_sd) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->name_refcnt,
+ sizeof(*adb->name_refcnt) * adb->nnames);
+
+ /*
+ * Install new resources.
+ */
+ adb->names = newnames;
+ adb->deadnames = newdeadnames;
+ adb->namelocks = newnamelocks;
+ adb->name_sd = newname_sd;
+ adb->name_refcnt = newname_refcnt;
+ adb->nnames = n;
+
+ /*
+ * Only on success do we set adb->grownames_sent to ISC_FALSE.
+ * This will prevent us being continuously being called on error.
+ */
+ adb->grownames_sent = ISC_FALSE;
+ goto done;
+
+ cleanup:
+ if (newnames != NULL)
+ isc_mem_put(adb->mctx, newnames, sizeof(*newnames) * n);
+ if (newdeadnames != NULL)
+ isc_mem_put(adb->mctx, newdeadnames, sizeof(*newdeadnames) * n);
+ if (newnamelocks != NULL)
+ isc_mem_put(adb->mctx, newnamelocks, sizeof(*newnamelocks) * n);
+ if (newname_sd != NULL)
+ isc_mem_put(adb->mctx, newname_sd, sizeof(*newname_sd) * n);
+ if (newname_refcnt != NULL)
+ isc_mem_put(adb->mctx, newname_refcnt,
+ sizeof(*newname_refcnt) * n);
+ done:
+ isc_task_endexclusive(task);
+
+ LOCK(&adb->lock);
+ if (dec_adb_irefcnt(adb))
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+ DP(ISC_LOG_INFO, "adb: grow_names finished");
+}
+
+/*
* Requires the adbname bucket be locked and that no entry buckets be locked.
*
* This code handles A and AAAA rdatasets only.
@@ -836,12 +1152,12 @@ violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
*/
static isc_boolean_t
shutdown_names(dns_adb_t *adb) {
- int bucket;
+ unsigned int bucket;
isc_boolean_t result = ISC_FALSE;
dns_adbname_t *name;
dns_adbname_t *next_name;
- for (bucket = 0; bucket < NBUCKETS; bucket++) {
+ for (bucket = 0; bucket < adb->nnames; bucket++) {
LOCK(&adb->namelocks[bucket]);
adb->name_sd[bucket] = ISC_TRUE;
@@ -881,12 +1197,12 @@ shutdown_names(dns_adb_t *adb) {
*/
static isc_boolean_t
shutdown_entries(dns_adb_t *adb) {
- int bucket;
+ unsigned int bucket;
isc_boolean_t result = ISC_FALSE;
dns_adbentry_t *entry;
dns_adbentry_t *next_entry;
- for (bucket = 0; bucket < NBUCKETS; bucket++) {
+ for (bucket = 0; bucket < adb->nentries; bucket++) {
LOCK(&adb->entrylocks[bucket]);
adb->entry_sd[bucket] = ISC_TRUE;
@@ -1306,6 +1622,16 @@ new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
ISC_LIST_INIT(name->finds);
ISC_LINK_INIT(name, plink);
+ LOCK(&adb->namescntlock);
+ adb->namescnt++;
+ if (!adb->grownames_sent && adb->namescnt > (adb->nnames * 8)) {
+ isc_event_t *event = &adb->grownames;
+ inc_adb_irefcnt(adb);
+ isc_task_send(adb->task, &event);
+ adb->grownames_sent = ISC_TRUE;
+ }
+ UNLOCK(&adb->namescntlock);
+
return (name);
}
@@ -1329,6 +1655,9 @@ free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
dns_name_free(&n->name, adb->mctx);
isc_mempool_put(adb->nmp, n);
+ LOCK(&adb->namescntlock);
+ adb->namescnt--;
+ UNLOCK(&adb->namescntlock);
}
static inline dns_adbnamehook_t *
@@ -1417,6 +1746,16 @@ new_adbentry(dns_adb_t *adb) {
e->expires = 0;
ISC_LIST_INIT(e->lameinfo);
ISC_LINK_INIT(e, plink);
+ LOCK(&adb->entriescntlock);
+ adb->entriescnt++;
+ if (!adb->growentries_sent &&
+ adb->entriescnt > (adb->nentries * 8)) {
+ isc_event_t *event = &adb->growentries;
+ inc_adb_irefcnt(adb);
+ isc_task_send(adb->task, &event);
+ adb->growentries_sent = ISC_TRUE;
+ }
+ UNLOCK(&adb->entriescntlock);
return (e);
}
@@ -1444,6 +1783,9 @@ free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
}
isc_mempool_put(adb->emp, e);
+ LOCK(&adb->entriescntlock);
+ adb->entriescnt--;
+ UNLOCK(&adb->entriescntlock);
}
static inline dns_adbfind_t *
@@ -1597,7 +1939,7 @@ find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
dns_adbname_t *adbname;
int bucket;
- bucket = dns_name_fullhash(name, ISC_FALSE) % NBUCKETS;
+ bucket = dns_name_fullhash(name, ISC_FALSE) % adb->nnames;
if (*bucketp == DNS_ADB_INVALIDBUCKET) {
LOCK(&adb->namelocks[bucket]);
@@ -1639,7 +1981,7 @@ find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
dns_adbentry_t *entry, *entry_next;
int bucket;
- bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS;
+ bucket = isc_sockaddr_hash(addr, ISC_TRUE) % adb->nentries;
if (*bucketp == DNS_ADB_INVALIDBUCKET) {
LOCK(&adb->entrylocks[bucket]);
@@ -1992,13 +2334,36 @@ destroy(dns_adb_t *adb) {
isc_mempool_destroy(&adb->aimp);
isc_mempool_destroy(&adb->afmp);
- DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
- DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);
+ DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
+ isc_mem_put(adb->mctx, adb->entries,
+ sizeof(*adb->entries) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->deadentries,
+ sizeof(*adb->deadentries) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entrylocks,
+ sizeof(*adb->entrylocks) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entry_sd,
+ sizeof(*adb->entry_sd) * adb->nentries);
+ isc_mem_put(adb->mctx, adb->entry_refcnt,
+ sizeof(*adb->entry_refcnt) * adb->nentries);
+
+ DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
+ isc_mem_put(adb->mctx, adb->names,
+ sizeof(*adb->names) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->deadnames,
+ sizeof(*adb->deadnames) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->namelocks,
+ sizeof(*adb->namelocks) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->name_sd,
+ sizeof(*adb->name_sd) * adb->nnames);
+ isc_mem_put(adb->mctx, adb->name_refcnt,
+ sizeof(*adb->name_refcnt) * adb->nnames);
DESTROYLOCK(&adb->reflock);
DESTROYLOCK(&adb->lock);
DESTROYLOCK(&adb->mplock);
DESTROYLOCK(&adb->overmemlock);
+ DESTROYLOCK(&adb->entriescntlock);
+ DESTROYLOCK(&adb->namescntlock);
isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
}
@@ -2014,7 +2379,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
{
dns_adb_t *adb;
isc_result_t result;
- int i;
+ unsigned int i;
REQUIRE(mem != NULL);
REQUIRE(view != NULL);
@@ -2054,6 +2419,30 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->shutting_down = ISC_FALSE;
ISC_LIST_INIT(adb->whenshutdown);
+ adb->nentries = nbuckets[0];
+ adb->entriescnt = 0;
+ adb->entries = NULL;
+ adb->deadentries = NULL;
+ adb->entry_sd = NULL;
+ adb->entry_refcnt = NULL;
+ adb->entrylocks = NULL;
+ ISC_EVENT_INIT(&adb->growentries, sizeof(adb->growentries), 0, NULL,
+ DNS_EVENT_ADBGROWENTRIES, grow_entries, adb,
+ adb, NULL, NULL);
+ adb->growentries_sent = ISC_FALSE;
+
+ adb->nnames = nbuckets[0];
+ adb->namescnt = 0;
+ adb->names = NULL;
+ adb->deadnames = NULL;
+ adb->name_sd = NULL;
+ adb->name_refcnt = NULL;
+ adb->namelocks = NULL;
+ ISC_EVENT_INIT(&adb->grownames, sizeof(adb->grownames), 0, NULL,
+ DNS_EVENT_ADBGROWNAMES, grow_names, adb,
+ adb, NULL, NULL);
+ adb->grownames_sent = ISC_FALSE;
+
isc_mem_attach(mem, &adb->mctx);
result = isc_mutex_init(&adb->lock);
@@ -2072,28 +2461,68 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (result != ISC_R_SUCCESS)
goto fail0e;
+ result = isc_mutex_init(&adb->entriescntlock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0f;
+
+ result = isc_mutex_init(&adb->namescntlock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0g;
+
+#define ALLOCENTRY(adb, el) \
+ do { \
+ (adb)->el = isc_mem_get((adb)->mctx, \
+ sizeof(*(adb)->el) * (adb)->nentries); \
+ if ((adb)->el == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ goto fail1; \
+ }\
+ } while (0)
+ ALLOCENTRY(adb, entries);
+ ALLOCENTRY(adb, deadentries);
+ ALLOCENTRY(adb, entrylocks);
+ ALLOCENTRY(adb, entry_sd);
+ ALLOCENTRY(adb, entry_refcnt);
+#undef ALLOCENTRY
+
+#define ALLOCNAME(adb, el) \
+ do { \
+ (adb)->el = isc_mem_get((adb)->mctx, \
+ sizeof(*(adb)->el) * (adb)->nnames); \
+ if ((adb)->el == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ goto fail1; \
+ }\
+ } while (0)
+ ALLOCNAME(adb, names);
+ ALLOCNAME(adb, deadnames);
+ ALLOCNAME(adb, namelocks);
+ ALLOCNAME(adb, name_sd);
+ ALLOCNAME(adb, name_refcnt);
+#undef ALLOCNAME
+
/*
* Initialize the bucket locks for names and elements.
* May as well initialize the list heads, too.
*/
- result = isc_mutexblock_init(adb->namelocks, NBUCKETS);
+ result = isc_mutexblock_init(adb->namelocks, adb->nnames);
if (result != ISC_R_SUCCESS)
goto fail1;
- for (i = 0; i < NBUCKETS; i++) {
+ for (i = 0; i < adb->nnames; 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++) {
+ for (i = 0; i < adb->nentries; 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++;
}
- result = isc_mutexblock_init(adb->entrylocks, NBUCKETS);
+ result = isc_mutexblock_init(adb->entrylocks, adb->nentries);
if (result != ISC_R_SUCCESS)
goto fail2;
@@ -2140,12 +2569,42 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
isc_task_detach(&adb->task);
/* clean up entrylocks */
- DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
+ DESTROYMUTEXBLOCK(adb->entrylocks, adb->nentries);
fail2: /* clean up namelocks */
- DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);
+ DESTROYMUTEXBLOCK(adb->namelocks, adb->nnames);
fail1: /* clean up only allocated memory */
+ if (adb->entries != NULL)
+ isc_mem_put(adb->mctx, adb->entries,
+ sizeof(*adb->entries) * adb->nentries);
+ if (adb->deadentries != NULL)
+ isc_mem_put(adb->mctx, adb->deadentries,
+ sizeof(*adb->deadentries) * adb->nentries);
+ if (adb->entrylocks != NULL)
+ isc_mem_put(adb->mctx, adb->entrylocks,
+ sizeof(*adb->entrylocks) * adb->nentries);
+ if (adb->entry_sd != NULL)
+ isc_mem_put(adb->mctx, adb->entry_sd,
+ sizeof(*adb->entry_sd) * adb->nentries);
+ if (adb->entry_refcnt != NULL)
+ isc_mem_put(adb->mctx, adb->entry_refcnt,
+ sizeof(*adb->entry_refcnt) * adb->nentries);
+ if (adb->names != NULL)
+ isc_mem_put(adb->mctx, adb->names,
+ sizeof(*adb->names) * adb->nnames);
+ if (adb->deadnames != NULL)
+ isc_mem_put(adb->mctx, adb->deadnames,
+ sizeof(*adb->deadnames) * adb->nnames);
+ if (adb->namelocks != NULL)
+ isc_mem_put(adb->mctx, adb->namelocks,
+ sizeof(*adb->namelocks) * adb->nnames);
+ if (adb->name_sd != NULL)
+ isc_mem_put(adb->mctx, adb->name_sd,
+ sizeof(*adb->name_sd) * adb->nnames);
+ if (adb->name_refcnt != NULL)
+ isc_mem_put(adb->mctx, adb->name_refcnt,
+ sizeof(*adb->name_refcnt) * adb->nnames);
if (adb->nmp != NULL)
isc_mempool_destroy(&adb->nmp);
if (adb->nhmp != NULL)
@@ -2161,6 +2620,10 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (adb->afmp != NULL)
isc_mempool_destroy(&adb->afmp);
+ DESTROYLOCK(&adb->namescntlock);
+ fail0g:
+ DESTROYLOCK(&adb->entriescntlock);
+ fail0f:
DESTROYLOCK(&adb->overmemlock);
fail0e:
DESTROYLOCK(&adb->reflock);
@@ -2728,7 +3191,7 @@ dns_adb_cancelfind(dns_adbfind_t *find) {
void
dns_adb_dump(dns_adb_t *adb, FILE *f) {
- int i;
+ unsigned int i;
isc_stdtime_t now;
REQUIRE(DNS_ADB_VALID(adb));
@@ -2744,9 +3207,9 @@ dns_adb_dump(dns_adb_t *adb, FILE *f) {
LOCK(&adb->lock);
isc_stdtime_get(&now);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nnames; i++)
RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nentries; i++)
RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
dump_adb(adb, f, ISC_FALSE, now);
@@ -2762,7 +3225,7 @@ dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
static void
dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
- int i;
+ unsigned int i;
dns_adbname_t *name;
dns_adbentry_t *entry;
@@ -2772,15 +3235,15 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
adb, adb->erefcnt, adb->irefcnt,
isc_mempool_getallocated(adb->nhmp));
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nnames; i++)
LOCK(&adb->namelocks[i]);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nentries; i++)
LOCK(&adb->entrylocks[i]);
/*
* Dump the names
*/
- for (i = 0; i < NBUCKETS; i++) {
+ for (i = 0; i < adb->nnames; i++) {
name = ISC_LIST_HEAD(adb->names[i]);
if (name == NULL)
continue;
@@ -2824,7 +3287,7 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
fprintf(f, ";\n; Unassociated entries\n;\n");
- for (i = 0; i < NBUCKETS; i++) {
+ for (i = 0; i < adb->nentries; i++) {
entry = ISC_LIST_HEAD(adb->entries[i]);
while (entry != NULL) {
if (entry->refcnt == 0)
@@ -2836,9 +3299,9 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
/*
* Unlock everything
*/
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nentries; i++)
UNLOCK(&adb->entrylocks[i]);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nnames; i++)
UNLOCK(&adb->namelocks[i]);
}
@@ -2999,10 +3462,20 @@ dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
else
adbname->fetch6_err = FIND_ERR_UNEXPECTED;
- result = dns_view_find(adb->view, &adbname->name, rdtype, now,
- NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
- ISC_TF(NAME_HINTOK(adbname)),
- NULL, NULL, fname, &rdataset, NULL);
+ /*
+ * We need to specify whether to search static-stub zones (if
+ * configured) depending on whether this is a "start at zone" lookup,
+ * i.e., whether it's a "bailiwick" glue. If it's bailiwick (in which
+ * case NAME_STARTATZONE is set) we need to stop the search at any
+ * matching static-stub zone without looking into the cache to honor
+ * the configuration on which server we should send queries to.
+ */
+ result = dns_view_find2(adb->view, &adbname->name, rdtype, now,
+ NAME_GLUEOK(adbname) ? DNS_DBFIND_GLUEOK : 0,
+ ISC_TF(NAME_HINTOK(adbname)),
+ (adbname->flags & NAME_STARTATZONE) != 0 ?
+ ISC_TRUE : ISC_FALSE,
+ NULL, NULL, fname, &rdataset, NULL);
/* XXXVIX this switch statement is too sparse to gen a jump table. */
switch (result) {
@@ -3557,9 +4030,9 @@ dns_adb_flush(dns_adb_t *adb) {
/*
* Call our cleanup routines.
*/
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nnames; i++)
RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
- for (i = 0; i < NBUCKETS; i++)
+ for (i = 0; i < adb->nentries; i++)
RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
#ifdef DUMP_ADB_AFTER_CLEANING
@@ -3578,7 +4051,7 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
INSIST(DNS_ADB_VALID(adb));
LOCK(&adb->lock);
- bucket = dns_name_hash(name, ISC_FALSE) % NBUCKETS;
+ bucket = dns_name_hash(name, ISC_FALSE) % adb->nnames;
LOCK(&adb->namelocks[bucket]);
adbname = ISC_LIST_HEAD(adb->names[bucket]);
while (adbname != NULL) {
diff --git a/contrib/bind9/lib/dns/api b/contrib/bind9/lib/dns/api
index 87c3c90..9bac060 100644
--- a/contrib/bind9/lib/dns/api
+++ b/contrib/bind9/lib/dns/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 59
-LIBREVISION = 5
+LIBINTERFACE = 82
+LIBREVISION = 3
LIBAGE = 1
diff --git a/contrib/bind9/lib/dns/byaddr.c b/contrib/bind9/lib/dns/byaddr.c
index 96b9f38..2fd61a2 100644
--- a/contrib/bind9/lib/dns/byaddr.c
+++ b/contrib/bind9/lib/dns/byaddr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: byaddr.c,v 1.39 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: byaddr.c,v 1.41 2009-09-02 23:48:02 tbox Exp $ */
/*! \file */
@@ -43,25 +43,6 @@
* XXXRTH We could use a static event...
*/
-struct dns_byaddr {
- /* Unlocked. */
- unsigned int magic;
- isc_mem_t * mctx;
- isc_mutex_t lock;
- dns_fixedname_t name;
- /* Locked by lock. */
- unsigned int options;
- dns_lookup_t * lookup;
- isc_task_t * task;
- dns_byaddrevent_t * event;
- isc_boolean_t canceled;
-};
-
-#define BYADDR_MAGIC ISC_MAGIC('B', 'y', 'A', 'd')
-#define VALID_BYADDR(b) ISC_MAGIC_VALID(b, BYADDR_MAGIC)
-
-#define MAX_RESTARTS 16
-
static char hex_digits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
@@ -125,10 +106,29 @@ dns_byaddr_createptrname2(isc_netaddr_t *address, unsigned int options,
len = (unsigned int)strlen(textname);
isc_buffer_init(&buffer, textname, len);
isc_buffer_add(&buffer, len);
- return (dns_name_fromtext(name, &buffer, dns_rootname,
- ISC_FALSE, NULL));
+ return (dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL));
}
+#ifdef BIND9
+struct dns_byaddr {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ isc_mutex_t lock;
+ dns_fixedname_t name;
+ /* Locked by lock. */
+ unsigned int options;
+ dns_lookup_t * lookup;
+ isc_task_t * task;
+ dns_byaddrevent_t * event;
+ isc_boolean_t canceled;
+};
+
+#define BYADDR_MAGIC ISC_MAGIC('B', 'y', 'A', 'd')
+#define VALID_BYADDR(b) ISC_MAGIC_VALID(b, BYADDR_MAGIC)
+
+#define MAX_RESTARTS 16
+
static inline isc_result_t
copy_ptr_targets(dns_byaddr_t *byaddr, dns_rdataset_t *rdataset) {
isc_result_t result;
@@ -314,3 +314,4 @@ dns_byaddr_destroy(dns_byaddr_t **byaddrp) {
*byaddrp = NULL;
}
+#endif /* BIND9 */
diff --git a/contrib/bind9/lib/dns/cache.c b/contrib/bind9/lib/dns/cache.c
index 28ead66..bf93da2 100644
--- a/contrib/bind9/lib/dns/cache.c
+++ b/contrib/bind9/lib/dns/cache.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cache.c,v 1.80.50.3 2009-05-06 23:34:30 jinmei Exp $ */
+/* $Id: cache.c,v 1.87 2009-11-12 23:43:02 each Exp $ */
/*! \file */
@@ -122,6 +122,7 @@ struct dns_cache {
isc_mutex_t lock;
isc_mutex_t filelock;
isc_mem_t *mctx;
+ char *name;
/* Locked by 'lock'. */
int references;
@@ -132,6 +133,7 @@ struct dns_cache {
char *db_type;
int db_argc;
char **db_argv;
+ isc_uint32_t size;
/* Locked by 'filelock'. */
char *filename;
@@ -171,6 +173,16 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
const char *db_type, unsigned int db_argc, char **db_argv,
dns_cache_t **cachep)
{
+ return (dns_cache_create2(mctx, taskmgr, timermgr, rdclass, "",
+ db_type, db_argc, db_argv, cachep));
+}
+
+isc_result_t
+dns_cache_create2(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
+ const char *cachename, const char *db_type,
+ unsigned int db_argc, char **db_argv, dns_cache_t **cachep)
+{
isc_result_t result;
dns_cache_t *cache;
int i;
@@ -179,6 +191,7 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
REQUIRE(cachep != NULL);
REQUIRE(*cachep == NULL);
REQUIRE(mctx != NULL);
+ REQUIRE(cachename != NULL);
cache = isc_mem_get(mctx, sizeof(*cache));
if (cache == NULL)
@@ -187,6 +200,15 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
cache->mctx = NULL;
isc_mem_attach(mctx, &cache->mctx);
+ cache->name = NULL;
+ if (cachename != NULL) {
+ cache->name = isc_mem_strdup(mctx, cachename);
+ if (cache->name == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_mem;
+ }
+ }
+
result = isc_mutex_init(&cache->lock);
if (result != ISC_R_SUCCESS)
goto cleanup_mem;
@@ -275,6 +297,8 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
cleanup_lock:
DESTROYLOCK(&cache->lock);
cleanup_mem:
+ if (cache->name != NULL)
+ isc_mem_free(mctx, cache->name);
isc_mem_put(mctx, cache, sizeof(*cache));
isc_mem_detach(&mctx);
return (result);
@@ -323,6 +347,9 @@ cache_free(dns_cache_t *cache) {
if (cache->db_type != NULL)
isc_mem_free(cache->mctx, cache->db_type);
+ if (cache->name != NULL)
+ isc_mem_free(cache->mctx, cache->name);
+
DESTROYLOCK(&cache->lock);
DESTROYLOCK(&cache->filelock);
cache->magic = 0;
@@ -423,6 +450,7 @@ dns_cache_setfilename(dns_cache_t *cache, const char *filename) {
return (ISC_R_SUCCESS);
}
+#ifdef BIND9
isc_result_t
dns_cache_load(dns_cache_t *cache) {
isc_result_t result;
@@ -438,22 +466,29 @@ dns_cache_load(dns_cache_t *cache) {
return (result);
}
+#endif /* BIND9 */
isc_result_t
dns_cache_dump(dns_cache_t *cache) {
+#ifdef BIND9
isc_result_t result;
+#endif
REQUIRE(VALID_CACHE(cache));
if (cache->filename == NULL)
return (ISC_R_SUCCESS);
+#ifdef BIND9
LOCK(&cache->filelock);
result = dns_master_dump(cache->mctx, cache->db, NULL,
&dns_master_style_cache, cache->filename);
UNLOCK(&cache->filelock);
-
return (result);
+#else
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+
}
void
@@ -493,6 +528,26 @@ dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int t) {
UNLOCK(&cache->lock);
}
+unsigned int
+dns_cache_getcleaninginterval(dns_cache_t *cache) {
+ unsigned int t;
+
+ REQUIRE(VALID_CACHE(cache));
+
+ LOCK(&cache->lock);
+ t = cache->cleaner.cleaning_interval;
+ UNLOCK(&cache->lock);
+
+ return (t);
+}
+
+const char *
+dns_cache_getname(dns_cache_t *cache) {
+ REQUIRE(VALID_CACHE(cache));
+
+ return (cache->name);
+}
+
/*
* Initialize the cache cleaner object at *cleaner.
* Space for the object must be allocated by the caller.
@@ -519,6 +574,7 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
cleaner->cleaning_timer = NULL;
cleaner->resched_event = NULL;
cleaner->overmem_event = NULL;
+ cleaner->cleaning_interval = 0; /* Initially turned off. */
result = dns_db_createiterator(cleaner->cache->db, ISC_FALSE,
&cleaner->iterator);
@@ -547,7 +603,6 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
goto cleanup;
}
- cleaner->cleaning_interval = 0; /* Initially turned off. */
result = isc_timer_create(timermgr, isc_timertype_inactive,
NULL, NULL, cleaner->task,
cleaning_timer_action, cleaner,
@@ -949,6 +1004,10 @@ dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) {
if (size != 0 && size < DNS_CACHE_MINSIZE)
size = DNS_CACHE_MINSIZE;
+ LOCK(&cache->lock);
+ cache->size = size;
+ UNLOCK(&cache->lock);
+
hiwater = size - (size >> 3); /* Approximately 7/8ths. */
lowater = size - (size >> 2); /* Approximately 3/4ths. */
@@ -972,6 +1031,19 @@ dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) {
isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater);
}
+isc_uint32_t
+dns_cache_getcachesize(dns_cache_t *cache) {
+ isc_uint32_t size;
+
+ REQUIRE(VALID_CACHE(cache));
+
+ LOCK(&cache->lock);
+ size = cache->size;
+ UNLOCK(&cache->lock);
+
+ return (size);
+}
+
/*
* The cleaner task is shutting down; do the necessary cleanup.
*/
diff --git a/contrib/bind9/lib/dns/client.c b/contrib/bind9/lib/dns/client.c
new file mode 100644
index 0000000..e55ea1f
--- /dev/null
+++ b/contrib/bind9/lib/dns/client.c
@@ -0,0 +1,3019 @@
+/*
+ * Copyright (C) 2009, 2010 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: client.c,v 1.12 2010-12-03 12:03:22 marka Exp $ */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/app.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/client.h>
+#include <dns/db.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/forward.h>
+#include <dns/keytable.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/request.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/tsec.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+
+#include <dst/dst.h>
+
+#define DNS_CLIENT_MAGIC ISC_MAGIC('D', 'N', 'S', 'c')
+#define DNS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, DNS_CLIENT_MAGIC)
+
+#define RCTX_MAGIC ISC_MAGIC('R', 'c', 't', 'x')
+#define RCTX_VALID(c) ISC_MAGIC_VALID(c, RCTX_MAGIC)
+
+#define REQCTX_MAGIC ISC_MAGIC('R', 'q', 'c', 'x')
+#define REQCTX_VALID(c) ISC_MAGIC_VALID(c, REQCTX_MAGIC)
+
+#define UCTX_MAGIC ISC_MAGIC('U', 'c', 't', 'x')
+#define UCTX_VALID(c) ISC_MAGIC_VALID(c, UCTX_MAGIC)
+
+#define MAX_RESTARTS 16
+
+/*%
+ * DNS client object
+ */
+struct dns_client {
+ /* Unlocked */
+ unsigned int magic;
+ unsigned int attributes;
+ isc_mutex_t lock;
+ isc_mem_t *mctx;
+ isc_appctx_t *actx;
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *task;
+ isc_socketmgr_t *socketmgr;
+ isc_timermgr_t *timermgr;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_dispatch_t *dispatchv6;
+
+ unsigned int update_timeout;
+ unsigned int update_udptimeout;
+ unsigned int update_udpretries;
+ unsigned int find_timeout;
+ unsigned int find_udpretries;
+
+ /* Locked */
+ unsigned int references;
+ dns_viewlist_t viewlist;
+ ISC_LIST(struct resctx) resctxs;
+ ISC_LIST(struct reqctx) reqctxs;
+ ISC_LIST(struct updatectx) updatectxs;
+};
+
+/*%
+ * Timeout/retry constants for dynamic update borrowed from nsupdate
+ */
+#define DEF_UPDATE_TIMEOUT 300
+#define MIN_UPDATE_TIMEOUT 30
+#define DEF_UPDATE_UDPTIMEOUT 3
+#define DEF_UPDATE_UDPRETRIES 3
+
+#define DEF_FIND_TIMEOUT 5
+#define DEF_FIND_UDPRETRIES 3
+
+#define DNS_CLIENTATTR_OWNCTX 0x01
+
+#define DNS_CLIENTVIEW_NAME "dnsclient"
+
+/*%
+ * Internal state for a single name resolution procedure
+ */
+typedef struct resctx {
+ /* Unlocked */
+ unsigned int magic;
+ isc_mutex_t lock;
+ dns_client_t *client;
+ isc_boolean_t want_dnssec;
+
+ /* Locked */
+ ISC_LINK(struct resctx) link;
+ isc_task_t *task;
+ dns_view_t *view;
+ unsigned int restarts;
+ dns_fixedname_t name;
+ dns_rdatatype_t type;
+ dns_fetch_t *fetch;
+ dns_namelist_t namelist;
+ isc_result_t result;
+ dns_clientresevent_t *event;
+ isc_boolean_t canceled;
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+} resctx_t;
+
+/*%
+ * Argument of an internal event for synchronous name resolution.
+ */
+typedef struct resarg {
+ /* Unlocked */
+ isc_appctx_t *actx;
+ dns_client_t *client;
+ isc_mutex_t lock;
+
+ /* Locked */
+ isc_result_t result;
+ isc_result_t vresult;
+ dns_namelist_t *namelist;
+ dns_clientrestrans_t *trans;
+ isc_boolean_t canceled;
+} resarg_t;
+
+/*%
+ * Internal state for a single DNS request
+ */
+typedef struct reqctx {
+ /* Unlocked */
+ unsigned int magic;
+ isc_mutex_t lock;
+ dns_client_t *client;
+ unsigned int parseoptions;
+
+ /* Locked */
+ ISC_LINK(struct reqctx) link;
+ isc_boolean_t canceled;
+ dns_tsigkey_t *tsigkey;
+ dns_request_t *request;
+ dns_clientreqevent_t *event;
+} reqctx_t;
+
+/*%
+ * Argument of an internal event for synchronous DNS request.
+ */
+typedef struct reqarg {
+ /* Unlocked */
+ isc_appctx_t *actx;
+ dns_client_t *client;
+ isc_mutex_t lock;
+
+ /* Locked */
+ isc_result_t result;
+ dns_clientreqtrans_t *trans;
+ isc_boolean_t canceled;
+} reqarg_t;
+
+/*%
+ * Argument of an internal event for synchronous name resolution.
+ */
+typedef struct updatearg {
+ /* Unlocked */
+ isc_appctx_t *actx;
+ dns_client_t *client;
+ isc_mutex_t lock;
+
+ /* Locked */
+ isc_result_t result;
+ dns_clientupdatetrans_t *trans;
+ isc_boolean_t canceled;
+} updatearg_t;
+
+/*%
+ * Internal state for a single dynamic update procedure
+ */
+typedef struct updatectx {
+ /* Unlocked */
+ unsigned int magic;
+ isc_mutex_t lock;
+ dns_client_t *client;
+
+ /* Locked */
+ dns_request_t *updatereq;
+ dns_request_t *soareq;
+ dns_clientrestrans_t *restrans;
+ dns_clientrestrans_t *restrans2;
+ isc_boolean_t canceled;
+
+ /* Task Locked */
+ ISC_LINK(struct updatectx) link;
+ dns_clientupdatestate_t state;
+ dns_rdataclass_t rdclass;
+ dns_view_t *view;
+ dns_message_t *updatemsg;
+ dns_message_t *soaquery;
+ dns_clientupdateevent_t *event;
+ dns_tsigkey_t *tsigkey;
+ dst_key_t *sig0key;
+ dns_name_t *firstname;
+ dns_name_t soaqname;
+ dns_fixedname_t zonefname;
+ dns_name_t *zonename;
+ isc_sockaddrlist_t servers;
+ unsigned int nservers;
+ isc_sockaddr_t *currentserver;
+ struct updatectx *bp4;
+ struct updatectx *bp6;
+} updatectx_t;
+
+static isc_result_t request_soa(updatectx_t *uctx);
+static void client_resfind(resctx_t *rctx, dns_fetchevent_t *event);
+static isc_result_t send_update(updatectx_t *uctx);
+
+static isc_result_t
+getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
+ isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
+ isc_boolean_t is_shared, dns_dispatch_t **dispp)
+{
+ unsigned int attrs, attrmask;
+ isc_sockaddr_t sa;
+ dns_dispatch_t *disp;
+ unsigned buffersize, maxbuffers, maxrequests, buckets, increment;
+ isc_result_t result;
+
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_UDP;
+ switch (family) {
+ case AF_INET:
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ break;
+ case AF_INET6:
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ break;
+ default:
+ INSIST(0);
+ }
+ attrmask = 0;
+ attrmask |= DNS_DISPATCHATTR_UDP;
+ attrmask |= DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4;
+ attrmask |= DNS_DISPATCHATTR_IPV6;
+
+ isc_sockaddr_anyofpf(&sa, family);
+
+ buffersize = 4096;
+ maxbuffers = is_shared ? 1000 : 8;
+ maxrequests = 32768;
+ buckets = is_shared ? 16411 : 3;
+ increment = is_shared ? 16433 : 5;
+
+ disp = NULL;
+ result = dns_dispatch_getudp(dispatchmgr, socketmgr,
+ taskmgr, &sa,
+ buffersize, maxbuffers, maxrequests,
+ buckets, increment,
+ attrs, attrmask, &disp);
+ if (result == ISC_R_SUCCESS)
+ *dispp = disp;
+
+ return (result);
+}
+
+static isc_result_t
+dns_client_createview(isc_mem_t *mctx, dns_rdataclass_t rdclass,
+ unsigned int options, isc_taskmgr_t *taskmgr,
+ unsigned int ntasks, isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr, dns_dispatchmgr_t *dispatchmgr,
+ dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
+ dns_view_t **viewp)
+{
+ isc_result_t result;
+ dns_view_t *view = NULL;
+ const char *dbtype;
+
+ result = dns_view_create(mctx, rdclass, DNS_CLIENTVIEW_NAME, &view);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Initialize view security roots */
+ result = dns_view_initsecroots(view, mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_view_detach(&view);
+ return (result);
+ }
+
+ result = dns_view_createresolver(view, taskmgr, ntasks, socketmgr,
+ timermgr, 0, dispatchmgr,
+ dispatchv4, dispatchv6);
+ if (result != ISC_R_SUCCESS) {
+ dns_view_detach(&view);
+ return (result);
+ }
+
+ /*
+ * Set cache DB.
+ * XXX: it may be better if specific DB implementations can be
+ * specified via some configuration knob.
+ */
+ if ((options & DNS_CLIENTCREATEOPT_USECACHE) != 0)
+ dbtype = "rbt";
+ else
+ dbtype = "ecdb";
+ result = dns_db_create(mctx, dbtype, dns_rootname, dns_dbtype_cache,
+ rdclass, 0, NULL, &view->cachedb);
+ if (result != ISC_R_SUCCESS) {
+ dns_view_detach(&view);
+ return (result);
+ }
+
+ *viewp = view;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_client_create(dns_client_t **clientp, unsigned int options) {
+ isc_result_t result;
+ isc_mem_t *mctx = NULL;
+ isc_appctx_t *actx = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_socketmgr_t *socketmgr = NULL;
+ isc_timermgr_t *timermgr = NULL;
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = isc_appctx_create(mctx, &actx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_app_ctxstart(actx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_socketmgr_createinctx(mctx, actx, &socketmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_timermgr_createinctx(mctx, actx, &timermgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr,
+ options, clientp);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ (*clientp)->attributes |= DNS_CLIENTATTR_OWNCTX;
+
+ /* client has its own reference to mctx, so we can detach it here */
+ isc_mem_detach(&mctx);
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (taskmgr != NULL)
+ isc_taskmgr_destroy(&taskmgr);
+ if (timermgr != NULL)
+ isc_timermgr_destroy(&timermgr);
+ if (socketmgr != NULL)
+ isc_socketmgr_destroy(&socketmgr);
+ if (actx != NULL)
+ isc_appctx_destroy(&actx);
+ isc_mem_detach(&mctx);
+
+ return (result);
+}
+
+isc_result_t
+dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
+ unsigned int options, dns_client_t **clientp)
+{
+ dns_client_t *client;
+ isc_result_t result;
+ dns_dispatchmgr_t *dispatchmgr = NULL;
+ dns_dispatch_t *dispatchv4 = NULL;
+ dns_dispatch_t *dispatchv6 = NULL;
+ dns_view_t *view = NULL;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(taskmgr != NULL);
+ REQUIRE(timermgr != NULL);
+ REQUIRE(socketmgr != NULL);
+ REQUIRE(clientp != NULL && *clientp == NULL);
+
+ client = isc_mem_get(mctx, sizeof(*client));
+ if (client == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&client->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, client, sizeof(*client));
+ return (result);
+ }
+
+ client->actx = actx;
+ client->taskmgr = taskmgr;
+ client->socketmgr = socketmgr;
+ client->timermgr = timermgr;
+
+ client->task = NULL;
+ result = isc_task_create(client->taskmgr, 0, &client->task);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ client->dispatchmgr = dispatchmgr;
+
+ /* TODO: whether to use dispatch v4 or v6 should be configurable */
+ client->dispatchv4 = NULL;
+ client->dispatchv6 = NULL;
+ result = getudpdispatch(AF_INET, dispatchmgr, socketmgr,
+ taskmgr, ISC_TRUE, &dispatchv4);
+ if (result == ISC_R_SUCCESS)
+ client->dispatchv4 = dispatchv4;
+ result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr,
+ taskmgr, ISC_TRUE, &dispatchv6);
+ if (result == ISC_R_SUCCESS)
+ client->dispatchv6 = dispatchv6;
+
+ /* We need at least one of the dispatchers */
+ if (dispatchv4 == NULL && dispatchv6 == NULL) {
+ INSIST(result != ISC_R_SUCCESS);
+ goto cleanup;
+ }
+
+ /* Create the default view for class IN */
+ result = dns_client_createview(mctx, dns_rdataclass_in, options,
+ taskmgr, 31, socketmgr, timermgr,
+ dispatchmgr, dispatchv4, dispatchv6,
+ &view);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ISC_LIST_INIT(client->viewlist);
+ ISC_LIST_APPEND(client->viewlist, view, link);
+
+ dns_view_freeze(view); /* too early? */
+
+ ISC_LIST_INIT(client->resctxs);
+ ISC_LIST_INIT(client->reqctxs);
+ ISC_LIST_INIT(client->updatectxs);
+
+ client->mctx = NULL;
+ isc_mem_attach(mctx, &client->mctx);
+
+ client->update_timeout = DEF_UPDATE_TIMEOUT;
+ client->update_udptimeout = DEF_UPDATE_UDPTIMEOUT;
+ client->update_udpretries = DEF_UPDATE_UDPRETRIES;
+ client->find_timeout = DEF_FIND_TIMEOUT;
+ client->find_udpretries = DEF_FIND_UDPRETRIES;
+
+ client->references = 1;
+ client->magic = DNS_CLIENT_MAGIC;
+
+ *clientp = client;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (dispatchv4 != NULL)
+ dns_dispatch_detach(&dispatchv4);
+ if (dispatchv6 != NULL)
+ dns_dispatch_detach(&dispatchv6);
+ if (dispatchmgr != NULL)
+ dns_dispatchmgr_destroy(&dispatchmgr);
+ if (client->task != NULL)
+ isc_task_detach(&client->task);
+ isc_mem_put(mctx, client, sizeof(*client));
+
+ return (result);
+}
+
+static void
+destroyclient(dns_client_t **clientp) {
+ dns_client_t *client = *clientp;
+ dns_view_t *view;
+
+ while ((view = ISC_LIST_HEAD(client->viewlist)) != NULL) {
+ ISC_LIST_UNLINK(client->viewlist, view, link);
+ dns_view_detach(&view);
+ }
+
+ if (client->dispatchv4 != NULL)
+ dns_dispatch_detach(&client->dispatchv4);
+ if (client->dispatchv6 != NULL)
+ dns_dispatch_detach(&client->dispatchv6);
+
+ dns_dispatchmgr_destroy(&client->dispatchmgr);
+
+ isc_task_detach(&client->task);
+
+ /*
+ * If the client has created its own running environments,
+ * destroy them.
+ */
+ if ((client->attributes & DNS_CLIENTATTR_OWNCTX) != 0) {
+ isc_taskmgr_destroy(&client->taskmgr);
+ isc_timermgr_destroy(&client->timermgr);
+ isc_socketmgr_destroy(&client->socketmgr);
+
+ isc_app_ctxfinish(client->actx);
+ isc_appctx_destroy(&client->actx);
+ }
+
+ DESTROYLOCK(&client->lock);
+ client->magic = 0;
+
+ isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
+
+ *clientp = NULL;
+}
+
+void
+dns_client_destroy(dns_client_t **clientp) {
+ dns_client_t *client;
+ isc_boolean_t destroyok = ISC_FALSE;
+
+ REQUIRE(clientp != NULL);
+ client = *clientp;
+ REQUIRE(DNS_CLIENT_VALID(client));
+
+ LOCK(&client->lock);
+ client->references--;
+ if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) &&
+ ISC_LIST_EMPTY(client->reqctxs) &&
+ ISC_LIST_EMPTY(client->updatectxs)) {
+ destroyok = ISC_TRUE;
+ }
+ UNLOCK(&client->lock);
+
+ if (destroyok)
+ destroyclient(&client);
+
+ *clientp = NULL;
+}
+
+isc_result_t
+dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *namespace, isc_sockaddrlist_t *addrs)
+{
+ isc_result_t result;
+ dns_view_t *view = NULL;
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(addrs != NULL);
+
+ if (namespace == NULL)
+ namespace = dns_rootname;
+
+ LOCK(&client->lock);
+ result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
+ rdclass, &view);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&client->lock);
+ return (result);
+ }
+ UNLOCK(&client->lock);
+
+ result = dns_fwdtable_add(view->fwdtable, namespace, addrs,
+ dns_fwdpolicy_only);
+
+ dns_view_detach(&view);
+
+ return (result);
+}
+
+isc_result_t
+dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *namespace)
+{
+ isc_result_t result;
+ dns_view_t *view = NULL;
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+
+ if (namespace == NULL)
+ namespace = dns_rootname;
+
+ LOCK(&client->lock);
+ result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
+ rdclass, &view);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&client->lock);
+ return (result);
+ }
+ UNLOCK(&client->lock);
+
+ result = dns_fwdtable_delete(view->fwdtable, namespace);
+
+ dns_view_detach(&view);
+
+ return (result);
+}
+
+static isc_result_t
+getrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) {
+ dns_rdataset_t *rdataset;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
+
+ rdataset = isc_mem_get(mctx, sizeof(*rdataset));
+ if (rdataset == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dns_rdataset_init(rdataset);
+
+ *rdatasetp = rdataset;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+putrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) {
+ dns_rdataset_t *rdataset;
+
+ REQUIRE(rdatasetp != NULL);
+ rdataset = *rdatasetp;
+ REQUIRE(rdataset != NULL);
+
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+
+ isc_mem_put(mctx, rdataset, sizeof(*rdataset));
+
+ *rdatasetp = NULL;
+}
+
+static void
+fetch_done(isc_task_t *task, isc_event_t *event) {
+ resctx_t *rctx = event->ev_arg;
+ dns_fetchevent_t *fevent;
+
+ REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+ REQUIRE(RCTX_VALID(rctx));
+ REQUIRE(rctx->task == task);
+ fevent = (dns_fetchevent_t *)event;
+
+ client_resfind(rctx, fevent);
+}
+
+static inline isc_result_t
+start_fetch(resctx_t *rctx) {
+ isc_result_t result;
+
+ /*
+ * The caller must be holding the rctx's lock.
+ */
+
+ REQUIRE(rctx->fetch == NULL);
+
+ result = dns_resolver_createfetch(rctx->view->resolver,
+ dns_fixedname_name(&rctx->name),
+ rctx->type,
+ NULL, NULL, NULL, 0,
+ rctx->task, fetch_done, rctx,
+ rctx->rdataset,
+ rctx->sigrdataset,
+ &rctx->fetch);
+
+ return (result);
+}
+
+static isc_result_t
+view_find(resctx_t *rctx, dns_db_t **dbp, dns_dbnode_t **nodep,
+ dns_name_t *foundname)
+{
+ isc_result_t result;
+ dns_name_t *name = dns_fixedname_name(&rctx->name);
+ dns_rdatatype_t type;
+
+ if (rctx->type == dns_rdatatype_rrsig)
+ type = dns_rdatatype_any;
+ else
+ type = rctx->type;
+
+ result = dns_view_find(rctx->view, name, type, 0, 0, ISC_FALSE,
+ dbp, nodep, foundname, rctx->rdataset,
+ rctx->sigrdataset);
+
+ return (result);
+}
+
+static void
+client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
+ isc_mem_t *mctx;
+ isc_result_t result, tresult;
+ isc_result_t vresult = ISC_R_SUCCESS;
+ isc_boolean_t want_restart;
+ isc_boolean_t send_event = ISC_FALSE;
+ dns_name_t *name, *prefix;
+ dns_fixedname_t foundname, fixed;
+ dns_rdataset_t *trdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int nlabels;
+ int order;
+ dns_namereln_t namereln;
+ dns_rdata_cname_t cname;
+ dns_rdata_dname_t dname;
+
+ REQUIRE(RCTX_VALID(rctx));
+
+ LOCK(&rctx->lock);
+
+ mctx = rctx->view->mctx;
+
+ result = ISC_R_SUCCESS;
+ name = dns_fixedname_name(&rctx->name);
+
+ do {
+ dns_name_t *fname = NULL;
+ dns_name_t *ansname = NULL;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+
+ rctx->restarts++;
+ want_restart = ISC_FALSE;
+
+ if (event == NULL && !rctx->canceled) {
+ dns_fixedname_init(&foundname);
+ fname = dns_fixedname_name(&foundname);
+ INSIST(!dns_rdataset_isassociated(rctx->rdataset));
+ INSIST(rctx->sigrdataset == NULL ||
+ !dns_rdataset_isassociated(rctx->sigrdataset));
+ result = view_find(rctx, &db, &node, fname);
+ if (result == ISC_R_NOTFOUND) {
+ /*
+ * We don't know anything about the name.
+ * Launch a fetch.
+ */
+ if (node != NULL) {
+ INSIST(db != NULL);
+ dns_db_detachnode(db, &node);
+ }
+ if (db != NULL)
+ dns_db_detach(&db);
+ result = start_fetch(rctx);
+ if (result != ISC_R_SUCCESS) {
+ putrdataset(mctx, &rctx->rdataset);
+ if (rctx->sigrdataset != NULL)
+ putrdataset(mctx,
+ &rctx->sigrdataset);
+ send_event = ISC_TRUE;
+ }
+ goto done;
+ }
+ } else {
+ INSIST(event->fetch == rctx->fetch);
+ dns_resolver_destroyfetch(&rctx->fetch);
+ db = event->db;
+ node = event->node;
+ result = event->result;
+ vresult = event->vresult;
+ fname = dns_fixedname_name(&event->foundname);
+ INSIST(event->rdataset == rctx->rdataset);
+ INSIST(event->sigrdataset == rctx->sigrdataset);
+ }
+
+ /*
+ * If we've been canceled, forget about the result.
+ */
+ if (rctx->canceled)
+ result = ISC_R_CANCELED;
+ else {
+ /*
+ * Otherwise, get some resource for copying the
+ * result.
+ */
+ ansname = isc_mem_get(mctx, sizeof(*ansname));
+ if (ansname == NULL)
+ tresult = ISC_R_NOMEMORY;
+ else {
+ dns_name_t *aname;
+
+ aname = dns_fixedname_name(&rctx->name);
+ dns_name_init(ansname, NULL);
+ tresult = dns_name_dup(aname, mctx, ansname);
+ if (tresult != ISC_R_SUCCESS)
+ isc_mem_put(mctx, ansname,
+ sizeof(*ansname));
+ }
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ send_event = ISC_TRUE;
+ /*
+ * This case is handled in the main line below.
+ */
+ break;
+ case DNS_R_CNAME:
+ /*
+ * Add the CNAME to the answer list.
+ */
+ trdataset = rctx->rdataset;
+ ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
+ rctx->rdataset = NULL;
+ if (rctx->sigrdataset != NULL) {
+ ISC_LIST_APPEND(ansname->list,
+ rctx->sigrdataset, link);
+ rctx->sigrdataset = NULL;
+ }
+ ISC_LIST_APPEND(rctx->namelist, ansname, link);
+ ansname = NULL;
+
+ /*
+ * Copy the CNAME's target into the lookup's
+ * query name and start over.
+ */
+ tresult = dns_rdataset_first(trdataset);
+ if (tresult != ISC_R_SUCCESS)
+ goto done;
+ dns_rdataset_current(trdataset, &rdata);
+ tresult = dns_rdata_tostruct(&rdata, &cname, NULL);
+ dns_rdata_reset(&rdata);
+ if (tresult != ISC_R_SUCCESS)
+ goto done;
+ tresult = dns_name_copy(&cname.cname, name, NULL);
+ dns_rdata_freestruct(&cname);
+ if (tresult == ISC_R_SUCCESS)
+ want_restart = ISC_TRUE;
+ else
+ result = tresult;
+ goto done;
+ case DNS_R_DNAME:
+ /*
+ * Add the DNAME to the answer list.
+ */
+ trdataset = rctx->rdataset;
+ ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
+ rctx->rdataset = NULL;
+ if (rctx->sigrdataset != NULL) {
+ ISC_LIST_APPEND(ansname->list,
+ rctx->sigrdataset, link);
+ rctx->sigrdataset = NULL;
+ }
+ ISC_LIST_APPEND(rctx->namelist, ansname, link);
+ ansname = NULL;
+
+ namereln = dns_name_fullcompare(name, fname, &order,
+ &nlabels);
+ INSIST(namereln == dns_namereln_subdomain);
+ /*
+ * Get the target name of the DNAME.
+ */
+ tresult = dns_rdataset_first(trdataset);
+ if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ goto done;
+ }
+ dns_rdataset_current(trdataset, &rdata);
+ tresult = dns_rdata_tostruct(&rdata, &dname, NULL);
+ dns_rdata_reset(&rdata);
+ if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ goto done;
+ }
+ /*
+ * Construct the new query name and start over.
+ */
+ dns_fixedname_init(&fixed);
+ prefix = dns_fixedname_name(&fixed);
+ dns_name_split(name, nlabels, prefix, NULL);
+ tresult = dns_name_concatenate(prefix, &dname.dname,
+ name, NULL);
+ dns_rdata_freestruct(&dname);
+ if (tresult == ISC_R_SUCCESS)
+ want_restart = ISC_TRUE;
+ else
+ result = tresult;
+ goto done;
+ case DNS_R_NCACHENXDOMAIN:
+ case DNS_R_NCACHENXRRSET:
+ ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
+ ISC_LIST_APPEND(rctx->namelist, ansname, link);
+ ansname = NULL;
+ rctx->rdataset = NULL;
+ /* What about sigrdataset? */
+ if (rctx->sigrdataset != NULL)
+ putrdataset(mctx, &rctx->sigrdataset);
+ send_event = ISC_TRUE;
+ goto done;
+ default:
+ if (rctx->rdataset != NULL)
+ putrdataset(mctx, &rctx->rdataset);
+ if (rctx->sigrdataset != NULL)
+ putrdataset(mctx, &rctx->sigrdataset);
+ send_event = ISC_TRUE;
+ goto done;
+ }
+
+ if (rctx->type == dns_rdatatype_any) {
+ int n = 0;
+ dns_rdatasetiter_t *rdsiter = NULL;
+
+ tresult = dns_db_allrdatasets(db, node, NULL, 0,
+ &rdsiter);
+ if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ goto done;
+ }
+
+ tresult = dns_rdatasetiter_first(rdsiter);
+ while (tresult == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter,
+ rctx->rdataset);
+ if (rctx->rdataset->type != 0) {
+ ISC_LIST_APPEND(ansname->list,
+ rctx->rdataset,
+ link);
+ n++;
+ rctx->rdataset = NULL;
+ } else {
+ /*
+ * We're not interested in this
+ * rdataset.
+ */
+ dns_rdataset_disassociate(
+ rctx->rdataset);
+ }
+ tresult = dns_rdatasetiter_next(rdsiter);
+
+ if (tresult == ISC_R_SUCCESS &&
+ rctx->rdataset == NULL) {
+ tresult = getrdataset(mctx,
+ &rctx->rdataset);
+ if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ break;
+ }
+ }
+ }
+ if (n == 0) {
+ /*
+ * We didn't match any rdatasets (which means
+ * something went wrong in this
+ * implementation).
+ */
+ result = DNS_R_SERVFAIL; /* better code? */
+ } else {
+ ISC_LIST_APPEND(rctx->namelist, ansname, link);
+ ansname = NULL;
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (tresult != ISC_R_NOMORE)
+ result = DNS_R_SERVFAIL; /* ditto */
+ else
+ result = ISC_R_SUCCESS;
+ goto done;
+ } else {
+ /*
+ * This is the "normal" case -- an ordinary question
+ * to which we've got the answer.
+ */
+ ISC_LIST_APPEND(ansname->list, rctx->rdataset, link);
+ rctx->rdataset = NULL;
+ if (rctx->sigrdataset != NULL) {
+ ISC_LIST_APPEND(ansname->list,
+ rctx->sigrdataset, link);
+ rctx->sigrdataset = NULL;
+ }
+ ISC_LIST_APPEND(rctx->namelist, ansname, link);
+ ansname = NULL;
+ }
+
+ done:
+ /*
+ * Free temporary resources
+ */
+ if (ansname != NULL) {
+ dns_rdataset_t *rdataset;
+
+ while ((rdataset = ISC_LIST_HEAD(ansname->list))
+ != NULL) {
+ ISC_LIST_UNLINK(ansname->list, rdataset, link);
+ putrdataset(mctx, &rdataset);
+ }
+ dns_name_free(ansname, mctx);
+ isc_mem_put(mctx, ansname, sizeof(*ansname));
+ }
+
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&event));
+
+ /*
+ * Limit the number of restarts.
+ */
+ if (want_restart && rctx->restarts == MAX_RESTARTS) {
+ want_restart = ISC_FALSE;
+ result = ISC_R_QUOTA;
+ send_event = ISC_TRUE;
+ }
+
+ /*
+ * Prepare further find with new resources
+ */
+ if (want_restart) {
+ INSIST(rctx->rdataset == NULL &&
+ rctx->sigrdataset == NULL);
+
+ result = getrdataset(mctx, &rctx->rdataset);
+ if (result == ISC_R_SUCCESS && rctx->want_dnssec) {
+ result = getrdataset(mctx, &rctx->sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ putrdataset(mctx, &rctx->rdataset);
+ }
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ want_restart = ISC_FALSE;
+ send_event = ISC_TRUE;
+ }
+ }
+ } while (want_restart);
+
+ if (send_event) {
+ isc_task_t *task;
+
+ while ((name = ISC_LIST_HEAD(rctx->namelist)) != NULL) {
+ ISC_LIST_UNLINK(rctx->namelist, name, link);
+ ISC_LIST_APPEND(rctx->event->answerlist, name, link);
+ }
+
+ rctx->event->result = result;
+ rctx->event->vresult = vresult;
+ task = rctx->event->ev_sender;
+ rctx->event->ev_sender = rctx;
+ isc_task_sendanddetach(&task, ISC_EVENT_PTR(&rctx->event));
+ }
+
+ UNLOCK(&rctx->lock);
+}
+
+static void
+resolve_done(isc_task_t *task, isc_event_t *event) {
+ resarg_t *resarg = event->ev_arg;
+ dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
+ dns_name_t *name;
+
+ UNUSED(task);
+
+ LOCK(&resarg->lock);
+
+ resarg->result = rev->result;
+ resarg->vresult = rev->vresult;
+ while ((name = ISC_LIST_HEAD(rev->answerlist)) != NULL) {
+ ISC_LIST_UNLINK(rev->answerlist, name, link);
+ ISC_LIST_APPEND(*resarg->namelist, name, link);
+ }
+
+ dns_client_destroyrestrans(&resarg->trans);
+ isc_event_free(&event);
+
+ if (!resarg->canceled) {
+ UNLOCK(&resarg->lock);
+
+ /* Exit from the internal event loop */
+ isc_app_ctxsuspend(resarg->actx);
+ } else {
+ /*
+ * We have already exited from the loop (due to some
+ * unexpected event). Just clean the arg up.
+ */
+ UNLOCK(&resarg->lock);
+ DESTROYLOCK(&resarg->lock);
+ isc_mem_put(resarg->client->mctx, resarg, sizeof(*resarg));
+ }
+}
+
+isc_result_t
+dns_client_resolve(dns_client_t *client, dns_name_t *name,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ unsigned int options, dns_namelist_t *namelist)
+{
+ isc_result_t result;
+ isc_appctx_t *actx;
+ resarg_t *resarg;
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(namelist != NULL && ISC_LIST_EMPTY(*namelist));
+
+ if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 &&
+ (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) {
+ /*
+ * If the client is run under application's control, we need
+ * to create a new running (sub)environment for this
+ * particular resolution.
+ */
+ return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */
+ } else
+ actx = client->actx;
+
+ resarg = isc_mem_get(client->mctx, sizeof(*resarg));
+ if (resarg == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&resarg->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(client->mctx, resarg, sizeof(*resarg));
+ return (result);
+ }
+
+ resarg->actx = actx;
+ resarg->client = client;
+ resarg->result = DNS_R_SERVFAIL;
+ resarg->namelist = namelist;
+ resarg->trans = NULL;
+ resarg->canceled = ISC_FALSE;
+ result = dns_client_startresolve(client, name, rdclass, type, options,
+ client->task, resolve_done, resarg,
+ &resarg->trans);
+ if (result != ISC_R_SUCCESS) {
+ DESTROYLOCK(&resarg->lock);
+ isc_mem_put(client->mctx, resarg, sizeof(*resarg));
+ return (result);
+ }
+
+ /*
+ * Start internal event loop. It blocks until the entire process
+ * is completed.
+ */
+ result = isc_app_ctxrun(actx);
+
+ LOCK(&resarg->lock);
+ if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND)
+ result = resarg->result;
+ if (result != ISC_R_SUCCESS && resarg->vresult != ISC_R_SUCCESS) {
+ /*
+ * If this lookup failed due to some error in DNSSEC
+ * validation, return the validation error code.
+ * XXX: or should we pass the validation result separately?
+ */
+ result = resarg->vresult;
+ }
+ if (resarg->trans != NULL) {
+ /*
+ * Unusual termination (perhaps due to signal). We need some
+ * tricky cleanup process.
+ */
+ resarg->canceled = ISC_TRUE;
+ dns_client_cancelresolve(resarg->trans);
+
+ UNLOCK(&resarg->lock);
+
+ /* resarg will be freed in the event handler. */
+ } else {
+ UNLOCK(&resarg->lock);
+
+ DESTROYLOCK(&resarg->lock);
+ isc_mem_put(client->mctx, resarg, sizeof(*resarg));
+ }
+
+ return (result);
+}
+
+isc_result_t
+dns_client_startresolve(dns_client_t *client, dns_name_t *name,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_clientrestrans_t **transp)
+{
+ dns_view_t *view = NULL;
+ dns_clientresevent_t *event = NULL;
+ resctx_t *rctx = NULL;
+ isc_task_t *clone = NULL;
+ isc_mem_t *mctx;
+ isc_result_t result;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ isc_boolean_t want_dnssec;
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(transp != NULL && *transp == NULL);
+
+ LOCK(&client->lock);
+ result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
+ rdclass, &view);
+ UNLOCK(&client->lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ mctx = client->mctx;
+ rdataset = NULL;
+ sigrdataset = NULL;
+ want_dnssec = ISC_TF((options & DNS_CLIENTRESOPT_NODNSSEC) == 0);
+
+ /*
+ * Prepare some intermediate resources
+ */
+ clone = NULL;
+ isc_task_attach(task, &clone);
+ event = (dns_clientresevent_t *)
+ isc_event_allocate(mctx, clone, DNS_EVENT_CLIENTRESDONE,
+ action, arg, sizeof(*event));
+ if (event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ event->result = DNS_R_SERVFAIL;
+ ISC_LIST_INIT(event->answerlist);
+
+ rctx = isc_mem_get(mctx, sizeof(*rctx));
+ if (rctx == NULL)
+ result = ISC_R_NOMEMORY;
+ else {
+ result = isc_mutex_init(&rctx->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, rctx, sizeof(*rctx));
+ rctx = NULL;
+ }
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = getrdataset(mctx, &rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ rctx->rdataset = rdataset;
+
+ if (want_dnssec) {
+ result = getrdataset(mctx, &sigrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ rctx->sigrdataset = sigrdataset;
+
+ dns_fixedname_init(&rctx->name);
+ result = dns_name_copy(name, dns_fixedname_name(&rctx->name), NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ rctx->client = client;
+ ISC_LINK_INIT(rctx, link);
+ rctx->canceled = ISC_FALSE;
+ rctx->task = client->task;
+ rctx->type = type;
+ rctx->view = view;
+ rctx->restarts = 0;
+ rctx->fetch = NULL;
+ rctx->want_dnssec = want_dnssec;
+ ISC_LIST_INIT(rctx->namelist);
+ rctx->event = event;
+
+ rctx->magic = RCTX_MAGIC;
+
+ LOCK(&client->lock);
+ ISC_LIST_APPEND(client->resctxs, rctx, link);
+ UNLOCK(&client->lock);
+
+ client_resfind(rctx, NULL);
+
+ *transp = (dns_clientrestrans_t *)rctx;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (rdataset != NULL)
+ putrdataset(client->mctx, &rdataset);
+ if (sigrdataset != NULL)
+ putrdataset(client->mctx, &sigrdataset);
+ if (rctx != NULL) {
+ DESTROYLOCK(&rctx->lock);
+ isc_mem_put(mctx, rctx, sizeof(*rctx));
+ }
+ if (event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&event));
+ isc_task_detach(&clone);
+ dns_view_detach(&view);
+
+ return (result);
+}
+
+void
+dns_client_cancelresolve(dns_clientrestrans_t *trans) {
+ resctx_t *rctx;
+
+ REQUIRE(trans != NULL);
+ rctx = (resctx_t *)trans;
+ REQUIRE(RCTX_VALID(rctx));
+
+ LOCK(&rctx->lock);
+
+ if (!rctx->canceled) {
+ rctx->canceled = ISC_TRUE;
+ if (rctx->fetch != NULL)
+ dns_resolver_cancelfetch(rctx->fetch);
+ }
+
+ UNLOCK(&rctx->lock);
+}
+
+void
+dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist) {
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(namelist != NULL);
+
+ while ((name = ISC_LIST_HEAD(*namelist)) != NULL) {
+ ISC_LIST_UNLINK(*namelist, name, link);
+ while ((rdataset = ISC_LIST_HEAD(name->list)) != NULL) {
+ ISC_LIST_UNLINK(name->list, rdataset, link);
+ putrdataset(client->mctx, &rdataset);
+ }
+ dns_name_free(name, client->mctx);
+ isc_mem_put(client->mctx, name, sizeof(*name));
+ }
+}
+
+void
+dns_client_destroyrestrans(dns_clientrestrans_t **transp) {
+ resctx_t *rctx;
+ isc_mem_t *mctx;
+ dns_client_t *client;
+ isc_boolean_t need_destroyclient = ISC_FALSE;
+
+ REQUIRE(transp != NULL);
+ rctx = (resctx_t *)*transp;
+ REQUIRE(RCTX_VALID(rctx));
+ REQUIRE(rctx->fetch == NULL);
+ REQUIRE(rctx->event == NULL);
+ client = rctx->client;
+ REQUIRE(DNS_CLIENT_VALID(client));
+
+ mctx = client->mctx;
+ dns_view_detach(&rctx->view);
+
+ LOCK(&client->lock);
+
+ INSIST(ISC_LINK_LINKED(rctx, link));
+ ISC_LIST_UNLINK(client->resctxs, rctx, link);
+
+ if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) &&
+ ISC_LIST_EMPTY(client->reqctxs) &&
+ ISC_LIST_EMPTY(client->updatectxs))
+ need_destroyclient = ISC_TRUE;
+
+ UNLOCK(&client->lock);
+
+ INSIST(ISC_LIST_EMPTY(rctx->namelist));
+
+ DESTROYLOCK(&rctx->lock);
+ rctx->magic = 0;
+
+ isc_mem_put(mctx, rctx, sizeof(*rctx));
+
+ if (need_destroyclient)
+ destroyclient(&client);
+
+ *transp = NULL;
+}
+
+isc_result_t
+dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *keyname, isc_buffer_t *keydatabuf)
+{
+ isc_result_t result;
+ dns_view_t *view = NULL;
+ dst_key_t *dstkey = NULL;
+ dns_keytable_t *secroots = NULL;
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+
+ LOCK(&client->lock);
+ result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
+ rdclass, &view);
+ UNLOCK(&client->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_view_getsecroots(view, &secroots);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dst_key_fromdns(keyname, rdclass, keydatabuf, client->mctx,
+ &dstkey);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_keytable_add(secroots, ISC_FALSE, &dstkey);
+
+ cleanup:
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+ if (view != NULL)
+ dns_view_detach(&view);
+ if (secroots != NULL)
+ dns_keytable_detach(&secroots);
+ return (result);
+}
+
+/*%
+ * Simple request routines
+ */
+static void
+request_done(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ dns_request_t *request;
+ isc_result_t result, eresult;
+ reqctx_t *ctx;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+ result = eresult = reqev->result;
+ ctx = reqev->ev_arg;
+ REQUIRE(REQCTX_VALID(ctx));
+
+ isc_event_free(&event);
+
+ LOCK(&ctx->lock);
+
+ if (eresult == ISC_R_SUCCESS) {
+ result = dns_request_getresponse(request, ctx->event->rmessage,
+ ctx->parseoptions);
+ }
+
+ if (ctx->tsigkey != NULL)
+ dns_tsigkey_detach(&ctx->tsigkey);
+
+ if (ctx->canceled)
+ ctx->event->result = ISC_R_CANCELED;
+ else
+ ctx->event->result = result;
+ task = ctx->event->ev_sender;
+ ctx->event->ev_sender = ctx;
+ isc_task_sendanddetach(&task, ISC_EVENT_PTR(&ctx->event));
+
+ UNLOCK(&ctx->lock);
+}
+
+static void
+localrequest_done(isc_task_t *task, isc_event_t *event) {
+ reqarg_t *reqarg = event->ev_arg;
+ dns_clientreqevent_t *rev =(dns_clientreqevent_t *)event;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == DNS_EVENT_CLIENTREQDONE);
+
+ LOCK(&reqarg->lock);
+
+ reqarg->result = rev->result;
+ dns_client_destroyreqtrans(&reqarg->trans);
+ isc_event_free(&event);
+
+ if (!reqarg->canceled) {
+ UNLOCK(&reqarg->lock);
+
+ /* Exit from the internal event loop */
+ isc_app_ctxsuspend(reqarg->actx);
+ } else {
+ /*
+ * We have already exited from the loop (due to some
+ * unexpected event). Just clean the arg up.
+ */
+ UNLOCK(&reqarg->lock);
+ DESTROYLOCK(&reqarg->lock);
+ isc_mem_put(reqarg->client->mctx, reqarg, sizeof(*reqarg));
+ }
+}
+
+isc_result_t
+dns_client_request(dns_client_t *client, dns_message_t *qmessage,
+ dns_message_t *rmessage, isc_sockaddr_t *server,
+ unsigned int options, unsigned int parseoptions,
+ dns_tsec_t *tsec, unsigned int timeout,
+ unsigned int udptimeout, unsigned int udpretries)
+{
+ isc_appctx_t *actx;
+ reqarg_t *reqarg;
+ isc_result_t result;
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(qmessage != NULL);
+ REQUIRE(rmessage != NULL);
+
+ if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 &&
+ (options & DNS_CLIENTREQOPT_ALLOWRUN) == 0) {
+ /*
+ * If the client is run under application's control, we need
+ * to create a new running (sub)environment for this
+ * particular resolution.
+ */
+ return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */
+ } else
+ actx = client->actx;
+
+ reqarg = isc_mem_get(client->mctx, sizeof(*reqarg));
+ if (reqarg == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&reqarg->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(client->mctx, reqarg, sizeof(*reqarg));
+ return (result);
+ }
+
+ reqarg->actx = actx;
+ reqarg->client = client;
+ reqarg->trans = NULL;
+ reqarg->canceled = ISC_FALSE;
+
+ result = dns_client_startrequest(client, qmessage, rmessage, server,
+ options, parseoptions, tsec, timeout,
+ udptimeout, udpretries,
+ client->task, localrequest_done,
+ reqarg, &reqarg->trans);
+ if (result != ISC_R_SUCCESS) {
+ DESTROYLOCK(&reqarg->lock);
+ isc_mem_put(client->mctx, reqarg, sizeof(*reqarg));
+ return (result);
+ }
+
+ /*
+ * Start internal event loop. It blocks until the entire process
+ * is completed.
+ */
+ result = isc_app_ctxrun(actx);
+
+ LOCK(&reqarg->lock);
+ if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND)
+ result = reqarg->result;
+ if (reqarg->trans != NULL) {
+ /*
+ * Unusual termination (perhaps due to signal). We need some
+ * tricky cleanup process.
+ */
+ reqarg->canceled = ISC_TRUE;
+ dns_client_cancelresolve(reqarg->trans);
+
+ UNLOCK(&reqarg->lock);
+
+ /* reqarg will be freed in the event handler. */
+ } else {
+ UNLOCK(&reqarg->lock);
+
+ DESTROYLOCK(&reqarg->lock);
+ isc_mem_put(client->mctx, reqarg, sizeof(*reqarg));
+ }
+
+ return (result);
+}
+
+isc_result_t
+dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage,
+ dns_message_t *rmessage, isc_sockaddr_t *server,
+ unsigned int options, unsigned int parseoptions,
+ dns_tsec_t *tsec, unsigned int timeout,
+ unsigned int udptimeout, unsigned int udpretries,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_clientreqtrans_t **transp)
+{
+ isc_result_t result;
+ dns_view_t *view = NULL;
+ isc_task_t *clone = NULL;
+ dns_clientreqevent_t *event = NULL;
+ reqctx_t *ctx = NULL;
+ dns_tsectype_t tsectype = dns_tsectype_none;
+
+ UNUSED(options);
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(qmessage != NULL);
+ REQUIRE(rmessage != NULL);
+ REQUIRE(transp != NULL && *transp == NULL);
+
+ if (tsec != NULL) {
+ tsectype = dns_tsec_gettype(tsec);
+ if (tsectype != dns_tsectype_tsig)
+ return (ISC_R_NOTIMPLEMENTED); /* XXX */
+ }
+
+ LOCK(&client->lock);
+ result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
+ qmessage->rdclass, &view);
+ UNLOCK(&client->lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ clone = NULL;
+ isc_task_attach(task, &clone);
+ event = (dns_clientreqevent_t *)
+ isc_event_allocate(client->mctx, clone,
+ DNS_EVENT_CLIENTREQDONE,
+ action, arg, sizeof(*event));
+ if (event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ ctx = isc_mem_get(client->mctx, sizeof(*ctx));
+ if (ctx == NULL)
+ result = ISC_R_NOMEMORY;
+ else {
+ result = isc_mutex_init(&ctx->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(client->mctx, ctx, sizeof(*ctx));
+ ctx = NULL;
+ }
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ ctx->client = client;
+ ISC_LINK_INIT(ctx, link);
+ ctx->parseoptions = parseoptions;
+ ctx->canceled = ISC_FALSE;
+ ctx->event = event;
+ ctx->event->rmessage = rmessage;
+ ctx->tsigkey = NULL;
+ if (tsec != NULL)
+ dns_tsec_getkey(tsec, &ctx->tsigkey);
+
+ ctx->magic = REQCTX_MAGIC;
+
+ LOCK(&client->lock);
+ ISC_LIST_APPEND(client->reqctxs, ctx, link);
+ UNLOCK(&client->lock);
+
+ ctx->request = NULL;
+ result = dns_request_createvia3(view->requestmgr, qmessage, NULL,
+ server, options, ctx->tsigkey,
+ timeout, udptimeout, udpretries,
+ client->task, request_done, ctx,
+ &ctx->request);
+ if (result == ISC_R_SUCCESS) {
+ dns_view_detach(&view);
+ *transp = (dns_clientreqtrans_t *)ctx;
+ return (ISC_R_SUCCESS);
+ }
+
+ cleanup:
+ if (ctx != NULL) {
+ LOCK(&client->lock);
+ ISC_LIST_UNLINK(client->reqctxs, ctx, link);
+ UNLOCK(&client->lock);
+ DESTROYLOCK(&ctx->lock);
+ isc_mem_put(client->mctx, ctx, sizeof(*ctx));
+ }
+ if (event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&event));
+ isc_task_detach(&clone);
+ dns_view_detach(&view);
+
+ return (result);
+}
+
+void
+dns_client_cancelrequest(dns_clientreqtrans_t *trans) {
+ reqctx_t *ctx;
+
+ REQUIRE(trans != NULL);
+ ctx = (reqctx_t *)trans;
+ REQUIRE(REQCTX_VALID(ctx));
+
+ LOCK(&ctx->lock);
+
+ if (!ctx->canceled) {
+ ctx->canceled = ISC_TRUE;
+ if (ctx->request != NULL)
+ dns_request_cancel(ctx->request);
+ }
+
+ UNLOCK(&ctx->lock);
+}
+
+void
+dns_client_destroyreqtrans(dns_clientreqtrans_t **transp) {
+ reqctx_t *ctx;
+ isc_mem_t *mctx;
+ dns_client_t *client;
+ isc_boolean_t need_destroyclient = ISC_FALSE;
+
+ REQUIRE(transp != NULL);
+ ctx = (reqctx_t *)*transp;
+ REQUIRE(REQCTX_VALID(ctx));
+ client = ctx->client;
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(ctx->event == NULL);
+ REQUIRE(ctx->request != NULL);
+
+ dns_request_destroy(&ctx->request);
+ mctx = client->mctx;
+
+ LOCK(&client->lock);
+
+ INSIST(ISC_LINK_LINKED(ctx, link));
+ ISC_LIST_UNLINK(client->reqctxs, ctx, link);
+
+ if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) &&
+ ISC_LIST_EMPTY(client->reqctxs) &&
+ ISC_LIST_EMPTY(client->updatectxs)) {
+ need_destroyclient = ISC_TRUE;
+ }
+
+ UNLOCK(&client->lock);
+
+ DESTROYLOCK(&ctx->lock);
+ ctx->magic = 0;
+
+ isc_mem_put(mctx, ctx, sizeof(*ctx));
+
+ if (need_destroyclient)
+ destroyclient(&client);
+
+ *transp = NULL;
+}
+
+/*%
+ * Dynamic update routines
+ */
+static isc_result_t
+rcode2result(dns_rcode_t rcode) {
+ /* XXX: isn't there a similar function? */
+ switch (rcode) {
+ case dns_rcode_formerr:
+ return (DNS_R_FORMERR);
+ case dns_rcode_servfail:
+ return (DNS_R_SERVFAIL);
+ case dns_rcode_nxdomain:
+ return (DNS_R_NXDOMAIN);
+ case dns_rcode_notimp:
+ return (DNS_R_NOTIMP);
+ case dns_rcode_refused:
+ return (DNS_R_REFUSED);
+ case dns_rcode_yxdomain:
+ return (DNS_R_YXDOMAIN);
+ case dns_rcode_yxrrset:
+ return (DNS_R_YXRRSET);
+ case dns_rcode_nxrrset:
+ return (DNS_R_NXRRSET);
+ case dns_rcode_notauth:
+ return (DNS_R_NOTAUTH);
+ case dns_rcode_notzone:
+ return (DNS_R_NOTZONE);
+ case dns_rcode_badvers:
+ return (DNS_R_BADVERS);
+ }
+
+ return (ISC_R_FAILURE);
+}
+
+static void
+update_sendevent(updatectx_t *uctx, isc_result_t result) {
+ isc_task_t *task;
+
+ dns_message_destroy(&uctx->updatemsg);
+ if (uctx->tsigkey != NULL)
+ dns_tsigkey_detach(&uctx->tsigkey);
+ if (uctx->sig0key != NULL)
+ dst_key_free(&uctx->sig0key);
+
+ if (uctx->canceled)
+ uctx->event->result = ISC_R_CANCELED;
+ else
+ uctx->event->result = result;
+ uctx->event->state = uctx->state;
+ task = uctx->event->ev_sender;
+ uctx->event->ev_sender = uctx;
+ isc_task_sendanddetach(&task, ISC_EVENT_PTR(&uctx->event));
+}
+
+static void
+update_done(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ dns_requestevent_t *reqev = NULL;
+ dns_request_t *request;
+ dns_message_t *answer = NULL;
+ updatectx_t *uctx = event->ev_arg;
+ dns_client_t *client;
+ unsigned int timeout;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+ REQUIRE(UCTX_VALID(uctx));
+ client = uctx->client;
+ REQUIRE(DNS_CLIENT_VALID(client));
+
+ result = reqev->result;
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
+ &answer);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ uctx->state = dns_clientupdatestate_done;
+ result = dns_request_getresponse(request, answer,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ if (result == ISC_R_SUCCESS && answer->rcode != dns_rcode_noerror)
+ result = rcode2result(answer->rcode);
+
+ out:
+ if (answer != NULL)
+ dns_message_destroy(&answer);
+ isc_event_free(&event);
+
+ LOCK(&uctx->lock);
+ uctx->currentserver = ISC_LIST_NEXT(uctx->currentserver, link);
+ dns_request_destroy(&uctx->updatereq);
+ if (result != ISC_R_SUCCESS && !uctx->canceled &&
+ uctx->currentserver != NULL) {
+ dns_message_renderreset(uctx->updatemsg);
+ dns_message_settsigkey(uctx->updatemsg, NULL);
+
+ timeout = client->update_timeout / uctx->nservers;
+ if (timeout < MIN_UPDATE_TIMEOUT)
+ timeout = MIN_UPDATE_TIMEOUT;
+ result = dns_request_createvia3(uctx->view->requestmgr,
+ uctx->updatemsg,
+ NULL,
+ uctx->currentserver, 0,
+ uctx->tsigkey,
+ timeout,
+ client->update_udptimeout,
+ client->update_udpretries,
+ client->task,
+ update_done, uctx,
+ &uctx->updatereq);
+ UNLOCK(&uctx->lock);
+
+ if (result == ISC_R_SUCCESS) {
+ /* XXX: should we keep the 'done' state here? */
+ uctx->state = dns_clientupdatestate_sent;
+ return;
+ }
+ } else
+ UNLOCK(&uctx->lock);
+
+ update_sendevent(uctx, result);
+}
+
+static isc_result_t
+send_update(updatectx_t *uctx) {
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_client_t *client = uctx->client;
+ unsigned int timeout;
+
+ REQUIRE(uctx->zonename != NULL && uctx->currentserver != NULL);
+
+ result = dns_message_gettempname(uctx->updatemsg, &name);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_init(name, NULL);
+ dns_name_clone(uctx->zonename, name);
+ result = dns_message_gettemprdataset(uctx->updatemsg, &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(uctx->updatemsg, &name);
+ return (result);
+ }
+ dns_rdataset_makequestion(rdataset, uctx->rdclass, dns_rdatatype_soa);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(uctx->updatemsg, name, DNS_SECTION_ZONE);
+ if (uctx->tsigkey == NULL && uctx->sig0key != NULL) {
+ result = dns_message_setsig0key(uctx->updatemsg,
+ uctx->sig0key);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ timeout = client->update_timeout / uctx->nservers;
+ if (timeout < MIN_UPDATE_TIMEOUT)
+ timeout = MIN_UPDATE_TIMEOUT;
+ result = dns_request_createvia3(uctx->view->requestmgr,
+ uctx->updatemsg,
+ NULL, uctx->currentserver, 0,
+ uctx->tsigkey, timeout,
+ client->update_udptimeout,
+ client->update_udpretries,
+ client->task, update_done, uctx,
+ &uctx->updatereq);
+ if (result == ISC_R_SUCCESS &&
+ uctx->state == dns_clientupdatestate_prepare) {
+ uctx->state = dns_clientupdatestate_sent;
+ }
+
+ return (result);
+}
+
+static void
+resolveaddr_done(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ int family;
+ dns_rdatatype_t qtype;
+ dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ updatectx_t *uctx;
+ isc_boolean_t completed = ISC_FALSE;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_arg != NULL);
+ uctx = *(updatectx_t **)event->ev_arg;
+ REQUIRE(UCTX_VALID(uctx));
+
+ if (event->ev_arg == &uctx->bp4) {
+ family = AF_INET;
+ qtype = dns_rdatatype_a;
+ LOCK(&uctx->lock);
+ dns_client_destroyrestrans(&uctx->restrans);
+ UNLOCK(&uctx->lock);
+ } else {
+ INSIST(event->ev_arg == &uctx->bp6);
+ family = AF_INET6;
+ qtype = dns_rdatatype_aaaa;
+ LOCK(&uctx->lock);
+ dns_client_destroyrestrans(&uctx->restrans2);
+ UNLOCK(&uctx->lock);
+ }
+
+ result = rev->result;
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (!dns_rdataset_isassociated(rdataset))
+ continue;
+ if (rdataset->type != qtype)
+ continue;
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata;
+ dns_rdata_in_a_t rdata_a;
+ dns_rdata_in_aaaa_t rdata_aaaa;
+ isc_sockaddr_t *sa;
+
+ sa = isc_mem_get(uctx->client->mctx,
+ sizeof(*sa));
+ if (sa == NULL) {
+ /*
+ * If we fail to get a sockaddr,
+ we simply move forward with the
+ * addresses we've got so far.
+ */
+ goto done;
+ }
+
+ dns_rdata_init(&rdata);
+ switch (family) {
+ case AF_INET:
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &rdata_a,
+ NULL);
+ isc_sockaddr_fromin(sa,
+ &rdata_a.in_addr,
+ 53);
+ dns_rdata_freestruct(&rdata_a);
+ break;
+ case AF_INET6:
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &rdata_aaaa,
+ NULL);
+ isc_sockaddr_fromin6(sa,
+ &rdata_aaaa.in6_addr,
+ 53);
+ dns_rdata_freestruct(&rdata_aaaa);
+ break;
+ }
+
+ ISC_LINK_INIT(sa, link);
+ ISC_LIST_APPEND(uctx->servers, sa, link);
+ uctx->nservers++;
+ }
+ }
+ }
+
+ done:
+ dns_client_freeresanswer(uctx->client, &rev->answerlist);
+ isc_event_free(&event);
+
+ LOCK(&uctx->lock);
+ if (uctx->restrans == NULL && uctx->restrans2 == NULL)
+ completed = ISC_TRUE;
+ UNLOCK(&uctx->lock);
+
+ if (completed) {
+ INSIST(uctx->currentserver == NULL);
+ uctx->currentserver = ISC_LIST_HEAD(uctx->servers);
+ if (uctx->currentserver != NULL && !uctx->canceled)
+ send_update(uctx);
+ else {
+ if (result == ISC_R_SUCCESS)
+ result = ISC_R_NOTFOUND;
+ update_sendevent(uctx, result);
+ }
+ }
+}
+
+static isc_result_t
+process_soa(updatectx_t *uctx, dns_rdataset_t *soaset, dns_name_t *soaname) {
+ isc_result_t result;
+ dns_rdata_t soarr = DNS_RDATA_INIT;
+ dns_rdata_soa_t soa;
+ dns_name_t primary;
+
+ result = dns_rdataset_first(soaset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdata_init(&soarr);
+ dns_rdataset_current(soaset, &soarr);
+ result = dns_rdata_tostruct(&soarr, &soa, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_name_init(&primary, NULL);
+ dns_name_clone(&soa.origin, &primary);
+
+ if (uctx->zonename == NULL) {
+ uctx->zonename = dns_fixedname_name(&uctx->zonefname);
+ result = dns_name_copy(soaname, uctx->zonename, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ }
+
+ if (uctx->currentserver != NULL)
+ result = send_update(uctx);
+ else {
+ /*
+ * Get addresses of the primary server. We don't use the ADB
+ * feature so that we could avoid caching data.
+ */
+ LOCK(&uctx->lock);
+ uctx->bp4 = uctx;
+ result = dns_client_startresolve(uctx->client, &primary,
+ uctx->rdclass,
+ dns_rdatatype_a,
+ 0, uctx->client->task,
+ resolveaddr_done, &uctx->bp4,
+ &uctx->restrans);
+ if (result == ISC_R_SUCCESS) {
+ uctx->bp6 = uctx;
+ result = dns_client_startresolve(uctx->client,
+ &primary,
+ uctx->rdclass,
+ dns_rdatatype_aaaa,
+ 0, uctx->client->task,
+ resolveaddr_done,
+ &uctx->bp6,
+ &uctx->restrans2);
+ }
+ UNLOCK(&uctx->lock);
+ }
+
+ out:
+ dns_rdata_freestruct(&soa);
+
+ return (result);
+}
+
+static void
+receive_soa(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ updatectx_t *uctx;
+ dns_client_t *client;
+ isc_result_t result, eresult;
+ dns_request_t *request;
+ dns_message_t *rcvmsg = NULL;
+ dns_section_t section;
+ dns_rdataset_t *soaset = NULL;
+ int pass = 0;
+ dns_name_t *name;
+ dns_message_t *soaquery = NULL;
+ isc_sockaddr_t *addr;
+ isc_boolean_t seencname = ISC_FALSE;
+ isc_boolean_t droplabel = ISC_FALSE;
+ dns_name_t tname;
+ unsigned int nlabels;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+ result = eresult = reqev->result;
+ uctx = reqev->ev_arg;
+ client = uctx->client;
+ soaquery = uctx->soaquery;
+ addr = uctx->currentserver;
+ INSIST(addr != NULL);
+
+ isc_event_free(&event);
+
+ if (eresult != ISC_R_SUCCESS) {
+ result = eresult;
+ goto out;
+ }
+
+ result = dns_message_create(uctx->client->mctx,
+ DNS_MESSAGE_INTENTPARSE, &rcvmsg);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ result = dns_request_getresponse(request, rcvmsg,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+
+ if (result == DNS_R_TSIGERRORSET) {
+ dns_request_t *newrequest = NULL;
+
+ /* Retry SOA request without TSIG */
+ dns_message_destroy(&rcvmsg);
+ dns_message_renderreset(uctx->soaquery);
+ result = dns_request_createvia3(uctx->view->requestmgr,
+ uctx->soaquery, NULL, addr, 0,
+ NULL,
+ client->find_timeout * 20,
+ client->find_timeout, 3,
+ uctx->client->task,
+ receive_soa, uctx,
+ &newrequest);
+ if (result == ISC_R_SUCCESS) {
+ LOCK(&uctx->lock);
+ dns_request_destroy(&uctx->soareq);
+ uctx->soareq = newrequest;
+ UNLOCK(&uctx->lock);
+
+ return;
+ }
+ goto out;
+ }
+
+ section = DNS_SECTION_ANSWER;
+
+ if (rcvmsg->rcode != dns_rcode_noerror &&
+ rcvmsg->rcode != dns_rcode_nxdomain) {
+ result = rcode2result(rcvmsg->rcode);
+ goto out;
+ }
+
+ lookforsoa:
+ if (pass == 0)
+ section = DNS_SECTION_ANSWER;
+ else if (pass == 1)
+ section = DNS_SECTION_AUTHORITY;
+ else {
+ droplabel = ISC_TRUE;
+ goto out;
+ }
+
+ result = dns_message_firstname(rcvmsg, section);
+ if (result != ISC_R_SUCCESS) {
+ pass++;
+ goto lookforsoa;
+ }
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(rcvmsg, section, &name);
+ soaset = NULL;
+ result = dns_message_findtype(name, dns_rdatatype_soa, 0,
+ &soaset);
+ if (result == ISC_R_SUCCESS)
+ break;
+ if (section == DNS_SECTION_ANSWER) {
+ dns_rdataset_t *tset = NULL;
+ if (dns_message_findtype(name, dns_rdatatype_cname, 0,
+ &tset) == ISC_R_SUCCESS
+ ||
+ dns_message_findtype(name, dns_rdatatype_dname, 0,
+ &tset) == ISC_R_SUCCESS
+ )
+ {
+ seencname = ISC_TRUE;
+ break;
+ }
+ }
+
+ result = dns_message_nextname(rcvmsg, section);
+ }
+
+ if (soaset == NULL && !seencname) {
+ pass++;
+ goto lookforsoa;
+ }
+
+ if (seencname) {
+ droplabel = ISC_TRUE;
+ goto out;
+ }
+
+ result = process_soa(uctx, soaset, name);
+
+ out:
+ if (droplabel) {
+ result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
+ INSIST(result == ISC_R_SUCCESS);
+ name = NULL;
+ dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
+ nlabels = dns_name_countlabels(name);
+ if (nlabels == 1)
+ result = DNS_R_SERVFAIL; /* is there a better error? */
+ else {
+ dns_name_init(&tname, NULL);
+ dns_name_getlabelsequence(name, 1, nlabels - 1,
+ &tname);
+ dns_name_clone(&tname, name);
+ dns_request_destroy(&request);
+ LOCK(&uctx->lock);
+ uctx->soareq = NULL;
+ UNLOCK(&uctx->lock);
+ dns_message_renderreset(soaquery);
+ dns_message_settsigkey(soaquery, NULL);
+ result = dns_request_createvia3(uctx->view->requestmgr,
+ soaquery, NULL,
+ uctx->currentserver, 0,
+ uctx->tsigkey,
+ client->find_timeout *
+ 20,
+ client->find_timeout,
+ 3, client->task,
+ receive_soa, uctx,
+ &uctx->soareq);
+ }
+ }
+
+ if (!droplabel || result != ISC_R_SUCCESS) {
+ dns_message_destroy(&uctx->soaquery);
+ LOCK(&uctx->lock);
+ dns_request_destroy(&uctx->soareq);
+ UNLOCK(&uctx->lock);
+ }
+
+ if (rcvmsg != NULL)
+ dns_message_destroy(&rcvmsg);
+
+ if (result != ISC_R_SUCCESS)
+ update_sendevent(uctx, result);
+}
+
+static isc_result_t
+request_soa(updatectx_t *uctx) {
+ isc_result_t result;
+ dns_message_t *soaquery = uctx->soaquery;
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset = NULL;
+
+ if (soaquery == NULL) {
+ result = dns_message_create(uctx->client->mctx,
+ DNS_MESSAGE_INTENTRENDER,
+ &soaquery);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ soaquery->flags |= DNS_MESSAGEFLAG_RD;
+ result = dns_message_gettempname(soaquery, &name);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ result = dns_message_gettemprdataset(soaquery, &rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ dns_rdataset_makequestion(rdataset, uctx->rdclass, dns_rdatatype_soa);
+ dns_name_clone(uctx->firstname, name);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
+ rdataset = NULL;
+ name = NULL;
+
+ result = dns_request_createvia3(uctx->view->requestmgr,
+ soaquery, NULL, uctx->currentserver, 0,
+ uctx->tsigkey,
+ uctx->client->find_timeout * 20,
+ uctx->client->find_timeout, 3,
+ uctx->client->task, receive_soa, uctx,
+ &uctx->soareq);
+ if (result == ISC_R_SUCCESS) {
+ uctx->soaquery = soaquery;
+ return (ISC_R_SUCCESS);
+ }
+
+ fail:
+ if (rdataset != NULL) {
+ ISC_LIST_UNLINK(name->list, rdataset, link); /* for safety */
+ dns_message_puttemprdataset(soaquery, &rdataset);
+ }
+ if (name != NULL)
+ dns_message_puttempname(soaquery, &name);
+ dns_message_destroy(&soaquery);
+
+ return (result);
+}
+
+static void
+resolvesoa_done(isc_task_t *task, isc_event_t *event) {
+ dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
+ updatectx_t *uctx;
+ dns_name_t *name, tname;
+ dns_rdataset_t *rdataset = NULL;
+ isc_result_t result = rev->result;
+ unsigned int nlabels;
+
+ UNUSED(task);
+
+ uctx = event->ev_arg;
+ REQUIRE(UCTX_VALID(uctx));
+
+ LOCK(&uctx->lock);
+ dns_client_destroyrestrans(&uctx->restrans);
+ UNLOCK(&uctx->lock);
+
+ uctx = event->ev_arg;
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_NCACHENXDOMAIN &&
+ result != DNS_R_NCACHENXRRSET) {
+ /* XXX: what about DNSSEC failure? */
+ goto out;
+ }
+
+ for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (dns_rdataset_isassociated(rdataset) &&
+ rdataset->type == dns_rdatatype_soa)
+ break;
+ }
+ }
+
+ if (rdataset == NULL) {
+ /* Drop one label and retry resolution. */
+ nlabels = dns_name_countlabels(&uctx->soaqname);
+ if (nlabels == 1) {
+ result = DNS_R_SERVFAIL; /* is there a better error? */
+ goto out;
+ }
+ dns_name_init(&tname, NULL);
+ dns_name_getlabelsequence(&uctx->soaqname, 1, nlabels - 1,
+ &tname);
+ dns_name_clone(&tname, &uctx->soaqname);
+
+ result = dns_client_startresolve(uctx->client, &uctx->soaqname,
+ uctx->rdclass,
+ dns_rdatatype_soa, 0,
+ uctx->client->task,
+ resolvesoa_done, uctx,
+ &uctx->restrans);
+ } else
+ result = process_soa(uctx, rdataset, &uctx->soaqname);
+
+ out:
+ dns_client_freeresanswer(uctx->client, &rev->answerlist);
+ isc_event_free(&event);
+
+ if (result != ISC_R_SUCCESS)
+ update_sendevent(uctx, result);
+}
+
+static isc_result_t
+copy_name(isc_mem_t *mctx, dns_message_t *msg, dns_name_t *name,
+ dns_name_t **newnamep)
+{
+ isc_result_t result;
+ dns_name_t *newname = NULL;
+ isc_region_t r;
+ isc_buffer_t *namebuf = NULL, *rdatabuf = NULL;
+ dns_rdatalist_t *rdatalist;
+ dns_rdataset_t *rdataset, *newrdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT, *newrdata;
+
+ result = dns_message_gettempname(msg, &newname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ dns_name_init(newname, NULL);
+ dns_name_setbuffer(newname, namebuf);
+ dns_message_takebuffer(msg, &namebuf);
+ result = dns_name_copy(name, newname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ rdatalist = NULL;
+ result = dns_message_gettemprdatalist(msg, &rdatalist);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ dns_rdatalist_init(rdatalist);
+ rdatalist->type = rdataset->type;
+ rdatalist->rdclass = rdataset->rdclass;
+ rdatalist->covers = rdataset->covers;
+ rdatalist->ttl = rdataset->ttl;
+
+ result = dns_rdataset_first(rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+
+ newrdata = NULL;
+ result = dns_message_gettemprdata(msg, &newrdata);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ dns_rdata_toregion(&rdata, &r);
+ rdatabuf = NULL;
+ result = isc_buffer_allocate(mctx, &rdatabuf,
+ r.length);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ isc_buffer_putmem(rdatabuf, r.base, r.length);
+ isc_buffer_usedregion(rdatabuf, &r);
+ dns_rdata_init(newrdata);
+ dns_rdata_fromregion(newrdata, rdata.rdclass,
+ rdata.type, &r);
+ newrdata->flags = rdata.flags;
+
+ ISC_LIST_APPEND(rdatalist->rdata, newrdata, link);
+ dns_message_takebuffer(msg, &rdatabuf);
+
+ result = dns_rdataset_next(rdataset);
+ }
+
+ newrdataset = NULL;
+ result = dns_message_gettemprdataset(msg, &newrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ dns_rdataset_init(newrdataset);
+ dns_rdatalist_tordataset(rdatalist, newrdataset);
+
+ ISC_LIST_APPEND(newname->list, newrdataset, link);
+ }
+
+ *newnamep = newname;
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ dns_message_puttempname(msg, &newname);
+
+ return (result);
+
+}
+
+static void
+internal_update_callback(isc_task_t *task, isc_event_t *event) {
+ updatearg_t *uarg = event->ev_arg;
+ dns_clientupdateevent_t *uev = (dns_clientupdateevent_t *)event;
+
+ UNUSED(task);
+
+ LOCK(&uarg->lock);
+
+ uarg->result = uev->result;
+
+ dns_client_destroyupdatetrans(&uarg->trans);
+ isc_event_free(&event);
+
+ if (!uarg->canceled) {
+ UNLOCK(&uarg->lock);
+
+ /* Exit from the internal event loop */
+ isc_app_ctxsuspend(uarg->actx);
+ } else {
+ /*
+ * We have already exited from the loop (due to some
+ * unexpected event). Just clean the arg up.
+ */
+ UNLOCK(&uarg->lock);
+ DESTROYLOCK(&uarg->lock);
+ isc_mem_put(uarg->client->mctx, uarg, sizeof(*uarg));
+ }
+}
+
+isc_result_t
+dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *zonename, dns_namelist_t *prerequisites,
+ dns_namelist_t *updates, isc_sockaddrlist_t *servers,
+ dns_tsec_t *tsec, unsigned int options)
+{
+ isc_result_t result;
+ isc_appctx_t *actx;
+ updatearg_t *uarg;
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+
+ if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 &&
+ (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) {
+ /*
+ * If the client is run under application's control, we need
+ * to create a new running (sub)environment for this
+ * particular resolution.
+ */
+ return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */
+ } else
+ actx = client->actx;
+
+ uarg = isc_mem_get(client->mctx, sizeof(*uarg));
+ if (uarg == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&uarg->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(client->mctx, uarg, sizeof(*uarg));
+ return (result);
+ }
+
+ uarg->actx = actx;
+ uarg->client = client;
+ uarg->result = ISC_R_FAILURE;
+ uarg->trans = NULL;
+ uarg->canceled = ISC_FALSE;
+
+ result = dns_client_startupdate(client, rdclass, zonename,
+ prerequisites, updates, servers,
+ tsec, options, client->task,
+ internal_update_callback, uarg,
+ &uarg->trans);
+ if (result != ISC_R_SUCCESS) {
+ DESTROYLOCK(&uarg->lock);
+ isc_mem_put(client->mctx, uarg, sizeof(*uarg));
+ return (result);
+ }
+
+ /*
+ * Start internal event loop. It blocks until the entire process
+ * is completed.
+ */
+ result = isc_app_ctxrun(actx);
+
+ LOCK(&uarg->lock);
+ if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND)
+ result = uarg->result;
+
+ if (uarg->trans != NULL) {
+ /*
+ * Unusual termination (perhaps due to signal). We need some
+ * tricky cleanup process.
+ */
+ uarg->canceled = ISC_TRUE;
+ dns_client_cancelupdate(uarg->trans);
+
+ UNLOCK(&uarg->lock);
+
+ /* uarg will be freed in the event handler. */
+ } else {
+ UNLOCK(&uarg->lock);
+
+ DESTROYLOCK(&uarg->lock);
+ isc_mem_put(client->mctx, uarg, sizeof(*uarg));
+ }
+
+ return (result);
+}
+
+isc_result_t
+dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *zonename, dns_namelist_t *prerequisites,
+ dns_namelist_t *updates, isc_sockaddrlist_t *servers,
+ dns_tsec_t *tsec, unsigned int options,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_clientupdatetrans_t **transp)
+{
+ dns_view_t *view = NULL;
+ isc_result_t result;
+ dns_name_t *name, *newname;
+ updatectx_t *uctx;
+ isc_task_t *clone = NULL;
+ dns_section_t section = DNS_SECTION_UPDATE;
+ isc_sockaddr_t *server, *sa = NULL;
+ dns_tsectype_t tsectype = dns_tsectype_none;
+
+ UNUSED(options);
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(transp != NULL && *transp == NULL);
+ REQUIRE(updates != NULL);
+ REQUIRE(task != NULL);
+
+ if (tsec != NULL) {
+ tsectype = dns_tsec_gettype(tsec);
+ if (tsectype != dns_tsectype_tsig)
+ return (ISC_R_NOTIMPLEMENTED); /* XXX */
+ }
+
+ LOCK(&client->lock);
+ result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
+ rdclass, &view);
+ UNLOCK(&client->lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Create a context and prepare some resources */
+ uctx = isc_mem_get(client->mctx, sizeof(*uctx));
+ if (uctx == NULL) {
+ dns_view_detach(&view);
+ return (ISC_R_NOMEMORY);
+ }
+ result = isc_mutex_init(&uctx->lock);
+ if (result != ISC_R_SUCCESS) {
+ dns_view_detach(&view);
+ isc_mem_put(client->mctx, uctx, sizeof(*uctx));
+ return (ISC_R_NOMEMORY);
+ }
+ clone = NULL;
+ isc_task_attach(task, &clone);
+ uctx->client = client;
+ ISC_LINK_INIT(uctx, link);
+ uctx->state = dns_clientupdatestate_prepare;
+ uctx->view = view;
+ uctx->rdclass = rdclass;
+ uctx->canceled = ISC_FALSE;
+ uctx->updatemsg = NULL;
+ uctx->soaquery = NULL;
+ uctx->updatereq = NULL;
+ uctx->restrans = NULL;
+ uctx->restrans2 = NULL;
+ uctx->bp4 = NULL;
+ uctx->bp6 = NULL;
+ uctx->soareq = NULL;
+ uctx->event = NULL;
+ uctx->tsigkey = NULL;
+ uctx->sig0key = NULL;
+ uctx->zonename = NULL;
+ dns_name_init(&uctx->soaqname, NULL);
+ ISC_LIST_INIT(uctx->servers);
+ uctx->nservers = 0;
+ uctx->currentserver = NULL;
+ dns_fixedname_init(&uctx->zonefname);
+ if (tsec != NULL)
+ dns_tsec_getkey(tsec, &uctx->tsigkey);
+ uctx->event = (dns_clientupdateevent_t *)
+ isc_event_allocate(client->mctx, clone, DNS_EVENT_UPDATEDONE,
+ action, arg, sizeof(*uctx->event));
+ if (uctx->event == NULL)
+ goto fail;
+ if (zonename != NULL) {
+ uctx->zonename = dns_fixedname_name(&uctx->zonefname);
+ result = dns_name_copy(zonename, uctx->zonename, NULL);
+ }
+ if (servers != NULL) {
+ for (server = ISC_LIST_HEAD(*servers);
+ server != NULL;
+ server = ISC_LIST_NEXT(server, link)) {
+ sa = isc_mem_get(client->mctx, sizeof(*sa));
+ if (sa == NULL)
+ goto fail;
+ sa->type = server->type;
+ sa->length = server->length;
+ ISC_LINK_INIT(sa, link);
+ ISC_LIST_APPEND(uctx->servers, sa, link);
+ if (uctx->currentserver == NULL)
+ uctx->currentserver = sa;
+ uctx->nservers++;
+ }
+ }
+
+ /* Make update message */
+ result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTRENDER,
+ &uctx->updatemsg);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ uctx->updatemsg->opcode = dns_opcode_update;
+
+ if (prerequisites != NULL) {
+ for (name = ISC_LIST_HEAD(*prerequisites); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ newname = NULL;
+ result = copy_name(client->mctx, uctx->updatemsg,
+ name, &newname);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ dns_message_addname(uctx->updatemsg, newname,
+ DNS_SECTION_PREREQUISITE);
+ }
+ }
+
+ for (name = ISC_LIST_HEAD(*updates); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ newname = NULL;
+ result = copy_name(client->mctx, uctx->updatemsg, name,
+ &newname);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ dns_message_addname(uctx->updatemsg, newname,
+ DNS_SECTION_UPDATE);
+ }
+
+ uctx->firstname = NULL;
+ result = dns_message_firstname(uctx->updatemsg, section);
+ if (result == ISC_R_NOMORE) {
+ section = DNS_SECTION_PREREQUISITE;
+ result = dns_message_firstname(uctx->updatemsg, section);
+ }
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ dns_message_currentname(uctx->updatemsg, section, &uctx->firstname);
+
+ uctx->magic = UCTX_MAGIC;
+
+ LOCK(&client->lock);
+ ISC_LIST_APPEND(client->updatectxs, uctx, link);
+ UNLOCK(&client->lock);
+
+ if (uctx->zonename != NULL && uctx->currentserver != NULL) {
+ result = send_update(uctx);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ } else if (uctx->currentserver != NULL) {
+ result = request_soa(uctx);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ } else {
+ dns_name_clone(uctx->firstname, &uctx->soaqname);
+ result = dns_client_startresolve(uctx->client, &uctx->soaqname,
+ uctx->rdclass,
+ dns_rdatatype_soa, 0,
+ client->task, resolvesoa_done,
+ uctx, &uctx->restrans);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ }
+
+ *transp = (dns_clientupdatetrans_t *)uctx;
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ if (ISC_LINK_LINKED(uctx, link)) {
+ LOCK(&client->lock);
+ ISC_LIST_UNLINK(client->updatectxs, uctx, link);
+ UNLOCK(&client->lock);
+ }
+ if (uctx->updatemsg != NULL)
+ dns_message_destroy(&uctx->updatemsg);
+ while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) {
+ ISC_LIST_UNLINK(uctx->servers, sa, link);
+ isc_mem_put(client->mctx, sa, sizeof(*sa));
+ }
+ if (uctx->event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&uctx->event));
+ if (uctx->tsigkey != NULL)
+ dns_tsigkey_detach(&uctx->tsigkey);
+ isc_task_detach(&clone);
+ DESTROYLOCK(&uctx->lock);
+ uctx->magic = 0;
+ isc_mem_put(client->mctx, uctx, sizeof(*uctx));
+ dns_view_detach(&view);
+
+ return (result);
+}
+
+void
+dns_client_cancelupdate(dns_clientupdatetrans_t *trans) {
+ updatectx_t *uctx;
+
+ REQUIRE(trans != NULL);
+ uctx = (updatectx_t *)trans;
+ REQUIRE(UCTX_VALID(uctx));
+
+ LOCK(&uctx->lock);
+
+ if (!uctx->canceled) {
+ uctx->canceled = ISC_TRUE;
+ if (uctx->updatereq != NULL)
+ dns_request_cancel(uctx->updatereq);
+ if (uctx->soareq != NULL)
+ dns_request_cancel(uctx->soareq);
+ if (uctx->restrans != NULL)
+ dns_client_cancelresolve(uctx->restrans);
+ if (uctx->restrans2 != NULL)
+ dns_client_cancelresolve(uctx->restrans2);
+ }
+
+ UNLOCK(&uctx->lock);
+}
+
+void
+dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp) {
+ updatectx_t *uctx;
+ isc_mem_t *mctx;
+ dns_client_t *client;
+ isc_boolean_t need_destroyclient = ISC_FALSE;
+ isc_sockaddr_t *sa;
+
+ REQUIRE(transp != NULL);
+ uctx = (updatectx_t *)*transp;
+ REQUIRE(UCTX_VALID(uctx));
+ client = uctx->client;
+ REQUIRE(DNS_CLIENT_VALID(client));
+ REQUIRE(uctx->updatereq == NULL && uctx->updatemsg == NULL &&
+ uctx->soareq == NULL && uctx->soaquery == NULL &&
+ uctx->event == NULL && uctx->tsigkey == NULL &&
+ uctx->sig0key == NULL);
+
+ mctx = client->mctx;
+ dns_view_detach(&uctx->view);
+ while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) {
+ ISC_LIST_UNLINK(uctx->servers, sa, link);
+ isc_mem_put(mctx, sa, sizeof(*sa));
+ }
+
+ LOCK(&client->lock);
+
+ INSIST(ISC_LINK_LINKED(uctx, link));
+ ISC_LIST_UNLINK(client->updatectxs, uctx, link);
+
+ if (client->references == 0 && ISC_LIST_EMPTY(client->resctxs) &&
+ ISC_LIST_EMPTY(client->reqctxs) &&
+ ISC_LIST_EMPTY(client->updatectxs))
+ need_destroyclient = ISC_TRUE;
+
+ UNLOCK(&client->lock);
+
+ DESTROYLOCK(&uctx->lock);
+ uctx->magic = 0;
+
+ isc_mem_put(mctx, uctx, sizeof(*uctx));
+
+ if (need_destroyclient)
+ destroyclient(&client);
+
+ *transp = NULL;
+}
+
+isc_mem_t *
+dns_client_mctx(dns_client_t *client) {
+
+ REQUIRE(DNS_CLIENT_VALID(client));
+ return (client->mctx);
+}
+
+typedef struct {
+ isc_buffer_t buffer;
+ dns_rdataset_t rdataset;
+ dns_rdatalist_t rdatalist;
+ dns_rdata_t rdata;
+ size_t size;
+ isc_mem_t * mctx;
+ unsigned char data[FLEXIBLE_ARRAY_MEMBER];
+} dns_client_updaterec_t;
+
+isc_result_t
+dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner,
+ dns_rdatatype_t type, dns_rdata_t *source,
+ dns_ttl_t ttl, dns_name_t *target,
+ dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist,
+ dns_rdata_t *rdata, isc_mem_t *mctx)
+{
+ dns_client_updaterec_t *updaterec = NULL;
+ size_t size = offsetof(dns_client_updaterec_t, data);
+
+ REQUIRE(op < updateop_max);
+ REQUIRE(owner != NULL);
+ REQUIRE((rdataset != NULL && rdatalist != NULL && rdata != NULL) ||
+ (rdataset == NULL && rdatalist == NULL && rdata == NULL &&
+ mctx != NULL));
+ if (op == updateop_add)
+ REQUIRE(source != NULL);
+ if (source != NULL) {
+ REQUIRE(source->type == type);
+ REQUIRE(op == updateop_add || op == updateop_delete ||
+ op == updateop_exist);
+ }
+
+ size += owner->length;
+ if (source != NULL)
+ size += source->length;
+
+ if (rdataset == NULL) {
+ updaterec = isc_mem_get(mctx, size);
+ if (updaterec == NULL)
+ return (ISC_R_NOMEMORY);
+ rdataset = &updaterec->rdataset;
+ rdatalist = &updaterec->rdatalist;
+ rdata = &updaterec->rdata;
+ dns_rdataset_init(rdataset);
+ dns_rdatalist_init(&updaterec->rdatalist);
+ dns_rdata_init(&updaterec->rdata);
+ isc_buffer_init(&updaterec->buffer, updaterec->data,
+ size - offsetof(dns_client_updaterec_t, data));
+ dns_name_copy(owner, target, &updaterec->buffer);
+ if (source != NULL) {
+ isc_region_t r;
+ dns_rdata_clone(source, rdata);
+ dns_rdata_toregion(rdata, &r);
+ rdata->data = isc_buffer_used(&updaterec->buffer);
+ isc_buffer_copyregion(&updaterec->buffer, &r);
+ }
+ updaterec->mctx = NULL;
+ isc_mem_attach(mctx, &updaterec->mctx);
+ } else if (source != NULL)
+ dns_rdata_clone(source, rdata);
+
+ switch (op) {
+ case updateop_add:
+ break;
+ case updateop_delete:
+ if (source != NULL) {
+ ttl = 0;
+ dns_rdata_makedelete(rdata);
+ } else
+ dns_rdata_deleterrset(rdata, type);
+ break;
+ case updateop_notexist:
+ dns_rdata_notexist(rdata, type);
+ break;
+ case updateop_exist:
+ if (source == NULL) {
+ ttl = 0;
+ dns_rdata_exists(rdata, type);
+ }
+ case updateop_none:
+ break;
+ default:
+ INSIST(0);
+ }
+
+ rdatalist->type = rdata->type;
+ rdatalist->rdclass = rdata->rdclass;
+ if (source != NULL) {
+ rdatalist->covers = dns_rdata_covers(rdata);
+ rdatalist->ttl = ttl;
+ }
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ ISC_LIST_APPEND(target->list, rdataset, link);
+ if (updaterec != NULL) {
+ target->attributes |= DNS_NAMEATTR_HASUPDATEREC;
+ dns_name_setbuffer(target, &updaterec->buffer);
+ }
+ if (op == updateop_add || op == updateop_delete)
+ target->attributes |= DNS_NAMEATTR_UPDATE;
+ else
+ target->attributes |= DNS_NAMEATTR_PREREQUISITE;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_client_freeupdate(dns_name_t **namep) {
+ dns_client_updaterec_t *updaterec;
+ dns_rdatalist_t *rdatalist;
+ dns_rdataset_t *rdataset;
+ dns_rdata_t *rdata;
+ dns_name_t *name;
+
+ REQUIRE(namep != NULL && *namep != NULL);
+
+ name = *namep;
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_HEAD(name->list)) {
+ ISC_LIST_UNLINK(name->list, rdataset, link);
+ rdatalist = NULL;
+ dns_rdatalist_fromrdataset(rdataset, &rdatalist);
+ if (rdatalist == NULL) {
+ dns_rdataset_disassociate(rdataset);
+ continue;
+ }
+ for (rdata = ISC_LIST_HEAD(rdatalist->rdata);
+ rdata != NULL;
+ rdata = ISC_LIST_HEAD(rdatalist->rdata))
+ ISC_LIST_UNLINK(rdatalist->rdata, rdata, link);
+ dns_rdataset_disassociate(rdataset);
+ }
+
+ if ((name->attributes & DNS_NAMEATTR_HASUPDATEREC) != 0) {
+ updaterec = (dns_client_updaterec_t *)name->buffer;
+ INSIST(updaterec != NULL);
+ isc_mem_putanddetach(&updaterec->mctx, updaterec,
+ updaterec->size);
+ *namep = NULL;
+ }
+}
diff --git a/contrib/bind9/lib/dns/db.c b/contrib/bind9/lib/dns/db.c
index f52f674..c74d24d 100644
--- a/contrib/bind9/lib/dns/db.c
+++ b/contrib/bind9/lib/dns/db.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009, 2011 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: db.c,v 1.88.50.2 2009-06-23 00:19:34 tbox Exp $ */
+/* $Id: db.c,v 1.97 2011-01-13 04:59:25 tbox Exp $ */
/*! \file */
@@ -34,10 +34,12 @@
#include <dns/callbacks.h>
#include <dns/db.h>
+#include <dns/dbiterator.h>
#include <dns/log.h>
#include <dns/master.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
#include <dns/result.h>
/***
@@ -61,14 +63,18 @@ struct dns_dbimplementation {
*/
#include "rbtdb.h"
+#ifdef BIND9
#include "rbtdb64.h"
+#endif
static ISC_LIST(dns_dbimplementation_t) implementations;
static isc_rwlock_t implock;
static isc_once_t once = ISC_ONCE_INIT;
static dns_dbimplementation_t rbtimp;
+#ifdef BIND9
static dns_dbimplementation_t rbt64imp;
+#endif
static void
initialize(void) {
@@ -80,15 +86,19 @@ initialize(void) {
rbtimp.driverarg = NULL;
ISC_LINK_INIT(&rbtimp, link);
+#ifdef BIND9
rbt64imp.name = "rbt64";
rbt64imp.create = dns_rbtdb64_create;
rbt64imp.mctx = NULL;
rbt64imp.driverarg = NULL;
ISC_LINK_INIT(&rbt64imp, link);
+#endif
ISC_LIST_INIT(implementations);
ISC_LIST_APPEND(implementations, &rbtimp, link);
+#ifdef BIND9
ISC_LIST_APPEND(implementations, &rbt64imp, link);
+#endif
}
static inline dns_dbimplementation_t *
@@ -290,6 +300,7 @@ dns_db_class(dns_db_t *db) {
return (db->rdclass);
}
+#ifdef BIND9
isc_result_t
dns_db_beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp,
dns_dbload_t **dbloadp) {
@@ -318,14 +329,19 @@ dns_db_endload(dns_db_t *db, dns_dbload_t **dbloadp) {
isc_result_t
dns_db_load(dns_db_t *db, const char *filename) {
- return (dns_db_load2(db, filename, dns_masterformat_text));
+ return (dns_db_load3(db, filename, dns_masterformat_text, 0));
}
isc_result_t
dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) {
+ return (dns_db_load3(db, filename, format, 0));
+}
+
+isc_result_t
+dns_db_load3(dns_db_t *db, const char *filename, dns_masterformat_t format,
+ unsigned int options) {
isc_result_t result, eresult;
dns_rdatacallbacks_t callbacks;
- unsigned int options = 0;
/*
* Load master file 'filename' into 'db'.
@@ -376,6 +392,7 @@ dns_db_dump2(dns_db_t *db, dns_dbversion_t *version, const char *filename,
return ((db->methods->dump)(db, version, filename, masterformat));
}
+#endif /* BIND9 */
/***
*** Version Methods
@@ -921,8 +938,27 @@ dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name)
}
void
-dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
+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);
}
+
+void
+dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st)
+{
+ if (db->methods->rpz_enabled != NULL)
+ (db->methods->rpz_enabled)(db, st);
+}
+
+isc_result_t
+dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+ dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ dns_rdataset_t *ardataset, dns_rpz_st_t *st)
+{
+ if (db->methods->rpz_findips == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+ return ((db->methods->rpz_findips)(rpz, rpz_type, zone, db, version,
+ ardataset, st));
+}
diff --git a/contrib/bind9/lib/dns/diff.c b/contrib/bind9/lib/dns/diff.c
index a92a496..3dbb5cf 100644
--- a/contrib/bind9/lib/dns/diff.c
+++ b/contrib/bind9/lib/dns/diff.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: diff.c,v 1.18.50.2 2009-01-05 23:47:22 tbox Exp $ */
+/* $Id: diff.c,v 1.23 2009-12-01 00:47:09 each Exp $ */
/*! \file */
@@ -387,10 +387,22 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
* from a server that is not as careful.
* Issue a warning and continue.
*/
- if (warn)
+ if (warn) {
+ char classbuf[DNS_RDATATYPE_FORMATSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(dns_db_origin(db),
+ namebuf,
+ sizeof(namebuf));
+ dns_rdataclass_format(dns_db_class(db),
+ classbuf,
+ sizeof(classbuf));
isc_log_write(DIFF_COMMON_LOGARGS,
ISC_LOG_WARNING,
- "update with no effect");
+ "%s/%s: dns_diff_apply: "
+ "update with no effect",
+ namebuf, classbuf);
+ }
} else if (result == DNS_R_NXRRSET) {
/*
* OK.
@@ -478,6 +490,7 @@ dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
if (result == DNS_R_UNCHANGED) {
isc_log_write(DIFF_COMMON_LOGARGS,
ISC_LOG_WARNING,
+ "dns_diff_load: "
"update with no effect");
} else if (result == ISC_R_SUCCESS ||
result == DNS_R_NXRRSET) {
diff --git a/contrib/bind9/lib/dns/dispatch.c b/contrib/bind9/lib/dns/dispatch.c
index 632d349..c074911 100644
--- a/contrib/bind9/lib/dns/dispatch.c
+++ b/contrib/bind9/lib/dns/dispatch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011 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.155.12.11 2009-12-02 23:26:28 marka Exp $ */
+/* $Id: dispatch.c,v 1.168.248.1.2.1 2011-06-02 23:47:34 tbox Exp $ */
/*! \file */
@@ -417,7 +417,7 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
/*%
* ARC4 random number generator derived from OpenBSD.
- * Only dispatch_arc4random() and dispatch_arc4uniformrandom() are expected
+ * Only dispatch_random() and dispatch_uniformrandom() are expected
* to be called from general dispatch routines; the rest of them are subroutines
* for these two.
*
@@ -437,8 +437,11 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#ifdef BIND9
static void
-dispatch_arc4init(arc4ctx_t *actx, isc_entropy_t *entropy, isc_mutex_t *lock) {
+dispatch_initrandom(arc4ctx_t *actx, isc_entropy_t *entropy,
+ isc_mutex_t *lock)
+{
int n;
for (n = 0; n < 256; n++)
actx->s[n] = n;
@@ -527,7 +530,7 @@ dispatch_arc4stir(arc4ctx_t *actx) {
}
static isc_uint16_t
-dispatch_arc4random(arc4ctx_t *actx) {
+dispatch_random(arc4ctx_t *actx) {
isc_uint16_t result;
if (actx->lock != NULL)
@@ -543,9 +546,38 @@ dispatch_arc4random(arc4ctx_t *actx) {
return (result);
}
+#else
+/*
+ * For general purpose library, we don't have to be too strict about the
+ * quality of random values. Performance doesn't matter much, either.
+ * So we simply use the isc_random module to keep the library as small as
+ * possible.
+ */
+
+static void
+dispatch_initrandom(arc4ctx_t *actx, isc_entropy_t *entropy,
+ isc_mutex_t *lock)
+{
+ UNUSED(actx);
+ UNUSED(entropy);
+ UNUSED(lock);
+
+ return;
+}
static isc_uint16_t
-dispatch_arc4uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) {
+dispatch_random(arc4ctx_t *actx) {
+ isc_uint32_t r;
+
+ UNUSED(actx);
+
+ isc_random_get(&r);
+ return (r & 0xffff);
+}
+#endif /* BIND9 */
+
+static isc_uint16_t
+dispatch_uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) {
isc_uint16_t min, r;
if (upper_bound < 2)
@@ -568,7 +600,7 @@ dispatch_arc4uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) {
* to re-roll.
*/
for (;;) {
- r = dispatch_arc4random(actx);
+ r = dispatch_random(actx);
if (r >= min)
break;
}
@@ -859,7 +891,7 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
*/
localaddr = disp->local;
for (i = 0; i < 64; i++) {
- port = ports[dispatch_arc4uniformrandom(DISP_ARC4CTX(disp),
+ port = ports[dispatch_uniformrandom(DISP_ARC4CTX(disp),
nports)];
isc_sockaddr_setport(&localaddr, port);
@@ -964,6 +996,7 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
INSIST(dispsock->portentry != NULL);
deref_portentry(disp, &dispsock->portentry);
+#ifdef BIND9
if (disp->nsockets > DNS_DISPATCH_POOLSOCKS)
destroy_dispsocket(disp, &dispsock);
else {
@@ -987,6 +1020,13 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
destroy_dispsocket(disp, &dispsock);
}
}
+#else
+ /* This kind of optimization isn't necessary for normal use */
+ UNUSED(qid);
+ UNUSED(result);
+
+ destroy_dispsocket(disp, &dispsock);
+#endif
}
/*
@@ -1707,13 +1747,17 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
isc_mempool_destroy(&mgr->epool);
isc_mempool_destroy(&mgr->rpool);
isc_mempool_destroy(&mgr->dpool);
- isc_mempool_destroy(&mgr->bpool);
- isc_mempool_destroy(&mgr->spool);
+ if (mgr->bpool != NULL)
+ isc_mempool_destroy(&mgr->bpool);
+ if (mgr->spool != NULL)
+ isc_mempool_destroy(&mgr->spool);
DESTROYLOCK(&mgr->pool_lock);
+#ifdef BIND9
if (mgr->entropy != NULL)
isc_entropy_detach(&mgr->entropy);
+#endif /* BIND9 */
if (mgr->qid != NULL)
qid_destroy(mctx, &mgr->qid);
@@ -1752,9 +1796,13 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
return (result);
isc_socket_setname(sock, "dispatcher", NULL);
} else {
+#ifdef BIND9
result = isc_socket_open(sock);
if (result != ISC_R_SUCCESS)
return (result);
+#else
+ INSIST(0);
+#endif
}
#ifndef ISC_ALLOW_MAPPED
@@ -1764,8 +1812,13 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
if (result != ISC_R_SUCCESS) {
if (*sockp == NULL)
isc_socket_detach(&sock);
- else
+ else {
+#ifdef BIND9
isc_socket_close(sock);
+#else
+ INSIST(0);
+#endif
+ }
return (result);
}
@@ -1897,10 +1950,14 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
if (result != ISC_R_SUCCESS)
goto kill_dpool;
+#ifdef BIND9
if (entropy != NULL)
isc_entropy_attach(entropy, &mgr->entropy);
+#else
+ UNUSED(entropy);
+#endif
- dispatch_arc4init(&mgr->arc4ctx, mgr->entropy, &mgr->arc4_lock);
+ dispatch_initrandom(&mgr->arc4ctx, mgr->entropy, &mgr->arc4_lock);
*mgrp = mgr;
return (ISC_R_SUCCESS);
@@ -2411,7 +2468,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
ISC_LIST_INIT(disp->activesockets);
ISC_LIST_INIT(disp->inactivesockets);
disp->nsockets = 0;
- dispatch_arc4init(&disp->arc4ctx, mgr->entropy, NULL);
+ dispatch_initrandom(&disp->arc4ctx, mgr->entropy, NULL);
disp->port_table = NULL;
disp->portpool = NULL;
@@ -2708,7 +2765,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
for (i = 0; i < 1024; i++) {
in_port_t prt;
- prt = ports[dispatch_arc4uniformrandom(
+ prt = ports[dispatch_uniformrandom(
DISP_ARC4CTX(disp),
nports)];
isc_sockaddr_setport(&localaddr_bound, prt);
@@ -2844,8 +2901,10 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
disp->task[i] = NULL;
result = isc_task_create(taskmgr, 0, &disp->task[i]);
if (result != ISC_R_SUCCESS) {
- while (--i >= 0)
- isc_task_destroy(&disp->task[i]);
+ while (--i >= 0) {
+ isc_task_shutdown(disp->task[i]);
+ isc_task_detach(&disp->task[i]);
+ }
goto kill_socket;
}
isc_task_setname(disp->task[i], "udpdispatch", disp);
@@ -3045,7 +3104,7 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
/*
* Try somewhat hard to find an unique ID.
*/
- id = (dns_messageid_t)dispatch_arc4random(DISP_ARC4CTX(disp));
+ id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp));
bucket = dns_hash(qid, dest, id, localport);
ok = ISC_FALSE;
for (i = 0; i < 64; i++) {
diff --git a/contrib/bind9/lib/dns/dlz.c b/contrib/bind9/lib/dns/dlz.c
index f848230..5a508e9 100644
--- a/contrib/bind9/lib/dns/dlz.c
+++ b/contrib/bind9/lib/dns/dlz.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005, 2007, 2009, 2010 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: dlz.c,v 1.5.332.2 2009-01-18 23:47:35 tbox Exp $ */
+/* $Id: dlz.c,v 1.10 2010-12-20 23:47:20 tbox Exp $ */
/*! \file */
@@ -64,6 +64,8 @@
#include <dns/log.h>
#include <dns/master.h>
#include <dns/dlz.h>
+#include <dns/ssu.h>
+#include <dns/zone.h>
#include <isc/buffer.h>
@@ -230,6 +232,12 @@ dns_dlzdestroy(dns_dlzdb_t **dbp) {
*/
REQUIRE(dbp != NULL && DNS_DLZ_VALID(*dbp));
+#ifdef BIND9
+ if ((*dbp)->ssutable != NULL) {
+ dns_ssutable_detach(&(*dbp)->ssutable);
+ }
+#endif
+
/* call the drivers destroy method */
if ((*dbp) != NULL) {
mctx = (*dbp)->mctx;
@@ -499,7 +507,7 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp) {
mctx = dlz_imp->mctx;
/*
- * return the memory back to the available memory pool and
+ * Return the memory back to the available memory pool and
* remove it from the memory context.
*/
isc_mem_put(mctx, dlz_imp, sizeof(dns_dlzimplementation_t));
@@ -508,3 +516,143 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp) {
/* Unlock the dlz_implementations list. */
RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
}
+
+#ifdef BIND9
+/*
+ * Create a writeable DLZ zone. This can be called by DLZ drivers
+ * during configure() to create a zone that can be updated. The zone
+ * type is set to dns_zone_dlz, which is equivalent to a master zone
+ *
+ * This function uses a callback setup in dns_dlzconfigure() to call
+ * into the server zone code to setup the remaining pieces of server
+ * specific functionality on the zone
+ */
+isc_result_t
+dns_dlz_writeablezone(dns_view_t *view, const char *zone_name) {
+ dns_zone_t *zone = NULL;
+ dns_zone_t *dupzone = NULL;
+ isc_result_t result;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixorigin;
+ dns_name_t *origin;
+ dns_rdataclass_t zclass;
+ dns_dlzdb_t *dlzdatabase;
+
+ REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
+
+ dlzdatabase = view->dlzdatabase;
+
+ REQUIRE(dlzdatabase->configure_callback != NULL);
+
+ isc_buffer_init(&buffer, zone_name, strlen(zone_name));
+ isc_buffer_add(&buffer, strlen(zone_name));
+ dns_fixedname_init(&fixorigin);
+ result = dns_name_fromtext(dns_fixedname_name(&fixorigin),
+ &buffer, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ origin = dns_fixedname_name(&fixorigin);
+
+ zclass = view->rdclass;
+
+ /* See if the zone already exists */
+ result = dns_view_findzone(view, origin, &dupzone);
+ if (result == ISC_R_SUCCESS) {
+ dns_zone_detach(&dupzone);
+ result = ISC_R_EXISTS;
+ goto cleanup;
+ }
+ INSIST(dupzone == NULL);
+
+ /* Create it */
+ result = dns_zone_create(&zone, view->mctx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_zone_setorigin(zone, origin);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_zone_setview(zone, view);
+
+ dns_zone_setadded(zone, ISC_TRUE);
+
+ if (dlzdatabase->ssutable == NULL) {
+ result = dns_ssutable_createdlz(dlzdatabase->mctx,
+ &dlzdatabase->ssutable,
+ view->dlzdatabase);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ dns_zone_setssutable(zone, dlzdatabase->ssutable);
+
+ result = dlzdatabase->configure_callback(view, zone);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * Add the zone to its view in the new view list.
+ */
+ result = dns_view_addzone(view, zone);
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ return (result);
+}
+#endif
+
+/*%
+ * Configure a DLZ driver. This is optional, and if supplied gives
+ * the backend an opportunity to configure parameters related to DLZ.
+ */
+isc_result_t
+dns_dlzconfigure(dns_view_t *view, isc_result_t (*callback)(dns_view_t *,
+ dns_zone_t *))
+{
+ dns_dlzimplementation_t *impl;
+ dns_dlzdb_t *dlzdatabase;
+ isc_result_t result;
+
+ REQUIRE(view != NULL);
+ REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
+ REQUIRE(view->dlzdatabase->implementation != NULL);
+
+ dlzdatabase = view->dlzdatabase;
+ impl = dlzdatabase->implementation;
+
+ if (impl->methods->configure == NULL)
+ return (ISC_R_SUCCESS);
+
+ dlzdatabase->configure_callback = callback;
+
+ result = impl->methods->configure(impl->driverarg,
+ dlzdatabase->dbdata, view);
+ return (result);
+}
+
+isc_boolean_t
+dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase,
+ dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
+ dns_rdatatype_t type, const dst_key_t *key)
+{
+ dns_dlzimplementation_t *impl;
+ isc_boolean_t r;
+
+ REQUIRE(dlzdatabase != NULL);
+ REQUIRE(dlzdatabase->implementation != NULL);
+ REQUIRE(dlzdatabase->implementation->methods != NULL);
+ impl = dlzdatabase->implementation;
+
+ if (impl->methods->ssumatch == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "No ssumatch method for DLZ database");
+ return (ISC_FALSE);
+ }
+
+ r = impl->methods->ssumatch(signer, name, tcpaddr, type, key,
+ impl->driverarg, dlzdatabase->dbdata);
+ return (r);
+}
diff --git a/contrib/bind9/lib/dns/dns64.c b/contrib/bind9/lib/dns/dns64.c
new file mode 100644
index 0000000..180c0a9
--- /dev/null
+++ b/contrib/bind9/lib/dns/dns64.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2010 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: dns64.c,v 1.6 2010-12-09 04:59:09 marka Exp $ */
+
+#include <config.h>
+
+#include <isc/list.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/dns64.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+
+struct dns_dns64 {
+ unsigned char bits[16]; /*
+ * Prefix + suffix bits.
+ */
+ dns_acl_t * clients; /*
+ * Which clients get mapped
+ * addresses.
+ */
+ dns_acl_t * mapped; /*
+ * IPv4 addresses to be mapped.
+ */
+ dns_acl_t * excluded; /*
+ * IPv6 addresses that are
+ * treated as not existing.
+ */
+ unsigned int prefixlen; /*
+ * Start of mapped address.
+ */
+ unsigned int flags;
+ isc_mem_t * mctx;
+ ISC_LINK(dns_dns64_t) link;
+};
+
+isc_result_t
+dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
+ unsigned int prefixlen, isc_netaddr_t *suffix,
+ dns_acl_t *clients, dns_acl_t *mapped, dns_acl_t *excluded,
+ unsigned int flags, dns_dns64_t **dns64)
+{
+ dns_dns64_t *new;
+ unsigned int nbytes = 16;
+
+ REQUIRE(prefix != NULL && prefix->family == AF_INET6);
+ /* Legal prefix lengths from draft-ietf-behave-address-format-04. */
+ REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 ||
+ prefixlen == 56 || prefixlen == 64 || prefixlen == 96);
+ REQUIRE(isc_netaddr_prefixok(prefix, prefixlen) == ISC_R_SUCCESS);
+ REQUIRE(dns64 != NULL && *dns64 == NULL);
+
+ if (suffix != NULL) {
+ static const unsigned char zeros[16];
+ REQUIRE(prefix->family == AF_INET6);
+ nbytes = prefixlen / 8 + 4;
+ /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
+ if (prefixlen >= 32 && prefixlen <= 64)
+ nbytes++;
+ REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0);
+ }
+
+ new = isc_mem_get(mctx, sizeof(dns_dns64_t));
+ if (new == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(new->bits, 0, sizeof(new->bits));
+ memcpy(new->bits, prefix->type.in6.s6_addr, prefixlen / 8);
+ if (suffix != NULL)
+ memcpy(new->bits + nbytes, suffix->type.in6.s6_addr + nbytes,
+ 16 - nbytes);
+ new->clients = NULL;
+ if (clients != NULL)
+ dns_acl_attach(clients, &new->clients);
+ new->mapped = NULL;
+ if (mapped != NULL)
+ dns_acl_attach(mapped, &new->mapped);
+ new->excluded = NULL;
+ if (excluded != NULL)
+ dns_acl_attach(excluded, &new->excluded);
+ new->prefixlen = prefixlen;
+ new->flags = flags;
+ ISC_LINK_INIT(new, link);
+ new->mctx = NULL;
+ isc_mem_attach(mctx, &new->mctx);
+ *dns64 = new;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_dns64_destroy(dns_dns64_t **dns64p) {
+ dns_dns64_t *dns64;
+
+ REQUIRE(dns64p != NULL && *dns64p != NULL);
+
+ dns64 = *dns64p;
+ *dns64p = NULL;
+
+ REQUIRE(!ISC_LINK_LINKED(dns64, link));
+
+ if (dns64->clients != NULL)
+ dns_acl_detach(&dns64->clients);
+ if (dns64->mapped != NULL)
+ dns_acl_detach(&dns64->mapped);
+ if (dns64->excluded != NULL)
+ dns_acl_detach(&dns64->excluded);
+ isc_mem_putanddetach(&dns64->mctx, dns64, sizeof(*dns64));
+}
+
+isc_result_t
+dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
+ const dns_name_t *reqsigner, const dns_aclenv_t *env,
+ unsigned int flags, unsigned char *a, unsigned char *aaaa)
+{
+ unsigned int nbytes, i;
+ isc_result_t result;
+ int match;
+
+ if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 &&
+ (flags & DNS_DNS64_RECURSIVE) == 0)
+ return (DNS_R_DISALLOWED);
+
+ if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 &&
+ (flags & DNS_DNS64_DNSSEC) != 0)
+ return (DNS_R_DISALLOWED);
+
+ if (dns64->clients != NULL) {
+ result = dns_acl_match(reqaddr, reqsigner, dns64->clients, env,
+ &match, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (match <= 0)
+ return (DNS_R_DISALLOWED);
+ }
+
+ if (dns64->mapped != NULL) {
+ struct in_addr ina;
+ isc_netaddr_t netaddr;
+
+ memcpy(&ina.s_addr, a, 4);
+ isc_netaddr_fromin(&netaddr, &ina);
+ result = dns_acl_match(&netaddr, NULL, dns64->mapped, env,
+ &match, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (match <= 0)
+ return (DNS_R_DISALLOWED);
+ }
+
+ nbytes = dns64->prefixlen / 8;
+ INSIST(nbytes <= 12);
+ /* Copy prefix. */
+ memcpy(aaaa, dns64->bits, nbytes);
+ /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
+ if (nbytes == 8)
+ aaaa[nbytes++] = 0;
+ /* Copy mapped address. */
+ for (i = 0; i < 4U; i++) {
+ aaaa[nbytes++] = a[i];
+ /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */
+ if (nbytes == 8)
+ aaaa[nbytes++] = 0;
+ }
+ /* Copy suffix. */
+ memcpy(aaaa + nbytes, dns64->bits + nbytes, 16 - nbytes);
+ return (ISC_R_SUCCESS);
+}
+
+dns_dns64_t *
+dns_dns64_next(dns_dns64_t *dns64) {
+ dns64 = ISC_LIST_NEXT(dns64, link);
+ return (dns64);
+}
+
+void
+dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64) {
+ ISC_LIST_APPEND(*list, dns64, link);
+}
+
+void
+dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64) {
+ ISC_LIST_UNLINK(*list, dns64, link);
+}
+
+isc_boolean_t
+dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
+ const dns_name_t *reqsigner, const dns_aclenv_t *env,
+ unsigned int flags, dns_rdataset_t *rdataset,
+ isc_boolean_t *aaaaok, size_t aaaaoklen)
+{
+ struct in6_addr in6;
+ isc_netaddr_t netaddr;
+ isc_result_t result;
+ int match;
+ isc_boolean_t answer = ISC_FALSE;
+ isc_boolean_t found = ISC_FALSE;
+ unsigned int i, ok;
+
+ REQUIRE(rdataset != NULL);
+ REQUIRE(rdataset->type == dns_rdatatype_aaaa);
+ REQUIRE(rdataset->rdclass == dns_rdataclass_in);
+ if (aaaaok != NULL)
+ REQUIRE(aaaaoklen == dns_rdataset_count(rdataset));
+
+ for (;dns64 != NULL; dns64 = ISC_LIST_NEXT(dns64, link)) {
+ if ((dns64->flags & DNS_DNS64_RECURSIVE_ONLY) != 0 &&
+ (flags & DNS_DNS64_RECURSIVE) == 0)
+ continue;
+
+ if ((dns64->flags & DNS_DNS64_BREAK_DNSSEC) == 0 &&
+ (flags & DNS_DNS64_DNSSEC) != 0)
+ continue;
+ /*
+ * Work out if this dns64 structure applies to this client.
+ */
+ if (dns64->clients != NULL) {
+ result = dns_acl_match(reqaddr, reqsigner,
+ dns64->clients, env,
+ &match, NULL);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (match <= 0)
+ continue;
+ }
+
+ if (!found && aaaaok != NULL) {
+ for (i = 0; i < aaaaoklen; i++)
+ aaaaok[i] = ISC_FALSE;
+ }
+ found = ISC_TRUE;
+
+ /*
+ * If we are not excluding any addresses then any AAAA
+ * will do.
+ */
+ if (dns64->excluded == NULL) {
+ answer = ISC_TRUE;
+ for (i = 0; i < aaaaoklen; i++)
+ aaaaok[i] = ISC_TRUE;
+ goto done;
+ }
+
+ i = 0; ok = 0;
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ if (aaaaok == NULL || !aaaaok[i]) {
+
+ dns_rdataset_current(rdataset, &rdata);
+ memcpy(&in6.s6_addr, rdata.data, 16);
+ isc_netaddr_fromin6(&netaddr, &in6);
+
+ result = dns_acl_match(&netaddr, NULL,
+ dns64->excluded,
+ env, &match, NULL);
+ if (result == ISC_R_SUCCESS && match <= 0) {
+ answer = ISC_TRUE;
+ if (aaaaok == NULL)
+ goto done;
+ aaaaok[i] = ISC_TRUE;
+ ok++;
+ }
+ } else
+ ok++;
+ i++;
+ }
+ /*
+ * Are all addresses ok?
+ */
+ if (aaaaok != NULL && ok == aaaaoklen)
+ goto done;
+ }
+
+ done:
+ if (!found && aaaaok != NULL) {
+ for (i = 0; i < aaaaoklen; i++)
+ aaaaok[i] = ISC_TRUE;
+ }
+ return (found ? answer : ISC_TRUE);
+}
diff --git a/contrib/bind9/lib/dns/dnssec.c b/contrib/bind9/lib/dns/dnssec.c
index 67a2c67..dc249b7 100644
--- a/contrib/bind9/lib/dns/dnssec.c
+++ b/contrib/bind9/lib/dns/dnssec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 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.93.12.6 2009-06-22 23:47:18 tbox Exp $
+ * $Id: dnssec.c,v 1.119 2010-01-13 23:48:59 tbox Exp $
*/
/*! \file */
@@ -26,15 +26,18 @@
#include <stdlib.h>
#include <isc/buffer.h>
+#include <isc/dir.h>
#include <isc/mem.h>
#include <isc/serial.h>
#include <isc/string.h>
#include <isc/util.h>
#include <dns/db.h>
+#include <dns/diff.h>
#include <dns/dnssec.h>
#include <dns/fixedname.h>
#include <dns/keyvalues.h>
+#include <dns/log.h>
#include <dns/message.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
@@ -539,6 +542,59 @@ dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
return (result);
}
+static isc_boolean_t
+key_active(dst_key_t *key) {
+ isc_result_t result;
+ isc_stdtime_t now, publish, active, revoke, inactive, delete;
+ isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
+ isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE;
+ isc_boolean_t delset = ISC_FALSE;
+ int major, minor;
+
+ /* Is this an old-style key? */
+ result = dst_key_getprivateformat(key, &major, &minor);
+
+ /*
+ * Smart signing started with key format 1.3; prior to that, all
+ * keys are assumed active
+ */
+ if (major == 1 && minor <= 2)
+ return (ISC_TRUE);
+
+ isc_stdtime_get(&now);
+
+ result = dst_key_gettime(key, DST_TIME_PUBLISH, &publish);
+ if (result == ISC_R_SUCCESS)
+ pubset = ISC_TRUE;
+
+ result = dst_key_gettime(key, DST_TIME_ACTIVATE, &active);
+ if (result == ISC_R_SUCCESS)
+ actset = ISC_TRUE;
+
+ result = dst_key_gettime(key, DST_TIME_REVOKE, &revoke);
+ if (result == ISC_R_SUCCESS)
+ revset = ISC_TRUE;
+
+ result = dst_key_gettime(key, DST_TIME_INACTIVE, &inactive);
+ if (result == ISC_R_SUCCESS)
+ inactset = ISC_TRUE;
+
+ result = dst_key_gettime(key, DST_TIME_DELETE, &delete);
+ if (result == ISC_R_SUCCESS)
+ delset = ISC_TRUE;
+
+ if ((inactset && inactive <= now) || (delset && delete <= now))
+ return (ISC_FALSE);
+
+ if (revset && revoke <= now && pubset && publish <= now)
+ return (ISC_TRUE);
+
+ if (actset && active <= now)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
#define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \
== DNS_KEYOWNER_ZONE)
@@ -580,14 +636,70 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
directory,
mctx, &keys[count]);
+
+ /*
+ * If the key was revoked and the private file
+ * doesn't exist, maybe it was revoked internally
+ * by named. Try loading the unrevoked version.
+ */
if (result == ISC_R_FILENOTFOUND) {
+ isc_uint32_t flags;
+ flags = dst_key_flags(pubkey);
+ if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
+ dst_key_setflags(pubkey,
+ flags & ~DNS_KEYFLAG_REVOKE);
+ result = dst_key_fromfile(dst_key_name(pubkey),
+ dst_key_id(pubkey),
+ dst_key_alg(pubkey),
+ DST_TYPE_PUBLIC|
+ DST_TYPE_PRIVATE,
+ directory,
+ mctx, &keys[count]);
+ if (result == ISC_R_SUCCESS &&
+ dst_key_pubcompare(pubkey, keys[count],
+ ISC_FALSE)) {
+ dst_key_setflags(keys[count], flags);
+ }
+ dst_key_setflags(pubkey, flags);
+ }
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ char keybuf[DNS_NAME_FORMATSIZE];
+ char algbuf[DNS_SECALG_FORMATSIZE];
+ dns_name_format(dst_key_name(pubkey), keybuf,
+ sizeof(keybuf));
+ dns_secalg_format(dst_key_alg(pubkey), algbuf,
+ sizeof(algbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
+ "dns_dnssec_findzonekeys2: error "
+ "reading private key file %s/%s/%d: %s",
+ keybuf, algbuf, dst_key_id(pubkey),
+ isc_result_totext(result));
+ }
+
+ if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
keys[count] = pubkey;
pubkey = NULL;
count++;
goto next;
}
+
if (result != ISC_R_SUCCESS)
goto failure;
+
+ /*
+ * If a key is marked inactive, skip it
+ */
+ if (!key_active(keys[count])) {
+ dst_key_free(&keys[count]);
+ keys[count] = pubkey;
+ pubkey = NULL;
+ count++;
+ goto next;
+ }
+
if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) {
/* We should never get here. */
dst_key_free(&keys[count]);
@@ -951,3 +1063,691 @@ dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
dst_key_free(&dstkey);
return (ISC_FALSE);
}
+
+isc_result_t
+dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
+ dns_dnsseckey_t **dkp)
+{
+ isc_result_t result;
+ dns_dnsseckey_t *dk;
+ int major, minor;
+
+ REQUIRE(dkp != NULL && *dkp == NULL);
+ dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t));
+ if (dk == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dk->key = *dstkey;
+ *dstkey = NULL;
+ dk->force_publish = ISC_FALSE;
+ dk->force_sign = ISC_FALSE;
+ dk->hint_publish = ISC_FALSE;
+ dk->hint_sign = ISC_FALSE;
+ dk->hint_remove = ISC_FALSE;
+ dk->first_sign = ISC_FALSE;
+ dk->is_active = ISC_FALSE;
+ dk->prepublish = 0;
+ dk->source = dns_keysource_unknown;
+ dk->index = 0;
+
+ /* KSK or ZSK? */
+ dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0);
+
+ /* Is this an old-style key? */
+ result = dst_key_getprivateformat(dk->key, &major, &minor);
+
+ /* Smart signing started with key format 1.3 */
+ dk->legacy = ISC_TF(major == 1 && minor <= 2);
+
+ ISC_LINK_INIT(dk, link);
+ *dkp = dk;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) {
+ dns_dnsseckey_t *dk;
+
+ REQUIRE(dkp != NULL && *dkp != NULL);
+ dk = *dkp;
+ if (dk->key != NULL)
+ dst_key_free(&dk->key);
+ isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t));
+ *dkp = NULL;
+}
+
+static void
+get_hints(dns_dnsseckey_t *key) {
+ isc_result_t result;
+ isc_stdtime_t now, publish, active, revoke, inactive, delete;
+ isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
+ isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE;
+ isc_boolean_t delset = ISC_FALSE;
+
+ REQUIRE(key != NULL && key->key != NULL);
+
+ isc_stdtime_get(&now);
+
+ result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish);
+ if (result == ISC_R_SUCCESS)
+ pubset = ISC_TRUE;
+
+ result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
+ if (result == ISC_R_SUCCESS)
+ actset = ISC_TRUE;
+
+ result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke);
+ if (result == ISC_R_SUCCESS)
+ revset = ISC_TRUE;
+
+ result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &inactive);
+ if (result == ISC_R_SUCCESS)
+ inactset = ISC_TRUE;
+
+ result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete);
+ if (result == ISC_R_SUCCESS)
+ delset = ISC_TRUE;
+
+ /* Metadata says publish (but possibly not activate) */
+ if (pubset && publish <= now)
+ key->hint_publish = ISC_TRUE;
+
+ /* Metadata says activate (so we must also publish) */
+ if (actset && active <= now) {
+ key->hint_sign = ISC_TRUE;
+ key->hint_publish = ISC_TRUE;
+ }
+
+ /*
+ * Activation date is set (maybe in the future), but
+ * publication date isn't. Most likely the user wants to
+ * publish now and activate later.
+ */
+ if (actset && !pubset)
+ key->hint_publish = ISC_TRUE;
+
+ /*
+ * If activation date is in the future, make note of how far off
+ */
+ if (key->hint_publish && actset && active > now) {
+ key->prepublish = active - now;
+ }
+
+ /*
+ * Key has been marked inactive: we can continue publishing,
+ * but don't sign.
+ */
+ if (key->hint_publish && inactset && inactive <= now) {
+ key->hint_sign = ISC_FALSE;
+ }
+
+ /*
+ * Metadata says revoke. If the key is published,
+ * we *have to* sign with it per RFC5011--even if it was
+ * not active before.
+ *
+ * If it hasn't already been done, we should also revoke it now.
+ */
+ if (key->hint_publish && (revset && revoke <= now)) {
+ isc_uint32_t flags;
+ key->hint_sign = ISC_TRUE;
+ flags = dst_key_flags(key->key);
+ if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
+ flags |= DNS_KEYFLAG_REVOKE;
+ dst_key_setflags(key->key, flags);
+ }
+ }
+
+ /*
+ * Metadata says delete, so don't publish this key or sign with it.
+ */
+ if (delset && delete <= now) {
+ key->hint_publish = ISC_FALSE;
+ key->hint_sign = ISC_FALSE;
+ key->hint_remove = ISC_TRUE;
+ }
+}
+
+/*%
+ * Get a list of DNSSEC keys from the key repository
+ */
+isc_result_t
+dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
+ isc_mem_t *mctx, dns_dnsseckeylist_t *keylist)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t dir_open = ISC_FALSE;
+ dns_dnsseckeylist_t list;
+ isc_dir_t dir;
+ dns_dnsseckey_t *key = NULL;
+ dst_key_t *dstkey = NULL;
+ char namebuf[DNS_NAME_FORMATSIZE], *p;
+ isc_buffer_t b;
+ unsigned int len;
+
+ REQUIRE(keylist != NULL);
+ ISC_LIST_INIT(list);
+ isc_dir_init(&dir);
+
+ isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1);
+ RETERR(dns_name_totext(origin, ISC_FALSE, &b));
+ len = isc_buffer_usedlength(&b);
+ namebuf[len] = '\0';
+
+ if (directory == NULL)
+ directory = ".";
+ RETERR(isc_dir_open(&dir, directory));
+ dir_open = ISC_TRUE;
+
+ while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
+ if (dir.entry.name[0] == 'K' &&
+ dir.entry.length > len + 1 &&
+ dir.entry.name[len + 1] == '+' &&
+ strncasecmp(dir.entry.name + 1, namebuf, len) == 0) {
+ p = strrchr(dir.entry.name, '.');
+ if (p != NULL && strcmp(p, ".private") != 0)
+ continue;
+
+ dstkey = NULL;
+ result = dst_key_fromnamedfile(dir.entry.name,
+ directory,
+ DST_TYPE_PUBLIC |
+ DST_TYPE_PRIVATE,
+ mctx, &dstkey);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DNSSEC,
+ ISC_LOG_WARNING,
+ "dns_dnssec_findmatchingkeys: "
+ "error reading key file %s: %s",
+ dir.entry.name,
+ isc_result_totext(result));
+ continue;
+ }
+
+ RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
+ key->source = dns_keysource_repository;
+ get_hints(key);
+
+ if (key->legacy) {
+ dns_dnsseckey_destroy(mctx, &key);
+ } else {
+ ISC_LIST_APPEND(list, key, link);
+ key = NULL;
+ }
+ }
+ }
+
+ if (!ISC_LIST_EMPTY(list))
+ ISC_LIST_APPENDLIST(*keylist, list, link);
+ else
+ result = ISC_R_NOTFOUND;
+
+ failure:
+ if (dir_open)
+ isc_dir_close(&dir);
+ INSIST(key == NULL);
+ while ((key = ISC_LIST_HEAD(list)) != NULL) {
+ ISC_LIST_UNLINK(list, key, link);
+ INSIST(key->key != NULL);
+ dst_key_free(&key->key);
+ dns_dnsseckey_destroy(mctx, &key);
+ }
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+ return (result);
+}
+
+/*%
+ * Add 'newkey' to 'keylist' if it's not already there.
+ *
+ * If 'savekeys' is ISC_TRUE, then we need to preserve all
+ * the keys in the keyset, regardless of whether they have
+ * metadata indicating they should be deactivated or removed.
+ */
+static void
+addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey,
+ isc_boolean_t savekeys, isc_mem_t *mctx)
+{
+ dns_dnsseckey_t *key;
+
+ /* Skip duplicates */
+ for (key = ISC_LIST_HEAD(*keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ if (dst_key_id(key->key) == dst_key_id(*newkey) &&
+ dst_key_alg(key->key) == dst_key_alg(*newkey) &&
+ dns_name_equal(dst_key_name(key->key),
+ dst_key_name(*newkey)))
+ break;
+ }
+
+ if (key != NULL) {
+ /*
+ * Found a match. If the old key was only public and the
+ * new key is private, replace the old one; otherwise
+ * leave it. But either way, mark the key as having
+ * been found in the zone.
+ */
+ if (dst_key_isprivate(key->key)) {
+ dst_key_free(newkey);
+ } else if (dst_key_isprivate(*newkey)) {
+ dst_key_free(&key->key);
+ key->key = *newkey;
+ }
+
+ key->source = dns_keysource_zoneapex;
+ return;
+ }
+
+ dns_dnsseckey_create(mctx, newkey, &key);
+ if (key->legacy || savekeys) {
+ key->force_publish = ISC_TRUE;
+ key->force_sign = dst_key_isprivate(key->key);
+ }
+ key->source = dns_keysource_zoneapex;
+ ISC_LIST_APPEND(*keylist, key, link);
+ *newkey = NULL;
+}
+
+
+/*%
+ * Mark all keys which signed the DNSKEY/SOA RRsets as "active",
+ * for future reference.
+ */
+static isc_result_t
+mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t sigs;
+ dns_dnsseckey_t *key;
+
+ REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs));
+
+ dns_rdataset_init(&sigs);
+ dns_rdataset_clone(rrsigs, &sigs);
+ for (key = ISC_LIST_HEAD(*keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ isc_uint16_t keyid, sigid;
+ dns_secalg_t keyalg, sigalg;
+ keyid = dst_key_id(key->key);
+ keyalg = dst_key_alg(key->key);
+
+ for (result = dns_rdataset_first(&sigs);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&sigs)) {
+ dns_rdata_rrsig_t sig;
+
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&sigs, &rdata);
+ result = dns_rdata_tostruct(&rdata, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ sigalg = sig.algorithm;
+ sigid = sig.keyid;
+ if (keyid == sigid && keyalg == sigalg) {
+ key->is_active = ISC_TRUE;
+ break;
+ }
+ }
+ }
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ if (dns_rdataset_isassociated(&sigs))
+ dns_rdataset_disassociate(&sigs);
+ return (result);
+}
+
+/*%
+ * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
+ */
+isc_result_t
+dns_dnssec_keylistfromrdataset(dns_name_t *origin,
+ const char *directory, isc_mem_t *mctx,
+ dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
+ dns_rdataset_t *soasigs, isc_boolean_t savekeys,
+ isc_boolean_t public,
+ dns_dnsseckeylist_t *keylist)
+{
+ dns_rdataset_t keys;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dst_key_t *pubkey = NULL, *privkey = NULL;
+ isc_result_t result;
+
+ REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset));
+
+ dns_rdataset_init(&keys);
+
+ dns_rdataset_clone(keyset, &keys);
+ for (result = dns_rdataset_first(&keys);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&keys)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&keys, &rdata);
+ RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey));
+
+ if (!is_zone_key(pubkey) ||
+ (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
+ goto skip;
+
+ /* Corrupted .key file? */
+ if (!dns_name_equal(origin, dst_key_name(pubkey)))
+ goto skip;
+
+ if (public) {
+ addkey(keylist, &pubkey, savekeys, mctx);
+ goto skip;
+ }
+
+ result = dst_key_fromfile(dst_key_name(pubkey),
+ dst_key_id(pubkey),
+ dst_key_alg(pubkey),
+ DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
+ directory, mctx, &privkey);
+
+ /*
+ * If the key was revoked and the private file
+ * doesn't exist, maybe it was revoked internally
+ * by named. Try loading the unrevoked version.
+ */
+ if (result == ISC_R_FILENOTFOUND) {
+ isc_uint32_t flags;
+ flags = dst_key_flags(pubkey);
+ if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
+ dst_key_setflags(pubkey,
+ flags & ~DNS_KEYFLAG_REVOKE);
+ result = dst_key_fromfile(dst_key_name(pubkey),
+ dst_key_id(pubkey),
+ dst_key_alg(pubkey),
+ DST_TYPE_PUBLIC|
+ DST_TYPE_PRIVATE,
+ directory,
+ mctx, &privkey);
+ if (result == ISC_R_SUCCESS &&
+ dst_key_pubcompare(pubkey, privkey,
+ ISC_FALSE)) {
+ dst_key_setflags(privkey, flags);
+ }
+ dst_key_setflags(pubkey, flags);
+ }
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ char keybuf[DNS_NAME_FORMATSIZE];
+ char algbuf[DNS_SECALG_FORMATSIZE];
+ dns_name_format(dst_key_name(pubkey), keybuf,
+ sizeof(keybuf));
+ dns_secalg_format(dst_key_alg(pubkey), algbuf,
+ sizeof(algbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
+ "dns_dnssec_keylistfromrdataset: error "
+ "reading private key file %s/%s/%d: %s",
+ keybuf, algbuf, dst_key_id(pubkey),
+ isc_result_totext(result));
+ }
+
+ if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
+ addkey(keylist, &pubkey, savekeys, mctx);
+ goto skip;
+ }
+ RETERR(result);
+
+ /* This should never happen. */
+ if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0)
+ goto skip;
+
+ addkey(keylist, &privkey, savekeys, mctx);
+ skip:
+ if (pubkey != NULL)
+ dst_key_free(&pubkey);
+ if (privkey != NULL)
+ dst_key_free(&privkey);
+ }
+
+ if (result != ISC_R_NOMORE)
+ RETERR(result);
+
+ if (keysigs != NULL && dns_rdataset_isassociated(keysigs))
+ RETERR(mark_active_keys(keylist, keysigs));
+
+ if (soasigs != NULL && dns_rdataset_isassociated(soasigs))
+ RETERR(mark_active_keys(keylist, soasigs));
+
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dns_rdataset_isassociated(&keys))
+ dns_rdataset_disassociate(&keys);
+ if (pubkey != NULL)
+ dst_key_free(&pubkey);
+ if (privkey != NULL)
+ dst_key_free(&privkey);
+ return (result);
+}
+
+static isc_result_t
+make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
+ dns_rdata_t *target)
+{
+ isc_result_t result;
+ isc_buffer_t b;
+ isc_region_t r;
+
+ isc_buffer_init(&b, buf, bufsize);
+ result = dst_key_todns(key, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdata_reset(target);
+ isc_buffer_usedregion(&b, &r);
+ dns_rdata_fromregion(target, dst_key_class(key),
+ dns_rdatatype_dnskey, &r);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin,
+ dns_ttl_t ttl, isc_mem_t *mctx, isc_boolean_t allzsk,
+ void (*report)(const char *, ...))
+{
+ isc_result_t result;
+ dns_difftuple_t *tuple = NULL;
+ unsigned char buf[DST_KEY_MAXSIZE];
+ dns_rdata_t dnskey = DNS_RDATA_INIT;
+ char alg[80];
+
+ dns_rdata_reset(&dnskey);
+ RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
+
+ dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
+ report("Fetching %s %d/%s from key %s.",
+ key->ksk ? (allzsk ? "KSK/ZSK" : "KSK") : "ZSK",
+ dst_key_id(key->key), alg,
+ key->source == dns_keysource_user ? "file" : "repository");
+
+ if (key->prepublish && ttl > key->prepublish) {
+ char keystr[DST_KEY_FORMATSIZE];
+ isc_stdtime_t now;
+
+ dst_key_format(key->key, keystr, sizeof(keystr));
+ report("Key %s: Delaying activation to match the DNSKEY TTL.\n",
+ keystr, ttl);
+
+ isc_stdtime_get(&now);
+ dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl);
+ }
+
+ /* publish key */
+ RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl,
+ &dnskey, &tuple));
+ dns_diff_appendminimal(diff, &tuple);
+ result = ISC_R_SUCCESS;
+
+ failure:
+ return (result);
+}
+
+static isc_result_t
+remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin,
+ dns_ttl_t ttl, isc_mem_t *mctx, const char *reason,
+ void (*report)(const char *, ...))
+{
+ isc_result_t result;
+ dns_difftuple_t *tuple = NULL;
+ unsigned char buf[DST_KEY_MAXSIZE];
+ dns_rdata_t dnskey = DNS_RDATA_INIT;
+ char alg[80];
+
+ dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
+ report("Removing %s key %d/%s from DNSKEY RRset.",
+ reason, dst_key_id(key->key), alg);
+
+ RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
+ RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, &dnskey,
+ &tuple));
+ dns_diff_appendminimal(diff, &tuple);
+ result = ISC_R_SUCCESS;
+
+ failure:
+ return (result);
+}
+
+/*
+ * Update 'keys' with information from 'newkeys'.
+ *
+ * If 'removed' is not NULL, any keys that are being removed from
+ * the zone will be added to the list for post-removal processing.
+ */
+isc_result_t
+dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
+ dns_dnsseckeylist_t *removed, dns_name_t *origin,
+ dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk,
+ isc_mem_t *mctx, void (*report)(const char *, ...))
+{
+ isc_result_t result;
+ dns_dnsseckey_t *key, *key1, *key2, *next;
+
+ /*
+ * First, look through the existing key list to find keys
+ * supplied from the command line which are not in the zone.
+ * Update the zone to include them.
+ */
+ for (key = ISC_LIST_HEAD(*keys);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ if (key->source == dns_keysource_user &&
+ (key->hint_publish || key->force_publish)) {
+ RETERR(publish_key(diff, key, origin, ttl,
+ mctx, allzsk, report));
+ }
+ }
+
+ /*
+ * Second, scan the list of newly found keys looking for matches
+ * with known keys, and update accordingly.
+ */
+ for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) {
+ isc_boolean_t key_revoked = ISC_FALSE;
+
+ next = ISC_LIST_NEXT(key1, link);
+
+ for (key2 = ISC_LIST_HEAD(*keys);
+ key2 != NULL;
+ key2 = ISC_LIST_NEXT(key2, link)) {
+ if (dst_key_pubcompare(key1->key, key2->key,
+ ISC_TRUE)) {
+ int r1, r2;
+ r1 = dst_key_flags(key1->key) &
+ DNS_KEYFLAG_REVOKE;
+ r2 = dst_key_flags(key2->key) &
+ DNS_KEYFLAG_REVOKE;
+ key_revoked = ISC_TF(r1 != r2);
+ break;
+ }
+ }
+
+ /* No match found in keys; add the new key. */
+ if (key2 == NULL) {
+ dns_dnsseckey_t *next;
+
+ next = ISC_LIST_NEXT(key1, link);
+ ISC_LIST_UNLINK(*newkeys, key1, link);
+ ISC_LIST_APPEND(*keys, key1, link);
+
+ if (key1->source != dns_keysource_zoneapex &&
+ (key1->hint_publish || key1->force_publish)) {
+ RETERR(publish_key(diff, key1, origin, ttl,
+ mctx, allzsk, report));
+ if (key1->hint_sign || key1->force_sign)
+ key1->first_sign = ISC_TRUE;
+ }
+
+ continue;
+ }
+
+ /* Match found: remove or update it as needed */
+ if (key1->hint_remove) {
+ RETERR(remove_key(diff, key2, origin, ttl, mctx,
+ "expired", report));
+ ISC_LIST_UNLINK(*keys, key2, link);
+ if (removed != NULL)
+ ISC_LIST_APPEND(*removed, key2, link);
+ else
+ dns_dnsseckey_destroy(mctx, &key2);
+ } else if (key_revoked &&
+ (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) {
+
+ /*
+ * A previously valid key has been revoked.
+ * We need to remove the old version and pull
+ * in the new one.
+ */
+ RETERR(remove_key(diff, key2, origin, ttl, mctx,
+ "revoked", report));
+ ISC_LIST_UNLINK(*keys, key2, link);
+ if (removed != NULL)
+ ISC_LIST_APPEND(*removed, key2, link);
+ else
+ dns_dnsseckey_destroy(mctx, &key2);
+
+ RETERR(publish_key(diff, key1, origin, ttl,
+ mctx, allzsk, report));
+ ISC_LIST_UNLINK(*newkeys, key1, link);
+ ISC_LIST_APPEND(*keys, key1, link);
+
+ /*
+ * XXX: The revoke flag is only defined for trust
+ * anchors. Setting the flag on a non-KSK is legal,
+ * but not defined in any RFC. It seems reasonable
+ * to treat it the same as a KSK: keep it in the
+ * zone, sign the DNSKEY set with it, but not
+ * sign other records with it.
+ */
+ key1->ksk = ISC_TRUE;
+ continue;
+ } else {
+ if (!key2->is_active &&
+ (key1->hint_sign || key1->force_sign))
+ key2->first_sign = ISC_TRUE;
+ key2->hint_sign = key1->hint_sign;
+ key2->hint_publish = key1->hint_publish;
+ }
+ }
+
+ /* Free any leftover keys in newkeys */
+ while (!ISC_LIST_EMPTY(*newkeys)) {
+ key1 = ISC_LIST_HEAD(*newkeys);
+ ISC_LIST_UNLINK(*newkeys, key1, link);
+ dns_dnsseckey_destroy(mctx, &key1);
+ }
+
+ result = ISC_R_SUCCESS;
+
+ failure:
+ return (result);
+}
diff --git a/contrib/bind9/lib/dns/ds.c b/contrib/bind9/lib/dns/ds.c
index 9cf5659..80e1503 100644
--- a/contrib/bind9/lib/dns/ds.c
+++ b/contrib/bind9/lib/dns/ds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002, 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: ds.c,v 1.11 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: ds.c,v 1.13 2010-12-23 23:47:08 tbox Exp $ */
/*! \file */
@@ -38,6 +38,13 @@
#include <dst/dst.h>
+#ifdef HAVE_OPENSSL_GOST
+#include <dst/result.h>
+#include <openssl/evp.h>
+
+extern const EVP_MD * EVP_gost(void);
+#endif
+
isc_result_t
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
unsigned int digest_type, unsigned char *buffer,
@@ -49,6 +56,12 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
isc_region_t r;
isc_buffer_t b;
dns_rdata_ds_t ds;
+ isc_sha1_t sha1;
+ isc_sha256_t sha256;
+#ifdef HAVE_OPENSSL_GOST
+ EVP_MD_CTX ctx;
+ const EVP_MD *md;
+#endif
REQUIRE(key != NULL);
REQUIRE(key->type == dns_rdatatype_dnskey);
@@ -63,8 +76,8 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
memset(buffer, 0, DNS_DS_BUFFERSIZE);
isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);
- if (digest_type == DNS_DSDIGEST_SHA1) {
- isc_sha1_t sha1;
+ switch (digest_type) {
+ case DNS_DSDIGEST_SHA1:
isc_sha1_init(&sha1);
dns_name_toregion(name, &r);
isc_sha1_update(&sha1, r.base, r.length);
@@ -72,8 +85,33 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
INSIST(r.length >= 4);
isc_sha1_update(&sha1, r.base, r.length);
isc_sha1_final(&sha1, digest);
- } else {
- isc_sha256_t sha256;
+ break;
+#ifdef HAVE_OPENSSL_GOST
+#define CHECK(x) \
+ if ((x) != 1) { \
+ EVP_MD_CTX_cleanup(&ctx); \
+ return (DST_R_OPENSSLFAILURE); \
+ }
+
+ case DNS_DSDIGEST_GOST:
+ md = EVP_gost();
+ if (md == NULL)
+ return (DST_R_OPENSSLFAILURE);
+ EVP_MD_CTX_init(&ctx);
+ CHECK(EVP_DigestInit(&ctx, md));
+ dns_name_toregion(name, &r);
+ CHECK(EVP_DigestUpdate(&ctx,
+ (const void *) r.base,
+ (size_t) r.length));
+ dns_rdata_toregion(key, &r);
+ INSIST(r.length >= 4);
+ CHECK(EVP_DigestUpdate(&ctx,
+ (const void *) r.base,
+ (size_t) r.length));
+ CHECK(EVP_DigestFinal(&ctx, digest, NULL));
+ break;
+#endif
+ default:
isc_sha256_init(&sha256);
dns_name_toregion(name, &r);
isc_sha256_update(&sha256, r.base, r.length);
@@ -81,6 +119,7 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
INSIST(r.length >= 4);
isc_sha256_update(&sha256, r.base, r.length);
isc_sha256_final(digest, &sha256);
+ break;
}
ds.mctx = NULL;
@@ -89,8 +128,19 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
ds.algorithm = r.base[3];
ds.key_tag = dst_region_computeid(&r, ds.algorithm);
ds.digest_type = digest_type;
- ds.length = (digest_type == DNS_DSDIGEST_SHA1) ?
- ISC_SHA1_DIGESTLENGTH : ISC_SHA256_DIGESTLENGTH;
+ switch (digest_type) {
+ case DNS_DSDIGEST_SHA1:
+ ds.length = ISC_SHA1_DIGESTLENGTH;
+ break;
+#ifdef HAVE_OPENSSL_GOST
+ case DNS_DSDIGEST_GOST:
+ ds.length = ISC_GOST_DIGESTLENGTH;
+ break;
+#endif
+ default:
+ ds.length = ISC_SHA256_DIGESTLENGTH;
+ break;
+ }
ds.digest = digest;
return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
@@ -99,6 +149,12 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
isc_boolean_t
dns_ds_digest_supported(unsigned int digest_type) {
+#ifdef HAVE_OPENSSL_GOST
+ return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
+ digest_type == DNS_DSDIGEST_SHA256 ||
+ digest_type == DNS_DSDIGEST_GOST));
+#else
return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
digest_type == DNS_DSDIGEST_SHA256));
+#endif
}
diff --git a/contrib/bind9/lib/dns/dst_api.c b/contrib/bind9/lib/dns/dst_api.c
index 97d2657..1ece312 100644
--- a/contrib/bind9/lib/dns/dst_api.c
+++ b/contrib/bind9/lib/dns/dst_api.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2011 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
@@ -31,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: dst_api.c,v 1.16.12.12 2010-12-09 01:12:55 marka Exp $
+ * $Id: dst_api.c,v 1.57 2011-01-11 23:47:13 tbox Exp $
*/
/*! \file */
@@ -39,6 +39,7 @@
#include <config.h>
#include <stdlib.h>
+#include <time.h>
#include <isc/buffer.h>
#include <isc/dir.h>
@@ -48,6 +49,7 @@
#include <isc/lex.h>
#include <isc/mem.h>
#include <isc/once.h>
+#include <isc/platform.h>
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/random.h>
@@ -70,7 +72,9 @@
#define DST_AS_STR(t) ((t).value.as_textregion.base)
static dst_func_t *dst_t_func[DST_MAX_ALGS];
+#ifdef BIND9
static isc_entropy_t *dst_entropy_pool = NULL;
+#endif
static unsigned int dst_entropy_flags = 0;
static isc_boolean_t dst_initialized = ISC_FALSE;
@@ -108,10 +112,11 @@ static isc_result_t frombuffer(dns_name_t *name,
static isc_result_t algorithm_status(unsigned int alg);
-static isc_result_t addsuffix(char *filename, unsigned int len,
- const char *ofilename, const char *suffix);
+static isc_result_t addsuffix(char *filename, int len,
+ const char *dirname, const char *ofilename,
+ const char *suffix);
-#define RETERR(x) \
+#define RETERR(x) \
do { \
result = (x); \
if (result != ISC_R_SUCCESS) \
@@ -126,7 +131,7 @@ static isc_result_t addsuffix(char *filename, unsigned int len,
return (_r); \
} while (0); \
-#ifdef OPENSSL
+#if defined(OPENSSL) && defined(BIND9)
static void *
default_memalloc(void *arg, size_t size) {
UNUSED(arg);
@@ -144,14 +149,29 @@ default_memfree(void *arg, void *ptr) {
isc_result_t
dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
+ return (dst_lib_init2(mctx, ectx, NULL, eflags));
+}
+
+isc_result_t
+dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx,
+ const char *engine, unsigned int eflags) {
isc_result_t result;
- REQUIRE(mctx != NULL && ectx != NULL);
+ REQUIRE(mctx != NULL);
+#ifdef BIND9
+ REQUIRE(ectx != NULL);
+#else
+ UNUSED(ectx);
+#endif
REQUIRE(dst_initialized == ISC_FALSE);
+#ifndef OPENSSL
+ UNUSED(engine);
+#endif
+
dst__memory_pool = NULL;
-#ifdef OPENSSL
+#if defined(OPENSSL) && defined(BIND9)
UNUSED(mctx);
/*
* When using --with-openssl, there seems to be no good way of not
@@ -166,11 +186,15 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
if (result != ISC_R_SUCCESS)
return (result);
isc_mem_setname(dst__memory_pool, "dst", NULL);
+#ifndef OPENSSL_LEAKS
isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE);
+#endif
#else
isc_mem_attach(mctx, &dst__memory_pool);
#endif
+#ifdef BIND9
isc_entropy_attach(ectx, &dst_entropy_pool);
+#endif
dst_entropy_flags = eflags;
dst_result_register();
@@ -183,7 +207,7 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384]));
RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512]));
#ifdef OPENSSL
- RETERR(dst__openssl_init());
+ RETERR(dst__openssl_init(engine));
RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5],
DST_ALG_RSAMD5));
RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1],
@@ -199,6 +223,9 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
#endif
RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
+#ifdef HAVE_OPENSSL_GOST
+ RETERR(dst__opensslgost_init(&dst_t_func[DST_ALG_ECCGOST]));
+#endif
#endif /* OPENSSL */
#ifdef GSSAPI
RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
@@ -207,6 +234,8 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
return (ISC_R_SUCCESS);
out:
+ /* avoid immediate crash! */
+ dst_initialized = ISC_TRUE;
dst_lib_destroy();
return (result);
}
@@ -225,9 +254,10 @@ dst_lib_destroy(void) {
#endif
if (dst__memory_pool != NULL)
isc_mem_detach(&dst__memory_pool);
+#ifdef BIND9
if (dst_entropy_pool != NULL)
isc_entropy_detach(&dst_entropy_pool);
-
+#endif
}
isc_boolean_t
@@ -402,7 +432,7 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
return (result);
key = NULL;
- result = dst_key_fromnamedfile(filename, type, mctx, &key);
+ result = dst_key_fromnamedfile(filename, NULL, type, mctx, &key);
if (result != ISC_R_SUCCESS)
return (result);
@@ -424,12 +454,11 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
}
isc_result_t
-dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
- dst_key_t **keyp)
+dst_key_fromnamedfile(const char *filename, const char *dirname,
+ int type, isc_mem_t *mctx, dst_key_t **keyp)
{
isc_result_t result;
dst_key_t *pubkey = NULL, *key = NULL;
- dns_keytag_t id;
char *newfilename = NULL;
int newfilenamelen = 0;
isc_lex_t *lex = NULL;
@@ -440,11 +469,23 @@ dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
REQUIRE(mctx != NULL);
REQUIRE(keyp != NULL && *keyp == NULL);
+ /* If an absolute path is specified, don't use the key directory */
+#ifndef WIN32
+ if (filename[0] == '/')
+ dirname = NULL;
+#else /* WIN32 */
+ if (filename[0] == '/' || filename[0] == '\\')
+ dirname = NULL;
+#endif
+
newfilenamelen = strlen(filename) + 5;
+ if (dirname != NULL)
+ newfilenamelen += strlen(dirname) + 1;
newfilename = isc_mem_get(mctx, newfilenamelen);
if (newfilename == NULL)
return (ISC_R_NOMEMORY);
- result = addsuffix(newfilename, newfilenamelen, filename, ".key");
+ result = addsuffix(newfilename, newfilenamelen,
+ dirname, filename, ".key");
INSIST(result == ISC_R_SUCCESS);
result = dst_key_read_public(newfilename, type, mctx, &pubkey);
@@ -474,38 +515,43 @@ dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
key = get_key_struct(pubkey->key_name, pubkey->key_alg,
pubkey->key_flags, pubkey->key_proto, 0,
pubkey->key_class, mctx);
- id = pubkey->key_id;
- dst_key_free(&pubkey);
-
- if (key == NULL)
+ if (key == NULL) {
+ dst_key_free(&pubkey);
return (ISC_R_NOMEMORY);
+ }
if (key->func->parse == NULL)
RETERR(DST_R_UNSUPPORTEDALG);
newfilenamelen = strlen(filename) + 9;
+ if (dirname != NULL)
+ newfilenamelen += strlen(dirname) + 1;
newfilename = isc_mem_get(mctx, newfilenamelen);
if (newfilename == NULL)
RETERR(ISC_R_NOMEMORY);
- result = addsuffix(newfilename, newfilenamelen, filename, ".private");
+ result = addsuffix(newfilename, newfilenamelen,
+ dirname, filename, ".private");
INSIST(result == ISC_R_SUCCESS);
RETERR(isc_lex_create(mctx, 1500, &lex));
RETERR(isc_lex_openfile(lex, newfilename));
isc_mem_put(mctx, newfilename, newfilenamelen);
- RETERR(key->func->parse(key, lex));
+ RETERR(key->func->parse(key, lex, pubkey));
isc_lex_destroy(&lex);
RETERR(computeid(key));
- if (id != key->key_id)
+ if (pubkey->key_id != key->key_id)
RETERR(DST_R_INVALIDPRIVATEKEY);
+ dst_key_free(&pubkey);
*keyp = key;
return (ISC_R_SUCCESS);
out:
+ if (pubkey != NULL)
+ dst_key_free(&pubkey);
if (newfilename != NULL)
isc_mem_put(mctx, newfilename, newfilenamelen);
if (lex != NULL)
@@ -640,7 +686,7 @@ dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
RETERR(isc_lex_create(key->mctx, 1500, &lex));
RETERR(isc_lex_openbuffer(lex, buffer));
- RETERR(key->func->parse(key, lex));
+ RETERR(key->func->parse(key, lex, NULL));
out:
if (lex != NULL)
isc_lex_destroy(&lex);
@@ -657,9 +703,10 @@ dst_key_getgssctx(const dst_key_t *key)
isc_result_t
dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
- dst_key_t **keyp)
+ dst_key_t **keyp, isc_region_t *intoken)
{
dst_key_t *key;
+ isc_result_t result;
REQUIRE(gssctx != NULL);
REQUIRE(keyp != NULL && *keyp == NULL);
@@ -669,9 +716,21 @@ dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
if (key == NULL)
return (ISC_R_NOMEMORY);
+ if (intoken != NULL) {
+ /*
+ * Keep the token for use by external ssu rules. They may need
+ * to examine the PAC in the kerberos ticket.
+ */
+ RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
+ intoken->length));
+ RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
+ }
+
key->keydata.gssctx = gssctx;
*keyp = key;
- return (ISC_R_SUCCESS);
+ result = ISC_R_SUCCESS;
+out:
+ return result;
}
isc_result_t
@@ -723,6 +782,18 @@ dst_key_generate(dns_name_t *name, unsigned int alg,
dns_rdataclass_t rdclass,
isc_mem_t *mctx, dst_key_t **keyp)
{
+ return (dst_key_generate2(name, alg, bits, param, flags, protocol,
+ rdclass, mctx, keyp, NULL));
+}
+
+isc_result_t
+dst_key_generate2(dns_name_t *name, unsigned int alg,
+ unsigned int bits, unsigned int param,
+ unsigned int flags, unsigned int protocol,
+ dns_rdataclass_t rdclass,
+ isc_mem_t *mctx, dst_key_t **keyp,
+ void (*callback)(int))
+{
dst_key_t *key;
isc_result_t ret;
@@ -748,7 +819,7 @@ dst_key_generate(dns_name_t *name, unsigned int alg,
return (DST_R_UNSUPPORTEDALG);
}
- ret = key->func->generate(key, param);
+ ret = key->func->generate(key, param, callback);
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
@@ -764,25 +835,185 @@ dst_key_generate(dns_name_t *name, unsigned int alg,
return (ISC_R_SUCCESS);
}
-isc_boolean_t
-dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
+isc_result_t
+dst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep)
+{
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(valuep != NULL);
+ REQUIRE(type <= DST_MAX_NUMERIC);
+ if (!key->numset[type])
+ return (ISC_R_NOTFOUND);
+ *valuep = key->nums[type];
+ return (ISC_R_SUCCESS);
+}
+
+void
+dst_key_setnum(dst_key_t *key, int type, isc_uint32_t value)
+{
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(type <= DST_MAX_NUMERIC);
+ key->nums[type] = value;
+ key->numset[type] = ISC_TRUE;
+}
+
+void
+dst_key_unsetnum(dst_key_t *key, int type)
+{
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(type <= DST_MAX_NUMERIC);
+ key->numset[type] = ISC_FALSE;
+}
+
+isc_result_t
+dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(timep != NULL);
+ REQUIRE(type <= DST_MAX_TIMES);
+ if (!key->timeset[type])
+ return (ISC_R_NOTFOUND);
+ *timep = key->times[type];
+ return (ISC_R_SUCCESS);
+}
+
+void
+dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(type <= DST_MAX_TIMES);
+ key->times[type] = when;
+ key->timeset[type] = ISC_TRUE;
+}
+
+void
+dst_key_unsettime(dst_key_t *key, int type) {
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(type <= DST_MAX_TIMES);
+ key->timeset[type] = ISC_FALSE;
+}
+
+isc_result_t
+dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) {
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(majorp != NULL);
+ REQUIRE(minorp != NULL);
+ *majorp = key->fmt_major;
+ *minorp = key->fmt_minor;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dst_key_setprivateformat(dst_key_t *key, int major, int minor) {
+ REQUIRE(VALID_KEY(key));
+ key->fmt_major = major;
+ key->fmt_minor = minor;
+}
+
+static isc_boolean_t
+comparekeys(const dst_key_t *key1, const dst_key_t *key2,
+ isc_boolean_t match_revoked_key,
+ isc_boolean_t (*compare)(const dst_key_t *key1,
+ const dst_key_t *key2))
+{
REQUIRE(dst_initialized == ISC_TRUE);
REQUIRE(VALID_KEY(key1));
REQUIRE(VALID_KEY(key2));
if (key1 == key2)
return (ISC_TRUE);
+
if (key1 == NULL || key2 == NULL)
return (ISC_FALSE);
- if (key1->key_alg == key2->key_alg &&
- key1->key_id == key2->key_id &&
- key1->func->compare != NULL &&
- key1->func->compare(key1, key2) == ISC_TRUE)
- return (ISC_TRUE);
+
+ if (key1->key_alg != key2->key_alg)
+ return (ISC_FALSE);
+
+ /*
+ * For all algorithms except RSAMD5, revoking the key
+ * changes the key ID, increasing it by 128. If we want to
+ * be able to find matching keys even if one of them is the
+ * revoked version of the other one, then we need to check
+ * for that possibility.
+ */
+ if (key1->key_id != key2->key_id) {
+ if (!match_revoked_key)
+ return (ISC_FALSE);
+ if (key1->key_alg == DST_ALG_RSAMD5)
+ return (ISC_FALSE);
+ if ((key1->key_flags & DNS_KEYFLAG_REVOKE) ==
+ (key2->key_flags & DNS_KEYFLAG_REVOKE))
+ return (ISC_FALSE);
+ if ((key1->key_flags & DNS_KEYFLAG_REVOKE) != 0 &&
+ key1->key_id != ((key2->key_id + 128) & 0xffff))
+ return (ISC_FALSE);
+ if ((key2->key_flags & DNS_KEYFLAG_REVOKE) != 0 &&
+ key2->key_id != ((key1->key_id + 128) & 0xffff))
+ return (ISC_FALSE);
+ }
+
+ if (compare != NULL)
+ return (compare(key1, key2));
else
return (ISC_FALSE);
}
+
+/*
+ * Compares only the public portion of two keys, by converting them
+ * both to wire format and comparing the results.
+ */
+static isc_boolean_t
+pub_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ isc_result_t result;
+ unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE];
+ isc_buffer_t b1, b2;
+ isc_region_t r1, r2;
+
+ isc_buffer_init(&b1, buf1, sizeof(buf1));
+ result = dst_key_todns(key1, &b1);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+ /* Zero out flags. */
+ buf1[0] = buf1[1] = 0;
+ if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
+ isc_buffer_subtract(&b1, 2);
+
+ isc_buffer_init(&b2, buf2, sizeof(buf2));
+ result = dst_key_todns(key2, &b2);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+ /* Zero out flags. */
+ buf2[0] = buf2[1] = 0;
+ if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
+ isc_buffer_subtract(&b2, 2);
+
+ isc_buffer_usedregion(&b1, &r1);
+ /* Remove extended flags. */
+ if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
+ memmove(&buf1[4], &buf1[6], r1.length - 6);
+ r1.length -= 2;
+ }
+
+ isc_buffer_usedregion(&b2, &r2);
+ /* Remove extended flags. */
+ if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
+ memmove(&buf2[4], &buf2[6], r2.length - 6);
+ r2.length -= 2;
+ }
+ return (ISC_TF(isc_region_compare(&r1, &r2) == 0));
+}
+
+isc_boolean_t
+dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ return (comparekeys(key1, key2, ISC_FALSE, key1->func->compare));
+}
+
+isc_boolean_t
+dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
+ isc_boolean_t match_revoked_key)
+{
+ return (comparekeys(key1, key2, match_revoked_key, pub_compare));
+}
+
+
isc_boolean_t
dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
REQUIRE(dst_initialized == ISC_TRUE);
@@ -839,6 +1070,9 @@ dst_key_free(dst_key_t **keyp) {
isc_mem_free(mctx, key->label);
dns_name_free(key->key_name, mctx);
isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
+ if (key->key_tkeytoken) {
+ isc_buffer_free(&key->key_tkeytoken);
+ }
memset(key, 0, sizeof(dst_key_t));
isc_mem_put(mctx, key, sizeof(dst_key_t));
*keyp = NULL;
@@ -882,6 +1116,9 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
case DST_ALG_NSEC3DSA:
*n = DNS_SIG_DSASIGSIZE;
break;
+ case DST_ALG_ECCGOST:
+ *n = DNS_SIG_GOSTSIGSIZE;
+ break;
case DST_ALG_HMACMD5:
*n = 16;
break;
@@ -923,6 +1160,69 @@ dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
return (ISC_R_SUCCESS);
}
+/*%
+ * Set the flags on a key, then recompute the key ID
+ */
+isc_result_t
+dst_key_setflags(dst_key_t *key, isc_uint32_t flags) {
+ REQUIRE(VALID_KEY(key));
+ key->key_flags = flags;
+ return (computeid(key));
+}
+
+void
+dst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char algstr[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
+ dns_secalg_format((dns_secalg_t) dst_key_alg(key), algstr,
+ sizeof(algstr));
+ snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
+}
+
+isc_result_t
+dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
+
+ REQUIRE(buffer != NULL && *buffer == NULL);
+ REQUIRE(length != NULL && *length == 0);
+ REQUIRE(VALID_KEY(key));
+
+ if (key->func->isprivate == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+ return (key->func->dump(key, mctx, buffer, length));
+}
+
+isc_result_t
+dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
+ unsigned int protocol, dns_rdataclass_t rdclass,
+ isc_mem_t *mctx, const char *keystr, dst_key_t **keyp)
+{
+ isc_result_t result;
+ dst_key_t *key;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(keyp != NULL && *keyp == NULL);
+
+ if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
+ return (DST_R_UNSUPPORTEDALG);
+
+ if (dst_t_func[alg]->restore == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx);
+ if (key == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = (dst_t_func[alg]->restore)(key, keystr);
+ if (result == ISC_R_SUCCESS)
+ *keyp = key;
+ else
+ dst_key_free(&key);
+
+ return (result);
+}
+
/***
*** Static methods
***/
@@ -938,6 +1238,7 @@ get_key_struct(dns_name_t *name, unsigned int alg,
{
dst_key_t *key;
isc_result_t result;
+ int i;
key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
if (key == NULL)
@@ -974,6 +1275,12 @@ get_key_struct(dns_name_t *name, unsigned int alg,
key->key_size = bits;
key->key_class = rdclass;
key->func = dst_t_func[alg];
+ key->fmt_major = 0;
+ key->fmt_minor = 0;
+ for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
+ key->times[i] = 0;
+ key->timeset[i] = ISC_FALSE;
+ }
return (key);
}
@@ -1046,7 +1353,7 @@ dst_key_read_public(const char *filename, int type,
isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
isc_buffer_add(&b, strlen(DST_AS_STR(token)));
ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname,
- ISC_FALSE, NULL);
+ 0, NULL);
if (ret != ISC_R_SUCCESS)
goto cleanup;
@@ -1116,6 +1423,7 @@ issymmetric(const dst_key_t *key) {
case DST_ALG_DSA:
case DST_ALG_NSEC3DSA:
case DST_ALG_DH:
+ case DST_ALG_ECCGOST:
return (ISC_FALSE);
case DST_ALG_HMACMD5:
case DST_ALG_GSSAPI:
@@ -1126,6 +1434,55 @@ issymmetric(const dst_key_t *key) {
}
/*%
+ * Write key timing metadata to a file pointer, preceded by 'tag'
+ */
+static void
+printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
+ isc_result_t result;
+#ifdef ISC_PLATFORM_USETHREADS
+ char output[26]; /* Minimum buffer as per ctime_r() specification. */
+#else
+ const char *output;
+#endif
+ isc_stdtime_t when;
+ time_t t;
+ char utc[sizeof("YYYYMMDDHHSSMM")];
+ isc_buffer_t b;
+ isc_region_t r;
+
+ result = dst_key_gettime(key, type, &when);
+ if (result == ISC_R_NOTFOUND)
+ return;
+
+ /* time_t and isc_stdtime_t might be different sizes */
+ t = when;
+#ifdef ISC_PLATFORM_USETHREADS
+#ifdef WIN32
+ if (ctime_s(output, sizeof(output), &t) != 0)
+ goto error;
+#else
+ if (ctime_r(&t, output) == NULL)
+ goto error;
+#endif
+#else
+ output = ctime(&t);
+#endif
+
+ isc_buffer_init(&b, utc, sizeof(utc));
+ result = dns_time32_totext(when, &b);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ isc_buffer_usedregion(&b, &r);
+ fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base,
+ (int)strlen(output) - 1, output);
+ return;
+
+ error:
+ fprintf(stream, "%s: (set, unable to display)\n", tag);
+}
+
+/*%
* Writes a public key to disk in DNS format.
*/
static isc_result_t
@@ -1184,12 +1541,34 @@ write_public_key(const dst_key_t *key, int type, const char *directory) {
(void)isc_fsaccess_set(filename, access);
}
- ret = dns_name_print(key->key_name, fp);
- if (ret != ISC_R_SUCCESS) {
- fclose(fp);
- return (ret);
+ /* Write key information in comments */
+ if ((type & DST_TYPE_KEY) == 0) {
+ fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
+ (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ?
+ "revoked " :
+ "",
+ (key->key_flags & DNS_KEYFLAG_KSK) != 0 ?
+ "key" :
+ "zone",
+ key->key_id);
+ ret = dns_name_print(key->key_name, fp);
+ if (ret != ISC_R_SUCCESS) {
+ fclose(fp);
+ return (ret);
+ }
+ fputc('\n', fp);
+
+ printtime(key, DST_TIME_CREATED, "; Created", fp);
+ printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
+ printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
+ printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
+ printtime(key, DST_TIME_INACTIVE, "; Inactive", fp);
+ printtime(key, DST_TIME_DELETE, "; Delete", fp);
}
+ /* Now print the actual key */
+ ret = dns_name_print(key->key_name, fp);
+
fprintf(fp, " ");
isc_buffer_usedregion(&classb, &r);
@@ -1317,15 +1696,16 @@ algorithm_status(unsigned int alg) {
alg == DST_ALG_DSA || alg == DST_ALG_DH ||
alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA ||
alg == DST_ALG_NSEC3RSASHA1 ||
- alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512)
+ alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512 ||
+ alg == DST_ALG_ECCGOST)
return (DST_R_NOCRYPTO);
#endif
return (DST_R_UNSUPPORTEDALG);
}
static isc_result_t
-addsuffix(char *filename, unsigned int len, const char *ofilename,
- const char *suffix)
+addsuffix(char *filename, int len, const char *odirname,
+ const char *ofilename, const char *suffix)
{
int olen = strlen(ofilename);
int n;
@@ -1337,27 +1717,42 @@ addsuffix(char *filename, unsigned int len, const char *ofilename,
else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0)
olen -= 4;
- n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
+ if (odirname == NULL)
+ n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
+ else
+ n = snprintf(filename, len, "%s/%.*s%s",
+ odirname, olen, ofilename, suffix);
if (n < 0)
return (ISC_R_FAILURE);
- if ((unsigned int)n >= len)
+ if (n >= len)
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
}
isc_result_t
dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
+#ifdef BIND9
unsigned int flags = dst_entropy_flags;
if (len == 0)
return (ISC_R_SUCCESS);
if (pseudo)
flags &= ~ISC_ENTROPY_GOODONLY;
+ else
+ flags |= ISC_ENTROPY_BLOCKING;
return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
+#else
+ UNUSED(buf);
+ UNUSED(len);
+ UNUSED(pseudo);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
}
unsigned int
dst__entropy_status(void) {
+#ifdef BIND9
#ifdef GSSAPI
unsigned int flags = dst_entropy_flags;
isc_result_t ret;
@@ -1376,4 +1771,12 @@ dst__entropy_status(void) {
}
#endif
return (isc_entropy_status(dst_entropy_pool));
+#else
+ return (0);
+#endif
+}
+
+isc_buffer_t *
+dst_key_tkeytoken(const dst_key_t *key) {
+ return (key->key_tkeytoken);
}
diff --git a/contrib/bind9/lib/dns/dst_internal.h b/contrib/bind9/lib/dns/dst_internal.h
index 01bf1f2..220b3da 100644
--- a/contrib/bind9/lib/dns/dst_internal.h
+++ b/contrib/bind9/lib/dns/dst_internal.h
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2011 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
@@ -29,7 +29,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_internal.h,v 1.11.120.3 2010-12-09 01:12:55 marka Exp $ */
+/* $Id: dst_internal.h,v 1.29 2011-01-11 23:47:13 tbox Exp $ */
#ifndef DST_DST_INTERNAL_H
#define DST_DST_INTERNAL_H 1
@@ -44,9 +44,12 @@
#include <isc/refcount.h>
#include <isc/sha1.h>
#include <isc/sha2.h>
+#include <isc/stdtime.h>
#include <isc/hmacmd5.h>
#include <isc/hmacsha.h>
+#include <dns/time.h>
+
#include <dst/dst.h>
#ifdef OPENSSL
@@ -60,8 +63,8 @@
ISC_LANG_BEGINDECLS
-#define KEY_MAGIC ISC_MAGIC('D','S','T','K')
-#define CTX_MAGIC ISC_MAGIC('D','S','T','C')
+#define KEY_MAGIC ISC_MAGIC('D','S','T','K')
+#define CTX_MAGIC ISC_MAGIC('D','S','T','C')
#define VALID_KEY(x) ISC_MAGIC_VALID(x, KEY_MAGIC)
#define VALID_CTX(x) ISC_MAGIC_VALID(x, CTX_MAGIC)
@@ -74,7 +77,7 @@ 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_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;
@@ -115,7 +118,17 @@ struct dst_key {
dst_hmacsha512_key_t *hmacsha512;
} keydata; /*%< pointer to key in crypto pkg fmt */
- dst_func_t * func; /*%< crypto package specific functions */
+
+ isc_stdtime_t times[DST_MAX_TIMES + 1]; /*%< timing metadata */
+ isc_boolean_t timeset[DST_MAX_TIMES + 1]; /*%< data set? */
+ isc_stdtime_t nums[DST_MAX_NUMERIC + 1]; /*%< numeric metadata */
+ isc_boolean_t numset[DST_MAX_NUMERIC + 1]; /*%< data set? */
+
+ int fmt_major; /*%< private key format, major version */
+ int fmt_minor; /*%< private key format, minor version */
+
+ dst_func_t * func; /*%< crypto package specific functions */
+ isc_buffer_t *key_tkeytoken; /*%< TKEY token data */
};
struct dst_context {
@@ -160,7 +173,8 @@ struct dst_func {
isc_boolean_t (*compare)(const dst_key_t *key1, const dst_key_t *key2);
isc_boolean_t (*paramcompare)(const dst_key_t *key1,
const dst_key_t *key2);
- isc_result_t (*generate)(dst_key_t *key, int parms);
+ isc_result_t (*generate)(dst_key_t *key, int parms,
+ void (*callback)(int));
isc_boolean_t (*isprivate)(const dst_key_t *key);
void (*destroy)(dst_key_t *key);
@@ -168,19 +182,24 @@ struct dst_func {
isc_result_t (*todns)(const dst_key_t *key, isc_buffer_t *data);
isc_result_t (*fromdns)(dst_key_t *key, isc_buffer_t *data);
isc_result_t (*tofile)(const dst_key_t *key, const char *directory);
- isc_result_t (*parse)(dst_key_t *key, isc_lex_t *lexer);
+ isc_result_t (*parse)(dst_key_t *key,
+ isc_lex_t *lexer,
+ dst_key_t *pub);
/* cleanup */
void (*cleanup)(void);
isc_result_t (*fromlabel)(dst_key_t *key, const char *engine,
const char *label, const char *pin);
+ isc_result_t (*dump)(dst_key_t *key, isc_mem_t *mctx, char **buffer,
+ int *length);
+ isc_result_t (*restore)(dst_key_t *key, const char *keystr);
};
/*%
* Initializers
*/
-isc_result_t dst__openssl_init(void);
+isc_result_t dst__openssl_init(const char *engine);
isc_result_t dst__hmacmd5_init(struct dst_func **funcp);
isc_result_t dst__hmacsha1_init(struct dst_func **funcp);
@@ -193,6 +212,9 @@ isc_result_t dst__opensslrsa_init(struct dst_func **funcp,
isc_result_t dst__openssldsa_init(struct dst_func **funcp);
isc_result_t dst__openssldh_init(struct dst_func **funcp);
isc_result_t dst__gssapi_init(struct dst_func **funcp);
+#ifdef HAVE_OPENSSL_GOST
+isc_result_t dst__opensslgost_init(struct dst_func **funcp);
+#endif
/*%
* Destructors
diff --git a/contrib/bind9/lib/dns/dst_openssl.h b/contrib/bind9/lib/dns/dst_openssl.h
index a095d45..781085b 100644
--- a/contrib/bind9/lib/dns/dst_openssl.h
+++ b/contrib/bind9/lib/dns/dst_openssl.h
@@ -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) 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: dst_openssl.h,v 1.7 2008-04-01 23:47:10 tbox Exp $ */
+/* $Id: dst_openssl.h,v 1.9 2009-10-06 04:40:14 tbox Exp $ */
#ifndef DST_OPENSSL_H
#define DST_OPENSSL_H 1
@@ -29,10 +29,7 @@ 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);
+dst__openssl_getengine(const char *engine);
ISC_LANG_ENDDECLS
diff --git a/contrib/bind9/lib/dns/dst_parse.c b/contrib/bind9/lib/dns/dst_parse.c
index 37264be..4d7d784 100644
--- a/contrib/bind9/lib/dns/dst_parse.c
+++ b/contrib/bind9/lib/dns/dst_parse.c
@@ -31,7 +31,7 @@
/*%
* Principal Author: Brian Wellington
- * $Id: dst_parse.c,v 1.14.120.6 2010-01-15 19:38:53 each Exp $
+ * $Id: dst_parse.c,v 1.27 2010-12-23 04:07:58 marka Exp $
*/
#include <config.h>
@@ -41,9 +41,12 @@
#include <isc/fsaccess.h>
#include <isc/lex.h>
#include <isc/mem.h>
+#include <isc/stdtime.h>
#include <isc/string.h>
#include <isc/util.h>
+#include <dns/time.h>
+
#include "dst_internal.h"
#include "dst_parse.h"
#include "dst/result.h"
@@ -53,6 +56,25 @@
#define PRIVATE_KEY_STR "Private-key-format:"
#define ALGORITHM_STR "Algorithm:"
+#define TIMING_NTAGS (DST_MAX_TIMES + 1)
+static const char *timetags[TIMING_NTAGS] = {
+ "Created:",
+ "Publish:",
+ "Activate:",
+ "Revoke:",
+ "Inactive:",
+ "Delete:",
+ "DSPublish:"
+};
+
+#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
+static const char *numerictags[NUMERIC_NTAGS] = {
+ "Predecessor:",
+ "Successor:",
+ "MaxTTL:",
+ "RollPeriod:"
+};
+
struct parse_map {
const int value;
const char *tag;
@@ -82,6 +104,8 @@ static struct parse_map map[] = {
{TAG_DSA_PRIVATE, "Private_value(x):"},
{TAG_DSA_PUBLIC, "Public_value(y):"},
+ {TAG_GOST_PRIVASN1, "GostAsn1:"},
+
{TAG_HMACMD5_KEY, "Key:"},
{TAG_HMACMD5_BITS, "Bits:"},
@@ -107,13 +131,12 @@ static int
find_value(const char *s, const unsigned int alg) {
int i;
- for (i = 0; ; i++) {
- if (map[i].tag == NULL)
- return (-1);
- else if (strcasecmp(s, map[i].tag) == 0 &&
- TAG_ALG(map[i].value) == alg)
+ for (i = 0; map[i].tag != NULL; i++) {
+ if (strcasecmp(s, map[i].tag) == 0 &&
+ (TAG_ALG(map[i].value) == alg))
return (map[i].value);
}
+ return (-1);
}
static const char *
@@ -129,6 +152,28 @@ find_tag(const int value) {
}
static int
+find_metadata(const char *s, const char *tags[], int ntags) {
+ int i;
+
+ for (i = 0; i < ntags; i++) {
+ if (strcasecmp(s, tags[i]) == 0)
+ return (i);
+ }
+
+ return (-1);
+}
+
+static int
+find_timedata(const char *s) {
+ return (find_metadata(s, timetags, TIMING_NTAGS));
+}
+
+static int
+find_numericdata(const char *s) {
+ return (find_metadata(s, numerictags, NUMERIC_NTAGS));
+}
+
+static int
check_rsa(const dst_private_t *priv) {
int i, j;
isc_boolean_t have[RSA_NTAGS];
@@ -197,6 +242,15 @@ check_dsa(const dst_private_t *priv) {
}
static int
+check_gost(const dst_private_t *priv) {
+ if (priv->nelements != GOST_NTAGS)
+ return (-1);
+ if (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0))
+ return (-1);
+ return (0);
+}
+
+static int
check_hmac_md5(const dst_private_t *priv, isc_boolean_t old) {
int i, j;
@@ -253,6 +307,8 @@ check_data(const dst_private_t *priv, const unsigned int alg,
return (check_dh(priv));
case DST_ALG_DSA:
return (check_dsa(priv));
+ case DST_ALG_ECCGOST:
+ return (check_gost(priv));
case DST_ALG_HMACMD5:
return (check_hmac_md5(priv, old));
case DST_ALG_HMACSHA1:
@@ -285,7 +341,7 @@ dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx) {
priv->nelements = 0;
}
-int
+isc_result_t
dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
isc_mem_t *mctx, dst_private_t *priv)
{
@@ -294,6 +350,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
isc_token_t token;
unsigned char *data = NULL;
unsigned int opt = ISC_LEXOPT_EOL;
+ isc_stdtime_t when;
isc_result_t ret;
REQUIRE(priv != NULL);
@@ -341,13 +398,16 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
goto fail;
}
- if (major > MAJOR_VERSION ||
- (major == MAJOR_VERSION && minor > MINOR_VERSION))
- {
+ if (major > DST_MAJOR_VERSION) {
ret = DST_R_INVALIDPRIVATEKEY;
goto fail;
}
+ /*
+ * Store the private key format version number
+ */
+ dst_key_setprivateformat(key, major, minor);
+
READLINE(lex, opt, &token);
/*
@@ -377,7 +437,6 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
for (n = 0; n < MAXFIELDS; n++) {
int tag;
isc_region_t r;
-
do {
ret = isc_lex_gettoken(lex, opt, &token);
if (ret == ISC_R_EOF)
@@ -391,11 +450,50 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
goto fail;
}
+ /* Numeric metadata */
+ tag = find_numericdata(DST_AS_STR(token));
+ if (tag >= 0) {
+ INSIST(tag < NUMERIC_NTAGS);
+
+ NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
+ if (token.type != isc_tokentype_number) {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ dst_key_setnum(key, tag, token.value.as_ulong);
+ goto next;
+ }
+
+ /* Timing metadata */
+ tag = find_timedata(DST_AS_STR(token));
+ if (tag >= 0) {
+ INSIST(tag < TIMING_NTAGS);
+
+ NEXTTOKEN(lex, opt, &token);
+ if (token.type != isc_tokentype_string) {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ ret = dns_time32_fromtext(DST_AS_STR(token), &when);
+ if (ret != ISC_R_SUCCESS)
+ goto fail;
+
+ dst_key_settime(key, tag, when);
+
+ goto next;
+ }
+
+ /* Key data */
tag = find_value(DST_AS_STR(token), alg);
- if (tag < 0 || TAG_ALG(tag) != alg) {
+ if (tag < 0 && minor > DST_MINOR_VERSION)
+ goto next;
+ else if (tag < 0) {
ret = DST_R_INVALIDPRIVATEKEY;
goto fail;
}
+
priv->elements[n].tag = tag;
data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE);
@@ -406,23 +504,23 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
ret = isc_base64_tobuffer(lex, &b, -1);
if (ret != ISC_R_SUCCESS)
goto fail;
+
isc_buffer_usedregion(&b, &r);
priv->elements[n].length = r.length;
priv->elements[n].data = r.base;
+ priv->nelements++;
+ next:
READLINE(lex, opt, &token);
data = NULL;
}
done:
- priv->nelements = n;
-
if (check_data(priv, alg, ISC_TRUE) < 0)
goto fail;
return (ISC_R_SUCCESS);
fail:
- priv->nelements = n;
dst__privstruct_free(priv, mctx);
if (data != NULL)
isc_mem_put(mctx, data, MAXFIELDSIZE);
@@ -430,17 +528,21 @@ fail:
return (ret);
}
-int
+isc_result_t
dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
const char *directory)
{
FILE *fp;
int ret, i;
- isc_result_t iret;
+ isc_result_t result;
char filename[ISC_DIR_NAMEMAX];
char buffer[MAXFIELDSIZE * 2];
- isc_buffer_t b;
isc_fsaccess_t access;
+ isc_stdtime_t when;
+ isc_uint32_t value;
+ isc_buffer_t b;
+ isc_region_t r;
+ int major, minor;
REQUIRE(priv != NULL);
@@ -461,11 +563,17 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
&access);
(void)isc_fsaccess_set(filename, access);
+ dst_key_getprivateformat(key, &major, &minor);
+ if (major == 0 && minor == 0) {
+ major = DST_MAJOR_VERSION;
+ minor = DST_MINOR_VERSION;
+ }
+
/* XXXDCL return value should be checked for full filesystem */
- fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, MAJOR_VERSION,
- MINOR_VERSION);
+ fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, major, minor);
fprintf(fp, "%s %d ", ALGORITHM_STR, dst_key_alg(key));
+
/* XXXVIX this switch statement is too sparse to gen a jump table. */
switch (dst_key_alg(key)) {
case DST_ALG_RSAMD5:
@@ -480,18 +588,21 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
case DST_ALG_RSASHA1:
fprintf(fp, "(RSASHA1)\n");
break;
- case DST_ALG_NSEC3DSA:
- fprintf(fp, "(NSEC3DSA)\n");
- break;
case DST_ALG_NSEC3RSASHA1:
fprintf(fp, "(NSEC3RSASHA1)\n");
break;
+ case DST_ALG_NSEC3DSA:
+ fprintf(fp, "(NSEC3DSA)\n");
+ break;
case DST_ALG_RSASHA256:
fprintf(fp, "(RSASHA256)\n");
break;
case DST_ALG_RSASHA512:
fprintf(fp, "(RSASHA512)\n");
break;
+ case DST_ALG_ECCGOST:
+ fprintf(fp, "(ECC-GOST)\n");
+ break;
case DST_ALG_HMACMD5:
fprintf(fp, "(HMAC_MD5)\n");
break;
@@ -516,8 +627,6 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
}
for (i = 0; i < priv->nelements; i++) {
- isc_buffer_t b;
- isc_region_t r;
const char *s;
s = find_tag(priv->elements[i].tag);
@@ -525,8 +634,8 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
r.base = priv->elements[i].data;
r.length = priv->elements[i].length;
isc_buffer_init(&b, buffer, sizeof(buffer));
- iret = isc_base64_totext(&r, sizeof(buffer), "", &b);
- if (iret != ISC_R_SUCCESS) {
+ result = isc_base64_totext(&r, sizeof(buffer), "", &b);
+ if (result != ISC_R_SUCCESS) {
fclose(fp);
return (DST_R_INVALIDPRIVATEKEY);
}
@@ -537,10 +646,36 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
fprintf(fp, "\n");
}
+ /* Add the metadata tags */
+ if (major > 1 || (major == 1 && minor >= 3)) {
+ for (i = 0; i < NUMERIC_NTAGS; i++) {
+ result = dst_key_getnum(key, i, &value);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ fprintf(fp, "%s %u\n", numerictags[i], value);
+ }
+ for (i = 0; i < TIMING_NTAGS; i++) {
+ result = dst_key_gettime(key, i, &when);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ isc_buffer_init(&b, buffer, sizeof(buffer));
+ result = dns_time32_totext(when, &b);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ isc_buffer_usedregion(&b, &r);
+
+ fprintf(fp, "%s ", timetags[i]);
+ isc_util_fwrite(r.base, 1, r.length, fp);
+ fprintf(fp, "\n");
+ }
+ }
+
fflush(fp);
- iret = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
+ result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
fclose(fp);
- return (iret);
+ return (result);
}
/*! \file */
diff --git a/contrib/bind9/lib/dns/dst_parse.h b/contrib/bind9/lib/dns/dst_parse.h
index 11e2b33..d1034ce 100644
--- a/contrib/bind9/lib/dns/dst_parse.h
+++ b/contrib/bind9/lib/dns/dst_parse.h
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2010 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
@@ -29,7 +29,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_parse.h,v 1.11 2008-05-15 00:50:26 each Exp $ */
+/* $Id: dst_parse.h,v 1.17 2010-12-23 23:47:08 tbox Exp $ */
/*! \file */
#ifndef DST_DST_PARSE_H
@@ -39,11 +39,13 @@
#include <dst/dst.h>
-#define MAJOR_VERSION 1
-#define MINOR_VERSION 2
-
#define MAXFIELDSIZE 512
-#define MAXFIELDS 12
+
+/*
+ * Maximum number of fields in a private file is 18 (12 algorithm-
+ * specific fields for RSA, plus 6 generic fields).
+ */
+#define MAXFIELDS 12+6
#define TAG_SHIFT 4
#define TAG_ALG(tag) ((unsigned int)(tag) >> TAG_SHIFT)
@@ -76,6 +78,9 @@
#define TAG_DSA_PRIVATE ((DST_ALG_DSA << TAG_SHIFT) + 3)
#define TAG_DSA_PUBLIC ((DST_ALG_DSA << TAG_SHIFT) + 4)
+#define GOST_NTAGS 1
+#define TAG_GOST_PRIVASN1 ((DST_ALG_ECCGOST << TAG_SHIFT) + 0)
+
#define OLD_HMACMD5_NTAGS 1
#define HMACMD5_NTAGS 2
#define TAG_HMACMD5_KEY ((DST_ALG_HMACMD5 << TAG_SHIFT) + 0)
@@ -121,11 +126,11 @@ ISC_LANG_BEGINDECLS
void
dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx);
-int
+isc_result_t
dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
isc_mem_t *mctx, dst_private_t *priv);
-int
+isc_result_t
dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
const char *directory);
diff --git a/contrib/bind9/lib/dns/ecdb.c b/contrib/bind9/lib/dns/ecdb.c
new file mode 100644
index 0000000..d98a3eb
--- /dev/null
+++ b/contrib/bind9/lib/dns/ecdb.c
@@ -0,0 +1,810 @@
+/*
+ * Copyright (C) 2009-2011 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: ecdb.c,v 1.8 2011-01-14 00:51:43 tbox Exp $ */
+
+#include "config.h"
+
+#include <isc/result.h>
+#include <isc/util.h>
+#include <isc/mutex.h>
+#include <isc/mem.h>
+
+#include <dns/db.h>
+#include <dns/ecdb.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdataslab.h>
+
+#define ECDB_MAGIC ISC_MAGIC('E', 'C', 'D', 'B')
+#define VALID_ECDB(db) ((db) != NULL && \
+ (db)->common.impmagic == ECDB_MAGIC)
+
+#define ECDBNODE_MAGIC ISC_MAGIC('E', 'C', 'D', 'N')
+#define VALID_ECDBNODE(ecdbn) ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC)
+
+#if DNS_RDATASET_FIXED
+#error "Fixed rdataset isn't supported in this implementation"
+#endif
+
+/*%
+ * The 'ephemeral' cache DB (ecdb) implementation. An ecdb just provides
+ * temporary storage for ongoing name resolution with the common DB interfaces.
+ * It actually doesn't cache anything. The implementation expects any stored
+ * data is released within a short period, and does not care about the
+ * scalability in terms of the number of nodes.
+ */
+
+typedef struct dns_ecdb {
+ /* Unlocked */
+ dns_db_t common;
+ isc_mutex_t lock;
+
+ /* Locked */
+ unsigned int references;
+ ISC_LIST(struct dns_ecdbnode) nodes;
+} dns_ecdb_t;
+
+typedef struct dns_ecdbnode {
+ /* Unlocked */
+ unsigned int magic;
+ isc_mutex_t lock;
+ dns_ecdb_t *ecdb;
+ dns_name_t name;
+ ISC_LINK(struct dns_ecdbnode) link;
+
+ /* Locked */
+ ISC_LIST(struct rdatasetheader) rdatasets;
+ unsigned int references;
+} dns_ecdbnode_t;
+
+typedef struct rdatasetheader {
+ dns_rdatatype_t type;
+ dns_ttl_t ttl;
+ dns_trust_t trust;
+ dns_rdatatype_t covers;
+ unsigned int attributes;
+
+ ISC_LINK(struct rdatasetheader) link;
+} rdatasetheader_t;
+
+/* Copied from rbtdb.c */
+#define RDATASET_ATTR_NXDOMAIN 0x0010
+#define NXDOMAIN(header) \
+ (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
+
+static isc_result_t dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin,
+ dns_dbtype_t type,
+ dns_rdataclass_t rdclass,
+ unsigned int argc, char *argv[],
+ void *driverarg, dns_db_t **dbp);
+
+static void rdataset_disassociate(dns_rdataset_t *rdataset);
+static isc_result_t rdataset_first(dns_rdataset_t *rdataset);
+static isc_result_t rdataset_next(dns_rdataset_t *rdataset);
+static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
+static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
+static unsigned int rdataset_count(dns_rdataset_t *rdataset);
+static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
+
+static dns_rdatasetmethods_t rdataset_methods = {
+ rdataset_disassociate,
+ rdataset_first,
+ rdataset_next,
+ rdataset_current,
+ rdataset_clone,
+ rdataset_count,
+ NULL, /* addnoqname */
+ NULL, /* getnoqname */
+ NULL, /* addclosest */
+ NULL, /* getclosest */
+ NULL, /* getadditional */
+ NULL, /* setadditional */
+ NULL, /* putadditional */
+ rdataset_settrust, /* settrust */
+ NULL /* expire */
+};
+
+typedef struct ecdb_rdatasetiter {
+ dns_rdatasetiter_t common;
+ rdatasetheader_t *current;
+} ecdb_rdatasetiter_t;
+
+static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
+static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);
+static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);
+static void rdatasetiter_current(dns_rdatasetiter_t *iterator,
+ dns_rdataset_t *rdataset);
+
+static dns_rdatasetitermethods_t rdatasetiter_methods = {
+ rdatasetiter_destroy,
+ rdatasetiter_first,
+ rdatasetiter_next,
+ rdatasetiter_current
+};
+
+isc_result_t
+dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp) {
+ REQUIRE(mctx != NULL);
+ REQUIRE(dbimp != NULL && *dbimp == NULL);
+
+ return (dns_db_register("ecdb", dns_ecdb_create, NULL, mctx, dbimp));
+}
+
+void
+dns_ecdb_unregister(dns_dbimplementation_t **dbimp) {
+ REQUIRE(dbimp != NULL && *dbimp != NULL);
+
+ dns_db_unregister(dbimp);
+}
+
+/*%
+ * DB routines
+ */
+
+static void
+attach(dns_db_t *source, dns_db_t **targetp) {
+ dns_ecdb_t *ecdb = (dns_ecdb_t *)source;
+
+ REQUIRE(VALID_ECDB(ecdb));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ LOCK(&ecdb->lock);
+ ecdb->references++;
+ UNLOCK(&ecdb->lock);
+
+ *targetp = source;
+}
+
+static void
+destroy_ecdb(dns_ecdb_t **ecdbp) {
+ dns_ecdb_t *ecdb = *ecdbp;
+ isc_mem_t *mctx = ecdb->common.mctx;
+
+ if (dns_name_dynamic(&ecdb->common.origin))
+ dns_name_free(&ecdb->common.origin, mctx);
+
+ DESTROYLOCK(&ecdb->lock);
+
+ ecdb->common.impmagic = 0;
+ ecdb->common.magic = 0;
+
+ isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb));
+
+ *ecdbp = NULL;
+}
+
+static void
+detach(dns_db_t **dbp) {
+ dns_ecdb_t *ecdb;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(dbp != NULL);
+ ecdb = (dns_ecdb_t *)*dbp;
+ REQUIRE(VALID_ECDB(ecdb));
+
+ LOCK(&ecdb->lock);
+ ecdb->references--;
+ if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
+ need_destroy = ISC_TRUE;
+ UNLOCK(&ecdb->lock);
+
+ if (need_destroy)
+ destroy_ecdb(&ecdb);
+
+ *dbp = NULL;
+}
+
+static void
+attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
+ dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
+ dns_ecdbnode_t *node = (dns_ecdbnode_t *)source;
+
+ REQUIRE(VALID_ECDB(ecdb));
+ REQUIRE(VALID_ECDBNODE(node));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ LOCK(&node->lock);
+ INSIST(node->references > 0);
+ node->references++;
+ INSIST(node->references != 0); /* Catch overflow. */
+ UNLOCK(&node->lock);
+
+ *targetp = node;
+}
+
+static void
+destroynode(dns_ecdbnode_t *node) {
+ isc_mem_t *mctx;
+ dns_ecdb_t *ecdb = node->ecdb;
+ isc_boolean_t need_destroydb = ISC_FALSE;
+ rdatasetheader_t *header;
+
+ mctx = ecdb->common.mctx;
+
+ LOCK(&ecdb->lock);
+ ISC_LIST_UNLINK(ecdb->nodes, node, link);
+ if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
+ need_destroydb = ISC_TRUE;
+ UNLOCK(&ecdb->lock);
+
+ dns_name_free(&node->name, mctx);
+
+ while ((header = ISC_LIST_HEAD(node->rdatasets)) != NULL) {
+ unsigned int headersize;
+
+ ISC_LIST_UNLINK(node->rdatasets, header, link);
+ headersize =
+ dns_rdataslab_size((unsigned char *)header,
+ sizeof(*header));
+ isc_mem_put(mctx, header, headersize);
+ }
+
+ DESTROYLOCK(&node->lock);
+
+ node->magic = 0;
+ isc_mem_put(mctx, node, sizeof(*node));
+
+ if (need_destroydb)
+ destroy_ecdb(&ecdb);
+}
+
+static void
+detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
+ dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
+ dns_ecdbnode_t *node;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(VALID_ECDB(ecdb));
+ REQUIRE(nodep != NULL);
+ node = (dns_ecdbnode_t *)*nodep;
+ REQUIRE(VALID_ECDBNODE(node));
+
+ UNUSED(ecdb); /* in case REQUIRE() is empty */
+
+ LOCK(&node->lock);
+ INSIST(node->references > 0);
+ node->references--;
+ if (node->references == 0)
+ need_destroy = ISC_TRUE;
+ UNLOCK(&node->lock);
+
+ if (need_destroy)
+ destroynode(node);
+
+ *nodep = NULL;
+}
+
+static isc_result_t
+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, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
+
+ REQUIRE(VALID_ECDB(ecdb));
+
+ UNUSED(name);
+ UNUSED(version);
+ UNUSED(type);
+ UNUSED(options);
+ UNUSED(now);
+ UNUSED(nodep);
+ UNUSED(foundname);
+ UNUSED(rdataset);
+ UNUSED(sigrdataset);
+
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+findzonecut(dns_db_t *db, dns_name_t *name,
+ unsigned int options, isc_stdtime_t now,
+ dns_dbnode_t **nodep, dns_name_t *foundname,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
+
+ REQUIRE(VALID_ECDB(ecdb));
+
+ UNUSED(name);
+ UNUSED(options);
+ UNUSED(now);
+ UNUSED(nodep);
+ UNUSED(foundname);
+ UNUSED(rdataset);
+ UNUSED(sigrdataset);
+
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
+ dns_dbnode_t **nodep)
+{
+ dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
+ isc_mem_t *mctx;
+ dns_ecdbnode_t *node;
+ isc_result_t result;
+
+ REQUIRE(VALID_ECDB(ecdb));
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ UNUSED(name);
+
+ if (create != ISC_TRUE) {
+ /* an 'ephemeral' node is never reused. */
+ return (ISC_R_NOTFOUND);
+ }
+
+ mctx = ecdb->common.mctx;
+ node = isc_mem_get(mctx, sizeof(*node));
+ if (node == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&node->lock);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_mutex_init() failed: %s",
+ isc_result_totext(result));
+ isc_mem_put(mctx, node, sizeof(*node));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ dns_name_init(&node->name, NULL);
+ result = dns_name_dup(name, mctx, &node->name);
+ if (result != ISC_R_SUCCESS) {
+ DESTROYLOCK(&node->lock);
+ isc_mem_put(mctx, node, sizeof(*node));
+ return (result);
+ }
+ node->ecdb= ecdb;
+ node->references = 1;
+ ISC_LIST_INIT(node->rdatasets);
+
+ ISC_LINK_INIT(node, link);
+
+ LOCK(&ecdb->lock);
+ ISC_LIST_APPEND(ecdb->nodes, node, link);
+ UNLOCK(&ecdb->lock);
+
+ node->magic = ECDBNODE_MAGIC;
+
+ *nodep = node;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node,
+ rdatasetheader_t *header, dns_rdataset_t *rdataset)
+{
+ unsigned char *raw;
+
+ /*
+ * Caller must be holding the node lock.
+ */
+
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = ecdb->common.rdclass;
+ rdataset->type = header->type;
+ rdataset->covers = header->covers;
+ rdataset->ttl = header->ttl;
+ rdataset->trust = header->trust;
+ if (NXDOMAIN(header))
+ rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
+
+ rdataset->private1 = ecdb;
+ rdataset->private2 = node;
+ raw = (unsigned char *)header + sizeof(*header);
+ rdataset->private3 = raw;
+ rdataset->count = 0;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+
+ INSIST(node->references > 0);
+ node->references++;
+}
+
+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,
+ dns_rdataset_t *addedrdataset)
+{
+ dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
+ isc_region_t r;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_mem_t *mctx;
+ dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
+ rdatasetheader_t *header;
+
+ REQUIRE(VALID_ECDB(ecdb));
+ REQUIRE(VALID_ECDBNODE(ecdbnode));
+
+ UNUSED(version);
+ UNUSED(now);
+ UNUSED(options);
+
+ mctx = ecdb->common.mctx;
+
+ LOCK(&ecdbnode->lock);
+
+ /*
+ * Sanity check: this implementation does not allow overriding an
+ * existing rdataset of the same type.
+ */
+ for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL;
+ header = ISC_LIST_NEXT(header, link)) {
+ INSIST(header->type != rdataset->type ||
+ header->covers != rdataset->covers);
+ }
+
+ result = dns_rdataslab_fromrdataset(rdataset, mctx,
+ &r, sizeof(rdatasetheader_t));
+ if (result != ISC_R_SUCCESS)
+ goto unlock;
+
+ header = (rdatasetheader_t *)r.base;
+ header->type = rdataset->type;
+ header->ttl = rdataset->ttl;
+ header->trust = rdataset->trust;
+ header->covers = rdataset->covers;
+ header->attributes = 0;
+ if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+ header->attributes |= RDATASET_ATTR_NXDOMAIN;
+ ISC_LINK_INIT(header, link);
+ ISC_LIST_APPEND(ecdbnode->rdatasets, header, link);
+
+ if (addedrdataset == NULL)
+ goto unlock;
+
+ bind_rdataset(ecdb, ecdbnode, header, addedrdataset);
+
+ unlock:
+ UNLOCK(&ecdbnode->lock);
+
+ return (result);
+}
+
+static isc_result_t
+deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers)
+{
+ UNUSED(db);
+ UNUSED(node);
+ UNUSED(version);
+ UNUSED(type);
+ UNUSED(covers);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+createiterator(dns_db_t *db, unsigned int options,
+ dns_dbiterator_t **iteratorp)
+{
+ UNUSED(db);
+ UNUSED(options);
+ UNUSED(iteratorp);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
+{
+ dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
+ dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
+ isc_mem_t *mctx;
+ ecdb_rdatasetiter_t *iterator;
+
+ REQUIRE(VALID_ECDB(ecdb));
+ REQUIRE(VALID_ECDBNODE(ecdbnode));
+
+ mctx = ecdb->common.mctx;
+
+ iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t));
+ if (iterator == NULL)
+ return (ISC_R_NOMEMORY);
+
+ iterator->common.magic = DNS_RDATASETITER_MAGIC;
+ iterator->common.methods = &rdatasetiter_methods;
+ iterator->common.db = db;
+ iterator->common.node = NULL;
+ attachnode(db, node, &iterator->common.node);
+ iterator->common.version = version;
+ iterator->common.now = now;
+
+ *iteratorp = (dns_rdatasetiter_t *)iterator;
+
+ return (ISC_R_SUCCESS);
+}
+
+static dns_dbmethods_t ecdb_methods = {
+ attach,
+ detach,
+ NULL, /* beginload */
+ NULL, /* endload */
+ NULL, /* dump */
+ NULL, /* currentversion */
+ NULL, /* newversion */
+ NULL, /* attachversion */
+ NULL, /* closeversion */
+ findnode,
+ find,
+ findzonecut,
+ attachnode,
+ detachnode,
+ NULL, /* expirenode */
+ NULL, /* printnode */
+ createiterator, /* createiterator */
+ NULL, /* findrdataset */
+ allrdatasets,
+ addrdataset,
+ NULL, /* subtractrdataset */
+ deleterdataset,
+ NULL, /* issecure */
+ NULL, /* nodecount */
+ NULL, /* ispersistent */
+ NULL, /* overmem */
+ NULL, /* settask */
+ NULL, /* getoriginnode */
+ NULL, /* transfernode */
+ NULL, /* getnsec3parameters */
+ NULL, /* findnsec3node */
+ NULL, /* setsigningtime */
+ NULL, /* getsigningtime */
+ NULL, /* resigned */
+ NULL, /* isdnssec */
+ NULL, /* getrrsetstats */
+ NULL, /* rpz_enabled */
+ NULL /* rpz_findips */
+};
+
+static isc_result_t
+dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
+ dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+ void *driverarg, dns_db_t **dbp)
+{
+ dns_ecdb_t *ecdb;
+ isc_result_t result;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(origin == dns_rootname);
+ REQUIRE(type == dns_dbtype_cache);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(driverarg);
+
+ ecdb = isc_mem_get(mctx, sizeof(*ecdb));
+ if (ecdb == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ecdb->common.attributes = DNS_DBATTR_CACHE;
+ ecdb->common.rdclass = rdclass;
+ ecdb->common.methods = &ecdb_methods;
+ dns_name_init(&ecdb->common.origin, NULL);
+ result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, ecdb, sizeof(*ecdb));
+ return (result);
+ }
+
+ result = isc_mutex_init(&ecdb->lock);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_mutex_init() failed: %s",
+ isc_result_totext(result));
+ if (dns_name_dynamic(&ecdb->common.origin))
+ dns_name_free(&ecdb->common.origin, mctx);
+ isc_mem_put(mctx, ecdb, sizeof(*ecdb));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ ecdb->references = 1;
+ ISC_LIST_INIT(ecdb->nodes);
+
+ ecdb->common.mctx = NULL;
+ isc_mem_attach(mctx, &ecdb->common.mctx);
+ ecdb->common.impmagic = ECDB_MAGIC;
+ ecdb->common.magic = DNS_DB_MAGIC;
+
+ *dbp = (dns_db_t *)ecdb;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Rdataset Methods
+ */
+
+static void
+rdataset_disassociate(dns_rdataset_t *rdataset) {
+ dns_db_t *db = rdataset->private1;
+ dns_dbnode_t *node = rdataset->private2;
+
+ dns_db_detachnode(db, &node);
+}
+
+static isc_result_t
+rdataset_first(dns_rdataset_t *rdataset) {
+ unsigned char *raw = rdataset->private3;
+ unsigned int count;
+
+ count = raw[0] * 256 + raw[1];
+ if (count == 0) {
+ rdataset->private5 = NULL;
+ return (ISC_R_NOMORE);
+ }
+ raw += 2;
+ /*
+ * The privateuint4 field is the number of rdata beyond the cursor
+ * position, so we decrement the total count by one before storing
+ * it.
+ */
+ count--;
+ rdataset->privateuint4 = count;
+ rdataset->private5 = raw;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rdataset_next(dns_rdataset_t *rdataset) {
+ unsigned int count;
+ unsigned int length;
+ unsigned char *raw;
+
+ count = rdataset->privateuint4;
+ if (count == 0)
+ return (ISC_R_NOMORE);
+ count--;
+ rdataset->privateuint4 = count;
+ raw = rdataset->private5;
+ length = raw[0] * 256 + raw[1];
+ raw += length + 2;
+ rdataset->private5 = raw;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
+ unsigned char *raw = rdataset->private5;
+ isc_region_t r;
+ unsigned int length;
+ unsigned int flags = 0;
+
+ REQUIRE(raw != NULL);
+
+ length = raw[0] * 256 + raw[1];
+ raw += 2;
+ if (rdataset->type == dns_rdatatype_rrsig) {
+ if (*raw & DNS_RDATASLAB_OFFLINE)
+ flags |= DNS_RDATA_OFFLINE;
+ length--;
+ raw++;
+ }
+ r.length = length;
+ r.base = raw;
+ dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
+ rdata->flags |= flags;
+}
+
+static void
+rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+ dns_db_t *db = source->private1;
+ dns_dbnode_t *node = source->private2;
+ dns_dbnode_t *cloned_node = NULL;
+
+ attachnode(db, node, &cloned_node);
+ *target = *source;
+
+ /*
+ * Reset iterator state.
+ */
+ target->privateuint4 = 0;
+ target->private5 = NULL;
+}
+
+static unsigned int
+rdataset_count(dns_rdataset_t *rdataset) {
+ unsigned char *raw = rdataset->private3;
+ unsigned int count;
+
+ count = raw[0] * 256 + raw[1];
+
+ return (count);
+}
+
+static void
+rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
+ rdatasetheader_t *header = rdataset->private3;
+
+ header--;
+ header->trust = rdataset->trust = trust;
+}
+
+/*
+ * Rdataset Iterator Methods
+ */
+
+static void
+rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
+ ecdb_rdatasetiter_t *ecdbiterator;
+ isc_mem_t *mctx;
+
+ REQUIRE(iteratorp != NULL);
+ ecdbiterator = (ecdb_rdatasetiter_t *)*iteratorp;
+ REQUIRE(DNS_RDATASETITER_VALID(&ecdbiterator->common));
+
+ mctx = ecdbiterator->common.db->mctx;
+
+ ecdbiterator->common.magic = 0;
+
+ dns_db_detachnode(ecdbiterator->common.db, &ecdbiterator->common.node);
+ isc_mem_put(mctx, ecdbiterator, sizeof(ecdb_rdatasetiter_t));
+
+ *iteratorp = NULL;
+}
+
+static isc_result_t
+rdatasetiter_first(dns_rdatasetiter_t *iterator) {
+ ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
+ dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node;
+
+ REQUIRE(DNS_RDATASETITER_VALID(iterator));
+
+ if (ISC_LIST_EMPTY(ecdbnode->rdatasets))
+ return (ISC_R_NOMORE);
+ ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rdatasetiter_next(dns_rdatasetiter_t *iterator) {
+ ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
+
+ REQUIRE(DNS_RDATASETITER_VALID(iterator));
+
+ ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link);
+ if (ecdbiterator->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
+ ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
+ dns_ecdb_t *ecdb;
+
+ ecdb = (dns_ecdb_t *)iterator->db;
+ REQUIRE(VALID_ECDB(ecdb));
+
+ bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset);
+}
diff --git a/contrib/bind9/lib/dns/forward.c b/contrib/bind9/lib/dns/forward.c
index 1406b46..1f9c41a 100644
--- a/contrib/bind9/lib/dns/forward.c
+++ b/contrib/bind9/lib/dns/forward.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: forward.c,v 1.12 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: forward.c,v 1.14 2009-09-02 23:48:02 tbox Exp $ */
/*! \file */
@@ -133,11 +133,27 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
}
isc_result_t
+dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name) {
+ isc_result_t result;
+
+ REQUIRE(VALID_FWDTABLE(fwdtable));
+
+ RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
+ result = dns_rbt_deletename(fwdtable->table, name, ISC_FALSE);
+ RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
+
+ if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+
+ return (result);
+}
+
+isc_result_t
dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name,
dns_forwarders_t **forwardersp)
{
return (dns_fwdtable_find2(fwdtable, name, NULL, forwardersp));
-}
+}
isc_result_t
dns_fwdtable_find2(dns_fwdtable_t *fwdtable, dns_name_t *name,
diff --git a/contrib/bind9/lib/dns/gen-unix.h b/contrib/bind9/lib/dns/gen-unix.h
index 91cd4d5..47a343d 100644
--- a/contrib/bind9/lib/dns/gen-unix.h
+++ b/contrib/bind9/lib/dns/gen-unix.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gen-unix.h,v 1.19.332.2 2009-01-18 23:47:35 tbox Exp $ */
+/* $Id: gen-unix.h,v 1.21 2009-01-17 23:47:42 tbox Exp $ */
/*! \file
* \brief
diff --git a/contrib/bind9/lib/dns/gen.c b/contrib/bind9/lib/dns/gen.c
index 6f8ce7d..f1d46ea 100644
--- a/contrib/bind9/lib/dns/gen.c
+++ b/contrib/bind9/lib/dns/gen.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) 1998-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: gen.c,v 1.83 2008-09-25 04:02:38 tbox Exp $ */
+/* $Id: gen.c,v 1.85 2009-12-04 22:06:37 tbox Exp $ */
/*! \file */
@@ -631,6 +631,8 @@ main(int argc, char **argv) {
TOWIRETYPE, TOWIRECLASS, TOWIREDEF);
doswitch("COMPARESWITCH", "compare", COMPAREARGS,
COMPARETYPE, COMPARECLASS, COMPAREDEF);
+ doswitch("CASECOMPARESWITCH", "casecompare", COMPAREARGS,
+ COMPARETYPE, COMPARECLASS, COMPAREDEF);
doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS,
FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF);
doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS,
diff --git a/contrib/bind9/lib/dns/gssapi_link.c b/contrib/bind9/lib/dns/gssapi_link.c
index a7af67f..e14d0eb 100644
--- a/contrib/bind9/lib/dns/gssapi_link.c
+++ b/contrib/bind9/lib/dns/gssapi_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,13 +16,14 @@
*/
/*
- * $Id: gssapi_link.c,v 1.12 2008-11-11 03:55:01 marka Exp $
+ * $Id: gssapi_link.c,v 1.16 2011-01-11 23:47:13 tbox Exp $
*/
#include <config.h>
#ifdef GSSAPI
+#include <isc/base64.h>
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/string.h>
@@ -44,6 +45,12 @@
(gb).value = (r).base; \
} while (0)
+#define GBUFFER_TO_REGION(gb, r) \
+ do { \
+ (r).length = (gb).length; \
+ (r).base = (gb).value; \
+ } while (0)
+
struct dst_gssapi_signverifyctx {
isc_buffer_t *buffer;
@@ -254,9 +261,10 @@ gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) {
}
static isc_result_t
-gssapi_generate(dst_key_t *key, int unused) {
+gssapi_generate(dst_key_t *key, int unused, void (*callback)(int)) {
UNUSED(key);
UNUSED(unused);
+ UNUSED(callback);
/* No idea */
return (ISC_R_FAILURE);
@@ -275,6 +283,79 @@ gssapi_destroy(dst_key_t *key) {
key->keydata.gssctx = NULL;
}
+static isc_result_t
+gssapi_restore(dst_key_t *key, const char *keystr) {
+ OM_uint32 major, minor;
+ size_t len;
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ gss_buffer_desc gssbuffer;
+ isc_result_t result;
+
+ len = strlen(keystr);
+ if ((len % 4) != 0)
+ return (ISC_R_BADBASE64);
+
+ len = (len / 4) * 3;
+
+ result = isc_buffer_allocate(key->mctx, &b, len);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = isc_base64_decodestring(keystr, b);
+ if (result != ISC_R_SUCCESS) {
+ isc_buffer_free(&b);
+ return (result);
+ }
+
+ isc_buffer_remainingregion(b, &r);
+ REGION_TO_GBUFFER(r, gssbuffer);
+ major = gss_import_sec_context(&minor, &gssbuffer,
+ &key->keydata.gssctx);
+ if (major != GSS_S_COMPLETE) {
+ isc_buffer_free(&b);
+ return (ISC_R_FAILURE);
+ }
+
+ isc_buffer_free(&b);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+gssapi_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
+ OM_uint32 major, minor;
+ gss_buffer_desc gssbuffer;
+ size_t len;
+ char *buf;
+ isc_buffer_t b;
+ isc_region_t r;
+ isc_result_t result;
+
+ major = gss_export_sec_context(&minor, &key->keydata.gssctx,
+ &gssbuffer);
+ if (major != GSS_S_COMPLETE) {
+ fprintf(stderr, "gss_export_sec_context -> %d, %d\n",
+ major, minor);
+ return (ISC_R_FAILURE);
+ }
+ if (gssbuffer.length == 0)
+ return (ISC_R_FAILURE);
+ len = ((gssbuffer.length + 2)/3) * 4;
+ buf = isc_mem_get(mctx, len);
+ if (buf == NULL) {
+ gss_release_buffer(&minor, &gssbuffer);
+ return (ISC_R_NOMEMORY);
+ }
+ isc_buffer_init(&b, buf, len);
+ GBUFFER_TO_REGION(gssbuffer, r);
+ result = isc_base64_totext(&r, 0, "", &b);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ gss_release_buffer(&minor, &gssbuffer);
+ *buffer = buf;
+ *length = len;
+ return (ISC_R_SUCCESS);
+}
+
static dst_func_t gssapi_functions = {
gssapi_create_signverify_ctx,
gssapi_destroy_signverify_ctx,
@@ -292,7 +373,9 @@ static dst_func_t gssapi_functions = {
NULL, /*%< tofile */
NULL, /*%< parse */
NULL, /*%< cleanup */
- NULL /*%< fromlabel */
+ NULL, /*%< fromlabel */
+ gssapi_dump,
+ gssapi_restore,
};
isc_result_t
diff --git a/contrib/bind9/lib/dns/gssapictx.c b/contrib/bind9/lib/dns/gssapictx.c
index f365a64..707745c 100644
--- a/contrib/bind9/lib/dns/gssapictx.c
+++ b/contrib/bind9/lib/dns/gssapictx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,16 +15,18 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gssapictx.c,v 1.12.118.5 2010-12-22 02:37:55 marka Exp $ */
+/* $Id: gssapictx.c,v 1.26 2011-01-10 03:49:49 marka Exp $ */
#include <config.h>
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <isc/buffer.h>
#include <isc/dir.h>
#include <isc/entropy.h>
+#include <isc/file.h>
#include <isc/lex.h>
#include <isc/mem.h>
#include <isc/once.h>
@@ -201,9 +203,12 @@ log_cred(const gss_cred_id_t cred) {
* - tkey-gssapi-credential doesn't start with DNS/
* - the default realm in /etc/krb5.conf and the
* tkey-gssapi-credential bind config option don't match
+ *
+ * Note that if tkey-gssapi-keytab is set then these configure checks
+ * are not performed, and runtime errors from gssapi are used instead
*/
static void
-dst_gssapi_check_config(const char *gss_name) {
+check_config(const char *gss_name) {
const char *p;
krb5_context krb5_ctx;
char *krb5_realm = NULL;
@@ -263,7 +268,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
* 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
+ * named.conf. Unfortunately, this creates a circular
* dependency due to DNS-based realm lookup in at least one
* GSSAPI implementation (Heimdal). Oh well.
*/
@@ -273,7 +278,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
gret = gss_import_name(&minor, &gnamebuf,
GSS_C_NO_OID, &gname);
if (gret != GSS_S_COMPLETE) {
- dst_gssapi_check_config((char *)array);
+ check_config((char *)array);
gss_log(3, "failed gss_import_name: %s",
gss_error_tostring(gret, minor, buf,
@@ -306,7 +311,7 @@ dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
initiate ? "initiate" : "accept",
(char *)gnamebuf.value,
gss_error_tostring(gret, minor, buf, sizeof(buf)));
- dst_gssapi_check_config((char *)array);
+ check_config((char *)array);
return (ISC_R_FAILURE);
}
@@ -361,7 +366,7 @@ dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
rname++;
/*
- * Find the host portion of the signer's name. We do this by
+ * 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"
*
@@ -440,7 +445,7 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
return (isc_boolean_false);
/*
- * Find the host portion of the signer's name. Zero out the $ so
+ * 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.
*
@@ -454,7 +459,7 @@ dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
/*
* 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.
+ * the string. The rest of the name has to match the realm.
*/
if (name != NULL) {
nname = strchr(nbuf, '.');
@@ -510,9 +515,34 @@ dst_gssapi_releasecred(gss_cred_id_t *cred) {
#endif
}
+#ifdef GSSAPI
+/*
+ * Format a gssapi error message info into a char ** on the given memory
+ * context. This is used to return gssapi error messages back up the
+ * call chain for reporting to the user.
+ */
+static void
+gss_err_message(isc_mem_t *mctx, isc_uint32_t major, isc_uint32_t minor,
+ char **err_message)
+{
+ char buf[1024];
+ char *estr;
+
+ if (err_message == NULL || mctx == NULL) {
+ /* the caller doesn't want any error messages */
+ return;
+ }
+
+ estr = gss_error_tostring(major, minor, buf, sizeof(buf));
+ if (estr)
+ (*err_message) = isc_mem_strdup(mctx, estr);
+}
+#endif
+
isc_result_t
dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
- isc_buffer_t *outtoken, gss_ctx_id_t *gssctx)
+ isc_buffer_t *outtoken, gss_ctx_id_t *gssctx,
+ isc_mem_t *mctx, char **err_message)
{
#ifdef GSSAPI
isc_region_t r;
@@ -523,10 +553,10 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
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);
+ REQUIRE(mctx != NULL);
isc_buffer_init(&namebuf, array, sizeof(array));
name_to_gbuffer(name, &namebuf, &gnamebuf);
@@ -534,6 +564,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
/* Get the name as a GSS name */
gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
if (gret != GSS_S_COMPLETE) {
+ gss_err_message(mctx, gret, minor, err_message);
result = ISC_R_FAILURE;
goto out;
}
@@ -550,8 +581,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
* Note that we don't set GSS_C_SEQUENCE_FLAG as Windows DNS
* servers don't like it.
*/
- flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG |
- GSS_C_INTEG_FLAG;
+ flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG;
gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx,
gname, GSS_SPNEGO_MECHANISM, flags,
@@ -559,9 +589,9 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
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)));
+ gss_err_message(mctx, gret, minor, err_message);
+ gss_log(3, "Failure initiating security context: %s",
+ *err_message);
result = ISC_R_FAILURE;
goto out;
}
@@ -593,6 +623,8 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
UNUSED(intoken);
UNUSED(outtoken);
UNUSED(gssctx);
+ UNUSED(mctx);
+ UNUSED(err_message);
return (ISC_R_NOTIMPLEMENTED);
#endif
@@ -600,6 +632,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
isc_result_t
dst_gssapi_acceptctx(gss_cred_id_t cred,
+ const char *gssapi_keytab,
isc_region_t *intoken, isc_buffer_t **outtoken,
gss_ctx_id_t *ctxout, dns_name_t *principal,
isc_mem_t *mctx)
@@ -626,6 +659,34 @@ dst_gssapi_acceptctx(gss_cred_id_t cred,
else
context = *ctxout;
+ if (gssapi_keytab != NULL) {
+#ifdef ISC_PLATFORM_GSSAPI_KRB5_HEADER
+ gret = gsskrb5_register_acceptor_identity(gssapi_keytab);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed "
+ "gsskrb5_register_acceptor_identity(%s): %s",
+ gssapi_keytab,
+ gss_error_tostring(gret, minor,
+ buf, sizeof(buf)));
+ return (DNS_R_INVALIDTKEY);
+ }
+#else
+ /*
+ * Minimize memory leakage by only setting KRB5_KTNAME
+ * if it needs to change.
+ */
+ const char *old = getenv("KRB5_KTNAME");
+ if (old == NULL || strcmp(old, gssapi_keytab) != 0) {
+ char *kt = malloc(strlen(gssapi_keytab) + 13);
+ if (kt == NULL)
+ return (ISC_R_NOMEMORY);
+ sprintf(kt, "KRB5_KTNAME=%s", gssapi_keytab);
+ if (putenv(kt) != 0)
+ return (ISC_R_NOMEMORY);
+ }
+#endif
+ }
+
gret = gss_accept_sec_context(&minor, &context, cred, &gintoken,
GSS_C_NO_CHANNEL_BINDINGS, &gname,
NULL, &gouttoken, NULL, NULL, NULL);
@@ -692,7 +753,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred,
isc_buffer_add(&namebuf, r.length);
RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname,
- ISC_FALSE, NULL));
+ 0, NULL));
if (gnamebuf.length != 0) {
gret = gss_release_buffer(&minor, &gnamebuf);
@@ -717,6 +778,7 @@ dst_gssapi_acceptctx(gss_cred_id_t cred,
return (result);
#else
UNUSED(cred);
+ UNUSED(gssapi_keytab);
UNUSED(intoken);
UNUSED(outtoken);
UNUSED(ctxout);
diff --git a/contrib/bind9/lib/dns/hmac_link.c b/contrib/bind9/lib/dns/hmac_link.c
index 5d6dce7..ecc4089 100644
--- a/contrib/bind9/lib/dns/hmac_link.c
+++ b/contrib/bind9/lib/dns/hmac_link.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2011 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
@@ -31,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: hmac_link.c,v 1.11 2008-04-01 23:47:10 tbox Exp $
+ * $Id: hmac_link.c,v 1.19 2011-01-11 23:47:13 tbox Exp $
*/
#include <config.h>
@@ -50,14 +50,10 @@
#include "dst_internal.h"
#include "dst_parse.h"
-#define HMAC_LEN 64
-#define HMAC_IPAD 0x36
-#define HMAC_OPAD 0x5c
-
static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
struct dst_hmacmd5_key {
- unsigned char key[HMAC_LEN];
+ unsigned char key[ISC_MD5_BLOCK_LENGTH];
};
static isc_result_t
@@ -79,7 +75,7 @@ hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
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);
+ isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
return (ISC_R_SUCCESS);
}
@@ -142,26 +138,28 @@ hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, HMAC_LEN) == 0)
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH) == 0)
return (ISC_TRUE);
else
return (ISC_FALSE);
}
static isc_result_t
-hmacmd5_generate(dst_key_t *key, int pseudorandom_ok) {
+hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
isc_buffer_t b;
isc_result_t ret;
- int bytes;
- unsigned char data[HMAC_LEN];
+ unsigned int bytes;
+ unsigned char data[ISC_SHA1_BLOCK_LENGTH];
+
+ UNUSED(callback);
bytes = (key->key_size + 7) / 8;
- if (bytes > HMAC_LEN) {
- bytes = HMAC_LEN;
- key->key_size = HMAC_LEN * 8;
+ if (bytes > ISC_SHA1_BLOCK_LENGTH) {
+ bytes = ISC_SHA1_BLOCK_LENGTH;
+ key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
}
- memset(data, 0, HMAC_LEN);
+ memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
if (ret != ISC_R_SUCCESS)
@@ -170,7 +168,7 @@ hmacmd5_generate(dst_key_t *key, int pseudorandom_ok) {
isc_buffer_init(&b, data, bytes);
isc_buffer_add(&b, bytes);
ret = hmacmd5_fromdns(key, &b);
- memset(data, 0, HMAC_LEN);
+ memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
return (ret);
}
@@ -184,6 +182,7 @@ hmacmd5_isprivate(const dst_key_t *key) {
static void
hmacmd5_destroy(dst_key_t *key) {
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;
@@ -223,7 +222,7 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
memset(hkey->key, 0, sizeof(hkey->key));
- if (r.length > HMAC_LEN) {
+ if (r.length > ISC_SHA1_BLOCK_LENGTH) {
isc_md5_init(&md5ctx);
isc_md5_update(&md5ctx, r.base, r.length);
isc_md5_final(&md5ctx, hkey->key);
@@ -268,15 +267,17 @@ hmacmd5_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer) {
+hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t result, tresult;
isc_buffer_t b;
isc_mem_t *mctx = key->mctx;
unsigned int i;
+ UNUSED(pub);
/* read private key file */
- result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx, &priv);
+ result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx,
+ &priv);
if (result != ISC_R_SUCCESS)
return (result);
@@ -324,6 +325,8 @@ static dst_func_t hmacmd5_functions = {
hmacmd5_parse,
NULL, /*%< cleanup */
NULL, /*%< fromlabel */
+ NULL, /*%< dump */
+ NULL, /*%< restore */
};
isc_result_t
@@ -337,7 +340,7 @@ dst__hmacmd5_init(dst_func_t **funcp) {
static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
struct dst_hmacsha1_key {
- unsigned char key[ISC_SHA1_DIGESTLENGTH];
+ unsigned char key[ISC_SHA1_BLOCK_LENGTH];
};
static isc_result_t
@@ -348,7 +351,7 @@ hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
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);
+ isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
return (ISC_R_SUCCESS);
}
@@ -411,26 +414,28 @@ hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_DIGESTLENGTH) == 0)
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH) == 0)
return (ISC_TRUE);
else
return (ISC_FALSE);
}
static isc_result_t
-hmacsha1_generate(dst_key_t *key, int pseudorandom_ok) {
+hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
isc_buffer_t b;
isc_result_t ret;
- int bytes;
- unsigned char data[HMAC_LEN];
+ unsigned int bytes;
+ unsigned char data[ISC_SHA1_BLOCK_LENGTH];
+
+ UNUSED(callback);
bytes = (key->key_size + 7) / 8;
- if (bytes > HMAC_LEN) {
- bytes = HMAC_LEN;
- key->key_size = HMAC_LEN * 8;
+ if (bytes > ISC_SHA1_BLOCK_LENGTH) {
+ bytes = ISC_SHA1_BLOCK_LENGTH;
+ key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
}
- memset(data, 0, HMAC_LEN);
+ memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
if (ret != ISC_R_SUCCESS)
@@ -439,7 +444,7 @@ hmacsha1_generate(dst_key_t *key, int pseudorandom_ok) {
isc_buffer_init(&b, data, bytes);
isc_buffer_add(&b, bytes);
ret = hmacsha1_fromdns(key, &b);
- memset(data, 0, ISC_SHA1_DIGESTLENGTH);
+ memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
return (ret);
}
@@ -453,6 +458,7 @@ hmacsha1_isprivate(const dst_key_t *key) {
static void
hmacsha1_destroy(dst_key_t *key) {
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;
@@ -492,7 +498,7 @@ hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
memset(hkey->key, 0, sizeof(hkey->key));
- if (r.length > ISC_SHA1_DIGESTLENGTH) {
+ if (r.length > ISC_SHA1_BLOCK_LENGTH) {
isc_sha1_init(&sha1ctx);
isc_sha1_update(&sha1ctx, r.base, r.length);
isc_sha1_final(&sha1ctx, hkey->key);
@@ -537,13 +543,14 @@ hmacsha1_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer) {
+hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t result, tresult;
isc_buffer_t b;
isc_mem_t *mctx = key->mctx;
unsigned int i;
+ UNUSED(pub);
/* read private key file */
result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
&priv);
@@ -594,6 +601,8 @@ static dst_func_t hmacsha1_functions = {
hmacsha1_parse,
NULL, /* cleanup */
NULL, /* fromlabel */
+ NULL, /* dump */
+ NULL, /* restore */
};
isc_result_t
@@ -607,7 +616,7 @@ dst__hmacsha1_init(dst_func_t **funcp) {
static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
struct dst_hmacsha224_key {
- unsigned char key[ISC_SHA224_DIGESTLENGTH];
+ unsigned char key[ISC_SHA224_BLOCK_LENGTH];
};
static isc_result_t
@@ -618,7 +627,7 @@ hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
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);
+ isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
return (ISC_R_SUCCESS);
}
@@ -681,26 +690,30 @@ hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_DIGESTLENGTH) == 0)
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH) == 0)
return (ISC_TRUE);
else
return (ISC_FALSE);
}
static isc_result_t
-hmacsha224_generate(dst_key_t *key, int pseudorandom_ok) {
+hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
+ void (*callback)(int))
+{
isc_buffer_t b;
isc_result_t ret;
- int bytes;
- unsigned char data[HMAC_LEN];
+ unsigned int bytes;
+ unsigned char data[ISC_SHA224_BLOCK_LENGTH];
+
+ UNUSED(callback);
bytes = (key->key_size + 7) / 8;
- if (bytes > HMAC_LEN) {
- bytes = HMAC_LEN;
- key->key_size = HMAC_LEN * 8;
+ if (bytes > ISC_SHA224_BLOCK_LENGTH) {
+ bytes = ISC_SHA224_BLOCK_LENGTH;
+ key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
}
- memset(data, 0, HMAC_LEN);
+ memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
if (ret != ISC_R_SUCCESS)
@@ -709,7 +722,7 @@ hmacsha224_generate(dst_key_t *key, int pseudorandom_ok) {
isc_buffer_init(&b, data, bytes);
isc_buffer_add(&b, bytes);
ret = hmacsha224_fromdns(key, &b);
- memset(data, 0, ISC_SHA224_DIGESTLENGTH);
+ memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
return (ret);
}
@@ -723,6 +736,7 @@ hmacsha224_isprivate(const dst_key_t *key) {
static void
hmacsha224_destroy(dst_key_t *key) {
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;
@@ -762,7 +776,7 @@ hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
memset(hkey->key, 0, sizeof(hkey->key));
- if (r.length > ISC_SHA224_DIGESTLENGTH) {
+ if (r.length > ISC_SHA224_BLOCK_LENGTH) {
isc_sha224_init(&sha224ctx);
isc_sha224_update(&sha224ctx, r.base, r.length);
isc_sha224_final(hkey->key, &sha224ctx);
@@ -807,13 +821,14 @@ hmacsha224_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer) {
+hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t result, tresult;
isc_buffer_t b;
isc_mem_t *mctx = key->mctx;
unsigned int i;
+ UNUSED(pub);
/* read private key file */
result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
&priv);
@@ -864,6 +879,8 @@ static dst_func_t hmacsha224_functions = {
hmacsha224_parse,
NULL, /* cleanup */
NULL, /* fromlabel */
+ NULL, /* dump */
+ NULL, /* restore */
};
isc_result_t
@@ -877,7 +894,7 @@ dst__hmacsha224_init(dst_func_t **funcp) {
static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
struct dst_hmacsha256_key {
- unsigned char key[ISC_SHA256_DIGESTLENGTH];
+ unsigned char key[ISC_SHA256_BLOCK_LENGTH];
};
static isc_result_t
@@ -888,7 +905,7 @@ hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
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);
+ isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
return (ISC_R_SUCCESS);
}
@@ -951,26 +968,30 @@ hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_DIGESTLENGTH) == 0)
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH) == 0)
return (ISC_TRUE);
else
return (ISC_FALSE);
}
static isc_result_t
-hmacsha256_generate(dst_key_t *key, int pseudorandom_ok) {
+hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
+ void (*callback)(int))
+{
isc_buffer_t b;
isc_result_t ret;
- int bytes;
- unsigned char data[HMAC_LEN];
+ unsigned int bytes;
+ unsigned char data[ISC_SHA256_BLOCK_LENGTH];
+
+ UNUSED(callback);
bytes = (key->key_size + 7) / 8;
- if (bytes > HMAC_LEN) {
- bytes = HMAC_LEN;
- key->key_size = HMAC_LEN * 8;
+ if (bytes > ISC_SHA256_BLOCK_LENGTH) {
+ bytes = ISC_SHA256_BLOCK_LENGTH;
+ key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
}
- memset(data, 0, HMAC_LEN);
+ memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
if (ret != ISC_R_SUCCESS)
@@ -979,7 +1000,7 @@ hmacsha256_generate(dst_key_t *key, int pseudorandom_ok) {
isc_buffer_init(&b, data, bytes);
isc_buffer_add(&b, bytes);
ret = hmacsha256_fromdns(key, &b);
- memset(data, 0, ISC_SHA256_DIGESTLENGTH);
+ memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
return (ret);
}
@@ -993,6 +1014,7 @@ hmacsha256_isprivate(const dst_key_t *key) {
static void
hmacsha256_destroy(dst_key_t *key) {
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;
@@ -1032,7 +1054,7 @@ hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
memset(hkey->key, 0, sizeof(hkey->key));
- if (r.length > ISC_SHA256_DIGESTLENGTH) {
+ if (r.length > ISC_SHA256_BLOCK_LENGTH) {
isc_sha256_init(&sha256ctx);
isc_sha256_update(&sha256ctx, r.base, r.length);
isc_sha256_final(hkey->key, &sha256ctx);
@@ -1077,13 +1099,14 @@ hmacsha256_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer) {
+hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t result, tresult;
isc_buffer_t b;
isc_mem_t *mctx = key->mctx;
unsigned int i;
+ UNUSED(pub);
/* read private key file */
result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
&priv);
@@ -1134,6 +1157,8 @@ static dst_func_t hmacsha256_functions = {
hmacsha256_parse,
NULL, /* cleanup */
NULL, /* fromlabel */
+ NULL, /* dump */
+ NULL, /* restore */
};
isc_result_t
@@ -1147,7 +1172,7 @@ dst__hmacsha256_init(dst_func_t **funcp) {
static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
struct dst_hmacsha384_key {
- unsigned char key[ISC_SHA384_DIGESTLENGTH];
+ unsigned char key[ISC_SHA384_BLOCK_LENGTH];
};
static isc_result_t
@@ -1158,7 +1183,7 @@ hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
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);
+ isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
return (ISC_R_SUCCESS);
}
@@ -1221,26 +1246,30 @@ hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_DIGESTLENGTH) == 0)
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH) == 0)
return (ISC_TRUE);
else
return (ISC_FALSE);
}
static isc_result_t
-hmacsha384_generate(dst_key_t *key, int pseudorandom_ok) {
+hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
+ void (*callback)(int))
+{
isc_buffer_t b;
isc_result_t ret;
- int bytes;
- unsigned char data[HMAC_LEN];
+ unsigned int bytes;
+ unsigned char data[ISC_SHA384_BLOCK_LENGTH];
+
+ UNUSED(callback);
bytes = (key->key_size + 7) / 8;
- if (bytes > HMAC_LEN) {
- bytes = HMAC_LEN;
- key->key_size = HMAC_LEN * 8;
+ if (bytes > ISC_SHA384_BLOCK_LENGTH) {
+ bytes = ISC_SHA384_BLOCK_LENGTH;
+ key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
}
- memset(data, 0, HMAC_LEN);
+ memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
if (ret != ISC_R_SUCCESS)
@@ -1249,7 +1278,7 @@ hmacsha384_generate(dst_key_t *key, int pseudorandom_ok) {
isc_buffer_init(&b, data, bytes);
isc_buffer_add(&b, bytes);
ret = hmacsha384_fromdns(key, &b);
- memset(data, 0, ISC_SHA384_DIGESTLENGTH);
+ memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
return (ret);
}
@@ -1263,6 +1292,7 @@ hmacsha384_isprivate(const dst_key_t *key) {
static void
hmacsha384_destroy(dst_key_t *key) {
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;
@@ -1302,7 +1332,7 @@ hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
memset(hkey->key, 0, sizeof(hkey->key));
- if (r.length > ISC_SHA384_DIGESTLENGTH) {
+ if (r.length > ISC_SHA384_BLOCK_LENGTH) {
isc_sha384_init(&sha384ctx);
isc_sha384_update(&sha384ctx, r.base, r.length);
isc_sha384_final(hkey->key, &sha384ctx);
@@ -1347,13 +1377,14 @@ hmacsha384_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer) {
+hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t result, tresult;
isc_buffer_t b;
isc_mem_t *mctx = key->mctx;
unsigned int i;
+ UNUSED(pub);
/* read private key file */
result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
&priv);
@@ -1404,6 +1435,8 @@ static dst_func_t hmacsha384_functions = {
hmacsha384_parse,
NULL, /* cleanup */
NULL, /* fromlabel */
+ NULL, /* dump */
+ NULL, /* restore */
};
isc_result_t
@@ -1417,7 +1450,7 @@ dst__hmacsha384_init(dst_func_t **funcp) {
static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
struct dst_hmacsha512_key {
- unsigned char key[ISC_SHA512_DIGESTLENGTH];
+ unsigned char key[ISC_SHA512_BLOCK_LENGTH];
};
static isc_result_t
@@ -1428,7 +1461,7 @@ hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
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);
+ isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
return (ISC_R_SUCCESS);
}
@@ -1491,26 +1524,30 @@ hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
- if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_DIGESTLENGTH) == 0)
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH) == 0)
return (ISC_TRUE);
else
return (ISC_FALSE);
}
static isc_result_t
-hmacsha512_generate(dst_key_t *key, int pseudorandom_ok) {
+hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
+ void (*callback)(int))
+{
isc_buffer_t b;
isc_result_t ret;
- int bytes;
- unsigned char data[HMAC_LEN];
+ unsigned int bytes;
+ unsigned char data[ISC_SHA512_BLOCK_LENGTH];
+
+ UNUSED(callback);
bytes = (key->key_size + 7) / 8;
- if (bytes > HMAC_LEN) {
- bytes = HMAC_LEN;
- key->key_size = HMAC_LEN * 8;
+ if (bytes > ISC_SHA512_BLOCK_LENGTH) {
+ bytes = ISC_SHA512_BLOCK_LENGTH;
+ key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
}
- memset(data, 0, HMAC_LEN);
+ memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
if (ret != ISC_R_SUCCESS)
@@ -1519,7 +1556,7 @@ hmacsha512_generate(dst_key_t *key, int pseudorandom_ok) {
isc_buffer_init(&b, data, bytes);
isc_buffer_add(&b, bytes);
ret = hmacsha512_fromdns(key, &b);
- memset(data, 0, ISC_SHA512_DIGESTLENGTH);
+ memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
return (ret);
}
@@ -1533,6 +1570,7 @@ hmacsha512_isprivate(const dst_key_t *key) {
static void
hmacsha512_destroy(dst_key_t *key) {
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;
@@ -1572,7 +1610,7 @@ hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
memset(hkey->key, 0, sizeof(hkey->key));
- if (r.length > ISC_SHA512_DIGESTLENGTH) {
+ if (r.length > ISC_SHA512_BLOCK_LENGTH) {
isc_sha512_init(&sha512ctx);
isc_sha512_update(&sha512ctx, r.base, r.length);
isc_sha512_final(hkey->key, &sha512ctx);
@@ -1617,13 +1655,14 @@ hmacsha512_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer) {
+hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t result, tresult;
isc_buffer_t b;
isc_mem_t *mctx = key->mctx;
unsigned int i;
+ UNUSED(pub);
/* read private key file */
result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
&priv);
@@ -1674,6 +1713,8 @@ static dst_func_t hmacsha512_functions = {
hmacsha512_parse,
NULL, /* cleanup */
NULL, /* fromlabel */
+ NULL, /* dump */
+ NULL, /* restore */
};
isc_result_t
diff --git a/contrib/bind9/lib/dns/include/dns/Makefile.in b/contrib/bind9/lib/dns/include/dns/Makefile.in
index a4cd810..e13d084 100644
--- a/contrib/bind9/lib/dns/include/dns/Makefile.in
+++ b/contrib/bind9/lib/dns/include/dns/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007, 2008 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/or distribute this software for any
@@ -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.55 2008-11-14 23:47:33 tbox Exp $
+# $Id: Makefile.in,v 1.57 2009-10-08 23:48:10 tbox Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -21,19 +21,17 @@ top_srcdir = @top_srcdir@
@BIND9_VERSION@
-HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h \
- cert.h compress.h \
+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 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 \
+ 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 private.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 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
+ 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
GENHEADERS = enumclass.h enumtype.h rdatastruct.h
diff --git a/contrib/bind9/lib/dns/include/dns/acl.h b/contrib/bind9/lib/dns/include/dns/acl.h
index 1045cd2..04f5577 100644
--- a/contrib/bind9/lib/dns/include/dns/acl.h
+++ b/contrib/bind9/lib/dns/include/dns/acl.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acl.h,v 1.31.206.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: acl.h,v 1.33 2009-01-17 23:47:43 tbox Exp $ */
#ifndef DNS_ACL_H
#define DNS_ACL_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/cache.h b/contrib/bind9/lib/dns/include/dns/cache.h
index 94077d6..e4ea5f4 100644
--- a/contrib/bind9/lib/dns/include/dns/cache.h
+++ b/contrib/bind9/lib/dns/include/dns/cache.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cache.h,v 1.26 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: cache.h,v 1.28 2009-01-09 23:47:46 tbox Exp $ */
#ifndef DNS_CACHE_H
#define DNS_CACHE_H 1
@@ -65,8 +65,15 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
const char *db_type, unsigned int db_argc, char **db_argv,
dns_cache_t **cachep);
+isc_result_t
+dns_cache_create2(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, dns_rdataclass_t rdclass,
+ const char *cachename, const char *db_type,
+ unsigned int db_argc, char **db_argv, dns_cache_t **cachep);
/*%<
- * Create a new DNS cache.
+ * Create a new DNS cache. dns_cache_create2() will create a named cache.
+ * dns_cache_create() is a backward compatible version that internally specifies
+ * an empty name.
*
* Requires:
*
@@ -76,6 +83,8 @@ dns_cache_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
* manager, or both are NULL. If NULL, no periodic cleaning of the
* cache will take place.
*
+ *\li 'cachename' is a valid string. This must not be NULL.
+ *
*\li 'cachep' is a valid pointer, and *cachep == NULL
*
* Ensures:
@@ -217,12 +226,36 @@ dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int interval);
* Set the periodic cache cleaning interval to 'interval' seconds.
*/
+unsigned int
+dns_cache_getcleaninginterval(dns_cache_t *cache);
+/*%<
+ * Get the periodic cache cleaning interval to 'interval' seconds.
+ */
+
+isc_uint32_t
+dns_cache_getcachesize(dns_cache_t *cache);
+/*%<
+ * Get the maximum cache size.
+ */
+
+const char *
+dns_cache_getname(dns_cache_t *cache);
+/*%<
+ * Get the cache name.
+ */
+
void
dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size);
/*%<
* Set the maximum cache size. 0 means unlimited.
*/
+isc_uint32_t
+dns_cache_getcachesize(dns_cache_t *cache);
+/*%<
+ * Get the maximum cache size.
+ */
+
isc_result_t
dns_cache_flush(dns_cache_t *cache);
/*%<
diff --git a/contrib/bind9/lib/dns/include/dns/client.h b/contrib/bind9/lib/dns/include/dns/client.h
new file mode 100644
index 0000000..13cdf8f
--- /dev/null
+++ b/contrib/bind9/lib/dns/include/dns/client.h
@@ -0,0 +1,621 @@
+/*
+ * Copyright (C) 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: client.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+#ifndef DNS_CLIENT_H
+#define DNS_CLIENT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ *
+ * \brief
+ * The DNS client module provides convenient programming interfaces to various
+ * DNS services, such as name resolution with or without DNSSEC validation or
+ * dynamic DNS update. This module is primarily expected to be used by other
+ * applications than BIND9-related ones that need such advanced DNS features.
+ *
+ * MP:
+ *\li In the typical usage of this module, application threads will not share
+ * the same data structures created and manipulated in this module.
+ * However, the module still ensures appropriate synchronization of such
+ * data structures.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li This module does not handle any low-level data directly, and so no
+ * security issue specific to this module is anticipated.
+ */
+
+#include <isc/event.h>
+#include <isc/sockaddr.h>
+
+#include <dns/tsig.h>
+#include <dns/types.h>
+
+#include <dst/dst.h>
+
+typedef enum {
+ updateop_none = 0,
+ updateop_add = 1,
+ updateop_delete = 2,
+ updateop_exist = 3,
+ updateop_notexist = 4,
+ updateop_max = 5
+} dns_client_updateop_t;
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * Optional flags for dns_client_create(x).
+ */
+/*%< Enable caching resolution results (experimental). */
+#define DNS_CLIENTCREATEOPT_USECACHE 0x8000
+
+/*%
+ * Optional flags for dns_client_(start)resolve.
+ */
+/*%< Disable DNSSEC validation. */
+#define DNS_CLIENTRESOPT_NODNSSEC 0x01
+/*%< Allow running external context. */
+#define DNS_CLIENTRESOPT_ALLOWRUN 0x02
+
+/*%
+ * Optional flags for dns_client_(start)request.
+ */
+/*%< Allow running external context. */
+#define DNS_CLIENTREQOPT_ALLOWRUN 0x01
+
+/*%
+ * A dns_clientresevent_t is sent when name resolution performed by a client
+ * completes. 'result' stores the result code of the entire resolution
+ * procedure. 'vresult' specifically stores the result code of DNSSEC
+ * validation if it is performed. When name resolution successfully completes,
+ * 'answerlist' is typically non empty, containing answer names along with
+ * RRsets. It is the receiver's responsibility to free this list by calling
+ * dns_client_freeresanswer() before freeing the event structure.
+ */
+typedef struct dns_clientresevent {
+ ISC_EVENT_COMMON(struct dns_clientresevent);
+ isc_result_t result;
+ isc_result_t vresult;
+ dns_namelist_t answerlist;
+} dns_clientresevent_t; /* too long? */
+
+/*%
+ * Status of a dynamic update procedure.
+ */
+typedef enum {
+ dns_clientupdatestate_prepare, /*%< no updates have been sent */
+ dns_clientupdatestate_sent, /*%< updates were sent, no response */
+ dns_clientupdatestate_done /*%< update was sent and succeeded */
+} dns_clientupdatestate_t;
+
+/*%
+ * A dns_clientreqevent_t is sent when a DNS request is completed by a client.
+ * 'result' stores the result code of the entire transaction.
+ * If the transaction is successfully completed but the response packet cannot
+ * be parsed, 'result' will store the result code of dns_message_parse().
+ * If the response packet is received, 'rmessage' will contain the response
+ * message, whether it is successfully parsed or not.
+ */
+typedef struct dns_clientreqevent {
+ ISC_EVENT_COMMON(struct dns_clientreqevent);
+ isc_result_t result;
+ dns_message_t *rmessage;
+} dns_clientreqevent_t; /* too long? */
+
+/*%
+ * A dns_clientupdateevent_t is sent when dynamic update performed by a client
+ * completes. 'result' stores the result code of the entire update procedure.
+ * 'state' specifies the status of the update procedure when this event is
+ * sent. This can be used as a hint by the receiver to determine whether
+ * the update attempt was ever made. In particular, if the state is
+ * dns_clientupdatestate_prepare, the receiver can be sure that the requested
+ * update was not applied.
+ */
+typedef struct dns_clientupdateevent {
+ ISC_EVENT_COMMON(struct dns_clientupdateevent);
+ isc_result_t result;
+ dns_clientupdatestate_t state;
+} dns_clientupdateevent_t; /* too long? */
+
+isc_result_t
+dns_client_create(dns_client_t **clientp, unsigned int options);
+
+isc_result_t
+dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
+ unsigned int options, dns_client_t **clientp);
+/*%<
+ * Create a DNS client. These functions create a new client object with
+ * minimal internal resources such as the default 'view' for the IN class and
+ * IPv4/IPv6 dispatches for the view.
+ *
+ * dns_client_createx() takes 'manager' arguments so that the caller can
+ * control the behavior of the client through the underlying event framework.
+ * On the other hand, dns_client_create() simplifies the interface and creates
+ * the managers internally. A DNS client object created via
+ * dns_client_create() is expected to be used by an application that only needs
+ * simple synchronous services or by a thread-based application.
+ *
+ * If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options',
+ * dns_client_create(x) will create a cache database with the view.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'actx' is a valid application context.
+ *
+ *\li 'taskmgr' is a valid task manager.
+ *
+ *\li 'socketmgr' is a valid socket manager.
+ *
+ *\li 'timermgr' is a valid timer manager.
+ *
+ *\li clientp != NULL && *clientp == NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ */
+
+void
+dns_client_destroy(dns_client_t **clientp);
+/*%<
+ * Destroy 'client'.
+ *
+ * Requires:
+ *
+ *\li '*clientp' is a valid client.
+ *
+ * Ensures:
+ *
+ *\li *clientp == NULL.
+ */
+
+isc_result_t
+dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *namespace, isc_sockaddrlist_t *addrs);
+/*%<
+ * Specify a list of addresses of recursive name servers that the client will
+ * use for name resolution. A view for the 'rdclass' class must be created
+ * beforehand. If 'namespace' is non NULL, the specified server will be used
+ * if and only if the query name is a subdomain of 'namespace'. When servers
+ * for multiple 'namespace's are provided, and a query name is covered by
+ * more than one 'namespace', the servers for the best (longest) matching
+ * namespace will be used. If 'namespace' is NULL, it works as if
+ * dns_rootname (.) were specified.
+ *
+ * Requires:
+ *
+ *\li 'client' is a valid client.
+ *
+ *\li 'namespace' is NULL or a valid name.
+ *
+ *\li 'addrs' != NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ */
+
+isc_result_t
+dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *namespace);
+/*%<
+ * Remove configured recursive name servers for the 'rdclass' and 'namespace'
+ * from the client. See the description of dns_client_setservers() for
+ * the requirements about 'rdclass' and 'namespace'.
+ *
+ * Requires:
+ *
+ *\li 'client' is a valid client.
+ *
+ *\li 'namespace' is NULL or a valid name.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ */
+
+isc_result_t
+dns_client_resolve(dns_client_t *client, dns_name_t *name,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ unsigned int options, dns_namelist_t *namelist);
+
+isc_result_t
+dns_client_startresolve(dns_client_t *client, dns_name_t *name,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_clientrestrans_t **transp);
+/*%<
+ * Perform name resolution for 'name', 'rdclass', and 'type'.
+ *
+ * If any trusted keys are configured and the query name is considered to
+ * belong to a secure zone, these functions also validate the responses
+ * using DNSSEC by default. If the DNS_CLIENTRESOPT_NODNSSEC flag is set
+ * in 'options', DNSSEC validation is disabled regardless of the configured
+ * trusted keys or the query name.
+ *
+ * dns_client_resolve() provides a synchronous service. This function starts
+ * name resolution internally and blocks until it completes. On success,
+ * 'namelist' will contain a list of answer names, each of which has
+ * corresponding RRsets. The caller must provide a valid empty list, and
+ * is responsible for freeing the list content via dns_client_freeresanswer().
+ * If the name resolution fails due to an error in DNSSEC validation,
+ * dns_client_resolve() returns the result code indicating the validation
+ * error. Otherwise, it returns the result code of the entire resolution
+ * process, either success or failure.
+ *
+ * It is typically expected that the client object passed to
+ * dns_client_resolve() was created via dns_client_create() and has its own
+ * managers and contexts. However, if the DNS_CLIENTRESOPT_ALLOWRUN flag is
+ * set in 'options', this function performs the synchronous service even if
+ * it does not have its own manager and context structures.
+ *
+ * dns_client_startresolve() is an asynchronous version of dns_client_resolve()
+ * and does not block. When name resolution is completed, 'action' will be
+ * called with the argument of a 'dns_clientresevent_t' object, which contains
+ * the resulting list of answer names (on success). On return, '*transp' is
+ * set to an opaque transaction ID so that the caller can cancel this
+ * resolution process.
+ *
+ * Requires:
+ *
+ *\li 'client' is a valid client.
+ *
+ *\li 'addrs' != NULL.
+ *
+ *\li 'name' is a valid name.
+ *
+ *\li 'namelist' != NULL and is not empty.
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li 'transp' != NULL && *transp == NULL;
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ */
+
+void
+dns_client_cancelresolve(dns_clientrestrans_t *trans);
+/*%<
+ * Cancel an ongoing resolution procedure started via
+ * dns_client_startresolve().
+ *
+ * Notes:
+ *
+ *\li If the resolution procedure has not completed, post its CLIENTRESDONE
+ * event with a result code of #ISC_R_CANCELED.
+ *
+ * Requires:
+ *
+ *\li 'trans' is a valid transaction ID.
+ */
+
+void
+dns_client_destroyrestrans(dns_clientrestrans_t **transp);
+/*%<
+ * Destroy name resolution transaction state identified by '*transp'.
+ *
+ * Requires:
+ *
+ *\li '*transp' is a valid transaction ID.
+ *
+ *\li The caller has received the CLIENTRESDONE event (either because the
+ * resolution completed or because dns_client_cancelresolve() was called).
+ *
+ * Ensures:
+ *
+ *\li *transp == NULL.
+ */
+
+void
+dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist);
+/*%<
+ * Free resources allocated for the content of 'namelist'.
+ *
+ * Requires:
+ *
+ *\li 'client' is a valid client.
+ *
+ *\li 'namelist' != NULL.
+ */
+
+isc_result_t
+dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *keyname, isc_buffer_t *keydatabuf);
+/*%<
+ * Add a DNSSEC trusted key for the 'rdclass' class. A view for the 'rdclass'
+ * class must be created beforehand. 'keyname' is the DNS name of the key,
+ * and 'keydatabuf' stores the resource data of the key.
+ *
+ * Requires:
+ *
+ *\li 'client' is a valid client.
+ *
+ *\li 'keyname' is a valid name.
+ *
+ *\li 'keydatabuf' is a valid buffer.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ */
+
+isc_result_t
+dns_client_request(dns_client_t *client, dns_message_t *qmessage,
+ dns_message_t *rmessage, isc_sockaddr_t *server,
+ unsigned int options, unsigned int parseoptions,
+ dns_tsec_t *tsec, unsigned int timeout,
+ unsigned int udptimeout, unsigned int udpretries);
+
+isc_result_t
+dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage,
+ dns_message_t *rmessage, isc_sockaddr_t *server,
+ unsigned int options, unsigned int parseoptions,
+ dns_tsec_t *tsec, unsigned int timeout,
+ unsigned int udptimeout, unsigned int udpretries,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_clientreqtrans_t **transp);
+
+/*%<
+ * Send a DNS request containig a query message 'query' to 'server'.
+ *
+ * 'parseoptions' will be used when the response packet is parsed, and will be
+ * passed to dns_message_parse() via dns_request_getresponse(). See
+ * dns_message_parse() for more details.
+ *
+ * 'tsec' is a transaction security object containing, e.g. a TSIG key for
+ * authenticating the request/response transaction. This is optional and can
+ * be NULL, in which case this library performs the transaction without any
+ * transaction authentication.
+ *
+ * 'timeout', 'udptimeout', and 'udpretries' are passed to
+ * dns_request_createvia3(). See dns_request_createvia3() for more details.
+ *
+ * dns_client_request() provides a synchronous service. This function sends
+ * the request and blocks until a response is received. On success,
+ * 'rmessage' will contain the response message. The caller must provide a
+ * valid initialized message.
+ *
+ * It is usually expected that the client object passed to
+ * dns_client_request() was created via dns_client_create() and has its own
+ * managers and contexts. However, if the DNS_CLIENTREQOPT_ALLOWRUN flag is
+ * set in 'options', this function performs the synchronous service even if
+ * it does not have its own manager and context structures.
+ *
+ * dns_client_startrequest() is an asynchronous version of dns_client_request()
+ * and does not block. When the transaction is completed, 'action' will be
+ * called with the argument of a 'dns_clientreqevent_t' object, which contains
+ * the response message (on success). On return, '*transp' is set to an opaque
+ * transaction ID so that the caller can cancel this request.
+ *
+ * Requires:
+ *
+ *\li 'client' is a valid client.
+ *
+ *\li 'qmessage' and 'rmessage' are valid initialized message.
+ *
+ *\li 'server' is a valid socket address structure.
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li 'transp' != NULL && *transp == NULL;
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ *
+ *\li Any result that dns_message_parse() can return.
+ */
+
+void
+dns_client_cancelrequest(dns_clientreqtrans_t *transp);
+/*%<
+ * Cancel an ongoing DNS request procedure started via
+ * dns_client_startrequest().
+ *
+ * Notes:
+ *
+ *\li If the request procedure has not completed, post its CLIENTREQDONE
+ * event with a result code of #ISC_R_CANCELED.
+ *
+ * Requires:
+ *
+ *\li 'trans' is a valid transaction ID.
+ */
+
+void
+dns_client_destroyreqtrans(dns_clientreqtrans_t **transp);
+/*%
+ * Destroy DNS request transaction state identified by '*transp'.
+ *
+ * Requires:
+ *
+ *\li '*transp' is a valid transaction ID.
+ *
+ *\li The caller has received the CLIENTREQDONE event (either because the
+ * request completed or because dns_client_cancelrequest() was called).
+ *
+ * Ensures:
+ *
+ *\li *transp == NULL.
+ */
+
+isc_result_t
+dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *zonename, dns_namelist_t *prerequisites,
+ dns_namelist_t *updates, isc_sockaddrlist_t *servers,
+ dns_tsec_t *tsec, unsigned int options);
+
+isc_result_t
+dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass,
+ dns_name_t *zonename, dns_namelist_t *prerequisites,
+ dns_namelist_t *updates, isc_sockaddrlist_t *servers,
+ dns_tsec_t *tsec, unsigned int options,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_clientupdatetrans_t **transp);
+/*%<
+ * Perform DNS dynamic update for 'updates' of the 'rdclass' class with
+ * optional 'prerequisites'.
+ *
+ * 'updates' are a list of names with associated RRsets to be updated.
+ *
+ * 'prerequisites' are a list of names with associated RRsets corresponding to
+ * the prerequisites of the updates. This is optional and can be NULL, in
+ * which case the prerequisite section of the update message will be empty.
+ *
+ * Both 'updates' and 'prerequisites' must be constructed as specified in
+ * RFC2136.
+ *
+ * 'zonename' is the name of the zone in which the updated names exist.
+ * This is optional and can be NULL. In this case, these functions internally
+ * identify the appropriate zone through some queries for the SOA RR starting
+ * with the first name in prerequisites or updates.
+ *
+ * 'servers' is a list of authoritative servers to which the update message
+ * should be sent. This is optional and can be NULL. In this case, these
+ * functions internally identify the appropriate primary server name and its
+ * addresses through some queries for the SOA RR (like the case of zonename)
+ * and supplemental A/AAAA queries for the server name.
+ * Note: The client module generally assumes the given addresses are of the
+ * primary server of the corresponding zone. It will work even if a secondary
+ * server address is specified as long as the server allows update forwarding,
+ * it is generally discouraged to include secondary server addresses unless
+ * there's strong reason to do so.
+ *
+ * 'tsec' is a transaction security object containing, e.g. a TSIG key for
+ * authenticating the update transaction (and the supplemental query/response
+ * transactions if the server is specified). This is optional and can be
+ * NULL, in which case the library tries the update without any transaction
+ * authentication.
+ *
+ * dns_client_update() provides a synchronous service. This function blocks
+ * until the entire update procedure completes, including the additional
+ * queries when necessary.
+ *
+ * dns_client_startupdate() is an asynchronous version of dns_client_update().
+ * It immediately returns (typically with *transp being set to a non-NULL
+ * pointer), and performs the update procedure through a set of internal
+ * events. All transactions including the additional query exchanges are
+ * performed as a separate event, so none of these events cause blocking
+ * operation. When the update procedure completes, the specified function
+ * 'action' will be called with the argument of a 'dns_clientupdateevent_t'
+ * structure. On return, '*transp' is set to an opaque transaction ID so that
+ * the caller can cancel this update process.
+ *
+ * Notes:
+ *\li No options are currently defined.
+ *
+ * Requires:
+ *
+ *\li 'client' is a valid client.
+ *
+ *\li 'updates' != NULL.
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li 'transp' != NULL && *transp == NULL;
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ */
+
+void
+dns_client_cancelupdate(dns_clientupdatetrans_t *trans);
+/*%<
+ * Cancel an ongoing dynamic update procedure started via
+ * dns_client_startupdate().
+ *
+ * Notes:
+ *
+ *\li If the update procedure has not completed, post its UPDATEDONE
+ * event with a result code of #ISC_R_CANCELED.
+ *
+ * Requires:
+ *
+ *\li 'trans' is a valid transaction ID.
+ */
+
+void
+dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp);
+/*%<
+ * Destroy dynamic update transaction identified by '*transp'.
+ *
+ * Requires:
+ *
+ *\li '*transp' is a valid transaction ID.
+ *
+ *\li The caller has received the UPDATEDONE event (either because the
+ * update completed or because dns_client_cancelupdate() was called).
+ *
+ * Ensures:
+ *
+ *\li *transp == NULL.
+ */
+
+isc_result_t
+dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner,
+ dns_rdatatype_t type, dns_rdata_t *source,
+ dns_ttl_t ttl, dns_name_t *target,
+ dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist,
+ dns_rdata_t *rdata, isc_mem_t *mctx);
+/*%<
+ * TBD
+ */
+
+void
+dns_client_freeupdate(dns_name_t **namep);
+/*%<
+ * TBD
+ */
+
+isc_mem_t *
+dns_client_mctx(dns_client_t *client);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_CLIENT_H */
diff --git a/contrib/bind9/lib/dns/include/dns/compress.h b/contrib/bind9/lib/dns/include/dns/compress.h
index 4181c77..ebe543b 100644
--- a/contrib/bind9/lib/dns/include/dns/compress.h
+++ b/contrib/bind9/lib/dns/include/dns/compress.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: compress.h,v 1.40.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: compress.h,v 1.42 2009-01-17 23:47:43 tbox Exp $ */
#ifndef DNS_COMPRESS_H
#define DNS_COMPRESS_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/db.h b/contrib/bind9/lib/dns/include/dns/db.h
index f622834..edb1263 100644
--- a/contrib/bind9/lib/dns/include/dns/db.h
+++ b/contrib/bind9/lib/dns/include/dns/db.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011 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.93.50.5 2009-11-25 23:48:42 tbox Exp $ */
+/* $Id: db.h,v 1.104 2011-01-13 04:59:25 tbox Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
@@ -59,7 +59,11 @@
#include <isc/ondestroy.h>
#include <isc/stdtime.h>
+#include <dns/fixedname.h>
#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rpz.h>
#include <dns/types.h>
ISC_LANG_BEGINDECLS
@@ -167,6 +171,13 @@ typedef struct dns_dbmethods {
dns_dbversion_t *version);
isc_boolean_t (*isdnssec)(dns_db_t *db);
dns_stats_t *(*getrrsetstats)(dns_db_t *db);
+ void (*rpz_enabled)(dns_db_t *db, dns_rpz_st_t *st);
+ isc_result_t (*rpz_findips)(dns_rpz_zone_t *rpz,
+ dns_rpz_type_t rpz_type,
+ dns_zone_t *zone, dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_rdataset_t *ardataset,
+ dns_rpz_st_t *st);
} dns_dbmethods_t;
typedef isc_result_t
@@ -491,6 +502,10 @@ dns_db_load(dns_db_t *db, const char *filename);
isc_result_t
dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format);
+
+isc_result_t
+dns_db_load3(dns_db_t *db, const char *filename, dns_masterformat_t format,
+ unsigned int options);
/*%<
* Load master file 'filename' into 'db'.
*
@@ -614,7 +629,7 @@ dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
*
* Note: if '*versionp' is a read-write version and 'commit' is ISC_TRUE,
* then all changes made in the version will take effect, otherwise they
- * will be rolled back. The value if 'commit' is ignored for read-only
+ * will be rolled back. The value of 'commit' is ignored for read-only
* versions.
*
* Requires:
@@ -841,6 +856,9 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* \li #DNS_R_COVERINGNSEC The returned data is a NSEC
* that potentially covers 'name'.
*
+ * \li #DNS_R_EMPTYWILD The name is a wildcard without
+ * resource records.
+ *
* Error results:
*
* \li #ISC_R_NOMEMORY
@@ -1477,6 +1495,31 @@ dns_db_getrrsetstats(dns_db_t *db);
* dns_rdatasetstats_create(); otherwise NULL.
*/
+void
+dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st);
+/*%<
+ * See if a policy database has DNS_RPZ_TYPE_IP, DNS_RPZ_TYPE_NSIP, or
+ * DNS_RPZ_TYPE_NSDNAME records.
+ */
+
+isc_result_t
+dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+ dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ dns_rdataset_t *ardataset, dns_rpz_st_t *st);
+/*%<
+ * Search the CDIR block tree of a response policy tree of trees for the best
+ * match to any of the IP addresses in an A or AAAA rdataset.
+ *
+ * Requires:
+ * \li search in policy zone 'rpz' for a match of 'rpz_type' either
+ * DNS_RPZ_TYPE_IP or DNS_RPZ_TYPE_NSIP
+ * \li 'zone' and 'db' are the database corresponding to 'rpz'
+ * \li 'version' is the required version of the database
+ * \li 'ardataset' is an A or AAAA rdataset of addresses to check
+ * \li 'found' specifies the previous best match if any or
+ * or NULL, an empty name, 0, DNS_RPZ_POLICY_MISS, and 0
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_DB_H */
diff --git a/contrib/bind9/lib/dns/include/dns/diff.h b/contrib/bind9/lib/dns/include/dns/diff.h
index f5e25ee..b6c929f 100644
--- a/contrib/bind9/lib/dns/include/dns/diff.h
+++ b/contrib/bind9/lib/dns/include/dns/diff.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: diff.h,v 1.15.120.4 2010-06-04 23:48:25 tbox Exp $ */
+/* $Id: diff.h,v 1.19 2010-06-04 23:51:14 tbox Exp $ */
#ifndef DNS_DIFF_H
#define DNS_DIFF_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/dispatch.h b/contrib/bind9/lib/dns/include/dns/dispatch.h
index 6e2f3e1..3d252a1 100644
--- a/contrib/bind9/lib/dns/include/dns/dispatch.h
+++ b/contrib/bind9/lib/dns/include/dns/dispatch.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dispatch.h,v 1.60.82.2 2009-01-29 23:47:44 tbox Exp $ */
+/* $Id: dispatch.h,v 1.62 2009-01-27 23:47:54 tbox Exp $ */
#ifndef DNS_DISPATCH_H
#define DNS_DISPATCH_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/dlz.h b/contrib/bind9/lib/dns/include/dns/dlz.h
index 28a24a9..e04b1b1 100644
--- a/contrib/bind9/lib/dns/include/dns/dlz.h
+++ b/contrib/bind9/lib/dns/include/dns/dlz.h
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005-2007, 2009, 2010 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: dlz.h,v 1.7.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: dlz.h,v 1.12 2010-12-20 23:47:21 tbox Exp $ */
/*! \file dns/dlz.h */
@@ -87,6 +87,7 @@
#include <dns/name.h>
#include <dns/types.h>
#include <dns/view.h>
+#include <dst/dst.h>
#include <isc/lang.h>
@@ -166,12 +167,37 @@ typedef isc_result_t
* return a result code indicating the type of error.
*/
+
+typedef isc_result_t
+(*dns_dlzconfigure_t)(void *driverarg, void *dbdata, dns_view_t *view);
+/*%<
+ * Method prototype. Drivers implementing the DLZ interface may
+ * optionally supply a configure method. If supplied, this will be
+ * called immediately after the create method is called. The driver
+ * may call configuration functions during the configure call
+ */
+
+
+typedef isc_boolean_t (*dns_dlzssumatch_t)(dns_name_t *signer,
+ dns_name_t *name,
+ isc_netaddr_t *tcpaddr,
+ dns_rdatatype_t type,
+ const dst_key_t *key,
+ void *driverarg, void *dbdata);
+/*%<
+ * Method prototype. Drivers implementing the DLZ interface may
+ * optionally supply a ssumatch method. If supplied, this will be
+ * called to authorize update requests
+ */
+
/*% the methods supplied by a DLZ driver */
typedef struct dns_dlzmethods {
dns_dlzcreate_t create;
dns_dlzdestroy_t destroy;
dns_dlzfindzone_t findzone;
dns_dlzallowzonexfr_t allowzonexfr;
+ dns_dlzconfigure_t configure;
+ dns_dlzssumatch_t ssumatch;
} dns_dlzmethods_t;
/*% information about a DLZ driver */
@@ -183,12 +209,18 @@ struct dns_dlzimplementation {
ISC_LINK(dns_dlzimplementation_t) link;
};
-/*% an instance of a DLZ driver */
+typedef isc_result_t (*dlzconfigure_callback_t)(dns_view_t *, dns_zone_t *);
+
+/*% An instance of a DLZ driver */
struct dns_dlzdb {
unsigned int magic;
isc_mem_t *mctx;
dns_dlzimplementation_t *implementation;
void *dbdata;
+ dlzconfigure_callback_t configure_callback;
+#ifdef BIND9
+ dns_ssutable_t *ssutable;
+#endif
};
@@ -285,6 +317,30 @@ dns_dlzunregister(dns_dlzimplementation_t **dlzimp);
* is called.
*/
+
+isc_result_t
+dns_dlz_writeablezone(dns_view_t *view, const char *zone_name);
+
+/*%<
+ * creates a writeable DLZ zone. Must be called from within the
+ * configure() method of a DLZ driver.
+ */
+
+
+isc_result_t
+dns_dlzconfigure(dns_view_t *view, dlzconfigure_callback_t callback);
+/*%<
+ * call a DLZ drivers configure method, if supplied
+ */
+
+isc_boolean_t
+dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase,
+ dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
+ dns_rdatatype_t type, const dst_key_t *key);
+/*%<
+ * call a DLZ drivers ssumatch method, if supplied. Otherwise return ISC_FALSE
+ */
+
ISC_LANG_ENDDECLS
#endif /* DLZ_H */
diff --git a/contrib/bind9/lib/dns/include/dns/dns64.h b/contrib/bind9/lib/dns/include/dns/dns64.h
new file mode 100644
index 0000000..5fd32e8
--- /dev/null
+++ b/contrib/bind9/lib/dns/include/dns/dns64.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 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: dns64.h,v 1.3 2010-12-08 23:51:56 tbox Exp $ */
+
+#ifndef DNS_DNS64_H
+#define DNS_DNS64_H 1
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * dns_dns64_create() flags.
+ */
+#define DNS_DNS64_RECURSIVE_ONLY 0x01 /* If set then this record
+ * only applies to recursive
+ * queries.
+ */
+#define DNS_DNS64_BREAK_DNSSEC 0x02 /* If set then still perform
+ * DNSSEC synthesis even
+ * though the result would
+ * fail validation.
+ */
+
+/*
+ * dns_dns64_aaaaok() and dns_dns64_aaaafroma() flags.
+ */
+#define DNS_DNS64_RECURSIVE 0x01 /* Recursive query. */
+#define DNS_DNS64_DNSSEC 0x02 /* DNSSEC sensitive query. */
+
+isc_result_t
+dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix,
+ unsigned int prefixlen, isc_netaddr_t *suffix,
+ dns_acl_t *client, dns_acl_t *mapped, dns_acl_t *excluded,
+ unsigned int flags, dns_dns64_t **dns64);
+/*
+ * Create a dns64 record which is used to identify the set of clients
+ * it applies to and how to perform the DNS64 synthesis.
+ *
+ * 'prefix' and 'prefixlen' defined the leading bits of the AAAA records
+ * to be synthesised. 'suffix' defines the bits after the A records bits.
+ * If suffix is NULL zeros will be used for these bits. 'client' defines
+ * for which clients this record applies. If 'client' is NULL then all
+ * clients apply. 'mapped' defines which A records are candidated for
+ * mapping. If 'mapped' is NULL then all A records will be mapped.
+ * 'excluded' defines which AAAA are to be treated as non-existent for the
+ * purposed of determining whether to perform syntesis. If 'excluded' is
+ * NULL then no AAAA records prevent synthesis.
+ *
+ * If DNS_DNS64_RECURSIVE_ONLY is set then the record will only match if
+ * DNS_DNS64_RECURSIVE is set when calling dns_dns64_aaaaok() and
+ * dns_dns64_aaaafroma().
+ *
+ * If DNS_DNS64_BREAK_DNSSEC is set then the record will still apply if
+ * DNS_DNS64_DNSSEC is set when calling dns_dns64_aaaaok() and
+ * dns_dns64_aaaafroma() otherwise the record will be ignored.
+ *
+ * Requires:
+ * 'mctx' to be valid.
+ * 'prefix' to be valid and the address family to AF_INET6.
+ * 'prefixlen' to be one of 32, 40, 48, 56, 72 and 96.
+ * the bits not covered by prefixlen in prefix to
+ * be zero.
+ * 'suffix' to be NULL or the address family be set to AF_INET6
+ * and the leading 'prefixlen' + 32 bits of the 'suffix'
+ * to be zero. If 'prefixlen' is 40, 48 or 56 then the
+ * the leading 'prefixlen' + 40 bits of 'suffix' must be
+ * zero.
+ * 'client' to be NULL or a valid acl.
+ * 'mapped' to be NULL or a valid acl.
+ * 'exculded' to be NULL or a valid acl.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOMEMORY
+ */
+
+void
+dns_dns64_destroy(dns_dns64_t **dns64p);
+/*
+ * Destroys a dns64 record.
+ *
+ * Requires the record to not be linked.
+ */
+
+isc_result_t
+dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
+ const dns_name_t *reqsigner, const dns_aclenv_t *env,
+ unsigned int flags, unsigned char *a, unsigned char *aaaa);
+/*
+ * dns_dns64_aaaafroma() determines whether to perform a DNS64 address
+ * synthesis from 'a' based on 'dns64', 'reqaddr', 'reqsigner', 'env',
+ * 'flags' and 'aaaa'. If synthesis is performed then the result is
+ * written to '*aaaa'.
+ *
+ * The synthesised address will be of the form:
+ *
+ * <prefix bits><a bits><suffix bits>
+ *
+ * If <a bits> straddle bits 64-71 of the AAAA record, then 8 zero bits will
+ * be inserted at bits 64-71.
+ *
+ * Requires:
+ * 'dns64' to be valid.
+ * 'reqaddr' to be valid.
+ * 'reqsigner' to be NULL or valid.
+ * 'env' to be valid.
+ * 'a' to point to a IPv4 address in network order.
+ * 'aaaa' to point to a IPv6 address buffer in network order.
+ *
+ * Returns:
+ * ISC_R_SUCCESS if synthesis was performed.
+ * DNS_R_DISALLOWED if there is no match.
+ */
+
+dns_dns64_t *
+dns_dns64_next(dns_dns64_t *dns64);
+/*
+ * Return the next dns64 record in the list.
+ */
+
+void
+dns_dns64_append(dns_dns64list_t *list, dns_dns64_t *dns64);
+/*
+ * Append the dns64 record to the list.
+ */
+
+void
+dns_dns64_unlink(dns_dns64list_t *list, dns_dns64_t *dns64);
+/*
+ * Unlink the dns64 record from the list.
+ */
+
+isc_boolean_t
+dns_dns64_aaaaok(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr,
+ const dns_name_t *reqsigner, const dns_aclenv_t *env,
+ unsigned int flags, dns_rdataset_t *rdataset,
+ isc_boolean_t *aaaaok, size_t aaaaoklen);
+/*
+ * Determine if there are any non-excluded AAAA records in from the
+ * matching dns64 records in the list starting at 'dns64'. If there
+ * is a non-exluded address return ISC_TRUE. If all addresses are
+ * excluded in the matched records return ISC_FALSE. If no records
+ * match then return ISC_TRUE.
+ *
+ * If aaaaok is defined then dns_dns64_aaaaok() return a array of which
+ * addresses in 'rdataset' were deemed to not be exclude by any matching
+ * record. If there are no matching records then all entries are set
+ * to ISC_TRUE.
+ *
+ * Requires
+ * 'rdataset' to be valid and to be for type AAAA and class IN.
+ * 'aaaaoklen' must match the number of records in 'rdataset'
+ * if 'aaaaok' in non NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_DNS64_H */
diff --git a/contrib/bind9/lib/dns/include/dns/dnssec.h b/contrib/bind9/lib/dns/include/dns/dnssec.h
index 5a1468a..c6d910b 100644
--- a/contrib/bind9/lib/dns/include/dns/dnssec.h
+++ b/contrib/bind9/lib/dns/include/dns/dnssec.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010 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: dnssec.h,v 1.32.332.6 2009-06-22 23:47:18 tbox Exp $ */
+/* $Id: dnssec.h,v 1.42 2010-01-09 23:48:45 tbox Exp $ */
#ifndef DNS_DNSSEC_H
#define DNS_DNSSEC_H 1
@@ -25,12 +25,48 @@
#include <isc/lang.h>
#include <isc/stdtime.h>
+#include <dns/diff.h>
#include <dns/types.h>
#include <dst/dst.h>
ISC_LANG_BEGINDECLS
+/*
+ * Indicates how the signer found this key: in the key repository, at the
+ * zone apex, or specified by the user.
+ */
+typedef enum {
+ dns_keysource_unknown,
+ dns_keysource_repository,
+ dns_keysource_zoneapex,
+ dns_keysource_user
+} dns_keysource_t;
+
+/*
+ * A DNSSEC key and hints about its intended use gleaned from metadata
+ */
+struct dns_dnsseckey {
+ dst_key_t *key;
+ isc_boolean_t hint_publish; /*% metadata says to publish */
+ isc_boolean_t force_publish; /*% publish regardless of metadata */
+ isc_boolean_t hint_sign; /*% metadata says to sign with this key */
+ isc_boolean_t force_sign; /*% sign with key regardless of metadata */
+ isc_boolean_t hint_remove; /*% metadata says *don't* publish */
+ isc_boolean_t is_active; /*% key is already active */
+ isc_boolean_t first_sign; /*% key is newly becoming active */
+ unsigned int prepublish; /*% how long until active? */
+ dns_keysource_t source; /*% how the key was found */
+ isc_boolean_t ksk; /*% this is a key-signing key */
+ isc_boolean_t legacy; /*% this is old-style key with no
+ metadata (possibly generated by
+ an older version of BIND9) and
+ should be ignored when searching
+ for keys to import into the zone */
+ unsigned int index; /*% position in list */
+ ISC_LINK(dns_dnsseckey_t) link;
+};
+
isc_result_t
dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
dst_key_t **key);
@@ -184,6 +220,103 @@ dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
isc_boolean_t ignoretime, isc_mem_t *mctx);
+isc_result_t
+dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
+ dns_dnsseckey_t **dkp);
+/*%<
+ * Create and initialize a dns_dnsseckey_t structure.
+ *
+ * Requires:
+ *\li 'dkp' is not NULL and '*dkp' is NULL.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp);
+/*%<
+ * Reclaim a dns_dnsseckey_t structure.
+ *
+ * Requires:
+ *\li 'dkp' is not NULL and '*dkp' is not NULL.
+ *
+ * Ensures:
+ *\li '*dkp' is NULL.
+ */
+
+isc_result_t
+dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
+ isc_mem_t *mctx, dns_dnsseckeylist_t *keylist);
+/*%<
+ * Search 'directory' for K* key files matching the name in 'origin'.
+ * Append all such keys, along with use hints gleaned from their
+ * metadata, onto 'keylist'.
+ *
+ * Requires:
+ *\li 'keylist' is not NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOTFOUND
+ *\li #ISC_R_NOMEMORY
+ *\li any error returned by dns_name_totext(), isc_dir_open(), or
+ * dst_key_fromnamedfile()
+ *
+ * Ensures:
+ *\li On error, keylist is unchanged
+ */
+
+isc_result_t
+dns_dnssec_keylistfromrdataset(dns_name_t *origin,
+ const char *directory, isc_mem_t *mctx,
+ dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
+ dns_rdataset_t *soasigs, isc_boolean_t savekeys,
+ isc_boolean_t public,
+ dns_dnsseckeylist_t *keylist);
+/*%<
+ * Append the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
+ * Omit duplicates. If 'public' is ISC_FALSE, search 'directory' for
+ * matching key files, and load the private keys that go with
+ * the public ones. If 'savekeys' is ISC_TRUE, mark the keys so
+ * they will not be deleted or inactivated regardless of metadata.
+ *
+ * 'keysigs' and 'soasigs', if not NULL and associated, contain the
+ * RRSIGS for the DNSKEY and SOA records respectively and are used to mark
+ * whether a key is already active in the zone.
+ */
+
+isc_result_t
+dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
+ dns_dnsseckeylist_t *removed, dns_name_t *origin,
+ dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk,
+ isc_mem_t *mctx, void (*report)(const char *, ...));
+/*%<
+ * Update the list of keys in 'keys' with new key information in 'newkeys'.
+ *
+ * For each key in 'newkeys', see if it has a match in 'keys'.
+ * - If not, and if the metadata says the key should be published:
+ * add it to 'keys', and place a dns_difftuple into 'diff' so
+ * the key can be added to the DNSKEY set. If the metadata says it
+ * should be active, set the first_sign flag.
+ * - If so, and if the metadata says it should be removed:
+ * remove it from 'keys', and place a dns_difftuple into 'diff' so
+ * the key can be removed from the DNSKEY set. if 'removed' is non-NULL,
+ * copy the key into that list; otherwise destroy it.
+ * - Otherwise, make sure keys has current metadata.
+ *
+ * If 'allzsk' is true, we are allowing KSK-flagged keys to be used as
+ * ZSKs.
+ *
+ * 'ttl' is the TTL of the DNSKEY RRset; if it is longer than the
+ * time until a new key will be activated, then we have to delay the
+ * key's activation.
+ *
+ * 'report' points to a function for reporting status.
+ *
+ * On completion, any remaining keys in 'newkeys' are freed.
+ */
ISC_LANG_ENDDECLS
#endif /* DNS_DNSSEC_H */
diff --git a/contrib/bind9/lib/dns/include/dns/ds.h b/contrib/bind9/lib/dns/include/dns/ds.h
index 77a2cb8..04e4bab 100644
--- a/contrib/bind9/lib/dns/include/dns/ds.h
+++ b/contrib/bind9/lib/dns/include/dns/ds.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010 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: ds.h,v 1.10 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: ds.h,v 1.12 2010-12-23 23:47:08 tbox Exp $ */
#ifndef DNS_DS_H
#define DNS_DS_H 1
@@ -26,6 +26,11 @@
#define DNS_DSDIGEST_SHA1 (1)
#define DNS_DSDIGEST_SHA256 (2)
+#define DNS_DSDIGEST_GOST (3)
+
+/* should not be here... */
+
+#define ISC_GOST_DIGESTLENGTH 32U
/*
* Assuming SHA-256 digest type.
diff --git a/contrib/bind9/lib/dns/include/dns/ecdb.h b/contrib/bind9/lib/dns/include/dns/ecdb.h
new file mode 100644
index 0000000..be71a52
--- /dev/null
+++ b/contrib/bind9/lib/dns/include/dns/ecdb.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 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: ecdb.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+#ifndef DNS_ECDB_H
+#define DNS_ECDB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/* TBD */
+
+/***
+ *** Imports
+ ***/
+
+#include <dns/types.h>
+
+/***
+ *** Types
+ ***/
+
+/***
+ *** Functions
+ ***/
+
+/* TBD: describe those */
+
+isc_result_t
+dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp);
+
+void
+dns_ecdb_unregister(dns_dbimplementation_t **dbimp);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ECDB_H */
diff --git a/contrib/bind9/lib/dns/include/dns/events.h b/contrib/bind9/lib/dns/include/dns/events.h
index 689566b..d985833 100644
--- a/contrib/bind9/lib/dns/include/dns/events.h
+++ b/contrib/bind9/lib/dns/include/dns/events.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: events.h,v 1.49.332.4 2010-05-10 23:48:14 tbox Exp $ */
+/* $Id: events.h,v 1.56 2010-12-21 03:11:42 marka Exp $ */
#ifndef DNS_EVENTS_H
#define DNS_EVENTS_H 1
@@ -69,6 +69,11 @@
#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_MANAGEKEYS (ISC_EVENTCLASS_DNS + 42)
+#define DNS_EVENT_CLIENTRESDONE (ISC_EVENTCLASS_DNS + 43)
+#define DNS_EVENT_CLIENTREQDONE (ISC_EVENTCLASS_DNS + 44)
+#define DNS_EVENT_ADBGROWENTRIES (ISC_EVENTCLASS_DNS + 45)
+#define DNS_EVENT_ADBGROWNAMES (ISC_EVENTCLASS_DNS + 46)
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
diff --git a/contrib/bind9/lib/dns/include/dns/forward.h b/contrib/bind9/lib/dns/include/dns/forward.h
index 5fbe898..683969d 100644
--- a/contrib/bind9/lib/dns/include/dns/forward.h
+++ b/contrib/bind9/lib/dns/include/dns/forward.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: forward.h,v 1.11 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: forward.h,v 1.13 2009-09-02 23:48:02 tbox Exp $ */
#ifndef DNS_FORWARD_H
#define DNS_FORWARD_H 1
@@ -67,6 +67,21 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
*/
isc_result_t
+dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name);
+/*%<
+ * Removes an entry for 'name' from the forwarding table. If an entry
+ * that exactly matches 'name' does not exist, ISC_R_NOTFOUND will be returned.
+ *
+ * Requires:
+ * \li fwdtable is a valid forwarding table.
+ * \li name is a valid name
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND
+ */
+
+isc_result_t
dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name,
dns_forwarders_t **forwardersp);
/*%<
diff --git a/contrib/bind9/lib/dns/include/dns/journal.h b/contrib/bind9/lib/dns/include/dns/journal.h
index 9e56c19..28a7dbe 100644
--- a/contrib/bind9/lib/dns/include/dns/journal.h
+++ b/contrib/bind9/lib/dns/include/dns/journal.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: journal.h,v 1.33.120.4 2009-11-04 23:47:25 tbox Exp $ */
+/* $Id: journal.h,v 1.37 2009-11-04 23:48:18 tbox Exp $ */
#ifndef DNS_JOURNAL_H
#define DNS_JOURNAL_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/keydata.h b/contrib/bind9/lib/dns/include/dns/keydata.h
new file mode 100644
index 0000000..36bf590
--- /dev/null
+++ b/contrib/bind9/lib/dns/include/dns/keydata.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 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: keydata.h,v 1.2 2009-06-30 02:52:32 each Exp $ */
+
+#ifndef DNS_KEYDATA_H
+#define DNS_KEYDATA_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/keydata.h
+ * \brief
+ * KEYDATA utilities.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <dns/types.h>
+#include <dns/rdatastruct.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_keydata_todnskey(dns_rdata_keydata_t *keydata,
+ dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx);
+
+isc_result_t
+dns_keydata_fromdnskey(dns_rdata_keydata_t *keydata,
+ dns_rdata_dnskey_t *dnskey,
+ isc_uint32_t refresh, isc_uint32_t addhd,
+ isc_uint32_t removehd, isc_mem_t *mctx);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_KEYDATA_H */
diff --git a/contrib/bind9/lib/dns/include/dns/keytable.h b/contrib/bind9/lib/dns/include/dns/keytable.h
index 40c4b16..a53ec08 100644
--- a/contrib/bind9/lib/dns/include/dns/keytable.h
+++ b/contrib/bind9/lib/dns/include/dns/keytable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keytable.h,v 1.16 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: keytable.h,v 1.23 2010-06-25 03:24:05 marka Exp $ */
#ifndef DNS_KEYTABLE_H
#define DNS_KEYTABLE_H 1
@@ -42,6 +42,10 @@
*/
#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/refcount.h>
+#include <isc/rwlock.h>
+#include <isc/stdtime.h>
#include <dns/types.h>
@@ -49,6 +53,33 @@
ISC_LANG_BEGINDECLS
+struct dns_keytable {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ isc_rwlock_t rwlock;
+ /* Locked by lock. */
+ isc_uint32_t active_nodes;
+ /* Locked by rwlock. */
+ isc_uint32_t references;
+ dns_rbt_t *table;
+};
+
+#define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l')
+#define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC)
+
+struct dns_keynode {
+ unsigned int magic;
+ isc_refcount_t refcount;
+ dst_key_t * key;
+ isc_boolean_t managed;
+ struct dns_keynode * next;
+};
+
+#define KEYNODE_MAGIC ISC_MAGIC('K', 'N', 'o', 'd')
+#define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC)
+
isc_result_t
dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep);
/*%<
@@ -106,16 +137,22 @@ dns_keytable_detach(dns_keytable_t **keytablep);
*/
isc_result_t
-dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp);
+dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
+ dst_key_t **keyp);
/*%<
- * Add '*keyp' to 'keytable'.
+ * Add '*keyp' to 'keytable' (using the name in '*keyp').
+ * The value of keynode->managed is set to 'managed'
*
* Notes:
*
*\li Ownership of *keyp is transferred to the keytable.
+ *\li If the key already exists in the table, ISC_R_EXISTS is
+ * returned and the new key is freed.
*
* Requires:
*
+ *\li 'keytable' points to a valid keytable.
+ *
*\li keyp != NULL && *keyp is a valid dst_key_t *.
*
* Ensures:
@@ -125,11 +162,124 @@ dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp);
* Returns:
*
*\li ISC_R_SUCCESS
+ *\li ISC_R_EXISTS
+ *
+ *\li Any other result indicates failure.
+ */
+
+isc_result_t
+dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name);
+/*%<
+ * Add a null key to 'keytable' for name 'name'. This marks the
+ * name as a secure domain, but doesn't supply any key data to allow the
+ * domain to be validated. (Used when automated trust anchor management
+ * has gotten broken by a zone misconfiguration; for example, when the
+ * active key has been revoked but the stand-by key was still in its 30-day
+ * waiting period for validity.)
+ *
+ * Notes:
+ *
+ *\li If a key already exists in the table, ISC_R_EXISTS is
+ * returned and nothing is done.
+ *
+ * Requires:
+ *
+ *\li 'keytable' points to a valid keytable.
+ *
+ *\li keyp != NULL && *keyp is a valid dst_key_t *.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_EXISTS
+ *
+ *\li Any other result indicates failure.
+ */
+
+isc_result_t
+dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname);
+/*%<
+ * Delete node(s) from 'keytable' matching name 'keyname'
+ *
+ * Requires:
+ *
+ *\li 'keytable' points to a valid keytable.
+ *
+ *\li 'name' is not NULL
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Any other result indicates failure.
+ */
+
+isc_result_t
+dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey);
+/*%<
+ * Delete node(s) from 'keytable' containing copies of the key pointed
+ * to by 'dstkey'
+ *
+ * Requires:
+ *
+ *\li 'keytable' points to a valid keytable.
+ *\li 'dstkey' is not NULL
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
*
*\li Any other result indicates failure.
*/
isc_result_t
+dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname,
+ dns_keynode_t **keynodep);
+/*%<
+ * Search for the first instance of a key named 'name' in 'keytable',
+ * without regard to keyid and algorithm. Use dns_keytable_nextkeynode()
+ * to find subsequent instances.
+ *
+ * Requires:
+ *
+ *\li 'keytable' is a valid keytable.
+ *
+ *\li 'name' is a valid absolute name.
+ *
+ *\li keynodep != NULL && *keynodep == NULL
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOTFOUND
+ *
+ *\li Any other result indicates an error.
+ */
+
+isc_result_t
+dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
+ dns_keynode_t **nextnodep);
+/*%<
+ * Return for the next key after 'keynode' in 'keytable', without regard to
+ * keyid and algorithm.
+ *
+ * Requires:
+ *
+ *\li 'keytable' is a valid keytable.
+ *
+ *\li 'keynode' is a valid keynode.
+ *
+ *\li nextnodep != NULL && *nextnodep == NULL
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOTFOUND
+ *
+ *\li Any other result indicates an error.
+ */
+
+isc_result_t
dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
dns_secalg_t algorithm, dns_keytag_t tag,
dns_keynode_t **keynodep);
@@ -157,7 +307,7 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
isc_result_t
dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
- dns_keynode_t **nextnodep);
+ dns_keynode_t **nextnodep);
/*%<
* Search for the next key with the same properties as 'keynode' in
* 'keytable' as found by dns_keytable_findkeynode().
@@ -201,6 +351,22 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
*/
void
+dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
+ dns_keynode_t **target);
+/*%<
+ * Attach a keynode and and increment the active_nodes counter in a
+ * corresponding keytable.
+ *
+ * Requires:
+ *
+ *\li 'keytable' is a valid keytable.
+ *
+ *\li 'source' is a valid keynode.
+ *
+ *\li 'target' is not null and '*target' is null.
+ */
+
+void
dns_keytable_detachkeynode(dns_keytable_t *keytable,
dns_keynode_t **keynodep);
/*%<
@@ -244,12 +410,48 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
*\li Any other result is an error.
*/
+isc_result_t
+dns_keytable_dump(dns_keytable_t *keytable, FILE *fp);
+/*%<
+ * Dump the keytable on fp.
+ */
+
dst_key_t *
dns_keynode_key(dns_keynode_t *keynode);
/*%<
* Get the DST key associated with keynode.
*/
+isc_boolean_t
+dns_keynode_managed(dns_keynode_t *keynode);
+/*%<
+ * Is this flagged as a managed key?
+ */
+
+isc_result_t
+dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target);
+/*%<
+ * Allocate space for a keynode
+ */
+
+void
+dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target);
+/*%<
+ * Attach keynode 'source' to '*target'
+ */
+
+void
+dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **target);
+/*%<
+ * Detach a single keynode, without touching any keynodes that
+ * may be pointed to by its 'next' pointer
+ */
+
+void
+dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **target);
+/*%<
+ * Detach a keynode and all its succesors.
+ */
ISC_LANG_ENDDECLS
#endif /* DNS_KEYTABLE_H */
diff --git a/contrib/bind9/lib/dns/include/dns/keyvalues.h b/contrib/bind9/lib/dns/include/dns/keyvalues.h
index 70ca3fa..2107657 100644
--- a/contrib/bind9/lib/dns/include/dns/keyvalues.h
+++ b/contrib/bind9/lib/dns/include/dns/keyvalues.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keyvalues.h,v 1.23.48.4 2010-01-15 23:47:33 tbox Exp $ */
+/* $Id: keyvalues.h,v 1.29 2010-12-23 23:47:08 tbox Exp $ */
#ifndef DNS_KEYVALUES_H
#define DNS_KEYVALUES_H 1
@@ -42,7 +42,7 @@
#define DNS_KEYOWNER_ENTITY 0x0200 /*%< key is assoc. with entity eg host */
#define DNS_KEYOWNER_ZONE 0x0100 /*%< key is zone key */
#define DNS_KEYOWNER_RESERVED 0x0300 /*%< reserved meaning */
-#define DNS_KEYFLAG_REVOKE 0x0080 /*%< key revoked (per rfc5001) */
+#define DNS_KEYFLAG_REVOKE 0x0080 /*%< key revoked (per rfc5011) */
#define DNS_KEYFLAG_RESERVED9 0x0040 /*%< reserved - must be zero */
#define DNS_KEYFLAG_RESERVED10 0x0020 /*%< reserved - must be zero */
#define DNS_KEYFLAG_RESERVED11 0x0010 /*%< reserved - must be zero */
@@ -51,7 +51,6 @@
#define DNS_KEYFLAG_RESERVEDMASK (DNS_KEYFLAG_RESERVED2 | \
DNS_KEYFLAG_RESERVED4 | \
DNS_KEYFLAG_RESERVED5 | \
- DNS_KEYFLAG_RESERVED8 | \
DNS_KEYFLAG_RESERVED9 | \
DNS_KEYFLAG_RESERVED10 | \
DNS_KEYFLAG_RESERVED11 )
@@ -71,6 +70,7 @@
#define DNS_KEYALG_NSEC3RSASHA1 7
#define DNS_KEYALG_RSASHA256 8
#define DNS_KEYALG_RSASHA512 10
+#define DNS_KEYALG_ECCGOST 12
#define DNS_KEYALG_INDIRECT 252
#define DNS_KEYALG_PRIVATEDNS 253
#define DNS_KEYALG_PRIVATEOID 254 /*%< Key begins with OID giving alg */
@@ -99,4 +99,6 @@
#define DNS_SIG_DSAMINBYTES 213
#define DNS_SIG_DSAMAXBYTES 405
+#define DNS_SIG_GOSTSIGSIZE 64
+
#endif /* DNS_KEYVALUES_H */
diff --git a/contrib/bind9/lib/dns/include/dns/lib.h b/contrib/bind9/lib/dns/include/dns/lib.h
index 361ef8f..70874b7 100644
--- a/contrib/bind9/lib/dns/include/dns/lib.h
+++ b/contrib/bind9/lib/dns/include/dns/lib.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lib.h,v 1.16 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: lib.h,v 1.18 2009-09-02 23:48:02 tbox Exp $ */
#ifndef DNS_LIB_H
#define DNS_LIB_H 1
@@ -40,6 +40,20 @@ dns_lib_initmsgcat(void);
* has not already been initialized.
*/
+isc_result_t
+dns_lib_init(void);
+/*%<
+ * A set of initialization procedure used in the DNS library. This function
+ * is provided for an application that is not aware of the underlying ISC or
+ * DNS libraries much.
+ */
+
+void
+dns_lib_shutdown(void);
+/*%<
+ * Free temporary resources allocated in dns_lib_init().
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_LIB_H */
diff --git a/contrib/bind9/lib/dns/include/dns/log.h b/contrib/bind9/lib/dns/include/dns/log.h
index 4b648ff..a5650ed 100644
--- a/contrib/bind9/lib/dns/include/dns/log.h
+++ b/contrib/bind9/lib/dns/include/dns/log.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.h,v 1.42.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: log.h,v 1.45 2009-12-18 22:16:49 each Exp $ */
/*! \file dns/log.h
* \author Principal Authors: DCL */
@@ -73,6 +73,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
#define DNS_LOGMODULE_HINTS (&dns_modules[24])
#define DNS_LOGMODULE_ACACHE (&dns_modules[25])
#define DNS_LOGMODULE_DLZ (&dns_modules[26])
+#define DNS_LOGMODULE_DNSSEC (&dns_modules[27])
ISC_LANG_BEGINDECLS
diff --git a/contrib/bind9/lib/dns/include/dns/lookup.h b/contrib/bind9/lib/dns/include/dns/lookup.h
index 81bb9b9..7e6a566 100644
--- a/contrib/bind9/lib/dns/include/dns/lookup.h
+++ b/contrib/bind9/lib/dns/include/dns/lookup.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lookup.h,v 1.12.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: lookup.h,v 1.14 2009-01-17 23:47:43 tbox Exp $ */
#ifndef DNS_LOOKUP_H
#define DNS_LOOKUP_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/master.h b/contrib/bind9/lib/dns/include/dns/master.h
index 3f3a4de..2ee6374 100644
--- a/contrib/bind9/lib/dns/include/dns/master.h
+++ b/contrib/bind9/lib/dns/include/dns/master.h
@@ -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-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: master.h,v 1.51 2008-04-02 02:37:42 marka Exp $ */
+/* $Id: master.h,v 1.53 2009-07-01 23:47:36 tbox Exp $ */
#ifndef DNS_MASTER_H
#define DNS_MASTER_H 1
@@ -56,6 +56,7 @@
#define DNS_MASTER_CHECKMXFAIL 0x00001000
#define DNS_MASTER_RESIGN 0x00002000
+#define DNS_MASTER_KEY 0x00004000 /*%< Loading a key zone master file. */
ISC_LANG_BEGINDECLS
diff --git a/contrib/bind9/lib/dns/include/dns/masterdump.h b/contrib/bind9/lib/dns/include/dns/masterdump.h
index 96a198d..684dd82 100644
--- a/contrib/bind9/lib/dns/include/dns/masterdump.h
+++ b/contrib/bind9/lib/dns/include/dns/masterdump.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: masterdump.h,v 1.42.602.2 2011-06-02 23:46:22 tbox Exp $ */
+/* $Id: masterdump.h,v 1.42.596.2 2011-06-02 23:47:35 tbox Exp $ */
#ifndef DNS_MASTERDUMP_H
#define DNS_MASTERDUMP_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/message.h b/contrib/bind9/lib/dns/include/dns/message.h
index 98fb321..438de1e 100644
--- a/contrib/bind9/lib/dns/include/dns/message.h
+++ b/contrib/bind9/lib/dns/include/dns/message.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 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.h,v 1.125.118.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: message.h,v 1.132 2010-03-04 23:50:34 tbox Exp $ */
#ifndef DNS_MESSAGE_H
#define DNS_MESSAGE_H 1
@@ -81,8 +81,7 @@
* name = NULL;
* name = dns_message_gettempname(message, &name);
* dns_name_init(name, NULL);
- * result = dns_name_fromtext(name, &source, dns_rootname, ISC_FALSE,
- * buffer);
+ * result = dns_name_fromtext(name, &source, dns_rootname, 0, buffer);
* dns_message_takebuffer(message, &buffer);
* \endcode
*
@@ -137,6 +136,8 @@ typedef int dns_pseudosection_t;
typedef int dns_messagetextflag_t;
#define DNS_MESSAGETEXTFLAG_NOCOMMENTS 0x0001
#define DNS_MESSAGETEXTFLAG_NOHEADERS 0x0002
+#define DNS_MESSAGETEXTFLAG_ONESOA 0x0004
+#define DNS_MESSAGETEXTFLAG_OMITSOA 0x0008
/*
* Dynamic update names for these sections.
@@ -174,6 +175,9 @@ typedef int dns_messagetextflag_t;
additional section. */
#define DNS_MESSAGERENDER_PREFER_AAAA 0x0010 /*%< prefer AAAA records in
additional section. */
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+#define DNS_MESSAGERENDER_FILTER_AAAA 0x0020 /*%< filter AAAA records */
+#endif
typedef struct dns_msgblock dns_msgblock_t;
@@ -369,6 +373,14 @@ dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
* #DNS_MESSAGETEXTFLAG_NOHEADERS is cleared, header lines will
* be emitted.
*
+ * If #DNS_MESSAGETEXTFLAG_ONESOA is set then only print the
+ * first SOA record in the answer section. If
+ * #DNS_MESSAGETEXTFLAG_OMITSOA is set don't print any SOA records
+ * in the answer section. These are useful for suppressing the
+ * display of the second SOA record in a AXFR by setting
+ * #DNS_MESSAGETEXTFLAG_ONESOA on the first message in a AXFR stream
+ * and #DNS_MESSAGETEXTFLAG_OMITSOA on subsequent messages.
+ *
* Requires:
*
*\li 'msg' is a valid message.
diff --git a/contrib/bind9/lib/dns/include/dns/name.h b/contrib/bind9/lib/dns/include/dns/name.h
index 801c9ac..c13a85d 100644
--- a/contrib/bind9/lib/dns/include/dns/name.h
+++ b/contrib/bind9/lib/dns/include/dns/name.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: name.h,v 1.126.332.5 2010-07-09 23:45:55 tbox Exp $ */
+/* $Id: name.h,v 1.137 2011-01-13 04:59:26 tbox Exp $ */
#ifndef DNS_NAME_H
#define DNS_NAME_H 1
@@ -121,21 +121,27 @@ struct dns_name {
#define DNS_NAME_MAGIC ISC_MAGIC('D','N','S','n')
-#define DNS_NAMEATTR_ABSOLUTE 0x0001
-#define DNS_NAMEATTR_READONLY 0x0002
-#define DNS_NAMEATTR_DYNAMIC 0x0004
-#define DNS_NAMEATTR_DYNOFFSETS 0x0008
-#define DNS_NAMEATTR_NOCOMPRESS 0x0010
+#define DNS_NAMEATTR_ABSOLUTE 0x00000001
+#define DNS_NAMEATTR_READONLY 0x00000002
+#define DNS_NAMEATTR_DYNAMIC 0x00000004
+#define DNS_NAMEATTR_DYNOFFSETS 0x00000008
+#define DNS_NAMEATTR_NOCOMPRESS 0x00000010
/*
* Attributes below 0x0100 reserved for name.c usage.
*/
-#define DNS_NAMEATTR_CACHE 0x0100 /*%< Used by resolver. */
-#define DNS_NAMEATTR_ANSWER 0x0200 /*%< Used by resolver. */
-#define DNS_NAMEATTR_NCACHE 0x0400 /*%< Used by resolver. */
-#define DNS_NAMEATTR_CHAINING 0x0800 /*%< Used by resolver. */
-#define DNS_NAMEATTR_CHASE 0x1000 /*%< Used by resolver. */
-#define DNS_NAMEATTR_WILDCARD 0x2000 /*%< Used by server. */
+#define DNS_NAMEATTR_CACHE 0x00000100 /*%< Used by resolver. */
+#define DNS_NAMEATTR_ANSWER 0x00000200 /*%< Used by resolver. */
+#define DNS_NAMEATTR_NCACHE 0x00000400 /*%< Used by resolver. */
+#define DNS_NAMEATTR_CHAINING 0x00000800 /*%< Used by resolver. */
+#define DNS_NAMEATTR_CHASE 0x00001000 /*%< Used by resolver. */
+#define DNS_NAMEATTR_WILDCARD 0x00002000 /*%< Used by server. */
+#define DNS_NAMEATTR_PREREQUISITE 0x00004000 /*%< Used by client. */
+#define DNS_NAMEATTR_UPDATE 0x00008000 /*%< Used by client. */
+#define DNS_NAMEATTR_HASUPDATEREC 0x00010000 /*%< Used by client. */
+/*
+ * Various flags.
+ */
#define DNS_NAME_DOWNCASE 0x0001
#define DNS_NAME_CHECKNAMES 0x0002 /*%< Used by rdata. */
#define DNS_NAME_CHECKNAMESFAIL 0x0004 /*%< Used by rdata. */
@@ -750,7 +756,7 @@ dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
isc_result_t
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
- dns_name_t *origin, unsigned int options,
+ const dns_name_t *origin, unsigned int options,
isc_buffer_t *target);
/*%<
* Convert the textual representation of a DNS name at source
@@ -1139,6 +1145,56 @@ dns_name_format(dns_name_t *name, char *cp, unsigned int size);
*/
isc_result_t
+dns_name_tostring(dns_name_t *source, char **target, isc_mem_t *mctx);
+/*%<
+ * Convert 'name' to string format, allocating sufficient memory to
+ * hold it (free with isc_mem_free()).
+ *
+ * Differs from dns_name_format in that it allocates its own memory.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid name.
+ *\li 'target' is not NULL.
+ *\li '*target' is NULL.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Any error that dns_name_totext() can return.
+ */
+
+isc_result_t
+dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
+ isc_mem_t *mctx);
+isc_result_t
+dns_name_fromstring2(dns_name_t *target, const char *src,
+ const dns_name_t *origin, unsigned int options,
+ isc_mem_t *mctx);
+/*%<
+ * Convert a string to a name and place it in target, allocating memory
+ * as necessary. 'options' has the same semantics as that of
+ * dns_name_fromtext().
+ *
+ * If 'target' has a buffer then the name will be copied into it rather than
+ * memory being allocated.
+ *
+ * Requires:
+ *
+ * \li 'target' is a valid name that is not read-only.
+ * \li 'src' is not NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *
+ *\li Any error that dns_name_fromtext() can return.
+ *
+ *\li Any error that dns_name_dup() can return.
+ */
+
+isc_result_t
dns_name_settotextfilter(dns_name_totextfilter_t proc);
/*%<
* Set / clear a thread specific function 'proc' to be called at the
diff --git a/contrib/bind9/lib/dns/include/dns/ncache.h b/contrib/bind9/lib/dns/include/dns/ncache.h
index 0c1d950..32345cf 100644
--- a/contrib/bind9/lib/dns/include/dns/ncache.h
+++ b/contrib/bind9/lib/dns/include/dns/ncache.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.h,v 1.25.48.4 2010-05-14 23:47:50 tbox Exp $ */
+/* $Id: ncache.h,v 1.29 2010-05-14 23:50:40 tbox Exp $ */
#ifndef DNS_NCACHE_H
#define DNS_NCACHE_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/nsec3.h b/contrib/bind9/lib/dns/include/dns/nsec3.h
index ba808e4..ac0c8f2 100644
--- a/contrib/bind9/lib/dns/include/dns/nsec3.h
+++ b/contrib/bind9/lib/dns/include/dns/nsec3.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2008-2010 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: nsec3.h,v 1.5.48.3 2009-10-06 21:20:18 each Exp $ */
+/* $Id: nsec3.h,v 1.12 2010-05-18 02:38:10 tbox Exp $ */
#ifndef DNS_NSEC3_H
#define DNS_NSEC3_H 1
@@ -110,6 +110,12 @@ 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);
+
+isc_result_t
+dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, dns_ttl_t nsecttl,
+ isc_boolean_t unsecure, dns_rdatatype_t private,
+ dns_diff_t *diff);
/*%<
* Add NSEC3 records for 'name', recording the change in 'diff'.
* Adjust previous NSEC3 records, if any, to reflect the addition.
@@ -130,6 +136,10 @@ dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
* NSEC3PARAM record otherwise OPTOUT will be inherited from the previous
* record in the chain.
*
+ * dns_nsec3_addnsec3sx() is similar to dns_nsec3_addnsec3s() but 'private'
+ * specifies the type of the private rdataset to be checked in addition to
+ * the nsec3param rdataset at the zone apex.
+ *
* Requires:
* 'db' to be valid.
* 'version' to be valid or NULL.
@@ -145,6 +155,10 @@ dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
isc_result_t
dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
dns_diff_t *diff);
+
+isc_result_t
+dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_rdatatype_t private, dns_diff_t *diff);
/*%<
* Remove NSEC3 records for 'name', recording the change in 'diff'.
* Adjust previous NSEC3 records, if any, to reflect the removal.
@@ -156,6 +170,10 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
* to dns_nsec3_addnsec3s(). Unlike dns_nsec3_addnsec3s() updated NSEC3
* records have the OPTOUT flag preserved.
*
+ * dns_nsec3_delnsec3sx() is similar to dns_nsec3_delnsec3s() but 'private'
+ * specifies the type of the private rdataset to be checked in addition to
+ * the nsec3param rdataset at the zone apex.
+ *
* Requires:
* 'db' to be valid.
* 'version' to be valid or NULL.
@@ -167,10 +185,19 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
isc_result_t
dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
isc_boolean_t complete, isc_boolean_t *answer);
+
+isc_result_t
+dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t complete, dns_rdatatype_t private,
+ 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.
*
+ * dns_nsec3_activex() is similar to dns_nsec3_active() but 'private'
+ * specifies the type of the private rdataset to be checked in addition to
+ * the nsec3param rdataset at the zone apex.
+ *
* Requires:
* 'db' to be valid.
* 'version' to be valid or NULL.
@@ -191,6 +218,36 @@ dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
* 'iterationsp' to be non NULL.
*/
+isc_boolean_t
+dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
+ unsigned char *buf, size_t buflen);
+/*%<
+ * Convert a private rdata to a nsec3param rdata.
+ *
+ * Return ISC_TRUE if 'src' could be successfully converted.
+ *
+ * 'buf' should be at least DNS_NSEC3PARAM_BUFFERSIZE in size.
+ */
+
+void
+dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
+ dns_rdatatype_t privatetype,
+ unsigned char *buf, size_t buflen);
+/*%<
+ * Convert a nsec3param rdata to a private rdata.
+ *
+ * 'buf' should be at least src->length + 1 in size.
+ */
+
+isc_result_t
+dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
+ dns_zone_t *zone, dns_diff_t *diff);
+
+/*%<
+ * Mark NSEC3PARAM for deletion.
+ */
+
+
ISC_LANG_ENDDECLS
#endif /* DNS_NSEC3_H */
diff --git a/contrib/bind9/lib/dns/include/dns/peer.h b/contrib/bind9/lib/dns/include/dns/peer.h
index 1f8a42e..a1a3e34 100644
--- a/contrib/bind9/lib/dns/include/dns/peer.h
+++ b/contrib/bind9/lib/dns/include/dns/peer.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: peer.h,v 1.33.118.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: peer.h,v 1.35 2009-01-17 23:47:43 tbox Exp $ */
#ifndef DNS_PEER_H
#define DNS_PEER_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/private.h b/contrib/bind9/lib/dns/include/dns/private.h
new file mode 100644
index 0000000..ffedb5f
--- /dev/null
+++ b/contrib/bind9/lib/dns/include/dns/private.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 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: private.h,v 1.3 2009-10-09 23:48:09 tbox Exp $ */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <dns/types.h>
+#include <dns/db.h>
+
+#ifndef DNS_PRIVATE_H
+#define DNS_PRIVATE_H
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
+ dns_rdatatype_t privatetype,
+ isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3);
+/*%<
+ * Examine the NSEC, NSEC3PARAM and privatetype RRsets at the apex of the
+ * database to determine which of NSEC or NSEC3 chains we are currently
+ * maintaining. In normal operations only one of NSEC or NSEC3 is being
+ * maintained but when we are transitiong between NSEC and NSEC3 we need
+ * to update both sets of chains. If 'privatetype' is zero then the
+ * privatetype RRset will not be examined.
+ *
+ * Requires:
+ * \li 'db' is valid.
+ * \li 'version' is valid or NULL.
+ * \li 'build_nsec' is a pointer to a isc_boolean_t or NULL.
+ * \li 'build_nsec3' is a pointer to a isc_boolean_t or NULL.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS, 'build_nsec' and 'build_nsec3' will be valid.
+ * \li other on error
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/contrib/bind9/lib/dns/include/dns/rbt.h b/contrib/bind9/lib/dns/include/dns/rbt.h
index 72ef2f1..6149e8d 100644
--- a/contrib/bind9/lib/dns/include/dns/rbt.h
+++ b/contrib/bind9/lib/dns/include/dns/rbt.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbt.h,v 1.71.48.3 2009-10-20 05:06:04 marka Exp $ */
+/* $Id: rbt.h,v 1.77 2009-11-04 01:18:19 marka Exp $ */
#ifndef DNS_RBT_H
#define DNS_RBT_H 1
@@ -70,6 +70,12 @@ ISC_LANG_BEGINDECLS
* multiple dns_rbtnode structures will not work.
*/
typedef struct dns_rbtnode dns_rbtnode_t;
+enum {
+ DNS_RBT_NSEC_NORMAL=0, /* in main tree */
+ DNS_RBT_NSEC_HAS_NSEC=1, /* also has node in nsec tree */
+ DNS_RBT_NSEC_NSEC=2, /* in nsec tree */
+ DNS_RBT_NSEC_NSEC3=3 /* in nsec3 tree */
+};
struct dns_rbtnode {
#if DNS_RBT_USEMAGIC
unsigned int magic;
@@ -94,10 +100,7 @@ struct dns_rbtnode {
* 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 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
- * another bit for "attributes", which doesn't yet need any more).
+ * possible future expansion.
*
* In each case below the "range" indicated is what's _necessary_ for
* the bitfield to hold, not what it actually _can_ hold.
@@ -105,8 +108,8 @@ struct dns_rbtnode {
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 nsec3 : 1; /*%< range is 0..1 */
+ unsigned int attributes : 3; /*%< range is 0..2 */
+ unsigned int nsec : 2; /*%< range is 0..3 */
unsigned int namelen : 8; /*%< range is 1..255 */
unsigned int offsetlen : 8; /*%< range is 1..128 */
unsigned int oldnamelen : 8; /*%< range is 1..255 */
@@ -909,7 +912,7 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
} 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_refdestroy(node) REQUIRE((node)->references == 0)
#define dns_rbtnode_refcurrent(node) ((node)->references)
#define dns_rbtnode_refincrement0(node, refs) \
do { \
diff --git a/contrib/bind9/lib/dns/include/dns/rdata.h b/contrib/bind9/lib/dns/include/dns/rdata.h
index 1674b0c..b70a353 100644
--- a/contrib/bind9/lib/dns/include/dns/rdata.h
+++ b/contrib/bind9/lib/dns/include/dns/rdata.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdata.h,v 1.70.120.3 2009-02-16 00:29:27 marka Exp $ */
+/* $Id: rdata.h,v 1.77 2009-12-04 21:09:33 marka Exp $ */
#ifndef DNS_RDATA_H
#define DNS_RDATA_H 1
@@ -95,6 +95,7 @@
#include <dns/types.h>
#include <dns/name.h>
+#include <dns/message.h>
ISC_LANG_BEGINDECLS
@@ -124,9 +125,27 @@ struct dns_rdata {
#define DNS_RDATA_INIT { NULL, 0, 0, 0, 0, {(void*)(-1), (void *)(-1)}}
+#define DNS_RDATA_CHECKINITIALIZED
+#ifdef DNS_RDATA_CHECKINITIALIZED
+#define DNS_RDATA_INITIALIZED(rdata) \
+ ((rdata)->data == NULL && (rdata)->length == 0 && \
+ (rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \
+ !ISC_LINK_LINKED((rdata), link))
+#else
+#ifdef ISC_LIST_CHECKINIT
+#define DNS_RDATA_INITIALIZED(rdata) \
+ (!ISC_LINK_LINKED((rdata), link))
+#else
+#define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE
+#endif
+#endif
+
#define DNS_RDATA_UPDATE 0x0001 /*%< update pseudo record. */
#define DNS_RDATA_OFFLINE 0x0002 /*%< RRSIG has a offline key. */
+#define DNS_RDATA_VALIDFLAGS(rdata) \
+ (((rdata)->flags & ~(DNS_RDATA_UPDATE|DNS_RDATA_OFFLINE)) == 0)
+
/*
* Flags affecting rdata formatting style. Flags 0xFFFF0000
* are used by masterfile-level formatting and defined elsewhere.
@@ -201,6 +220,25 @@ dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2);
*\li > 0 'rdata1' is greater than 'rdata2'
*/
+int
+dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2);
+/*%<
+ * dns_rdata_casecompare() is similar to dns_rdata_compare() but also
+ * compares domain names case insensitively in known rdata types that
+ * are treated as opaque data by dns_rdata_compare().
+ *
+ * Requires:
+ *
+ *\li 'rdata1' is a valid, non-empty rdata
+ *
+ *\li 'rdata2' is a valid, non-empty rdata
+ *
+ * Returns:
+ *\li < 0 'rdata1' is less than 'rdata2'
+ *\li 0 'rdata1' is equal to 'rdata2'
+ *\li > 0 'rdata1' is greater than 'rdata2'
+ */
+
/***
*** Conversions
***/
@@ -698,6 +736,21 @@ dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad);
* 'bad' to be NULL or valid.
*/
+void
+dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type);
+
+void
+dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type);
+
+void
+dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type);
+
+void
+dns_rdata_makedelete(dns_rdata_t *rdata);
+
+const char *
+dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section);
+
ISC_LANG_ENDDECLS
#endif /* DNS_RDATA_H */
diff --git a/contrib/bind9/lib/dns/include/dns/rdataset.h b/contrib/bind9/lib/dns/include/dns/rdataset.h
index a8c3e9c..7f50c12 100644
--- a/contrib/bind9/lib/dns/include/dns/rdataset.h
+++ b/contrib/bind9/lib/dns/include/dns/rdataset.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataset.h,v 1.65.50.4.6.3 2011-06-21 20:13:23 each Exp $ */
+/* $Id: rdataset.h,v 1.69.270.3 2011-06-21 20:15:54 each Exp $ */
#ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/request.h b/contrib/bind9/lib/dns/include/dns/request.h
index 8808c0a..f2db1031b 100644
--- a/contrib/bind9/lib/dns/include/dns/request.h
+++ b/contrib/bind9/lib/dns/include/dns/request.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010 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.h,v 1.27.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: request.h,v 1.31 2010-03-04 23:50:34 tbox Exp $ */
#ifndef DNS_REQUEST_H
#define DNS_REQUEST_H 1
@@ -47,6 +47,7 @@
#include <dns/types.h>
#define DNS_REQUESTOPT_TCP 0x00000001U
+#define DNS_REQUESTOPT_CASE 0x00000002U
typedef struct dns_requestevent {
ISC_EVENT_COMMON(struct dns_requestevent);
@@ -175,6 +176,9 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
* #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request
* will timeout after 'timeout' seconds.
*
+ *\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive
+ * compression.
+ *
*\li When the request completes, successfully, due to a timeout, or
* because it was canceled, a completion event will be sent to 'task'.
*
@@ -227,6 +231,9 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
* will timeout after 'timeout' seconds. UDP requests will be resent
* at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero.
*
+ *\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive
+ * compression.
+ *
*\li When the request completes, successfully, due to a timeout, or
* because it was canceled, a completion event will be sent to 'task'.
*
diff --git a/contrib/bind9/lib/dns/include/dns/resolver.h b/contrib/bind9/lib/dns/include/dns/resolver.h
index c9034bf..2db1770 100644
--- a/contrib/bind9/lib/dns/include/dns/resolver.h
+++ b/contrib/bind9/lib/dns/include/dns/resolver.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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: resolver.h,v 1.60.56.5 2010-02-25 10:56:41 tbox Exp $ */
+/* $Id: resolver.h,v 1.67.86.1.2.1 2011-06-02 23:47:36 tbox Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
@@ -81,6 +81,7 @@ typedef struct dns_fetchevent {
dns_fixedname_t foundname;
isc_sockaddr_t * client;
dns_messageid_t id;
+ isc_result_t vresult;
} dns_fetchevent_t;
/*
@@ -179,7 +180,7 @@ dns_resolver_freeze(dns_resolver_t *res);
*
* Requires:
*
- *\li 'res' is a valid, unfrozen resolver.
+ *\li 'res' is a valid resolver.
*
* Ensures:
*
@@ -491,6 +492,27 @@ dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
isc_boolean_t
dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name);
+
+void
+dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds);
+/*%<
+ * Set the length of time the resolver will work on a query, in seconds.
+ *
+ * If timeout is 0, the default timeout will be applied.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ */
+
+unsigned int
+dns_resolver_gettimeout(dns_resolver_t *resolver);
+/*%<
+ * Get the current length of time the resolver will work on a query, in seconds.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ */
+
void
dns_resolver_setclientsperquery(dns_resolver_t *resolver,
isc_uint32_t min, isc_uint32_t max);
diff --git a/contrib/bind9/lib/dns/include/dns/result.h b/contrib/bind9/lib/dns/include/dns/result.h
index 74b84d6..adc1215 100644
--- a/contrib/bind9/lib/dns/include/dns/result.h
+++ b/contrib/bind9/lib/dns/include/dns/result.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: result.h,v 1.116.48.2 2010-02-25 10:56:41 tbox Exp $ */
+/* $Id: result.h,v 1.122 2011-01-11 23:47:13 tbox Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
@@ -148,10 +148,11 @@
#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_NOTMASTER (ISC_RESULTCLASS_DNS + 105)
+#define DNS_R_NOTMASTER (ISC_RESULTCLASS_DNS + 105)
#define DNS_R_BROKENCHAIN (ISC_RESULTCLASS_DNS + 106)
+#define DNS_R_EXPIRED (ISC_RESULTCLASS_DNS + 107)
-#define DNS_R_NRESULTS 107 /*%< Number of results */
+#define DNS_R_NRESULTS 108 /*%< Number of results */
/*
* DNS wire format rcodes.
diff --git a/contrib/bind9/lib/dns/include/dns/rpz.h b/contrib/bind9/lib/dns/include/dns/rpz.h
new file mode 100644
index 0000000..404f517
--- /dev/null
+++ b/contrib/bind9/lib/dns/include/dns/rpz.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2011 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: rpz.h,v 1.3 2011-01-13 04:59:26 tbox Exp $ */
+
+#ifndef DNS_RPZ_H
+#define DNS_RPZ_H 1
+
+#include <isc/lang.h>
+
+#include <dns/fixedname.h>
+#include <dns/rdata.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define DNS_RPZ_IP_ZONE "rpz-ip"
+#define DNS_RPZ_NSIP_ZONE "rpz-nsip"
+#define DNS_RPZ_NSDNAME_ZONE "rpz-nsdname"
+
+typedef isc_uint8_t dns_rpz_cidr_bits_t;
+
+typedef enum {
+ DNS_RPZ_TYPE_BAD,
+ DNS_RPZ_TYPE_QNAME,
+ DNS_RPZ_TYPE_IP,
+ DNS_RPZ_TYPE_NSIP,
+ DNS_RPZ_TYPE_NSDNAME
+} dns_rpz_type_t;
+
+/*
+ * Require DNS_RPZ_POLICY_NO_OP < DNS_RPZ_POLICY_NXDOMAIN <
+ * DNS_RPZ_POLICY_NODATA < DNS_RPZ_POLICY_CNAME.
+ */
+typedef enum {
+ DNS_RPZ_POLICY_GIVEN = 0, /* 'given': what something else says */
+ DNS_RPZ_POLICY_NO_OP = 1, /* 'no-op': do not rewrite */
+ DNS_RPZ_POLICY_NXDOMAIN = 2, /* 'nxdomain': answer with NXDOMAIN */
+ DNS_RPZ_POLICY_NODATA = 3, /* 'nodata': answer with ANCOUNT=0 */
+ DNS_RPZ_POLICY_CNAME = 4, /* 'cname x': answer with x's rrsets */
+ DNS_RPZ_POLICY_RECORD = 5,
+ DNS_RPZ_POLICY_MISS,
+ DNS_RPZ_POLICY_ERROR
+} dns_rpz_policy_t;
+
+/*
+ * Specify a response policy zone.
+ */
+typedef struct dns_rpz_zone dns_rpz_zone_t;
+
+struct dns_rpz_zone {
+ ISC_LINK(dns_rpz_zone_t) link;
+ int num;
+ dns_name_t origin; /* Policy zone name */
+ dns_name_t nsdname; /* RPZ_NSDNAME_ZONE.origin */
+ dns_rpz_policy_t policy; /* RPZ_POLICY_GIVEN or override */
+ dns_name_t cname; /* override name for
+ RPZ_POLICY_CNAME */
+};
+
+/*
+ * Radix trees for response policy IP addresses.
+ */
+typedef struct dns_rpz_cidr dns_rpz_cidr_t;
+
+/*
+ * context for finding the best policy
+ */
+typedef struct {
+ unsigned int state;
+# define DNS_RPZ_REWRITTEN 0x0001
+# define DNS_RPZ_DONE_QNAME 0x0002
+# define DNS_RPZ_DONE_A 0x0004
+# define DNS_RPZ_RECURSING 0x0008
+# define DNS_RPZ_HAVE_IP 0x0010
+# define DNS_RPZ_HAVE_NSIPv4 0x0020
+# define DNS_RPZ_HAVE_NSIPv6 0x0040
+# define DNS_RPZ_HAD_NSDNAME 0x0080
+ /*
+ * Best match so far.
+ */
+ struct {
+ dns_rpz_type_t type;
+ dns_rpz_zone_t *rpz;
+ dns_rpz_cidr_bits_t prefix;
+ dns_rpz_policy_t policy;
+ dns_ttl_t ttl;
+ isc_result_t result;
+ dns_zone_t *zone;
+ dns_db_t *db;
+ dns_dbnode_t *node;
+ dns_rdataset_t *rdataset;
+ } m;
+ /*
+ * State for chasing NS names and addresses including recursion.
+ */
+ struct {
+ unsigned int label;
+ dns_db_t *db;
+ dns_rdataset_t *ns_rdataset;
+ dns_rdatatype_t r_type;
+ isc_result_t r_result;
+ dns_rdataset_t *r_rdataset;
+ } ns;
+ /*
+ * State of real query while recursing for NSIP or NSDNAME.
+ */
+ struct {
+ isc_result_t result;
+ isc_boolean_t is_zone;
+ isc_boolean_t authoritative;
+ dns_zone_t *zone;
+ dns_db_t *db;
+ dns_dbnode_t *node;
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_rdatatype_t qtype;
+ } q;
+ dns_name_t *qname;
+ dns_name_t *r_name;
+ dns_name_t *fname;
+ dns_fixedname_t _qnamef;
+ dns_fixedname_t _r_namef;
+ dns_fixedname_t _fnamef;
+} dns_rpz_st_t;
+
+#define DNS_RPZ_TTL_DEFAULT 5
+
+/*
+ * So various response policy zone messages can be turned up or down.
+ */
+#define DNS_RPZ_ERROR_LEVEL ISC_LOG_WARNING
+#define DNS_RPZ_INFO_LEVEL ISC_LOG_INFO
+#define DNS_RPZ_DEBUG_LEVEL1 ISC_LOG_DEBUG(1)
+#define DNS_RPZ_DEBUG_LEVEL2 ISC_LOG_DEBUG(2)
+
+const char *
+dns_rpz_type2str(dns_rpz_type_t type);
+
+dns_rpz_policy_t
+dns_rpz_str2policy(const char *str);
+
+void
+dns_rpz_set_need(isc_boolean_t need);
+
+isc_boolean_t
+dns_rpz_needed(void);
+
+void
+dns_rpz_cidr_free(dns_rpz_cidr_t **cidr);
+
+void
+dns_rpz_view_destroy(dns_view_t *view);
+
+isc_result_t
+dns_rpz_new_cidr(isc_mem_t *mctx, dns_name_t *origin,
+ dns_rpz_cidr_t **rbtdb_cidr);
+void
+dns_rpz_enabled(dns_rpz_cidr_t *cidr, dns_rpz_st_t *st);
+
+void
+dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name);
+
+void
+dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name);
+
+isc_result_t
+dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr,
+ dns_rpz_type_t type, dns_name_t *canon_name,
+ dns_name_t *search_name, dns_rpz_cidr_bits_t *prefix);
+
+dns_rpz_policy_t
+dns_rpz_decode_cname(dns_rdataset_t *, dns_name_t *selfname);
+
+#endif /* DNS_RPZ_H */
+
diff --git a/contrib/bind9/lib/dns/include/dns/rriterator.h b/contrib/bind9/lib/dns/include/dns/rriterator.h
new file mode 100644
index 0000000..0087349
--- /dev/null
+++ b/contrib/bind9/lib/dns/include/dns/rriterator.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 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: rriterator.h,v 1.2 2009-06-30 02:52:32 each Exp $ */
+
+#ifndef DNS_RRITERATOR_H
+#define DNS_RRITERATOR_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/rriterator.h
+ * \brief
+ * Functions for "walking" a zone database, visiting each RR or RRset in turn.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/ondestroy.h>
+#include <isc/stdtime.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Types
+ *****/
+
+/*%
+ * A dns_rriterator_t is an iterator that iterates over an entire database,
+ * returning one RR at a time, in some arbitrary order.
+ */
+
+typedef struct dns_rriterator {
+ unsigned int magic;
+ isc_result_t result;
+ dns_db_t *db;
+ dns_dbiterator_t *dbit;
+ dns_dbversion_t *ver;
+ isc_stdtime_t now;
+ dns_dbnode_t *node;
+ dns_fixedname_t fixedname;
+ dns_rdatasetiter_t *rdatasetit;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata;
+} dns_rriterator_t;
+
+#define RRITERATOR_MAGIC ISC_MAGIC('R', 'R', 'I', 't')
+#define VALID_RRITERATOR(m) ISC_MAGIC_VALID(m, RRITERATOR_MAGIC)
+
+isc_result_t
+dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db,
+ dns_dbversion_t *ver, isc_stdtime_t now);
+
+isc_result_t
+dns_rriterator_first(dns_rriterator_t *it);
+
+isc_result_t
+dns_rriterator_nextrrset(dns_rriterator_t *it);
+
+isc_result_t
+dns_rriterator_next(dns_rriterator_t *it);
+
+void
+dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name,
+ isc_uint32_t *ttl, dns_rdataset_t **rdataset,
+ dns_rdata_t **rdata);
+
+void
+dns_rriterator_pause(dns_rriterator_t *it);
+
+void
+dns_rriterator_destroy(dns_rriterator_t *it);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RRITERATOR_H */
diff --git a/contrib/bind9/lib/dns/include/dns/sdb.h b/contrib/bind9/lib/dns/include/dns/sdb.h
index 18995ed..5744837 100644
--- a/contrib/bind9/lib/dns/include/dns/sdb.h
+++ b/contrib/bind9/lib/dns/include/dns/sdb.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdb.h,v 1.21.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: sdb.h,v 1.23 2009-01-17 23:47:43 tbox Exp $ */
#ifndef DNS_SDB_H
#define DNS_SDB_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/sdlz.h b/contrib/bind9/lib/dns/include/dns/sdlz.h
index 9d2a0ed..b917cc0 100644
--- a/contrib/bind9/lib/dns/include/dns/sdlz.h
+++ b/contrib/bind9/lib/dns/include/dns/sdlz.h
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005-2007, 2009-2011 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.h,v 1.7.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: sdlz.h,v 1.14 2011-01-13 08:50:29 tbox Exp $ */
/*! \file dns/sdlz.h */
@@ -74,11 +74,10 @@ typedef struct dns_sdlzlookup dns_sdlzlookup_t;
/* A simple DLZ database traversal in progress. */
typedef struct dns_sdlzallnodes dns_sdlzallnodes_t;
-
-typedef isc_result_t
-(*dns_sdlzallnodesfunc_t)(const char *zone, void *driverarg, void *dbdata,
- dns_sdlzallnodes_t *allnodes);
-
+typedef isc_result_t (*dns_sdlzallnodesfunc_t)(const char *zone,
+ void *driverarg,
+ void *dbdata,
+ dns_sdlzallnodes_t *allnodes);
/*%<
* Method prototype. Drivers implementing the SDLZ interface may
* supply an all nodes method. This method is called when the DNS
@@ -92,9 +91,9 @@ typedef isc_result_t
* does not have to implement an all nodes method.
*/
-typedef isc_result_t
-(*dns_sdlzallowzonexfr_t)(void *driverarg, void *dbdata, const char *name,
- const char *client);
+typedef isc_result_t (*dns_sdlzallowzonexfr_t)(void *driverarg,
+ void *dbdata, const char *name,
+ const char *client);
/*%<
* Method prototype. Drivers implementing the SDLZ interface may
@@ -117,9 +116,9 @@ typedef isc_result_t
* error.
*/
-typedef isc_result_t
-(*dns_sdlzauthorityfunc_t)(const char *zone, void *driverarg, void *dbdata,
- dns_sdlzlookup_t *lookup);
+typedef isc_result_t (*dns_sdlzauthorityfunc_t)(const char *zone,
+ void *driverarg, void *dbdata,
+ dns_sdlzlookup_t *lookup);
/*%<
* Method prototype. Drivers implementing the SDLZ interface may
@@ -131,9 +130,9 @@ typedef isc_result_t
* method.
*/
-typedef isc_result_t
-(*dns_sdlzcreate_t)(const char *dlzname, unsigned int argc, char *argv[],
- void *driverarg, void **dbdata);
+typedef isc_result_t (*dns_sdlzcreate_t)(const char *dlzname,
+ unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata);
/*%<
* Method prototype. Drivers implementing the SDLZ interface may
@@ -142,8 +141,7 @@ typedef isc_result_t
* does not have to implement a create method.
*/
-typedef void
-(*dns_sdlzdestroy_t)(void *driverarg, void *dbdata);
+typedef void (*dns_sdlzdestroy_t)(void *driverarg, void *dbdata);
/*%<
* Method prototype. Drivers implementing the SDLZ interface may
@@ -198,6 +196,87 @@ typedef isc_result_t
* lookup method.
*/
+typedef isc_result_t (*dns_sdlznewversion_t)(const char *zone,
+ void *driverarg, void *dbdata,
+ void **versionp);
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface may
+ * supply a newversion method. This method is called to start a
+ * write transaction on a zone and should only be implemented by
+ * writeable backends.
+ * When implemented, the driver should create a new transaction, and
+ * fill *versionp with a pointer to the transaction state. The
+ * closeversion function will be called to close the transaction.
+ */
+
+typedef void (*dns_sdlzcloseversion_t)(const char *zone, isc_boolean_t commit,
+ void *driverarg, void *dbdata,
+ void **versionp);
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface must
+ * supply a closeversion method if they supply a newversion method.
+ * When implemented, the driver should close the given transaction,
+ * committing changes if 'commit' is ISC_TRUE. If 'commit' is not true
+ * then all changes should be discarded and the database rolled back.
+ * If the call is successful then *versionp should be set to NULL
+ */
+
+typedef isc_result_t (*dns_sdlzconfigure_t)(dns_view_t *view, void *driverarg,
+ void *dbdata);
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface may
+ * supply a configure method. When supplied, it will be called
+ * immediately after the create method to give the driver a chance
+ * to configure writeable zones
+ */
+
+
+typedef isc_boolean_t (*dns_sdlzssumatch_t)(const char *signer,
+ const char *name,
+ const char *tcpaddr,
+ const char *type,
+ const char *key,
+ isc_uint32_t keydatalen,
+ unsigned char *keydata,
+ void *driverarg,
+ void *dbdata);
+
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface may
+ * supply a ssumatch method. If supplied, then ssumatch will be
+ * called to authorize any zone updates. The driver should return
+ * ISC_TRUE to allow the update, and ISC_FALSE to deny it. For a DLZ
+ * controlled zone, this is the only access control on updates.
+ */
+
+
+typedef isc_result_t (*dns_sdlzmodrdataset_t)(const char *name,
+ const char *rdatastr,
+ void *driverarg, void *dbdata,
+ void *version);
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface may
+ * supply addrdataset and subtractrdataset methods. If supplied, then these
+ * will be called when rdatasets are added/subtracted during
+ * updates. The version parameter comes from a call to the sdlz
+ * newversion() method from the driver. The rdataset parameter is a
+ * linearise string representation of the rdataset change. The format
+ * is the same as used by dig when displaying records. The fields are
+ * tab delimited.
+ */
+
+typedef isc_result_t (*dns_sdlzdelrdataset_t)(const char *name,
+ const char *type,
+ void *driverarg, void *dbdata,
+ void *version);
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface may
+ * supply a delrdataset method. If supplied, then this
+ * function will be called when rdatasets are deleted during
+ * updates. The call should remove all rdatasets of the given type for
+ * the specified name.
+ */
+
typedef struct dns_sdlzmethods {
dns_sdlzcreate_t create;
dns_sdlzdestroy_t destroy;
@@ -206,6 +285,13 @@ typedef struct dns_sdlzmethods {
dns_sdlzauthorityfunc_t authority;
dns_sdlzallnodesfunc_t allnodes;
dns_sdlzallowzonexfr_t allowzonexfr;
+ dns_sdlznewversion_t newversion;
+ dns_sdlzcloseversion_t closeversion;
+ dns_sdlzconfigure_t configure;
+ dns_sdlzssumatch_t ssumatch;
+ dns_sdlzmodrdataset_t addrdataset;
+ dns_sdlzmodrdataset_t subtractrdataset;
+ dns_sdlzdelrdataset_t delrdataset;
} dns_sdlzmethods_t;
isc_result_t
@@ -261,6 +347,14 @@ dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
*/
+isc_result_t
+dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
+ dns_name_t *name, dns_db_t **dbp);
+/*%<
+ * Create the database pointers for a writeable SDLZ zone
+ */
+
+
ISC_LANG_ENDDECLS
#endif /* SDLZ_H */
diff --git a/contrib/bind9/lib/dns/include/dns/secalg.h b/contrib/bind9/lib/dns/include/dns/secalg.h
index 0eb0333..49613d5 100644
--- a/contrib/bind9/lib/dns/include/dns/secalg.h
+++ b/contrib/bind9/lib/dns/include/dns/secalg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: secalg.h,v 1.19 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: secalg.h,v 1.21 2009-10-12 23:48:02 tbox Exp $ */
#ifndef DNS_SECALG_H
#define DNS_SECALG_H 1
@@ -66,6 +66,13 @@ dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target);
*\li ISC_R_NOSPACE target buffer is too small
*/
+#define DNS_SECALG_FORMATSIZE 20
+void
+dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size);
+/*%<
+ * Wrapper for dns_secalg_totext(), writing text into 'cp'
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_SECALG_H */
diff --git a/contrib/bind9/lib/dns/include/dns/soa.h b/contrib/bind9/lib/dns/include/dns/soa.h
index c1ad706..6ebf61d 100644
--- a/contrib/bind9/lib/dns/include/dns/soa.h
+++ b/contrib/bind9/lib/dns/include/dns/soa.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: soa.h,v 1.9 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: soa.h,v 1.12 2009-09-10 01:47:09 each Exp $ */
#ifndef DNS_SOA_H
#define DNS_SOA_H 1
@@ -40,6 +40,28 @@
ISC_LANG_BEGINDECLS
+#define DNS_SOA_BUFFERSIZE ((2 * DNS_NAME_MAXWIRE) + (4 * 5))
+
+isc_result_t
+dns_soa_buildrdata(dns_name_t *origin, dns_name_t *contact,
+ dns_rdataclass_t rdclass,
+ isc_uint32_t serial, isc_uint32_t refresh,
+ isc_uint32_t retry, isc_uint32_t expire,
+ isc_uint32_t minimum, unsigned char *buffer,
+ dns_rdata_t *rdata);
+/*%<
+ * Build the rdata of an SOA record.
+ *
+ * Requires:
+ *\li buffer Points to a temporary buffer of at least
+ * DNS_SOA_BUFFERSIZE bytes.
+ *\li rdata Points to an initialized dns_rdata_t.
+ *
+ * Ensures:
+ * \li *rdata Contains a valid SOA rdata. The 'data' member
+ * refers to 'buffer'.
+ */
+
isc_uint32_t
dns_soa_getserial(dns_rdata_t *rdata);
isc_uint32_t
diff --git a/contrib/bind9/lib/dns/include/dns/ssu.h b/contrib/bind9/lib/dns/include/dns/ssu.h
index 686928b..5d6c178 100644
--- a/contrib/bind9/lib/dns/include/dns/ssu.h
+++ b/contrib/bind9/lib/dns/include/dns/ssu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2010, 2011 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: ssu.h,v 1.24 2008-01-18 23:46:58 tbox Exp $ */
+/* $Id: ssu.h,v 1.28 2011-01-06 23:47:00 tbox Exp $ */
#ifndef DNS_SSU_H
#define DNS_SSU_H 1
@@ -25,6 +25,7 @@
#include <isc/lang.h>
#include <dns/types.h>
+#include <dst/dst.h>
ISC_LANG_BEGINDECLS
@@ -40,7 +41,9 @@ ISC_LANG_BEGINDECLS
#define DNS_SSUMATCHTYPE_SUBDOMAINKRB5 9
#define DNS_SSUMATCHTYPE_TCPSELF 10
#define DNS_SSUMATCHTYPE_6TO4SELF 11
-#define DNS_SSUMATCHTYPE_MAX 11 /* max value */
+#define DNS_SSUMATCHTYPE_EXTERNAL 12
+#define DNS_SSUMATCHTYPE_DLZ 13
+#define DNS_SSUMATCHTYPE_MAX 12 /* max value */
isc_result_t
dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table);
@@ -57,6 +60,16 @@ dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table);
*\li ISC_R_NOMEMORY
*/
+isc_result_t
+dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep,
+ dns_dlzdb_t *dlzdatabase);
+/*%<
+ * Create an SSU table that contains a dlzdatabase pointer, and a
+ * single rule with matchtype DNS_SSUMATCHTYPE_DLZ. This type of SSU
+ * table is used by writeable DLZ drivers to offload authorization for
+ * updates to the driver.
+ */
+
void
dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp);
/*%<
@@ -120,7 +133,7 @@ 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, isc_netaddr_t *tcpaddr,
- dns_rdatatype_t type);
+ dns_rdatatype_t type, const dst_key_t *key);
/*%<
* Checks that the attempted update of (name, type) is allowed according
* to the rules specified in the simple-secure-update rule table. If
@@ -184,6 +197,16 @@ isc_result_t dns_ssutable_nextrule(dns_ssurule_t *rule,
*\li #ISC_R_NOMORE
*/
+
+/*%<
+ * Check a policy rule via an external application
+ */
+isc_boolean_t
+dns_ssu_external_match(dns_name_t *identity, dns_name_t *signer,
+ dns_name_t *name, isc_netaddr_t *tcpaddr,
+ dns_rdatatype_t type, const dst_key_t *key,
+ isc_mem_t *mctx);
+
ISC_LANG_ENDDECLS
#endif /* DNS_SSU_H */
diff --git a/contrib/bind9/lib/dns/include/dns/stats.h b/contrib/bind9/lib/dns/include/dns/stats.h
index 853c1e9..c19b0c7 100644
--- a/contrib/bind9/lib/dns/include/dns/stats.h
+++ b/contrib/bind9/lib/dns/include/dns/stats.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: stats.h,v 1.18.56.2 2009-01-29 23:47:44 tbox Exp $ */
+/* $Id: stats.h,v 1.20 2009-01-27 23:47:54 tbox Exp $ */
#ifndef DNS_STATS_H
#define DNS_STATS_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/tkey.h b/contrib/bind9/lib/dns/include/dns/tkey.h
index cb1fe0e..f9e34f8 100644
--- a/contrib/bind9/lib/dns/include/dns/tkey.h
+++ b/contrib/bind9/lib/dns/include/dns/tkey.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tkey.h,v 1.26.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: tkey.h,v 1.32 2011-01-08 23:47:01 tbox Exp $ */
#ifndef DNS_TKEY_H
#define DNS_TKEY_H 1
@@ -44,6 +44,7 @@ struct dns_tkeyctx {
gss_cred_id_t gsscred;
isc_mem_t *mctx;
isc_entropy_t *ectx;
+ char *gssapi_keytab;
};
isc_result_t
@@ -123,7 +124,8 @@ 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,
isc_buffer_t *intoken, isc_uint32_t lifetime,
- gss_ctx_id_t *context, isc_boolean_t win2k);
+ gss_ctx_id_t *context, isc_boolean_t win2k,
+ isc_mem_t *mctx, char **err_message);
/*%<
* Builds a query containing a TKEY that will generate a GSSAPI context.
* The key is requested to have the specified lifetime (in seconds).
@@ -141,6 +143,7 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
*\li ISC_R_SUCCESS msg was successfully updated to include the
* query to be sent
*\li other an error occurred while building the message
+ *\li *err_message optional error message
*/
@@ -187,7 +190,7 @@ isc_result_t
dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dns_name_t *gname, gss_ctx_id_t *context,
isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
- dns_tsig_keyring_t *ring);
+ dns_tsig_keyring_t *ring, char **err_message);
/*%<
* XXX
*/
@@ -211,12 +214,11 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
* component of the query or response
*/
-
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);
+ isc_boolean_t win2k, char **err_message);
/*
* Client side negotiation of GSS-TSIG. Process the response
diff --git a/contrib/bind9/lib/dns/include/dns/tsec.h b/contrib/bind9/lib/dns/include/dns/tsec.h
new file mode 100644
index 0000000..698634e
--- /dev/null
+++ b/contrib/bind9/lib/dns/include/dns/tsec.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2009, 2010 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: tsec.h,v 1.6 2010-12-09 00:54:34 marka Exp $ */
+
+#ifndef DNS_TSEC_H
+#define DNS_TSEC_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ *
+ * \brief
+ * The TSEC (Transaction Security) module is an abstraction layer for managing
+ * DNS transaction mechanisms such as TSIG or SIG(0). A TSEC structure is a
+ * mechanism-independent object containing key information specific to the
+ * mechanism, and is expected to be used as an argument to other modules
+ * that use transaction security in a mechanism-independent manner.
+ *
+ * MP:
+ *\li A TSEC structure is expected to be thread-specific. No inter-thread
+ * synchronization is ensured in multiple access to a single TSEC
+ * structure.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li This module does not handle any low-level data directly, and so no
+ * security issue specific to this module is anticipated.
+ */
+
+#include <dns/types.h>
+
+#include <dst/dst.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * Transaction security types.
+ */
+typedef enum {
+ dns_tsectype_none,
+ dns_tsectype_tsig,
+ dns_tsectype_sig0
+} dns_tsectype_t;
+
+isc_result_t
+dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key,
+ dns_tsec_t **tsecp);
+/*%<
+ * Create a TSEC structure and stores a type-dependent key structure in it.
+ * For a TSIG key (type is dns_tsectype_tsig), dns_tsec_create() creates a
+ * TSIG key structure from '*key' and keeps it in the structure. For other
+ * types, this function simply retains '*key' in the structure. In either
+ * case, the ownership of '*key' is transferred to the TSEC module; the caller
+ * must not modify or destroy it after the call to dns_tsec_create().
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'type' is a valid value of dns_tsectype_t (see above).
+ *
+ *\li 'key' is a valid key.
+ *
+ *\li tsecp != NULL && *tsecp == NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ */
+
+void
+dns_tsec_destroy(dns_tsec_t **tsecp);
+/*%<
+ * Destroy the TSEC structure. The stored key is also detached or destroyed.
+ *
+ * Requires
+ *
+ *\li '*tsecp' is a valid TSEC structure.
+ *
+ * Ensures
+ *
+ *\li *tsecp == NULL.
+ *
+ */
+
+dns_tsectype_t
+dns_tsec_gettype(dns_tsec_t *tsec);
+/*%<
+ * Return the TSEC type of '*tsec'.
+ *
+ * Requires
+ *
+ *\li 'tsec' is a valid TSEC structure.
+ *
+ */
+
+void
+dns_tsec_getkey(dns_tsec_t *tsec, void *keyp);
+/*%<
+ * Return the TSEC key of '*tsec' in '*keyp'.
+ *
+ * Requires
+ *
+ *\li keyp != NULL
+ *
+ * Ensures
+ *
+ *\li *tsecp points to a valid key structure depending on the TSEC type.
+ */
+
+#endif /* DNS_TSEC_H */
diff --git a/contrib/bind9/lib/dns/include/dns/tsig.h b/contrib/bind9/lib/dns/include/dns/tsig.h
index 5161fb3..ef9423b 100644
--- a/contrib/bind9/lib/dns/include/dns/tsig.h
+++ b/contrib/bind9/lib/dns/include/dns/tsig.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2011 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: tsig.h,v 1.51.332.4 2010-12-09 01:12:55 marka Exp $ */
+/* $Id: tsig.h,v 1.59 2011-01-11 23:47:13 tbox Exp $ */
#ifndef DNS_TSIG_H
#define DNS_TSIG_H 1
@@ -25,6 +25,7 @@
#include <isc/lang.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>
+#include <isc/stdio.h>
#include <isc/stdtime.h>
#include <dns/types.h>
@@ -69,6 +70,7 @@ struct dns_tsig_keyring {
unsigned int generated;
unsigned int maxgenerated;
ISC_LIST(dns_tsigkey_t) lru;
+ unsigned int references;
};
struct dns_tsigkey {
@@ -253,9 +255,30 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp);
*\li #ISC_R_NOMEMORY
*/
+isc_result_t
+dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
+ dns_tsigkey_t *tkey);
+/*%<
+ * Place a TSIG key onto a key ring.
+ *
+ * Requires:
+ *\li 'ring', 'name' and 'tkey' are not NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li Any other value indicates failure.
+ */
+
+
+void
+dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target);
void
-dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp);
+dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp);
+
+isc_result_t
+dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp);
+
/*%<
* Destroy a TSIG key ring.
*
@@ -263,6 +286,9 @@ dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp);
*\li 'ringp' is not NULL
*/
+void
+dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp);
+
ISC_LANG_ENDDECLS
#endif /* DNS_TSIG_H */
diff --git a/contrib/bind9/lib/dns/include/dns/types.h b/contrib/bind9/lib/dns/include/dns/types.h
index 4e4c195..dc02c86 100644
--- a/contrib/bind9/lib/dns/include/dns/types.h
+++ b/contrib/bind9/lib/dns/include/dns/types.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: types.h,v 1.130.50.7 2010-05-14 23:47:50 tbox Exp $ */
+/* $Id: types.h,v 1.143 2010-12-08 02:46:16 marka Exp $ */
#ifndef DNS_TYPES_H
#define DNS_TYPES_H 1
@@ -44,6 +44,10 @@ typedef struct dns_adbentry dns_adbentry_t;
typedef struct dns_adbfind dns_adbfind_t;
typedef ISC_LIST(dns_adbfind_t) dns_adbfindlist_t;
typedef struct dns_byaddr dns_byaddr_t;
+typedef struct dns_client dns_client_t;
+typedef void dns_clientrestrans_t;
+typedef void dns_clientreqtrans_t;
+typedef void dns_clientupdatetrans_t;
typedef struct dns_cache dns_cache_t;
typedef isc_uint16_t dns_cert_t;
typedef struct dns_compress dns_compress_t;
@@ -63,6 +67,10 @@ typedef struct dns_dispatchevent dns_dispatchevent_t;
typedef struct dns_dispatchlist dns_dispatchlist_t;
typedef struct dns_dispatchmgr dns_dispatchmgr_t;
typedef struct dns_dispentry dns_dispentry_t;
+typedef struct dns_dns64 dns_dns64_t;
+typedef ISC_LIST(dns_dns64_t) dns_dns64list_t;
+typedef struct dns_dnsseckey dns_dnsseckey_t;
+typedef ISC_LIST(dns_dnsseckey_t) dns_dnsseckeylist_t;
typedef struct dns_dumpctx dns_dumpctx_t;
typedef struct dns_fetch dns_fetch_t;
typedef struct dns_fixedname dns_fixedname_t;
@@ -72,6 +80,7 @@ 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 ISC_LIST(dns_keynode_t) dns_keynodelist_t;
typedef struct dns_keytable dns_keytable_t;
typedef isc_uint16_t dns_keytag_t;
typedef struct dns_loadctx dns_loadctx_t;
@@ -111,6 +120,7 @@ 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_tsec dns_tsec_t;
typedef struct dns_tsig_keyring dns_tsig_keyring_t;
typedef struct dns_tsigkey dns_tsigkey_t;
typedef isc_uint32_t dns_ttl_t;
@@ -179,6 +189,12 @@ typedef enum {
dns_masterformat_raw = 2
} dns_masterformat_t;
+typedef enum {
+ dns_v4_aaaa_ok = 0,
+ dns_v4_aaaa_filter = 1,
+ dns_v4_aaaa_break_dnssec = 2
+} dns_v4_aaaa_t;
+
/*
* These are generated by gen.c.
*/
diff --git a/contrib/bind9/lib/dns/include/dns/validator.h b/contrib/bind9/lib/dns/include/dns/validator.h
index fb5b834..5fec135 100644
--- a/contrib/bind9/lib/dns/include/dns/validator.h
+++ b/contrib/bind9/lib/dns/include/dns/validator.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.h,v 1.41.48.5 2010-02-25 10:56:41 tbox Exp $ */
+/* $Id: validator.h,v 1.46 2010-02-25 05:08:01 tbox Exp $ */
#ifndef DNS_VALIDATOR_H
#define DNS_VALIDATOR_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/view.h b/contrib/bind9/lib/dns/include/dns/view.h
index ec96d4c..4b24023 100644
--- a/contrib/bind9/lib/dns/include/dns/view.h
+++ b/contrib/bind9/lib/dns/include/dns/view.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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: view.h,v 1.111.88.6 2010-09-24 08:30:28 tbox Exp $ */
+/* $Id: view.h,v 1.132 2011-01-13 01:59:28 marka Exp $ */
#ifndef DNS_VIEW_H
#define DNS_VIEW_H 1
@@ -73,6 +73,8 @@
#include <dns/acl.h>
#include <dns/fixedname.h>
+#include <dns/rdatastruct.h>
+#include <dns/rpz.h>
#include <dns/types.h>
ISC_LANG_BEGINDECLS
@@ -92,8 +94,13 @@ struct dns_view {
dns_cache_t * cache;
dns_db_t * cachedb;
dns_db_t * hints;
- dns_keytable_t * secroots;
- dns_keytable_t * trustedkeys;
+
+ /*
+ * security roots.
+ * internal use only; access via * dns_view_getsecroots()
+ */
+ dns_keytable_t * secroots_priv;
+
isc_mutex_t lock;
isc_boolean_t frozen;
isc_task_t * task;
@@ -102,6 +109,7 @@ struct dns_view {
isc_event_t reqevent;
isc_stats_t * resstats;
dns_stats_t * resquerystats;
+ isc_boolean_t cacheshared;
/* Configurable data. */
dns_tsig_keyring_t * statickeys;
@@ -129,6 +137,10 @@ struct dns_view {
dns_acl_t * transferacl;
dns_acl_t * updateacl;
dns_acl_t * upfwdacl;
+ dns_acl_t * denyansweracl;
+ dns_rbt_t * answeracl_exclude;
+ dns_rbt_t * denyanswernames;
+ dns_rbt_t * answernames_exclude;
isc_boolean_t requestixfr;
isc_boolean_t provideixfr;
isc_boolean_t requestnsid;
@@ -145,6 +157,11 @@ struct dns_view {
dns_name_t * dlv;
dns_fixedname_t dlv_fixed;
isc_uint16_t maxudp;
+ dns_v4_aaaa_t v4_aaaa;
+ dns_acl_t * v4_aaaa_acl;
+ dns_dns64list_t dns64;
+ unsigned int dns64cnt;
+ ISC_LIST(dns_rpz_zone_t) rpz_zones;
/*
* Configurable data for server use only,
@@ -162,6 +179,17 @@ struct dns_view {
unsigned int attributes;
/* Under owner's locking control. */
ISC_LINK(struct dns_view) link;
+ dns_viewlist_t * viewlist;
+
+ dns_zone_t * managed_keys;
+
+#ifdef BIND9
+ /* File in which to store configuration for newly added zones */
+ char * new_zone_file;
+
+ void * new_zone_config;
+ void (*cfg_destroy)(void **);
+#endif
};
#define DNS_VIEW_MAGIC ISC_MAGIC('V','i','e','w')
@@ -310,8 +338,12 @@ dns_view_createresolver(dns_view_t *view,
void
dns_view_setcache(dns_view_t *view, dns_cache_t *cache);
+void
+dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared);
/*%<
- * Set the view's cache database.
+ * Set the view's cache database. If 'shared' is true, this means the cache
+ * is created by another view and is shared with that view. dns_view_setcache()
+ * is a backward compatible version equivalent to setcache2(..., ISC_FALSE).
*
* Requires:
*
@@ -346,6 +378,8 @@ dns_view_sethints(dns_view_t *view, dns_db_t *hints);
void
dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring);
+void
+dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring);
/*%<
* Set the view's static TSIG keys
*
@@ -362,6 +396,15 @@ dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring);
*/
void
+dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp);
+/*%<
+ * Return the views dynamic keys.
+ *
+ * \li 'view' is a valid, unfrozen view.
+ * \li 'ringp' != NULL && ringp == NULL.
+ */
+
+void
dns_view_setdstport(dns_view_t *view, in_port_t dstport);
/*%<
* Set the view's destination port. This is the port to
@@ -398,7 +441,7 @@ dns_view_addzone(dns_view_t *view, dns_zone_t *zone);
void
dns_view_freeze(dns_view_t *view);
/*%<
- * Freeze view.
+ * Freeze view. No changes can be made to view configuration while frozen.
*
* Requires:
*
@@ -409,14 +452,44 @@ dns_view_freeze(dns_view_t *view);
*\li 'view' is frozen.
*/
+void
+dns_view_thaw(dns_view_t *view);
+/*%<
+ * Thaw view. This allows zones to be added or removed at runtime. This is
+ * NOT thread-safe; the caller MUST have run isc_task_exclusive() prior to
+ * thawing the view.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, frozen view.
+ *
+ * Ensures:
+ *
+ *\li 'view' is no longer frozen.
+ */
isc_result_t
dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints,
dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+isc_result_t
+dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
+ isc_stdtime_t now, unsigned int options,
+ isc_boolean_t use_hints, isc_boolean_t use_static_stub,
+ dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
/*%<
* Find an rdataset whose owner name is 'name', and whose type is
* 'type'.
+ * In general, this function first searches view's zone and cache DBs for the
+ * best match data against 'name'. If nothing found there, and if 'use_hints'
+ * is ISC_TRUE, the view's hint DB (if configured) is searched.
+ * If the view is configured with a static-stub zone which gives the longest
+ * match for 'name' among the zones, however, the cache DB is not consulted
+ * unless 'use_static_stub' is ISC_FALSE (see below about this argument).
+ *
+ * dns_view_find() is a backward compatible version equivalent to
+ * dns_view_find2() with use_static_stub argument being ISC_FALSE.
*
* Notes:
*
@@ -432,6 +505,23 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
* in the hints database but not the type, the result code will be
* #DNS_R_HINTNXRRSET.
*
+ *\li If 'use_static_stub' is ISC_FALSE and the longest match zone for 'name'
+ * is a static-stub zone, it's ignored and the cache and/or hints will be
+ * searched. In the majority of the cases this argument should be
+ * ISC_FALSE. The only known usage of this argument being ISC_TRUE is
+ * if this search is for a "bailiwick" glue A or AAAA RRset that may
+ * best match a static-stub zone. Consider the following example:
+ * this view is configured with a static-stub zone "example.com",
+ * and an attempt of recursive resolution needs to send a query for the
+ * zone. In this case it's quite likely that the resolver is trying to
+ * find A/AAAA RRs for the apex name "example.com". And, to honor the
+ * static-stub configuration it needs to return the glue RRs in the
+ * static-stub zone even if that exact RRs coming from the authoritative
+ * zone has been cached.
+ * In other general cases, the requested data is better to be
+ * authoritative, either locally configured or retrieved from an external
+ * server, and the data in the static-stub zone should better be ignored.
+ *
*\li 'foundname' must meet the requirements of dns_db_find().
*
*\li If 'sigrdataset' is not NULL, and there is a SIG rdataset which
@@ -728,8 +818,14 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp);
isc_result_t
dns_view_flushcache(dns_view_t *view);
+isc_result_t
+dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly);
/*%<
- * Flush the view's cache (and ADB).
+ * Flush the view's cache (and ADB). If 'fixuponly' is true, it only updates
+ * the internal reference to the cache DB with omitting actual flush operation.
+ * 'fixuponly' is intended to be used for a view that shares a cache with
+ * a different view. dns_view_flushcache() is a backward compatible version
+ * that always sets fixuponly to false.
*
* Requires:
* 'view' is valid.
@@ -878,4 +974,105 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp);
*\li 'statsp' != NULL && '*statsp' != NULL
*/
+isc_boolean_t
+dns_view_iscacheshared(dns_view_t *view);
+/*%<
+ * Check if the view shares the cache created by another view.
+ *
+ * Requires:
+ * \li 'view' is valid.
+ *
+ * Returns:
+ *\li #ISC_TRUE if the cache is shared.
+ *\li #ISC_FALSE otherwise.
+ */
+
+isc_result_t
+dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx);
+/*%<
+ * Initialize security roots for the view. (Note that secroots is
+ * NULL until this function is called, so any function using
+ * secroots must check its validity first. One way to do this is
+ * use dns_view_getsecroots() and check its return value.)
+ *
+ * Requires:
+ * \li 'view' is valid.
+ * \li 'view->secroots' is NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li Any other result indicates failure
+ */
+
+isc_result_t
+dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp);
+/*%<
+ * Get the security roots for this view. Returns ISC_R_NOTFOUND if
+ * the security roots keytable has not been initialized for the view.
+ *
+ * '*ktp' is attached on success; the caller is responsible for
+ * detaching it with dns_keytable_detach().
+ *
+ * Requires:
+ * \li 'view' is valid.
+ * \li 'ktp' is not NULL and '*ktp' is NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOTFOUND
+ */
+
+isc_result_t
+dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
+ isc_boolean_t *secure_domain);
+/*%<
+ * Is 'name' at or beneath a trusted key? Put answer in
+ * '*secure_domain'.
+ *
+ * Requires:
+ * \li 'view' is valid.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li Any other value indicates failure
+ */
+
+void
+dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
+ dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx);
+/*%<
+ * Remove keys that match 'keyname' and 'dnskey' from the views trust
+ * anchors.
+ *
+ * Requires:
+ * \li 'view' is valid.
+ * \li 'keyname' is valid.
+ * \li 'mctx' is valid.
+ * \li 'dnskey' is valid.
+ */
+
+void
+dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
+ void (*cfg_destroy)(void **));
+/*%<
+ * Set whether or not to allow zones to be created or deleted at runtime.
+ *
+ * If 'allow' is ISC_TRUE, determines the filename into which new zone
+ * configuration will be written. Preserves the configuration context
+ * (a pointer to which is passed in 'cfgctx') for use when parsing new
+ * zone configuration. 'cfg_destroy' points to a callback routine to
+ * destroy the configuration context when the view is destroyed. (This
+ * roundabout method is used in order to avoid libdns having a dependency
+ * on libisccfg and libbind9.)
+ *
+ * If 'allow' is ISC_FALSE, removes any existing references to
+ * configuration context and frees any memory.
+ *
+ * Requires:
+ * \li 'view' is valid.
+ */
+
+void
+dns_view_restorekeyring(dns_view_t *view);
+
#endif /* DNS_VIEW_H */
diff --git a/contrib/bind9/lib/dns/include/dns/xfrin.h b/contrib/bind9/lib/dns/include/dns/xfrin.h
index b957e25..58910d2 100644
--- a/contrib/bind9/lib/dns/include/dns/xfrin.h
+++ b/contrib/bind9/lib/dns/include/dns/xfrin.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: xfrin.h,v 1.28.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: xfrin.h,v 1.30 2009-01-17 23:47:43 tbox Exp $ */
#ifndef DNS_XFRIN_H
#define DNS_XFRIN_H 1
diff --git a/contrib/bind9/lib/dns/include/dns/zone.h b/contrib/bind9/lib/dns/include/dns/zone.h
index 96cb998..67756d9 100644
--- a/contrib/bind9/lib/dns/include/dns/zone.h
+++ b/contrib/bind9/lib/dns/include/dns/zone.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.h,v 1.160.50.8 2010-12-14 23:46:09 tbox Exp $ */
+/* $Id: zone.h,v 1.182 2010-12-18 01:56:22 each Exp $ */
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
@@ -40,7 +40,10 @@ typedef enum {
dns_zone_none,
dns_zone_master,
dns_zone_slave,
- dns_zone_stub
+ dns_zone_stub,
+ dns_zone_staticstub,
+ dns_zone_key,
+ dns_zone_dlz
} dns_zonetype_t;
#define DNS_ZONEOPT_SERVERS 0x00000001U /*%< perform server checks */
@@ -70,6 +73,10 @@ typedef enum {
#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 */
+#define DNS_ZONEOPT_SECURETOINSECURE 0x08000000U /*%< dnssec-secure-to-insecure */
+#define DNS_ZONEOPT_DNSKEYKSKONLY 0x10000000U /*%< dnssec-dnskey-kskonly */
+#define DNS_ZONEOPT_CHECKDUPRR 0x20000000U /*%< check-dup-records */
+#define DNS_ZONEOPT_CHECKDUPRRFAIL 0x40000000U /*%< fatal check-dup-records failures */
#ifndef NOMINUM_PUBLIC
/*
@@ -78,6 +85,14 @@ typedef enum {
#define DNS_ZONEOPT_NOTIFYFORWARD 0x80000000U /* forward notify to master */
#endif /* NOMINUM_PUBLIC */
+/*
+ * Zone key maintenance options
+ */
+#define DNS_ZONEKEY_ALLOW 0x00000001U /*%< fetch keys on command */
+#define DNS_ZONEKEY_MAINTAIN 0x00000002U /*%< publish/sign on schedule */
+#define DNS_ZONEKEY_CREATE 0x00000004U /*%< make keys when needed */
+#define DNS_ZONEKEY_FULLSIGN 0x00000008U /*%< roll to new keys immediately */
+
#ifndef DNS_ZONE_MINREFRESH
#define DNS_ZONE_MINREFRESH 300 /*%< 5 minutes */
#endif
@@ -367,6 +382,22 @@ dns_zone_getdb(dns_zone_t *zone, dns_db_t **dbp);
*\li DNS_R_NOTLOADED
*/
+void
+dns_zone_setdb(dns_zone_t *zone, dns_db_t *db);
+/*%<
+ * Sets the zone database to 'db'.
+ *
+ * This function is expected to be used to configure a zone with a
+ * database which is not loaded from a file or zone transfer.
+ * It can be used for a general purpose zone, but right now its use
+ * is limited to static-stub zones to avoid possible undiscovered
+ * problems in the general cases.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone of static-stub.
+ *\li zone doesn't have a database.
+ */
+
isc_result_t
dns_zone_setdbtype(dns_zone_t *zone,
unsigned int dbargc, const char * const *dbargv);
@@ -568,6 +599,25 @@ dns_zone_getoptions(dns_zone_t *zone);
*/
void
+dns_zone_setkeyopt(dns_zone_t *zone, unsigned int option, isc_boolean_t value);
+/*%<
+ * Set key options on ('value' == ISC_TRUE) or off ('value' ==
+ * #ISC_FALSE).
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+unsigned int
+dns_zone_getkeyopts(dns_zone_t *zone);
+/*%<
+ * Returns the current zone key options.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val);
/*%<
* Set the minimum refresh time.
@@ -1747,6 +1797,61 @@ dns_zone_getprivatetype(dns_zone_t *zone);
* will not be permanent.
*/
+void
+dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign);
+/*%<
+ * Update the zone's DNSKEY set from the key repository.
+ *
+ * If 'fullsign' is true, trigger an immediate full signing of
+ * the zone with the new key. Otherwise, if there are no keys or
+ * if the new keys are for algorithms that have already signed the
+ * zone, then the zone can be re-signed incrementally.
+ */
+
+isc_result_t
+dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ unsigned int *errors);
+/*%
+ * Check if the name servers for the zone are sane (have address, don't
+ * refer to CNAMEs/DNAMEs. The number of constiancy errors detected in
+ * returned in '*errors'
+ *
+ * Requires:
+ * \li 'zone' to be valid.
+ * \li 'db' to be valid.
+ * \li 'version' to be valid or NULL.
+ * \li 'errors' to be non NULL.
+ *
+ * Returns:
+ * ISC_R_SUCCESS if there were no errors examining the zone contents.
+ */
+
+void
+dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added);
+/*%
+ * Sets the value of zone->added, which should be ISC_TRUE for
+ * zones that were originally added by "rndc addzone".
+ *
+ * Requires:
+ * \li 'zone' to be valid.
+ */
+
+isc_boolean_t
+dns_zone_getadded(dns_zone_t *zone);
+/*%
+ * Returns ISC_TRUE if the zone was originally added at runtime
+ * using "rndc addzone".
+ *
+ * Requires:
+ * \li 'zone' to be valid.
+ */
+
+isc_result_t
+dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db);
+/*%
+ * Load the origin names for a writeable DLZ database.
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_ZONE_H */
diff --git a/contrib/bind9/lib/dns/include/dst/dst.h b/contrib/bind9/lib/dns/include/dst/dst.h
index 1a30d2b..3c999f6 100644
--- a/contrib/bind9/lib/dns/include/dst/dst.h
+++ b/contrib/bind9/lib/dns/include/dst/dst.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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: dst.h,v 1.12.50.3 2010-12-09 01:12:55 marka Exp $ */
+/* $Id: dst.h,v 1.31 2011-01-11 23:47:14 tbox Exp $ */
#ifndef DST_DST_H
#define DST_DST_H 1
@@ -23,8 +23,11 @@
/*! \file dst/dst.h */
#include <isc/lang.h>
+#include <isc/stdtime.h>
#include <dns/types.h>
+#include <dns/name.h>
+#include <dns/secalg.h>
#include <dst/gssapi.h>
@@ -55,6 +58,7 @@ typedef struct dst_context dst_context_t;
#define DST_ALG_NSEC3RSASHA1 7
#define DST_ALG_RSASHA256 8
#define DST_ALG_RSASHA512 10
+#define DST_ALG_ECCGOST 12
#define DST_ALG_HMACMD5 157
#define DST_ALG_GSSAPI 160
#define DST_ALG_HMACSHA1 161 /* XXXMPA */
@@ -80,12 +84,55 @@ typedef struct dst_context dst_context_t;
#define DST_TYPE_PRIVATE 0x2000000
#define DST_TYPE_PUBLIC 0x4000000
+/* Key timing metadata definitions */
+#define DST_TIME_CREATED 0
+#define DST_TIME_PUBLISH 1
+#define DST_TIME_ACTIVATE 2
+#define DST_TIME_REVOKE 3
+#define DST_TIME_INACTIVE 4
+#define DST_TIME_DELETE 5
+#define DST_TIME_DSPUBLISH 6
+#define DST_MAX_TIMES 6
+
+/* Numeric metadata definitions */
+#define DST_NUM_PREDECESSOR 0
+#define DST_NUM_SUCCESSOR 1
+#define DST_NUM_MAXTTL 2
+#define DST_NUM_ROLLPERIOD 3
+#define DST_MAX_NUMERIC 3
+
+/*
+ * Current format version number of the private key parser.
+ *
+ * When parsing a key file with the same major number but a higher minor
+ * number, the key parser will ignore any fields it does not recognize.
+ * Thus, DST_MINOR_VERSION should be incremented whenever new
+ * fields are added to the private key file (such as new metadata).
+ *
+ * When rewriting these keys, those fields will be dropped, and the
+ * format version set back to the current one..
+ *
+ * When a key is seen with a higher major number, the key parser will
+ * reject it as invalid. Thus, DST_MAJOR_VERSION should be incremented
+ * and DST_MINOR_VERSION set to zero whenever there is a format change
+ * which is not backward compatible to previous versions of the dst_key
+ * parser, such as change in the syntax of an existing field, the removal
+ * of a currently mandatory field, or a new field added which would
+ * alter the functioning of the key if it were absent.
+ */
+#define DST_MAJOR_VERSION 1
+#define DST_MINOR_VERSION 3
+
/***
*** Functions
***/
isc_result_t
dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags);
+
+isc_result_t
+dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx,
+ const char *engine, unsigned int eflags);
/*%<
* Initializes the DST subsystem.
*
@@ -96,6 +143,7 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags);
* Returns:
* \li ISC_R_SUCCESS
* \li ISC_R_NOMEMORY
+ * \li DST_R_NOENGINE
*
* Ensures:
* \li DST is properly initialized.
@@ -244,13 +292,17 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id, unsigned int alg, int type,
*/
isc_result_t
-dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
- dst_key_t **keyp);
+dst_key_fromnamedfile(const char *filename, const char *dirname,
+ int type, isc_mem_t *mctx, dst_key_t **keyp);
/*%<
* Reads a key from permanent storage. The key can either be a public or
* key, and is specified by filename. If a private key is specified, the
* public key must also be present.
*
+ * If 'dirname' is not NULL, and 'filename' is a relative path,
+ * then the file is looked up relative to the given directory.
+ * If 'filename' is an absolute path, 'dirname' is ignored.
+ *
* Requires:
* \li "filename" is not NULL
* \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union
@@ -419,7 +471,7 @@ dst_key_getgssctx(const dst_key_t *key);
isc_result_t
dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
- dst_key_t **keyp);
+ dst_key_t **keyp, isc_region_t *intoken);
/*%<
* Converts a GSSAPI opaque context id into a DST key.
*
@@ -450,6 +502,14 @@ dst_key_generate(dns_name_t *name, unsigned int alg,
unsigned int flags, unsigned int protocol,
dns_rdataclass_t rdclass,
isc_mem_t *mctx, dst_key_t **keyp);
+
+isc_result_t
+dst_key_generate2(dns_name_t *name, unsigned int alg,
+ unsigned int bits, unsigned int param,
+ unsigned int flags, unsigned int protocol,
+ dns_rdataclass_t rdclass,
+ isc_mem_t *mctx, dst_key_t **keyp,
+ void (*callback)(int));
/*%<
* Generate a DST key (or keypair) with the supplied parameters. The
* interpretation of the "param" field depends on the algorithm:
@@ -482,7 +542,31 @@ dst_key_generate(dns_name_t *name, unsigned int alg,
isc_boolean_t
dst_key_compare(const dst_key_t *key1, const dst_key_t *key2);
/*%<
- * Compares two DST keys.
+ * Compares two DST keys. Returns true if they match, false otherwise.
+ *
+ * Keys ARE NOT considered to match if one of them is the revoked version
+ * of the other.
+ *
+ * Requires:
+ *\li "key1" is a valid key.
+ *\li "key2" is a valid key.
+ *
+ * Returns:
+ *\li ISC_TRUE
+ * \li ISC_FALSE
+ */
+
+isc_boolean_t
+dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
+ isc_boolean_t match_revoked_key);
+/*%<
+ * Compares only the public portions of two DST keys. Returns true
+ * if they match, false otherwise. This allows us, for example, to
+ * determine whether a public key found in a zone matches up with a
+ * key pair found on disk.
+ *
+ * If match_revoked_key is TRUE, then keys ARE considered to match if one
+ * of them is the revoked version of the other. Otherwise, they are not.
*
* Requires:
*\li "key1" is a valid key.
@@ -521,10 +605,12 @@ dst_key_attach(dst_key_t *source, dst_key_t **target);
void
dst_key_free(dst_key_t **keyp);
/*%<
- * Release all memory associated with the key.
+ * Decrement the key's reference counter and, when it reaches zero,
+ * release all memory associated with the key.
*
* Requires:
*\li "keyp" is not NULL and "*keyp" is a valid key.
+ *\li reference counter greater than zero.
*
* Ensures:
*\li All memory associated with "*keyp" will be freed.
@@ -633,7 +719,7 @@ dst_region_computeid(const isc_region_t *source, unsigned int alg);
isc_uint16_t
dst_key_getbits(const dst_key_t *key);
-/*
+/*%<
* Get the number of digest bits required (0 == MAX).
*
* Requires:
@@ -642,13 +728,150 @@ dst_key_getbits(const dst_key_t *key);
void
dst_key_setbits(dst_key_t *key, isc_uint16_t bits);
-/*
+/*%<
* Set the number of digest bits required (0 == MAX).
*
* Requires:
* "key" is a valid key.
*/
+isc_result_t
+dst_key_setflags(dst_key_t *key, isc_uint32_t flags);
+/*
+ * Set the key flags, and recompute the key ID.
+ *
+ * Requires:
+ * "key" is a valid key.
+ */
+
+isc_result_t
+dst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep);
+/*%<
+ * Get a member of the numeric metadata array and place it in '*valuep'.
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "type" is no larger than DST_MAX_NUMERIC
+ * "timep" is not null.
+ */
+
+void
+dst_key_setnum(dst_key_t *key, int type, isc_uint32_t value);
+/*%<
+ * Set a member of the numeric metadata array.
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "type" is no larger than DST_MAX_NUMERIC
+ */
+
+void
+dst_key_unsetnum(dst_key_t *key, int type);
+/*%<
+ * Flag a member of the numeric metadata array as "not set".
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "type" is no larger than DST_MAX_NUMERIC
+ */
+
+isc_result_t
+dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep);
+/*%<
+ * Get a member of the timing metadata array and place it in '*timep'.
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "type" is no larger than DST_MAX_TIMES
+ * "timep" is not null.
+ */
+
+void
+dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when);
+/*%<
+ * Set a member of the timing metadata array.
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "type" is no larger than DST_MAX_TIMES
+ */
+
+void
+dst_key_unsettime(dst_key_t *key, int type);
+/*%<
+ * Flag a member of the timing metadata array as "not set".
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "type" is no larger than DST_MAX_TIMES
+ */
+
+isc_result_t
+dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp);
+/*%<
+ * Get the private key format version number. (If the key does not have
+ * a private key associated with it, the version will be 0.0.) The major
+ * version number is placed in '*majorp', and the minor version number in
+ * '*minorp'.
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "majorp" is not NULL.
+ * "minorp" is not NULL.
+ */
+
+void
+dst_key_setprivateformat(dst_key_t *key, int major, int minor);
+/*%<
+ * Set the private key format version number.
+ *
+ * Requires:
+ * "key" is a valid key.
+ */
+
+#define DST_KEY_FORMATSIZE (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + 7)
+
+void
+dst_key_format(const dst_key_t *key, char *cp, unsigned int size);
+/*%<
+ * Write the uniquely identifying information about the key (name,
+ * algorithm, key ID) into a string 'cp' of size 'size'.
+ */
+
+
+isc_buffer_t *
+dst_key_tkeytoken(const dst_key_t *key);
+/*%<
+ * Return the token from the TKEY request, if any. If this key was
+ * not negotiated via TKEY, return NULL.
+ */
+
+
+isc_result_t
+dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length);
+/*%<
+ * Allocate 'buffer' and dump the key into it in base64 format. The buffer
+ * is not NUL terminated. The length of the buffer is returned in *length.
+ *
+ * 'buffer' needs to be freed using isc_mem_put(mctx, buffer, length);
+ *
+ * Requires:
+ * 'buffer' to be non NULL and *buffer to be NULL.
+ * 'length' to be non NULL and *length to be zero.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOMEMORY
+ * ISC_R_NOTIMPLEMENTED
+ * others.
+ */
+
+isc_result_t
+dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
+ unsigned int protocol, dns_rdataclass_t rdclass,
+ isc_mem_t *mctx, const char *keystr, dst_key_t **keyp);
+
+
ISC_LANG_ENDDECLS
#endif /* DST_DST_H */
diff --git a/contrib/bind9/lib/dns/include/dst/gssapi.h b/contrib/bind9/lib/dns/include/dst/gssapi.h
index 0a468d3..189e6b5 100644
--- a/contrib/bind9/lib/dns/include/dst/gssapi.h
+++ b/contrib/bind9/lib/dns/include/dst/gssapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: gssapi.h,v 1.9.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: gssapi.h,v 1.16 2011-01-08 23:47:01 tbox Exp $ */
#ifndef DST_GSSAPI_H
#define DST_GSSAPI_H 1
@@ -34,8 +34,12 @@
* MSVC does not like macros in #include lines.
*/
#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
#else
#include ISC_PLATFORM_GSSAPIHEADER
+#ifdef ISC_PLATFORM_GSSAPI_KRB5_HEADER
+#include ISC_PLATFORM_GSSAPI_KRB5_HEADER
+#endif
#endif
#ifndef GSS_SPNEGO_MECHANISM
#define GSS_SPNEGO_MECHANISM ((void*)0)
@@ -90,7 +94,8 @@ dst_gssapi_releasecred(gss_cred_id_t *cred);
isc_result_t
dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
- isc_buffer_t *outtoken, gss_ctx_id_t *gssctx);
+ isc_buffer_t *outtoken, gss_ctx_id_t *gssctx,
+ isc_mem_t *mctx, char **err_message);
/*
* Initiates a GSS context.
*
@@ -108,10 +113,12 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
* ISC_R_SUCCESS msg was successfully updated to include the
* query to be sent
* other an error occurred while building the message
+ * *err_message optional error message
*/
isc_result_t
dst_gssapi_acceptctx(gss_cred_id_t cred,
+ const char *gssapi_keytab,
isc_region_t *intoken, isc_buffer_t **outtoken,
gss_ctx_id_t *context, dns_name_t *principal,
isc_mem_t *mctx);
diff --git a/contrib/bind9/lib/dns/iptable.c b/contrib/bind9/lib/dns/iptable.c
index 071f9a6..7c334dd 100644
--- a/contrib/bind9/lib/dns/iptable.c
+++ b/contrib/bind9/lib/dns/iptable.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: iptable.c,v 1.12.44.3 2009-02-18 23:47:12 tbox Exp $ */
+/* $Id: iptable.c,v 1.15 2009-02-18 23:47:48 tbox Exp $ */
#include <config.h>
diff --git a/contrib/bind9/lib/dns/journal.c b/contrib/bind9/lib/dns/journal.c
index 520083e..a6d630e 100644
--- a/contrib/bind9/lib/dns/journal.c
+++ b/contrib/bind9/lib/dns/journal.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: journal.c,v 1.103.48.8 2010-11-17 23:45:45 tbox Exp $ */
+/* $Id: journal.c,v 1.112 2010-11-17 23:47:08 tbox Exp $ */
#include <config.h>
@@ -562,11 +562,9 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
if (result == ISC_R_FILENOTFOUND) {
if (create) {
- isc_log_write(JOURNAL_COMMON_LOGARGS,
- ISC_LOG_INFO,
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(1),
"journal file %s does not exist, "
- "creating it",
- j->filename);
+ "creating it", j->filename);
CHECK(journal_file_create(mctx, filename));
/*
* Retry.
diff --git a/contrib/bind9/lib/dns/keydata.c b/contrib/bind9/lib/dns/keydata.c
new file mode 100644
index 0000000..c2f82c8
--- /dev/null
+++ b/contrib/bind9/lib/dns/keydata.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 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: keydata.c,v 1.3 2009-07-01 23:47:36 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/rdata.h>
+#include <dns/rdatastruct.h>
+#include <dns/keydata.h>
+
+isc_result_t
+dns_keydata_todnskey(dns_rdata_keydata_t *keydata,
+ dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
+{
+ REQUIRE(keydata != NULL && dnskey != NULL);
+
+ dnskey->common.rdtype = dns_rdatatype_dnskey;
+ dnskey->common.rdclass = keydata->common.rdclass;
+ dnskey->mctx = mctx;
+ dnskey->flags = keydata->flags;
+ dnskey->protocol = keydata->protocol;
+ dnskey->algorithm = keydata->algorithm;
+
+ dnskey->datalen = keydata->datalen;
+
+ if (mctx == NULL)
+ dnskey->data = keydata->data;
+ else {
+ dnskey->data = isc_mem_allocate(mctx, dnskey->datalen);
+ if (dnskey->data == NULL)
+ return (ISC_R_NOMEMORY);
+ memcpy(dnskey->data, keydata->data, dnskey->datalen);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_keydata_fromdnskey(dns_rdata_keydata_t *keydata,
+ dns_rdata_dnskey_t *dnskey,
+ isc_uint32_t refresh, isc_uint32_t addhd,
+ isc_uint32_t removehd, isc_mem_t *mctx)
+{
+ REQUIRE(keydata != NULL && dnskey != NULL);
+
+ keydata->common.rdtype = dns_rdatatype_keydata;
+ keydata->common.rdclass = dnskey->common.rdclass;
+ keydata->mctx = mctx;
+ keydata->refresh = refresh;
+ keydata->addhd = addhd;
+ keydata->removehd = removehd;
+ keydata->flags = dnskey->flags;
+ keydata->protocol = dnskey->protocol;
+ keydata->algorithm = dnskey->algorithm;
+
+ keydata->datalen = dnskey->datalen;
+ if (mctx == NULL)
+ keydata->data = dnskey->data;
+ else {
+ keydata->data = isc_mem_allocate(mctx, keydata->datalen);
+ if (keydata->data == NULL)
+ return (ISC_R_NOMEMORY);
+ memcpy(keydata->data, dnskey->data, keydata->datalen);
+ }
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/contrib/bind9/lib/dns/keytable.c b/contrib/bind9/lib/dns/keytable.c
index 874868d..3edc3d6 100644
--- a/contrib/bind9/lib/dns/keytable.c
+++ b/contrib/bind9/lib/dns/keytable.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keytable.c,v 1.34 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: keytable.c,v 1.41 2010-06-25 23:46:51 tbox Exp $ */
/*! \file */
@@ -31,41 +31,12 @@
#include <dns/rbt.h>
#include <dns/result.h>
-struct dns_keytable {
- /* Unlocked. */
- unsigned int magic;
- isc_mem_t *mctx;
- isc_mutex_t lock;
- isc_rwlock_t rwlock;
- /* Locked by lock. */
- isc_uint32_t active_nodes;
- /* Locked by rwlock. */
- isc_uint32_t references;
- dns_rbt_t *table;
-};
-
-#define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l')
-#define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC)
-
-struct dns_keynode {
- unsigned int magic;
- dst_key_t * key;
- struct dns_keynode * next;
-};
-
-#define KEYNODE_MAGIC ISC_MAGIC('K', 'N', 'o', 'd')
-#define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC)
-
static void
free_keynode(void *node, void *arg) {
dns_keynode_t *keynode = node;
isc_mem_t *mctx = arg;
- REQUIRE(VALID_KEYNODE(keynode));
- dst_key_free(&keynode->key);
- if (keynode->next != NULL)
- free_keynode(keynode->next, mctx);
- isc_mem_put(mctx, keynode, sizeof(dns_keynode_t));
+ dns_keynode_detachall(mctx, &keynode);
}
isc_result_t
@@ -116,7 +87,6 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
return (result);
}
-
void
dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
@@ -173,50 +143,224 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
*keytablep = NULL;
}
-isc_result_t
-dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp) {
+static isc_result_t
+insert(dns_keytable_t *keytable, isc_boolean_t managed,
+ dns_name_t *keyname, dst_key_t **keyp)
+{
isc_result_t result;
- dns_keynode_t *knode;
+ dns_keynode_t *knode = NULL;
dns_rbtnode_t *node;
- dns_name_t *keyname;
-
- /*
- * Add '*keyp' to 'keytable'.
- */
+ REQUIRE(keyp == NULL || *keyp != NULL);
REQUIRE(VALID_KEYTABLE(keytable));
- REQUIRE(keyp != NULL);
- keyname = dst_key_name(*keyp);
+ result = dns_keynode_create(keytable->mctx, &knode);
+ if (result != ISC_R_SUCCESS)
+ return (result);
- knode = isc_mem_get(keytable->mctx, sizeof(*knode));
- if (knode == NULL)
- return (ISC_R_NOMEMORY);
+ knode->managed = managed;
RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
node = NULL;
result = dns_rbt_addnode(keytable->table, keyname, &node);
- if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
- knode->magic = KEYNODE_MAGIC;
- knode->key = *keyp;
- knode->next = node->data;
+ if (keyp != NULL) {
+ if (result == ISC_R_EXISTS) {
+ /* Key already in table? */
+ dns_keynode_t *k;
+ for (k = node->data; k != NULL; k = k->next) {
+ if (k->key == NULL) {
+ k->key = *keyp;
+ break;
+ }
+ if (dst_key_compare(k->key, *keyp) == ISC_TRUE)
+ break;
+ }
+
+ if (k == NULL)
+ result = ISC_R_SUCCESS;
+ else
+ dst_key_free(keyp);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ knode->key = *keyp;
+ knode->next = node->data;
+ *keyp = NULL;
+ }
+ }
+
+ if (result == ISC_R_SUCCESS) {
node->data = knode;
- *keyp = NULL;
knode = NULL;
- result = ISC_R_SUCCESS;
}
+ /* Key was already there? That's the same as a success */
+ if (result == ISC_R_EXISTS)
+ result = ISC_R_SUCCESS;
+
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
if (knode != NULL)
- isc_mem_put(keytable->mctx, knode, sizeof(*knode));
+ dns_keynode_detach(keytable->mctx, &knode);
+
+ return (result);
+}
+
+isc_result_t
+dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
+ dst_key_t **keyp)
+{
+ REQUIRE(keyp != NULL && *keyp != NULL);
+ return (insert(keytable, managed, dst_key_name(*keyp), keyp));
+}
+
+isc_result_t
+dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name) {
+ return (insert(keytable, ISC_TRUE, name, NULL));
+}
+
+isc_result_t
+dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname) {
+ isc_result_t result;
+ dns_rbtnode_t *node = NULL;
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(keyname != NULL);
+
+ RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
+ result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
+ DNS_RBTFIND_NOOPTIONS, NULL, NULL);
+ if (result == ISC_R_SUCCESS) {
+ if (node->data != NULL)
+ result = dns_rbt_deletenode(keytable->table,
+ node, ISC_FALSE);
+ else
+ result = ISC_R_NOTFOUND;
+ } else if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
return (result);
}
isc_result_t
+dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) {
+ isc_result_t result;
+ dns_name_t *keyname;
+ dns_rbtnode_t *node = NULL;
+ dns_keynode_t *knode = NULL, **kprev = NULL;
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(dstkey != NULL);
+
+ keyname = dst_key_name(dstkey);
+
+ RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
+ result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
+ DNS_RBTFIND_NOOPTIONS, NULL, NULL);
+
+ if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+ if (result != ISC_R_SUCCESS)
+ goto finish;
+
+ if (node->data == NULL) {
+ result = ISC_R_NOTFOUND;
+ goto finish;
+ }
+
+ knode = node->data;
+ if (knode->next == NULL &&
+ (knode->key == NULL ||
+ dst_key_compare(knode->key, dstkey) == ISC_TRUE)) {
+ result = dns_rbt_deletenode(keytable->table, node, ISC_FALSE);
+ goto finish;
+ }
+
+ kprev = (dns_keynode_t **) &node->data;
+ while (knode != NULL) {
+ if (dst_key_compare(knode->key, dstkey) == ISC_TRUE)
+ break;
+ kprev = &knode->next;
+ knode = knode->next;
+ }
+
+ if (knode != NULL) {
+ if (knode->key != NULL)
+ dst_key_free(&knode->key);
+ /*
+ * This is equivalent to:
+ * dns_keynode_attach(knode->next, &tmp);
+ * dns_keynode_detach(kprev);
+ * dns_keynode_attach(tmp, &kprev);
+ * dns_keynode_detach(&tmp);
+ */
+ *kprev = knode->next;
+ knode->next = NULL;
+ dns_keynode_detach(keytable->mctx, &knode);
+ } else
+ result = DNS_R_PARTIALMATCH;
+ finish:
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
+ return (result);
+}
+
+isc_result_t
+dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname,
+ dns_keynode_t **keynodep)
+{
+ isc_result_t result;
+ dns_rbtnode_t *node = NULL;
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(keyname != NULL);
+ REQUIRE(keynodep != NULL && *keynodep == NULL);
+
+ RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
+ result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
+ DNS_RBTFIND_NOOPTIONS, NULL, NULL);
+ if (result == ISC_R_SUCCESS) {
+ if (node->data != NULL) {
+ LOCK(&keytable->lock);
+ keytable->active_nodes++;
+ UNLOCK(&keytable->lock);
+ dns_keynode_attach(node->data, keynodep);
+ } else
+ result = ISC_R_NOTFOUND;
+ } else if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+isc_result_t
+dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
+ dns_keynode_t **nextnodep)
+{
+ /*
+ * Return the next key after 'keynode', regardless of
+ * properties.
+ */
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(VALID_KEYNODE(keynode));
+ REQUIRE(nextnodep != NULL && *nextnodep == NULL);
+
+ if (keynode->next == NULL)
+ return (ISC_R_NOTFOUND);
+
+ dns_keynode_attach(keynode->next, nextnodep);
+ LOCK(&keytable->lock);
+ keytable->active_nodes++;
+ UNLOCK(&keytable->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
dns_secalg_t algorithm, dns_keytag_t tag,
dns_keynode_t **keynodep)
@@ -250,6 +394,10 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
if (result == ISC_R_SUCCESS) {
INSIST(data != NULL);
for (knode = data; knode != NULL; knode = knode->next) {
+ if (knode->key == NULL) {
+ knode = NULL;
+ break;
+ }
if (algorithm == dst_key_alg(knode->key)
&& tag == dst_key_id(knode->key))
break;
@@ -258,7 +406,7 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
LOCK(&keytable->lock);
keytable->active_nodes++;
UNLOCK(&keytable->lock);
- *keynodep = knode;
+ dns_keynode_attach(knode, keynodep);
} else
result = DNS_R_PARTIALMATCH;
} else if (result == DNS_R_PARTIALMATCH)
@@ -286,6 +434,10 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
REQUIRE(nextnodep != NULL && *nextnodep == NULL);
for (knode = keynode->next; knode != NULL; knode = knode->next) {
+ if (knode->key == NULL) {
+ knode = NULL;
+ break;
+ }
if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
dst_key_id(keynode->key) == dst_key_id(knode->key))
break;
@@ -295,7 +447,7 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
keytable->active_nodes++;
UNLOCK(&keytable->lock);
result = ISC_R_SUCCESS;
- *nextnodep = knode;
+ dns_keynode_attach(knode, nextnodep);
} else
result = ISC_R_NOTFOUND;
@@ -331,6 +483,25 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
}
void
+dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
+ dns_keynode_t **target)
+{
+ /*
+ * Give back a keynode found via dns_keytable_findkeynode().
+ */
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(VALID_KEYNODE(source));
+ REQUIRE(target != NULL && *target == NULL);
+
+ LOCK(&keytable->lock);
+ keytable->active_nodes++;
+ UNLOCK(&keytable->lock);
+
+ dns_keynode_attach(source, target);
+}
+
+void
dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
{
/*
@@ -345,7 +516,7 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
keytable->active_nodes--;
UNLOCK(&keytable->lock);
- *keynodep = NULL;
+ dns_keynode_detach(keytable->mctx, keynodep);
}
isc_result_t
@@ -382,6 +553,44 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
return (result);
}
+isc_result_t
+dns_keytable_dump(dns_keytable_t *keytable, FILE *fp)
+{
+ isc_result_t result;
+ dns_keynode_t *knode;
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+
+ RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
+ dns_rbtnodechain_init(&chain, keytable->mctx);
+ result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+ goto cleanup;
+ for (;;) {
+ char pbuf[DST_KEY_FORMATSIZE];
+
+ dns_rbtnodechain_current(&chain, NULL, NULL, &node);
+ for (knode = node->data; knode != NULL; knode = knode->next) {
+ dst_key_format(knode->key, pbuf, sizeof(pbuf));
+ fprintf(fp, "%s ; %s\n", pbuf,
+ knode->managed ? "managed" : "trusted");
+ }
+ result = dns_rbtnodechain_next(&chain, NULL, NULL);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ break;
+ }
+ }
+
+ cleanup:
+ dns_rbtnodechain_invalidate(&chain);
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
+ return (result);
+}
+
dst_key_t *
dns_keynode_key(dns_keynode_t *keynode) {
@@ -393,3 +602,71 @@ dns_keynode_key(dns_keynode_t *keynode) {
return (keynode->key);
}
+
+isc_boolean_t
+dns_keynode_managed(dns_keynode_t *keynode) {
+ /*
+ * Is this a managed key?
+ */
+ REQUIRE(VALID_KEYNODE(keynode));
+
+ return (keynode->managed);
+}
+
+isc_result_t
+dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
+ isc_result_t result;
+ dns_keynode_t *knode = NULL;
+
+ REQUIRE(target != NULL && *target == NULL);
+
+ knode = isc_mem_get(mctx, sizeof(dns_keynode_t));
+ if (knode == NULL)
+ return (ISC_R_NOMEMORY);
+
+ knode->magic = KEYNODE_MAGIC;
+ knode->managed = ISC_FALSE;
+ knode->key = NULL;
+ knode->next = NULL;
+
+ result = isc_refcount_init(&knode->refcount, 1);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ *target = knode;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
+ REQUIRE(VALID_KEYNODE(source));
+ isc_refcount_increment(&source->refcount, NULL);
+ *target = source;
+}
+
+void
+dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
+ unsigned int refs;
+ dns_keynode_t *node = *keynode;
+ REQUIRE(VALID_KEYNODE(node));
+ isc_refcount_decrement(&node->refcount, &refs);
+ if (refs == 0) {
+ if (node->key != NULL)
+ dst_key_free(&node->key);
+ isc_refcount_destroy(&node->refcount);
+ isc_mem_put(mctx, node, sizeof(dns_keynode_t));
+ }
+ *keynode = NULL;
+}
+
+void
+dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **keynode) {
+ dns_keynode_t *next = NULL, *node = *keynode;
+ REQUIRE(VALID_KEYNODE(node));
+ while (node != NULL) {
+ next = node->next;
+ dns_keynode_detach(mctx, &node);
+ node = next;
+ }
+ *keynode = NULL;
+}
diff --git a/contrib/bind9/lib/dns/lib.c b/contrib/bind9/lib/dns/lib.c
index 761be56..6953c88 100644
--- a/contrib/bind9/lib/dns/lib.c
+++ b/contrib/bind9/lib/dns/lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lib.c,v 1.16 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: lib.c,v 1.19 2009-09-03 00:12:23 each Exp $ */
/*! \file */
@@ -23,11 +23,20 @@
#include <stddef.h>
-#include <isc/once.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
#include <isc/msgcat.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
#include <isc/util.h>
+#include <dns/db.h>
+#include <dns/ecdb.h>
#include <dns/lib.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+
/***
*** Globals
@@ -63,3 +72,97 @@ dns_lib_initmsgcat(void) {
RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS);
}
+
+static isc_once_t init_once = ISC_ONCE_INIT;
+static isc_mem_t *dns_g_mctx = NULL;
+#ifndef BIND9
+static dns_dbimplementation_t *dbimp = NULL;
+#endif
+static isc_boolean_t initialize_done = ISC_FALSE;
+static isc_mutex_t reflock;
+static unsigned int references = 0;
+
+static void
+initialize(void) {
+ isc_result_t result;
+
+ REQUIRE(initialize_done == ISC_FALSE);
+
+ result = isc_mem_create(0, 0, &dns_g_mctx);
+ if (result != ISC_R_SUCCESS)
+ return;
+ dns_result_register();
+#ifndef BIND9
+ result = dns_ecdb_register(dns_g_mctx, &dbimp);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mctx;
+#endif
+ result = isc_hash_create(dns_g_mctx, NULL, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_db;
+
+ result = dst_lib_init(dns_g_mctx, NULL, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_hash;
+
+ result = isc_mutex_init(&reflock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_dst;
+
+ initialize_done = ISC_TRUE;
+ return;
+
+ cleanup_dst:
+ dst_lib_destroy();
+ cleanup_hash:
+ isc_hash_destroy();
+ cleanup_db:
+#ifndef BIND9
+ dns_ecdb_unregister(&dbimp);
+ cleanup_mctx:
+#endif
+ isc_mem_detach(&dns_g_mctx);
+}
+
+isc_result_t
+dns_lib_init(void) {
+ isc_result_t result;
+
+ /*
+ * Since this routine is expected to be used by a normal application,
+ * it should be better to return an error, instead of an emergency
+ * abort, on any failure.
+ */
+ result = isc_once_do(&init_once, initialize);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (!initialize_done)
+ return (ISC_R_FAILURE);
+
+ LOCK(&reflock);
+ references++;
+ UNLOCK(&reflock);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_lib_shutdown(void) {
+ isc_boolean_t cleanup_ok = ISC_FALSE;
+
+ LOCK(&reflock);
+ if (--references == 0)
+ cleanup_ok = ISC_TRUE;
+ UNLOCK(&reflock);
+
+ if (!cleanup_ok)
+ return;
+
+ dst_lib_destroy();
+ isc_hash_destroy();
+#ifndef BIND9
+ dns_ecdb_unregister(&dbimp);
+#endif
+ isc_mem_detach(&dns_g_mctx);
+}
diff --git a/contrib/bind9/lib/dns/log.c b/contrib/bind9/lib/dns/log.c
index 5b3ee32..9de5976 100644
--- a/contrib/bind9/lib/dns/log.c
+++ b/contrib/bind9/lib/dns/log.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.c,v 1.45 2007-06-18 23:47:40 tbox Exp $ */
+/* $Id: log.c,v 1.47 2009-12-18 23:49:03 tbox Exp $ */
/*! \file */
@@ -79,6 +79,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = {
{ "dns/hints", 0 },
{ "dns/acache", 0 },
{ "dns/dlz", 0 },
+ { "dns/dnssec", 0 },
{ NULL, 0 }
};
diff --git a/contrib/bind9/lib/dns/master.c b/contrib/bind9/lib/dns/master.c
index 9c6d3b8..e90a74c 100644
--- a/contrib/bind9/lib/dns/master.c
+++ b/contrib/bind9/lib/dns/master.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: master.c,v 1.171.120.2 2009-01-18 23:47:40 tbox Exp $ */
+/* $Id: master.c,v 1.178 2009-09-01 00:22:26 jinmei Exp $ */
/*! \file */
@@ -85,7 +85,11 @@
*/
#define TOKENSIZ (8*1024)
-#define DNS_MASTER_BUFSZ 2048
+/*%
+ * Buffers sizes for $GENERATE.
+ */
+#define DNS_MASTER_LHS 2048
+#define DNS_MASTER_RHS MINTSIZ
typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
@@ -614,6 +618,57 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
return (result);
}
+static const char *hex = "0123456789abcdef0123456789ABCDEF";
+
+/*%
+ * Convert value into a nibble sequence from least significant to most
+ * significant nibble. Zero fill upper most significant nibbles if
+ * required to make the width.
+ *
+ * Returns the number of characters that should have been written without
+ * counting the terminating NUL.
+ */
+static unsigned int
+nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
+ unsigned int count = 0;
+
+ /*
+ * This reserve space for the NUL string terminator.
+ */
+ if (length > 0U) {
+ *numbuf = '\0';
+ length--;
+ }
+ do {
+ char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
+ value >>= 4;
+ if (length > 0U) {
+ *numbuf++ = val;
+ *numbuf = '\0';
+ length--;
+ }
+ if (width > 0)
+ width--;
+ count++;
+ /*
+ * If width is non zero then we need to add a label seperator.
+ * If value is non zero then we need to add another label and
+ * that requires a label seperator.
+ */
+ if (width > 0 || value != 0) {
+ if (length > 0U) {
+ *numbuf++ = '.';
+ *numbuf = '\0';
+ length--;
+ }
+ if (width > 0)
+ width--;
+ count++;
+ }
+ } while (value != 0 || width > 0);
+ return (count);
+}
+
static isc_result_t
genname(char *name, int it, char *buffer, size_t length) {
char fmt[sizeof("%04000000000d")];
@@ -624,6 +679,7 @@ genname(char *name, int it, char *buffer, size_t length) {
isc_textregion_t r;
unsigned int n;
unsigned int width;
+ isc_boolean_t nibblemode;
r.base = buffer;
r.length = length;
@@ -638,10 +694,11 @@ genname(char *name, int it, char *buffer, size_t length) {
isc_textregion_consume(&r, 1);
continue;
}
+ nibblemode = ISC_FALSE;
strcpy(fmt, "%d");
/* Get format specifier. */
if (*name == '{' ) {
- n = sscanf(name, "{%d,%u,%1[doxX]}",
+ n = sscanf(name, "{%d,%u,%1[doxXnN]}",
&delta, &width, mode);
switch (n) {
case 1:
@@ -651,6 +708,8 @@ genname(char *name, int it, char *buffer, size_t length) {
"%%0%ud", width);
break;
case 3:
+ if (mode[0] == 'n' || mode[0] == 'N')
+ nibblemode = ISC_TRUE;
n = snprintf(fmt, sizeof(fmt),
"%%0%u%c", width, mode[0]);
break;
@@ -663,7 +722,12 @@ genname(char *name, int it, char *buffer, size_t length) {
while (*name != '\0' && *name++ != '}')
continue;
}
- n = snprintf(numbuf, sizeof(numbuf), fmt, it + delta);
+ if (nibblemode)
+ n = nibbles(numbuf, sizeof(numbuf), width,
+ mode[0], it + delta);
+ else
+ n = snprintf(numbuf, sizeof(numbuf), fmt,
+ it + delta);
if (n >= sizeof(numbuf))
return (ISC_R_NOSPACE);
cp = numbuf;
@@ -746,8 +810,8 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
ISC_LIST_INIT(head);
target_mem = isc_mem_get(lctx->mctx, target_size);
- rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ);
- lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_BUFSZ);
+ rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
+ lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
result = ISC_R_NOMEMORY;
goto error_cleanup;
@@ -778,35 +842,13 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
goto insist_cleanup;
}
- switch (type) {
- case dns_rdatatype_ns:
- case dns_rdatatype_ptr:
- case dns_rdatatype_cname:
- case dns_rdatatype_dname:
- break;
-
- case dns_rdatatype_a:
- case dns_rdatatype_aaaa:
- if (lctx->zclass == dns_rdataclass_in ||
- lctx->zclass == dns_rdataclass_ch ||
- lctx->zclass == dns_rdataclass_hs)
- break;
- /* FALLTHROUGH */
- default:
- (*callbacks->error)(callbacks,
- "%s: %s:%lu: unsupported type '%s'",
- "$GENERATE", source, line, gtype);
- result = ISC_R_NOTIMPLEMENTED;
- goto error_cleanup;
- }
-
ISC_LIST_INIT(rdatalist.rdata);
ISC_LINK_INIT(&rdatalist, link);
for (i = start; i <= stop; i += step) {
- result = genname(lhs, i, lhsbuf, DNS_MASTER_BUFSZ);
+ result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
if (result != ISC_R_SUCCESS)
goto error_cleanup;
- result = genname(rhs, i, rhsbuf, DNS_MASTER_BUFSZ);
+ result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
if (result != ISC_R_SUCCESS)
goto error_cleanup;
@@ -820,6 +862,7 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
(lctx->options & DNS_MASTER_SLAVE) == 0 &&
+ (lctx->options & DNS_MASTER_KEY) == 0 &&
!dns_name_issubdomain(owner, lctx->top))
{
char namebuf[DNS_NAME_FORMATSIZE];
@@ -880,9 +923,9 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
if (target_mem != NULL)
isc_mem_put(lctx->mctx, target_mem, target_size);
if (lhsbuf != NULL)
- isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_BUFSZ);
+ isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
if (rhsbuf != NULL)
- isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_BUFSZ);
+ isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
return (result);
}
@@ -1270,7 +1313,8 @@ load_text(dns_loadctx_t *lctx) {
goto log_and_cleanup;
}
/* RHS */
- GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING,
+ &token, ISC_FALSE);
rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
if (rhs == NULL) {
result = ISC_R_NOMEMORY;
@@ -1338,7 +1382,7 @@ load_text(dns_loadctx_t *lctx) {
isc_buffer_setactive(&buffer,
token.value.as_region.length);
result = dns_name_fromtext(new_name, &buffer,
- ictx->origin, ISC_FALSE, NULL);
+ ictx->origin, 0, NULL);
if (MANYERRS(lctx, result)) {
SETRESULT(lctx, result);
LOGIT(result);
@@ -1459,6 +1503,7 @@ load_text(dns_loadctx_t *lctx) {
}
if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
(lctx->options & DNS_MASTER_SLAVE) == 0 &&
+ (lctx->options & DNS_MASTER_KEY) == 0 &&
!dns_name_issubdomain(new_name, lctx->top))
{
char namebuf[DNS_NAME_FORMATSIZE];
diff --git a/contrib/bind9/lib/dns/masterdump.c b/contrib/bind9/lib/dns/masterdump.c
index d6befb5..e2adf9b 100644
--- a/contrib/bind9/lib/dns/masterdump.c
+++ b/contrib/bind9/lib/dns/masterdump.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: masterdump.c,v 1.94.50.3.18.3 2011-06-21 20:13:22 each Exp $ */
+/* $Id: masterdump.c,v 1.99.328.3 2011-06-21 20:15:47 each Exp $ */
/*! \file */
@@ -42,6 +42,7 @@
#include <dns/log.h>
#include <dns/master.h>
#include <dns/masterdump.h>
+#include <dns/ncache.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdataset.h>
@@ -60,6 +61,11 @@
return (_r); \
} while (0)
+#define CHECK(x) do { \
+ if ((x) != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
struct dns_master_style {
unsigned int flags; /* DNS_STYLEFLAG_* */
unsigned int ttl_column;
@@ -156,6 +162,7 @@ static char spaces[N_SPACES+1] = " ";
#define N_TABS 10
static char tabs[N_TABS+1] = "\t\t\t\t\t\t\t\t\t\t";
+#ifdef BIND9
struct dns_dumpctx {
unsigned int magic;
isc_mem_t *mctx;
@@ -183,6 +190,7 @@ struct dns_dumpctx {
dns_totext_ctx_t *ctx,
isc_buffer_t *buffer, FILE *f);
};
+#endif /* BIND9 */
#define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
@@ -336,6 +344,52 @@ str_totext(const char *source, isc_buffer_t *target) {
return (ISC_R_SUCCESS);
}
+static isc_result_t
+ncache_summary(dns_rdataset_t *rdataset, isc_boolean_t omit_final_dot,
+ isc_buffer_t *target)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdataset_t rds;
+ dns_name_t name;
+
+ dns_rdataset_init(&rds);
+ dns_name_init(&name, NULL);
+
+ do {
+ dns_ncache_current(rdataset, &name, &rds);
+ for (result = dns_rdataset_first(&rds);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rds)) {
+ CHECK(str_totext("; ", target));
+ CHECK(dns_name_totext(&name, omit_final_dot, target));
+ CHECK(str_totext(" ", target));
+ CHECK(dns_rdatatype_totext(rds.type, target));
+ if (rds.type == dns_rdatatype_rrsig) {
+ CHECK(str_totext(" ", target));
+ CHECK(dns_rdatatype_totext(rds.covers, target));
+ CHECK(str_totext(" ...\n", target));
+ } else {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rds, &rdata);
+ CHECK(str_totext(" ", target));
+ CHECK(dns_rdata_tofmttext(&rdata, dns_rootname,
+ 0, 0, " ", target));
+ CHECK(str_totext("\n", target));
+ }
+ }
+ dns_rdataset_disassociate(&rds);
+ result = dns_rdataset_next(rdataset);
+ } while (result == ISC_R_SUCCESS);
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ cleanup:
+ if (dns_rdataset_isassociated(&rds))
+ dns_rdataset_disassociate(&rds);
+
+ return (result);
+}
+
/*
* Convert 'rdataset' to master file text format according to 'ctx',
* storing the result in 'target'. If 'owner_name' is NULL, it
@@ -462,6 +516,13 @@ rdataset_totext(dns_rdataset_t *rdataset,
RETERR(str_totext(";-$NXDOMAIN\n", target));
else
RETERR(str_totext(";-$NXRRSET\n", target));
+ /*
+ * Print a summary of the cached records which make
+ * up the negative response.
+ */
+ RETERR(ncache_summary(rdataset, omit_final_dot,
+ target));
+ break;
} else {
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_region_t r;
@@ -637,6 +698,7 @@ dns_master_questiontotext(dns_name_t *owner_name,
ISC_FALSE, target));
}
+#ifdef BIND9
/*
* Print an rdataset. 'buffer' is a scratch buffer, which must have been
* dynamically allocated by the caller. It must be large enough to
@@ -1692,6 +1754,7 @@ dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
return (result);
}
+#endif /* BIND9 */
isc_result_t
dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags,
diff --git a/contrib/bind9/lib/dns/message.c b/contrib/bind9/lib/dns/message.c
index 2023741..b58c139 100644
--- a/contrib/bind9/lib/dns/message.c
+++ b/contrib/bind9/lib/dns/message.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: message.c,v 1.245.50.7.6.3 2011-06-21 20:13:22 each Exp $ */
+/* $Id: message.c,v 1.254.186.3 2011-06-21 20:15:47 each Exp $ */
/*! \file */
@@ -1804,6 +1804,36 @@ wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
return (ISC_TRUE);
}
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+/*
+ * Decide whether to not answer with an AAAA record and its RRSIG
+ */
+static inline isc_boolean_t
+norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options)
+{
+ switch (rdataset->type) {
+ case dns_rdatatype_aaaa:
+ if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0)
+ return (ISC_FALSE);
+ break;
+
+ case dns_rdatatype_rrsig:
+ if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 ||
+ rdataset->covers != dns_rdatatype_aaaa)
+ return (ISC_FALSE);
+ break;
+
+ default:
+ return (ISC_FALSE);
+ }
+
+ if (rdataset->rdclass != dns_rdataclass_in)
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
+
+#endif
isc_result_t
dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
unsigned int options)
@@ -1931,6 +1961,23 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
preferred_glue))
goto next;
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ /*
+ * Suppress AAAAs if asked and we are
+ * not doing DNSSEC or are breaking DNSSEC.
+ * Say so in the AD bit if we break DNSSEC.
+ */
+ if (norender_rdataset(rdataset, options) &&
+ sectionid != DNS_SECTION_QUESTION) {
+ if (sectionid == DNS_SECTION_ANSWER ||
+ sectionid == DNS_SECTION_AUTHORITY)
+ msg->flags &= ~DNS_MESSAGEFLAG_AD;
+ if (OPTOUT(rdataset))
+ msg->flags &= ~DNS_MESSAGEFLAG_AD;
+ goto next;
+ }
+
+#endif
st = *(msg->buffer);
count = 0;
@@ -3071,6 +3118,7 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
dns_name_t *name, empty_name;
dns_rdataset_t *rdataset;
isc_result_t result;
+ isc_boolean_t seensoa = ISC_FALSE;
REQUIRE(DNS_MESSAGE_VALID(msg));
REQUIRE(target != NULL);
@@ -3100,6 +3148,15 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
for (rdataset = ISC_LIST_HEAD(name->list);
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (section == DNS_SECTION_ANSWER &&
+ rdataset->type == dns_rdatatype_soa) {
+ if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0)
+ continue;
+ if (seensoa &&
+ (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0)
+ continue;
+ seensoa = ISC_TRUE;
+ }
if (section == DNS_SECTION_QUESTION) {
ADD_STRING(target, ";");
result = dns_master_questiontotext(name,
diff --git a/contrib/bind9/lib/dns/name.c b/contrib/bind9/lib/dns/name.c
index 80864b8..f88f281 100644
--- a/contrib/bind9/lib/dns/name.c
+++ b/contrib/bind9/lib/dns/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: name.c,v 1.165.120.3 2010-07-09 05:15:05 each Exp $ */
+/* $Id: name.c,v 1.174 2011-01-13 04:59:25 tbox Exp $ */
/*! \file */
@@ -34,6 +34,7 @@
#include <isc/util.h>
#include <dns/compress.h>
+#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/result.h>
@@ -1018,10 +1019,9 @@ dns_name_toregion(dns_name_t *name, isc_region_t *r) {
DNS_NAME_TOREGION(name, r);
}
-
isc_result_t
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
- dns_name_t *origin, unsigned int options,
+ const dns_name_t *origin, unsigned int options,
isc_buffer_t *target)
{
unsigned char *ndata, *label;
@@ -2360,6 +2360,75 @@ dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
snprintf(cp, size, "<unknown>");
}
+/*
+ * dns_name_tostring() -- similar to dns_name_format() but allocates its own
+ * memory.
+ */
+isc_result_t
+dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
+ isc_result_t result;
+ isc_buffer_t buf;
+ isc_region_t reg;
+ char *p, txt[DNS_NAME_FORMATSIZE];
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(target != NULL && *target == NULL);
+
+ isc_buffer_init(&buf, txt, sizeof(txt));
+ result = dns_name_totext(name, ISC_FALSE, &buf);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ isc_buffer_usedregion(&buf, &reg);
+ p = isc_mem_allocate(mctx, reg.length + 1);
+ memcpy(p, (char *) reg.base, (int) reg.length);
+ p[reg.length] = '\0';
+
+ *target = p;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * dns_name_fromstring() -- convert directly from a string to a name,
+ * allocating memory as needed
+ */
+isc_result_t
+dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
+ isc_mem_t *mctx)
+{
+ return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
+}
+
+isc_result_t
+dns_name_fromstring2(dns_name_t *target, const char *src,
+ const dns_name_t *origin, unsigned int options,
+ isc_mem_t *mctx)
+{
+ isc_result_t result;
+ isc_buffer_t buf;
+ dns_fixedname_t fn;
+ dns_name_t *name;
+
+ REQUIRE(src != NULL);
+
+ isc_buffer_init(&buf, src, strlen(src));
+ isc_buffer_add(&buf, strlen(src));
+ if (BINDABLE(target) && target->buffer != NULL)
+ name = target;
+ else {
+ dns_fixedname_init(&fn);
+ name = dns_fixedname_name(&fn);
+ }
+
+ result = dns_name_fromtext(name, &buf, origin, options, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (name != target)
+ result = dns_name_dupwithoffsets(name, mctx, target);
+ return (result);
+}
+
isc_result_t
dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
unsigned char *ndata;
diff --git a/contrib/bind9/lib/dns/ncache.c b/contrib/bind9/lib/dns/ncache.c
index f1fc323..420a118 100644
--- a/contrib/bind9/lib/dns/ncache.c
+++ b/contrib/bind9/lib/dns/ncache.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.c,v 1.43.48.7.6.3 2011-06-21 20:13:22 each Exp $ */
+/* $Id: ncache.c,v 1.50.124.1.2.3 2011-06-21 20:15:47 each Exp $ */
/*! \file */
@@ -35,7 +35,7 @@
#define DNS_NCACHE_RDATA 20U
/*
- * The format of an ncache rdata is a sequence of one or more records of
+ * The format of an ncache rdata is a sequence of zero or more records of
* the following format:
*
* owner name
@@ -223,42 +223,6 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
return (result);
if (trust == 0xffff) {
- /*
- * We didn't find any authority data from which to create a
- * negative cache rdataset. In particular, we have no SOA.
- *
- * We trust that the caller wants negative caching, so this
- * means we have a "type 3 nxdomain" or "type 3 nodata"
- * response (see RFC2308 for details).
- *
- * We will now build a suitable negative cache rdataset that
- * will cause zero bytes to be emitted when converted to
- * wire format.
- */
-
- /*
- * The ownername must exist, but it doesn't matter what value
- * it has. We use the root name.
- */
- dns_name_toregion(dns_rootname, &r);
- result = isc_buffer_copyregion(&buffer, &r);
- if (result != ISC_R_SUCCESS)
- return (result);
- /*
- * Copy the type and a zero rdata count to the buffer.
- */
- isc_buffer_availableregion(&buffer, &r);
- if (r.length < 5)
- return (ISC_R_NOSPACE);
- isc_buffer_putuint16(&buffer, 0); /* type */
- /*
- * RFC2308, section 5, says that negative answers without
- * SOAs should not be cached.
- */
- ttl = 0;
- /*
- * Set trust.
- */
if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 &&
message->counts[DNS_SECTION_ANSWER] == 0) {
/*
@@ -268,22 +232,7 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
trust = dns_trust_authauthority;
} else
trust = dns_trust_additional;
- isc_buffer_putuint8(&buffer, (unsigned char)trust); /* trust */
- isc_buffer_putuint16(&buffer, 0); /* count */
-
- /*
- * 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);
+ ttl = 0;
}
INSIST(trust != 0xffff);
diff --git a/contrib/bind9/lib/dns/nsec.c b/contrib/bind9/lib/dns/nsec.c
index 7d93ecc..94c5163 100644
--- a/contrib/bind9/lib/dns/nsec.c
+++ b/contrib/bind9/lib/dns/nsec.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec.c,v 1.11.48.2 2009-01-06 23:47:26 tbox Exp $ */
+/* $Id: nsec.c,v 1.13 2009-01-06 23:47:57 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/dns/nsec3.c b/contrib/bind9/lib/dns/nsec3.c
index 9c85781..e75e744 100644
--- a/contrib/bind9/lib/dns/nsec3.c
+++ b/contrib/bind9/lib/dns/nsec3.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2006, 2008-2010 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: nsec3.c,v 1.6.12.4 2009-11-03 23:47:46 tbox Exp $ */
+/* $Id: nsec3.c,v 1.19.96.1 2011-06-21 20:15:48 each Exp $ */
#include <config.h>
@@ -28,6 +28,8 @@
#include <dst/dst.h>
#include <dns/db.h>
+#include <dns/zone.h>
+#include <dns/compress.h>
#include <dns/dbiterator.h>
#include <dns/diff.h>
#include <dns/fixedname.h>
@@ -472,7 +474,6 @@ delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
return (result);
}
-#ifndef RFC5155_STRICT
static isc_boolean_t
better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
dns_rdataset_t rdataset;
@@ -487,7 +488,17 @@ better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_rdataset_current(&rdataset, &rdata);
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+
+ if (rdataset.type != dns_rdatatype_nsec3param) {
+ dns_rdata_t tmprdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &tmprdata);
+ if (!dns_nsec3param_fromprivate(&tmprdata, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ } else
+ dns_rdataset_current(&rdataset, &rdata);
+
if (rdata.length != param->length)
continue;
if (rdata.data[0] != param->data[0] ||
@@ -505,7 +516,6 @@ better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
dns_rdataset_disassociate(&rdataset);
return (ISC_FALSE);
}
-#endif
static isc_result_t
find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
@@ -548,7 +558,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
dns_rdataset_t rdataset;
int pass;
isc_boolean_t exists;
- isc_boolean_t remove_unsecure = ISC_FALSE;
+ isc_boolean_t maybe_remove_unsecure = ISC_FALSE;
isc_uint8_t flags;
isc_buffer_t buffer;
isc_result_t result;
@@ -629,8 +639,12 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
*/
if (!unsecure)
goto addnsec3;
- else
- remove_unsecure = ISC_TRUE;
+ else if (CREATE(nsec3param->flags) && OPTOUT(flags)) {
+ result = dns_nsec3_delnsec3(db, version, name,
+ nsec3param, diff);
+ goto failure;
+ } else
+ maybe_remove_unsecure = ISC_TRUE;
} else {
dns_rdataset_disassociate(&rdataset);
if (result != ISC_R_NOMORE)
@@ -666,26 +680,19 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
if (result != ISC_R_SUCCESS)
goto failure;
- if (remove_unsecure) {
+ if (maybe_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 we have OPTOUT set in the previous NSEC3 record
+ * we actually need to delete the NSEC3 record.
+ * Otherwise we just need to replace the NSEC3 record.
*/
- if (!OPTOUT(nsec3.flags)) {
- /*
- * Just update the NSEC3 record.
- */
- goto addnsec3;
- } else {
- /*
- * This is actually a deletion not a add.
- */
+ if (OPTOUT(nsec3.flags)) {
result = dns_nsec3_delnsec3(db, version, name,
nsec3param, diff);
goto failure;
}
+ goto addnsec3;
} else {
/*
* Is this is a unsecure delegation we are adding?
@@ -928,17 +935,323 @@ dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(&rdataset, &rdata);
- dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
+
+ if (nsec3param.flags != 0)
+ continue;
+ /*
+ * 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_boolean_t
+dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
+ unsigned char *buf, size_t buflen)
+{
+ dns_decompress_t dctx;
+ isc_result_t result;
+ isc_buffer_t buf1;
+ isc_buffer_t buf2;
+
+ /*
+ * Algorithm 0 (reserved by RFC 4034) is used to identify
+ * NSEC3PARAM records from DNSKEY pointers.
+ */
+ if (src->length < 1 || src->data[0] != 0)
+ return (ISC_FALSE);
+
+ isc_buffer_init(&buf1, src->data + 1, src->length - 1);
+ isc_buffer_add(&buf1, src->length - 1);
+ isc_buffer_setactive(&buf1, src->length - 1);
+ isc_buffer_init(&buf2, buf, buflen);
+ dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
+ result = dns_rdata_fromwire(target, src->rdclass,
+ dns_rdatatype_nsec3param,
+ &buf1, &dctx, 0, &buf2);
+ dns_decompress_invalidate(&dctx);
+
+ return (ISC_TF(result == ISC_R_SUCCESS));
+}
+
+void
+dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
+ dns_rdatatype_t privatetype,
+ unsigned char *buf, size_t buflen)
+{
+ REQUIRE(buflen >= src->length + 1);
+
+ REQUIRE(DNS_RDATA_INITIALIZED(target));
+
+ memcpy(buf + 1, src->data, src->length);
+ buf[0] = 0;
+ target->data = buf;
+ target->length = src->length + 1;
+ target->type = privatetype;
+ target->rdclass = src->rdclass;
+ target->flags = 0;
+ ISC_LINK_INIT(target, link);
+}
+
+#ifdef BIND9
+static isc_result_t
+rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ const dns_rdata_t *rdata, isc_boolean_t *flag)
+{
+ dns_rdataset_t rdataset;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ if (rdata->type == dns_rdatatype_nsec3)
+ CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
+ else
+ CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
+ result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ *flag = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ goto failure;
+ }
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t myrdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &myrdata);
+ if (!dns_rdata_casecompare(&myrdata, rdata))
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS) {
+ *flag = ISC_TRUE;
+ } else if (result == ISC_R_NOMORE) {
+ *flag = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ }
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+#endif
+
+#ifdef BIND9
+isc_result_t
+dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
+ dns_zone_t *zone, dns_diff_t *diff)
+{
+ dns_dbnode_t *node = NULL;
+ dns_difftuple_t *tuple = NULL;
+ dns_name_t next;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ isc_boolean_t flag;
+ isc_result_t result = ISC_R_SUCCESS;
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1];
+ dns_name_t *origin = dns_zone_getorigin(zone);
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
+
+ dns_name_init(&next, NULL);
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Cause all NSEC3 chains to be deleted.
+ */
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
+ 0, (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto try_private;
+ 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 private = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &rdata);
+
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin,
+ rdataset.ttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, ver, diff));
+ INSIST(tuple == NULL);
+
+ dns_nsec3param_toprivate(&rdata, &private, privatetype,
+ buf, sizeof(buf));
+ buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
+
+ CHECK(rr_exists(db, ver, origin, &private, &flag));
+
+ if (!flag) {
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ origin, 0, &private,
+ &tuple));
+ CHECK(do_one_tuple(&tuple, db, ver, diff));
+ INSIST(tuple == NULL);
+ }
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ dns_rdataset_disassociate(&rdataset);
+
+ try_private:
+ if (privatetype == 0)
+ goto success;
+ result = dns_db_findrdataset(db, node, ver, privatetype, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto 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);
+ INSIST(rdata.length <= sizeof(buf));
+ memcpy(buf, rdata.data, rdata.length);
+
+ if (buf[0] != 0 ||
+ buf[2] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) {
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin,
+ 0, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, ver, diff));
+ INSIST(tuple == NULL);
+
+ rdata.data = buf;
+ buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
+
+ CHECK(rr_exists(db, ver, origin, &rdata, &flag));
+
+ if (!flag) {
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ origin, 0, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, ver, diff));
+ INSIST(tuple == NULL);
+ }
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ success:
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+#endif
+
+isc_result_t
+dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, dns_ttl_t nsecttl,
+ isc_boolean_t unsecure, dns_rdatatype_t type,
+ dns_diff_t *diff)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdataset_t rdataset;
+ dns_rdataset_t prdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&prdataset);
+
+ /*
+ * 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, type, 0, 0,
+ &prdataset, NULL);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ goto failure;
+
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3param, 0, 0,
+ &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto try_private;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * 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);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
-#ifdef RFC5155_STRICT
if (nsec3param.flags != 0)
continue;
-#else
+
+ /*
+ * We have a active chain. Update it.
+ */
+ CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
+ nsecttl, unsecure, diff));
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ dns_rdataset_disassociate(&rdataset);
+
+ try_private:
+ if (!dns_rdataset_isassociated(&prdataset))
+ goto success;
+ /*
+ * Update each active NSEC3 chain.
+ */
+ for (result = dns_rdataset_first(&prdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&prdataset)) {
+ dns_rdata_t rdata1 = DNS_RDATA_INIT;
+ dns_rdata_t rdata2 = DNS_RDATA_INIT;
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+
+ dns_rdataset_current(&prdataset, &rdata1);
+ if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
+ buf, sizeof(buf)))
+ continue;
+ CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
+
if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
continue;
- if (better_param(&rdataset, &rdata))
+ if (better_param(&prdataset, &rdata2))
continue;
-#endif
/*
* We have a active chain. Update it.
@@ -947,11 +1260,13 @@ dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
nsecttl, unsecure, diff));
}
if (result == ISC_R_NOMORE)
+ success:
result = ISC_R_SUCCESS;
-
failure:
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
+ if (dns_rdataset_isassociated(&prdataset))
+ dns_rdataset_disassociate(&prdataset);
if (node != NULL)
dns_db_detachnode(db, &node);
@@ -1120,6 +1435,8 @@ dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
*/
nsec3.next = nexthash;
nsec3.next_length = next_length;
+ if (CREATE(nsec3param->flags))
+ nsec3.flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
dns_rdatatype_nsec3, &nsec3,
@@ -1257,6 +1574,13 @@ isc_result_t
dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
dns_diff_t *diff)
{
+ return (dns_nsec3_delnsec3sx(db, version, name, 0, diff));
+}
+
+isc_result_t
+dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_rdatatype_t privatetype, dns_diff_t *diff)
+{
dns_dbnode_t *node = NULL;
dns_rdata_nsec3param_t nsec3param;
dns_rdataset_t rdataset;
@@ -1274,11 +1598,10 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
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);
+ goto try_private;
if (result != ISC_R_SUCCESS)
- return (result);
+ goto failure;
/*
* Update each active NSEC3 chain.
@@ -1289,17 +1612,47 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(&rdataset, &rdata);
- dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
-#ifdef RFC5155_STRICT
if (nsec3param.flags != 0)
continue;
-#else
+ /*
+ * We have a active chain. Update it.
+ */
+ CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ try_private:
+ if (privatetype == 0)
+ goto success;
+ result = dns_db_findrdataset(db, node, version, privatetype, 0, 0,
+ &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Update each NSEC3 chain being built.
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata1 = DNS_RDATA_INIT;
+ dns_rdata_t rdata2 = DNS_RDATA_INIT;
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+
+ dns_rdataset_current(&rdataset, &rdata1);
+ if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
+ buf, sizeof(buf)))
+ continue;
+ CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
+
if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
continue;
- if (better_param(&rdataset, &rdata))
+ if (better_param(&rdataset, &rdata2))
continue;
-#endif
/*
* We have a active chain. Update it.
@@ -1307,6 +1660,7 @@ dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
}
if (result == ISC_R_NOMORE)
+ success:
result = ISC_R_SUCCESS;
failure:
@@ -1322,6 +1676,14 @@ isc_result_t
dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
isc_boolean_t complete, isc_boolean_t *answer)
{
+ return (dns_nsec3_activex(db, version, complete, 0, answer));
+}
+
+isc_result_t
+dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t complete, dns_rdatatype_t privatetype,
+ isc_boolean_t *answer)
+{
dns_dbnode_t *node = NULL;
dns_rdataset_t rdataset;
dns_rdata_nsec3param_t nsec3param;
@@ -1338,34 +1700,78 @@ dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
result = dns_db_findrdataset(db, node, version,
dns_rdatatype_nsec3param, 0, 0,
&rdataset, NULL);
- dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ goto try_private;
+
+ 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_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)
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &node);
+ *answer = ISC_TRUE;
+ return (ISC_R_SUCCESS);
+ }
+ if (result == ISC_R_NOMORE)
+ *answer = ISC_FALSE;
+
+ try_private:
+ if (privatetype == 0 || complete) {
+ *answer = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ }
+ result = dns_db_findrdataset(db, node, version, privatetype, 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_rdata_t rdata1 = DNS_RDATA_INIT;
+ dns_rdata_t rdata2 = DNS_RDATA_INIT;
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
- dns_rdataset_current(&rdataset, &rdata);
- result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ dns_rdataset_current(&rdataset, &rdata1);
+ if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
+ buf, sizeof(buf)))
+ continue;
+ result = dns_rdata_tostruct(&rdata2, &nsec3param, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- if ((nsec3param.flags) == 0 ||
- (!complete && CREATE(nsec3param.flags)))
+ if (!complete && CREATE(nsec3param.flags))
break;
}
dns_rdataset_disassociate(&rdataset);
- if (result == ISC_R_SUCCESS)
+ if (result == ISC_R_SUCCESS) {
*answer = ISC_TRUE;
+ result = ISC_R_SUCCESS;
+ }
if (result == ISC_R_NOMORE) {
*answer = ISC_FALSE;
result = ISC_R_SUCCESS;
}
+
return (result);
}
diff --git a/contrib/bind9/lib/dns/openssl_link.c b/contrib/bind9/lib/dns/openssl_link.c
index 081e3c6..8c733f6 100644
--- a/contrib/bind9/lib/dns/openssl_link.c
+++ b/contrib/bind9/lib/dns/openssl_link.c
@@ -31,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: openssl_link.c,v 1.22.112.5 2010-09-15 12:37:35 tbox Exp $
+ * $Id: openssl_link.c,v 1.29 2010-09-15 12:38:36 tbox Exp $
*/
#ifdef OPENSSL
@@ -45,6 +45,8 @@
#include <isc/thread.h>
#include <isc/util.h>
+#include <dst/result.h>
+
#include "dst_internal.h"
#include "dst_openssl.h"
@@ -60,12 +62,6 @@
#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;
@@ -74,15 +70,7 @@ 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);
+static ENGINE *e = NULL;
#endif
static int
@@ -135,8 +123,16 @@ id_callback(void) {
static void *
mem_alloc(size_t size) {
+#ifdef OPENSSL_LEAKS
+ void *ptr;
+
+ INSIST(dst__memory_pool != NULL);
+ ptr = isc_mem_allocate(dst__memory_pool, size);
+ return (ptr);
+#else
INSIST(dst__memory_pool != NULL);
return (isc_mem_allocate(dst__memory_pool, size));
+#endif
}
static void
@@ -148,16 +144,26 @@ mem_free(void *ptr) {
static void *
mem_realloc(void *ptr, size_t size) {
+#ifdef OPENSSL_LEAKS
+ void *rptr;
+
+ INSIST(dst__memory_pool != NULL);
+ rptr = isc_mem_reallocate(dst__memory_pool, ptr, size);
+ return (rptr);
+#else
INSIST(dst__memory_pool != NULL);
return (isc_mem_reallocate(dst__memory_pool, ptr, size));
+#endif
}
isc_result_t
-dst__openssl_init() {
+dst__openssl_init(const char *engine) {
isc_result_t result;
#ifdef USE_ENGINE
- /* const char *name; */
ENGINE *re;
+#else
+
+ UNUSED(engine);
#endif
#ifdef DNS_CRYPTO_LEAKS
@@ -187,70 +193,26 @@ dst__openssl_init() {
rm->add = entropy_add;
rm->pseudorand = entropy_getpseudo;
rm->status = entropy_status;
+
#ifdef USE_ENGINE
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;
- }
-#endif /* USE_PKCS11 */
- if (engine_id != NULL) {
- e = ENGINE_by_id(engine_id);
+
+ if (engine != NULL && *engine == '\0')
+ engine = NULL;
+
+ if (engine != NULL) {
+ e = ENGINE_by_id(engine);
if (e == NULL) {
- result = ISC_R_NOTFOUND;
+ result = DST_R_NOENGINE;
goto cleanup_rm;
}
- if (!ENGINE_init(e)) {
- result = ISC_R_FAILURE;
- ENGINE_free(e);
+ /* This will init the engine. */
+ if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
+ result = DST_R_NOENGINE;
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();
@@ -263,7 +225,6 @@ dst__openssl_init() {
ENGINE_free(re);
} else
ENGINE_finish(re);
-
#else
RAND_set_rand_method(rm);
#endif /* USE_ENGINE */
@@ -271,13 +232,18 @@ dst__openssl_init() {
#ifdef USE_ENGINE
cleanup_rm:
+ if (e != NULL)
+ ENGINE_free(e);
+ e = NULL;
mem_free(rm);
+ rm = NULL;
#endif
cleanup_mutexinit:
CRYPTO_set_locking_callback(NULL);
DESTROYMUTEXBLOCK(locks, nlocks);
cleanup_mutexalloc:
mem_free(locks);
+ locks = NULL;
return (result);
}
@@ -287,15 +253,22 @@ dst__openssl_destroy() {
/*
* Sequence taken from apps_shutdown() in <apps/apps.h>.
*/
+ if (rm != NULL) {
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+ RAND_cleanup();
+#endif
+ mem_free(rm);
+ rm = NULL;
+ }
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
- CONF_modules_unload(1);
+ CONF_modules_free();
#endif
+ OBJ_cleanup();
EVP_cleanup();
#if defined(USE_ENGINE)
- if (e != NULL) {
- ENGINE_finish(e);
- e = NULL;
- }
+ if (e != NULL)
+ ENGINE_free(e);
+ e = NULL;
#if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
ENGINE_cleanup();
#endif
@@ -304,23 +277,18 @@ dst__openssl_destroy() {
CRYPTO_cleanup_all_ex_data();
#endif
ERR_clear_error();
- ERR_free_strings();
ERR_remove_state(0);
+ ERR_free_strings();
#ifdef DNS_CRYPTO_LEAKS
CRYPTO_mem_leaks_fp(stderr);
#endif
- if (rm != NULL) {
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
- RAND_cleanup();
-#endif
- mem_free(rm);
- }
if (locks != NULL) {
CRYPTO_set_locking_callback(NULL);
DESTROYMUTEXBLOCK(locks, nlocks);
mem_free(locks);
+ locks = NULL;
}
}
@@ -341,91 +309,18 @@ dst__openssl_toresult(isc_result_t fallback) {
}
ENGINE *
-dst__openssl_getengine(const char *name) {
-
- UNUSED(name);
-
+dst__openssl_getengine(const char *engine) {
+ if (engine == NULL)
+ return (NULL);
#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);
+ return (NULL);
+ if (strcmp(engine, ENGINE_get_id(e)) == 0)
+ return (e);
+#endif
+ return (NULL);
}
-#endif /* USE_PKCS11 */
#else /* OPENSSL */
diff --git a/contrib/bind9/lib/dns/openssldh_link.c b/contrib/bind9/lib/dns/openssldh_link.c
index e31137f..9deda6b 100644
--- a/contrib/bind9/lib/dns/openssldh_link.c
+++ b/contrib/bind9/lib/dns/openssldh_link.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2009, 2011 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
@@ -31,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: openssldh_link.c,v 1.14 2008-04-01 23:47:10 tbox Exp $
+ * $Id: openssldh_link.c,v 1.20 2011-01-11 23:47:13 tbox Exp $
*/
#ifdef OPENSSL
@@ -149,12 +149,37 @@ openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
return (ISC_TRUE);
}
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+static int
+progress_cb(int p, int n, BN_GENCB *cb)
+{
+ union {
+ void *dptr;
+ void (*fptr)(int);
+ } u;
+
+ UNUSED(n);
+
+ u.dptr = cb->arg;
+ if (u.fptr != NULL)
+ u.fptr(p);
+ return (1);
+}
+#endif
+
static isc_result_t
-openssldh_generate(dst_key_t *key, int generator) {
+openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
+ DH *dh = NULL;
#if OPENSSL_VERSION_NUMBER > 0x00908000L
BN_GENCB cb;
+ union {
+ void *dptr;
+ void (*fptr)(int);
+ } u;
+#else
+
+ UNUSED(callback);
#endif
- DH *dh = NULL;
if (generator == 0) {
if (key->key_size == 768 ||
@@ -181,7 +206,12 @@ openssldh_generate(dst_key_t *key, int generator) {
if (dh == NULL)
return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
- BN_GENCB_set_old(&cb, NULL, NULL);
+ if (callback == NULL) {
+ BN_GENCB_set_old(&cb, NULL, NULL);
+ } else {
+ u.fptr = callback;
+ BN_GENCB_set(&cb, &progress_cb, u.dptr);
+ }
if (!DH_generate_parameters_ex(dh, key->key_size, generator,
&cb)) {
@@ -476,7 +506,7 @@ openssldh_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-openssldh_parse(dst_key_t *key, isc_lex_t *lexer) {
+openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t ret;
int i;
@@ -484,6 +514,7 @@ openssldh_parse(dst_key_t *key, isc_lex_t *lexer) {
isc_mem_t *mctx;
#define DST_RET(a) {ret = a; goto err;}
+ UNUSED(pub);
mctx = key->mctx;
/* read private key file */
@@ -609,6 +640,8 @@ static dst_func_t openssldh_functions = {
openssldh_parse,
openssldh_cleanup,
NULL, /*%< fromlabel */
+ NULL, /*%< dump */
+ NULL, /*%< restore */
};
isc_result_t
diff --git a/contrib/bind9/lib/dns/openssldsa_link.c b/contrib/bind9/lib/dns/openssldsa_link.c
index c563d9b..ae88d4c 100644
--- a/contrib/bind9/lib/dns/openssldsa_link.c
+++ b/contrib/bind9/lib/dns/openssldsa_link.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2009, 2011 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
@@ -29,7 +29,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: openssldsa_link.c,v 1.13.120.2 2009-01-14 23:47:26 tbox Exp $ */
+/* $Id: openssldsa_link.c,v 1.20 2011-01-11 23:47:13 tbox Exp $ */
#ifdef OPENSSL
#ifndef USE_EVP
@@ -313,15 +313,40 @@ openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
return (ISC_TRUE);
}
-static isc_result_t
-openssldsa_generate(dst_key_t *key, int unused) {
#if OPENSSL_VERSION_NUMBER > 0x00908000L
- BN_GENCB cb;
+static int
+progress_cb(int p, int n, BN_GENCB *cb)
+{
+ union {
+ void *dptr;
+ void (*fptr)(int);
+ } u;
+
+ UNUSED(n);
+
+ u.dptr = cb->arg;
+ if (u.fptr != NULL)
+ u.fptr(p);
+ return (1);
+}
#endif
+
+static isc_result_t
+openssldsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
DSA *dsa;
unsigned char rand_array[ISC_SHA1_DIGESTLENGTH];
isc_result_t result;
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+ BN_GENCB cb;
+ union {
+ void *dptr;
+ void (*fptr)(int);
+ } u;
+
+#else
+ UNUSED(callback);
+#endif
UNUSED(unused);
result = dst__entropy_getdata(rand_array, sizeof(rand_array),
@@ -334,7 +359,12 @@ openssldsa_generate(dst_key_t *key, int unused) {
if (dsa == NULL)
return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
- BN_GENCB_set_old(&cb, NULL, NULL);
+ if (callback == NULL) {
+ BN_GENCB_set_old(&cb, NULL, NULL);
+ } else {
+ u.fptr = callback;
+ BN_GENCB_set(&cb, &progress_cb, u.dptr);
+ }
if (!DSA_generate_parameters_ex(dsa, key->key_size, rand_array,
ISC_SHA1_DIGESTLENGTH, NULL, NULL,
@@ -512,7 +542,7 @@ openssldsa_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-openssldsa_parse(dst_key_t *key, isc_lex_t *lexer) {
+openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t ret;
int i;
@@ -520,6 +550,7 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer) {
isc_mem_t *mctx = key->mctx;
#define DST_RET(a) {ret = a; goto err;}
+ UNUSED(pub);
/* read private key file */
ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
if (ret != ISC_R_SUCCESS)
@@ -587,6 +618,8 @@ static dst_func_t openssldsa_functions = {
openssldsa_parse,
NULL, /*%< cleanup */
NULL, /*%< fromlabel */
+ NULL, /*%< dump */
+ NULL, /*%< restore */
};
isc_result_t
diff --git a/contrib/bind9/lib/dns/opensslgost_link.c b/contrib/bind9/lib/dns/opensslgost_link.c
new file mode 100644
index 0000000..1b029db
--- /dev/null
+++ b/contrib/bind9/lib/dns/opensslgost_link.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2010, 2011 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: opensslgost_link.c,v 1.5 2011-01-19 23:47:12 tbox Exp $ */
+
+#include <config.h>
+
+#ifdef HAVE_OPENSSL_GOST
+
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dst/result.h>
+
+#include "dst_internal.h"
+#include "dst_openssl.h"
+#include "dst_parse.h"
+
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+#include <openssl/engine.h>
+
+static ENGINE *e = NULL;
+static const EVP_MD *opensslgost_digest;
+extern const EVP_MD *EVP_gost(void);
+
+const EVP_MD *EVP_gost(void) {
+ return (opensslgost_digest);
+}
+
+#define DST_RET(a) {ret = a; goto err;}
+
+static isc_result_t opensslgost_todns(const dst_key_t *key,
+ isc_buffer_t *data);
+
+static isc_result_t
+opensslgost_createctx(dst_key_t *key, dst_context_t *dctx) {
+ EVP_MD_CTX *evp_md_ctx;
+ const EVP_MD *md = EVP_gost();
+
+ UNUSED(key);
+
+ if (md == NULL)
+ return (DST_R_OPENSSLFAILURE);
+
+ evp_md_ctx = EVP_MD_CTX_create();
+ if (evp_md_ctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (!EVP_DigestInit_ex(evp_md_ctx, md, NULL)) {
+ EVP_MD_CTX_destroy(evp_md_ctx);
+ return (ISC_R_FAILURE);
+ }
+ dctx->ctxdata.evp_md_ctx = evp_md_ctx;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+opensslgost_destroyctx(dst_context_t *dctx) {
+ 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;
+ }
+}
+
+static isc_result_t
+opensslgost_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ 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);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+opensslgost_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ dst_key_t *key = dctx->key;
+ isc_region_t r;
+ unsigned int siglen = 0;
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+ EVP_PKEY *pkey = key->keydata.pkey;
+
+ isc_buffer_availableregion(sig, &r);
+
+ 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);
+
+ isc_buffer_add(sig, siglen);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+opensslgost_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ dst_key_t *key = dctx->key;
+ int status = 0;
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+ EVP_PKEY *pkey = key->keydata.pkey;
+
+ status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey);
+ if (status != 1)
+ return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+opensslgost_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ EVP_PKEY *pkey1, *pkey2;
+
+ pkey1 = key1->keydata.pkey;
+ pkey2 = key2->keydata.pkey;
+
+ if (pkey1 == NULL && pkey2 == NULL)
+ return (ISC_TRUE);
+ else if (pkey1 == NULL || pkey2 == NULL)
+ return (ISC_FALSE);
+
+ if (EVP_PKEY_cmp(pkey1, pkey2) != 1)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+static int
+progress_cb(EVP_PKEY_CTX *ctx)
+{
+ union {
+ void *dptr;
+ void (*fptr)(int);
+ } u;
+ int p;
+
+ u.dptr = EVP_PKEY_CTX_get_app_data(ctx);
+ p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+ if (u.fptr != NULL)
+ u.fptr(p);
+ return (1);
+}
+
+static isc_result_t
+opensslgost_generate(dst_key_t *key, int unused, void (*callback)(int)) {
+ EVP_PKEY_CTX *ctx;
+ union {
+ void *dptr;
+ void (*fptr)(int);
+ } u;
+ EVP_PKEY *pkey = NULL;
+
+ UNUSED(unused);
+ ctx = EVP_PKEY_CTX_new_id(NID_id_GostR3410_2001, NULL);
+ if (ctx == NULL)
+ goto err;
+ if (callback != NULL) {
+ u.fptr = callback;
+ EVP_PKEY_CTX_set_app_data(ctx, u.dptr);
+ EVP_PKEY_CTX_set_cb(ctx, &progress_cb);
+ }
+ if (EVP_PKEY_keygen_init(ctx) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0)
+ goto err;
+ if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
+ goto err;
+ key->keydata.pkey = pkey;
+ EVP_PKEY_CTX_free(ctx);
+ return (ISC_R_SUCCESS);
+
+err:
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ if (ctx != NULL)
+ EVP_PKEY_CTX_free(ctx);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+}
+
+static isc_boolean_t
+opensslgost_isprivate(const dst_key_t *key) {
+ EVP_PKEY *pkey = key->keydata.pkey;
+ EC_KEY *ec;
+
+ INSIST(pkey != NULL);
+
+ ec = EVP_PKEY_get0(pkey);
+ return (ISC_TF(ec != NULL && EC_KEY_get0_private_key(ec) != NULL));
+}
+
+static void
+opensslgost_destroy(dst_key_t *key) {
+ EVP_PKEY *pkey = key->keydata.pkey;
+
+ EVP_PKEY_free(pkey);
+ key->keydata.pkey = NULL;
+}
+
+unsigned char gost_prefix[37] = {
+ 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
+ 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07,
+ 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01, 0x06,
+ 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01,
+ 0x03, 0x43, 0x00, 0x04, 0x40
+};
+
+static isc_result_t
+opensslgost_todns(const dst_key_t *key, isc_buffer_t *data) {
+ EVP_PKEY *pkey;
+ isc_region_t r;
+ unsigned char der[37 + 64], *p;
+ int len;
+
+ REQUIRE(key->keydata.pkey != NULL);
+
+ pkey = key->keydata.pkey;
+
+ isc_buffer_availableregion(data, &r);
+ if (r.length < 64)
+ return (ISC_R_NOSPACE);
+
+ p = der;
+ len = i2d_PUBKEY(pkey, &p);
+ INSIST(len == sizeof(der));
+ INSIST(memcmp(gost_prefix, der, 37) == 0);
+ memcpy(r.base, der + 37, 64);
+ isc_buffer_add(data, 64);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+opensslgost_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ isc_region_t r;
+ EVP_PKEY *pkey = NULL;
+ unsigned char der[37 + 64];
+ const unsigned char *p;
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ if (r.length != 64)
+ return (DST_R_INVALIDPUBLICKEY);
+ memcpy(der, gost_prefix, 37);
+ memcpy(der + 37, r.base, 64);
+ isc_buffer_forward(data, 64);
+
+ p = der;
+ if (d2i_PUBKEY(&pkey, &p, (long) sizeof(der)) == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ key->keydata.pkey = pkey;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+opensslgost_tofile(const dst_key_t *key, const char *directory) {
+ EVP_PKEY *pkey;
+ dst_private_t priv;
+ isc_result_t result;
+ unsigned char *der, *p;
+ int len;
+
+ if (key->keydata.pkey == NULL)
+ return (DST_R_NULLKEY);
+
+ pkey = key->keydata.pkey;
+
+ len = i2d_PrivateKey(pkey, NULL);
+ der = isc_mem_get(key->mctx, (size_t) len);
+ if (der == NULL)
+ return (ISC_R_NOMEMORY);
+
+ p = der;
+ if (i2d_PrivateKey(pkey, &p) != len) {
+ result = dst__openssl_toresult(DST_R_OPENSSLFAILURE);
+ goto fail;
+ }
+
+ priv.elements[0].tag = TAG_GOST_PRIVASN1;
+ priv.elements[0].length = len;
+ priv.elements[0].data = der;
+ priv.nelements = GOST_NTAGS;
+
+ result = dst__privstruct_writefile(key, &priv, directory);
+ fail:
+ if (der != NULL)
+ isc_mem_put(key->mctx, der, (size_t) len);
+ return (result);
+}
+
+static isc_result_t
+opensslgost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
+ dst_private_t priv;
+ isc_result_t ret;
+ isc_mem_t *mctx = key->mctx;
+ EVP_PKEY *pkey = NULL;
+ const unsigned char *p;
+
+ UNUSED(pub);
+
+ /* read private key file */
+ ret = dst__privstruct_parse(key, DST_ALG_ECCGOST, lexer, mctx, &priv);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1);
+ p = priv.elements[0].data;
+ if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
+ (long) priv.elements[0].length) == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ key->keydata.pkey = pkey;
+ key->key_size = EVP_PKEY_bits(pkey);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (ISC_R_SUCCESS);
+
+ err:
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ opensslgost_destroy(key);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (ret);
+}
+
+static void
+opensslgost_cleanup(void) {
+ if (e != NULL) {
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ e = NULL;
+ }
+}
+
+static dst_func_t opensslgost_functions = {
+ opensslgost_createctx,
+ opensslgost_destroyctx,
+ opensslgost_adddata,
+ opensslgost_sign,
+ opensslgost_verify,
+ NULL, /*%< computesecret */
+ opensslgost_compare,
+ NULL, /*%< paramcompare */
+ opensslgost_generate,
+ opensslgost_isprivate,
+ opensslgost_destroy,
+ opensslgost_todns,
+ opensslgost_fromdns,
+ opensslgost_tofile,
+ opensslgost_parse,
+ opensslgost_cleanup,
+ NULL, /*%< fromlabel */
+ NULL, /*%< dump */
+ NULL /*%< restore */
+};
+
+isc_result_t
+dst__opensslgost_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+
+ /* check if the gost engine works properly */
+ e = ENGINE_by_id("gost");
+ if (e == NULL)
+ return (DST_R_OPENSSLFAILURE);
+ if (ENGINE_init(e) <= 0) {
+ ENGINE_free(e);
+ e = NULL;
+ return (DST_R_OPENSSLFAILURE);
+ }
+ /* better than to rely on digest_gost symbol */
+ opensslgost_digest = ENGINE_get_digest(e, NID_id_GostR3411_94);
+ /* from openssl.cnf */
+ if ((opensslgost_digest == NULL) ||
+ (ENGINE_register_pkey_asn1_meths(e) <= 0) ||
+ (ENGINE_ctrl_cmd_string(e,
+ "CRYPT_PARAMS",
+ "id-Gost28147-89-CryptoPro-A-ParamSet",
+ 0) <= 0)) {
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ e = NULL;
+ return (DST_R_OPENSSLFAILURE);
+ }
+
+ if (*funcp == NULL)
+ *funcp = &opensslgost_functions;
+ return (ISC_R_SUCCESS);
+}
+
+#else /* HAVE_OPENSSL_GOST */
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
+
+#endif /* HAVE_OPENSSL_GOST */
+/*! \file */
diff --git a/contrib/bind9/lib/dns/opensslrsa_link.c b/contrib/bind9/lib/dns/opensslrsa_link.c
index 1e3c5c2..fcdc9f0 100644
--- a/contrib/bind9/lib/dns/opensslrsa_link.c
+++ b/contrib/bind9/lib/dns/opensslrsa_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -17,7 +17,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: opensslrsa_link.c,v 1.20.50.8 2010-01-22 02:36:49 marka Exp $
+ * $Id: opensslrsa_link.c,v 1.39 2011-01-11 23:47:13 tbox Exp $
*/
#ifdef OPENSSL
#include <config.h>
@@ -30,6 +30,7 @@
#endif
#endif
+
#include <isc/entropy.h>
#include <isc/md5.h>
#include <isc/sha1.h>
@@ -368,7 +369,7 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
RSA *rsa = key->keydata.rsa;
/* note: ISC_SHA512_DIGESTLENGTH >= ISC_*_DIGESTLENGTH */
unsigned char digest[PREFIXLEN + ISC_SHA512_DIGESTLENGTH];
- int status = 0;
+ int status;
int type = 0;
unsigned int digestlen = 0;
char *message;
@@ -703,10 +704,32 @@ opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
return (ISC_TRUE);
}
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+static int
+progress_cb(int p, int n, BN_GENCB *cb)
+{
+ union {
+ void *dptr;
+ void (*fptr)(int);
+ } u;
+
+ UNUSED(n);
+
+ u.dptr = cb->arg;
+ if (u.fptr != NULL)
+ u.fptr(p);
+ return (1);
+}
+#endif
+
static isc_result_t
-opensslrsa_generate(dst_key_t *key, int exp) {
+opensslrsa_generate(dst_key_t *key, int exp, void (*callback)(int)) {
#if OPENSSL_VERSION_NUMBER > 0x00908000L
BN_GENCB cb;
+ union {
+ void *dptr;
+ void (*fptr)(int);
+ } u;
RSA *rsa = RSA_new();
BIGNUM *e = BN_new();
#if USE_EVP
@@ -732,7 +755,12 @@ opensslrsa_generate(dst_key_t *key, int exp) {
BN_set_bit(e, 32);
}
- BN_GENCB_set_old(&cb, NULL, NULL);
+ if (callback == NULL) {
+ BN_GENCB_set_old(&cb, NULL, NULL);
+ } else {
+ u.fptr = callback;
+ BN_GENCB_set(&cb, &progress_cb, u.dptr);
+ }
if (RSA_generate_key_ex(rsa, key->key_size, e, &cb)) {
BN_free(e);
@@ -763,8 +791,12 @@ err:
#if USE_EVP
EVP_PKEY *pkey = EVP_PKEY_new();
+ UNUSED(callback);
+
if (pkey == NULL)
return (ISC_R_NOMEMORY);
+#else
+ UNUSED(callback);
#endif
if (exp == 0)
@@ -1059,8 +1091,9 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) {
i++;
}
+
priv.nelements = i;
- result = dst__privstruct_writefile(key, &priv, directory);
+ result = dst__privstruct_writefile(key, &priv, directory);
fail:
#if USE_EVP
RSA_free(rsa);
@@ -1074,16 +1107,52 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) {
}
static isc_result_t
-opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
+rsa_check(RSA *rsa, RSA *pub)
+{
+ /* Public parameters should be the same but if they are not set
+ * copy them from the public key. */
+ if (pub != NULL) {
+ if (rsa->n != NULL) {
+ if (BN_cmp(rsa->n, pub->n) != 0)
+ return (DST_R_INVALIDPRIVATEKEY);
+ } else {
+ rsa->n = pub->n;
+ pub->n = NULL;
+ }
+ if (rsa->e != NULL) {
+ if (BN_cmp(rsa->e, pub->e) != 0)
+ return (DST_R_INVALIDPRIVATEKEY);
+ } else {
+ rsa->e = pub->e;
+ pub->e = NULL;
+ }
+ }
+ if (rsa->n == NULL || rsa->e == NULL)
+ return (DST_R_INVALIDPRIVATEKEY);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t ret;
int i;
- RSA *rsa = NULL;
+ RSA *rsa = NULL, *pubrsa = NULL;
ENGINE *e = NULL;
isc_mem_t *mctx = key->mctx;
- const char *name = NULL, *label = NULL;
+ const char *engine = NULL, *label = NULL;
EVP_PKEY *pkey = NULL;
+#if USE_EVP
+ if (pub != NULL && pub->keydata.pkey != NULL)
+ pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey);
+#else
+ if (pub != NULL && pub->keydata.rsa != NULL) {
+ pubrsa = pub->keydata.rsa;
+ pub->keydata.rsa = NULL;
+ }
+#endif
+
/* read private key file */
ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
if (ret != ISC_R_SUCCESS)
@@ -1092,7 +1161,7 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
for (i = 0; i < priv.nelements; i++) {
switch (priv.elements[i].tag) {
case TAG_RSA_ENGINE:
- name = (char *)priv.elements[i].data;
+ engine = (char *)priv.elements[i].data;
break;
case TAG_RSA_LABEL:
label = (char *)priv.elements[i].data;
@@ -1105,10 +1174,10 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
* 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 (label != NULL) {
+ if (engine == NULL)
+ DST_RET(DST_R_NOENGINE);
+ e = dst__openssl_getengine(engine);
if (e == NULL)
DST_RET(DST_R_NOENGINE);
pkey = ENGINE_load_private_key(e, label, NULL, NULL);
@@ -1116,22 +1185,29 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
/* ERR_print_errors_fp(stderr); */
DST_RET(ISC_R_NOTFOUND);
}
- key->engine = isc_mem_strdup(key->mctx, name);
+ key->engine = isc_mem_strdup(key->mctx, engine);
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);
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL)
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
key->key_size = EVP_PKEY_bits(pkey);
#if USE_EVP
key->keydata.pkey = pkey;
+ RSA_free(rsa);
#else
- key->keydata.rsa = EVP_PKEY_get1_RSA(pkey);
- if (rsa == NULL)
- DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ key->keydata.rsa = rsa;
EVP_PKEY_free(pkey);
#endif
dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
return (ISC_R_SUCCESS);
}
@@ -1144,9 +1220,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
pkey = EVP_PKEY_new();
if (pkey == NULL)
DST_RET(ISC_R_NOMEMORY);
- if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
+ if (!EVP_PKEY_set1_RSA(pkey, rsa))
DST_RET(ISC_R_FAILURE);
- }
key->keydata.pkey = pkey;
#else
key->keydata.rsa = rsa;
@@ -1196,8 +1271,13 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
}
}
dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
key->key_size = BN_num_bits(rsa->n);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
#if USE_EVP
RSA_free(rsa);
#endif
@@ -1211,6 +1291,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
#endif
if (rsa != NULL)
RSA_free(rsa);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
opensslrsa_destroy(key);
dst__privstruct_free(&priv, mctx);
memset(&priv, 0, sizeof(priv));
@@ -1224,33 +1306,63 @@ opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
ENGINE *e = NULL;
isc_result_t ret;
EVP_PKEY *pkey = NULL;
+ RSA *rsa = NULL, *pubrsa = NULL;
+ char *colon;
UNUSED(pin);
+ if (engine == NULL)
+ DST_RET(DST_R_NOENGINE);
e = dst__openssl_getengine(engine);
if (e == NULL)
DST_RET(DST_R_NOENGINE);
+ pkey = ENGINE_load_public_key(e, label, NULL, NULL);
+ if (pkey != NULL) {
+ pubrsa = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (pubrsa == NULL)
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
pkey = ENGINE_load_private_key(e, label, NULL, NULL);
if (pkey == NULL)
DST_RET(ISC_R_NOTFOUND);
- key->engine = isc_mem_strdup(key->mctx, label);
- if (key->engine == NULL)
- DST_RET(ISC_R_NOMEMORY);
+ if (engine != NULL) {
+ key->engine = isc_mem_strdup(key->mctx, engine);
+ if (key->engine == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ } else {
+ key->engine = isc_mem_strdup(key->mctx, label);
+ if (key->engine == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ colon = strchr(key->engine, ':');
+ if (colon != NULL)
+ *colon = '\0';
+ }
key->label = isc_mem_strdup(key->mctx, label);
if (key->label == NULL)
DST_RET(ISC_R_NOMEMORY);
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL)
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
key->key_size = EVP_PKEY_bits(pkey);
#if USE_EVP
key->keydata.pkey = pkey;
+ RSA_free(rsa);
#else
- key->keydata.rsa = EVP_PKEY_get1_RSA(pkey);
+ key->keydata.rsa = rsa;
EVP_PKEY_free(pkey);
- if (key->keydata.rsa == NULL)
- return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
#endif
return (ISC_R_SUCCESS);
err:
+ if (rsa != NULL)
+ RSA_free(rsa);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
if (pkey != NULL)
EVP_PKEY_free(pkey);
return (ret);
@@ -1274,6 +1386,8 @@ static dst_func_t opensslrsa_functions = {
opensslrsa_parse,
NULL, /*%< cleanup */
opensslrsa_fromlabel,
+ NULL, /*%< dump */
+ NULL, /*%< restore */
};
isc_result_t
diff --git a/contrib/bind9/lib/dns/peer.c b/contrib/bind9/lib/dns/peer.c
index 1e81023..3851c3e 100644
--- a/contrib/bind9/lib/dns/peer.c
+++ b/contrib/bind9/lib/dns/peer.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: peer.c,v 1.31 2008-04-03 06:09:04 tbox Exp $ */
+/* $Id: peer.c,v 1.33 2009-09-02 23:48:02 tbox Exp $ */
/*! \file */
@@ -536,7 +536,7 @@ dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval) {
isc_buffer_init(&b, keyval, strlen(keyval));
isc_buffer_add(&b, strlen(keyval));
result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
return (result);
diff --git a/contrib/bind9/lib/dns/private.c b/contrib/bind9/lib/dns/private.c
new file mode 100644
index 0000000..ba3e8ed
--- /dev/null
+++ b/contrib/bind9/lib/dns/private.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 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: private.c,v 1.3 2009-10-09 23:48:09 tbox Exp $ */
+
+#include "config.h"
+
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/base64.h>
+
+#include <dns/nsec3.h>
+#include <dns/private.h>
+
+/*
+ * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
+ * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
+ *
+ * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
+ * if all the NSEC3PARAM records (and associated chains) are slated for
+ * destruction and we have not been told to NOT build the NSEC chain.
+ *
+ * If the NSEC set exist then check to see if there is a request to create
+ * a NSEC3 chain.
+ *
+ * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
+ * type exists then we need to examine it to determine if NSEC3 chain has
+ * been requested to be built otherwise a NSEC chain needs to be built.
+ */
+
+#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
+#define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
+#define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
+
+#define CHECK(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+/*
+ * Work out if 'param' should be ignored or not (i.e. it is in the process
+ * of being removed).
+ *
+ * Note: we 'belt-and-braces' here by also checking for a CREATE private
+ * record and keep the param record in this case.
+ */
+
+static isc_boolean_t
+ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
+ isc_result_t result;
+
+ for (result = dns_rdataset_first(privateset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(privateset)) {
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t private = DNS_RDATA_INIT;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(privateset, &private);
+ if (!dns_nsec3param_fromprivate(&private, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ /*
+ * We are going to create a new NSEC3 chain so it
+ * doesn't matter if we are removing this one.
+ */
+ if (CREATE(rdata.data[1]))
+ return (ISC_FALSE);
+ if (rdata.data[0] != param->data[0] ||
+ 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;
+ /*
+ * The removal of this NSEC3 chain does NOT cause a
+ * NSEC chain to be created so we don't need to tell
+ * the caller that it will be removed.
+ */
+ if (NONSEC(rdata.data[1]))
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+isc_result_t
+dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
+ dns_rdatatype_t privatetype,
+ isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3)
+{
+ dns_dbnode_t *node;
+ dns_rdataset_t nsecset, nsec3paramset, privateset;
+ isc_boolean_t nsec3chain;
+ isc_boolean_t signing;
+ isc_result_t result;
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ unsigned int count;
+
+ node = NULL;
+ dns_rdataset_init(&nsecset);
+ dns_rdataset_init(&nsec3paramset);
+ dns_rdataset_init(&privateset);
+
+ CHECK(dns_db_getoriginnode(db, &node));
+
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
+ 0, (isc_stdtime_t) 0, &nsecset, NULL);
+
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ goto failure;
+
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
+ 0, (isc_stdtime_t) 0, &nsec3paramset,
+ NULL);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ goto failure;
+
+ if (dns_rdataset_isassociated(&nsecset) &&
+ dns_rdataset_isassociated(&nsec3paramset)) {
+ if (build_nsec != NULL)
+ *build_nsec = ISC_TRUE;
+ if (build_nsec3 != NULL)
+ *build_nsec3 = ISC_TRUE;
+ goto success;
+ }
+
+ if (privatetype != (dns_rdatatype_t)0) {
+ result = dns_db_findrdataset(db, node, ver, privatetype,
+ 0, (isc_stdtime_t) 0,
+ &privateset, NULL);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ goto failure;
+ }
+
+ /*
+ * Look to see if we also need to be creating a NSEC3 chains.
+ */
+ if (dns_rdataset_isassociated(&nsecset)) {
+ if (build_nsec != NULL)
+ *build_nsec = ISC_TRUE;
+ if (build_nsec3 != NULL)
+ *build_nsec3 = ISC_FALSE;
+ if (!dns_rdataset_isassociated(&privateset))
+ goto success;
+ for (result = dns_rdataset_first(&privateset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&privateset)) {
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t private = DNS_RDATA_INIT;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&privateset, &private);
+ if (!dns_nsec3param_fromprivate(&private, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ if (REMOVE(rdata.data[1]))
+ continue;
+ if (build_nsec3 != NULL)
+ *build_nsec3 = ISC_TRUE;
+ break;
+ }
+ goto success;
+ }
+
+ if (dns_rdataset_isassociated(&nsec3paramset)) {
+ if (build_nsec3 != NULL)
+ *build_nsec3 = ISC_TRUE;
+ if (build_nsec != NULL)
+ *build_nsec = ISC_FALSE;
+ if (!dns_rdataset_isassociated(&privateset))
+ goto success;
+ /*
+ * If we are in the process of building a new NSEC3 chain
+ * then we don't need to build a NSEC chain.
+ */
+ for (result = dns_rdataset_first(&privateset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&privateset)) {
+ dns_rdata_t private = DNS_RDATA_INIT;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&privateset, &private);
+ if (!dns_nsec3param_fromprivate(&private, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ if (CREATE(rdata.data[1]))
+ goto success;
+ }
+
+ /*
+ * Check to see if there will be a active NSEC3CHAIN once
+ * the changes queued complete.
+ */
+ count = 0;
+ for (result = dns_rdataset_first(&nsec3paramset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&nsec3paramset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ /*
+ * If there is more that one NSEC3 chain present then
+ * we don't need to construct a NSEC chain.
+ */
+ if (++count > 1)
+ goto success;
+ dns_rdataset_current(&nsec3paramset, &rdata);
+ if (ignore(&rdata, &privateset))
+ continue;
+ /*
+ * We still have a good NSEC3 chain or we are
+ * not creating a NSEC chain as NONSEC is set.
+ */
+ goto success;
+ }
+
+ /*
+ * The last NSEC3 chain is being removed and does not have
+ * have NONSEC set.
+ */
+ if (build_nsec != NULL)
+ *build_nsec = ISC_TRUE;
+ goto success;
+ }
+
+ if (build_nsec != NULL)
+ *build_nsec = ISC_FALSE;
+ if (build_nsec3 != NULL)
+ *build_nsec3 = ISC_FALSE;
+ if (!dns_rdataset_isassociated(&privateset))
+ goto success;
+
+ signing = ISC_FALSE;
+ nsec3chain = ISC_FALSE;
+
+ for (result = dns_rdataset_first(&privateset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&privateset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t private = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&privateset, &private);
+ if (!dns_nsec3param_fromprivate(&private, &rdata,
+ buf, sizeof(buf))) {
+ /*
+ * Look for record that says we are signing the
+ * zone with a key.
+ */
+ if (private.length == 5 && private.data[0] != 0 &&
+ private.data[3] == 0 && private.data[4] == 0)
+ signing = ISC_TRUE;
+ } else {
+ if (CREATE(rdata.data[1]))
+ nsec3chain = ISC_TRUE;
+ }
+ }
+
+ if (signing) {
+ if (nsec3chain) {
+ if (build_nsec3 != NULL)
+ *build_nsec3 = ISC_TRUE;
+ } else {
+ if (build_nsec != NULL)
+ *build_nsec = ISC_TRUE;
+ }
+ }
+
+ success:
+ result = ISC_R_SUCCESS;
+ failure:
+ if (dns_rdataset_isassociated(&nsecset))
+ dns_rdataset_disassociate(&nsecset);
+ if (dns_rdataset_isassociated(&nsec3paramset))
+ dns_rdataset_disassociate(&nsec3paramset);
+ if (dns_rdataset_isassociated(&privateset))
+ dns_rdataset_disassociate(&privateset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
diff --git a/contrib/bind9/lib/dns/rbt.c b/contrib/bind9/lib/dns/rbt.c
index 5e09db3..6c14e8e 100644
--- a/contrib/bind9/lib/dns/rbt.c
+++ b/contrib/bind9/lib/dns/rbt.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbt.c,v 1.142.50.3 2009-10-20 05:06:04 marka Exp $ */
+/* $Id: rbt.c,v 1.146 2009-10-27 04:46:58 marka Exp $ */
/*! \file */
@@ -537,7 +537,10 @@ 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;
+ if (current->nsec == DNS_RBT_NSEC_HAS_NSEC)
+ new_current->nsec = DNS_RBT_NSEC_NORMAL;
+ else
+ new_current->nsec = current->nsec;
PARENT(new_current) = PARENT(current);
LEFT(new_current) = LEFT(current);
RIGHT(new_current) = RIGHT(current);
@@ -1451,7 +1454,7 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
DIRTY(node) = 0;
dns_rbtnode_refinit(node, 0);
node->find_callback = 0;
- node->nsec3 = 0;
+ node->nsec = DNS_RBT_NSEC_NORMAL;
MAKE_BLACK(node);
diff --git a/contrib/bind9/lib/dns/rbtdb.c b/contrib/bind9/lib/dns/rbtdb.c
index 87b70e3..d4415d8 100644
--- a/contrib/bind9/lib/dns/rbtdb.c
+++ b/contrib/bind9/lib/dns/rbtdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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.270.12.26.4.1 2011-06-21 20:13:23 each Exp $ */
+/* $Id: rbtdb.c,v 1.310.8.1.2.1 2011-06-21 20:15:48 each Exp $ */
/*! \file */
@@ -53,6 +53,7 @@
#include <dns/nsec.h>
#include <dns/nsec3.h>
#include <dns/rbt.h>
+#include <dns/rpz.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
@@ -441,7 +442,9 @@ typedef struct {
/* Locked by tree_lock. */
dns_rbt_t * tree;
+ dns_rbt_t * nsec;
dns_rbt_t * nsec3;
+ dns_rpz_cidr_t * rpz_cidr;
/* Unlocked */
unsigned int quantum;
@@ -621,8 +624,9 @@ 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);
+#ifdef BIND9
+static void setnsec3parameters(dns_db_t *db, rbtdb_version_t *version);
+#endif
/*%
* 'init_count' is used to initialize 'newheader->count' which inturn
@@ -830,6 +834,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
isc_ondestroy_t ondest;
isc_result_t result;
char buf[DNS_NAME_FORMATSIZE];
+ dns_rbt_t **treep;
isc_time_t start;
if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
@@ -866,33 +871,26 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
if (event == NULL)
rbtdb->quantum = (rbtdb->task != NULL) ? 100 : 0;
- again:
- if (rbtdb->tree != NULL) {
- isc_time_now(&start);
- result = dns_rbt_destroy2(&rbtdb->tree, 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;
+
+ for (;;) {
+ /*
+ * pick the next tree to (start to) destroy
+ */
+ treep = &rbtdb->tree;
+ if (*treep == NULL) {
+ treep = &rbtdb->nsec;
+ if (*treep == NULL) {
+ treep = &rbtdb->nsec3;
+ /*
+ * we're finished after clear cutting
+ */
+ if (*treep == NULL)
+ break;
+ }
}
- INSIST(result == ISC_R_SUCCESS && rbtdb->tree == NULL);
- }
- if (rbtdb->nsec3 != NULL) {
isc_time_now(&start);
- result = dns_rbt_destroy2(&rbtdb->nsec3, rbtdb->quantum);
+ result = dns_rbt_destroy2(treep, rbtdb->quantum);
if (result == ISC_R_QUOTA) {
INSIST(rbtdb->task != NULL);
if (rbtdb->quantum != 0)
@@ -906,11 +904,11 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
rbtdb,
sizeof(isc_event_t));
if (event == NULL)
- goto again;
+ continue;
isc_task_send(rbtdb->task, &event);
return;
}
- INSIST(result == ISC_R_SUCCESS && rbtdb->nsec3 == NULL);
+ INSIST(result == ISC_R_SUCCESS && *treep == NULL);
}
if (event != NULL)
@@ -965,6 +963,11 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
if (rbtdb->rrsetstats != NULL)
dns_stats_detach(&rbtdb->rrsetstats);
+#ifdef BIND9
+ if (rbtdb->rpz_cidr != NULL)
+ dns_rpz_cidr_free(&rbtdb->rpz_cidr);
+#endif
+
isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks,
rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));
isc_rwlock_destroy(&rbtdb->tree_lock);
@@ -1488,6 +1491,82 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
node->dirty = 0;
}
+static void
+delete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node)
+{
+ dns_rbtnode_t *nsecnode;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result = ISC_R_UNEXPECTED;
+
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+
+ switch (node->nsec) {
+ case DNS_RBT_NSEC_NORMAL:
+#ifdef BIND9
+ if (rbtdb->rpz_cidr != NULL) {
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_rbt_fullnamefromnode(node, name);
+ dns_rpz_cidr_deleteip(rbtdb->rpz_cidr, name);
+ }
+#endif
+ result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
+ break;
+ case DNS_RBT_NSEC_HAS_NSEC:
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_rbt_fullnamefromnode(node, name);
+ /*
+ * Delete the corresponding node from the auxiliary NSEC
+ * tree before deleting from the main tree.
+ */
+ nsecnode = NULL;
+ result = dns_rbt_findnode(rbtdb->nsec, name, NULL, &nsecnode,
+ NULL, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
+ "delete_node: "
+ "dns_rbt_findnode(nsec): %s",
+ isc_result_totext(result));
+ } else {
+ result = dns_rbt_deletenode(rbtdb->nsec, nsecnode,
+ ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_WARNING,
+ "delete_nsecnode(): "
+ "dns_rbt_deletenode(nsecnode): %s",
+ isc_result_totext(result));
+ }
+ }
+ result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
+#ifdef BIND9
+ dns_rpz_cidr_deleteip(rbtdb->rpz_cidr, name);
+#endif
+ break;
+ case DNS_RBT_NSEC_NSEC:
+ result = dns_rbt_deletenode(rbtdb->nsec, node, ISC_FALSE);
+ break;
+ case DNS_RBT_NSEC_NSEC3:
+ result = dns_rbt_deletenode(rbtdb->nsec3, node, ISC_FALSE);
+ break;
+ }
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_WARNING,
+ "delete_nsecnode(): "
+ "dns_rbt_deletenode: %s",
+ isc_result_totext(result));
+ }
+}
+
/*%
* 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
@@ -1499,7 +1578,6 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
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]);
@@ -1513,19 +1591,8 @@ cleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) {
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));
+ delete_node(rbtdb, node);
+
node = ISC_LIST_HEAD(rbtdb->deadnodes[bucketnum]);
count--;
}
@@ -1774,22 +1841,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
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));
- }
+ delete_node(rbtdb, node);
}
} else if (dns_rbtnode_refcurrent(node) == 0) {
INSIST(!ISC_LINK_LINKED(node, deadlink));
@@ -1925,13 +1977,17 @@ cleanup_nondirty(rbtdb_version_t *version, rbtdb_changedlist_t *cleanup_list) {
static void
iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) {
+#ifndef BIND9
+ UNUSED(db);
+ UNUSED(version);
+ UNUSED(origin);
+
+ return;
+#else
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);
@@ -1963,41 +2019,30 @@ iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) {
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);
}
- setnsec3parameters(db, version, &nsec3createflag);
+ setnsec3parameters(db, version);
/*
* Do we have a valid NSEC/NSEC3 chain?
*/
- if (version->havensec3 || (hasnsec && !hasoptbit))
+ if (version->havensec3 || hasnsec)
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;
+#endif
}
/*%<
* Walk the origin node looking for NSEC3PARAM records.
* Cache the nsec3 parameters.
*/
+#ifdef BIND9
static void
-setnsec3parameters(dns_db_t *db, rbtdb_version_t *version,
- isc_boolean_t *nsec3createflag)
-{
+setnsec3parameters(dns_db_t *db, rbtdb_version_t *version) {
dns_rbtnode_t *node;
dns_rdata_nsec3param_t nsec3param;
dns_rdata_t rdata = DNS_RDATA_INIT;
@@ -2028,7 +2073,7 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version,
} while (header != NULL);
if (header != NULL &&
- header->type == dns_rdatatype_nsec3param) {
+ (header->type == dns_rdatatype_nsec3param)) {
/*
* Find A NSEC3PARAM with a supported algorithm.
*/
@@ -2063,17 +2108,8 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version,
!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
memcpy(version->salt, nsec3param.salt,
nsec3param.salt_length);
@@ -2096,6 +2132,7 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version,
isc_rwlocktype_read);
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
}
+#endif
static void
cleanup_dead_nodes_callback(isc_task_t *task, isc_event_t *event) {
@@ -2415,7 +2452,8 @@ 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;
+ if (result == ISC_R_SUCCESS)
+ node->nsec = DNS_RBT_NSEC_NORMAL;
node->find_callback = 1;
node->wild = 1;
return (ISC_R_SUCCESS);
@@ -2443,7 +2481,8 @@ 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;
+ if (result == ISC_R_SUCCESS)
+ node->nsec = DNS_RBT_NSEC_NORMAL;
}
i++;
}
@@ -2482,6 +2521,17 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
node = NULL;
result = dns_rbt_addnode(rbtdb->tree, name, &node);
if (result == ISC_R_SUCCESS) {
+#ifdef BIND9
+ if (rbtdb->rpz_cidr != NULL) {
+ dns_fixedname_t fnamef;
+ dns_name_t *fname;
+
+ dns_fixedname_init(&fnamef);
+ fname = dns_fixedname_name(&fnamef);
+ dns_rbt_fullnamefromnode(node, fname);
+ dns_rpz_cidr_addip(rbtdb->rpz_cidr, fname);
+ }
+#endif
dns_rbt_namefromnode(node, &nodename);
#ifdef DNS_RBT_USEHASH
node->locknum = node->hashval % rbtdb->node_lock_count;
@@ -2489,7 +2539,6 @@ 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)) {
@@ -2551,13 +2600,14 @@ findnsec3node(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 = 1U;
+ node->nsec = DNS_RBT_NSEC_NSEC3;
} else if (result != ISC_R_EXISTS) {
RWUNLOCK(&rbtdb->tree_lock, locktype);
return (result);
}
- } else
- INSIST(node->nsec3);
+ } else {
+ INSIST(node->nsec == DNS_RBT_NSEC_NSEC3);
+ }
NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
new_reference(rbtdb, node);
NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
@@ -3268,13 +3318,125 @@ matchparams(rdatasetheader_t *header, rbtdb_search_t *search)
* Find node of the NSEC/NSEC3 record that is 'name'.
*/
static inline isc_result_t
+previous_closest_nsec(dns_rdatatype_t type, rbtdb_search_t *search,
+ dns_name_t *name, dns_name_t *origin,
+ dns_rbtnode_t **nodep, dns_rbtnodechain_t *nsecchain,
+ isc_boolean_t *firstp)
+{
+ dns_fixedname_t ftarget;
+ dns_name_t *target;
+ dns_rbtnode_t *nsecnode;
+ isc_result_t result;
+
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ if (type == dns_rdatatype_nsec3) {
+ result = dns_rbtnodechain_prev(&search->chain, NULL, NULL);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+ return (result);
+ result = dns_rbtnodechain_current(&search->chain, name, origin,
+ nodep);
+ return (result);
+ }
+
+ dns_fixedname_init(&ftarget);
+ target = dns_fixedname_name(&ftarget);
+
+ for (;;) {
+ if (*firstp) {
+ /*
+ * Construct the name of the second node to check.
+ * It is the first node sought in the NSEC tree.
+ */
+ *firstp = ISC_FALSE;
+ dns_rbtnodechain_init(nsecchain, NULL);
+ result = dns_name_concatenate(name, origin,
+ target, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ nsecnode = NULL;
+ result = dns_rbt_findnode(search->rbtdb->nsec,
+ target, NULL,
+ &nsecnode, nsecchain,
+ DNS_RBTFIND_NOOPTIONS,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Since this was the first loop, finding the
+ * name in the NSEC tree implies that the first
+ * node checked in the main tree had an
+ * unacceptable NSEC record.
+ * Try the previous node in the NSEC tree.
+ */
+ result = dns_rbtnodechain_prev(nsecchain,
+ name, origin);
+ if (result == DNS_R_NEWORIGIN)
+ result = ISC_R_SUCCESS;
+ } else if (result == ISC_R_NOTFOUND ||
+ result == DNS_R_PARTIALMATCH) {
+ result = dns_rbtnodechain_current(nsecchain,
+ name, origin, NULL);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_NOMORE;
+ }
+ } else {
+ /*
+ * This is a second or later trip through the auxiliary
+ * tree for the name of a third or earlier NSEC node in
+ * the main tree. Previous trips through the NSEC tree
+ * must have found nodes in the main tree with NSEC
+ * records. Perhaps they lacked signature records.
+ */
+ result = dns_rbtnodechain_prev(nsecchain, name, origin);
+ if (result == DNS_R_NEWORIGIN)
+ result = ISC_R_SUCCESS;
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Construct the name to seek in the main tree.
+ */
+ result = dns_name_concatenate(name, origin, target, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ *nodep = NULL;
+ result = dns_rbt_findnode(search->rbtdb->tree, target, NULL,
+ nodep, &search->chain,
+ DNS_RBTFIND_NOOPTIONS, NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * There should always be a node in the main tree with the
+ * same name as the node in the auxiliary NSEC tree, except for
+ * nodes in the auxiliary tree that are awaiting deletion.
+ */
+ if (result != DNS_R_PARTIALMATCH && result != ISC_R_NOTFOUND) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_ERROR,
+ "previous_closest_nsec(): %s",
+ isc_result_totext(result));
+ return (DNS_R_BADDB);
+ }
+ }
+}
+
+/*
+ * Find the NSEC/NSEC3 which is or before the current point on the
+ * search chain. For NSEC3 records only NSEC3 records that match the
+ * current NSEC3PARAM record are considered.
+ */
+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, dns_rbt_t *tree,
dns_db_secure_t secure)
{
- dns_rbtnode_t *node;
+ dns_rbtnode_t *node, *prevnode;
rdatasetheader_t *header, *header_next, *found, *foundsig;
+ dns_rbtnodechain_t nsecchain;
isc_boolean_t empty_node;
isc_result_t result;
dns_fixedname_t fname, forigin;
@@ -3282,6 +3444,7 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
dns_rdatatype_t type;
rbtdb_rdatatype_t sigtype;
isc_boolean_t wraps;
+ isc_boolean_t first = ISC_TRUE;
isc_boolean_t need_sig = ISC_TF(secure == dns_db_secure);
if (tree == search->rbtdb->nsec3) {
@@ -3294,17 +3457,21 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
wraps = ISC_FALSE;
}
+ /*
+ * Use the auxiliary tree only starting with the second node in the
+ * hope that the original node will be right much of the time.
+ */
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_fixedname_init(&forigin);
+ origin = dns_fixedname_name(&forigin);
again:
+ node = NULL;
+ prevnode = NULL;
+ result = dns_rbtnodechain_current(&search->chain, name, origin, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
do {
- node = NULL;
- dns_fixedname_init(&fname);
- name = dns_fixedname_name(&fname);
- dns_fixedname_init(&forigin);
- origin = dns_fixedname_name(&forigin);
- result = dns_rbtnodechain_current(&search->chain, name,
- origin, &node);
- if (result != ISC_R_SUCCESS)
- return (result);
NODE_LOCK(&(search->rbtdb->node_locks[node->locknum].lock),
isc_rwlocktype_read);
found = NULL;
@@ -3354,11 +3521,12 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
empty_node = ISC_TRUE;
found = NULL;
foundsig = NULL;
- result = dns_rbtnodechain_prev(&search->chain,
- NULL, NULL);
+ result = previous_closest_nsec(type, search,
+ name, origin,
+ &prevnode, NULL,
+ NULL);
} else if (found != NULL &&
- (foundsig != NULL || !need_sig))
- {
+ (foundsig != NULL || !need_sig)) {
/*
* We've found the right NSEC/NSEC3 record.
*
@@ -3395,8 +3563,11 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
* node as if it were empty and keep looking.
*/
empty_node = ISC_TRUE;
- result = dns_rbtnodechain_prev(&search->chain,
- NULL, NULL);
+ result = previous_closest_nsec(type, search,
+ name, origin,
+ &prevnode,
+ &nsecchain,
+ &first);
} else {
/*
* We found an active node, but either the
@@ -3410,13 +3581,19 @@ find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
* This node isn't active. We've got to keep
* looking.
*/
- result = dns_rbtnodechain_prev(&search->chain, NULL,
- NULL);
+ result = previous_closest_nsec(type, search,
+ name, origin, &prevnode,
+ &nsecchain, &first);
}
NODE_UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock),
isc_rwlocktype_read);
+ node = prevnode;
+ prevnode = NULL;
} while (empty_node && result == ISC_R_SUCCESS);
+ if (!first)
+ dns_rbtnodechain_invalidate(&nsecchain);
+
if (result == ISC_R_NOMORE && wraps) {
result = dns_rbtnodechain_last(&search->chain, tree,
NULL, NULL);
@@ -3960,6 +4137,7 @@ zone_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
FATAL_ERROR(__FILE__, __LINE__, "zone_findzonecut() called!");
+ /* NOTREACHED */
return (ISC_R_NOTIMPLEMENTED);
}
@@ -4371,6 +4549,200 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
return (result);
}
+/*
+ * Mark a database for response policy rewriting.
+ */
+#ifdef BIND9
+static void
+get_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st)
+{
+ dns_rbtdb_t *rbtdb;
+
+ rbtdb = (dns_rbtdb_t *)db;
+ REQUIRE(VALID_RBTDB(rbtdb));
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ dns_rpz_enabled(rbtdb->rpz_cidr, st);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+}
+
+/*
+ * Search the CDIR block tree of a response policy tree of trees for all of
+ * the IP addresses in an A or AAAA rdataset.
+ * Among the policies for all IPv4 and IPv6 addresses for a name, choose
+ * the longest prefix. Among those with the longest prefix, the first
+ * configured policy. Among answers for with the longest prefixes for
+ * two or more IP addresses in the A and AAAA rdatasets the lexically
+ * smallest address.
+ */
+static isc_result_t
+rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+ dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ dns_rdataset_t *ardataset, dns_rpz_st_t *st)
+{
+ dns_rbtdb_t *rbtdb;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ isc_netaddr_t netaddr;
+ dns_fixedname_t selfnamef, qnamef;
+ dns_name_t *selfname, *qname;
+ dns_rbtnode_t *node;
+ dns_rdataset_t zrdataset;
+ dns_rpz_cidr_bits_t prefix;
+ isc_result_t result;
+ dns_rpz_policy_t rpz_policy;
+ dns_ttl_t ttl;
+
+ rbtdb = (dns_rbtdb_t *)db;
+ REQUIRE(VALID_RBTDB(rbtdb));
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ if (rbtdb->rpz_cidr == NULL) {
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ dns_db_detach(&db);
+ dns_zone_detach(&zone);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ dns_fixedname_init(&selfnamef);
+ dns_fixedname_init(&qnamef);
+ selfname = dns_fixedname_name(&selfnamef);
+ qname = dns_fixedname_name(&qnamef);
+
+ for (result = dns_rdataset_first(ardataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(ardataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(ardataset, &rdata);
+ switch (rdata.type) {
+ case dns_rdatatype_a:
+ INSIST(rdata.length == 4);
+ memcpy(&ina.s_addr, rdata.data, 4);
+ isc_netaddr_fromin(&netaddr, &ina);
+ break;
+ case dns_rdatatype_aaaa:
+ INSIST(rdata.length == 16);
+ memcpy(in6a.s6_addr, rdata.data, 16);
+ isc_netaddr_fromin6(&netaddr, &in6a);
+ break;
+ default:
+ continue;
+ }
+
+ result = dns_rpz_cidr_find(rbtdb->rpz_cidr, &netaddr, rpz_type,
+ selfname, qname, &prefix);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ /*
+ * Choose the policy with the longest matching prefix.
+ * Between policies with the same prefix, choose the first
+ * configured.
+ */
+ if (st->m.policy != DNS_RPZ_POLICY_MISS) {
+ if (prefix < st->m.prefix)
+ continue;
+ if (prefix == st->m.prefix &&
+ rpz->num > st->m.rpz->num)
+ continue;
+ }
+
+ /*
+ * We have rpz_st an entry with a prefix at least as long as
+ * the prefix of the entry we had before. Find the node
+ * corresponding to CDIR tree entry.
+ */
+ node = NULL;
+ result = dns_rbt_findnode(rbtdb->tree, qname, NULL,
+ &node, NULL, 0, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(qname, namebuf, sizeof(namebuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, DNS_RPZ_ERROR_LEVEL,
+ "rpz_findips findnode(%s): %s",
+ namebuf, isc_result_totext(result));
+ continue;
+ }
+ /*
+ * First look for a simple rewrite of the IP address.
+ * If that fails, look for a CNAME. If we cannot find
+ * a CNAME or the CNAME is neither of the special forms
+ * "*" or ".", treat it like a real CNAME.
+ */
+ dns_rdataset_init(&zrdataset);
+ result = dns_db_findrdataset(db, node, version, ardataset->type,
+ 0, 0, &zrdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_cname,
+ 0, 0, &zrdataset, NULL);
+ if (result == ISC_R_SUCCESS) {
+ if (zrdataset.type != dns_rdatatype_cname) {
+ rpz_policy = DNS_RPZ_POLICY_RECORD;
+ } else {
+ rpz_policy = dns_rpz_decode_cname(&zrdataset,
+ selfname);
+ if (rpz_policy == DNS_RPZ_POLICY_RECORD)
+ result = DNS_R_CNAME;
+ }
+ ttl = zrdataset.ttl;
+ } else {
+ rpz_policy = DNS_RPZ_POLICY_RECORD;
+ result = DNS_R_NXRRSET;
+ ttl = DNS_RPZ_TTL_DEFAULT;
+ }
+
+ /*
+ * Use an overriding action specified in the configuration file
+ */
+ if (rpz->policy != DNS_RPZ_POLICY_GIVEN &&
+ rpz_policy != DNS_RPZ_POLICY_NO_OP)
+ rpz_policy = rpz->policy;
+
+ /*
+ * We know the new prefix is at least as long as the current.
+ * Prefer the new answer if the new prefix is longer.
+ * Prefer the zone configured first if the prefixes are equal.
+ * With two actions from the same zone, prefer the action
+ * on the "smallest" name.
+ */
+ if (st->m.policy == DNS_RPZ_POLICY_MISS ||
+ prefix > st->m.prefix ||
+ rpz->num <= st->m.rpz->num ||
+ 0 > dns_name_compare(qname, st->qname)) {
+ if (dns_rdataset_isassociated(st->m.rdataset))
+ dns_rdataset_disassociate(st->m.rdataset);
+ if (st->m.node != NULL)
+ dns_db_detachnode(st->m.db, &st->m.node);
+ if (st->m.db != NULL)
+ dns_db_detach(&st->m.db);
+ if (st->m.zone != NULL)
+ dns_zone_detach(&st->m.zone);
+ st->m.rpz = rpz;
+ st->m.type = rpz_type;
+ st->m.prefix = prefix;
+ st->m.policy = rpz_policy;
+ st->m.ttl = ttl;
+ st->m.result = result;
+ dns_name_copy(qname, st->qname, NULL);
+ if (rpz_policy == DNS_RPZ_POLICY_RECORD &&
+ result != DNS_R_NXRRSET) {
+ dns_rdataset_clone(&zrdataset,st->m.rdataset);
+ dns_db_attachnode(db, node, &st->m.node);
+ }
+ dns_db_attach(db, &st->m.db);
+ dns_zone_attach(zone, &st->m.zone);
+ }
+ if (dns_rdataset_isassociated(&zrdataset))
+ dns_rdataset_disassociate(&zrdataset);
+ }
+
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ return (ISC_R_SUCCESS);
+}
+#endif
+
static isc_result_t
cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
@@ -5693,6 +6065,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
free_rdataset(rbtdb, rbtdb->common.mctx,
newheader);
newheader = (rdatasetheader_t *)merged;
+ init_rdataset(rbtdb, newheader);
if (loading && RESIGN(newheader) &&
RESIGN(header) &&
header->resign < newheader->resign)
@@ -6015,16 +6388,17 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
rdatasetheader_t *header;
isc_result_t result;
isc_boolean_t delegating;
+ isc_boolean_t newnsec;
isc_boolean_t tree_locked = ISC_FALSE;
isc_boolean_t cache_is_overmem = ISC_FALSE;
REQUIRE(VALID_RBTDB(rbtdb));
if (rbtdb->common.methods == &zone_methods)
- REQUIRE(((rbtnode->nsec3 &&
+ REQUIRE(((rbtnode->nsec == DNS_RBT_NSEC_NSEC3 &&
(rdataset->type == dns_rdatatype_nsec3 ||
rdataset->covers == dns_rdatatype_nsec3)) ||
- (!rbtnode->nsec3 &&
+ (rbtnode->nsec != DNS_RBT_NSEC_NSEC3 &&
rdataset->type != dns_rdatatype_nsec3 &&
rdataset->covers != dns_rdatatype_nsec3)));
@@ -6101,14 +6475,23 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
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.
+ * Add to the auxiliary NSEC tree if we're adding an NSEC record.
+ */
+ if (rbtnode->nsec != DNS_RBT_NSEC_HAS_NSEC &&
+ rdataset->type == dns_rdatatype_nsec)
+ newnsec = ISC_TRUE;
+ else
+ newnsec = ISC_FALSE;
+
+ /*
+ * If we're adding a delegation type, adding to the auxiliary NSEC tree,
+ * 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 (IS_CACHE(rbtdb) && isc_mem_isovermem(rbtdb->common.mctx))
cache_is_overmem = ISC_TRUE;
- if (delegating || cache_is_overmem) {
+ if (delegating || newnsec || cache_is_overmem) {
tree_locked = ISC_TRUE;
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
}
@@ -6137,14 +6520,35 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
* cleaning, we can release it now. However, we still need the
* node lock.
*/
- if (tree_locked && !delegating) {
+ if (tree_locked && !delegating && !newnsec) {
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
tree_locked = ISC_FALSE;
}
}
- result = add(rbtdb, rbtnode, rbtversion, newheader, options, ISC_FALSE,
- addedrdataset, now);
+ result = ISC_R_SUCCESS;
+ if (newnsec) {
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ dns_rbtnode_t *nsecnode;
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_rbt_fullnamefromnode(rbtnode, name);
+ nsecnode = NULL;
+ result = dns_rbt_addnode(rbtdb->nsec, name, &nsecnode);
+ if (result == ISC_R_SUCCESS) {
+ nsecnode->nsec = DNS_RBT_NSEC_NSEC;
+ rbtnode->nsec = DNS_RBT_NSEC_HAS_NSEC;
+ } else if (result == ISC_R_EXISTS) {
+ rbtnode->nsec = DNS_RBT_NSEC_HAS_NSEC;
+ result = ISC_R_SUCCESS;
+ }
+ }
+
+ if (result == ISC_R_SUCCESS)
+ result = add(rbtdb, rbtnode, rbtversion, newheader, options,
+ ISC_FALSE, addedrdataset, now);
if (result == ISC_R_SUCCESS && delegating)
rbtnode->find_callback = 1;
@@ -6181,10 +6585,10 @@ 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 &&
+ REQUIRE(((rbtnode->nsec == DNS_RBT_NSEC_NSEC3 &&
(rdataset->type == dns_rdatatype_nsec3 ||
rdataset->covers == dns_rdatatype_nsec3)) ||
- (!rbtnode->nsec3 &&
+ (rbtnode->nsec != DNS_RBT_NSEC_NSEC3 &&
rdataset->type != dns_rdatatype_nsec3 &&
rdataset->covers != dns_rdatatype_nsec3)));
@@ -6403,6 +6807,78 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
return (result);
}
+/*
+ * load a non-NSEC3 node in the main tree and optionally to the auxiliary NSEC
+ */
+static isc_result_t
+loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep,
+ isc_boolean_t hasnsec)
+{
+ isc_result_t noderesult, nsecresult;
+ dns_rbtnode_t *nsecnode;
+
+ noderesult = dns_rbt_addnode(rbtdb->tree, name, nodep);
+
+#ifdef BIND9
+ if (noderesult == ISC_R_SUCCESS)
+ dns_rpz_cidr_addip(rbtdb->rpz_cidr, name);
+#endif
+
+ if (!hasnsec)
+ return (noderesult);
+ if (noderesult == ISC_R_EXISTS) {
+ /*
+ * Add a node to the auxiliary NSEC tree for an old node
+ * just now getting an NSEC record.
+ */
+ if ((*nodep)->nsec == DNS_RBT_NSEC_HAS_NSEC)
+ return (noderesult);
+ } else if (noderesult != ISC_R_SUCCESS) {
+ return (noderesult);
+ }
+
+ /*
+ * Build the auxiliary tree for NSECs as we go.
+ * This tree speeds searches for closest NSECs that would otherwise
+ * need to examine many irrelevant nodes in large TLDs.
+ *
+ * Add nodes to the auxiliary tree after corresponding nodes have
+ * been added to the main tree.
+ */
+ nsecnode = NULL;
+ nsecresult = dns_rbt_addnode(rbtdb->nsec, name, &nsecnode);
+ if (nsecresult == ISC_R_SUCCESS) {
+ nsecnode->nsec = DNS_RBT_NSEC_NSEC;
+ (*nodep)->nsec = DNS_RBT_NSEC_HAS_NSEC;
+ return (noderesult);
+ }
+
+ if (nsecresult == ISC_R_EXISTS) {
+#if 1 /* 0 */
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_WARNING,
+ "addnode: NSEC node already exists");
+#endif
+ (*nodep)->nsec = DNS_RBT_NSEC_HAS_NSEC;
+ return (noderesult);
+ }
+
+ nsecresult = dns_rbt_deletenode(rbtdb->tree, *nodep, ISC_FALSE);
+ if (nsecresult != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_WARNING,
+ "loading_addrdataset: "
+ "dns_rbt_deletenode: %s after "
+ "dns_rbt_addnode(NSEC): %s",
+ isc_result_totext(nsecresult),
+ isc_result_totext(noderesult));
+ return (noderesult);
+}
+
static isc_result_t
loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
rbtdb_load_t *loadctx = arg;
@@ -6451,15 +6927,15 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
rdataset->covers == dns_rdatatype_nsec3) {
result = dns_rbt_addnode(rbtdb->nsec3, name, &node);
if (result == ISC_R_SUCCESS)
- node->nsec3 = 1;
+ node->nsec = DNS_RBT_NSEC_NSEC3;
+ } else if (rdataset->type == dns_rdatatype_nsec) {
+ result = loadnode(rbtdb, name, &node, ISC_TRUE);
} else {
- result = dns_rbt_addnode(rbtdb->tree, name, &node);
- if (result == ISC_R_SUCCESS)
- node->nsec3 = 0;
+ result = loadnode(rbtdb, name, &node, ISC_FALSE);
}
if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
return (result);
- if (result != ISC_R_EXISTS) {
+ if (result == ISC_R_SUCCESS) {
dns_name_t foundname;
dns_name_init(&foundname, NULL);
dns_rbt_namefromnode(node, &foundname);
@@ -6585,9 +7061,17 @@ dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
REQUIRE(VALID_RBTDB(rbtdb));
+#ifdef BIND9
return (dns_master_dump2(rbtdb->common.mctx, db, version,
&dns_master_style_default,
filename, masterformat));
+#else
+ UNUSED(version);
+ UNUSED(filename);
+ UNUSED(masterformat);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif /* BIND9 */
}
static void
@@ -6768,7 +7252,7 @@ setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
} else if (resign < oldresign)
isc_heap_increased(rbtdb->heaps[header->node->locknum],
header->heap_index);
- else
+ else if (resign > oldresign)
isc_heap_decreased(rbtdb->heaps[header->node->locknum],
header->heap_index);
} else if (resign && header->heap_index == 0) {
@@ -6913,7 +7397,14 @@ static dns_dbmethods_t zone_methods = {
getsigningtime,
resigned,
isdnssec,
+ NULL,
+#ifdef BIND9
+ get_rpz_enabled,
+ rpz_findips
+#else
+ NULL,
NULL
+#endif
};
static dns_dbmethods_t cache_methods = {
@@ -6952,7 +7443,9 @@ static dns_dbmethods_t cache_methods = {
NULL,
NULL,
isdnssec,
- getrrsetstats
+ getrrsetstats,
+ NULL,
+ NULL
};
isc_result_t
@@ -7122,12 +7615,36 @@ dns_rbtdb_create
return (result);
}
+ result = dns_rbt_create(mctx, delete_callback, rbtdb, &rbtdb->nsec);
+ 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);
}
+#ifdef BIND9
+ /*
+ * Get ready for response policy IP address searching if at least one
+ * zone has been configured as a response policy zone and this
+ * is not a cache zone.
+ * It would be better to know that this database is for a policy
+ * zone named for a view, but that would require knowledge from
+ * above such as an argv[] set from data in the zone.
+ */
+ if (type == dns_dbtype_zone && !dns_name_equal(origin, dns_rootname)) {
+ result = dns_rpz_new_cidr(mctx, origin, &rbtdb->rpz_cidr);
+ if (result != ISC_R_SUCCESS) {
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
+ return (result);
+ }
+ }
+#endif
+
/*
* 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.
@@ -7152,7 +7669,7 @@ dns_rbtdb_create
free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (result);
}
- rbtdb->origin_node->nsec3 = 0;
+ rbtdb->origin_node->nsec = DNS_RBT_NSEC_NORMAL;
/*
* We need to give the origin node the right locknum.
*/
@@ -7180,7 +7697,7 @@ dns_rbtdb_create
free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (result);
}
- nsec3node->nsec3 = 1;
+ nsec3node->nsec = DNS_RBT_NSEC_NSEC3;
/*
* We need to give the nsec3 origin node the right locknum.
*/
@@ -8238,6 +8755,21 @@ rdataset_getadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
dns_name_t *fname, dns_message_t *msg,
isc_stdtime_t now)
{
+#ifndef BIND9
+ UNUSED(rdataset);
+ UNUSED(type);
+ UNUSED(qtype);
+ UNUSED(acache);
+ UNUSED(zonep);
+ UNUSED(dbp);
+ UNUSED(versionp);
+ UNUSED(nodep);
+ UNUSED(fname);
+ UNUSED(msg);
+ UNUSED(now);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#else
dns_rbtdb_t *rbtdb = rdataset->private1;
dns_rbtnode_t *rbtnode = rdataset->private2;
unsigned char *raw = rdataset->private3; /* RDATASLAB */
@@ -8354,8 +8886,10 @@ acache_callback(dns_acacheentry_t *entry, void **arg) {
dns_db_detach((dns_db_t **)(void*)&rbtdb);
*arg = NULL;
+#endif /* BIND9 */
}
+#ifdef BIND9
static void
acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry,
acache_cbarg_t **cbargp)
@@ -8376,6 +8910,7 @@ acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry,
*cbargp = NULL;
}
+#endif /* BIND9 */
static isc_result_t
rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
@@ -8384,6 +8919,19 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
dns_dbversion_t *version, dns_dbnode_t *node,
dns_name_t *fname)
{
+#ifndef BIND9
+ UNUSED(rdataset);
+ UNUSED(type);
+ UNUSED(qtype);
+ UNUSED(acache);
+ UNUSED(zone);
+ UNUSED(db);
+ UNUSED(version);
+ UNUSED(node);
+ UNUSED(fname);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#else
dns_rbtdb_t *rbtdb = rdataset->private1;
dns_rbtnode_t *rbtnode = rdataset->private2;
unsigned char *raw = rdataset->private3; /* RDATASLAB */
@@ -8507,12 +9055,21 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
}
return (result);
+#endif
}
static isc_result_t
rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset,
dns_rdatasetadditional_t type, dns_rdatatype_t qtype)
{
+#ifndef BIND9
+ UNUSED(acache);
+ UNUSED(rdataset);
+ UNUSED(type);
+ UNUSED(qtype);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#else
dns_rbtdb_t *rbtdb = rdataset->private1;
dns_rbtnode_t *rbtnode = rdataset->private2;
unsigned char *raw = rdataset->private3; /* RDATASLAB */
@@ -8577,6 +9134,7 @@ rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset,
}
return (ISC_R_SUCCESS);
+#endif
}
/*%
diff --git a/contrib/bind9/lib/dns/rcode.c b/contrib/bind9/lib/dns/rcode.c
index 2dc0a29..18fedcd 100644
--- a/contrib/bind9/lib/dns/rcode.c
+++ b/contrib/bind9/lib/dns/rcode.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: rcode.c,v 1.8.48.2 2010-01-15 23:47:33 tbox Exp $ */
+/* $Id: rcode.c,v 1.16 2010-12-23 04:07:58 marka Exp $ */
#include <config.h>
#include <ctype.h>
@@ -79,12 +79,17 @@
{ dns_tsigerror_badtrunc, "BADTRUNC", 0}, \
{ 0, NULL, 0 }
-/* RFC2538 section 2.1 */
+/* RFC4398 section 2.1 */
#define CERTNAMES \
{ 1, "PKIX", 0}, \
{ 2, "SPKI", 0}, \
{ 3, "PGP", 0}, \
+ { 4, "IPKIX", 0}, \
+ { 5, "ISPKI", 0}, \
+ { 6, "IPGP", 0}, \
+ { 7, "ACPKIX", 0}, \
+ { 8, "IACPKIX", 0}, \
{ 253, "URI", 0}, \
{ 254, "OID", 0}, \
{ 0, NULL, 0}
@@ -102,6 +107,7 @@
{ DNS_KEYALG_NSEC3RSASHA1, "NSEC3RSASHA1", 0 }, \
{ DNS_KEYALG_RSASHA256, "RSASHA256", 0 }, \
{ DNS_KEYALG_RSASHA512, "RSASHA512", 0 }, \
+ { DNS_KEYALG_ECCGOST, "ECCGOST", 0 }, \
{ DNS_KEYALG_INDIRECT, "INDIRECT", 0 }, \
{ DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \
{ DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, \
@@ -313,6 +319,21 @@ dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) {
return (dns_mnemonic_totext(secalg, target, secalgs));
}
+void
+dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) {
+ isc_buffer_t b;
+ isc_region_t r;
+ isc_result_t result;
+
+ REQUIRE(cp != NULL && size > 0);
+ isc_buffer_init(&b, cp, size - 1);
+ result = dns_secalg_totext(alg, &b);
+ isc_buffer_usedregion(&b, &r);
+ r.base[r.length] = 0;
+ if (result != ISC_R_SUCCESS)
+ r.base[0] = 0;
+}
+
isc_result_t
dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) {
unsigned int value;
diff --git a/contrib/bind9/lib/dns/rdata.c b/contrib/bind9/lib/dns/rdata.c
index daaa83a..c282b03 100644
--- a/contrib/bind9/lib/dns/rdata.c
+++ b/contrib/bind9/lib/dns/rdata.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: rdata.c,v 1.199.50.4 2011-01-13 04:48:21 tbox Exp $ */
+/* $Id: rdata.c,v 1.209 2011-01-13 04:59:25 tbox Exp $ */
/*! \file */
@@ -38,6 +38,7 @@
#include <dns/enumtype.h>
#include <dns/keyflags.h>
#include <dns/keyvalues.h>
+#include <dns/message.h>
#include <dns/rcode.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
@@ -275,23 +276,6 @@ dns_rdata_init(dns_rdata_t *rdata) {
/* ISC_LIST_INIT(rdata->list); */
}
-#if 1
-#define DNS_RDATA_INITIALIZED(rdata) \
- ((rdata)->data == NULL && (rdata)->length == 0 && \
- (rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \
- !ISC_LINK_LINKED((rdata), link))
-#else
-#ifdef ISC_LIST_CHECKINIT
-#define DNS_RDATA_INITIALIZED(rdata) \
- (!ISC_LINK_LINKED((rdata), link))
-#else
-#define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE
-#endif
-#endif
-
-#define DNS_RDATA_VALIDFLAGS(rdata) \
- (((rdata)->flags & ~(DNS_RDATA_UPDATE|DNS_RDATA_OFFLINE)) == 0)
-
void
dns_rdata_reset(dns_rdata_t *rdata) {
@@ -365,6 +349,37 @@ dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
return (result);
}
+int
+dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
+ int result = 0;
+ isc_boolean_t use_default = ISC_FALSE;
+
+ REQUIRE(rdata1 != NULL);
+ REQUIRE(rdata2 != NULL);
+ REQUIRE(rdata1->data != NULL);
+ REQUIRE(rdata2->data != NULL);
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
+
+ if (rdata1->rdclass != rdata2->rdclass)
+ return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
+
+ if (rdata1->type != rdata2->type)
+ return (rdata1->type < rdata2->type ? -1 : 1);
+
+ CASECOMPARESWITCH
+
+ if (use_default) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ result = isc_region_compare(&r1, &r2);
+ }
+ return (result);
+}
+
/***
*** Conversions
***/
@@ -1772,3 +1787,93 @@ dns_rdatatype_isknown(dns_rdatatype_t type) {
return (ISC_TRUE);
return (ISC_FALSE);
}
+
+void
+dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) {
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(DNS_RDATA_INITIALIZED(rdata));
+
+ rdata->data = NULL;
+ rdata->length = 0;
+ rdata->flags = DNS_RDATA_UPDATE;
+ rdata->type = type;
+ rdata->rdclass = dns_rdataclass_any;
+}
+
+void
+dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) {
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(DNS_RDATA_INITIALIZED(rdata));
+
+ rdata->data = NULL;
+ rdata->length = 0;
+ rdata->flags = DNS_RDATA_UPDATE;
+ rdata->type = type;
+ rdata->rdclass = dns_rdataclass_none;
+}
+
+void
+dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) {
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(DNS_RDATA_INITIALIZED(rdata));
+
+ rdata->data = NULL;
+ rdata->length = 0;
+ rdata->flags = DNS_RDATA_UPDATE;
+ rdata->type = type;
+ rdata->rdclass = dns_rdataclass_any;
+}
+
+void
+dns_rdata_makedelete(dns_rdata_t *rdata) {
+ REQUIRE(rdata != NULL);
+
+ rdata->rdclass = dns_rdataclass_none;
+}
+
+const char *
+dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) {
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(DNS_RDATA_INITIALIZED(rdata));
+
+ switch (section) {
+ case DNS_SECTION_PREREQUISITE:
+ switch (rdata->rdclass) {
+ case dns_rdataclass_none:
+ switch (rdata->type) {
+ case dns_rdatatype_any:
+ return ("domain doesn't exist");
+ default:
+ return ("rrset doesn't exist");
+ }
+ case dns_rdataclass_any:
+ switch (rdata->type) {
+ case dns_rdatatype_any:
+ return ("domain exists");
+ default:
+ return ("rrset exists (value independent)");
+ }
+ default:
+ return ("rrset exists (value dependent)");
+ }
+ case DNS_SECTION_UPDATE:
+ switch (rdata->rdclass) {
+ case dns_rdataclass_none:
+ return ("delete");
+ case dns_rdataclass_any:
+ switch (rdata->type) {
+ case dns_rdatatype_any:
+ return ("delete all rrsets");
+ default:
+ return ("delete rrset");
+ }
+ default:
+ return ("add");
+ }
+ }
+ return ("invalid");
+}
diff --git a/contrib/bind9/lib/dns/rdata/any_255/tsig_250.c b/contrib/bind9/lib/dns/rdata/any_255/tsig_250.c
index e698239..9763f6d 100644
--- a/contrib/bind9/lib/dns/rdata/any_255/tsig_250.c
+++ b/contrib/bind9/lib/dns/rdata/any_255/tsig_250.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: tsig_250.c,v 1.63 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: tsig_250.c,v 1.65 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 13:39:43 PST 2000 by gson */
@@ -594,4 +594,9 @@ checknames_any_tsig(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_any_tsig(ARGS_COMPARE) {
+ return (compare_any_tsig(rdata1, rdata2));
+}
+
#endif /* RDATA_ANY_255_TSIG_250_C */
diff --git a/contrib/bind9/lib/dns/rdata/ch_3/a_1.c b/contrib/bind9/lib/dns/rdata/ch_3/a_1.c
index 156caac..2623f76 100644
--- a/contrib/bind9/lib/dns/rdata/ch_3/a_1.c
+++ b/contrib/bind9/lib/dns/rdata/ch_3/a_1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005, 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
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: a_1.c,v 1.6 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: a_1.c,v 1.8 2009-12-04 22:06:37 tbox Exp $ */
/* by Bjorn.Victor@it.uu.se, 2005-05-07 */
/* Based on generic/soa_6.c and generic/mx_15.c */
@@ -107,7 +107,7 @@ fromwire_ch_a(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
dns_name_init(&name, NULL);
-
+
RETERR(dns_name_fromwire(&name, source, dctx, options, target));
isc_buffer_activeregion(source, &sregion);
@@ -205,7 +205,7 @@ fromstruct_ch_a(ARGS_FROMSTRUCT) {
dns_name_toregion(&a->ch_addr_dom, &region);
RETERR(isc_buffer_copyregion(target, &region));
-
+
return (uint16_tobuffer(ntohs(a->ch_addr), target));
}
@@ -313,4 +313,8 @@ checknames_ch_a(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_ch_a(ARGS_COMPARE) {
+ return (compare_ch_a(rdata1, rdata2));
+}
#endif /* RDATA_CH_3_A_1_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/afsdb_18.c b/contrib/bind9/lib/dns/rdata/generic/afsdb_18.c
index f82167be..bd1d1e0 100644
--- a/contrib/bind9/lib/dns/rdata/generic/afsdb_18.c
+++ b/contrib/bind9/lib/dns/rdata/generic/afsdb_18.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: afsdb_18.c,v 1.47 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: afsdb_18.c,v 1.49 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Wed Mar 15 14:59:00 PST 2000 by explorer */
@@ -306,4 +306,8 @@ checknames_afsdb(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_afsdb(ARGS_COMPARE) {
+ return (compare_afsdb(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_AFSDB_18_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/cert_37.c b/contrib/bind9/lib/dns/rdata/generic/cert_37.c
index e0398d2..d06b4e6 100644
--- a/contrib/bind9/lib/dns/rdata/generic/cert_37.c
+++ b/contrib/bind9/lib/dns/rdata/generic/cert_37.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: cert_37.c,v 1.50 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: cert_37.c,v 1.52 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Wed Mar 15 21:14:32 EST 2000 by tale */
@@ -276,5 +276,9 @@ checknames_cert(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
-#endif /* RDATA_GENERIC_CERT_37_C */
+static inline int
+casecompare_cert(ARGS_COMPARE) {
+ return (compare_cert(rdata1, rdata2));
+}
+#endif /* RDATA_GENERIC_CERT_37_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/cname_5.c b/contrib/bind9/lib/dns/rdata/generic/cname_5.c
index f44d8c5..508bb20 100644
--- a/contrib/bind9/lib/dns/rdata/generic/cname_5.c
+++ b/contrib/bind9/lib/dns/rdata/generic/cname_5.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cname_5.c,v 1.47 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: cname_5.c,v 1.49 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Wed Mar 15 16:48:45 PST 2000 by brister */
@@ -229,4 +229,9 @@ checknames_cname(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_cname(ARGS_COMPARE) {
+ return (compare_cname(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_CNAME_5_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/dlv_32769.c b/contrib/bind9/lib/dns/rdata/generic/dlv_32769.c
index 21d7abbb4..0f87433c 100644
--- a/contrib/bind9/lib/dns/rdata/generic/dlv_32769.c
+++ b/contrib/bind9/lib/dns/rdata/generic/dlv_32769.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006, 2007, 2009, 2010 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: dlv_32769.c,v 1.6 2007-06-18 23:47:43 tbox Exp $ */
+/* $Id: dlv_32769.c,v 1.10 2010-12-23 23:47:08 tbox Exp $ */
/* draft-ietf-dnsext-delegation-signer-05.txt */
@@ -74,12 +74,20 @@ fromtext_dlv(ARGS_FROMTEXT) {
/*
* Digest.
*/
- if (c == DNS_DSDIGEST_SHA1)
+ switch (c) {
+ case DNS_DSDIGEST_SHA1:
length = ISC_SHA1_DIGESTLENGTH;
- else if (c == DNS_DSDIGEST_SHA256)
+ break;
+ case DNS_DSDIGEST_SHA256:
length = ISC_SHA256_DIGESTLENGTH;
- else
+ break;
+ case DNS_DSDIGEST_GOST:
+ length = ISC_GOST_DIGESTLENGTH;
+ break;
+ default:
length = -1;
+ break;
+ }
return (isc_hex_tobuffer(lexer, target, -1));
}
@@ -144,7 +152,7 @@ fromwire_dlv(ARGS_FROMWIRE) {
UNUSED(options);
isc_buffer_activeregion(source, &sr);
-
+
/*
* Check digest lengths if we know them.
*/
@@ -152,7 +160,9 @@ fromwire_dlv(ARGS_FROMWIRE) {
(sr.base[3] == DNS_DSDIGEST_SHA1 &&
sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
(sr.base[3] == DNS_DSDIGEST_SHA256 &&
- sr.length < 4 + ISC_SHA256_DIGESTLENGTH))
+ sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_GOST &&
+ sr.length < 4 + ISC_GOST_DIGESTLENGTH))
return (ISC_R_UNEXPECTEDEND);
/*
@@ -164,7 +174,9 @@ fromwire_dlv(ARGS_FROMWIRE) {
sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
else if (sr.base[3] == DNS_DSDIGEST_SHA256)
sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
-
+ else if (sr.base[3] == DNS_DSDIGEST_GOST)
+ sr.length = 4 + ISC_GOST_DIGESTLENGTH;
+
isc_buffer_forward(source, sr.length);
return (mem_tobuffer(target, sr.base, sr.length));
}
@@ -213,6 +225,9 @@ fromstruct_dlv(ARGS_FROMSTRUCT) {
case DNS_DSDIGEST_SHA256:
REQUIRE(dlv->length == ISC_SHA256_DIGESTLENGTH);
break;
+ case DNS_DSDIGEST_GOST:
+ REQUIRE(dlv->length == ISC_GOST_DIGESTLENGTH);
+ break;
}
UNUSED(type);
@@ -318,4 +333,9 @@ checknames_dlv(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_dlv(ARGS_COMPARE) {
+ return (compare_dlv(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_DLV_32769_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/dname_39.c b/contrib/bind9/lib/dns/rdata/generic/dname_39.c
index e36702d..61356bf 100644
--- a/contrib/bind9/lib/dns/rdata/generic/dname_39.c
+++ b/contrib/bind9/lib/dns/rdata/generic/dname_39.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dname_39.c,v 1.38 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: dname_39.c,v 1.40 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Wed Mar 15 16:52:38 PST 2000 by explorer */
@@ -230,4 +230,8 @@ checknames_dname(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_dname(ARGS_COMPARE) {
+ return (compare_dname(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_DNAME_39_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/dnskey_48.c b/contrib/bind9/lib/dns/rdata/generic/dnskey_48.c
index d526ca0..91fe9f8 100644
--- a/contrib/bind9/lib/dns/rdata/generic/dnskey_48.c
+++ b/contrib/bind9/lib/dns/rdata/generic/dnskey_48.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009 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: dnskey_48.c,v 1.8 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: dnskey_48.c,v 1.10 2009-12-04 22:06:37 tbox Exp $ */
/*
* Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
@@ -76,6 +76,7 @@ totext_dnskey(ARGS_TOTEXT) {
char buf[sizeof("64000")];
unsigned int flags;
unsigned char algorithm;
+ char namebuf[DNS_NAME_FORMATSIZE];
REQUIRE(rdata->type == 48);
REQUIRE(rdata->length != 0);
@@ -105,6 +106,15 @@ totext_dnskey(ARGS_TOTEXT) {
if ((flags & 0xc000) == 0xc000)
return (ISC_R_SUCCESS);
+ if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0 &&
+ algorithm == DNS_KEYALG_PRIVATEDNS) {
+ dns_name_t name;
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &sr);
+ dns_name_format(&name, namebuf, sizeof(namebuf));
+ } else
+ namebuf[0] = 0;
+
/* key */
if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
RETERR(str_totext(" (", target));
@@ -127,12 +137,18 @@ totext_dnskey(ARGS_TOTEXT) {
dns_rdata_toregion(rdata, &tmpr);
sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
RETERR(str_totext(buf, target));
+ if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(str_totext("; alg = ", target));
+ RETERR(str_totext(namebuf, target));
+ }
}
return (ISC_R_SUCCESS);
}
static inline isc_result_t
fromwire_dnskey(ARGS_FROMWIRE) {
+ unsigned char algorithm;
isc_region_t sr;
REQUIRE(type == 48);
@@ -146,6 +162,18 @@ fromwire_dnskey(ARGS_FROMWIRE) {
if (sr.length < 4)
return (ISC_R_UNEXPECTEDEND);
+ algorithm = sr.base[3];
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_region_consume(&sr, 4);
+ isc_buffer_forward(source, 4);
+
+ if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+ dns_name_t name;
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+ }
+ isc_buffer_activeregion(source, &sr);
isc_buffer_forward(source, sr.length);
return (mem_tobuffer(target, sr.base, sr.length));
}
@@ -309,4 +337,13 @@ checknames_dnskey(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_dnskey(ARGS_COMPARE) {
+
+ /*
+ * Treat ALG 253 (private DNS) subtype name case sensistively.
+ */
+ return (compare_dnskey(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_DNSKEY_48_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/ds_43.c b/contrib/bind9/lib/dns/rdata/generic/ds_43.c
index fcaa69b..ee74ab67 100644
--- a/contrib/bind9/lib/dns/rdata/generic/ds_43.c
+++ b/contrib/bind9/lib/dns/rdata/generic/ds_43.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2010 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: ds_43.c,v 1.12 2007-06-18 23:47:43 tbox Exp $ */
+/* $Id: ds_43.c,v 1.16 2010-12-23 23:47:08 tbox Exp $ */
/* draft-ietf-dnsext-delegation-signer-05.txt */
@@ -74,12 +74,20 @@ fromtext_ds(ARGS_FROMTEXT) {
/*
* Digest.
*/
- if (c == DNS_DSDIGEST_SHA1)
+ switch (c) {
+ case DNS_DSDIGEST_SHA1:
length = ISC_SHA1_DIGESTLENGTH;
- else if (c == DNS_DSDIGEST_SHA256)
+ break;
+ case DNS_DSDIGEST_SHA256:
length = ISC_SHA256_DIGESTLENGTH;
- else
+ break;
+ case DNS_DSDIGEST_GOST:
+ length = ISC_GOST_DIGESTLENGTH;
+ break;
+ default:
length = -1;
+ break;
+ }
return (isc_hex_tobuffer(lexer, target, length));
}
@@ -152,7 +160,9 @@ fromwire_ds(ARGS_FROMWIRE) {
(sr.base[3] == DNS_DSDIGEST_SHA1 &&
sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
(sr.base[3] == DNS_DSDIGEST_SHA256 &&
- sr.length < 4 + ISC_SHA256_DIGESTLENGTH))
+ sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_GOST &&
+ sr.length < 4 + ISC_GOST_DIGESTLENGTH))
return (ISC_R_UNEXPECTEDEND);
/*
@@ -164,6 +174,8 @@ fromwire_ds(ARGS_FROMWIRE) {
sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
else if (sr.base[3] == DNS_DSDIGEST_SHA256)
sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
+ else if (sr.base[3] == DNS_DSDIGEST_GOST)
+ sr.length = 4 + ISC_GOST_DIGESTLENGTH;
isc_buffer_forward(source, sr.length);
return (mem_tobuffer(target, sr.base, sr.length));
@@ -213,6 +225,9 @@ fromstruct_ds(ARGS_FROMSTRUCT) {
case DNS_DSDIGEST_SHA256:
REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
break;
+ case DNS_DSDIGEST_GOST:
+ REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH);
+ break;
}
UNUSED(type);
@@ -318,4 +333,9 @@ checknames_ds(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_ds(ARGS_COMPARE) {
+ return (compare_ds(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_DS_43_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/gpos_27.c b/contrib/bind9/lib/dns/rdata/generic/gpos_27.c
index 35fcc50..7a3992a 100644
--- a/contrib/bind9/lib/dns/rdata/generic/gpos_27.c
+++ b/contrib/bind9/lib/dns/rdata/generic/gpos_27.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: gpos_27.c,v 1.41 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: gpos_27.c,v 1.43 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Wed Mar 15 16:48:45 PST 2000 by brister */
@@ -249,4 +249,9 @@ checknames_gpos(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_gpos(ARGS_COMPARE) {
+ return (compare_gpos(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_GPOS_27_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/hinfo_13.c b/contrib/bind9/lib/dns/rdata/generic/hinfo_13.c
index 7f31ab0..6b301e6 100644
--- a/contrib/bind9/lib/dns/rdata/generic/hinfo_13.c
+++ b/contrib/bind9/lib/dns/rdata/generic/hinfo_13.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hinfo_13.c,v 1.44 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: hinfo_13.c,v 1.46 2009-12-04 22:06:37 tbox Exp $ */
/*
* Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
@@ -221,4 +221,8 @@ checknames_hinfo(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_hinfo(ARGS_COMPARE) {
+ return (compare_hinfo(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_HINFO_13_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/hip_55.c b/contrib/bind9/lib/dns/rdata/generic/hip_55.c
new file mode 100644
index 0000000..4cda9c6
--- /dev/null
+++ b/contrib/bind9/lib/dns/rdata/generic/hip_55.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2009, 2011 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: hip_55.c,v 1.8 2011-01-13 04:59:26 tbox Exp $ */
+
+/* reviewed: TBC */
+
+/* RFC 5205 */
+
+#ifndef RDATA_GENERIC_HIP_5_C
+#define RDATA_GENERIC_HIP_5_C
+
+#define RRTYPE_HIP_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_hip(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_buffer_t hit_len;
+ isc_buffer_t key_len;
+ unsigned char *start;
+ size_t len;
+
+ REQUIRE(type == 55);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Dummy HIT len.
+ */
+ hit_len = *target;
+ RETERR(uint8_tobuffer(0, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Dummy KEY len.
+ */
+ key_len = *target;
+ RETERR(uint16_tobuffer(0, target));
+
+ /*
+ * HIT (base16).
+ */
+ start = isc_buffer_used(target);
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target));
+
+ /*
+ * Fill in HIT len.
+ */
+ len = (unsigned char *)isc_buffer_used(target) - start;
+ if (len > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(len, &hit_len));
+
+ /*
+ * Public key (base64).
+ */
+ start = isc_buffer_used(target);
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target));
+
+ /*
+ * Fill in KEY len.
+ */
+ len = (unsigned char *)isc_buffer_used(target) - start;
+ if (len > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(len, &key_len));
+
+ /*
+ * Rendezvous Servers.
+ */
+ dns_name_init(&name, NULL);
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string,
+ ISC_TRUE));
+ if (token.type != isc_tokentype_string)
+ break;
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
+ target));
+ } while (1);
+
+ /*
+ * Let upper layer handle eol/eof.
+ */
+ isc_lex_ungettoken(lexer, &token);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_hip(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ size_t length, key_len, hit_len;
+ unsigned char algorithm;
+ char buf[sizeof("225 ")];
+
+ REQUIRE(rdata->type == 55);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+
+ hit_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ key_len = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext("( ", target));
+
+ /*
+ * Algorithm
+ */
+ sprintf(buf, "%u ", algorithm);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * HIT.
+ */
+ INSIST(hit_len < region.length);
+ length = region.length;
+ region.length = hit_len;
+ RETERR(isc_hex_totext(&region, 1, "", target));
+ region.length = length - hit_len;
+ RETERR(str_totext(tctx->linebreak, target));
+
+ /*
+ * Public KEY.
+ */
+ INSIST(key_len <= region.length);
+ length = region.length;
+ region.length = key_len;
+ RETERR(isc_base64_totext(&region, 1, "", target));
+ region.length = length - key_len;
+ RETERR(str_totext(tctx->linebreak, target));
+
+ /*
+ * Rendezvous Servers.
+ */
+ dns_name_init(&name, NULL);
+ while (region.length > 0) {
+ dns_name_fromregion(&name, &region);
+
+ RETERR(dns_name_totext(&name, ISC_FALSE, target));
+ isc_region_consume(&region, name.length);
+ if (region.length > 0)
+ RETERR(str_totext(tctx->linebreak, target));
+ }
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_hip(ARGS_FROMWIRE) {
+ isc_region_t region, rr;
+ dns_name_t name;
+ isc_uint8_t hit_len;
+ isc_uint16_t key_len;
+
+ REQUIRE(type == 55);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 4U)
+ RETERR(DNS_R_FORMERR);
+
+ rr = region;
+ hit_len = uint8_fromregion(&region);
+ if (hit_len == 0)
+ RETERR(DNS_R_FORMERR);
+ isc_region_consume(&region, 2); /* hit length + algorithm */
+ key_len = uint16_fromregion(&region);
+ if (key_len == 0)
+ RETERR(DNS_R_FORMERR);
+ isc_region_consume(&region, 2);
+ if (region.length < (unsigned) (hit_len + key_len))
+ RETERR(DNS_R_FORMERR);
+
+ RETERR(mem_tobuffer(target, rr.base, 4 + hit_len + key_len));
+ isc_buffer_forward(source, 4 + hit_len + key_len);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+ while (isc_buffer_activelength(source) > 0) {
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_hip(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 55);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static inline int
+compare_hip(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 55);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ return (isc_region_compare(&region1, &region2));
+}
+
+static inline isc_result_t
+fromstruct_hip(ARGS_FROMSTRUCT) {
+ dns_rdata_hip_t *hip = source;
+ dns_rdata_hip_t myhip;
+ isc_result_t result;
+
+ REQUIRE(type == 55);
+ REQUIRE(source != NULL);
+ REQUIRE(hip->common.rdtype == type);
+ REQUIRE(hip->common.rdclass == rdclass);
+ REQUIRE(hip->hit_len > 0 && hip->hit != NULL);
+ REQUIRE(hip->key_len > 0 && hip->key != NULL);
+ REQUIRE((hip->servers == NULL && hip->servers_len == 0) ||
+ (hip->servers != NULL && hip->servers_len != 0));
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(hip->hit_len, target));
+ RETERR(uint8_tobuffer(hip->algorithm, target));
+ RETERR(uint16_tobuffer(hip->key_len, target));
+ RETERR(mem_tobuffer(target, hip->hit, hip->hit_len));
+ RETERR(mem_tobuffer(target, hip->key, hip->key_len));
+
+ myhip = *hip;
+ for (result = dns_rdata_hip_first(&myhip);
+ result == ISC_R_SUCCESS;
+ result = dns_rdata_hip_next(&myhip))
+ /* empty */;
+
+ return(mem_tobuffer(target, hip->servers, hip->servers_len));
+}
+
+static inline isc_result_t
+tostruct_hip(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_hip_t *hip = target;
+
+ REQUIRE(rdata->type == 55);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ hip->common.rdclass = rdata->rdclass;
+ hip->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&hip->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ hip->hit_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ hip->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ hip->key_len = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ hip->hit = hip->key = hip->servers = NULL;
+
+ hip->hit = mem_maybedup(mctx, region.base, hip->hit_len);
+ if (hip->hit == NULL)
+ goto cleanup;
+ isc_region_consume(&region, hip->hit_len);
+
+ hip->key = mem_maybedup(mctx, region.base, hip->key_len);
+ if (hip->key == NULL)
+ goto cleanup;
+ isc_region_consume(&region, hip->key_len);
+
+ hip->servers_len = region.length;
+ if (hip->servers_len != 0) {
+ hip->servers = mem_maybedup(mctx, region.base, region.length);
+ if (hip->servers == NULL)
+ goto cleanup;
+ }
+
+ hip->offset = hip->servers_len;
+ hip->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (hip->hit != NULL)
+ isc_mem_free(mctx, hip->hit);
+ if (hip->key != NULL)
+ isc_mem_free(mctx, hip->key);
+ if (hip->servers != NULL)
+ isc_mem_free(mctx, hip->servers);
+ return (ISC_R_NOMEMORY);
+
+}
+
+static inline void
+freestruct_hip(ARGS_FREESTRUCT) {
+ dns_rdata_hip_t *hip = source;
+
+ REQUIRE(source != NULL);
+
+ if (hip->mctx == NULL)
+ return;
+
+ isc_mem_free(hip->mctx, hip->hit);
+ isc_mem_free(hip->mctx, hip->key);
+ if (hip->servers != NULL)
+ isc_mem_free(hip->mctx, hip->servers);
+ hip->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_hip(ARGS_ADDLDATA) {
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == 55);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_hip(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 55);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_hip(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 55);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_hip(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 55);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+isc_result_t
+dns_rdata_hip_first(dns_rdata_hip_t *hip) {
+ if (hip->servers_len == 0)
+ return (ISC_R_NOMORE);
+ hip->offset = 0;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdata_hip_next(dns_rdata_hip_t *hip) {
+ isc_region_t region;
+ dns_name_t name;
+
+ if (hip->offset >= hip->servers_len)
+ return (ISC_R_NOMORE);
+
+ region.base = hip->servers + hip->offset;
+ region.length = hip->servers_len - hip->offset;
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ hip->offset += name.length;
+ INSIST(hip->offset <= hip->servers_len);
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_rdata_hip_current(dns_rdata_hip_t *hip, dns_name_t *name) {
+ isc_region_t region;
+
+ REQUIRE(hip->offset < hip->servers_len);
+
+ region.base = hip->servers + hip->offset;
+ region.length = hip->servers_len - hip->offset;
+ dns_name_fromregion(name, &region);
+
+ INSIST(name->length + hip->offset <= hip->servers_len);
+}
+
+static inline int
+casecompare_hip(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+ isc_uint8_t hit_len;
+ isc_uint16_t key_len;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 55);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+
+ INSIST(r1.length > 4);
+ INSIST(r2.length > 4);
+ r1.length = 4;
+ r2.length = 4;
+ order = isc_region_compare(&r1, &r2);
+ if (order != 0)
+ return (order);
+
+ hit_len = uint8_fromregion(&r1);
+ isc_region_consume(&r1, 2); /* hit length + algorithm */
+ key_len = uint16_fromregion(&r1);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ isc_region_consume(&r1, 4);
+ isc_region_consume(&r2, 4);
+ INSIST(r1.length >= (unsigned) (hit_len + key_len));
+ INSIST(r2.length >= (unsigned) (hit_len + key_len));
+ order = isc_region_compare(&r1, &r2);
+ if (order != 0)
+ return (order);
+ isc_region_consume(&r1, hit_len + key_len);
+ isc_region_consume(&r2, hit_len + key_len);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ while (r1.length != 0 && r2.length != 0) {
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&r1, name_length(&name1));
+ isc_region_consume(&r2, name_length(&name2));
+ }
+ return (isc_region_compare(&r1, &r2));
+}
+
+#endif /* RDATA_GENERIC_HIP_5_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/hip_55.h b/contrib/bind9/lib/dns/rdata/generic/hip_55.h
new file mode 100644
index 0000000..79828ad
--- /dev/null
+++ b/contrib/bind9/lib/dns/rdata/generic/hip_55.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 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: hip_55.h,v 1.2 2009-02-26 06:09:19 marka Exp $ */
+
+#ifndef GENERIC_HIP_5_H
+#define GENERIC_HIP_5_H 1
+
+/* RFC 5205 */
+
+typedef struct dns_rdata_hip {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ unsigned char * hit;
+ unsigned char * key;
+ unsigned char * servers;
+ isc_uint8_t algorithm;
+ isc_uint8_t hit_len;
+ isc_uint16_t key_len;
+ isc_uint16_t servers_len;
+ /* Private */
+ isc_uint16_t offset;
+} dns_rdata_hip_t;
+
+isc_result_t
+dns_rdata_hip_first(dns_rdata_hip_t *);
+
+isc_result_t
+dns_rdata_hip_next(dns_rdata_hip_t *);
+
+void
+dns_rdata_hip_current(dns_rdata_hip_t *, dns_name_t *);
+
+#endif /* GENERIC_HIP_5_H */
diff --git a/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c b/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c
index f971d49..995a135 100644
--- a/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c
+++ b/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ipseckey_45.c,v 1.4.332.5 2011-01-13 04:48:23 tbox Exp $ */
+/* $Id: ipseckey_45.c,v 1.11 2011-01-13 04:59:26 tbox Exp $ */
#ifndef RDATA_GENERIC_IPSECKEY_45_C
#define RDATA_GENERIC_IPSECKEY_45_C
@@ -456,4 +456,43 @@ checknames_ipseckey(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_ipseckey(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 45);
+ REQUIRE(rdata1->length >= 3);
+ REQUIRE(rdata2->length >= 3);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3)
+ return (isc_region_compare(&region1, &region2));
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ isc_region_consume(&region1, 3);
+ isc_region_consume(&region2, 3);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ return (isc_region_compare(&region1, &region2));
+}
+
#endif /* RDATA_GENERIC_IPSECKEY_45_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/isdn_20.c b/contrib/bind9/lib/dns/rdata/generic/isdn_20.c
index a9e03b2c..b58776c 100644
--- a/contrib/bind9/lib/dns/rdata/generic/isdn_20.c
+++ b/contrib/bind9/lib/dns/rdata/generic/isdn_20.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: isdn_20.c,v 1.38 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: isdn_20.c,v 1.40 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Wed Mar 15 16:53:11 PST 2000 by bwelling */
@@ -231,4 +231,9 @@ checknames_isdn(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_isdn(ARGS_COMPARE) {
+ return (compare_isdn(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_ISDN_20_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/key_25.c b/contrib/bind9/lib/dns/rdata/generic/key_25.c
index acd314c..6fe27cb 100644
--- a/contrib/bind9/lib/dns/rdata/generic/key_25.c
+++ b/contrib/bind9/lib/dns/rdata/generic/key_25.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: key_25.c,v 1.51 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: key_25.c,v 1.53 2009-12-04 22:06:37 tbox Exp $ */
/*
* Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
@@ -76,6 +76,7 @@ totext_key(ARGS_TOTEXT) {
char buf[sizeof("64000")];
unsigned int flags;
unsigned char algorithm;
+ char namebuf[DNS_NAME_FORMATSIZE];
REQUIRE(rdata->type == 25);
REQUIRE(rdata->length != 0);
@@ -105,6 +106,15 @@ totext_key(ARGS_TOTEXT) {
if ((flags & 0xc000) == 0xc000)
return (ISC_R_SUCCESS);
+ if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0 &&
+ algorithm == DNS_KEYALG_PRIVATEDNS) {
+ dns_name_t name;
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &sr);
+ dns_name_format(&name, namebuf, sizeof(namebuf));
+ } else
+ namebuf[0] = 0;
+
/* key */
if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
RETERR(str_totext(" (", target));
@@ -127,12 +137,18 @@ totext_key(ARGS_TOTEXT) {
dns_rdata_toregion(rdata, &tmpr);
sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
RETERR(str_totext(buf, target));
+ if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(str_totext("; alg = ", target));
+ RETERR(str_totext(namebuf, target));
+ }
}
return (ISC_R_SUCCESS);
}
static inline isc_result_t
fromwire_key(ARGS_FROMWIRE) {
+ unsigned char algorithm;
isc_region_t sr;
REQUIRE(type == 25);
@@ -146,6 +162,18 @@ fromwire_key(ARGS_FROMWIRE) {
if (sr.length < 4)
return (ISC_R_UNEXPECTEDEND);
+ algorithm = sr.base[3];
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_region_consume(&sr, 4);
+ isc_buffer_forward(source, 4);
+
+ if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+ dns_name_t name;
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+ }
+ isc_buffer_activeregion(source, &sr);
isc_buffer_forward(source, sr.length);
return (mem_tobuffer(target, sr.base, sr.length));
}
@@ -309,4 +337,9 @@ checknames_key(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_key(ARGS_COMPARE) {
+ return (compare_key(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_KEY_25_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/keydata_65533.c b/contrib/bind9/lib/dns/rdata/generic/keydata_65533.c
new file mode 100644
index 0000000..3636209
--- /dev/null
+++ b/contrib/bind9/lib/dns/rdata/generic/keydata_65533.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 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: keydata_65533.c,v 1.3 2009-12-04 21:09:33 marka Exp $ */
+
+#ifndef GENERIC_KEYDATA_65533_C
+#define GENERIC_KEYDATA_65533_C 1
+
+#include <dst/dst.h>
+
+#define RRTYPE_KEYDATA_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_keydata(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_secalg_t alg;
+ dns_secproto_t proto;
+ dns_keyflags_t flags;
+ isc_uint32_t refresh, addhd, removehd;
+
+ REQUIRE(type == 65533);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* refresh timer */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &refresh));
+ RETERR(uint32_tobuffer(refresh, target));
+
+ /* add hold-down */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &addhd));
+ RETERR(uint32_tobuffer(addhd, target));
+
+ /* remove hold-down */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &removehd));
+ RETERR(uint32_tobuffer(removehd, target));
+
+ /* flags */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
+ RETERR(uint16_tobuffer(flags, target));
+
+ /* protocol */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &proto, 1));
+
+ /* algorithm */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &alg, 1));
+
+ /* No Key? */
+ if ((flags & 0xc000) == 0xc000)
+ return (ISC_R_SUCCESS);
+
+ return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_keydata(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000")];
+ unsigned int flags;
+ unsigned char algorithm;
+ unsigned long when;
+
+ REQUIRE(rdata->type == 65533);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* refresh timer */
+ when = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(when, target));
+ RETERR(str_totext(" ", target));
+
+ /* add hold-down */
+ when = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(when, target));
+ RETERR(str_totext(" ", target));
+
+ /* remove hold-down */
+ when = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(when, target));
+ RETERR(str_totext(" ", target));
+
+ /* flags */
+ flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u", flags);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /* protocol */
+ sprintf(buf, "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /* algorithm */
+ algorithm = sr.base[0];
+ sprintf(buf, "%u", algorithm);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+
+ /* No Key? */
+ if ((flags & 0xc000) == 0xc000)
+ return (ISC_R_SUCCESS);
+
+ /* key */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_base64_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0)
+ RETERR(str_totext(tctx->linebreak, target));
+ else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" ", target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(")", target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) {
+ isc_region_t tmpr;
+
+ RETERR(str_totext(" ; key id = ", target));
+ dns_rdata_toregion(rdata, &tmpr);
+ /* Skip over refresh, addhd, and removehd */
+ isc_region_consume(&tmpr, 12);
+ sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
+ RETERR(str_totext(buf, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_keydata(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 65533);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_keydata(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 65533);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_keydata(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 65533);
+ 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_keydata(ARGS_FROMSTRUCT) {
+ dns_rdata_keydata_t *keydata = source;
+
+ REQUIRE(type == 65533);
+ REQUIRE(source != NULL);
+ REQUIRE(keydata->common.rdtype == type);
+ REQUIRE(keydata->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /* Refresh timer */
+ RETERR(uint32_tobuffer(keydata->refresh, target));
+
+ /* Add hold-down */
+ RETERR(uint32_tobuffer(keydata->addhd, target));
+
+ /* Remove hold-down */
+ RETERR(uint32_tobuffer(keydata->removehd, target));
+
+ /* Flags */
+ RETERR(uint16_tobuffer(keydata->flags, target));
+
+ /* Protocol */
+ RETERR(uint8_tobuffer(keydata->protocol, target));
+
+ /* Algorithm */
+ RETERR(uint8_tobuffer(keydata->algorithm, target));
+
+ /* Data */
+ return (mem_tobuffer(target, keydata->data, keydata->datalen));
+}
+
+static inline isc_result_t
+tostruct_keydata(ARGS_TOSTRUCT) {
+ dns_rdata_keydata_t *keydata = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 65533);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ keydata->common.rdclass = rdata->rdclass;
+ keydata->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&keydata->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Refresh timer */
+ if (sr.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ keydata->refresh = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /* Add hold-down */
+ if (sr.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ keydata->addhd = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /* Remove hold-down */
+ if (sr.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ keydata->removehd = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /* Flags */
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ keydata->flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /* Protocol */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ keydata->protocol = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Algorithm */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ keydata->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Data */
+ keydata->datalen = sr.length;
+ keydata->data = mem_maybedup(mctx, sr.base, keydata->datalen);
+ if (keydata->data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ keydata->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_keydata(ARGS_FREESTRUCT) {
+ dns_rdata_keydata_t *keydata = (dns_rdata_keydata_t *) source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(keydata->common.rdtype == 65533);
+
+ if (keydata->mctx == NULL)
+ return;
+
+ if (keydata->data != NULL)
+ isc_mem_free(keydata->mctx, keydata->data);
+ keydata->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_keydata(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 65533);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_keydata(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 65533);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_keydata(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 65533);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_keydata(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 65533);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+static inline int
+casecompare_keydata(ARGS_COMPARE) {
+ return (compare_keydata(rdata1, rdata2));
+}
+
+#endif /* GENERIC_KEYDATA_65533_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/keydata_65533.h b/contrib/bind9/lib/dns/rdata/generic/keydata_65533.h
new file mode 100644
index 0000000..21cb1ba
--- /dev/null
+++ b/contrib/bind9/lib/dns/rdata/generic/keydata_65533.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef GENERIC_KEYDATA_65533_H
+#define GENERIC_KEYDATA_65533_H 1
+
+/* $Id: keydata_65533.h,v 1.2 2009-06-30 02:52:32 each Exp $ */
+
+typedef struct dns_rdata_keydata {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ isc_uint32_t refresh; /* Timer for refreshing data */
+ isc_uint32_t addhd; /* Hold-down timer for adding */
+ isc_uint32_t removehd; /* Hold-down timer for removing */
+ isc_uint16_t flags; /* Copy of DNSKEY_48 */
+ isc_uint8_t protocol;
+ isc_uint8_t algorithm;
+ isc_uint16_t datalen;
+ unsigned char * data;
+} dns_rdata_keydata_t;
+
+#endif /* GENERIC_KEYDATA_65533_H */
diff --git a/contrib/bind9/lib/dns/rdata/generic/loc_29.c b/contrib/bind9/lib/dns/rdata/generic/loc_29.c
index a5efb01..62d5cd0 100644
--- a/contrib/bind9/lib/dns/rdata/generic/loc_29.c
+++ b/contrib/bind9/lib/dns/rdata/generic/loc_29.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: loc_29.c,v 1.45.332.4 2009-02-17 05:54:12 marka Exp $ */
+/* $Id: loc_29.c,v 1.50 2009-12-04 21:09:33 marka Exp $ */
/* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
@@ -796,4 +796,9 @@ checknames_loc(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_loc(ARGS_COMPARE) {
+ return (compare_loc(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_LOC_29_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/mb_7.c b/contrib/bind9/lib/dns/rdata/generic/mb_7.c
index c47365a..7a4af1c 100644
--- a/contrib/bind9/lib/dns/rdata/generic/mb_7.c
+++ b/contrib/bind9/lib/dns/rdata/generic/mb_7.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mb_7.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: mb_7.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Wed Mar 15 17:31:26 PST 2000 by bwelling */
@@ -69,7 +69,7 @@ totext_mb(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_mb(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
REQUIRE(type == 7);
@@ -78,8 +78,8 @@ fromwire_mb(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&name, NULL);
- return (dns_name_fromwire(&name, source, dctx, options, target));
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
}
static inline isc_result_t
@@ -231,4 +231,9 @@ checknames_mb(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_mb(ARGS_COMPARE) {
+ return (compare_mb(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_MB_7_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/md_3.c b/contrib/bind9/lib/dns/rdata/generic/md_3.c
index 269f9be..ee06274 100644
--- a/contrib/bind9/lib/dns/rdata/generic/md_3.c
+++ b/contrib/bind9/lib/dns/rdata/generic/md_3.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: md_3.c,v 1.47 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: md_3.c,v 1.49 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Wed Mar 15 17:48:20 PST 2000 by bwelling */
@@ -69,7 +69,7 @@ totext_md(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_md(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
REQUIRE(type == 3);
@@ -78,8 +78,8 @@ fromwire_md(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&name, NULL);
- return (dns_name_fromwire(&name, source, dctx, options, target));
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
}
static inline isc_result_t
@@ -233,4 +233,9 @@ checknames_md(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_md(ARGS_COMPARE) {
+ return (compare_md(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_MD_3_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/mf_4.c b/contrib/bind9/lib/dns/rdata/generic/mf_4.c
index 9223384..d14bf6c 100644
--- a/contrib/bind9/lib/dns/rdata/generic/mf_4.c
+++ b/contrib/bind9/lib/dns/rdata/generic/mf_4.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mf_4.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: mf_4.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Wed Mar 15 17:47:33 PST 2000 by brister */
@@ -69,7 +69,7 @@ totext_mf(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_mf(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
REQUIRE(type == 4);
@@ -78,8 +78,8 @@ fromwire_mf(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&name, NULL);
- return (dns_name_fromwire(&name, source, dctx, options, target));
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
}
static inline isc_result_t
@@ -232,4 +232,9 @@ checknames_mf(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_mf(ARGS_COMPARE) {
+ return (compare_mf(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_MF_4_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/mg_8.c b/contrib/bind9/lib/dns/rdata/generic/mg_8.c
index ba7630c..c1d553a 100644
--- a/contrib/bind9/lib/dns/rdata/generic/mg_8.c
+++ b/contrib/bind9/lib/dns/rdata/generic/mg_8.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mg_8.c,v 1.43 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: mg_8.c,v 1.45 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Wed Mar 15 17:49:21 PST 2000 by brister */
@@ -69,7 +69,7 @@ totext_mg(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_mg(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
REQUIRE(type == 8);
@@ -78,8 +78,8 @@ fromwire_mg(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&name, NULL);
- return (dns_name_fromwire(&name, source, dctx, options, target));
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
}
static inline isc_result_t
@@ -227,4 +227,9 @@ checknames_mg(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_mg(ARGS_COMPARE) {
+ return (compare_mg(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_MG_8_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/minfo_14.c b/contrib/bind9/lib/dns/rdata/generic/minfo_14.c
index 6848a4e..881e624 100644
--- a/contrib/bind9/lib/dns/rdata/generic/minfo_14.c
+++ b/contrib/bind9/lib/dns/rdata/generic/minfo_14.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: minfo_14.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: minfo_14.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Wed Mar 15 17:45:32 PST 2000 by brister */
@@ -93,8 +93,8 @@ totext_minfo(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_minfo(ARGS_FROMWIRE) {
- dns_name_t rmail;
- dns_name_t email;
+ dns_name_t rmail;
+ dns_name_t email;
REQUIRE(type == 14);
@@ -103,11 +103,11 @@ fromwire_minfo(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&rmail, NULL);
- dns_name_init(&email, NULL);
+ dns_name_init(&rmail, NULL);
+ dns_name_init(&email, NULL);
- RETERR(dns_name_fromwire(&rmail, source, dctx, options, target));
- return (dns_name_fromwire(&email, source, dctx, options, target));
+ RETERR(dns_name_fromwire(&rmail, source, dctx, options, target));
+ return (dns_name_fromwire(&email, source, dctx, options, target));
}
static inline isc_result_t
@@ -321,4 +321,9 @@ checknames_minfo(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_minfo(ARGS_COMPARE) {
+ return (compare_minfo(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_MINFO_14_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/mr_9.c b/contrib/bind9/lib/dns/rdata/generic/mr_9.c
index a480bd4..6c02108 100644
--- a/contrib/bind9/lib/dns/rdata/generic/mr_9.c
+++ b/contrib/bind9/lib/dns/rdata/generic/mr_9.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mr_9.c,v 1.42 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: mr_9.c,v 1.44 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Wed Mar 15 21:30:35 EST 2000 by tale */
@@ -69,7 +69,7 @@ totext_mr(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_mr(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
REQUIRE(type == 9);
@@ -78,8 +78,8 @@ fromwire_mr(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&name, NULL);
- return (dns_name_fromwire(&name, source, dctx, options, target));
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
}
static inline isc_result_t
@@ -228,4 +228,9 @@ checknames_mr(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_mr(ARGS_COMPARE) {
+ return (compare_mr(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_MR_9_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/mx_15.c b/contrib/bind9/lib/dns/rdata/generic/mx_15.c
index b7b43f3..0d8e6cd 100644
--- a/contrib/bind9/lib/dns/rdata/generic/mx_15.c
+++ b/contrib/bind9/lib/dns/rdata/generic/mx_15.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: mx_15.c,v 1.56 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: mx_15.c,v 1.58 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Wed Mar 15 18:05:46 PST 2000 by brister */
@@ -120,7 +120,7 @@ totext_mx(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_mx(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
isc_region_t sregion;
REQUIRE(type == 15);
@@ -130,7 +130,7 @@ fromwire_mx(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&name, NULL);
+ dns_name_init(&name, NULL);
isc_buffer_activeregion(source, &sregion);
if (sregion.length < 2)
@@ -316,4 +316,9 @@ checknames_mx(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_mx(ARGS_COMPARE) {
+ return (compare_mx(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_MX_15_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/ns_2.c b/contrib/bind9/lib/dns/rdata/generic/ns_2.c
index 14e0c9d..f3df004 100644
--- a/contrib/bind9/lib/dns/rdata/generic/ns_2.c
+++ b/contrib/bind9/lib/dns/rdata/generic/ns_2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ns_2.c,v 1.46 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: ns_2.c,v 1.48 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Wed Mar 15 18:15:00 PST 2000 by bwelling */
@@ -77,7 +77,7 @@ totext_ns(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_ns(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
REQUIRE(type == 2);
@@ -86,8 +86,8 @@ fromwire_ns(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&name, NULL);
- return (dns_name_fromwire(&name, source, dctx, options, target));
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
}
static inline isc_result_t
@@ -248,4 +248,9 @@ checknames_ns(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_ns(ARGS_COMPARE) {
+ return (compare_ns(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_NS_2_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/nsec3_50.c b/contrib/bind9/lib/dns/rdata/generic/nsec3_50.c
index 890af1a..d21b009 100644
--- a/contrib/bind9/lib/dns/rdata/generic/nsec3_50.c
+++ b/contrib/bind9/lib/dns/rdata/generic/nsec3_50.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec3_50.c,v 1.4.48.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: nsec3_50.c,v 1.7 2009-12-04 21:09:34 marka Exp $ */
/*
* Copyright (C) 2004 Nominet, Ltd.
@@ -478,4 +478,9 @@ checknames_nsec3(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_nsec3(ARGS_COMPARE) {
+ return (compare_nsec3(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_NSEC3_50_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/nsec3param_51.c b/contrib/bind9/lib/dns/rdata/generic/nsec3param_51.c
index 1457015..01beb3c 100644
--- a/contrib/bind9/lib/dns/rdata/generic/nsec3param_51.c
+++ b/contrib/bind9/lib/dns/rdata/generic/nsec3param_51.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec3param_51.c,v 1.4.48.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: nsec3param_51.c,v 1.7 2009-12-04 21:09:34 marka Exp $ */
/*
* Copyright (C) 2004 Nominet, Ltd.
@@ -311,4 +311,9 @@ checknames_nsec3param(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_nsec3param(ARGS_COMPARE) {
+ return (compare_nsec3param(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_NSEC3PARAM_51_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/nsec_47.c b/contrib/bind9/lib/dns/rdata/generic/nsec_47.c
index ace1035..5807d5f 100644
--- a/contrib/bind9/lib/dns/rdata/generic/nsec_47.c
+++ b/contrib/bind9/lib/dns/rdata/generic/nsec_47.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007, 2008, 2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007-2009, 2011 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.11.82.2 2011-01-13 04:48:23 tbox Exp $ */
+/* $Id: nsec_47.c,v 1.15 2011-01-13 04:59:26 tbox Exp $ */
/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
@@ -361,4 +361,36 @@ checknames_nsec(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_nsec(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 47);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ return (isc_region_compare(&region1, &region2));
+}
#endif /* RDATA_GENERIC_NSEC_47_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/null_10.c b/contrib/bind9/lib/dns/rdata/generic/null_10.c
index 06a8877..e6d9b9a 100644
--- a/contrib/bind9/lib/dns/rdata/generic/null_10.c
+++ b/contrib/bind9/lib/dns/rdata/generic/null_10.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: null_10.c,v 1.42 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: null_10.c,v 1.44 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 13:57:50 PST 2000 by explorer */
@@ -189,4 +189,9 @@ checknames_null(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_null(ARGS_COMPARE) {
+ return (compare_null(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_NULL_10_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/nxt_30.c b/contrib/bind9/lib/dns/rdata/generic/nxt_30.c
index 362e6fc..44ded55 100644
--- a/contrib/bind9/lib/dns/rdata/generic/nxt_30.c
+++ b/contrib/bind9/lib/dns/rdata/generic/nxt_30.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: nxt_30.c,v 1.63 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: nxt_30.c,v 1.65 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
@@ -326,4 +326,8 @@ checknames_nxt(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_nxt(ARGS_COMPARE) {
+ return (compare_nxt(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_NXT_30_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/opt_41.c b/contrib/bind9/lib/dns/rdata/generic/opt_41.c
index 506f4a3..695057d 100644
--- a/contrib/bind9/lib/dns/rdata/generic/opt_41.c
+++ b/contrib/bind9/lib/dns/rdata/generic/opt_41.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009 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: opt_41.c,v 1.33 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: opt_41.c,v 1.35 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 14:06:44 PST 2000 by gson */
@@ -277,4 +277,9 @@ checknames_opt(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_opt(ARGS_COMPARE) {
+ return (compare_opt(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_OPT_41_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/proforma.c b/contrib/bind9/lib/dns/rdata/generic/proforma.c
index c3db196..0efc197 100644
--- a/contrib/bind9/lib/dns/rdata/generic/proforma.c
+++ b/contrib/bind9/lib/dns/rdata/generic/proforma.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: proforma.c,v 1.36 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: proforma.c,v 1.38 2009-12-04 22:06:37 tbox Exp $ */
#ifndef RDATA_GENERIC_#_#_C
#define RDATA_GENERIC_#_#_C
@@ -170,4 +170,21 @@ checknames_#(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_#(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == #);
+ REQUIRE(rdata1->rdclass == #);
+ REQUIRE(rdata1->length != 0); /* XXX */
+ REQUIRE(rdata2->length != 0); /* XXX */
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
#endif /* RDATA_GENERIC_#_#_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/ptr_12.c b/contrib/bind9/lib/dns/rdata/generic/ptr_12.c
index 8e718cd..0ed648f 100644
--- a/contrib/bind9/lib/dns/rdata/generic/ptr_12.c
+++ b/contrib/bind9/lib/dns/rdata/generic/ptr_12.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ptr_12.c,v 1.43 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: ptr_12.c,v 1.45 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 14:05:12 PST 2000 by explorer */
@@ -79,7 +79,7 @@ totext_ptr(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_ptr(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
REQUIRE(type == 12);
@@ -88,8 +88,8 @@ fromwire_ptr(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
- dns_name_init(&name, NULL);
- return (dns_name_fromwire(&name, source, dctx, options, target));
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
}
static inline isc_result_t
@@ -288,4 +288,8 @@ checknames_ptr(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_ptr(ARGS_COMPARE) {
+ return (compare_ptr(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_PTR_12_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/rp_17.c b/contrib/bind9/lib/dns/rdata/generic/rp_17.c
index 19d7b35..2865e2f 100644
--- a/contrib/bind9/lib/dns/rdata/generic/rp_17.c
+++ b/contrib/bind9/lib/dns/rdata/generic/rp_17.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rp_17.c,v 1.42 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: rp_17.c,v 1.44 2009-12-04 22:06:37 tbox Exp $ */
/* RFC1183 */
@@ -93,8 +93,8 @@ totext_rp(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_rp(ARGS_FROMWIRE) {
- dns_name_t rmail;
- dns_name_t email;
+ dns_name_t rmail;
+ dns_name_t email;
REQUIRE(type == 17);
@@ -103,11 +103,11 @@ fromwire_rp(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
- dns_name_init(&rmail, NULL);
- dns_name_init(&email, NULL);
+ dns_name_init(&rmail, NULL);
+ dns_name_init(&email, NULL);
- RETERR(dns_name_fromwire(&rmail, source, dctx, options, target));
- return (dns_name_fromwire(&email, source, dctx, options, target));
+ RETERR(dns_name_fromwire(&rmail, source, dctx, options, target));
+ return (dns_name_fromwire(&email, source, dctx, options, target));
}
static inline isc_result_t
@@ -311,4 +311,8 @@ checknames_rp(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_rp(ARGS_COMPARE) {
+ return (compare_rp(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_RP_17_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/rrsig_46.c b/contrib/bind9/lib/dns/rdata/generic/rrsig_46.c
index bcbb05b..1fa7d07 100644
--- a/contrib/bind9/lib/dns/rdata/generic/rrsig_46.c
+++ b/contrib/bind9/lib/dns/rdata/generic/rrsig_46.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2011 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011 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: rrsig_46.c,v 1.10.332.2 2011-01-13 04:48:23 tbox Exp $ */
+/* $Id: rrsig_46.c,v 1.14 2011-01-13 04:59:26 tbox Exp $ */
/* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */
@@ -544,4 +544,47 @@ checknames_rrsig(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_rrsig(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+ dns_name_t name1;
+ dns_name_t name2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 46);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+
+ INSIST(r1.length > 18);
+ INSIST(r2.length > 18);
+ r1.length = 18;
+ r2.length = 18;
+ order = isc_region_compare(&r1, &r2);
+ if (order != 0)
+ return (order);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ isc_region_consume(&r1, 18);
+ isc_region_consume(&r2, 18);
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&r1, name_length(&name1));
+ isc_region_consume(&r2, name_length(&name2));
+
+ return (isc_region_compare(&r1, &r2));
+}
+
#endif /* RDATA_GENERIC_RRSIG_46_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/rt_21.c b/contrib/bind9/lib/dns/rdata/generic/rt_21.c
index 48323c7..efd51e2 100644
--- a/contrib/bind9/lib/dns/rdata/generic/rt_21.c
+++ b/contrib/bind9/lib/dns/rdata/generic/rt_21.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rt_21.c,v 1.46 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: rt_21.c,v 1.48 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Thu Mar 16 15:02:31 PST 2000 by brister */
@@ -90,7 +90,7 @@ totext_rt(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_rt(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
isc_region_t sregion;
isc_region_t tregion;
@@ -101,7 +101,7 @@ fromwire_rt(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
- dns_name_init(&name, NULL);
+ dns_name_init(&name, NULL);
isc_buffer_activeregion(source, &sregion);
isc_buffer_availableregion(target, &tregion);
@@ -308,4 +308,9 @@ checknames_rt(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_rt(ARGS_COMPARE) {
+ return (compare_rt(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_RT_21_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/sig_24.c b/contrib/bind9/lib/dns/rdata/generic/sig_24.c
index 3010b8e..6366309 100644
--- a/contrib/bind9/lib/dns/rdata/generic/sig_24.c
+++ b/contrib/bind9/lib/dns/rdata/generic/sig_24.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: sig_24.c,v 1.66 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: sig_24.c,v 1.68 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */
@@ -575,4 +575,8 @@ checknames_sig(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_sig(ARGS_COMPARE) {
+ return (compare_sig(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_SIG_24_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/soa_6.c b/contrib/bind9/lib/dns/rdata/generic/soa_6.c
index d3fdf41..34361a8 100644
--- a/contrib/bind9/lib/dns/rdata/generic/soa_6.c
+++ b/contrib/bind9/lib/dns/rdata/generic/soa_6.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: soa_6.c,v 1.61.332.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: soa_6.c,v 1.64 2009-12-04 21:09:34 marka Exp $ */
/* Reviewed: Thu Mar 16 15:18:32 PST 2000 by explorer */
@@ -441,4 +441,9 @@ checknames_soa(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_soa(ARGS_COMPARE) {
+ return (compare_soa(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_SOA_6_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/spf_99.c b/contrib/bind9/lib/dns/rdata/generic/spf_99.c
index b1ad062..0f8ba5f 100644
--- a/contrib/bind9/lib/dns/rdata/generic/spf_99.c
+++ b/contrib/bind9/lib/dns/rdata/generic/spf_99.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009 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: spf_99.c,v 1.4 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: spf_99.c,v 1.6 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */
@@ -235,4 +235,8 @@ checknames_spf(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_spf(ARGS_COMPARE) {
+ return (compare_spf(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_SPF_99_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/sshfp_44.c b/contrib/bind9/lib/dns/rdata/generic/sshfp_44.c
index 892c1ec..7b34451 100644
--- a/contrib/bind9/lib/dns/rdata/generic/sshfp_44.c
+++ b/contrib/bind9/lib/dns/rdata/generic/sshfp_44.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006, 2007, 2009 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: sshfp_44.c,v 1.7 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: sshfp_44.c,v 1.9 2009-12-04 22:06:37 tbox Exp $ */
/* RFC 4255 */
@@ -259,4 +259,9 @@ checknames_sshfp(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_sshfp(ARGS_COMPARE) {
+ return (compare_sshfp(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_SSHFP_44_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/tkey_249.c b/contrib/bind9/lib/dns/rdata/generic/tkey_249.c
index 6927c8d..64acc0f 100644
--- a/contrib/bind9/lib/dns/rdata/generic/tkey_249.c
+++ b/contrib/bind9/lib/dns/rdata/generic/tkey_249.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 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: tkey_249.c,v 1.57 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: tkey_249.c,v 1.59 2009-12-04 22:06:37 tbox Exp $ */
/*
* Reviewed: Thu Mar 16 17:35:30 PST 2000 by halley.
@@ -552,4 +552,8 @@ checknames_tkey(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline isc_result_t
+casecompare_tkey(ARGS_COMPARE) {
+ return (compare_tkey(rdata1, rdata2));
+}
#endif /* RDATA_GENERIC_TKEY_249_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/txt_16.c b/contrib/bind9/lib/dns/rdata/generic/txt_16.c
index fa14b86..e04e0f0 100644
--- a/contrib/bind9/lib/dns/rdata/generic/txt_16.c
+++ b/contrib/bind9/lib/dns/rdata/generic/txt_16.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007, 2008 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: txt_16.c,v 1.45 2008-02-15 23:46:51 tbox Exp $ */
+/* $Id: txt_16.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */
@@ -235,4 +235,9 @@ checknames_txt(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline isc_result_t
+casecompare_txt(ARGS_COMPARE) {
+ return (compare_txt(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_TXT_16_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/unspec_103.c b/contrib/bind9/lib/dns/rdata/generic/unspec_103.c
index ffd14d9..0ce9a90 100644
--- a/contrib/bind9/lib/dns/rdata/generic/unspec_103.c
+++ b/contrib/bind9/lib/dns/rdata/generic/unspec_103.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: unspec_103.c,v 1.35 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: unspec_103.c,v 1.37 2009-12-04 22:06:37 tbox Exp $ */
#ifndef RDATA_GENERIC_UNSPEC_103_C
#define RDATA_GENERIC_UNSPEC_103_C
@@ -186,4 +186,9 @@ checknames_unspec(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_unspec(ARGS_COMPARE) {
+ return (compare_unspec(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_UNSPEC_103_C */
diff --git a/contrib/bind9/lib/dns/rdata/generic/x25_19.c b/contrib/bind9/lib/dns/rdata/generic/x25_19.c
index 47aeb7f..f315b89 100644
--- a/contrib/bind9/lib/dns/rdata/generic/x25_19.c
+++ b/contrib/bind9/lib/dns/rdata/generic/x25_19.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: x25_19.c,v 1.39 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: x25_19.c,v 1.41 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 16:15:57 PST 2000 by bwelling */
@@ -216,4 +216,9 @@ checknames_x25(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_x25(ARGS_COMPARE) {
+ return (compare_x25(rdata1, rdata2));
+}
+
#endif /* RDATA_GENERIC_X25_19_C */
diff --git a/contrib/bind9/lib/dns/rdata/hs_4/a_1.c b/contrib/bind9/lib/dns/rdata/hs_4/a_1.c
index ae30719..6d02b79 100644
--- a/contrib/bind9/lib/dns/rdata/hs_4/a_1.c
+++ b/contrib/bind9/lib/dns/rdata/hs_4/a_1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: a_1.c,v 1.31 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: a_1.c,v 1.33 2009-12-04 22:06:37 tbox Exp $ */
/* reviewed: Thu Mar 16 15:58:36 PST 2000 by brister */
@@ -229,4 +229,9 @@ checknames_hs_a(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_hs_a(ARGS_COMPARE) {
+ return (compare_hs_a(rdata1, rdata2));
+}
+
#endif /* RDATA_HS_4_A_1_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/a6_38.c b/contrib/bind9/lib/dns/rdata/in_1/a6_38.c
index 450b74c..ec453b1 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/a6_38.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/a6_38.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 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: a6_38.c,v 1.54 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: a6_38.c,v 1.56 2009-12-04 22:06:37 tbox Exp $ */
/* RFC2874 */
@@ -458,4 +458,9 @@ checknames_in_a6(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_a6(ARGS_COMPARE) {
+ return (compare_in_a6(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_A6_38_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/a_1.c b/contrib/bind9/lib/dns/rdata/in_1/a_1.c
index 1181e44..b4c1e94 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/a_1.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/a_1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: a_1.c,v 1.53 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: a_1.c,v 1.55 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
@@ -233,4 +233,9 @@ checknames_in_a(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_a(ARGS_COMPARE) {
+ return (compare_in_a(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_A_1_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/aaaa_28.c b/contrib/bind9/lib/dns/rdata/in_1/aaaa_28.c
index 119131c..fe3954e 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/aaaa_28.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/aaaa_28.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: aaaa_28.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: aaaa_28.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
@@ -230,4 +230,8 @@ checknames_in_aaaa(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_aaaa(ARGS_COMPARE) {
+ return (compare_in_aaaa(rdata1, rdata2));
+}
#endif /* RDATA_IN_1_AAAA_28_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/apl_42.c b/contrib/bind9/lib/dns/rdata/in_1/apl_42.c
index 70f6880..3f37880 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/apl_42.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/apl_42.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) 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.14 2008-01-22 23:28:04 tbox Exp $ */
+/* $Id: apl_42.c,v 1.16 2009-12-04 22:06:37 tbox Exp $ */
/* RFC3123 */
@@ -450,4 +450,9 @@ checknames_in_apl(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_apl(ARGS_COMPARE) {
+ return (compare_in_apl(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_APL_42_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c b/contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c
index 5759a76d..9eca46f 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2006, 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
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dhcid_49.c,v 1.5 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: dhcid_49.c,v 1.7 2009-12-04 22:06:37 tbox Exp $ */
/* RFC 4701 */
@@ -51,7 +51,7 @@ totext_in_dhcid(ARGS_TOTEXT) {
dns_rdata_toregion(rdata, &sr);
if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
- RETERR(str_totext("( " /*)*/, target));
+ RETERR(str_totext("( " /*)*/, target));
RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak,
target));
if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
@@ -226,4 +226,9 @@ checknames_in_dhcid(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_dhcid(ARGS_COMPARE) {
+ return (compare_in_dhcid(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_DHCID_49_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/kx_36.c b/contrib/bind9/lib/dns/rdata/in_1/kx_36.c
index 795844d..dfc103b 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/kx_36.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/kx_36.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: kx_36.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: kx_36.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Thu Mar 16 17:24:54 PST 2000 by explorer */
@@ -85,7 +85,7 @@ totext_in_kx(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_in_kx(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
isc_region_t sregion;
REQUIRE(type == 36);
@@ -96,7 +96,7 @@ fromwire_in_kx(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
- dns_name_init(&name, NULL);
+ dns_name_init(&name, NULL);
isc_buffer_activeregion(source, &sregion);
if (sregion.length < 2)
@@ -285,4 +285,9 @@ checknames_in_kx(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_kx(ARGS_COMPARE) {
+ return (compare_in_kx(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_KX_36_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c b/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c
index 51aadf7..3d09757 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/naptr_35.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-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.53 2008-02-15 23:46:51 tbox Exp $ */
+/* $Id: naptr_35.c,v 1.56 2009-12-04 21:09:34 marka Exp $ */
/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
@@ -25,12 +25,134 @@
#define RDATA_IN_1_NAPTR_35_C
#define RRTYPE_NAPTR_ATTRIBUTES (0)
+#ifdef HAVE_REGEX_H
+#include <regex.h>
+#endif
+
+/*
+ * Check the wire format of the Regexp field.
+ * Don't allow embeded NUL's.
+ */
+static inline isc_result_t
+txt_valid_regex(const unsigned char *txt) {
+#ifdef HAVE_REGEX_H
+ regex_t preg;
+ unsigned int regflags = REG_EXTENDED;
+ unsigned int nsub = 0;
+ char regex[256];
+ char *cp;
+#endif
+ isc_boolean_t flags = ISC_FALSE;
+ isc_boolean_t replace = ISC_FALSE;
+ unsigned char c;
+ unsigned char delim;
+ unsigned int len;
+
+ len = *txt++;
+ if (len == 0U)
+ return (ISC_R_SUCCESS);
+
+ delim = *txt++;
+ len--;
+
+ /*
+ * Digits, backslash and flags can't be delimiters.
+ */
+ switch (delim) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '\\': case 'i': case 0:
+ return (DNS_R_SYNTAX);
+ }
+
+#ifdef HAVE_REGEX_H
+ memset(&preg, 0, sizeof(preg));
+ cp = regex;
+#endif
+
+ while (len-- > 0) {
+ c = *txt++;
+ if (c == 0)
+ return (DNS_R_SYNTAX);
+ if (c == delim && !replace) {
+ replace = ISC_TRUE;
+ continue;
+ } else if (c == delim && !flags) {
+ flags = ISC_TRUE;
+ continue;
+ } else if (c == delim)
+ return (DNS_R_SYNTAX);
+ /*
+ * Flags are not escaped.
+ */
+ if (flags) {
+ switch (c) {
+ case 'i':
+#ifdef HAVE_REGEX_H
+ regflags |= REG_ICASE;
+#endif
+ continue;
+ default:
+ return (DNS_R_SYNTAX);
+ }
+ }
+#ifdef HAVE_REGEX_H
+ if (!replace)
+ *cp++ = c;
+#endif
+ if (c == '\\') {
+ if (len == 0)
+ return (DNS_R_SYNTAX);
+ c = *txt++;
+ if (c == 0)
+ return (DNS_R_SYNTAX);
+ len--;
+ if (replace)
+ switch (c) {
+ case '0': return (DNS_R_SYNTAX);
+#ifdef HAVE_REGEX_H
+ case '1': if (nsub < 1) nsub = 1; break;
+ case '2': if (nsub < 2) nsub = 2; break;
+ case '3': if (nsub < 3) nsub = 3; break;
+ case '4': if (nsub < 4) nsub = 4; break;
+ case '5': if (nsub < 5) nsub = 5; break;
+ case '6': if (nsub < 6) nsub = 6; break;
+ case '7': if (nsub < 7) nsub = 7; break;
+ case '8': if (nsub < 8) nsub = 8; break;
+ case '9': if (nsub < 9) nsub = 9; break;
+#endif
+ }
+#ifdef HAVE_REGEX_H
+ if (!replace)
+ *cp++ = c;
+#endif
+ }
+ }
+ if (!flags)
+ return (DNS_R_SYNTAX);
+#ifdef HAVE_REGEX_H
+ *cp = '\0';
+ if (regcomp(&preg, regex, regflags))
+ return (DNS_R_SYNTAX);
+ /*
+ * Check that substitutions in the replacement string are consistant
+ * with the regular expression.
+ */
+ if (preg.re_nsub < nsub) {
+ regfree(&preg);
+ return (DNS_R_SYNTAX);
+ }
+ regfree(&preg);
+#endif
+ return (ISC_R_SUCCESS);
+}
static inline isc_result_t
fromtext_in_naptr(ARGS_FROMTEXT) {
isc_token_t token;
dns_name_t name;
isc_buffer_t buffer;
+ unsigned char *regex;
REQUIRE(type == 35);
REQUIRE(rdclass == 1);
@@ -74,9 +196,11 @@ fromtext_in_naptr(ARGS_FROMTEXT) {
/*
* Regexp.
*/
+ regex = isc_buffer_used(target);
RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
ISC_FALSE));
RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ RETTOK(txt_valid_regex(regex));
/*
* Replacement.
@@ -156,6 +280,7 @@ static inline isc_result_t
fromwire_in_naptr(ARGS_FROMWIRE) {
dns_name_t name;
isc_region_t sr;
+ unsigned char *regex;
REQUIRE(type == 35);
REQUIRE(rdclass == 1);
@@ -189,7 +314,9 @@ fromwire_in_naptr(ARGS_FROMWIRE) {
/*
* Regexp.
*/
+ regex = isc_buffer_used(target);
RETERR(txt_fromwire(source, target));
+ RETERR(txt_valid_regex(regex));
/*
* Replacement.
@@ -575,4 +702,9 @@ checknames_in_naptr(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_naptr(ARGS_COMPARE) {
+ return (compare_in_naptr(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_NAPTR_35_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/nsap-ptr_23.c b/contrib/bind9/lib/dns/rdata/in_1/nsap-ptr_23.c
index 615d24a..2554b07 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/nsap-ptr_23.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/nsap-ptr_23.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsap-ptr_23.c,v 1.38 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: nsap-ptr_23.c,v 1.40 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Fri Mar 17 10:16:02 PST 2000 by gson */
@@ -73,7 +73,7 @@ totext_in_nsap_ptr(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_in_nsap_ptr(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
REQUIRE(type == 23);
REQUIRE(rdclass == 1);
@@ -83,8 +83,8 @@ fromwire_in_nsap_ptr(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
- dns_name_init(&name, NULL);
- return (dns_name_fromwire(&name, source, dctx, options, target));
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
}
static inline isc_result_t
@@ -242,4 +242,9 @@ checknames_in_nsap_ptr(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_nsap_ptr(ARGS_COMPARE) {
+ return (compare_in_nsap_ptr(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_NSAP_PTR_23_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/nsap_22.c b/contrib/bind9/lib/dns/rdata/in_1/nsap_22.c
index 1aaf13f..4a56c75 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/nsap_22.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/nsap_22.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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: nsap_22.c,v 1.42 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: nsap_22.c,v 1.44 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Fri Mar 17 10:41:07 PST 2000 by gson */
@@ -252,4 +252,9 @@ checknames_in_nsap(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_nsap(ARGS_COMPARE) {
+ return (compare_in_nsap(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_NSAP_22_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/px_26.c b/contrib/bind9/lib/dns/rdata/in_1/px_26.c
index 517b87c..50f68cd 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/px_26.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/px_26.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: px_26.c,v 1.43 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: px_26.c,v 1.45 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Mon Mar 20 10:44:27 PST 2000 */
@@ -115,7 +115,7 @@ totext_in_px(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_in_px(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
isc_region_t sregion;
REQUIRE(type == 26);
@@ -126,7 +126,7 @@ fromwire_in_px(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
- dns_name_init(&name, NULL);
+ dns_name_init(&name, NULL);
/*
* Preference.
@@ -371,4 +371,9 @@ checknames_in_px(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_px(ARGS_COMPARE) {
+ return (compare_in_px(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_PX_26_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/srv_33.c b/contrib/bind9/lib/dns/rdata/in_1/srv_33.c
index ac9e577..3dfd13e 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/srv_33.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/srv_33.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: srv_33.c,v 1.45 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: srv_33.c,v 1.47 2009-12-04 22:06:37 tbox Exp $ */
/* Reviewed: Fri Mar 17 13:01:00 PST 2000 by bwelling */
@@ -140,7 +140,7 @@ totext_in_srv(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_in_srv(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
isc_region_t sr;
REQUIRE(type == 33);
@@ -151,7 +151,7 @@ fromwire_in_srv(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
- dns_name_init(&name, NULL);
+ dns_name_init(&name, NULL);
/*
* Priority, weight, port.
@@ -370,4 +370,9 @@ checknames_in_srv(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_srv(ARGS_COMPARE) {
+ return (compare_in_srv(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_SRV_33_C */
diff --git a/contrib/bind9/lib/dns/rdata/in_1/wks_11.c b/contrib/bind9/lib/dns/rdata/in_1/wks_11.c
index b7d5057..29983ec 100644
--- a/contrib/bind9/lib/dns/rdata/in_1/wks_11.c
+++ b/contrib/bind9/lib/dns/rdata/in_1/wks_11.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: wks_11.c,v 1.54.332.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: wks_11.c,v 1.57 2009-12-04 21:09:34 marka Exp $ */
/* Reviewed: Fri Mar 17 15:01:49 PST 2000 by explorer */
@@ -348,4 +348,9 @@ checknames_in_wks(ARGS_CHECKNAMES) {
return (ISC_TRUE);
}
+static inline int
+casecompare_in_wks(ARGS_COMPARE) {
+ return (compare_in_wks(rdata1, rdata2));
+}
+
#endif /* RDATA_IN_1_WKS_11_C */
diff --git a/contrib/bind9/lib/dns/rdatalist.c b/contrib/bind9/lib/dns/rdatalist.c
index e8178a7..d30aff9 100644
--- a/contrib/bind9/lib/dns/rdatalist.c
+++ b/contrib/bind9/lib/dns/rdatalist.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatalist.c,v 1.36.50.2 2010-02-25 10:56:41 tbox Exp $ */
+/* $Id: rdatalist.c,v 1.40 2010-11-16 05:38:31 marka Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/dns/rdataset.c b/contrib/bind9/lib/dns/rdataset.c
index 672e001..fdd7669 100644
--- a/contrib/bind9/lib/dns/rdataset.c
+++ b/contrib/bind9/lib/dns/rdataset.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataset.c,v 1.82.50.4.6.3 2011-06-21 20:13:23 each Exp $ */
+/* $Id: rdataset.c,v 1.86.220.3 2011-06-21 20:15:53 each Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/dns/rdataslab.c b/contrib/bind9/lib/dns/rdataslab.c
index d1a02a0..932f8de 100644
--- a/contrib/bind9/lib/dns/rdataslab.c
+++ b/contrib/bind9/lib/dns/rdataslab.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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.48.50.4 2010-02-25 10:56:41 tbox Exp $ */
+/* $Id: rdataslab.c,v 1.52.148.1.2.1 2011-06-02 23:47:35 tbox Exp $ */
/*! \file */
@@ -144,21 +144,25 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
nalloc = dns_rdataset_count(rdataset);
nitems = nalloc;
- if (nitems == 0)
+ if (nitems == 0 && rdataset->type != 0)
return (ISC_R_FAILURE);
if (nalloc > 0xffff)
return (ISC_R_NOSPACE);
- x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata));
- if (x == NULL)
- return (ISC_R_NOMEMORY);
+
+ if (nalloc != 0) {
+ x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata));
+ if (x == NULL)
+ return (ISC_R_NOMEMORY);
+ } else
+ x = NULL;
/*
* Save all of the rdata members into an array.
*/
result = dns_rdataset_first(rdataset);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
goto free_rdatas;
for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) {
INSIST(result == ISC_R_SUCCESS);
@@ -223,11 +227,14 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
/*
* Don't forget the last item!
*/
+ if (nalloc != 0) {
#if DNS_RDATASET_FIXED
- buflen += (8 + x[i-1].rdata.length);
+ buflen += (8 + x[i-1].rdata.length);
#else
- buflen += (2 + x[i-1].rdata.length);
+ buflen += (2 + x[i-1].rdata.length);
#endif
+ }
+
/*
* Provide space to store the per RR meta data.
*/
@@ -316,7 +323,8 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
result = ISC_R_SUCCESS;
free_rdatas:
- isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata));
+ if (x != NULL)
+ isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata));
return (result);
}
diff --git a/contrib/bind9/lib/dns/request.c b/contrib/bind9/lib/dns/request.c
index c1cd235..b5d6248 100644
--- a/contrib/bind9/lib/dns/request.c
+++ b/contrib/bind9/lib/dns/request.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 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.82.72.2 2009-01-18 23:47:40 tbox Exp $ */
+/* $Id: request.c,v 1.87 2010-03-04 23:50:34 tbox Exp $ */
/*! \file */
@@ -449,7 +449,8 @@ req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
}
static isc_result_t
-new_request(isc_mem_t *mctx, dns_request_t **requestp) {
+new_request(isc_mem_t *mctx, dns_request_t **requestp)
+{
dns_request_t *request;
request = isc_mem_get(mctx, sizeof(*request));
@@ -1058,6 +1059,9 @@ req_render(dns_message_t *message, isc_buffer_t **bufferp,
return (result);
cleanup_cctx = ISC_TRUE;
+ if ((options & DNS_REQUESTOPT_CASE) != 0)
+ dns_compress_setsensitive(&cctx, ISC_TRUE);
+
/*
* Render message.
*/
diff --git a/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c
index f60eee9..6d9ab70 100644
--- a/contrib/bind9/lib/dns/resolver.c
+++ b/contrib/bind9/lib/dns/resolver.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.384.14.30.4.1 2011-06-21 20:13:23 each Exp $ */
+/* $Id: resolver.c,v 1.428.6.5.2.1 2011-06-21 20:15:53 each Exp $ */
/*! \file */
@@ -105,6 +105,14 @@
#define QTRACE(m)
#endif
+#ifndef DEFAULT_QUERY_TIMEOUT
+#define DEFAULT_QUERY_TIMEOUT 30 /* The default time in seconds for the whole query to live. */
+#endif
+
+#ifndef MAXIMUM_QUERY_TIMEOUT
+#define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */
+#endif
+
/*%
* Maximum EDNS0 input packet size.
*/
@@ -273,6 +281,8 @@ struct fetchctx {
unsigned int findfail;
unsigned int valfail;
isc_boolean_t timeout;
+ dns_adbaddrinfo_t *addrinfo;
+ isc_sockaddr_t *client;
};
#define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
@@ -384,6 +394,7 @@ struct dns_resolver {
unsigned int spillatmin;
isc_timer_t * spillattimer;
isc_boolean_t zero_no_soa_ttl;
+ unsigned int query_timeout;
/* Locked by lock. */
unsigned int references;
@@ -1035,6 +1046,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
ISC_LIST_UNLINK(fctx->events, event, ev_link);
task = event->ev_sender;
event->ev_sender = fctx;
+ event->vresult = fctx->vresult;
if (!HAVE_ANSWER(fctx))
event->result = result;
@@ -1742,9 +1754,8 @@ resquery_send(resquery_t *query) {
if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {
fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
} else if (res->view->enablevalidation) {
- result = dns_keytable_issecuredomain(res->view->secroots,
- &fctx->name,
- &secure_domain);
+ result = dns_view_issecuredomain(res->view, &fctx->name,
+ &secure_domain);
if (result != ISC_R_SUCCESS)
secure_domain = ISC_FALSE;
if (res->view->dlv != NULL)
@@ -2285,7 +2296,7 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
char code[64];
isc_buffer_t b;
isc_sockaddr_t *sa;
- const char *sep1, *sep2;
+ const char *spc = "";
isc_sockaddr_t *address = &addrinfo->sockaddr;
if (reason == DNS_R_LAME)
@@ -2331,18 +2342,14 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
isc_buffer_init(&b, code, sizeof(code) - 1);
dns_rcode_totext(fctx->rmessage->rcode, &b);
code[isc_buffer_usedlength(&b)] = '\0';
- sep1 = "(";
- sep2 = ") ";
+ spc = " ";
} else if (reason == DNS_R_UNEXPECTEDOPCODE) {
isc_buffer_init(&b, code, sizeof(code) - 1);
dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);
code[isc_buffer_usedlength(&b)] = '\0';
- sep1 = "(";
- sep2 = ") ";
+ spc = " ";
} else {
code[0] = '\0';
- sep1 = "";
- sep2 = "";
}
dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
@@ -2350,83 +2357,19 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
- "%s %s%s%sresolving '%s/%s/%s': %s",
- dns_result_totext(reason), sep1, code, sep2,
+ "error (%s%s%s) resolving '%s/%s/%s': %s",
+ dns_result_totext(reason), spc, code,
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)
+ * Sort addrinfo list by RTT.
*/
static void
-sort_adbfind(fetchctx_t *fctx, dns_adbfind_t *find) {
+sort_adbfind(dns_adbfind_t *find) {
dns_adbaddrinfo_t *best, *curr;
dns_adbaddrinfolist_t sorted;
- /* 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)) {
@@ -2444,19 +2387,19 @@ sort_adbfind(fetchctx_t *fctx, dns_adbfind_t *find) {
}
/*
- * Sort a list of finds by server RTT (with random jitter)
+ * Sort a list of finds by server RTT.
*/
static void
-sort_finds(fetchctx_t *fctx, dns_adbfindlist_t *findlist) {
+sort_finds(dns_adbfindlist_t *findlist) {
dns_adbfind_t *best, *curr;
dns_adbfindlist_t sorted;
dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;
- /* Sort each find's addrinfo list by SRTT (after adding jitter) */
+ /* Sort each find's addrinfo list by SRTT. */
for (curr = ISC_LIST_HEAD(*findlist);
curr != NULL;
curr = ISC_LIST_NEXT(curr, publink))
- sort_adbfind(fctx, curr);
+ sort_adbfind(curr);
/* Lame N^2 bubble sort. */
ISC_LIST_INIT(sorted);
@@ -2841,8 +2784,8 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
* We've found some addresses. We might still be looking
* for more addresses.
*/
- sort_finds(fctx, &fctx->finds);
- sort_finds(fctx, &fctx->altfinds);
+ sort_finds(&fctx->finds);
+ sort_finds(&fctx->altfinds);
result = ISC_R_SUCCESS;
}
@@ -3471,6 +3414,7 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
else
ISC_LIST_APPEND(fctx->events, event, ev_link);
fctx->references++;
+ fctx->client = client;
fetch->magic = DNS_FETCH_MAGIC;
fetch->private = fctx;
@@ -3569,6 +3513,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx->rand_buf = 0;
fctx->rand_bits = 0;
fctx->timeout = ISC_FALSE;
+ fctx->addrinfo = NULL;
+ fctx->client = NULL;
dns_name_init(&fctx->nsname, NULL);
fctx->nsfetch = NULL;
@@ -3658,7 +3604,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, res->query_timeout, 0);
iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
if (iresult != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -3800,6 +3746,33 @@ log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
namebuf, domainbuf, addrbuf);
}
+static inline void
+log_formerr(fetchctx_t *fctx, const char *format, ...) {
+ char nsbuf[ISC_SOCKADDR_FORMATSIZE];
+ char clbuf[ISC_SOCKADDR_FORMATSIZE];
+ const char *clmsg = "";
+ char msgbuf[2048];
+ va_list args;
+
+ va_start(args, format);
+ vsnprintf(msgbuf, sizeof(msgbuf), format, args);
+ va_end(args);
+
+ isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf));
+
+ if (fctx->client != NULL) {
+ clmsg = " for client ";
+ isc_sockaddr_format(fctx->client, clbuf, sizeof(clbuf));
+ } else {
+ clbuf[0] = '\0';
+ }
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
+ "DNS format error from %s resolving %s%s%s: %s",
+ nsbuf, fctx->info, clmsg, clbuf, msgbuf);
+}
+
static inline isc_result_t
same_question(fetchctx_t *fctx) {
isc_result_t result;
@@ -3814,8 +3787,10 @@ same_question(fetchctx_t *fctx) {
/*
* XXXRTH Currently we support only one question.
*/
- if (message->counts[DNS_SECTION_QUESTION] != 1)
+ if (message->counts[DNS_SECTION_QUESTION] != 1) {
+ log_formerr(fctx, "too many questions");
return (DNS_R_FORMERR);
+ }
result = dns_message_firstname(message, DNS_SECTION_QUESTION);
if (result != ISC_R_SUCCESS)
@@ -3825,10 +3800,21 @@ same_question(fetchctx_t *fctx) {
rdataset = ISC_LIST_HEAD(name->list);
INSIST(rdataset != NULL);
INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
+
if (fctx->type != rdataset->type ||
fctx->res->rdclass != rdataset->rdclass ||
- !dns_name_equal(&fctx->name, name))
+ !dns_name_equal(&fctx->name, name)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char class[DNS_RDATACLASS_FORMATSIZE];
+ char type[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(rdataset->rdclass, class, sizeof(class));
+ dns_rdatatype_format(rdataset->type, type, sizeof(type));
+ log_formerr(fctx, "question section mismatch: got %s/%s/%s",
+ namebuf, class, type);
return (DNS_R_FORMERR);
+ }
return (ISC_R_SUCCESS);
}
@@ -3958,6 +3944,7 @@ validated(isc_task_t *task, isc_event_t *event) {
REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
vevent = (dns_validatorevent_t *)event;
+ fctx->vresult = vevent->result;
FCTXTRACE("received validation completion event");
@@ -4331,8 +4318,8 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
* Is DNSSEC validation required for this name?
*/
if (res->view->enablevalidation) {
- result = dns_keytable_issecuredomain(res->view->secroots, name,
- &secure_domain);
+ result = dns_view_issecuredomain(res->view, name,
+ &secure_domain);
if (result != ISC_R_SUCCESS)
return (result);
@@ -4804,8 +4791,8 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
* Is DNSSEC validation required for this name?
*/
if (fctx->res->view->enablevalidation) {
- result = dns_keytable_issecuredomain(res->view->secroots, name,
- &secure_domain);
+ result = dns_view_issecuredomain(res->view, name,
+ &secure_domain);
if (result != ISC_R_SUCCESS)
return (result);
@@ -4949,7 +4936,9 @@ mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
}
static isc_result_t
-check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
+check_section(void *arg, dns_name_t *addname, dns_rdatatype_t type,
+ dns_section_t section)
+{
fetchctx_t *fctx = arg;
isc_result_t result;
dns_name_t *name;
@@ -4960,15 +4949,19 @@ check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
REQUIRE(VALID_FCTX(fctx));
+#if CHECK_FOR_GLUE_IN_ANSWER
+ if (section == DNS_SECTION_ANSWER && type != dns_rdatatype_a)
+ return (ISC_R_SUCCESS);
+#endif
+
if (GLUING(fctx))
gluing = ISC_TRUE;
else
gluing = ISC_FALSE;
name = NULL;
rdataset = NULL;
- result = dns_message_findname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
- addname, dns_rdatatype_any, 0, &name,
- NULL);
+ result = dns_message_findname(fctx->rmessage, section, addname,
+ dns_rdatatype_any, 0, &name, NULL);
if (result == ISC_R_SUCCESS) {
external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
if (type == dns_rdatatype_a) {
@@ -5006,6 +4999,21 @@ check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
return (ISC_R_SUCCESS);
}
+static isc_result_t
+check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
+ return (check_section(arg, addname, type, DNS_SECTION_ADDITIONAL));
+}
+
+#ifndef CHECK_FOR_GLUE_IN_ANSWER
+#define CHECK_FOR_GLUE_IN_ANSWER 0
+#endif
+#if CHECK_FOR_GLUE_IN_ANSWER
+static isc_result_t
+check_answer(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
+ return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
+}
+#endif
+
static void
chase_additional(fetchctx_t *fctx) {
isc_boolean_t rescan;
@@ -5062,8 +5070,8 @@ cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
}
static inline isc_result_t
-dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
- dns_fixedname_t *fixeddname)
+dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname,
+ dns_name_t *oname, dns_fixedname_t *fixeddname)
{
isc_result_t result;
dns_rdata_t rdata = DNS_RDATA_INIT;
@@ -5076,7 +5084,6 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
/*
* Get the target name of the DNAME.
*/
-
result = dns_rdataset_first(rdataset);
if (result != ISC_R_SUCCESS)
return (result);
@@ -5090,7 +5097,14 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
*/
namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
if (namereln != dns_namereln_subdomain) {
+ char qbuf[DNS_NAME_FORMATSIZE];
+ char obuf[DNS_NAME_FORMATSIZE];
+
dns_rdata_freestruct(&dname);
+ dns_name_format(qname, qbuf, sizeof(qbuf));
+ dns_name_format(oname, obuf, sizeof(obuf));
+ log_formerr(fctx, "unrelated DNAME in answer: "
+ "%s is not in %s", qbuf, obuf);
return (DNS_R_FORMERR);
}
dns_fixedname_init(&prefix);
@@ -5103,16 +5117,147 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
return (result);
}
+static isc_boolean_t
+is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
+ dns_rdataset_t *rdataset)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ isc_netaddr_t netaddr;
+ char addrbuf[ISC_NETADDR_FORMATSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[64];
+ char typebuf[64];
+ int match;
+
+ /* By default, we allow any addresses. */
+ if (view->denyansweracl == NULL)
+ return (ISC_TRUE);
+
+ /*
+ * If the owner name matches one in the exclusion list, either exactly
+ * or partially, allow it.
+ */
+ if (view->answeracl_exclude != NULL) {
+ dns_rbtnode_t *node = NULL;
+
+ result = dns_rbt_findnode(view->answeracl_exclude, name, NULL,
+ &node, NULL, 0, NULL, NULL);
+
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ return (ISC_TRUE);
+ }
+
+ /*
+ * Otherwise, search the filter list for a match for each address
+ * record. If a match is found, the address should be filtered,
+ * so should the entire answer.
+ */
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ if (rdataset->type == dns_rdatatype_a) {
+ INSIST(rdata.length == sizeof(ina.s_addr));
+ memcpy(&ina.s_addr, rdata.data, sizeof(ina.s_addr));
+ isc_netaddr_fromin(&netaddr, &ina);
+ } else {
+ INSIST(rdata.length == sizeof(in6a.s6_addr));
+ memcpy(in6a.s6_addr, rdata.data, sizeof(in6a.s6_addr));
+ isc_netaddr_fromin6(&netaddr, &in6a);
+ }
+
+ result = dns_acl_match(&netaddr, NULL, view->denyansweracl,
+ &view->aclenv, &match, NULL);
+
+ if (result == ISC_R_SUCCESS && match > 0) {
+ isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(rdataset->type, typebuf,
+ sizeof(typebuf));
+ dns_rdataclass_format(rdataset->rdclass, classbuf,
+ sizeof(classbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
+ "answer address %s denied for %s/%s/%s",
+ addrbuf, namebuf, typebuf, classbuf);
+ return (ISC_FALSE);
+ }
+ }
+
+ return (ISC_TRUE);
+}
+
+static isc_boolean_t
+is_answertarget_allowed(dns_view_t *view, dns_name_t *name,
+ dns_rdatatype_t type, dns_name_t *tname,
+ dns_name_t *domain)
+{
+ isc_result_t result;
+ dns_rbtnode_t *node = NULL;
+ char qnamebuf[DNS_NAME_FORMATSIZE];
+ char tnamebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[64];
+ char typebuf[64];
+
+ /* By default, we allow any target name. */
+ if (view->denyanswernames == NULL)
+ return (ISC_TRUE);
+
+ /*
+ * If the owner name matches one in the exclusion list, either exactly
+ * or partially, allow it.
+ */
+ if (view->answernames_exclude != NULL) {
+ result = dns_rbt_findnode(view->answernames_exclude, name, NULL,
+ &node, NULL, 0, NULL, NULL);
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ return (ISC_TRUE);
+ }
+
+ /*
+ * If the target name is a subdomain of the search domain, allow it.
+ */
+ if (dns_name_issubdomain(tname, domain))
+ return (ISC_TRUE);
+
+ /*
+ * Otherwise, apply filters.
+ */
+ result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node,
+ NULL, 0, NULL, NULL);
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
+ dns_name_format(name, qnamebuf, sizeof(qnamebuf));
+ dns_name_format(tname, tnamebuf, sizeof(tnamebuf));
+ dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+ dns_rdataclass_format(view->rdclass, classbuf,
+ sizeof(classbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
+ "%s target %s denied for %s/%s",
+ typebuf, tnamebuf, qnamebuf, classbuf);
+ return (ISC_FALSE);
+ }
+
+ return (ISC_TRUE);
+}
+
/*
* Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
- * If bind8_ns_resp is ISC_TRUE, this is a suspected BIND 8
- * response to an NS query that should be treated as a referral
- * even though the NS records occur in the answer section
- * rather than the authority section.
+ * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
+ * section for the NS RRset if the query type is NS; if it has
+ * LOOK_FOR_GLUE_IN_ANSWER we look for glue incorrectly returned in the answer
+ * section for A and AAAA queries.
*/
+#define LOOK_FOR_NS_IN_ANSWER 0x1
+#define LOOK_FOR_GLUE_IN_ANSWER 0x2
+
static isc_result_t
noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
- isc_boolean_t bind8_ns_resp)
+ unsigned int look_in_options)
{
isc_result_t result;
dns_message_t *message;
@@ -5120,11 +5265,16 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
dns_rdataset_t *rdataset, *ns_rdataset;
isc_boolean_t aa, negative_response;
dns_rdatatype_t type;
- dns_section_t section =
- bind8_ns_resp ? DNS_SECTION_ANSWER : DNS_SECTION_AUTHORITY;
+ dns_section_t section;
FCTXTRACE("noanswer_response");
+ if ((look_in_options & LOOK_FOR_NS_IN_ANSWER) != 0) {
+ INSIST(fctx->type == dns_rdatatype_ns);
+ section = DNS_SECTION_ANSWER;
+ } else
+ section = DNS_SECTION_AUTHORITY;
+
message = fctx->rmessage;
/*
@@ -5197,8 +5347,22 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
type = rdataset->covers;
if (((type == dns_rdatatype_ns ||
type == dns_rdatatype_soa) &&
- !dns_name_issubdomain(qname, name)))
+ !dns_name_issubdomain(qname, name))) {
+ char qbuf[DNS_NAME_FORMATSIZE];
+ char nbuf[DNS_NAME_FORMATSIZE];
+ char tbuf[DNS_RDATATYPE_FORMATSIZE];
+ dns_rdatatype_format(fctx->type, tbuf,
+ sizeof(tbuf));
+ dns_name_format(name, nbuf,
+ sizeof(nbuf));
+ dns_name_format(qname, qbuf,
+ sizeof(qbuf));
+ log_formerr(fctx,
+ "unrelated %s %s in "
+ "%s authority section",
+ tbuf, qbuf, nbuf);
return (DNS_R_FORMERR);
+ }
if (type == dns_rdatatype_ns) {
/*
* NS or RRSIG NS.
@@ -5208,8 +5372,14 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
if (rdataset->type ==
dns_rdatatype_ns) {
if (ns_name != NULL &&
- name != ns_name)
+ name != ns_name) {
+ log_formerr(fctx,
+ "multiple NS "
+ "RRsets in "
+ "authority "
+ "section");
return (DNS_R_FORMERR);
+ }
ns_name = name;
ns_rdataset = rdataset;
}
@@ -5228,8 +5398,14 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
if (rdataset->type ==
dns_rdatatype_soa) {
if (soa_name != NULL &&
- name != soa_name)
+ name != soa_name) {
+ log_formerr(fctx,
+ "multiple SOA "
+ "RRs in "
+ "authority "
+ "section");
return (DNS_R_FORMERR);
+ }
soa_name = name;
}
name->attributes |=
@@ -5305,15 +5481,25 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
*
* These should only be here if
* this is a referral, and there
- * should only be one DS.
+ * should only be one DS RRset.
*/
- if (ns_name == NULL)
+ if (ns_name == NULL) {
+ log_formerr(fctx,
+ "DS with no "
+ "referral");
return (DNS_R_FORMERR);
+ }
if (rdataset->type ==
dns_rdatatype_ds) {
if (ds_name != NULL &&
- name != ds_name)
+ name != ds_name) {
+ log_formerr(fctx,
+ "DS doesn't "
+ "match "
+ "referral "
+ "(NS)");
return (DNS_R_FORMERR);
+ }
ds_name = name;
}
name->attributes |=
@@ -5363,6 +5549,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
/*
* The responder is insane.
*/
+ log_formerr(fctx, "invalid response");
return (DNS_R_FORMERR);
}
}
@@ -5370,8 +5557,10 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
/*
* If we found both NS and SOA, they should be the same name.
*/
- if (ns_name != NULL && soa_name != NULL && ns_name != soa_name)
+ if (ns_name != NULL && soa_name != NULL && ns_name != soa_name) {
+ log_formerr(fctx, "NS/SOA mismatch");
return (DNS_R_FORMERR);
+ }
/*
* Do we have a referral? (We only want to follow a referral if
@@ -5384,14 +5573,18 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
* progress. We return DNS_R_FORMERR so that we'll keep
* trying other servers.
*/
- if (dns_name_equal(ns_name, &fctx->domain))
+ if (dns_name_equal(ns_name, &fctx->domain)) {
+ log_formerr(fctx, "non-improving referral");
return (DNS_R_FORMERR);
+ }
/*
* If the referral name is not a parent of the query
* name, consider the responder insane.
*/
if (! dns_name_issubdomain(&fctx->name, ns_name)) {
+ /* Logged twice */
+ log_formerr(fctx, "referral to non-parent");
FCTXTRACE("referral to non-parent");
return (DNS_R_FORMERR);
}
@@ -5405,6 +5598,20 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
fctx->attributes |= FCTX_ATTR_GLUING;
(void)dns_rdataset_additionaldata(ns_rdataset, check_related,
fctx);
+#if CHECK_FOR_GLUE_IN_ANSWER
+ /*
+ * Look in the answer section for "glue" that is incorrectly
+ * returned as a answer. This is needed if the server also
+ * minimizes the response size by not adding records to the
+ * additional section that are in the answer section or if
+ * the record gets dropped due to message size constraints.
+ */
+ if ((look_in_options & LOOK_FOR_GLUE_IN_ANSWER) != 0 &&
+ (fctx->type == dns_rdatatype_aaaa ||
+ fctx->type == dns_rdatatype_a))
+ (void)dns_rdataset_additionaldata(ns_rdataset,
+ check_answer, fctx);
+#endif
fctx->attributes &= ~FCTX_ATTR_GLUING;
/*
* NS rdatasets with 0 TTL cause problems.
@@ -5460,6 +5667,7 @@ answer_response(fetchctx_t *fctx) {
unsigned int aflag;
dns_rdatatype_t type;
dns_fixedname_t dname, fqname;
+ dns_view_t *view;
FCTXTRACE("answer_response");
@@ -5482,6 +5690,7 @@ answer_response(fetchctx_t *fctx) {
aa = ISC_FALSE;
qname = &fctx->name;
type = fctx->type;
+ view = fctx->res->view;
result = dns_message_firstname(message, DNS_SECTION_ANSWER);
while (!done && result == ISC_R_SUCCESS) {
name = NULL;
@@ -5500,8 +5709,21 @@ answer_response(fetchctx_t *fctx) {
* NSEC3 records are not allowed to
* appear in the answer section.
*/
+ log_formerr(fctx, "NSEC3 in answer");
return (DNS_R_FORMERR);
}
+
+ /*
+ * Apply filters, if given, on answers to reject
+ * a malicious attempt of rebinding.
+ */
+ if ((rdataset->type == dns_rdatatype_a ||
+ rdataset->type == dns_rdatatype_aaaa) &&
+ !is_answeraddress_allowed(view, name,
+ rdataset)) {
+ return (DNS_R_SERVFAIL);
+ }
+
if (rdataset->type == type && !found_cname) {
/*
* We've found an ordinary answer.
@@ -5540,8 +5762,16 @@ answer_response(fetchctx_t *fctx) {
*/
if (type == dns_rdatatype_rrsig ||
type == dns_rdatatype_dnskey ||
- type == dns_rdatatype_nsec)
+ type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3) {
+ char buf[DNS_RDATATYPE_FORMATSIZE];
+ dns_rdatatype_format(fctx->type,
+ buf, sizeof(buf));
+ log_formerr(fctx,
+ "CNAME response "
+ "for %s RR", buf);
return (DNS_R_FORMERR);
+ }
found = ISC_TRUE;
found_cname = ISC_TRUE;
want_chaining = ISC_TRUE;
@@ -5550,6 +5780,14 @@ answer_response(fetchctx_t *fctx) {
&tname);
if (result != ISC_R_SUCCESS)
return (result);
+ /* Apply filters on the target name. */
+ if (!is_answertarget_allowed(view,
+ name,
+ rdataset->type,
+ &tname,
+ &fctx->domain)) {
+ return (DNS_R_SERVFAIL);
+ }
} else if (rdataset->type == dns_rdatatype_rrsig
&& rdataset->covers ==
dns_rdatatype_cname
@@ -5650,6 +5888,8 @@ answer_response(fetchctx_t *fctx) {
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link)) {
isc_boolean_t found_dname = ISC_FALSE;
+ dns_name_t *dname_name;
+
found = ISC_FALSE;
aflag = 0;
if (rdataset->type == dns_rdatatype_dname) {
@@ -5660,12 +5900,15 @@ answer_response(fetchctx_t *fctx) {
* If we're not chaining, then the
* DNAME should not be external.
*/
- if (!chaining && external)
+ if (!chaining && external) {
+ log_formerr(fctx,
+ "external DNAME");
return (DNS_R_FORMERR);
+ }
found = ISC_TRUE;
want_chaining = ISC_TRUE;
aflag = DNS_RDATASETATTR_ANSWER;
- result = dname_target(rdataset,
+ result = dname_target(fctx, rdataset,
qname, name,
&dname);
if (result == ISC_R_NOSPACE) {
@@ -5679,6 +5922,15 @@ answer_response(fetchctx_t *fctx) {
return (result);
else
found_dname = ISC_TRUE;
+
+ dname_name = dns_fixedname_name(&dname);
+ if (!is_answertarget_allowed(view,
+ qname,
+ rdataset->type,
+ dname_name,
+ &fctx->domain)) {
+ return (DNS_R_SERVFAIL);
+ }
} else if (rdataset->type == dns_rdatatype_rrsig
&& rdataset->covers ==
dns_rdatatype_dname) {
@@ -5766,8 +6018,10 @@ answer_response(fetchctx_t *fctx) {
/*
* We should have found an answer.
*/
- if (!have_answer)
+ if (!have_answer) {
+ log_formerr(fctx, "reply has no answer");
return (DNS_R_FORMERR);
+ }
/*
* This response is now potentially cacheable.
@@ -5784,15 +6038,18 @@ answer_response(fetchctx_t *fctx) {
* If it isn't a noanswer response, no harm will be
* done.
*/
- return (noanswer_response(fctx, qname, ISC_FALSE));
+ return (noanswer_response(fctx, qname, 0));
}
/*
* We didn't end with an incomplete chain, so the rcode should be
* "no error".
*/
- if (message->rcode != dns_rcode_noerror)
+ if (message->rcode != dns_rcode_noerror) {
+ log_formerr(fctx, "CNAME/DNAME chain complete, but RCODE "
+ "indicates error");
return (DNS_R_FORMERR);
+ }
/*
* Examine the authority section (if there is one).
@@ -6129,6 +6386,39 @@ log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
isc_mem_put(mctx, buf, len);
}
+static isc_boolean_t
+iscname(fetchctx_t *fctx) {
+ isc_result_t result;
+
+ result = dns_message_findname(fctx->rmessage, DNS_SECTION_ANSWER,
+ &fctx->name, dns_rdatatype_cname, 0,
+ NULL, NULL);
+ return (result == ISC_R_SUCCESS ? ISC_TRUE : ISC_FALSE);
+}
+
+static isc_boolean_t
+betterreferral(fetchctx_t *fctx) {
+ isc_result_t result;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ dns_message_t *message = fctx->rmessage;
+
+ for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) {
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+ if (!isstrictsubdomain(name, &fctx->domain))
+ continue;
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ if (rdataset->type == dns_rdatatype_ns)
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
static void
resquery_response(isc_task_t *task, isc_event_t *event) {
isc_result_t result = ISC_R_SUCCESS;
@@ -6180,6 +6470,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
fctx->timeouts = 0;
fctx->timeout = ISC_FALSE;
+ fctx->addrinfo = query->addrinfo;
/*
* XXXRTH We should really get the current time just once. We
@@ -6476,6 +6767,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* cannot make any more progress with this
* fetch.
*/
+ log_formerr(fctx, "server sent FORMERR");
result = DNS_R_FORMERR;
}
} else if (message->rcode == dns_rcode_yxdomain) {
@@ -6590,27 +6882,62 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
(message->rcode == dns_rcode_noerror ||
message->rcode == dns_rcode_nxdomain)) {
/*
- * We've got answers. However, if we sent
- * a BIND 8 server an NS query, it may have
- * incorrectly responded with a non-authoritative
- * answer instead of a referral. Since this
- * answer lacks the SIGs necessary to do DNSSEC
- * validation, we must invoke the following special
- * kludge to treat it as a referral.
+ * [normal case]
+ * We've got answers. If it has an authoritative answer or an
+ * answer from a forwarder, we're done.
*/
- if (fctx->type == dns_rdatatype_ns &&
- (message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
- !ISFORWARDER(query->addrinfo))
- {
- result = noanswer_response(fctx, NULL, ISC_TRUE);
+ if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
+ ISFORWARDER(query->addrinfo))
+ result = answer_response(fctx);
+ else if (iscname(fctx) &&
+ fctx->type != dns_rdatatype_any &&
+ fctx->type != dns_rdatatype_cname) {
+ /*
+ * A BIND8 server could return a non-authoritative
+ * answer when a CNAME is followed. We should treat
+ * it as a valid answer.
+ */
+ result = answer_response(fctx);
+ } else if (fctx->type != dns_rdatatype_ns &&
+ !betterreferral(fctx)) {
+ /*
+ * Lame response !!!.
+ */
+ result = answer_response(fctx);
+ } else {
+ if (fctx->type == dns_rdatatype_ns) {
+ /*
+ * A BIND 8 server could incorrectly return a
+ * non-authoritative answer to an NS query
+ * instead of a referral. Since this answer
+ * lacks the SIGs necessary to do DNSSEC
+ * validation, we must invoke the following
+ * special kludge to treat it as a referral.
+ */
+ result = noanswer_response(fctx, NULL,
+ LOOK_FOR_NS_IN_ANSWER);
+ } else {
+ /*
+ * Some other servers may still somehow include
+ * an answer when it should return a referral
+ * with an empty answer. Check to see if we can
+ * treat this as a referral by ignoring the
+ * answer. Further more, there may be an
+ * implementation that moves A/AAAA glue records
+ * to the answer section for that type of
+ * delegation when the query is for that glue
+ * record. LOOK_FOR_GLUE_IN_ANSWER will handle
+ * such a corner case.
+ */
+ result = noanswer_response(fctx, NULL,
+ LOOK_FOR_GLUE_IN_ANSWER);
+ }
if (result != DNS_R_DELEGATION) {
/*
- * The answer section must have contained
- * something other than the NS records
- * we asked for. Since AA is not set
- * and the server is not a forwarder,
- * it is technically lame and it's easier
- * to treat it as such than to figure out
+ * At this point, AA is not set, the response
+ * is not a referral, and the server is not a
+ * forwarder. It is technically lame and it's
+ * easier to treat it as such than to figure out
* some more elaborate course of action.
*/
broken_server = DNS_R_LAME;
@@ -6619,7 +6946,6 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
}
goto force_referral;
}
- result = answer_response(fctx);
if (result != ISC_R_SUCCESS) {
if (result == DNS_R_FORMERR)
keep_trying = ISC_TRUE;
@@ -6631,7 +6957,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
/*
* NXDOMAIN, NXRDATASET, or referral.
*/
- result = noanswer_response(fctx, NULL, ISC_FALSE);
+ result = noanswer_response(fctx, NULL, 0);
if (result == DNS_R_CHASEDSSERVERS) {
} else if (result == DNS_R_DELEGATION) {
force_referral:
@@ -7043,6 +7369,7 @@ dns_resolver_create(dns_view_t *view,
res->spillatmax = 100;
res->spillattimer = NULL;
res->zero_no_soa_ttl = ISC_FALSE;
+ res->query_timeout = DEFAULT_QUERY_TIMEOUT;
res->ndisps = 0;
res->nextdisp = 0; /* meaningless at this point, but init it */
res->nbuckets = ntasks;
@@ -7194,6 +7521,7 @@ dns_resolver_create(dns_view_t *view,
return (result);
}
+#ifdef BIND9
static void
prime_done(isc_task_t *task, isc_event_t *event) {
dns_resolver_t *res;
@@ -7299,16 +7627,15 @@ dns_resolver_prime(dns_resolver_t *res) {
}
}
}
+#endif /* BIND9 */
void
dns_resolver_freeze(dns_resolver_t *res) {
-
/*
* Freeze resolver.
*/
REQUIRE(VALID_RESOLVER(res));
- REQUIRE(!res->frozen);
res->frozen = ISC_TRUE;
}
@@ -8341,3 +8668,22 @@ dns_resolver_getoptions(dns_resolver_t *resolver) {
return (resolver->options);
}
+
+unsigned int
+dns_resolver_gettimeout(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+
+ return (resolver->query_timeout);
+}
+
+void
+dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) {
+ REQUIRE(VALID_RESOLVER(resolver));
+
+ if (seconds == 0)
+ seconds = DEFAULT_QUERY_TIMEOUT;
+ if (seconds > MAXIMUM_QUERY_TIMEOUT)
+ seconds = MAXIMUM_QUERY_TIMEOUT;
+
+ resolver->query_timeout = seconds;
+}
diff --git a/contrib/bind9/lib/dns/result.c b/contrib/bind9/lib/dns/result.c
index 2b0457c..4cc194d 100644
--- a/contrib/bind9/lib/dns/result.c
+++ b/contrib/bind9/lib/dns/result.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: result.c,v 1.125.48.2 2010-02-25 10:56:41 tbox Exp $ */
+/* $Id: result.c,v 1.132 2011-01-11 23:47:13 tbox Exp $ */
/*! \file */
@@ -105,7 +105,7 @@ static const char *text[DNS_R_NRESULTS] = {
"no valid RRSIG", /*%< 59 DNS_R_NOVALIDSIG */
"no valid NSEC", /*%< 60 DNS_R_NOVALIDNSEC */
- "not insecure", /*%< 61 DNS_R_NOTINSECURE */
+ "insecurity proof failed", /*%< 61 DNS_R_NOTINSECURE */
"unknown service", /*%< 62 DNS_R_UNKNOWNSERVICE */
"recoverable error occurred", /*%< 63 DNS_R_RECOVERABLE */
"unknown opt attribute record", /*%< 64 DNS_R_UNKNOWNOPT */
@@ -160,6 +160,7 @@ static const char *text[DNS_R_NRESULTS] = {
"not master", /*%< 105 DNS_R_NOTMASTER */
"broken trust chain", /*%< 106 DNS_R_BROKENCHAIN */
+ "expired", /*%< 106 DNS_R_EXPIRED */
};
static const char *rcode_text[DNS_R_NRCODERESULTS] = {
diff --git a/contrib/bind9/lib/dns/rootns.c b/contrib/bind9/lib/dns/rootns.c
index d51a0d6..40e2244 100644
--- a/contrib/bind9/lib/dns/rootns.c
+++ b/contrib/bind9/lib/dns/rootns.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rootns.c,v 1.36.50.4 2010-06-18 05:37:50 marka Exp $ */
+/* $Id: rootns.c,v 1.40 2010-06-18 05:36:24 marka Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/dns/rpz.c b/contrib/bind9/lib/dns/rpz.c
new file mode 100644
index 0000000..f809e7b
--- /dev/null
+++ b/contrib/bind9/lib/dns/rpz.c
@@ -0,0 +1,1168 @@
+/*
+ * Copyright (C) 2011 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: rpz.c,v 1.7 2011-01-17 04:27:23 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/stdlib.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+#include <dns/rpz.h>
+#include <dns/view.h>
+
+
+/*
+ * Parallel radix trees for databases of response policy IP addresses
+ *
+ * The radix or Patricia trees are somewhat specialized to handle response
+ * policy addresses by representing the two test of IP IP addresses and name
+ * server IP addresses in a single tree.
+ *
+ * Each leaf indicates that an IP address is listed in the IP address or the
+ * name server IP address policy sub-zone (or both) of the corresponding
+ * response response zone. The policy data such as a CNAME or an A record
+ * is kept in the policy zone. After an IP address has been found in a radix
+ * tree, the node in the policy zone's database is found by converting
+ * the IP address to a domain name in a canonical form.
+ *
+ * The response policy zone canonical form of IPv6 addresses is one of:
+ * prefix.W.W.W.W.W.W.W.W
+ * prefix.WORDS.zz
+ * prefix.WORDS.zz.WORDS
+ * prefix.zz.WORDS
+ * where
+ * prefix is the prefix length of the IPv6 address between 1 and 128
+ * W is a number between 0 and 65535
+ * WORDS is one or more numbers W separated with "."
+ * zz corresponds to :: in the standard IPv6 text representation
+ *
+ * The canonical form of IPv4 addresses is:
+ * prefix.B.B.B.B
+ * where
+ * prefix is the prefix length of the address between 1 and 32
+ * B is a number between 0 and 255
+ *
+ * IPv4 addresses are distinguished from IPv6 addresses by having
+ * 5 labels all of which are numbers, and a prefix between 1 and 32.
+ */
+
+
+/*
+ * Use a private definition of IPv6 addresses because s6_addr32 is not
+ * always defined and our IPv6 addresses are in non-standard byte order
+ */
+typedef isc_uint32_t dns_rpz_cidr_word_t;
+#define DNS_RPZ_CIDR_WORD_BITS ((int)sizeof(dns_rpz_cidr_word_t)*8)
+#define DNS_RPZ_CIDR_KEY_BITS ((int)sizeof(dns_rpz_cidr_key_t)*8)
+#define DNS_RPZ_CIDR_WORDS (128/DNS_RPZ_CIDR_WORD_BITS)
+typedef struct {
+ dns_rpz_cidr_word_t w[DNS_RPZ_CIDR_WORDS];
+} dns_rpz_cidr_key_t;
+
+#define ADDR_V4MAPPED 0xffff
+
+#define DNS_RPZ_WORD_MASK(b) \
+ ((b) == 0 ? (dns_rpz_cidr_word_t)(-1) \
+ : ((dns_rpz_cidr_word_t)(-1) \
+ << (DNS_RPZ_CIDR_WORD_BITS - (b))))
+
+#define DNS_RPZ_IP_BIT(ip, bitno) \
+ (1 & ((ip)->w[(bitno)/DNS_RPZ_CIDR_WORD_BITS] >> \
+ (DNS_RPZ_CIDR_WORD_BITS - 1 - ((bitno) % DNS_RPZ_CIDR_WORD_BITS))))
+
+typedef struct dns_rpz_cidr_node dns_rpz_cidr_node_t;
+typedef isc_uint8_t dns_rpz_cidr_flags_t;
+struct dns_rpz_cidr_node {
+ dns_rpz_cidr_node_t *parent;
+ dns_rpz_cidr_node_t *child[2];
+ dns_rpz_cidr_key_t ip;
+ dns_rpz_cidr_bits_t bits;
+ dns_rpz_cidr_flags_t flags;
+#define DNS_RPZ_CIDR_FG_IP 0x01 /* has IP data or is parent of IP */
+#define DNS_RPZ_CIDR_FG_IP_DATA 0x02 /* has IP data */
+#define DNS_RPZ_CIDR_FG_NSIPv4 0x04 /* has or is parent of NSIPv4 data */
+#define DNS_RPZ_CIDR_FG_NSIPv6 0x08 /* has or is parent of NSIPv6 data */
+#define DNS_RPZ_CIDR_FG_NSIP_DATA 0x10 /* has NSIP data */
+};
+
+struct dns_rpz_cidr {
+ isc_mem_t *mctx;
+ isc_boolean_t had_nsdname;
+ dns_rpz_cidr_node_t *root;
+ dns_name_t ip_name; /* RPZ_IP_ZONE.LOCALHOST. */
+ dns_name_t nsip_name; /* RPZ_NSIP_ZONE.LOCALHOST. */
+ dns_name_t nsdname_name; /* RPZ_NSDNAME_ZONE.LOCALHOST */
+};
+
+
+static isc_boolean_t have_rpz_zones = ISC_FALSE;
+
+
+const char *
+dns_rpz_type2str(dns_rpz_type_t type)
+{
+ switch (type) {
+ case DNS_RPZ_TYPE_QNAME:
+ return ("QNAME");
+ case DNS_RPZ_TYPE_IP:
+ return ("IP");
+ case DNS_RPZ_TYPE_NSIP:
+ return ("NSIP");
+ case DNS_RPZ_TYPE_NSDNAME:
+ return ("NSDNAME");
+ case DNS_RPZ_TYPE_BAD:
+ break;
+ }
+ FATAL_ERROR(__FILE__, __LINE__,
+ "impossible response policy zone type %d", type);
+ return ("impossible");
+}
+
+
+
+dns_rpz_policy_t
+dns_rpz_str2policy(const char *str)
+{
+ if (str == NULL)
+ return (DNS_RPZ_POLICY_ERROR);
+ if (!strcasecmp(str, "given"))
+ return (DNS_RPZ_POLICY_GIVEN);
+ if (!strcasecmp(str, "no-op"))
+ return (DNS_RPZ_POLICY_NO_OP);
+ if (!strcasecmp(str, "nxdomain"))
+ return (DNS_RPZ_POLICY_NXDOMAIN);
+ if (!strcasecmp(str, "nodata"))
+ return (DNS_RPZ_POLICY_NODATA);
+ if (!strcasecmp(str, "cname"))
+ return (DNS_RPZ_POLICY_CNAME);
+ return (DNS_RPZ_POLICY_ERROR);
+}
+
+
+
+/*
+ * Free the radix tree of a response policy database.
+ */
+void
+dns_rpz_cidr_free(dns_rpz_cidr_t **cidrp) {
+ dns_rpz_cidr_node_t *cur, *child, *parent;
+ dns_rpz_cidr_t *cidr;
+
+ REQUIRE(cidrp != NULL);
+
+ cidr = *cidrp;
+ if (cidr == NULL)
+ return;
+
+ cur = cidr->root;
+ while (cur != NULL) {
+ /* Depth first. */
+ child = cur->child[0];
+ if (child != NULL) {
+ cur = child;
+ continue;
+ }
+ child = cur->child[1];
+ if (child != NULL) {
+ cur = child;
+ continue;
+ }
+
+ /* Delete this leaf and go up. */
+ parent = cur->parent;
+ if (parent == NULL)
+ cidr->root = NULL;
+ else
+ parent->child[parent->child[1] == cur] = NULL;
+ isc_mem_put(cidr->mctx, cur, sizeof(*cur));
+ cur = parent;
+ }
+
+ dns_name_free(&cidr->ip_name, cidr->mctx);
+ dns_name_free(&cidr->nsip_name, cidr->mctx);
+ dns_name_free(&cidr->nsdname_name, cidr->mctx);
+ isc_mem_put(cidr->mctx, cidr, sizeof(*cidr));
+ *cidrp = NULL;
+}
+
+
+
+/*
+ * Forget a view's list of policy zones.
+ */
+void
+dns_rpz_view_destroy(dns_view_t *view) {
+ dns_rpz_zone_t *zone;
+
+ REQUIRE(view != NULL);
+
+ while (!ISC_LIST_EMPTY(view->rpz_zones)) {
+ zone = ISC_LIST_HEAD(view->rpz_zones);
+ ISC_LIST_UNLINK(view->rpz_zones, zone, link);
+ if (dns_name_dynamic(&zone->origin))
+ dns_name_free(&zone->origin, view->mctx);
+ if (dns_name_dynamic(&zone->nsdname))
+ dns_name_free(&zone->nsdname, view->mctx);
+ if (dns_name_dynamic(&zone->cname))
+ dns_name_free(&zone->cname, view->mctx);
+ isc_mem_put(view->mctx, zone, sizeof(*zone));
+ }
+}
+
+/*
+ * Note that we have at least one response policy zone.
+ * It would be better for something to tell the rbtdb code that the
+ * zone is in at least one view's list of policy zones.
+ */
+void
+dns_rpz_set_need(isc_boolean_t need)
+{
+ have_rpz_zones = need;
+}
+
+
+isc_boolean_t
+dns_rpz_needed(void)
+{
+ return (have_rpz_zones);
+}
+
+
+
+/*
+ * Start a new radix tree for a response policy zone.
+ */
+isc_result_t
+dns_rpz_new_cidr(isc_mem_t *mctx, dns_name_t *origin,
+ dns_rpz_cidr_t **rbtdb_cidr)
+{
+ isc_result_t result;
+ dns_rpz_cidr_t *cidr;
+
+ REQUIRE(rbtdb_cidr != NULL && *rbtdb_cidr == NULL);
+
+ /*
+ * Only if there is at least one response policy zone.
+ */
+ if (!have_rpz_zones)
+ return (ISC_R_SUCCESS);
+
+ cidr = isc_mem_get(mctx, sizeof(*cidr));
+ if (cidr == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(cidr, 0, sizeof(*cidr));
+ cidr->mctx = mctx;
+
+ dns_name_init(&cidr->ip_name, NULL);
+ result = dns_name_fromstring2(&cidr->ip_name, DNS_RPZ_IP_ZONE, origin,
+ DNS_NAME_DOWNCASE, mctx);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, cidr, sizeof(*cidr));
+ return (result);
+ }
+
+ dns_name_init(&cidr->nsip_name, NULL);
+ result = dns_name_fromstring2(&cidr->nsip_name, DNS_RPZ_NSIP_ZONE,
+ origin, DNS_NAME_DOWNCASE, mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_free(&cidr->ip_name, mctx);
+ isc_mem_put(mctx, cidr, sizeof(*cidr));
+ return (result);
+ }
+
+ dns_name_init(&cidr->nsdname_name, NULL);
+ result = dns_name_fromstring2(&cidr->nsdname_name, DNS_RPZ_NSDNAME_ZONE,
+ origin, DNS_NAME_DOWNCASE, mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_free(&cidr->nsip_name, mctx);
+ dns_name_free(&cidr->ip_name, mctx);
+ isc_mem_put(mctx, cidr, sizeof(*cidr));
+ return (result);
+ }
+
+ *rbtdb_cidr = cidr;
+ return (ISC_R_SUCCESS);
+}
+
+
+/*
+ * See if a policy zone has IP, NSIP, or NSDNAME rules or records.
+ */
+void
+dns_rpz_enabled(dns_rpz_cidr_t *cidr, dns_rpz_st_t *st) {
+ if (cidr->root != NULL &&
+ (cidr->root->flags & DNS_RPZ_CIDR_FG_IP) != 0)
+ st->state |= DNS_RPZ_HAVE_IP;
+ if (cidr->root != NULL &&
+ (cidr->root->flags & DNS_RPZ_CIDR_FG_NSIPv4) != 0)
+ st->state |= DNS_RPZ_HAVE_NSIPv4;
+ if (cidr->root != NULL &&
+ (cidr->root->flags & DNS_RPZ_CIDR_FG_NSIPv6) != 0)
+ st->state |= DNS_RPZ_HAVE_NSIPv6;
+ if (cidr->had_nsdname)
+ st->state |= DNS_RPZ_HAD_NSDNAME;
+}
+
+static inline dns_rpz_cidr_flags_t
+get_flags(const dns_rpz_cidr_key_t *ip, dns_rpz_cidr_bits_t prefix,
+ dns_rpz_type_t rpz_type)
+{
+ if (rpz_type == DNS_RPZ_TYPE_NSIP) {
+ if (prefix >= 96 &&
+ ip->w[0] == 0 && ip->w[1] == 0 &&
+ ip->w[2] == ADDR_V4MAPPED)
+ return (DNS_RPZ_CIDR_FG_NSIP_DATA |
+ DNS_RPZ_CIDR_FG_NSIPv4);
+ else
+ return (DNS_RPZ_CIDR_FG_NSIP_DATA |
+ DNS_RPZ_CIDR_FG_NSIPv6);
+ } else {
+ return (DNS_RPZ_CIDR_FG_IP | DNS_RPZ_CIDR_FG_IP_DATA);
+ }
+}
+
+
+
+/*
+ * Mark a node as having IP or NSIP data and all of its parents
+ * as members of the IP or NSIP tree.
+ */
+static void
+set_node_flags(dns_rpz_cidr_node_t *node, dns_rpz_type_t rpz_type) {
+ dns_rpz_cidr_flags_t flags;
+
+ flags = get_flags(&node->ip, node->bits, rpz_type);
+ node->flags |= flags;
+ flags &= ~(DNS_RPZ_CIDR_FG_NSIP_DATA | DNS_RPZ_CIDR_FG_IP_DATA);
+ for (;;) {
+ node = node->parent;
+ if (node == NULL)
+ return;
+ node->flags |= flags;
+ }
+}
+
+
+
+/*
+ * Make a radix tree node.
+ */
+static dns_rpz_cidr_node_t *
+new_node(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *ip,
+ dns_rpz_cidr_bits_t bits, dns_rpz_cidr_flags_t flags)
+{
+ dns_rpz_cidr_node_t *node;
+ int i, words, wlen;
+
+ node = isc_mem_get(cidr->mctx, sizeof(*node));
+ if (node == NULL)
+ return (NULL);
+ memset(node, 0, sizeof(*node));
+
+ node->flags = flags & ~(DNS_RPZ_CIDR_FG_IP_DATA |
+ DNS_RPZ_CIDR_FG_NSIP_DATA);
+
+ node->bits = bits;
+ words = bits / DNS_RPZ_CIDR_WORD_BITS;
+ wlen = bits % DNS_RPZ_CIDR_WORD_BITS;
+ i = 0;
+ while (i < words) {
+ node->ip.w[i] = ip->w[i];
+ ++i;
+ }
+ if (wlen != 0) {
+ node->ip.w[i] = ip->w[i] & DNS_RPZ_WORD_MASK(wlen);
+ ++i;
+ }
+ while (i < DNS_RPZ_CIDR_WORDS)
+ node->ip.w[i++] = 0;
+
+ return (node);
+}
+
+
+
+static void
+badname(int level, dns_name_t *name, const char *comment)
+{
+ char printname[DNS_NAME_FORMATSIZE];
+
+ if (isc_log_wouldlog(dns_lctx, level)) {
+ dns_name_format(name, printname, sizeof(printname));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_RBTDB, level,
+ "invalid response policy name \"%s\"%s",
+ printname, comment);
+ }
+}
+
+
+
+/*
+ * Convert an IP address from radix tree binary (host byte order) to
+ * to its canonical response policy domain name and its name in the
+ * policy zone.
+ */
+static isc_result_t
+ip2name(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip,
+ dns_rpz_cidr_bits_t tgt_prefix, dns_rpz_type_t type,
+ dns_name_t *canon_name, dns_name_t *search_name)
+{
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+ int w[DNS_RPZ_CIDR_WORDS*2];
+ char str[1+8+1+INET6_ADDRSTRLEN+1];
+ isc_buffer_t buffer;
+ dns_name_t *name;
+ isc_result_t result;
+ isc_boolean_t zeros;
+ int i, n, len;
+
+ if (tgt_prefix > 96 &&
+ tgt_ip->w[0] == 0 &&
+ tgt_ip->w[1] == 0 &&
+ tgt_ip->w[2] == ADDR_V4MAPPED) {
+ len = snprintf(str, sizeof(str), "%d.%d.%d.%d.%d",
+ tgt_prefix - 96,
+ tgt_ip->w[3] & 0xff,
+ (tgt_ip->w[3]>>8) & 0xff,
+ (tgt_ip->w[3]>>16) & 0xff,
+ (tgt_ip->w[3]>>24) & 0xff);
+ if (len == -1 || len > (int)sizeof(str))
+ return (ISC_R_FAILURE);
+ } else {
+ for (i = 0; i < DNS_RPZ_CIDR_WORDS; i++) {
+ w[i*2+1] = ((tgt_ip->w[DNS_RPZ_CIDR_WORDS-1-i] >> 16)
+ & 0xffff);
+ w[i*2] = tgt_ip->w[DNS_RPZ_CIDR_WORDS-1-i] & 0xffff;
+ }
+ zeros = ISC_FALSE;
+ len = snprintf(str, sizeof(str), "%d", tgt_prefix);
+ if (len == -1)
+ return (ISC_R_FAILURE);
+ i = 0;
+ while (i < DNS_RPZ_CIDR_WORDS * 2) {
+ if (w[i] != 0 || zeros
+ || i >= DNS_RPZ_CIDR_WORDS * 2 - 1
+ || w[i+1] != 0) {
+ INSIST((size_t)len <= sizeof(str));
+ n = snprintf(&str[len], sizeof(str) - len,
+ ".%x", w[i++]);
+ if (n < 0)
+ return (ISC_R_FAILURE);
+ len += n;
+ } else {
+ zeros = ISC_TRUE;
+ INSIST((size_t)len <= sizeof(str));
+ n = snprintf(&str[len], sizeof(str) - len,
+ ".zz");
+ if (n < 0)
+ return (ISC_R_FAILURE);
+ len += n;
+ i += 2;
+ while (i < DNS_RPZ_CIDR_WORDS * 2 && w[i] == 0)
+ ++i;
+ }
+ if (len > (int)sizeof(str))
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ if (canon_name != NULL) {
+ isc__buffer_init(&buffer, str, sizeof(str));
+ isc__buffer_add(&buffer, len);
+ result = dns_name_fromtext(canon_name, &buffer,
+ dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (search_name != NULL) {
+ isc__buffer_init(&buffer, str, sizeof(str));
+ isc__buffer_add(&buffer, len);
+ if (type == DNS_RPZ_TYPE_NSIP)
+ name = &cidr->nsip_name;
+ else
+ name = &cidr->ip_name;
+ result = dns_name_fromtext(search_name, &buffer, name, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+
+
+/*
+ * Decide which kind of IP address response policy zone a name is in.
+ */
+static dns_rpz_type_t
+set_type(dns_rpz_cidr_t *cidr, dns_name_t *name) {
+
+ if (dns_name_issubdomain(name, &cidr->ip_name))
+ return (DNS_RPZ_TYPE_IP);
+
+ /*
+ * Require `./configure --enable-rpz-nsip` and nsdname
+ * until consistency problems are resolved.
+ */
+#ifdef ENABLE_RPZ_NSIP
+ if (dns_name_issubdomain(name, &cidr->nsip_name))
+ return (DNS_RPZ_TYPE_NSIP);
+#endif
+
+#ifdef ENABLE_RPZ_NSDNAME
+ if (dns_name_issubdomain(name, &cidr->nsdname_name))
+ return (DNS_RPZ_TYPE_NSDNAME);
+#endif
+
+ return (DNS_RPZ_TYPE_QNAME);
+}
+
+
+
+/*
+ * Convert an IP address from canonical response policy domain name form
+ * to radix tree binary (host byte order).
+ */
+static isc_result_t
+name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name,
+ dns_rpz_type_t type, dns_rpz_cidr_key_t *tgt_ip,
+ dns_rpz_cidr_bits_t *tgt_prefix)
+{
+ isc_buffer_t buffer;
+ unsigned char data[DNS_NAME_MAXWIRE+1];
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ const char *cp, *end;
+ char *cp2;
+ int ip_labels;
+ dns_rpz_cidr_bits_t bits;
+ unsigned long prefix, l;
+ int i;
+
+ /*
+ * Need at least enough labels for the shortest name,
+ * :: or 128.*.RPZ_x_ZONE.rpz.LOCALHOST.
+ */
+ ip_labels = dns_name_countlabels(src_name);
+ ip_labels -= dns_name_countlabels(&cidr->ip_name);
+ ip_labels--;
+ if (ip_labels < 1) {
+ badname(level, src_name, ", too short");
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * Get text for the IP address without RPZ_x_ZONE.rpz.LOCALHOST.
+ */
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_name_split(src_name, dns_name_countlabels(&cidr->ip_name),
+ name, NULL);
+ isc_buffer_init(&buffer, data, sizeof(data));
+ dns_name_totext(name, ISC_TRUE, &buffer);
+ isc_buffer_putuint8(&buffer, '\0');
+ cp = isc_buffer_base(&buffer);
+
+ prefix = strtoul(cp, &cp2, 10);
+ if (prefix < 1U || prefix > 128U || *cp2 != '.') {
+ badname(level, src_name, ", bad prefix length");
+ return (ISC_R_FAILURE);
+ }
+ cp = cp2+1;
+
+ end = isc_buffer_used(&buffer);
+ if (ip_labels == 4 && !strchr(cp, 'z')) {
+ /*
+ * Convert an IPv4 address
+ * from the form "prefix.w.z.y.x"
+ */
+ if (prefix > 32U) {
+ badname(level, src_name, "; bad IPv4 prefix length");
+ return (ISC_R_FAILURE);
+ }
+ prefix += 96;
+ *tgt_prefix = (dns_rpz_cidr_bits_t)prefix;
+ tgt_ip->w[0] = 0;
+ tgt_ip->w[1] = 0;
+ tgt_ip->w[2] = ADDR_V4MAPPED;
+ tgt_ip->w[3] = 0;
+ for (i = 0; i < 32; i += 8) {
+ l = strtoul(cp, &cp2, 10);
+ if (l > 255U || (*cp2 != '.' && *cp2 != '\0')) {
+ badname(level, src_name, "; bad IPv4 address");
+ return (ISC_R_FAILURE);
+ }
+ tgt_ip->w[3] |= l << i;
+ cp = cp2 + 1;
+ }
+ } else {
+ /*
+ * Convert a text IPv6 address.
+ */
+ *tgt_prefix = (dns_rpz_cidr_bits_t)prefix;
+ for (i = 0;
+ ip_labels > 0 && i < DNS_RPZ_CIDR_WORDS * 2;
+ ip_labels--) {
+ if (cp[0] == 'z' && cp[1] == 'z' &&
+ (cp[2] == '.' || cp[2] == '\0') &&
+ i <= 6) {
+ do {
+ if ((i & 1) == 0)
+ tgt_ip->w[3-i/2] = 0;
+ ++i;
+ } while (ip_labels + i <= 8);
+ cp += 3;
+ } else {
+ l = strtoul(cp, &cp2, 16);
+ if (l > 0xffffu ||
+ (*cp2 != '.' && *cp2 != '\0')) {
+ badname(level, src_name, "");
+ return (ISC_R_FAILURE);
+ }
+ if ((i & 1) == 0)
+ tgt_ip->w[3-i/2] = l;
+ else
+ tgt_ip->w[3-i/2] |= l << 16;
+ i++;
+ cp = cp2 + 1;
+ }
+ }
+ }
+ if (cp != end) {
+ badname(level, src_name, "");
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * Check for 1s after the prefix length.
+ */
+ bits = (dns_rpz_cidr_bits_t)prefix;
+ while (bits < DNS_RPZ_CIDR_KEY_BITS) {
+ dns_rpz_cidr_word_t aword;
+
+ i = bits % DNS_RPZ_CIDR_WORD_BITS;
+ aword = tgt_ip->w[bits / DNS_RPZ_CIDR_WORD_BITS];
+ if ((aword & ~DNS_RPZ_WORD_MASK(i)) != 0) {
+ badname(level, src_name, "; wrong prefix length");
+ return (ISC_R_FAILURE);
+ }
+ bits -= i;
+ bits += DNS_RPZ_CIDR_WORD_BITS;
+ }
+
+ /*
+ * Convert the IPv6 address back to a canonical policy domain name
+ * to ensure that it is in canonical form.
+ */
+ if (ISC_R_SUCCESS != ip2name(cidr, tgt_ip, (dns_rpz_cidr_bits_t)prefix,
+ type, NULL, name) ||
+ !dns_name_equal(src_name, name)) {
+ badname(level, src_name, "; not canonical");
+ return (ISC_R_FAILURE);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+
+
+/*
+ * find first differing bit
+ */
+static int
+ffbit(dns_rpz_cidr_word_t w) {
+ int bit;
+
+ if (w == 0)
+ return (DNS_RPZ_CIDR_WORD_BITS);
+ for (bit = 0; (w & (1U << (DNS_RPZ_CIDR_WORD_BITS-1))) == 0; bit++)
+ w <<= 1;
+ return (bit);
+}
+
+
+
+/*
+ * find the first differing bit in two keys
+ */
+static int
+diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_cidr_bits_t bits1,
+ const dns_rpz_cidr_key_t *key2, dns_rpz_cidr_bits_t bits2)
+{
+ dns_rpz_cidr_word_t delta;
+ dns_rpz_cidr_bits_t maxbit, bit;
+ int i;
+
+ maxbit = ISC_MIN(bits1, bits2);
+
+ /*
+ * find the first differing words
+ */
+ for (i = 0, bit = 0;
+ bit <= maxbit;
+ i++, bit += DNS_RPZ_CIDR_WORD_BITS) {
+ delta = key1->w[i] ^ key2->w[i];
+ if (delta != 0) {
+ bit += ffbit(delta);
+ break;
+ }
+ }
+ return (ISC_MIN(bit, maxbit));
+}
+
+
+
+/*
+ * Search a radix tree for an IP address for ordinary lookup
+ * or for a CIDR block adding or deleting an entry
+ * The tree read (for simple search) or write lock must be held by the caller.
+ *
+ * return ISC_R_SUCCESS, ISC_R_NOTFOUND, DNS_R_PARTIALMATCH, ISC_R_EXISTS,
+ * ISC_R_NOMEMORY
+ */
+static isc_result_t
+search(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip,
+ dns_rpz_cidr_bits_t tgt_prefix, dns_rpz_type_t type,
+ isc_boolean_t create,
+ dns_rpz_cidr_node_t **found) /* NULL or longest match node */
+{
+ dns_rpz_cidr_node_t *cur, *parent, *child, *new_parent, *sibling;
+ int cur_num, child_num;
+ dns_rpz_cidr_bits_t dbit;
+ dns_rpz_cidr_flags_t flags, data_flag;
+ isc_result_t find_result;
+
+ flags = get_flags(tgt_ip, tgt_prefix, type);
+ data_flag = flags & (DNS_RPZ_CIDR_FG_IP_DATA |
+ DNS_RPZ_CIDR_FG_NSIP_DATA);
+
+ find_result = ISC_R_NOTFOUND;
+ if (found != NULL)
+ *found = NULL;
+ cur = cidr->root;
+ parent = NULL;
+ cur_num = 0;
+ for (;;) {
+ if (cur == NULL) {
+ /*
+ * No child so we cannot go down. Fail or
+ * add the target as a child of the current parent.
+ */
+ if (!create)
+ return (find_result);
+ child = new_node(cidr, tgt_ip, tgt_prefix, 0);
+ if (child == NULL)
+ return (ISC_R_NOMEMORY);
+ if (parent == NULL)
+ cidr->root = child;
+ else
+ parent->child[cur_num] = child;
+ child->parent = parent;
+ set_node_flags(child, type);
+ if (found != NULL)
+ *found = cur;
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Pretend a node not in the correct tree does not exist
+ * if we are not adding to the tree,
+ * If we are adding, then continue down to eventually
+ * add a node and mark/put this node in the correct tree.
+ */
+ if ((cur->flags & flags) == 0 && !create)
+ return (find_result);
+
+ dbit = diff_keys(tgt_ip, tgt_prefix, &cur->ip, cur->bits);
+ /*
+ * dbit <= tgt_prefix and dbit <= cur->bits always.
+ * We are finished searching if we matched all of the target.
+ */
+ if (dbit == tgt_prefix) {
+ if (tgt_prefix == cur->bits) {
+ /*
+ * The current node matches the target exactly.
+ * It is the answer if it has data.
+ */
+ if ((cur->flags & data_flag) != 0) {
+ if (create)
+ return (ISC_R_EXISTS);
+ if (found != NULL)
+ *found = cur;
+ return (ISC_R_SUCCESS);
+ } else if (create) {
+ /*
+ * The node had no data but does now.
+ */
+ set_node_flags(cur, type);
+ if (found != NULL)
+ *found = cur;
+ return (ISC_R_SUCCESS);
+ }
+ return (find_result);
+ }
+
+ /*
+ * We know tgt_prefix < cur_bits which means that
+ * the target is shorter than the current node.
+ * Add the target as the current node's parent.
+ */
+ if (!create)
+ return (find_result);
+
+ new_parent = new_node(cidr, tgt_ip, tgt_prefix,
+ cur->flags);
+ if (new_parent == NULL)
+ return (ISC_R_NOMEMORY);
+ new_parent->parent = parent;
+ if (parent == NULL)
+ cidr->root = new_parent;
+ else
+ parent->child[cur_num] = new_parent;
+ child_num = DNS_RPZ_IP_BIT(&cur->ip, tgt_prefix+1);
+ new_parent->child[child_num] = cur;
+ cur->parent = new_parent;
+ set_node_flags(new_parent, type);
+ if (found != NULL)
+ *found = new_parent;
+ return (ISC_R_SUCCESS);
+ }
+
+ if (dbit == cur->bits) {
+ /*
+ * We have a partial match by matching of all of the
+ * current node but only part of the target.
+ * Try to go down.
+ */
+ if ((cur->flags & data_flag) != 0) {
+ find_result = DNS_R_PARTIALMATCH;
+ if (found != NULL)
+ *found = cur;
+ }
+
+ parent = cur;
+ cur_num = DNS_RPZ_IP_BIT(tgt_ip, dbit);
+ cur = cur->child[cur_num];
+ continue;
+ }
+
+
+ /*
+ * dbit < tgt_prefix and dbit < cur->bits,
+ * so we failed to match both the target and the current node.
+ * Insert a fork of a parent above the current node and
+ * add the target as a sibling of the current node
+ */
+ if (!create)
+ return (find_result);
+
+ sibling = new_node(cidr, tgt_ip, tgt_prefix, 0);
+ if (sibling == NULL)
+ return (ISC_R_NOMEMORY);
+ new_parent = new_node(cidr, tgt_ip, dbit, cur->flags);
+ if (new_parent == NULL) {
+ isc_mem_put(cidr->mctx, sibling, sizeof(*sibling));
+ return (ISC_R_NOMEMORY);
+ }
+ new_parent->parent = parent;
+ if (parent == NULL)
+ cidr->root = new_parent;
+ else
+ parent->child[cur_num] = new_parent;
+ child_num = DNS_RPZ_IP_BIT(tgt_ip, dbit);
+ new_parent->child[child_num] = sibling;
+ new_parent->child[1-child_num] = cur;
+ cur->parent = new_parent;
+ sibling->parent = new_parent;
+ set_node_flags(sibling, type);
+ if (found != NULL)
+ *found = sibling;
+ return (ISC_R_SUCCESS);
+ }
+}
+
+
+
+/*
+ * Add an IP address to the radix tree of a response policy database.
+ * The tree write lock must be held by the caller.
+ */
+void
+dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name)
+{
+ dns_rpz_cidr_key_t tgt_ip;
+ dns_rpz_cidr_bits_t tgt_prefix;
+ dns_rpz_type_t type;
+
+ if (cidr == NULL)
+ return;
+
+ /*
+ * no worries if the new name is not an IP address
+ */
+ type = set_type(cidr, name);
+ switch (type) {
+ case DNS_RPZ_TYPE_IP:
+ case DNS_RPZ_TYPE_NSIP:
+ break;
+ case DNS_RPZ_TYPE_NSDNAME:
+ cidr->had_nsdname = ISC_TRUE;
+ return;
+ case DNS_RPZ_TYPE_QNAME:
+ case DNS_RPZ_TYPE_BAD:
+ return;
+ }
+ if (ISC_R_SUCCESS != name2ipkey(cidr, DNS_RPZ_ERROR_LEVEL, name,
+ type, &tgt_ip, &tgt_prefix))
+ return;
+
+ if (ISC_R_EXISTS == search(cidr, &tgt_ip, tgt_prefix, type,
+ ISC_TRUE, NULL) &&
+ isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) {
+ char printname[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, printname, sizeof(printname));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
+ "duplicate response policy name \"%s\"",
+ printname);
+ }
+}
+
+
+
+/*
+ * Delete an IP address from the radix tree of a response policy database.
+ * The tree write lock must be held by the caller.
+ */
+void
+dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name) {
+ dns_rpz_cidr_key_t tgt_ip;
+ dns_rpz_cidr_bits_t tgt_prefix;
+ dns_rpz_type_t type;
+ dns_rpz_cidr_node_t *tgt = NULL, *parent, *child;
+ dns_rpz_cidr_flags_t flags, data_flag;
+
+ if (cidr == NULL)
+ return;
+
+ /*
+ * Decide which kind of policy zone IP address it is, if either
+ * and then find its node.
+ */
+ type = set_type(cidr, name);
+ switch (type) {
+ case DNS_RPZ_TYPE_IP:
+ case DNS_RPZ_TYPE_NSIP:
+ break;
+ case DNS_RPZ_TYPE_NSDNAME:
+ /*
+ * We cannot easily count nsdnames because
+ * internal rbt nodes get deleted.
+ */
+ return;
+ case DNS_RPZ_TYPE_QNAME:
+ case DNS_RPZ_TYPE_BAD:
+ return;
+ }
+
+ /*
+ * Do not get excited about the deletion of interior rbt nodes.
+ */
+ if (ISC_R_SUCCESS != name2ipkey(cidr, DNS_RPZ_DEBUG_LEVEL2, name,
+ type, &tgt_ip, &tgt_prefix))
+ return;
+ if (ISC_R_SUCCESS != search(cidr, &tgt_ip, tgt_prefix, type,
+ ISC_FALSE, &tgt)) {
+ if (isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) {
+ char printname[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, printname, sizeof(printname));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
+ "missing response policy node \"%s\"",
+ printname);
+ }
+ return;
+ }
+
+ /*
+ * Mark the node and its parents to reflect the deleted IP address.
+ */
+ flags = get_flags(&tgt_ip, tgt_prefix, type);
+ data_flag = flags & (DNS_RPZ_CIDR_FG_IP_DATA |
+ DNS_RPZ_CIDR_FG_NSIP_DATA);
+ tgt->flags &= ~data_flag;
+ for (parent = tgt; parent != NULL; parent = parent->parent) {
+ if ((parent->flags & data_flag) != 0 ||
+ (parent->child[0] != NULL &&
+ (parent->child[0]->flags & flags) != 0) ||
+ (parent->child[1] != NULL &&
+ (parent->child[1]->flags & flags) != 0))
+ break;
+ parent->flags &= ~flags;
+ }
+
+ /*
+ * We might need to delete 2 nodes.
+ */
+ do {
+ /*
+ * The node is now useless if it has no data of its own
+ * and 0 or 1 children. We are finished if it is not useless.
+ */
+ if ((child = tgt->child[0]) != NULL) {
+ if (tgt->child[1] != NULL)
+ return;
+ } else {
+ child = tgt->child[1];
+ }
+ if ((tgt->flags & (DNS_RPZ_CIDR_FG_IP_DATA |
+ DNS_RPZ_CIDR_FG_NSIP_DATA)) != 0)
+ return;
+
+ /*
+ * Replace the pointer to this node in the parent with
+ * the remaining child or NULL.
+ */
+ parent = tgt->parent;
+ if (parent == NULL) {
+ cidr->root = child;
+ } else {
+ parent->child[parent->child[1] == tgt] = child;
+ }
+ /*
+ * If the child exists fix up its parent pointer.
+ */
+ if (child != NULL)
+ child->parent = parent;
+ isc_mem_put(cidr->mctx, tgt, sizeof(*tgt));
+
+ tgt = parent;
+ } while (tgt != NULL);
+}
+
+
+
+/*
+ * Caller must hold tree lock.
+ * Return ISC_R_NOTFOUND
+ * or ISC_R_SUCCESS and the found entry's canonical and search names
+ * and its prefix length
+ */
+isc_result_t
+dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr,
+ dns_rpz_type_t type, dns_name_t *canon_name,
+ dns_name_t *search_name, dns_rpz_cidr_bits_t *prefix)
+{
+ dns_rpz_cidr_key_t tgt_ip;
+ isc_result_t result;
+ dns_rpz_cidr_node_t *found;
+ int i;
+
+ /*
+ * Convert IP address to CIDR tree key.
+ */
+ if (netaddr->family == AF_INET) {
+ tgt_ip.w[0] = 0;
+ tgt_ip.w[1] = 0;
+ tgt_ip.w[2] = ADDR_V4MAPPED;
+ tgt_ip.w[3] = ntohl(netaddr->type.in.s_addr);
+ } else if (netaddr->family == AF_INET6) {
+ dns_rpz_cidr_key_t src_ip6;
+
+ /*
+ * Given the int aligned struct in_addr member of netaddr->type
+ * one could cast netaddr->type.in6 to dns_rpz_cidr_key_t *,
+ * but there are objections.
+ */
+ memcpy(src_ip6.w, &netaddr->type.in6, sizeof(src_ip6.w));
+ for (i = 0; i < 4; i++) {
+ tgt_ip.w[i] = ntohl(src_ip6.w[i]);
+ }
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
+
+ result = search(cidr, &tgt_ip, 128, type, ISC_FALSE, &found);
+ if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH)
+ return (result);
+
+ *prefix = found->bits;
+ return (ip2name(cidr, &found->ip, found->bits, type,
+ canon_name, search_name));
+}
+
+
+
+/*
+ * Translate CNAME rdata to a QNAME response policy action.
+ */
+dns_rpz_policy_t
+dns_rpz_decode_cname(dns_rdataset_t *rdataset, dns_name_t *selfname) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_cname_t cname;
+ isc_result_t result;
+
+ result = dns_rdataset_first(rdataset);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdata_reset(&rdata);
+
+ /*
+ * CNAME . means NXDOMAIN
+ */
+ if (dns_name_equal(&cname.cname, dns_rootname))
+ return (DNS_RPZ_POLICY_NXDOMAIN);
+
+ /*
+ * CNAME *. means NODATA
+ */
+ if (dns_name_countlabels(&cname.cname) == 2
+ && dns_name_iswildcard(&cname.cname))
+ return (DNS_RPZ_POLICY_NODATA);
+
+ /*
+ * 128.1.0.127.rpz-ip CNAME 128.1.0.0.127. means "do not rewrite"
+ */
+ if (selfname != NULL && dns_name_equal(&cname.cname, selfname))
+ return (DNS_RPZ_POLICY_NO_OP);
+
+ /*
+ * evil.com CNAME garden.net rewrites www.evil.com to www.garden.net.
+ */
+ return (DNS_RPZ_POLICY_RECORD);
+}
diff --git a/contrib/bind9/lib/dns/rriterator.c b/contrib/bind9/lib/dns/rriterator.c
new file mode 100644
index 0000000..31d67af
--- /dev/null
+++ b/contrib/bind9/lib/dns/rriterator.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 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: rriterator.c,v 1.2 2009-06-30 02:52:32 each Exp $ */
+
+/*! \file */
+
+/***
+ *** Imports
+ ***/
+
+#include <config.h>
+
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+#include <dns/rriterator.h>
+
+/***
+ *** RRiterator methods
+ ***/
+
+isc_result_t
+dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
+ isc_stdtime_t now)
+{
+ isc_result_t result;
+ it->magic = RRITERATOR_MAGIC;
+ it->db = db;
+ it->dbit = NULL;
+ it->ver = ver;
+ it->now = now;
+ it->node = NULL;
+ result = dns_db_createiterator(it->db, 0, &it->dbit);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ it->rdatasetit = NULL;
+ dns_rdata_init(&it->rdata);
+ dns_rdataset_init(&it->rdataset);
+ dns_fixedname_init(&it->fixedname);
+ INSIST(! dns_rdataset_isassociated(&it->rdataset));
+ it->result = ISC_R_SUCCESS;
+ return (it->result);
+}
+
+isc_result_t
+dns_rriterator_first(dns_rriterator_t *it) {
+ REQUIRE(VALID_RRITERATOR(it));
+ /* Reset state */
+ if (dns_rdataset_isassociated(&it->rdataset))
+ dns_rdataset_disassociate(&it->rdataset);
+ if (it->rdatasetit != NULL)
+ dns_rdatasetiter_destroy(&it->rdatasetit);
+ if (it->node != NULL)
+ dns_db_detachnode(it->db, &it->node);
+ it->result = dns_dbiterator_first(it->dbit);
+
+ /*
+ * The top node may be empty when out of zone glue exists.
+ * Walk the tree to find the first node with data.
+ */
+ while (it->result == ISC_R_SUCCESS) {
+ it->result = dns_dbiterator_current(it->dbit, &it->node,
+ dns_fixedname_name(&it->fixedname));
+ if (it->result != ISC_R_SUCCESS)
+ return (it->result);
+
+ it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
+ it->now, &it->rdatasetit);
+ if (it->result != ISC_R_SUCCESS)
+ return (it->result);
+
+ it->result = dns_rdatasetiter_first(it->rdatasetit);
+ if (it->result != ISC_R_SUCCESS) {
+ /*
+ * This node is empty. Try next node.
+ */
+ dns_rdatasetiter_destroy(&it->rdatasetit);
+ dns_db_detachnode(it->db, &it->node);
+ it->result = dns_dbiterator_next(it->dbit);
+ continue;
+ }
+ dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
+ it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
+ it->result = dns_rdataset_first(&it->rdataset);
+ return (it->result);
+ }
+ return (it->result);
+}
+
+isc_result_t
+dns_rriterator_nextrrset(dns_rriterator_t *it) {
+ REQUIRE(VALID_RRITERATOR(it));
+ if (dns_rdataset_isassociated(&it->rdataset))
+ dns_rdataset_disassociate(&it->rdataset);
+ it->result = dns_rdatasetiter_next(it->rdatasetit);
+ /*
+ * The while loop body is executed more than once
+ * only when an empty dbnode needs to be skipped.
+ */
+ while (it->result == ISC_R_NOMORE) {
+ dns_rdatasetiter_destroy(&it->rdatasetit);
+ dns_db_detachnode(it->db, &it->node);
+ it->result = dns_dbiterator_next(it->dbit);
+ if (it->result == ISC_R_NOMORE) {
+ /* We are at the end of the entire database. */
+ return (it->result);
+ }
+ if (it->result != ISC_R_SUCCESS)
+ return (it->result);
+ it->result = dns_dbiterator_current(it->dbit, &it->node,
+ dns_fixedname_name(&it->fixedname));
+ if (it->result != ISC_R_SUCCESS)
+ return (it->result);
+ it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
+ it->now, &it->rdatasetit);
+ if (it->result != ISC_R_SUCCESS)
+ return (it->result);
+ it->result = dns_rdatasetiter_first(it->rdatasetit);
+ }
+ if (it->result != ISC_R_SUCCESS)
+ return (it->result);
+ dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
+ it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
+ it->result = dns_rdataset_first(&it->rdataset);
+ return (it->result);
+}
+
+isc_result_t
+dns_rriterator_next(dns_rriterator_t *it) {
+ REQUIRE(VALID_RRITERATOR(it));
+ if (it->result != ISC_R_SUCCESS)
+ return (it->result);
+
+ INSIST(it->dbit != NULL);
+ INSIST(it->node != NULL);
+ INSIST(it->rdatasetit != NULL);
+
+ it->result = dns_rdataset_next(&it->rdataset);
+ if (it->result == ISC_R_NOMORE)
+ return (dns_rriterator_nextrrset(it));
+ return (it->result);
+}
+
+void
+dns_rriterator_pause(dns_rriterator_t *it) {
+ REQUIRE(VALID_RRITERATOR(it));
+ RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
+}
+
+void
+dns_rriterator_destroy(dns_rriterator_t *it) {
+ REQUIRE(VALID_RRITERATOR(it));
+ if (dns_rdataset_isassociated(&it->rdataset))
+ dns_rdataset_disassociate(&it->rdataset);
+ if (it->rdatasetit != NULL)
+ dns_rdatasetiter_destroy(&it->rdatasetit);
+ if (it->node != NULL)
+ dns_db_detachnode(it->db, &it->node);
+ dns_dbiterator_destroy(&it->dbit);
+}
+
+void
+dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name,
+ isc_uint32_t *ttl, dns_rdataset_t **rdataset,
+ dns_rdata_t **rdata)
+{
+ REQUIRE(name != NULL && *name == NULL);
+ REQUIRE(VALID_RRITERATOR(it));
+ REQUIRE(it->result == ISC_R_SUCCESS);
+
+ *name = dns_fixedname_name(&it->fixedname);
+ *ttl = it->rdataset.ttl;
+
+ dns_rdata_reset(&it->rdata);
+ dns_rdataset_current(&it->rdataset, &it->rdata);
+
+ if (rdataset)
+ *rdataset = &it->rdataset;
+
+ if (rdata)
+ *rdata = &it->rdata;
+}
diff --git a/contrib/bind9/lib/dns/sdb.c b/contrib/bind9/lib/dns/sdb.c
index 49c6430..d27007d 100644
--- a/contrib/bind9/lib/dns/sdb.c
+++ b/contrib/bind9/lib/dns/sdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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.66.48.6 2010-08-16 05:21:42 marka Exp $ */
+/* $Id: sdb.c,v 1.76 2011-01-13 04:59:25 tbox Exp $ */
/*! \file */
@@ -450,7 +450,7 @@ getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
isc_buffer_init(&b, name, strlen(name));
isc_buffer_add(&b, strlen(name));
- result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
+ result = dns_name_fromtext(newname, &b, origin, 0, NULL);
if (result != ISC_R_SUCCESS)
return (result);
@@ -1253,6 +1253,8 @@ static dns_dbmethods_t sdb_methods = {
NULL,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
diff --git a/contrib/bind9/lib/dns/sdlz.c b/contrib/bind9/lib/dns/sdlz.c
index 6be315a..e684e1d 100644
--- a/contrib/bind9/lib/dns/sdlz.c
+++ b/contrib/bind9/lib/dns/sdlz.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2005-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005-2011 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.18.50.6 2010-08-16 05:21:42 marka Exp $ */
+/* $Id: sdlz.c,v 1.31 2011-01-13 06:29:16 marka Exp $ */
/*! \file */
@@ -108,6 +108,8 @@ struct dns_sdlz_db {
isc_mutex_t refcnt_lock;
/* Locked */
unsigned int references;
+ dns_dbversion_t *future_version;
+ int dummy_version;
};
struct dns_sdlzlookup {
@@ -164,8 +166,6 @@ typedef struct sdlz_rdatasetiter {
/* This is a reasonable value */
#define SDLZ_DEFAULT_TTL (60 * 60 * 24)
-static int dummy;
-
#ifdef __COVERITY__
#define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
#define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
@@ -225,11 +225,22 @@ static dns_dbiteratormethods_t dbiterator_methods = {
* Utility functions
*/
-/*% Converts the input string to lowercase, in place. */
+/*
+ * Log a message at the given level
+ */
+static void
+sdlz_log(int level, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level),
+ fmt, ap);
+ va_end(ap);
+}
+/*% Converts the input string to lowercase, in place. */
static void
dns_sdlz_tolower(char *str) {
-
unsigned int len = strlen(str);
unsigned int i;
@@ -237,7 +248,6 @@ dns_sdlz_tolower(char *str) {
if (str[i] >= 'A' && str[i] <= 'Z')
str[i] += 32;
}
-
}
static inline unsigned int
@@ -381,43 +391,79 @@ dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
static void
currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ REQUIRE(VALID_SDLZDB(sdlz));
REQUIRE(versionp != NULL && *versionp == NULL);
- UNUSED(db);
-
- *versionp = (void *) &dummy;
+ *versionp = (void *) &sdlz->dummy_version;
return;
}
static isc_result_t
newversion(dns_db_t *db, dns_dbversion_t **versionp) {
- UNUSED(db);
- UNUSED(versionp);
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ char origin[DNS_NAME_MAXTEXT + 1];
+ isc_result_t result;
- return (ISC_R_NOTIMPLEMENTED);
+ REQUIRE(VALID_SDLZDB(sdlz));
+
+ if (sdlz->dlzimp->methods->newversion == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
+
+ result = sdlz->dlzimp->methods->newversion(origin,
+ sdlz->dlzimp->driverarg,
+ sdlz->dbdata, versionp);
+ if (result != ISC_R_SUCCESS) {
+ sdlz_log(ISC_LOG_ERROR,
+ "sdlz newversion on origin %s failed : %s",
+ origin, isc_result_totext(result));
+ return (result);
+ }
+
+ sdlz->future_version = *versionp;
+ return (ISC_R_SUCCESS);
}
static void
attachversion(dns_db_t *db, dns_dbversion_t *source,
dns_dbversion_t **targetp)
{
- REQUIRE(source != NULL && source == (void *) &dummy);
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+ REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
- UNUSED(db);
- UNUSED(source);
- UNUSED(targetp);
*targetp = source;
}
static void
closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
- REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
- REQUIRE(commit == ISC_FALSE);
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ char origin[DNS_NAME_MAXTEXT + 1];
- UNUSED(db);
- UNUSED(commit);
+ REQUIRE(VALID_SDLZDB(sdlz));
+ REQUIRE(versionp != NULL);
+
+ if (*versionp == (void *)&sdlz->dummy_version) {
+ *versionp = NULL;
+ return;
+ }
+
+ REQUIRE(*versionp == sdlz->future_version);
+ REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
+
+ dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
- *versionp = NULL;
+ sdlz->dlzimp->methods->closeversion(origin, commit,
+ sdlz->dlzimp->driverarg,
+ sdlz->dbdata, versionp);
+ if (*versionp != NULL)
+ sdlz_log(ISC_LOG_ERROR,
+ "sdlz closeversion on origin %s failed", origin);
+
+ sdlz->future_version = NULL;
}
static isc_result_t
@@ -506,11 +552,11 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
dns_sdlzauthorityfunc_t authority;
REQUIRE(VALID_SDLZDB(sdlz));
- REQUIRE(create == ISC_FALSE);
REQUIRE(nodep != NULL && *nodep == NULL);
- UNUSED(name);
- UNUSED(create);
+ if (sdlz->dlzimp->methods->newversion == NULL) {
+ REQUIRE(create == ISC_FALSE);
+ }
isc_buffer_init(&b, namestr, sizeof(namestr));
if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
@@ -558,7 +604,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
* if the host (namestr) was not found, try to lookup a
* "wildcard" host.
*/
- if (result != ISC_R_SUCCESS) {
+ if (result != ISC_R_SUCCESS && !create) {
result = sdlz->dlzimp->methods->lookup(zonestr, "*",
sdlz->dlzimp->driverarg,
sdlz->dbdata, node);
@@ -566,7 +612,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
MAYBE_UNLOCK(sdlz->dlzimp);
- if (result != ISC_R_SUCCESS && !isorigin) {
+ if (result != ISC_R_SUCCESS && !isorigin && !create) {
destroynode(node);
return (result);
}
@@ -584,6 +630,23 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
}
}
+ if (node->name == NULL) {
+ node->name = isc_mem_get(sdlz->common.mctx,
+ sizeof(dns_name_t));
+ if (node->name == NULL) {
+ destroynode(node);
+ return (ISC_R_NOMEMORY);
+ }
+ dns_name_init(node->name, NULL);
+ result = dns_name_dup(name, sdlz->common.mctx, node->name);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(sdlz->common.mctx, node->name,
+ sizeof(dns_name_t));
+ destroynode(node);
+ return (result);
+ }
+ }
+
*nodep = node;
return (ISC_R_SUCCESS);
}
@@ -778,7 +841,7 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
REQUIRE(VALID_SDLZDB(sdlz));
REQUIRE(nodep == NULL || *nodep == NULL);
- REQUIRE(version == NULL || version == (void *) &dummy);
+ REQUIRE(version == NULL || version == (void*)&sdlz->dummy_version);
UNUSED(options);
UNUSED(sdlz);
@@ -920,9 +983,14 @@ static isc_result_t
allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
{
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db;
sdlz_rdatasetiter_t *iterator;
- REQUIRE(version == NULL || version == &dummy);
+ REQUIRE(VALID_SDLZDB(sdlz));
+
+ REQUIRE(version == NULL ||
+ version == (void*)&sdlz->dummy_version ||
+ version == sdlz->future_version);
UNUSED(version);
UNUSED(now);
@@ -945,47 +1013,139 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
}
static isc_result_t
+modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdataset_t *rdataset, unsigned int options,
+ dns_sdlzmodrdataset_t mod_function)
+{
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ dns_master_style_t *style = NULL;
+ isc_result_t result;
+ isc_buffer_t *buffer = NULL;
+ isc_mem_t *mctx;
+ dns_sdlznode_t *sdlznode;
+ char *rdatastr = NULL;
+ char name[DNS_NAME_MAXTEXT + 1];
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+
+ if (mod_function == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ sdlznode = (dns_sdlznode_t *)node;
+
+ UNUSED(options);
+
+ dns_name_format(sdlznode->name, name, sizeof(name));
+
+ mctx = sdlz->common.mctx;
+
+ result = isc_buffer_allocate(mctx, &buffer, 1024);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, mctx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_master_rdatasettotext(sdlznode->name, rdataset,
+ style, buffer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if (isc_buffer_usedlength(buffer) < 1) {
+ result = ISC_R_BADADDRESSFORM;
+ goto cleanup;
+ }
+
+ rdatastr = isc_buffer_base(buffer);
+ if (rdatastr == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
+
+ MAYBE_LOCK(sdlz->dlzimp);
+ result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
+ sdlz->dbdata, version);
+ MAYBE_UNLOCK(sdlz->dlzimp);
+
+cleanup:
+ isc_buffer_free(&buffer);
+ if (style != NULL)
+ dns_master_styledestroy(&style, mctx);
+
+ return (result);
+}
+
+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,
dns_rdataset_t *addedrdataset)
{
- UNUSED(db);
- UNUSED(node);
- UNUSED(version);
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ isc_result_t result;
+
UNUSED(now);
- UNUSED(rdataset);
- UNUSED(options);
UNUSED(addedrdataset);
+ REQUIRE(VALID_SDLZDB(sdlz));
- return (ISC_R_NOTIMPLEMENTED);
+ if (sdlz->dlzimp->methods->addrdataset == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ result = modrdataset(db, node, version, rdataset, options,
+ sdlz->dlzimp->methods->addrdataset);
+ return (result);
}
+
static isc_result_t
subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_rdataset_t *rdataset, unsigned int options,
dns_rdataset_t *newrdataset)
{
- UNUSED(db);
- UNUSED(node);
- UNUSED(version);
- UNUSED(rdataset);
- UNUSED(options);
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ isc_result_t result;
+
UNUSED(newrdataset);
+ REQUIRE(VALID_SDLZDB(sdlz));
- return (ISC_R_NOTIMPLEMENTED);
+ if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ result = modrdataset(db, node, version, rdataset, options,
+ sdlz->dlzimp->methods->subtractrdataset);
+ return (result);
}
static isc_result_t
deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_rdatatype_t type, dns_rdatatype_t covers)
{
- UNUSED(db);
- UNUSED(node);
- UNUSED(version);
- UNUSED(type);
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ char name[DNS_NAME_MAXTEXT + 1];
+ char b_type[DNS_RDATATYPE_FORMATSIZE];
+ dns_sdlznode_t *sdlznode;
+ isc_result_t result;
+
UNUSED(covers);
- return (ISC_R_NOTIMPLEMENTED);
+ REQUIRE(VALID_SDLZDB(sdlz));
+
+ if (sdlz->dlzimp->methods->delrdataset == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ sdlznode = (dns_sdlznode_t *)node;
+ dns_name_format(sdlznode->name, name, sizeof(name));
+ dns_rdatatype_format(type, b_type, sizeof(b_type));
+
+ MAYBE_LOCK(sdlz->dlzimp);
+ result = sdlz->dlzimp->methods->delrdataset(name, b_type,
+ sdlz->dlzimp->driverarg,
+ sdlz->dbdata, version);
+ MAYBE_UNLOCK(sdlz->dlzimp);
+
+ return (result);
}
static isc_boolean_t
@@ -1021,6 +1181,26 @@ settask(dns_db_t *db, isc_task_t *task) {
}
+/*
+ * getoriginnode() is used by the update code to find the
+ * dns_rdatatype_dnskey record for a zone
+ */
+static isc_result_t
+getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ isc_result_t result;
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+ if (sdlz->dlzimp->methods->newversion == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ result = findnode(db, &sdlz->common.origin, ISC_FALSE, nodep);
+ if (result != ISC_R_SUCCESS)
+ sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed : %s",
+ isc_result_totext(result));
+ return (result);
+}
+
static dns_dbmethods_t sdlzdb_methods = {
attach,
detach,
@@ -1049,6 +1229,8 @@ static dns_dbmethods_t sdlzdb_methods = {
ispersistent,
overmem,
settask,
+ getoriginnode,
+ NULL,
NULL,
NULL,
NULL,
@@ -1371,9 +1553,7 @@ dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
isc_result_t result = ISC_R_NOTFOUND;
/* Write debugging message to log */
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
- "Loading SDLZ driver.");
+ sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
/*
* Performs checks to make sure data is as we expect it to be.
@@ -1395,13 +1575,9 @@ dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
/* Write debugging message to log */
if (result == ISC_R_SUCCESS) {
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
- "SDLZ driver loaded successfully.");
+ sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
} else {
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
- "SDLZ driver failed to load.");
+ sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
}
return (result);
@@ -1414,9 +1590,7 @@ dns_sdlzdestroy(void *driverdata, void **dbdata)
dns_sdlzimplementation_t *imp;
/* Write debugging message to log */
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
- "Unloading SDLZ driver.");
+ sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
imp = driverdata;
@@ -1472,11 +1646,97 @@ dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
return (result);
}
+
+static isc_result_t
+dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view)
+{
+ isc_result_t result;
+ dns_sdlzimplementation_t *imp;
+
+ REQUIRE(driverarg != NULL);
+
+ imp = (dns_sdlzimplementation_t *) driverarg;
+
+ /* Call SDLZ driver's configure method */
+ if (imp->methods->configure != NULL) {
+ MAYBE_LOCK(imp);
+ result = imp->methods->configure(view, imp->driverarg, dbdata);
+ MAYBE_UNLOCK(imp);
+ } else {
+ result = ISC_R_SUCCESS;
+ }
+
+ return (result);
+}
+
+static isc_boolean_t
+dns_sdlzssumatch(dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
+ dns_rdatatype_t type, const dst_key_t *key, void *driverarg,
+ void *dbdata)
+{
+ dns_sdlzimplementation_t *imp;
+ char b_signer[DNS_NAME_FORMATSIZE];
+ char b_name[DNS_NAME_FORMATSIZE];
+ char b_addr[ISC_NETADDR_FORMATSIZE];
+ char b_type[DNS_RDATATYPE_FORMATSIZE];
+ char b_key[DST_KEY_FORMATSIZE];
+ isc_buffer_t *tkey_token;
+ isc_region_t token_region;
+ isc_uint32_t token_len = 0;
+ isc_boolean_t ret;
+
+ REQUIRE(driverarg != NULL);
+
+ imp = (dns_sdlzimplementation_t *) driverarg;
+ if (imp->methods->ssumatch == NULL)
+ return (ISC_FALSE);
+
+ /*
+ * Format the request elements. sdlz operates on strings, not
+ * structures
+ */
+ if (signer)
+ dns_name_format(signer, b_signer, sizeof(b_signer));
+ else
+ b_signer[0] = 0;
+
+ dns_name_format(name, b_name, sizeof(b_name));
+
+ if (tcpaddr)
+ isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
+ else
+ b_addr[0] = 0;
+
+ dns_rdatatype_format(type, b_type, sizeof(b_type));
+
+ if (key)
+ dst_key_format(key, b_key, sizeof(b_key));
+ else
+ b_key[0] = 0;
+
+ tkey_token = dst_key_tkeytoken(key);
+
+ if (tkey_token) {
+ isc_buffer_region(tkey_token, &token_region);
+ token_len = token_region.length;
+ }
+
+ MAYBE_LOCK(imp);
+ ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
+ token_len,
+ token_len ? token_region.base : NULL,
+ imp->driverarg, dbdata);
+ MAYBE_UNLOCK(imp);
+ return (ret);
+}
+
static dns_dlzmethods_t sdlzmethods = {
dns_sdlzcreate,
dns_sdlzdestroy,
dns_sdlzfindzone,
- dns_sdlzallowzonexfr
+ dns_sdlzallowzonexfr,
+ dns_sdlzconfigure,
+ dns_sdlzssumatch
};
/*
@@ -1530,8 +1790,16 @@ dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
ISC_LINK_INIT(rdatalist, link);
ISC_LIST_APPEND(lookup->lists, rdatalist, link);
} else
- if (rdatalist->ttl != ttl)
- return (DNS_R_BADTTL);
+ if (rdatalist->ttl > ttl) {
+ /*
+ * BIND9 doesn't enforce all RRs in an RRset
+ * having the same TTL, as per RFC 2136,
+ * section 7.12. If a DLZ backend has
+ * different TTLs, then the best
+ * we can do is return the lowest.
+ */
+ rdatalist->ttl = ttl;
+ }
rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
if (rdata == NULL)
@@ -1615,7 +1883,7 @@ dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
isc_buffer_init(&b, name, strlen(name));
isc_buffer_add(&b, strlen(name));
- result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
+ result = dns_name_fromtext(newname, &b, origin, 0, NULL);
if (result != ISC_R_SUCCESS)
return (result);
@@ -1694,9 +1962,7 @@ dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
DNS_SDLZFLAG_THREADSAFE)) == 0);
/* Write debugging message to log */
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
- "Registering SDLZ driver '%s'", drivername);
+ sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
/*
* Allocate memory for a sdlz_implementation object. Error if
@@ -1769,9 +2035,7 @@ dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
isc_mem_t *mctx;
/* Write debugging message to log */
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
- DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
- "Unregistering SDLZ driver.");
+ sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
/*
* Performs checks to make sure data is as we expect it to be.
@@ -1797,3 +2061,16 @@ dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
*sdlzimp = NULL;
}
+
+
+isc_result_t
+dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
+ dns_name_t *name, dns_db_t **dbp)
+{
+ isc_result_t result;
+
+ result = dns_sdlzcreateDBP(dlzdatabase->mctx,
+ dlzdatabase->implementation->driverarg,
+ dlzdatabase->dbdata, name, rdclass, dbp);
+ return (result);
+}
diff --git a/contrib/bind9/lib/dns/soa.c b/contrib/bind9/lib/dns/soa.c
index f338586..bd0d185 100644
--- a/contrib/bind9/lib/dns/soa.c
+++ b/contrib/bind9/lib/dns/soa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,15 +15,18 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: soa.c,v 1.8 2007-06-19 23:47:16 tbox Exp $ */
+/* $Id: soa.c,v 1.12 2009-09-10 02:18:40 each Exp $ */
/*! \file */
#include <config.h>
+#include <string.h>
+#include <isc/buffer.h>
#include <isc/util.h>
#include <dns/rdata.h>
+#include <dns/rdatastruct.h>
#include <dns/soa.h>
static inline isc_uint32_t
@@ -60,6 +63,39 @@ soa_get(dns_rdata_t *rdata, int offset) {
return (decode_uint32(rdata->data + rdata->length - 20 + offset));
}
+isc_result_t
+dns_soa_buildrdata(dns_name_t *origin, dns_name_t *contact,
+ dns_rdataclass_t rdclass,
+ isc_uint32_t serial, isc_uint32_t refresh,
+ isc_uint32_t retry, isc_uint32_t expire,
+ isc_uint32_t minimum, unsigned char *buffer,
+ dns_rdata_t *rdata) {
+ dns_rdata_soa_t soa;
+ isc_buffer_t rdatabuf;
+
+ REQUIRE(origin != NULL);
+ REQUIRE(contact != NULL);
+
+ memset(buffer, 0, DNS_SOA_BUFFERSIZE);
+ isc_buffer_init(&rdatabuf, buffer, DNS_SOA_BUFFERSIZE);
+
+ soa.common.rdtype = dns_rdatatype_soa;
+ soa.common.rdclass = rdclass;
+ soa.mctx = NULL;
+ soa.serial = serial;
+ soa.refresh = refresh;
+ soa.retry = retry;
+ soa.expire = expire;
+ soa.minimum = minimum;
+ dns_name_init(&soa.origin, NULL);
+ dns_name_clone(origin, &soa.origin);
+ dns_name_init(&soa.contact, NULL);
+ dns_name_clone(contact, &soa.contact);
+
+ return (dns_rdata_fromstruct(rdata, rdclass, dns_rdatatype_soa,
+ &soa, &rdatabuf));
+}
+
isc_uint32_t
dns_soa_getserial(dns_rdata_t *rdata) {
return soa_get(rdata, 0);
diff --git a/contrib/bind9/lib/dns/spnego.c b/contrib/bind9/lib/dns/spnego.c
index ad15331..5ad492c 100644
--- a/contrib/bind9/lib/dns/spnego.c
+++ b/contrib/bind9/lib/dns/spnego.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2006-2011 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: spnego.c,v 1.8.118.4 2009-07-21 07:27:13 marka Exp $ */
+/* $Id: spnego.c,v 1.16 2011-01-11 23:47:13 tbox Exp $ */
/*! \file
* \brief
@@ -172,6 +172,8 @@
/* asn1_err.h */
/* Generated from ../../../lib/asn1/asn1_err.et */
+#ifndef ERROR_TABLE_BASE_asn1
+/* these may be brought in already via gssapi_krb5.h */
typedef enum asn1_error_number {
ASN1_BAD_TIMEFORMAT = 1859794432,
ASN1_MISSING_FIELD = 1859794433,
@@ -186,6 +188,7 @@ typedef enum asn1_error_number {
} asn1_error_number;
#define ERROR_TABLE_BASE_asn1 1859794432
+#endif
#define __asn1_common_definitions__
@@ -409,7 +412,7 @@ code_NegTokenArg(OM_uint32 * minor_status,
{
OM_uint32 ret;
u_char *buf;
- size_t buf_size, buf_len;
+ size_t buf_size, buf_len = 0;
buf_size = 1024;
buf = malloc(buf_size);
diff --git a/contrib/bind9/lib/dns/ssu.c b/contrib/bind9/lib/dns/ssu.c
index 128071c..eb13551 100644
--- a/contrib/bind9/lib/dns/ssu.c
+++ b/contrib/bind9/lib/dns/ssu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2010, 2011 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
@@ -17,7 +17,7 @@
/*! \file */
/*
- * $Id: ssu.c,v 1.34 2008-01-18 23:46:58 tbox Exp $
+ * $Id: ssu.c,v 1.38 2011-01-06 23:47:00 tbox Exp $
* Principal Author: Brian Wellington
*/
@@ -30,11 +30,13 @@
#include <isc/string.h>
#include <isc/util.h>
+#include <dns/dlz.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/ssu.h>
#include <dst/gssapi.h>
+#include <dst/dst.h>
#define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
#define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
@@ -59,6 +61,7 @@ struct dns_ssutable {
isc_mem_t *mctx;
unsigned int references;
isc_mutex_t lock;
+ dns_dlzdb_t *dlzdatabase;
ISC_LIST(dns_ssurule_t) rules;
};
@@ -345,7 +348,8 @@ stf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) {
isc_boolean_t
dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
dns_name_t *name, isc_netaddr_t *tcpaddr,
- dns_rdatatype_t type)
+ dns_rdatatype_t type,
+ const dst_key_t *key)
{
dns_ssurule_t *rule;
unsigned int i;
@@ -483,10 +487,27 @@ dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
if (!dns_name_equal(stfself, name))
continue;
break;
+ case DNS_SSUMATCHTYPE_EXTERNAL:
+ if (!dns_ssu_external_match(rule->identity, signer,
+ name, tcpaddr, type, key,
+ table->mctx))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_DLZ:
+ if (!dns_dlz_ssumatch(table->dlzdatabase, signer,
+ name, tcpaddr, type, key))
+ continue;
+ break;
}
if (rule->ntypes == 0) {
- if (!isusertype(type))
+ /*
+ * If this is a DLZ rule, then the DLZ ssu
+ * checks will have already checked
+ * the type.
+ */
+ if (rule->matchtype != DNS_SSUMATCHTYPE_DLZ &&
+ !isusertype(type))
continue;
} else {
for (i = 0; i < rule->ntypes; i++) {
@@ -550,3 +571,42 @@ dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) {
*nextrule = ISC_LIST_NEXT(rule, link);
return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
}
+
+/*
+ * Create a specialised SSU table that points at an external DLZ database
+ */
+isc_result_t
+dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep,
+ dns_dlzdb_t *dlzdatabase)
+{
+ isc_result_t result;
+ dns_ssurule_t *rule;
+ dns_ssutable_t *table = NULL;
+
+ REQUIRE(tablep != NULL && *tablep == NULL);
+
+ result = dns_ssutable_create(mctx, &table);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ table->dlzdatabase = dlzdatabase;
+
+ rule = isc_mem_get(table->mctx, sizeof(dns_ssurule_t));
+ if (rule == NULL) {
+ dns_ssutable_detach(&table);
+ return (ISC_R_NOMEMORY);
+ }
+
+ rule->identity = NULL;
+ rule->name = NULL;
+ rule->types = NULL;
+ rule->grant = ISC_TRUE;
+ rule->matchtype = DNS_SSUMATCHTYPE_DLZ;
+ rule->ntypes = 0;
+ rule->types = NULL;
+ rule->magic = SSURULEMAGIC;
+
+ ISC_LIST_INITANDAPPEND(table->rules, rule, link);
+ *tablep = table;
+ return (ISC_R_SUCCESS);
+}
diff --git a/contrib/bind9/lib/dns/ssu_external.c b/contrib/bind9/lib/dns/ssu_external.c
new file mode 100644
index 0000000..ac72a1f
--- /dev/null
+++ b/contrib/bind9/lib/dns/ssu_external.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011 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: ssu_external.c,v 1.7 2011-01-13 07:05:57 marka Exp $ */
+
+/*
+ * This implements external update-policy rules. This allows permission
+ * to update a zone to be checked by consulting an external daemon (e.g.,
+ * kerberos).
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/strerror.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/ssu.h>
+#include <dns/log.h>
+#include <dns/rdatatype.h>
+
+#include <dst/dst.h>
+
+
+static void
+ssu_e_log(int level, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_SECURITY,
+ DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(level), fmt, ap);
+ va_end(ap);
+}
+
+
+/*
+ * Connect to a UNIX domain socket.
+ */
+static int
+ux_socket_connect(const char *path) {
+ int fd = -1;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ struct sockaddr_un addr;
+
+ REQUIRE(path != NULL);
+
+ if (strlen(path) > sizeof(addr.sun_path)) {
+ ssu_e_log(3, "ssu_external: socket path '%s' "
+ "longer than system maximum %u",
+ path, sizeof(addr.sun_path));
+ return (-1);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ssu_e_log(3, "ssu_external: unable to create socket - %s",
+ strbuf);
+ return (-1);
+ }
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ssu_e_log(3, "ssu_external: unable to connect to "
+ "socket '%s' - %s",
+ path, strbuf);
+ close(fd);
+ return (-1);
+ }
+#endif
+ return (fd);
+}
+
+/* Change this version if you update the format of the request */
+#define SSU_EXTERNAL_VERSION 1
+
+/*
+ * Perform an update-policy rule check against an external application
+ * over a socket.
+ *
+ * This currently only supports local: for unix domain datagram sockets.
+ *
+ * Note that by using a datagram socket and creating a new socket each
+ * time we avoid the need for locking and allow for parallel access to
+ * the authorization server.
+ */
+isc_boolean_t
+dns_ssu_external_match(dns_name_t *identity,
+ dns_name_t *signer, dns_name_t *name,
+ isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
+ const dst_key_t *key, isc_mem_t *mctx)
+{
+ char b_identity[DNS_NAME_FORMATSIZE];
+ char b_signer[DNS_NAME_FORMATSIZE];
+ char b_name[DNS_NAME_FORMATSIZE];
+ char b_addr[ISC_NETADDR_FORMATSIZE];
+ char b_type[DNS_RDATATYPE_FORMATSIZE];
+ char b_key[DST_KEY_FORMATSIZE];
+ isc_buffer_t *tkey_token;
+ int fd;
+ const char *sock_path;
+ size_t req_len;
+ isc_region_t token_region;
+ unsigned char *data;
+ isc_buffer_t buf;
+ isc_uint32_t token_len = 0;
+ isc_uint32_t reply;
+ ssize_t ret;
+
+ /* The identity contains local:/path/to/socket */
+ dns_name_format(identity, b_identity, sizeof(b_identity));
+
+ /* For now only local: is supported */
+ if (strncmp(b_identity, "local:", 6) != 0) {
+ ssu_e_log(3, "ssu_external: invalid socket path '%s'",
+ b_identity);
+ return (ISC_FALSE);
+ }
+ sock_path = &b_identity[6];
+
+ fd = ux_socket_connect(sock_path);
+ if (fd == -1)
+ return (ISC_FALSE);
+
+ tkey_token = dst_key_tkeytoken(key);
+
+ /* Format the request elements */
+ if (signer)
+ dns_name_format(signer, b_signer, sizeof(b_signer));
+ else
+ b_signer[0] = 0;
+
+ dns_name_format(name, b_name, sizeof(b_name));
+
+ if (tcpaddr)
+ isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
+ else
+ b_addr[0] = 0;
+
+ dns_rdatatype_format(type, b_type, sizeof(b_type));
+
+ if (key)
+ dst_key_format(key, b_key, sizeof(b_key));
+ else
+ b_key[0] = 0;
+
+ if (tkey_token) {
+ isc_buffer_region(tkey_token, &token_region);
+ token_len = token_region.length;
+ }
+
+ /* Work out how big the request will be */
+ req_len = sizeof(isc_uint32_t) + /* Format version */
+ sizeof(isc_uint32_t) + /* Length */
+ strlen(b_signer) + 1 + /* Signer */
+ strlen(b_name) + 1 + /* Name */
+ strlen(b_addr) + 1 + /* Address */
+ strlen(b_type) + 1 + /* Type */
+ strlen(b_key) + 1 + /* Key */
+ sizeof(isc_uint32_t) + /* tkey_token length */
+ token_len; /* tkey_token */
+
+
+ /* format the buffer */
+ data = isc_mem_allocate(mctx, req_len);
+ if (data == NULL) {
+ close(fd);
+ return (ISC_FALSE);
+ }
+
+ isc_buffer_init(&buf, data, req_len);
+ isc_buffer_putuint32(&buf, SSU_EXTERNAL_VERSION);
+ isc_buffer_putuint32(&buf, req_len);
+
+ /* Strings must be null-terminated */
+ isc_buffer_putstr(&buf, b_signer);
+ isc_buffer_putuint8(&buf, 0);
+ isc_buffer_putstr(&buf, b_name);
+ isc_buffer_putuint8(&buf, 0);
+ isc_buffer_putstr(&buf, b_addr);
+ isc_buffer_putuint8(&buf, 0);
+ isc_buffer_putstr(&buf, b_type);
+ isc_buffer_putuint8(&buf, 0);
+ isc_buffer_putstr(&buf, b_key);
+ isc_buffer_putuint8(&buf, 0);
+
+ isc_buffer_putuint32(&buf, token_len);
+ if (tkey_token && token_len != 0)
+ isc_buffer_putmem(&buf, token_region.base, token_len);
+
+ ENSURE(isc_buffer_availablelength(&buf) == 0);
+
+ /* Send the request */
+ ret = write(fd, data, req_len);
+ isc_mem_free(mctx, data);
+ if (ret != (ssize_t) req_len) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ssu_e_log(3, "ssu_external: unable to send request - %s",
+ strbuf);
+ close(fd);
+ return (ISC_FALSE);
+ }
+
+ /* Receive the reply */
+ ret = read(fd, &reply, sizeof(isc_uint32_t));
+ if (ret != (ssize_t) sizeof(isc_uint32_t)) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ssu_e_log(3, "ssu_external: unable to receive reply - %s",
+ strbuf);
+ close(fd);
+ return (ISC_FALSE);
+ }
+
+ close(fd);
+
+ reply = ntohl(reply);
+
+ if (reply == 0) {
+ ssu_e_log(3, "ssu_external: denied external auth for '%s'",
+ b_name);
+ return (ISC_FALSE);
+ } else if (reply == 1) {
+ ssu_e_log(3, "ssu_external: allowed external auth for '%s'",
+ b_name);
+ return (ISC_TRUE);
+ }
+
+ ssu_e_log(3, "ssu_external: invalid reply 0x%08x", reply);
+
+ return (ISC_FALSE);
+}
diff --git a/contrib/bind9/lib/dns/stats.c b/contrib/bind9/lib/dns/stats.c
index b73a3b3..cb46bf5 100644
--- a/contrib/bind9/lib/dns/stats.c
+++ b/contrib/bind9/lib/dns/stats.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: stats.c,v 1.16.118.2 2009-01-29 23:47:44 tbox Exp $ */
+/* $Id: stats.c,v 1.18 2009-01-27 23:47:54 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/dns/time.c b/contrib/bind9/lib/dns/time.c
index bd8cdc3..3f55f19 100644
--- a/contrib/bind9/lib/dns/time.c
+++ b/contrib/bind9/lib/dns/time.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: time.c,v 1.31.332.4 2010-04-21 23:48:05 tbox Exp $ */
+/* $Id: time.c,v 1.35 2010-04-21 23:51:22 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/dns/tkey.c b/contrib/bind9/lib/dns/tkey.c
index 7107dd5..a861ee3 100644
--- a/contrib/bind9/lib/dns/tkey.c
+++ b/contrib/bind9/lib/dns/tkey.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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.90.118.4 2010-12-09 01:12:55 marka Exp $
+ * $Id: tkey.c,v 1.100 2011-01-08 23:47:01 tbox Exp $
*/
/*! \file */
#include <config.h>
@@ -99,6 +99,7 @@ dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
tctx->dhkey = NULL;
tctx->domain = NULL;
tctx->gsscred = NULL;
+ tctx->gssapi_keytab = NULL;
*tctxp = tctx;
return (ISC_R_SUCCESS);
@@ -121,6 +122,9 @@ 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->gssapi_keytab != NULL) {
+ isc_mem_free(mctx, tctx->gssapi_keytab);
+ }
if (tctx->gsscred != NULL)
dst_gssapi_releasecred(&tctx->gsscred);
isc_entropy_detach(&tctx->ectx);
@@ -430,8 +434,17 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
isc_buffer_t *outtoken = NULL;
gss_ctx_id_t gss_ctx = NULL;
- if (tctx->gsscred == NULL)
+ /*
+ * You have to define either a gss credential (principal) to
+ * accept with tkey-gssapi-credential, or you have to
+ * configure a specific keytab (with tkey-gssapi-keytab) in
+ * order to use gsstkey
+ */
+ if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) {
+ tkey_log("process_gsstkey(): no tkey-gssapi-credential "
+ "or tkey-gssapi-keytab configured");
return (ISC_R_NOPERM);
+ }
if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
@@ -454,7 +467,11 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
dns_fixedname_init(&principal);
- result = dst_gssapi_acceptctx(tctx->gsscred, &intoken,
+ /*
+ * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set
+ */
+ result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
+ &intoken,
&outtoken, &gss_ctx,
dns_fixedname_name(&principal),
tctx->mctx);
@@ -479,7 +496,8 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
#endif
isc_uint32_t expire;
- RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx, &dstkey));
+ RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx,
+ &dstkey, &intoken));
/*
* Limit keys to 1 hour or the context's lifetime whichever
* is smaller.
@@ -734,8 +752,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
}
isc_buffer_init(&b, randomtext, sizeof(randomtext));
isc_buffer_add(&b, sizeof(randomtext));
- result = dns_name_fromtext(keyname, &b, NULL,
- ISC_FALSE, NULL);
+ result = dns_name_fromtext(keyname, &b, NULL, 0, NULL);
if (result != ISC_R_SUCCESS)
goto failure;
}
@@ -985,7 +1002,8 @@ 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,
isc_buffer_t *intoken, isc_uint32_t lifetime,
- gss_ctx_id_t *context, isc_boolean_t win2k)
+ gss_ctx_id_t *context, isc_boolean_t win2k,
+ isc_mem_t *mctx, char **err_message)
{
dns_rdata_tkey_t tkey;
isc_result_t result;
@@ -999,9 +1017,11 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
REQUIRE(name != NULL);
REQUIRE(gname != NULL);
REQUIRE(context != NULL);
+ REQUIRE(mctx != NULL);
isc_buffer_init(&token, array, sizeof(array));
- result = dst_gssapi_initctx(gname, NULL, &token, context);
+ result = dst_gssapi_initctx(gname, NULL, &token, context,
+ mctx, err_message);
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
return (result);
@@ -1218,7 +1238,7 @@ isc_result_t
dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
dns_name_t *gname, gss_ctx_id_t *context,
isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
- dns_tsig_keyring_t *ring)
+ dns_tsig_keyring_t *ring, char **err_message)
{
dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
dns_name_t *tkeyname;
@@ -1232,6 +1252,7 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
REQUIRE(qmsg != NULL);
REQUIRE(rmsg != NULL);
REQUIRE(gname != NULL);
+ REQUIRE(ring != NULL);
if (outkey != NULL)
REQUIRE(*outkey == NULL);
@@ -1268,10 +1289,11 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
isc_buffer_init(outtoken, array, sizeof(array));
isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
- RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context));
+ RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context,
+ ring->mctx, err_message));
RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
- &dstkey));
+ &dstkey, NULL));
RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME,
dstkey, ISC_FALSE, NULL,
@@ -1349,7 +1371,7 @@ 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)
+ isc_boolean_t win2k, char **err_message)
{
dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
dns_name_t *tkeyname;
@@ -1393,12 +1415,13 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
isc_buffer_init(&outtoken, array, sizeof(array));
- result = dst_gssapi_initctx(server, &intoken, &outtoken, context);
+ result = dst_gssapi_initctx(server, &intoken, &outtoken, context,
+ ring->mctx, err_message);
if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
return (result);
RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
- &dstkey));
+ &dstkey, NULL));
/*
* XXXSRA This seems confused. If we got CONTINUE from initctx,
diff --git a/contrib/bind9/lib/dns/tsec.c b/contrib/bind9/lib/dns/tsec.c
new file mode 100644
index 0000000..b7ed777
--- /dev/null
+++ b/contrib/bind9/lib/dns/tsec.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009, 2010 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: tsec.c,v 1.7 2010-12-09 00:54:34 marka Exp $ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+
+#include <dns/tsec.h>
+#include <dns/tsig.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+
+#define DNS_TSEC_MAGIC ISC_MAGIC('T', 's', 'e', 'c')
+#define DNS_TSEC_VALID(t) ISC_MAGIC_VALID(t, DNS_TSEC_MAGIC)
+
+/*%
+ * DNS Transaction Security object. We assume this is not shared by
+ * multiple threads, and so the structure does not contain a lock.
+ */
+struct dns_tsec {
+ unsigned int magic;
+ dns_tsectype_t type;
+ isc_mem_t *mctx;
+ union {
+ dns_tsigkey_t *tsigkey;
+ dst_key_t *key;
+ } ukey;
+};
+
+isc_result_t
+dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key,
+ dns_tsec_t **tsecp)
+{
+ isc_result_t result;
+ dns_tsec_t *tsec;
+ dns_tsigkey_t *tsigkey = NULL;
+ dns_name_t *algname;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(tsecp != NULL && *tsecp == NULL);
+
+ tsec = isc_mem_get(mctx, sizeof(*tsec));
+ if (tsec == NULL)
+ return (ISC_R_NOMEMORY);
+
+ tsec->type = type;
+ tsec->mctx = mctx;
+
+ switch (type) {
+ case dns_tsectype_tsig:
+ switch (dst_key_alg(key)) {
+ case DST_ALG_HMACMD5:
+ algname = dns_tsig_hmacmd5_name;
+ break;
+ case DST_ALG_HMACSHA1:
+ algname = dns_tsig_hmacsha1_name;
+ break;
+ case DST_ALG_HMACSHA224:
+ algname = dns_tsig_hmacsha224_name;
+ break;
+ case DST_ALG_HMACSHA256:
+ algname = dns_tsig_hmacsha256_name;
+ break;
+ case DST_ALG_HMACSHA384:
+ algname = dns_tsig_hmacsha384_name;
+ break;
+ case DST_ALG_HMACSHA512:
+ algname = dns_tsig_hmacsha512_name;
+ break;
+ default:
+ isc_mem_put(mctx, tsec, sizeof(*tsec));
+ return (DNS_R_BADALG);
+ }
+ result = dns_tsigkey_createfromkey(dst_key_name(key),
+ algname, key, ISC_FALSE,
+ NULL, 0, 0, mctx, NULL,
+ &tsigkey);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, tsec, sizeof(*tsec));
+ return (result);
+ }
+ tsec->ukey.tsigkey = tsigkey;
+ break;
+ case dns_tsectype_sig0:
+ tsec->ukey.key = key;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ tsec->magic = DNS_TSEC_MAGIC;
+
+ *tsecp = tsec;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_tsec_destroy(dns_tsec_t **tsecp) {
+ dns_tsec_t *tsec;
+
+ REQUIRE(tsecp != NULL && *tsecp != NULL);
+ tsec = *tsecp;
+ REQUIRE(DNS_TSEC_VALID(tsec));
+
+ switch (tsec->type) {
+ case dns_tsectype_tsig:
+ dns_tsigkey_detach(&tsec->ukey.tsigkey);
+ break;
+ case dns_tsectype_sig0:
+ dst_key_free(&tsec->ukey.key);
+ break;
+ default:
+ INSIST(0);
+ }
+
+ tsec->magic = 0;
+ isc_mem_put(tsec->mctx, tsec, sizeof(*tsec));
+
+ *tsecp = NULL;
+}
+
+dns_tsectype_t
+dns_tsec_gettype(dns_tsec_t *tsec) {
+ REQUIRE(DNS_TSEC_VALID(tsec));
+
+ return (tsec->type);
+}
+
+void
+dns_tsec_getkey(dns_tsec_t *tsec, void *keyp) {
+ REQUIRE(DNS_TSEC_VALID(tsec));
+ REQUIRE(keyp != NULL);
+
+ switch (tsec->type) {
+ case dns_tsectype_tsig:
+ dns_tsigkey_attach(tsec->ukey.tsigkey, (dns_tsigkey_t **)keyp);
+ break;
+ case dns_tsectype_sig0:
+ *(dst_key_t **)keyp = tsec->ukey.key;
+ break;
+ default:
+ INSIST(0);
+ }
+}
diff --git a/contrib/bind9/lib/dns/tsig.c b/contrib/bind9/lib/dns/tsig.c
index 65d32dc..cec5222 100644
--- a/contrib/bind9/lib/dns/tsig.c
+++ b/contrib/bind9/lib/dns/tsig.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +16,7 @@
*/
/*
- * $Id: tsig.c,v 1.136.18.5 2010-12-09 01:12:55 marka Exp $
+ * $Id: tsig.c,v 1.147 2011-01-11 23:47:13 tbox Exp $
*/
/*! \file */
#include <config.h>
@@ -91,31 +91,6 @@ static dns_name_t gsstsig = {
};
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
-static void
-remove_fromring(dns_tsigkey_t *tkey) {
- if (tkey->generated) {
- ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
- tkey->ring->generated--;
- }
- (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
-}
-
-static void
-adjust_lru(dns_tsigkey_t *tkey) {
- if (tkey->generated) {
- RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
- /*
- * We may have been removed from the LRU list between
- * removing the read lock and aquiring the write lock.
- */
- if (ISC_LINK_LINKED(tkey, link)) {
- ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
- ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
- }
- RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
- }
-}
-
/*
* Since Microsoft doesn't follow its own standard, we will use this
* alternate name as a second guess.
@@ -228,8 +203,10 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
else
strcpy(namestr, "<null>");
- if (key != NULL && key->generated)
+ if (key != NULL && key->generated && key->creator)
dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
+ else
+ strcpy(creatorstr, "<null>");
va_start(ap, fmt);
vsnprintf(message, sizeof(message), fmt, ap);
@@ -245,6 +222,71 @@ tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
level, "tsig key '%s': %s", namestr, message);
}
+static void
+remove_fromring(dns_tsigkey_t *tkey) {
+ if (tkey->generated) {
+ ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
+ tkey->ring->generated--;
+ }
+ (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
+}
+
+static void
+adjust_lru(dns_tsigkey_t *tkey) {
+ if (tkey->generated) {
+ RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
+ /*
+ * We may have been removed from the LRU list between
+ * removing the read lock and aquiring the write lock.
+ */
+ if (ISC_LINK_LINKED(tkey, link)) {
+ ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
+ ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
+ }
+ RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
+ }
+}
+
+/*
+ * A supplemental routine just to add a key to ring. Note that reference
+ * counter should be counted separately because we may be adding the key
+ * as part of creation of the key, in which case the reference counter was
+ * already initialized. Also note we don't need RWLOCK for the reference
+ * counter: it's protected by a separate lock.
+ */
+static isc_result_t
+keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
+ dns_tsigkey_t *tkey)
+{
+ isc_result_t result;
+
+ 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;
+ }
+
+ result = dns_rbt_addname(ring->keys, name, tkey);
+ if (tkey->generated) {
+ /*
+ * Add the new key to the LRU list and remove the least
+ * recently used key if there are too many keys on the list.
+ */
+ ISC_LIST_INITANDAPPEND(ring->lru, tkey, link);
+ if (ring->generated++ > ring->maxgenerated)
+ remove_fromring(ISC_LIST_HEAD(ring->lru));
+ }
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+
+ return (result);
+}
+
isc_result_t
dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
dst_key_t *dstkey, isc_boolean_t generated,
@@ -363,7 +405,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
tkey->ring = ring;
if (key != NULL)
- refs++;
+ refs = 1;
if (ring != NULL)
refs++;
ret = isc_refcount_init(&tkey->refs, refs);
@@ -379,36 +421,9 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
tkey->magic = TSIG_MAGIC;
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);
+ ret = keyring_add(ring, name, tkey);
+ if (ret != ISC_R_SUCCESS)
goto cleanup_refs;
- }
-
- if (tkey->generated) {
- /*
- * Add the new key to the LRU list and remove the
- * least recently used key if there are too many
- * keys on the list.
- */
- ISC_LIST_INITANDAPPEND(ring->lru, tkey, link);
- if (ring->generated++ > ring->maxgenerated)
- remove_fromring(ISC_LIST_HEAD(ring->lru));
- }
-
- RWUNLOCK(&ring->lock, isc_rwlocktype_write);
}
/*
@@ -424,6 +439,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
"the key '%s' is too short to be secure",
namestr);
}
+
if (key != NULL)
*key = tkey;
@@ -512,6 +528,184 @@ cleanup_ring(dns_tsig_keyring_t *ring)
}
}
+static void
+destroyring(dns_tsig_keyring_t *ring) {
+ dns_rbt_destroy(&ring->keys);
+ isc_rwlock_destroy(&ring->lock);
+ isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
+}
+
+static unsigned int
+dst_alg_fromname(dns_name_t *algorithm) {
+ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
+ return (DST_ALG_HMACMD5);
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
+ return (DST_ALG_HMACSHA1);
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
+ return (DST_ALG_HMACSHA224);
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
+ return (DST_ALG_HMACSHA256);
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
+ return (DST_ALG_HMACSHA384);
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
+ return (DST_ALG_HMACSHA512);
+ } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
+ return (DST_ALG_GSSAPI);
+ } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
+ return (DST_ALG_GSSAPI);
+ } else
+ return (0);
+}
+
+static isc_result_t
+restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) {
+ dst_key_t *dstkey = NULL;
+ char namestr[1024];
+ char creatorstr[1024];
+ char algorithmstr[1024];
+ char keystr[4096];
+ unsigned int inception, expire;
+ int n;
+ isc_buffer_t b;
+ dns_name_t *name, *creator, *algorithm;
+ dns_fixedname_t fname, fcreator, falgorithm;
+ isc_result_t result;
+ unsigned int dstalg;
+
+ n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
+ creatorstr, &inception, &expire, algorithmstr, keystr);
+ if (n == EOF)
+ return (ISC_R_NOMORE);
+ if (n != 6)
+ return (ISC_R_FAILURE);
+
+ if (isc_serial_lt(expire, now))
+ return (DNS_R_EXPIRED);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_init(&b, namestr, strlen(namestr));
+ isc_buffer_add(&b, strlen(namestr));
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_fixedname_init(&fcreator);
+ creator = dns_fixedname_name(&fcreator);
+ isc_buffer_init(&b, creatorstr, strlen(creatorstr));
+ isc_buffer_add(&b, strlen(creatorstr));
+ result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_fixedname_init(&falgorithm);
+ algorithm = dns_fixedname_name(&falgorithm);
+ isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
+ isc_buffer_add(&b, strlen(algorithmstr));
+ result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dstalg = dst_alg_fromname(algorithm);
+ if (dstalg == 0)
+ return (DNS_R_BADALG);
+
+ result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
+ ring->mctx, keystr, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
+ ISC_TRUE, creator, inception,
+ expire, ring->mctx, ring, NULL);
+ if (result != ISC_R_SUCCESS && dstkey != NULL)
+ dst_key_free(&dstkey);
+ return (result);
+}
+
+static void
+dump_key(dns_tsigkey_t *tkey, FILE *fp)
+{
+ char *buffer = NULL;
+ int length = 0;
+ char namestr[DNS_NAME_FORMATSIZE];
+ char creatorstr[DNS_NAME_FORMATSIZE];
+ char algorithmstr[DNS_NAME_FORMATSIZE];
+ isc_result_t result;
+
+ dns_name_format(&tkey->name, namestr, sizeof(namestr));
+ dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr));
+ dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr));
+ result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length);
+ if (result == ISC_R_SUCCESS)
+ fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
+ tkey->inception, tkey->expire, algorithmstr,
+ length, buffer);
+ if (buffer != NULL)
+ isc_mem_put(tkey->mctx, buffer, length);
+}
+
+isc_result_t
+dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
+ 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;
+ dns_tsig_keyring_t *ring;
+ unsigned int references;
+
+ REQUIRE(ringp != NULL && *ringp != NULL);
+
+ ring = *ringp;
+ *ringp = NULL;
+
+ RWLOCK(&ring->lock, isc_rwlocktype_write);
+ INSIST(ring->references > 0);
+ ring->references--;
+ references = ring->references;
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+
+ if (references != 0)
+ return (DNS_R_CONTINUE);
+
+ isc_stdtime_get(&now);
+ dns_name_init(&foundname, NULL);
+ dns_fixedname_init(&fixedorigin);
+ origin = dns_fixedname_name(&fixedorigin);
+ 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);
+ goto destroy;
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+ if (tkey != NULL && tkey->generated && tkey->expire >= now)
+ dump_key(tkey, fp);
+ result = dns_rbtnodechain_next(&chain, &foundname,
+ origin);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ goto destroy;
+ }
+ }
+
+ destroy:
+ destroyring(ring);
+ return (result);
+}
+
isc_result_t
dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
unsigned char *secret, int length, isc_boolean_t generated,
@@ -1589,14 +1783,43 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
ISC_LIST_INIT(ring->lru);
isc_mem_attach(mctx, &ring->mctx);
+ ring->references = 1;
*ringp = ring;
return (ISC_R_SUCCESS);
}
+isc_result_t
+dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
+ dns_tsigkey_t *tkey)
+{
+ isc_result_t result;
+
+ result = keyring_add(ring, name, tkey);
+ if (result == ISC_R_SUCCESS)
+ isc_refcount_increment(&tkey->refs, NULL);
+
+ return (result);
+}
+
void
-dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) {
+dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
+{
+ REQUIRE(source != NULL);
+ REQUIRE(target != NULL && *target == NULL);
+
+ RWLOCK(&source->lock, isc_rwlocktype_write);
+ INSIST(source->references > 0);
+ source->references++;
+ INSIST(source->references > 0);
+ *target = source;
+ RWUNLOCK(&source->lock, isc_rwlocktype_write);
+}
+
+void
+dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
dns_tsig_keyring_t *ring;
+ unsigned int references;
REQUIRE(ringp != NULL);
REQUIRE(*ringp != NULL);
@@ -1604,7 +1827,27 @@ dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) {
ring = *ringp;
*ringp = NULL;
- dns_rbt_destroy(&ring->keys);
- isc_rwlock_destroy(&ring->lock);
- isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
+ RWLOCK(&ring->lock, isc_rwlocktype_write);
+ INSIST(ring->references > 0);
+ ring->references--;
+ references = ring->references;
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+
+ if (references == 0)
+ destroyring(ring);
+}
+
+void
+dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
+ isc_stdtime_t now;
+ isc_result_t result;
+
+ isc_stdtime_get(&now);
+ do {
+ result = restore_key(ring, now, fp);
+ if (result == ISC_R_NOMORE)
+ return;
+ if (result == DNS_R_BADALG || result == DNS_R_EXPIRED)
+ result = ISC_R_SUCCESS;
+ } while (result == ISC_R_SUCCESS);
}
diff --git a/contrib/bind9/lib/dns/validator.c b/contrib/bind9/lib/dns/validator.c
index 79c8798..6c0d38d 100644
--- a/contrib/bind9/lib/dns/validator.c
+++ b/contrib/bind9/lib/dns/validator.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.164.12.23.4.3 2011-06-21 20:13:23 each Exp $ */
+/* $Id: validator.c,v 1.197.40.3 2011-06-21 20:15:54 each Exp $ */
#include <config.h>
@@ -28,17 +28,17 @@
#include <isc/util.h>
#include <dns/db.h>
-#include <dns/ds.h>
#include <dns/dnssec.h>
+#include <dns/ds.h>
#include <dns/events.h>
#include <dns/keytable.h>
+#include <dns/keyvalues.h>
#include <dns/log.h>
#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>
#include <dns/rdatatype.h>
#include <dns/resolver.h>
@@ -255,9 +255,17 @@ dlv_algorithm_supported(dns_validator_t *val) {
dlv.algorithm))
continue;
+#ifdef HAVE_OPENSSL_GOST
+ if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
+ dlv.digest_type != DNS_DSDIGEST_SHA1 &&
+ dlv.digest_type != DNS_DSDIGEST_GOST)
+ continue;
+#else
if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
dlv.digest_type != DNS_DSDIGEST_SHA1)
continue;
+#endif
+
return (ISC_TRUE);
}
@@ -383,7 +391,7 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
}
/*%
- * We have been asked to to look for a key.
+ * We have been asked to look for a key.
* If found resume the validation process.
* If not found fail the validation process.
*/
@@ -582,7 +590,8 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
if (isdelegation(tname, &val->frdataset, eresult)) {
if (val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
- "must be secure failure");
+ "must be secure failure, no DS"
+ " and this is a delegation");
validator_done(val, DNS_R_MUSTBESECURE);
} else if (val->view->dlv == NULL || DLVTRIED(val)) {
markanswer(val, "dsfetched2");
@@ -1089,7 +1098,7 @@ nsec3noexistnodata(dns_validator_t *val, dns_name_t* name,
if (ns && !soa) {
if (!atparent) {
/*
- * This NSEC record is from somewhere
+ * This NSEC3 record is from somewhere
* higher in the DNS, and at the
* parent of a delegation. It can not
* be legitimately used here.
@@ -1100,7 +1109,7 @@ nsec3noexistnodata(dns_validator_t *val, dns_name_t* name,
}
} else if (atparent && ns && soa) {
/*
- * This NSEC record is from the child.
+ * This NSEC3 record is from the child.
* It can not be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3),
@@ -1505,8 +1514,11 @@ 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, NULL, NULL))
+ if (check_deadlock(val, name, type, NULL, NULL)) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "deadlock found (create_fetch)");
return (DNS_R_NOVALIDSIG);
+ }
validator_logcreate(val, name, type, caller, "fetch");
return (dns_resolver_createfetch(val->view->resolver, name, type,
@@ -1528,8 +1540,11 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
{
isc_result_t result;
- if (check_deadlock(val, name, type, rdataset, sigrdataset))
+ if (check_deadlock(val, name, type, rdataset, sigrdataset)) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "deadlock found (create_validator)");
return (DNS_R_NOVALIDSIG);
+ }
validator_logcreate(val, name, type, caller, "validator");
result = dns_validator_create(val->view, name, type,
@@ -1768,16 +1783,23 @@ compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
*/
static isc_boolean_t
isselfsigned(dns_validator_t *val) {
+ dns_fixedname_t fixed;
dns_rdataset_t *rdataset, *sigrdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdata_dnskey_t key;
dns_rdata_rrsig_t sig;
dns_keytag_t keytag;
+ dns_name_t *name;
isc_result_t result;
+ dst_key_t *dstkey;
+ isc_mem_t *mctx;
+ isc_boolean_t answer = ISC_FALSE;
rdataset = val->event->rdataset;
sigrdataset = val->event->sigrdataset;
+ name = val->event->name;
+ mctx = val->view->mctx;
INSIST(rdataset->type == dns_rdatatype_dnskey);
@@ -1799,12 +1821,31 @@ isselfsigned(dns_validator_t *val) {
result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- if (sig.algorithm == key.algorithm &&
- sig.keyid == keytag)
- return (ISC_TRUE);
+ if (sig.algorithm != key.algorithm ||
+ sig.keyid != keytag ||
+ !dns_name_equal(name, &sig.signer))
+ continue;
+
+ dstkey = NULL;
+ result = dns_dnssec_keyfromrdata(name, &rdata, mctx,
+ &dstkey);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ result = dns_dnssec_verify2(name, rdataset, dstkey,
+ ISC_TRUE, mctx, &sigrdata,
+ dns_fixedname_name(&fixed));
+ dst_key_free(&dstkey);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
+ answer = ISC_TRUE;
+ continue;
+ }
+ dns_view_untrust(val->view, name, &key, mctx);
}
}
- return (ISC_FALSE);
+ return (answer);
}
/*%
@@ -1946,6 +1987,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
break;
}
val->key = dns_keynode_key(val->keynode);
+ if (val->key == NULL)
+ break;
} else {
if (get_dst_key(val, val->siginfo, val->keyset)
!= ISC_R_SUCCESS)
@@ -1962,8 +2005,6 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
isc_stdtime_get(&now);
ttl = ISC_MIN(event->rdataset->ttl,
val->siginfo->timeexpire - now);
- if (val->keyset != NULL)
- ttl = ISC_MIN(ttl, val->keyset->ttl);
event->rdataset->ttl = ttl;
event->sigrdataset->ttl = ttl;
}
@@ -1992,7 +2033,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
} else if (result == ISC_R_SUCCESS) {
marksecure(event);
validator_log(val, ISC_LOG_DEBUG(3),
- "marking as secure");
+ "marking as secure, "
+ "noqname proof not needed");
return (result);
} else {
validator_log(val, ISC_LOG_DEBUG(3),
@@ -2013,25 +2055,102 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
}
/*%
+ * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
+ * (val->event->rdataset).
+ */
+static isc_result_t
+checkkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid,
+ dns_secalg_t algorithm)
+{
+ dns_rdata_rrsig_t sig;
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+
+ for (result = dns_rdataset_first(val->event->sigrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(val->event->sigrdataset))
+ {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(val->event->sigrdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (keyid != sig.keyid || algorithm != sig.algorithm)
+ continue;
+ if (dstkey == NULL) {
+ result = dns_dnssec_keyfromrdata(val->event->name,
+ keyrdata,
+ val->view->mctx,
+ &dstkey);
+ if (result != ISC_R_SUCCESS)
+ /*
+ * This really shouldn't happen, but...
+ */
+ continue;
+ }
+ result = verify(val, dstkey, &rdata, sig.keyid);
+ if (result == ISC_R_SUCCESS)
+ break;
+ }
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+ return (result);
+}
+
+/*%
+ * Find the DNSKEY that corresponds to the DS.
+ */
+static isc_result_t
+keyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata,
+ isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm,
+ dns_rdata_t *keyrdata)
+{
+ dns_keytag_t keytag;
+ dns_rdata_dnskey_t key;
+ isc_result_t result;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ dns_rdata_t newdsrdata = DNS_RDATA_INIT;
+
+ dns_rdata_reset(keyrdata);
+ dns_rdataset_current(rdataset, keyrdata);
+ result = dns_rdata_tostruct(keyrdata, &key, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ keytag = compute_keytag(keyrdata, &key);
+ if (keyid != keytag || algorithm != key.algorithm)
+ continue;
+ dns_rdata_reset(&newdsrdata);
+ result = dns_ds_buildrdata(val->event->name, keyrdata, digest,
+ dsbuf, &newdsrdata);
+ if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "dns_ds_buildrdata() -> %s",
+ dns_result_totext(result));
+ continue;
+ }
+ if (dns_rdata_compare(dsrdata, &newdsrdata) == 0)
+ break;
+ }
+ return (result);
+}
+
+/*%
* Validate the DNSKEY RRset by looking for a DNSKEY that matches a
* DLV record and that also verifies the DNSKEY RRset.
*/
static isc_result_t
dlv_validatezonekey(dns_validator_t *val) {
- dns_keytag_t keytag;
dns_rdata_dlv_t dlv;
- dns_rdata_dnskey_t key;
- dns_rdata_rrsig_t sig;
dns_rdata_t dlvrdata = DNS_RDATA_INIT;
dns_rdata_t keyrdata = DNS_RDATA_INIT;
- dns_rdata_t newdsrdata = DNS_RDATA_INIT;
- dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdataset_t trdataset;
- dst_key_t *dstkey;
isc_boolean_t supported_algorithm;
isc_result_t result;
- unsigned char dsbuf[DNS_DS_BUFFERSIZE];
- isc_uint8_t digest_type;
+ char digest_types[256];
validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
@@ -2048,7 +2167,7 @@ dlv_validatezonekey(dns_validator_t *val) {
* need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
* is present.
*/
- digest_type = DNS_DSDIGEST_SHA1;
+ memset(digest_types, 1, sizeof(digest_types));
for (result = dns_rdataset_first(&val->dlv);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&val->dlv)) {
@@ -2064,7 +2183,7 @@ dlv_validatezonekey(dns_validator_t *val) {
if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
dlv.length == ISC_SHA256_DIGESTLENGTH) {
- digest_type = DNS_DSDIGEST_SHA256;
+ digest_types[DNS_DSDIGEST_SHA1] = 0;
break;
}
}
@@ -2082,7 +2201,7 @@ dlv_validatezonekey(dns_validator_t *val) {
dlv.digest_type))
continue;
- if (dlv.digest_type != digest_type)
+ if (digest_types[dlv.digest_type] == 0)
continue;
if (!dns_resolver_algorithm_supported(val->view->resolver,
@@ -2095,70 +2214,27 @@ dlv_validatezonekey(dns_validator_t *val) {
dns_rdataset_init(&trdataset);
dns_rdataset_clone(val->event->rdataset, &trdataset);
- for (result = dns_rdataset_first(&trdataset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(&trdataset))
- {
- dns_rdata_reset(&keyrdata);
- dns_rdataset_current(&trdataset, &keyrdata);
- result = dns_rdata_tostruct(&keyrdata, &key, NULL);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- keytag = compute_keytag(&keyrdata, &key);
- if (dlv.key_tag != keytag ||
- dlv.algorithm != key.algorithm)
- continue;
- dns_rdata_reset(&newdsrdata);
- result = dns_ds_buildrdata(val->event->name,
- &keyrdata, dlv.digest_type,
- dsbuf, &newdsrdata);
- if (result != ISC_R_SUCCESS) {
- validator_log(val, ISC_LOG_DEBUG(3),
- "dns_ds_buildrdata() -> %s",
- dns_result_totext(result));
- continue;
- }
- /* Covert to DLV */
- newdsrdata.type = dns_rdatatype_dlv;
- if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0)
- break;
- }
+ /*
+ * Convert to DLV to DS and find matching DNSKEY.
+ */
+ dlvrdata.type = dns_rdatatype_ds;
+ result = keyfromds(val, &trdataset, &dlvrdata,
+ dlv.digest_type, dlv.key_tag,
+ dlv.algorithm, &keyrdata);
if (result != ISC_R_SUCCESS) {
dns_rdataset_disassociate(&trdataset);
validator_log(val, ISC_LOG_DEBUG(3),
"no DNSKEY matching DLV");
continue;
}
+
validator_log(val, ISC_LOG_DEBUG(3),
"Found matching DLV record: checking for signature");
+ /*
+ * Check that this DNSKEY signed the DNSKEY rrset.
+ */
+ result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm);
- for (result = dns_rdataset_first(val->event->sigrdataset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(val->event->sigrdataset))
- {
- dns_rdata_reset(&sigrdata);
- dns_rdataset_current(val->event->sigrdataset,
- &sigrdata);
- result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- if (dlv.key_tag != sig.keyid ||
- dlv.algorithm != sig.algorithm)
- continue;
- dstkey = NULL;
- result = dns_dnssec_keyfromrdata(val->event->name,
- &keyrdata,
- val->view->mctx,
- &dstkey);
- if (result != ISC_R_SUCCESS)
- /*
- * This really shouldn't happen, but...
- */
- continue;
-
- result = verify(val, dstkey, &sigrdata, sig.keyid);
- dst_key_free(&dstkey);
- if (result == ISC_R_SUCCESS)
- break;
- }
dns_rdataset_disassociate(&trdataset);
if (result == ISC_R_SUCCESS)
break;
@@ -2167,12 +2243,13 @@ dlv_validatezonekey(dns_validator_t *val) {
}
if (result == ISC_R_SUCCESS) {
marksecure(val->event);
- validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
+ validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)");
return (result);
} else if (result == ISC_R_NOMORE && !supported_algorithm) {
if (val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
- "must be secure failure");
+ "must be secure failure,"
+ "no supported algorithm/digest (dlv)");
return (DNS_R_MUSTBESECURE);
}
validator_log(val, ISC_LOG_DEBUG(3),
@@ -2184,7 +2261,8 @@ dlv_validatezonekey(dns_validator_t *val) {
}
/*%
- * Attempts positive response validation of an RRset containing zone keys.
+ * Attempts positive response validation of an RRset containing zone keys
+ * (i.e. a DNSKEY rrset).
*
* Returns:
* \li ISC_R_SUCCESS Validation completed successfully
@@ -2198,19 +2276,15 @@ validatezonekey(dns_validator_t *val) {
dns_validatorevent_t *event;
dns_rdataset_t trdataset;
dns_rdata_t dsrdata = DNS_RDATA_INIT;
- dns_rdata_t newdsrdata = DNS_RDATA_INIT;
dns_rdata_t keyrdata = DNS_RDATA_INIT;
dns_rdata_t sigrdata = DNS_RDATA_INIT;
- unsigned char dsbuf[DNS_DS_BUFFERSIZE];
char namebuf[DNS_NAME_FORMATSIZE];
- dns_keytag_t keytag;
dns_rdata_ds_t ds;
- dns_rdata_dnskey_t key;
dns_rdata_rrsig_t sig;
dst_key_t *dstkey;
isc_boolean_t supported_algorithm;
isc_boolean_t atsep = ISC_FALSE;
- isc_uint8_t digest_type;
+ char digest_types[256];
/*
* Caller must be holding the validator lock.
@@ -2259,8 +2333,7 @@ validatezonekey(dns_validator_t *val) {
result = dns_keytable_findkeynode(val->keytable,
val->event->name,
sig.algorithm,
- sig.keyid,
- &keynode);
+ sig.keyid, &keynode);
if (result == ISC_R_NOTFOUND &&
dns_keytable_finddeepestmatch(val->keytable,
val->event->name, found) != ISC_R_SUCCESS) {
@@ -2284,11 +2357,18 @@ validatezonekey(dns_validator_t *val) {
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
dstkey = dns_keynode_key(keynode);
+ if (dstkey == NULL) {
+ dns_keytable_detachkeynode(
+ val->keytable,
+ &keynode);
+ break;
+ }
result = verify(val, dstkey, &sigrdata,
sig.keyid);
if (result == ISC_R_SUCCESS) {
- dns_keytable_detachkeynode(val->keytable,
- &keynode);
+ dns_keytable_detachkeynode(
+ val->keytable,
+ &keynode);
break;
}
result = dns_keytable_findnextkeynode(
@@ -2318,8 +2398,8 @@ validatezonekey(dns_validator_t *val) {
sizeof(namebuf));
validator_log(val, ISC_LOG_NOTICE,
"unable to find a DNSKEY which verifies "
- "the DNSKEY RRset and also matches one "
- "of specified trusted-keys for '%s'",
+ "the DNSKEY RRset and also matches a "
+ "trusted key for '%s'",
namebuf);
validator_log(val, ISC_LOG_NOTICE,
"please check the 'trusted-keys' for "
@@ -2413,7 +2493,8 @@ validatezonekey(dns_validator_t *val) {
if (val->dsset->trust < dns_trust_secure) {
if (val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
- "must be secure failure");
+ "must be secure failure,"
+ " insecure DS");
return (DNS_R_MUSTBESECURE);
}
if (val->view->dlv == NULL || DLVTRIED(val)) {
@@ -2437,7 +2518,7 @@ validatezonekey(dns_validator_t *val) {
* need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
* is present.
*/
- digest_type = DNS_DSDIGEST_SHA1;
+ memset(digest_types, 1, sizeof(digest_types));
for (result = dns_rdataset_first(val->dsset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(val->dsset)) {
@@ -2453,7 +2534,7 @@ validatezonekey(dns_validator_t *val) {
if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
ds.length == ISC_SHA256_DIGESTLENGTH) {
- digest_type = DNS_DSDIGEST_SHA256;
+ digest_types[DNS_DSDIGEST_SHA1] = 0;
break;
}
}
@@ -2471,7 +2552,7 @@ validatezonekey(dns_validator_t *val) {
ds.digest_type))
continue;
- if (ds.digest_type != digest_type)
+ if (digest_types[ds.digest_type] == 0)
continue;
if (!dns_resolver_algorithm_supported(val->view->resolver,
@@ -2485,29 +2566,10 @@ validatezonekey(dns_validator_t *val) {
dns_rdataset_clone(val->event->rdataset, &trdataset);
/*
- * Look for the KEY that matches the DS record.
+ * Find matching DNSKEY from DS.
*/
- for (result = dns_rdataset_first(&trdataset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(&trdataset))
- {
- dns_rdata_reset(&keyrdata);
- dns_rdataset_current(&trdataset, &keyrdata);
- result = dns_rdata_tostruct(&keyrdata, &key, NULL);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- keytag = compute_keytag(&keyrdata, &key);
- if (ds.key_tag != keytag ||
- ds.algorithm != key.algorithm)
- continue;
- dns_rdata_reset(&newdsrdata);
- result = dns_ds_buildrdata(val->event->name,
- &keyrdata, ds.digest_type,
- dsbuf, &newdsrdata);
- if (result != ISC_R_SUCCESS)
- continue;
- if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0)
- break;
- }
+ result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type,
+ ds.key_tag, ds.algorithm, &keyrdata);
if (result != ISC_R_SUCCESS) {
dns_rdataset_disassociate(&trdataset);
validator_log(val, ISC_LOG_DEBUG(3),
@@ -2515,38 +2577,11 @@ validatezonekey(dns_validator_t *val) {
continue;
}
- for (result = dns_rdataset_first(val->event->sigrdataset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(val->event->sigrdataset))
- {
- dns_rdata_reset(&sigrdata);
- dns_rdataset_current(val->event->sigrdataset,
- &sigrdata);
- result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- 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,
- val->view->mctx,
- &dstkey);
- if (result != ISC_R_SUCCESS)
- /*
- * This really shouldn't happen, but...
- */
- continue;
- result = verify(val, dstkey, &sigrdata, sig.keyid);
- dst_key_free(&dstkey);
- if (result == ISC_R_SUCCESS)
- break;
- }
+ /*
+ * Check that this DNSKEY signed the DNSKEY rrset.
+ */
+ result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm);
+
dns_rdataset_disassociate(&trdataset);
if (result == ISC_R_SUCCESS)
break;
@@ -2555,20 +2590,24 @@ validatezonekey(dns_validator_t *val) {
}
if (result == ISC_R_SUCCESS) {
marksecure(event);
- validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
+ validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
return (result);
} else if (result == ISC_R_NOMORE && !supported_algorithm) {
if (val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
- "must be secure failure");
+ "must be secure failure, "
+ "no supported algorithm/digest (DS)");
return (DNS_R_MUSTBESECURE);
}
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm/digest (DS)");
markanswer(val, "validatezonekey (3)");
return (ISC_R_SUCCESS);
- } else
+ } else {
+ validator_log(val, ISC_LOG_INFO,
+ "no valid signature found (DS)");
return (DNS_R_NOVALIDSIG);
+ }
}
/*%
@@ -3094,9 +3133,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
findnsec3proofs(val);
if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) {
validator_log(val, ISC_LOG_DEBUG(3),
- "noqname proof found");
- validator_log(val, ISC_LOG_DEBUG(3),
- "marking as secure");
+ "marking as secure, noqname proof found");
marksecure(val->event);
return (ISC_R_SUCCESS);
} else if (FOUNDOPTOUT(val) &&
@@ -3143,7 +3180,6 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
marksecure(val->event);
return (ISC_R_SUCCESS);
}
- findnsec3proofs(val);
if (val->authfail != 0 && val->authcount == val->authfail)
return (DNS_R_BROKENCHAIN);
@@ -3345,7 +3381,8 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
namebuf);
if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
- validator_log(val, ISC_LOG_WARNING, "must be secure failure");
+ validator_log(val, ISC_LOG_WARNING, "must be secure failure, "
+ " %s is under DLV (startfinddlvsep)", namebuf);
return (DNS_R_MUSTBESECURE);
}
@@ -3397,10 +3434,12 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
INSIST(val->view->dlv != NULL);
if (!resume) {
-
if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
+ dns_name_format(val->event->name, namebuf,
+ sizeof(namebuf));
validator_log(val, ISC_LOG_WARNING,
- "must be secure failure");
+ "must be secure failure, "
+ "%s is under DLV (finddlvsep)", namebuf);
return (DNS_R_MUSTBESECURE);
}
@@ -3468,8 +3507,11 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
return (result);
return (DNS_R_WAIT);
}
- if (val->frdataset.trust < dns_trust_secure)
+ if (val->frdataset.trust < dns_trust_secure) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "DLV not validated");
return (DNS_R_NOVALIDSIG);
+ }
val->havedlvsep = ISC_TRUE;
dns_rdataset_clone(&val->frdataset, &val->dlv);
return (ISC_R_SUCCESS);
@@ -3554,10 +3596,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
if (result == ISC_R_NOTFOUND) {
if (val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
- "must be secure failure");
+ "must be secure failure, "
+ "not beneath secure root");
result = DNS_R_MUSTBESECURE;
goto out;
- }
+ } else
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "not beneath secure root");
if (val->view->dlv == NULL || DLVTRIED(val)) {
markanswer(val, "proveunsecure (1)");
return (ISC_R_SUCCESS);
@@ -3577,7 +3622,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
/*
* If we have a DS rdataset and it is secure then check if
* the DS rdataset has a supported algorithm combination.
- * If not this is a insecure delegation as far as this
+ * If not this is an insecure delegation as far as this
* resolver is concerned. Fall back to DLV if available.
*/
if (have_ds && val->frdataset.trust >= dns_trust_secure &&
@@ -3588,7 +3633,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
if ((val->view->dlv == NULL || DLVTRIED(val)) &&
val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
- "must be secure failure at '%s'",
+ "must be secure failure at '%s', "
+ "can't fall back to DLV",
namebuf);
result = DNS_R_MUSTBESECURE;
goto out;
@@ -3630,7 +3676,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
/*
* There is no DS. If this is a delegation,
- * we maybe done.
+ * we may be done.
*/
/*
* If we have "trust == answer" then this namespace
@@ -3643,7 +3689,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
&val->frdataset,
NULL, dsvalidated,
"proveunsecure");
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
goto out;
return (DNS_R_WAIT);
}
@@ -3655,12 +3701,13 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
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 &&
+ 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");
+ "must be secure failure, "
+ "no DS at zone cut");
return (DNS_R_MUSTBESECURE);
}
if (val->view->dlv == NULL || DLVTRIED(val)) {
@@ -3676,13 +3723,18 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
* there's no way of validating existing
* negative response blobs, give up.
*/
+ validator_log(val, ISC_LOG_WARNING,
+ "can't validate existing "
+ "negative responses (no DS)");
result = DNS_R_NOVALIDSIG;
goto out;
}
if (isdelegation(tname, &val->frdataset, result)) {
if (val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
- "must be secure failure");
+ "must be secure failure, "
+ "%s is a delegation",
+ namebuf);
return (DNS_R_MUSTBESECURE);
}
if (val->view->dlv == NULL || DLVTRIED(val)) {
@@ -3705,7 +3757,10 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
if (val->mustbesecure) {
validator_log(val,
ISC_LOG_WARNING,
- "must be secure failure");
+ "must be secure failure, "
+ "no supported algorithm/"
+ "digest (%s/DS)",
+ namebuf);
result = DNS_R_MUSTBESECURE;
goto out;
}
@@ -3723,6 +3778,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
}
else if (!dns_rdataset_isassociated(&val->fsigrdataset))
{
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "DS is unsigned");
result = DNS_R_NOVALIDSIG;
goto out;
}
@@ -3771,6 +3828,10 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
* there's no way of validating existing
* negative response blobs, give up.
*/
+ validator_log(val, ISC_LOG_WARNING,
+ "can't validate existing "
+ "negative responses "
+ "(not a zone cut)");
result = DNS_R_NOVALIDSIG;
goto out;
}
@@ -3790,7 +3851,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
/* Couldn't complete insecurity proof */
validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
- return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
+ return (DNS_R_NOTINSECURE);
out:
if (dns_rdataset_isassociated(&val->frdataset))
@@ -3829,7 +3890,7 @@ dlv_validator_start(dns_validator_t *val) {
* \li 3. a negative answer (secure or unsecure).
*
* Note a answer that appears to be a secure positive answer may actually
- * be a unsecure positive answer.
+ * be an unsecure positive answer.
*/
static void
validator_start(isc_task_t *task, isc_event_t *event) {
@@ -3895,6 +3956,10 @@ validator_start(isc_task_t *task, isc_event_t *event) {
val->attributes |= VALATTR_INSECURITY;
result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
+ if (result == DNS_R_NOTINSECURE)
+ validator_log(val, ISC_LOG_INFO,
+ "got insecure response; "
+ "parent indicates it should be secure");
} else if (val->event->rdataset == NULL &&
val->event->sigrdataset == NULL)
{
@@ -3967,6 +4032,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
return (ISC_R_NOMEMORY);
val->view = NULL;
dns_view_weakattach(view, &val->view);
+
event = (dns_validatorevent_t *)
isc_event_allocate(view->mctx, task,
DNS_EVENT_VALIDATORSTART,
@@ -3995,8 +4061,12 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
val->fetch = NULL;
val->subvalidator = NULL;
val->parent = NULL;
+
val->keytable = NULL;
- dns_keytable_attach(val->view->secroots, &val->keytable);
+ result = dns_view_getsecroots(val->view, &val->keytable);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
val->keynode = NULL;
val->key = NULL;
val->siginfo = NULL;
diff --git a/contrib/bind9/lib/dns/view.c b/contrib/bind9/lib/dns/view.c
index 809cc15..24f925a 100644
--- a/contrib/bind9/lib/dns/view.c
+++ b/contrib/bind9/lib/dns/view.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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,16 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: view.c,v 1.150.84.6 2010-09-24 08:09:08 marka Exp $ */
+/* $Id: view.c,v 1.178 2011-01-13 09:53:04 marka Exp $ */
/*! \file */
#include <config.h>
+#include <isc/file.h>
#include <isc/hash.h>
+#include <isc/print.h>
+#include <isc/sha2.h>
#include <isc/stats.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/task.h>
@@ -33,17 +36,24 @@
#include <dns/cache.h>
#include <dns/db.h>
#include <dns/dlz.h>
+#ifdef BIND9
+#include <dns/dns64.h>
+#endif
+#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/forward.h>
#include <dns/keytable.h>
+#include <dns/keyvalues.h>
#include <dns/master.h>
#include <dns/masterdump.h>
#include <dns/order.h>
#include <dns/peer.h>
+#include <dns/rbt.h>
#include <dns/rdataset.h>
#include <dns/request.h>
#include <dns/resolver.h>
#include <dns/result.h>
+#include <dns/rpz.h>
#include <dns/stats.h>
#include <dns/tsig.h>
#include <dns/zone.h>
@@ -85,6 +95,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
if (result != ISC_R_SUCCESS)
goto cleanup_name;
+#ifdef BIND9
view->zonetable = NULL;
result = dns_zt_create(mctx, rdclass, &view->zonetable);
if (result != ISC_R_SUCCESS) {
@@ -94,24 +105,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
result = ISC_R_UNEXPECTED;
goto cleanup_mutex;
}
- view->secroots = NULL;
- result = dns_keytable_create(mctx, &view->secroots);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "dns_keytable_create() failed: %s",
- isc_result_totext(result));
- result = ISC_R_UNEXPECTED;
- goto cleanup_zt;
- }
- view->trustedkeys = NULL;
- result = dns_keytable_create(mctx, &view->trustedkeys);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "dns_keytable_create() failed: %s",
- isc_result_totext(result));
- result = ISC_R_UNEXPECTED;
- goto cleanup_secroots;
- }
+#endif
+ view->secroots_priv = NULL;
view->fwdtable = NULL;
result = dns_fwdtable_create(mctx, &view->fwdtable);
if (result != ISC_R_SUCCESS) {
@@ -119,7 +114,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
"dns_fwdtable_create() failed: %s",
isc_result_totext(result));
result = ISC_R_UNEXPECTED;
- goto cleanup_trustedkeys;
+ goto cleanup_zt;
}
view->acache = NULL;
@@ -155,6 +150,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->rootexclude = NULL;
view->resstats = NULL;
view->resquerystats = NULL;
+ view->cacheshared = ISC_FALSE;
+ ISC_LIST_INIT(view->dns64);
+ view->dns64cnt = 0;
/*
* Initialize configuration data with default values.
@@ -179,6 +177,10 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->notifyacl = NULL;
view->updateacl = NULL;
view->upfwdacl = NULL;
+ view->denyansweracl = NULL;
+ view->answeracl_exclude = NULL;
+ view->denyanswernames = NULL;
+ view->answernames_exclude = NULL;
view->requestixfr = ISC_TRUE;
view->provideixfr = ISC_TRUE;
view->maxcachettl = 7 * 24 * 3600;
@@ -188,11 +190,20 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
view->flush = ISC_FALSE;
view->dlv = NULL;
view->maxudp = 0;
+ view->v4_aaaa = dns_v4_aaaa_ok;
+ view->v4_aaaa_acl = NULL;
+ ISC_LIST_INIT(view->rpz_zones);
dns_fixedname_init(&view->dlv_fixed);
+ view->managed_keys = NULL;
+#ifdef BIND9
+ view->new_zone_file = NULL;
+ view->new_zone_config = NULL;
+ view->cfg_destroy = NULL;
result = dns_order_create(view->mctx, &view->order);
if (result != ISC_R_SUCCESS)
goto cleanup_dynkeys;
+#endif
result = dns_peerlist_new(view->mctx, &view->peers);
if (result != ISC_R_SUCCESS)
@@ -222,10 +233,12 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
dns_peerlist_detach(&view->peers);
cleanup_order:
+#ifdef BIND9
dns_order_detach(&view->order);
cleanup_dynkeys:
- dns_tsigkeyring_destroy(&view->dynamickeys);
+#endif
+ dns_tsigkeyring_detach(&view->dynamickeys);
cleanup_references:
isc_refcount_destroy(&view->references);
@@ -233,16 +246,12 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
cleanup_fwdtable:
dns_fwdtable_destroy(&view->fwdtable);
- cleanup_trustedkeys:
- dns_keytable_detach(&view->trustedkeys);
-
- cleanup_secroots:
- dns_keytable_detach(&view->secroots);
-
cleanup_zt:
+#ifdef BIND9
dns_zt_detach(&view->zonetable);
cleanup_mutex:
+#endif
DESTROYLOCK(&view->lock);
cleanup_name:
@@ -256,6 +265,10 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
static inline void
destroy(dns_view_t *view) {
+#ifdef BIND9
+ dns_dns64_t *dns64;
+#endif
+
REQUIRE(!ISC_LINK_LINKED(view, link));
REQUIRE(isc_refcount_current(&view->references) == 0);
REQUIRE(view->weakrefs == 0);
@@ -263,23 +276,62 @@ destroy(dns_view_t *view) {
REQUIRE(ADBSHUTDOWN(view));
REQUIRE(REQSHUTDOWN(view));
+#ifdef BIND9
if (view->order != NULL)
dns_order_detach(&view->order);
+#endif
if (view->peers != NULL)
dns_peerlist_detach(&view->peers);
- if (view->dynamickeys != NULL)
- dns_tsigkeyring_destroy(&view->dynamickeys);
+
+ if (view->dynamickeys != NULL) {
+ isc_result_t result;
+ char template[20];
+ char keyfile[20];
+ FILE *fp = NULL;
+ int n;
+
+ n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys",
+ view->name);
+ if (n > 0 && (size_t)n < sizeof(keyfile)) {
+ result = isc_file_mktemplate(keyfile, template,
+ sizeof(template));
+ if (result == ISC_R_SUCCESS)
+ (void)isc_file_openuniqueprivate(template, &fp);
+ }
+ if (fp == NULL)
+ dns_tsigkeyring_detach(&view->dynamickeys);
+ else {
+ result = dns_tsigkeyring_dumpanddetach(
+ &view->dynamickeys, fp);
+ if (result == ISC_R_SUCCESS) {
+ if (fclose(fp) == 0)
+ result = isc_file_rename(template,
+ keyfile);
+ if (result != ISC_R_SUCCESS)
+ (void)remove(template);
+ } else {
+ (void)fclose(fp);
+ (void)remove(template);
+ }
+ }
+ }
if (view->statickeys != NULL)
- dns_tsigkeyring_destroy(&view->statickeys);
+ dns_tsigkeyring_detach(&view->statickeys);
if (view->adb != NULL)
dns_adb_detach(&view->adb);
if (view->resolver != NULL)
dns_resolver_detach(&view->resolver);
+#ifdef BIND9
if (view->acache != NULL) {
if (view->cachedb != NULL)
dns_acache_putdb(view->acache, view->cachedb);
dns_acache_detach(&view->acache);
}
+ dns_rpz_view_destroy(view);
+#else
+ INSIST(view->acache == NULL);
+ INSIST(ISC_LIST_EMPTY(view->rpz_zones));
+#endif
if (view->requestmgr != NULL)
dns_requestmgr_detach(&view->requestmgr);
if (view->task != NULL)
@@ -318,6 +370,16 @@ destroy(dns_view_t *view) {
dns_acl_detach(&view->updateacl);
if (view->upfwdacl != NULL)
dns_acl_detach(&view->upfwdacl);
+ if (view->denyansweracl != NULL)
+ dns_acl_detach(&view->denyansweracl);
+ if (view->v4_aaaa_acl != NULL)
+ dns_acl_detach(&view->v4_aaaa_acl);
+ if (view->answeracl_exclude != NULL)
+ dns_rbt_destroy(&view->answeracl_exclude);
+ if (view->denyanswernames != NULL)
+ dns_rbt_destroy(&view->denyanswernames);
+ if (view->answernames_exclude != NULL)
+ dns_rbt_destroy(&view->answernames_exclude);
if (view->delonly != NULL) {
dns_name_t *name;
int i;
@@ -357,8 +419,19 @@ destroy(dns_view_t *view) {
isc_stats_detach(&view->resstats);
if (view->resquerystats != NULL)
dns_stats_detach(&view->resquerystats);
- dns_keytable_detach(&view->trustedkeys);
- dns_keytable_detach(&view->secroots);
+ if (view->secroots_priv != NULL)
+ dns_keytable_detach(&view->secroots_priv);
+#ifdef BIND9
+ for (dns64 = ISC_LIST_HEAD(view->dns64);
+ dns64 != NULL;
+ dns64 = ISC_LIST_HEAD(view->dns64)) {
+ dns_dns64_unlink(&view->dns64, dns64);
+ dns_dns64_destroy(&dns64);
+ }
+ if (view->managed_keys != NULL)
+ dns_zone_detach(&view->managed_keys);
+ dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
+#endif
dns_fwdtable_destroy(&view->fwdtable);
dns_aclenv_destroy(&view->aclenv);
DESTROYLOCK(&view->lock);
@@ -414,12 +487,19 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
dns_adb_shutdown(view->adb);
if (!REQSHUTDOWN(view))
dns_requestmgr_shutdown(view->requestmgr);
+#ifdef BIND9
if (view->acache != NULL)
dns_acache_shutdown(view->acache);
if (view->flush)
dns_zt_flushanddetach(&view->zonetable);
else
dns_zt_detach(&view->zonetable);
+ if (view->managed_keys != NULL) {
+ if (view->flush)
+ dns_zone_flush(view->managed_keys);
+ dns_zone_detach(&view->managed_keys);
+ }
+#endif
done = all_done(view);
UNLOCK(&view->lock);
}
@@ -440,6 +520,7 @@ dns_view_detach(dns_view_t **viewp) {
view_flushanddetach(viewp, ISC_FALSE);
}
+#ifdef BIND9
static isc_result_t
dialup(dns_zone_t *zone, void *dummy) {
UNUSED(dummy);
@@ -452,6 +533,7 @@ dns_view_dialup(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
(void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
}
+#endif
void
dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
@@ -633,12 +715,20 @@ dns_view_createresolver(dns_view_t *view,
void
dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
+ dns_view_setcache2(view, cache, ISC_FALSE);
+}
+
+void
+dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
+ view->cacheshared = shared;
if (view->cache != NULL) {
+#ifdef BIND9
if (view->acache != NULL)
dns_acache_putdb(view->acache, view->cachedb);
+#endif
dns_db_detach(&view->cachedb);
dns_cache_detach(&view->cache);
}
@@ -646,8 +736,17 @@ dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
dns_cache_attachdb(cache, &view->cachedb);
INSIST(DNS_DB_VALID(view->cachedb));
+#ifdef BIND9
if (view->acache != NULL)
dns_acache_setdb(view->acache, view->cachedb);
+#endif
+}
+
+isc_boolean_t
+dns_view_iscacheshared(dns_view_t *view) {
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ return (view->cacheshared);
}
void
@@ -665,26 +764,52 @@ dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ring != NULL);
if (view->statickeys != NULL)
- dns_tsigkeyring_destroy(&view->statickeys);
- view->statickeys = ring;
+ dns_tsigkeyring_detach(&view->statickeys);
+ dns_tsigkeyring_attach(ring, &view->statickeys);
}
void
-dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
+dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
REQUIRE(DNS_VIEW_VALID(view));
- view->dstport = dstport;
+ REQUIRE(ring != NULL);
+ if (view->dynamickeys != NULL)
+ dns_tsigkeyring_detach(&view->dynamickeys);
+ dns_tsigkeyring_attach(ring, &view->dynamickeys);
}
-isc_result_t
-dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
- isc_result_t result;
+void
+dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(ringp != NULL && *ringp == NULL);
+ if (view->dynamickeys != NULL)
+ dns_tsigkeyring_attach(view->dynamickeys, ringp);
+}
+
+void
+dns_view_restorekeyring(dns_view_t *view) {
+ FILE *fp;
+ char keyfile[20];
+ int n;
REQUIRE(DNS_VIEW_VALID(view));
- REQUIRE(!view->frozen);
- result = dns_zt_mount(view->zonetable, zone);
+ if (view->dynamickeys != NULL) {
+ n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys",
+ view->name);
+ if (n > 0 && (size_t)n < sizeof(keyfile)) {
+ fp = fopen(keyfile, "r");
+ if (fp != NULL) {
+ dns_keyring_restore(view->dynamickeys, fp);
+ (void)fclose(fp);
+ }
+ }
+ }
+}
- return (result);
+void
+dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ view->dstport = dstport;
}
void
@@ -699,6 +824,29 @@ dns_view_freeze(dns_view_t *view) {
view->frozen = ISC_TRUE;
}
+#ifdef BIND9
+void
+dns_view_thaw(dns_view_t *view) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(view->frozen);
+
+ view->frozen = ISC_FALSE;
+}
+
+isc_result_t
+dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
+ isc_result_t result;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+
+ result = dns_zt_mount(view->zonetable, zone);
+
+ return (result);
+}
+#endif
+
+#ifdef BIND9
isc_result_t
dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
isc_result_t result;
@@ -713,20 +861,37 @@ dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
return (result);
}
+#endif
isc_result_t
dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints,
dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
- dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
+ return (dns_view_find2(view, name, type, now, options, use_hints,
+ ISC_FALSE, dbp, nodep, foundname, rdataset,
+ sigrdataset));
+}
+
+isc_result_t
+dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
+ isc_stdtime_t now, unsigned int options,
+ isc_boolean_t use_hints, isc_boolean_t use_static_stub,
+ dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
isc_result_t result;
dns_db_t *db, *zdb;
dns_dbnode_t *node, *znode;
- isc_boolean_t is_cache;
+ isc_boolean_t is_cache, is_staticstub_zone;
dns_rdataset_t zrdataset, zsigrdataset;
dns_zone_t *zone;
+#ifndef BIND9
+ UNUSED(use_hints);
+ UNUSED(use_static_stub);
+#endif
+
/*
* Find an rdataset whose owner name is 'name', and whose type is
* 'type'.
@@ -752,15 +917,30 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
zone = NULL;
db = NULL;
node = NULL;
+ is_staticstub_zone = ISC_FALSE;
+#ifdef BIND9
result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
+ !use_static_stub) {
+ result = ISC_R_NOTFOUND;
+ }
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
result = dns_zone_getdb(zone, &db);
if (result != ISC_R_SUCCESS && view->cachedb != NULL)
dns_db_attach(view->cachedb, &db);
else if (result != ISC_R_SUCCESS)
goto cleanup;
+ if (dns_zone_gettype(zone) == dns_zone_staticstub &&
+ dns_name_equal(name, dns_zone_getorigin(zone))) {
+ is_staticstub_zone = ISC_TRUE;
+ }
} else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
dns_db_attach(view->cachedb, &db);
+#else
+ result = ISC_R_NOTFOUND;
+ if (view->cachedb != NULL)
+ dns_db_attach(view->cachedb, &db);
+#endif /* BIND9 */
else
goto cleanup;
@@ -773,8 +953,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
result = dns_db_find(db, name, NULL, type, options,
now, &node, foundname, rdataset, sigrdataset);
- if (result == DNS_R_DELEGATION ||
- result == ISC_R_NOTFOUND) {
+ if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
if (sigrdataset != NULL &&
@@ -784,10 +963,13 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
dns_db_detachnode(db, &node);
if (!is_cache) {
dns_db_detach(&db);
- if (view->cachedb != NULL) {
+ if (view->cachedb != NULL && !is_staticstub_zone) {
/*
* Either the answer is in the cache, or we
* don't know it.
+ * Note that if the result comes from a
+ * static-stub zone we stop the search here
+ * (see the function description in view.h).
*/
is_cache = ISC_TRUE;
dns_db_attach(view->cachedb, &db);
@@ -817,7 +999,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
*/
result = ISC_R_NOTFOUND;
} else if (result == DNS_R_GLUE) {
- if (view->cachedb != NULL) {
+ if (view->cachedb != NULL && !is_staticstub_zone) {
/*
* We found an answer, but the cache may be better.
* Remember what we've got and go look in the cache.
@@ -843,6 +1025,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
result = ISC_R_SUCCESS;
}
+#ifdef BIND9
if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
@@ -877,6 +1060,7 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
if (db == NULL && node != NULL)
dns_db_detachnode(view->hints, &node);
}
+#endif /* BIND9 */
cleanup:
if (dns_rdataset_isassociated(&zrdataset)) {
@@ -905,8 +1089,10 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
} else
INSIST(node == NULL);
+#ifdef BIND9
if (zone != NULL)
dns_zone_detach(&zone);
+#endif
return (result);
}
@@ -969,12 +1155,12 @@ dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
isc_result_t
dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
isc_stdtime_t now, unsigned int options,
- isc_boolean_t use_hints, isc_boolean_t use_cache,
+ isc_boolean_t use_hints, isc_boolean_t use_cache,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
isc_result_t result;
dns_db_t *db;
- isc_boolean_t is_cache, use_zone, try_hints;
+ isc_boolean_t is_cache, use_zone, try_hints, is_staticstub_zone;
dns_zone_t *zone;
dns_name_t *zfname;
dns_rdataset_t zrdataset, zsigrdataset;
@@ -986,6 +1172,7 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
db = NULL;
zone = NULL;
use_zone = ISC_FALSE;
+ is_staticstub_zone = ISC_FALSE;
try_hints = ISC_FALSE;
zfname = NULL;
@@ -999,9 +1186,16 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
/*
* Find the right database.
*/
+#ifdef BIND9
result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
- if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
result = dns_zone_getdb(zone, &db);
+ if (dns_zone_gettype(zone) == dns_zone_staticstub)
+ is_staticstub_zone = ISC_TRUE;
+ }
+#else
+ result = ISC_R_NOTFOUND;
+#endif
if (result == ISC_R_NOTFOUND) {
/*
* We're not directly authoritative for this query name, nor
@@ -1064,7 +1258,9 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
fname, rdataset, sigrdataset);
if (result == ISC_R_SUCCESS) {
if (zfname != NULL &&
- !dns_name_issubdomain(fname, zfname)) {
+ (!dns_name_issubdomain(fname, zfname) ||
+ (dns_zone_staticstub &&
+ dns_name_equal(fname, zfname)))) {
/*
* We found a zonecut in the cache, but our
* zone delegation is better.
@@ -1133,8 +1329,10 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
}
if (db != NULL)
dns_db_detach(&db);
+#ifdef BIND9
if (zone != NULL)
dns_zone_detach(&zone);
+#endif
return (result);
}
@@ -1161,6 +1359,7 @@ dns_viewlist_find(dns_viewlist_t *list, const char *name,
return (ISC_R_SUCCESS);
}
+#ifdef BIND9
isc_result_t
dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
isc_boolean_t allclasses, dns_rdataclass_t rdclass,
@@ -1225,6 +1424,7 @@ dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) {
return (dns_zt_loadnew(view->zonetable, stop));
}
+#endif /* BIND9 */
isc_result_t
dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp)
@@ -1269,6 +1469,7 @@ dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
view->dynamickeys));
}
+#ifdef BIND9
isc_result_t
dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
isc_result_t result;
@@ -1284,26 +1485,38 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
dns_resolver_printbadcache(view->resolver, fp);
return (ISC_R_SUCCESS);
}
+#endif
isc_result_t
dns_view_flushcache(dns_view_t *view) {
+ return (dns_view_flushcache2(view, ISC_FALSE));
+}
+
+isc_result_t
+dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) {
isc_result_t result;
REQUIRE(DNS_VIEW_VALID(view));
if (view->cachedb == NULL)
return (ISC_R_SUCCESS);
- result = dns_cache_flush(view->cache);
- if (result != ISC_R_SUCCESS)
- return (result);
+ if (!fixuponly) {
+ result = dns_cache_flush(view->cache);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+#ifdef BIND9
if (view->acache != NULL)
dns_acache_putdb(view->acache, view->cachedb);
+#endif
dns_db_detach(&view->cachedb);
dns_cache_attachdb(view->cache, &view->cachedb);
+#ifdef BIND9
if (view->acache != NULL)
dns_acache_setdb(view->acache, view->cachedb);
if (view->resolver != NULL)
dns_resolver_flushbadcache(view->resolver, NULL);
+#endif
dns_adb_flush(view->adb);
return (ISC_R_SUCCESS);
@@ -1437,11 +1650,13 @@ dns_view_getrootdelonly(dns_view_t *view) {
return (view->rootdelonly);
}
+#ifdef BIND9
isc_result_t
dns_view_freezezones(dns_view_t *view, isc_boolean_t value) {
REQUIRE(DNS_VIEW_VALID(view));
return (dns_zt_freezezones(view->zonetable, value));
}
+#endif
void
dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
@@ -1478,3 +1693,97 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
if (view->resquerystats != NULL)
dns_stats_attach(view->resquerystats, statsp);
}
+
+isc_result_t
+dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ if (view->secroots_priv != NULL)
+ dns_keytable_detach(&view->secroots_priv);
+ return (dns_keytable_create(mctx, &view->secroots_priv));
+}
+
+isc_result_t
+dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(ktp != NULL && *ktp == NULL);
+ if (view->secroots_priv == NULL)
+ return (ISC_R_NOTFOUND);
+ dns_keytable_attach(view->secroots_priv, ktp);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
+ isc_boolean_t *secure_domain) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ return (dns_keytable_issecuredomain(view->secroots_priv, name,
+ secure_domain));
+}
+
+void
+dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
+ dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ unsigned char data[4096];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t buffer;
+ dst_key_t *key = NULL;
+ dns_keytable_t *sr = NULL;
+
+ /*
+ * Clear the revoke bit, if set, so that the key will match what's
+ * in secroots now.
+ */
+ dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
+
+ /* Convert dnskey to DST key. */
+ isc_buffer_init(&buffer, data, sizeof(data));
+ dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
+ dns_rdatatype_dnskey, dnskey, &buffer);
+ result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ return;
+ result = dns_view_getsecroots(view, &sr);
+ if (result == ISC_R_SUCCESS) {
+ dns_keytable_deletekeynode(sr, key);
+ dns_keytable_detach(&sr);
+ }
+ dst_key_free(&key);
+}
+
+#define NZF ".nzf"
+
+void
+dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
+ void (*cfg_destroy)(void **))
+{
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow);
+
+#ifdef BIND9
+ if (view->new_zone_file != NULL) {
+ isc_mem_free(view->mctx, view->new_zone_file);
+ view->new_zone_file = NULL;
+ }
+
+ if (view->new_zone_config != NULL) {
+ view->cfg_destroy(&view->new_zone_config);
+ view->cfg_destroy = NULL;
+ }
+
+ if (allow) {
+ char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(NZF)];
+ isc_sha256_data((void *)view->name, strlen(view->name), buffer);
+ /* Truncate the hash at 16 chars; full length is overkill */
+ isc_string_printf(buffer + 16, sizeof(NZF), "%s", NZF);
+ view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
+ view->new_zone_config = cfgctx;
+ view->cfg_destroy = cfg_destroy;
+ }
+#else
+ UNUSED(allow);
+ UNUSED(cfgctx);
+ UNUSED(cfg_destroy);
+#endif
+}
diff --git a/contrib/bind9/lib/dns/xfrin.c b/contrib/bind9/lib/dns/xfrin.c
index b3f2e95..210bca9 100644
--- a/contrib/bind9/lib/dns/xfrin.c
+++ b/contrib/bind9/lib/dns/xfrin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2011 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: xfrin.c,v 1.166 2008-09-25 04:12:39 marka Exp $ */
+/* $Id: xfrin.c,v 1.166.522.2.2.1 2011-06-02 23:47:35 tbox Exp $ */
/*! \file */
@@ -83,8 +83,9 @@ typedef enum {
XFRST_IXFR_DEL,
XFRST_IXFR_ADDSOA,
XFRST_IXFR_ADD,
+ XFRST_IXFR_END,
XFRST_AXFR,
- XFRST_END
+ XFRST_AXFR_END
} xfrin_state_t;
/*%
@@ -203,6 +204,7 @@ static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
dns_rdata_t *rdata);
static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);
static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
+static isc_result_t axfr_finalize(dns_xfrin_ctx_t *xfr);
static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
@@ -318,6 +320,16 @@ axfr_commit(dns_xfrin_ctx_t *xfr) {
CHECK(axfr_apply(xfr));
CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));
+
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+static isc_result_t
+axfr_finalize(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+
CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
result = ISC_R_SUCCESS;
@@ -541,7 +553,7 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
isc_uint32_t soa_serial = dns_soa_getserial(rdata);
if (soa_serial == xfr->end_serial) {
CHECK(ixfr_commit(xfr));
- xfr->state = XFRST_END;
+ xfr->state = XFRST_IXFR_END;
break;
} else if (soa_serial != xfr->ixfr.current_serial) {
xfrin_log(xfr, ISC_LOG_ERROR,
@@ -572,11 +584,12 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
if (rdata->type == dns_rdatatype_soa) {
CHECK(axfr_commit(xfr));
- xfr->state = XFRST_END;
+ xfr->state = XFRST_AXFR_END;
break;
}
break;
- case XFRST_END:
+ case XFRST_AXFR_END:
+ case XFRST_IXFR_END:
FAIL(DNS_R_EXTRADATA);
default:
INSIST(0);
@@ -1318,8 +1331,9 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
} else if (dns_message_gettsigkey(msg) != NULL) {
xfr->sincetsig++;
- if (xfr->sincetsig > 100 ||
- xfr->nmsg == 0 || xfr->state == XFRST_END)
+ if (xfr->sincetsig > 100 || xfr->nmsg == 0 ||
+ xfr->state == XFRST_AXFR_END ||
+ xfr->state == XFRST_IXFR_END)
{
result = DNS_R_EXPECTEDTSIG;
goto failure;
@@ -1345,16 +1359,22 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
dns_message_destroy(&msg);
- if (xfr->state == XFRST_GOTSOA) {
+ switch (xfr->state) {
+ case XFRST_GOTSOA:
xfr->reqtype = dns_rdatatype_axfr;
xfr->state = XFRST_INITIALSOA;
CHECK(xfrin_send_request(xfr));
- } else if (xfr->state == XFRST_END) {
+ break;
+ case XFRST_AXFR_END:
+ CHECK(axfr_finalize(xfr));
+ /* FALLTHROUGH */
+ case XFRST_IXFR_END:
/*
* Close the journal.
*/
if (xfr->ixfr.journal != NULL)
dns_journal_destroy(&xfr->ixfr.journal);
+
/*
* Inform the caller we succeeded.
*/
@@ -1368,7 +1388,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
*/
xfr->shuttingdown = ISC_TRUE;
maybe_free(xfr);
- } else {
+ break;
+ default:
/*
* Read the next message.
*/
diff --git a/contrib/bind9/lib/dns/zone.c b/contrib/bind9/lib/dns/zone.c
index 108aefb..c727c2e 100644
--- a/contrib/bind9/lib/dns/zone.c
+++ b/contrib/bind9/lib/dns/zone.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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: zone.c,v 1.483.36.23 2010-12-14 00:48:22 marka Exp $ */
+/* $Id: zone.c,v 1.582.8.7 2011-02-18 23:23:08 each Exp $ */
/*! \file */
@@ -47,6 +47,8 @@
#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/journal.h>
+#include <dns/keydata.h>
+#include <dns/keytable.h>
#include <dns/keyvalues.h>
#include <dns/log.h>
#include <dns/master.h>
@@ -56,6 +58,8 @@
#include <dns/nsec.h>
#include <dns/nsec3.h>
#include <dns/peer.h>
+#include <dns/private.h>
+#include <dns/rbt.h>
#include <dns/rcode.h>
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
@@ -66,6 +70,7 @@
#include <dns/request.h>
#include <dns/resolver.h>
#include <dns/result.h>
+#include <dns/rriterator.h>
#include <dns/soa.h>
#include <dns/ssu.h>
#include <dns/stats.h>
@@ -129,6 +134,7 @@ 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;
+typedef struct dns_keyfetch dns_keyfetch_t;
#define DNS_ZONE_CHECKLOCK
#ifdef DNS_ZONE_CHECKLOCK
@@ -200,6 +206,8 @@ struct dns_zone {
isc_time_t keywarntime;
isc_time_t signingtime;
isc_time_t nsec3chaintime;
+ isc_time_t refreshkeytime;
+ isc_uint32_t refreshkeycount;
isc_uint32_t refresh;
isc_uint32_t retry;
isc_uint32_t expire;
@@ -273,13 +281,13 @@ struct dns_zone {
/*%
* Statistics counters about zone management.
*/
- isc_stats_t *stats;
+ isc_stats_t *stats;
/*%
* Optional per-zone statistics counters. Counted outside of this
* module.
*/
- isc_boolean_t requeststats_on;
- isc_stats_t *requeststats;
+ isc_boolean_t requeststats_on;
+ isc_stats_t *requeststats;
isc_uint32_t notifydelay;
dns_isselffunc_t isself;
void *isselfarg;
@@ -304,6 +312,21 @@ struct dns_zone {
isc_uint32_t signatures;
isc_uint32_t nodes;
dns_rdatatype_t privatetype;
+
+ /*%
+ * Autosigning/key-maintenance options
+ */
+ isc_uint32_t keyopts;
+
+ /*%
+ * True if added by "rndc addzone"
+ */
+ isc_boolean_t added;
+
+ /*%
+ * whether a rpz radix was needed when last loaded
+ */
+ isc_boolean_t rpz_zone;
};
#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
@@ -339,7 +362,7 @@ struct dns_zone {
* from SOA (if not set, we
* are still using
* default timer values) */
-#define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
+#define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
#define DNS_ZONEFLG_NOREFRESH 0x00010000U
#define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
#define DNS_ZONEFLG_DIALREFRESH 0x00040000U
@@ -352,8 +375,11 @@ struct dns_zone {
#define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
#define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */
#define DNS_ZONEFLG_THAW 0x08000000U
+/* #define DNS_ZONEFLG_XXXXX 0x10000000U XXXMPA unused. */
+#define DNS_ZONEFLG_NODELAY 0x20000000U
#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
+#define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
/* Flags for zone_load() */
#define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
@@ -484,7 +510,7 @@ struct dns_io {
* DNSKEY as result of an update.
*/
struct dns_signing {
- unsigned int magic;
+ unsigned int magic;
dns_db_t *db;
dns_dbiterator_t *dbiterator;
dns_secalg_t algorithm;
@@ -495,15 +521,15 @@ struct dns_signing {
};
struct dns_nsec3chain {
- unsigned int magic;
+ 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_boolean_t seen_nsec;
+ isc_boolean_t delete_nsec;
+ isc_boolean_t save_delete_nsec;
ISC_LINK(dns_nsec3chain_t) link;
};
/*%<
@@ -528,6 +554,19 @@ struct dns_nsec3chain {
* so it can be recovered in the event of a error.
*/
+struct dns_keyfetch {
+ dns_fixedname_t name;
+ dns_rdataset_t keydataset;
+ dns_rdataset_t dnskeyset;
+ dns_rdataset_t dnskeysigset;
+ dns_zone_t *zone;
+ dns_db_t *db;
+ dns_fetch_t *fetch;
+};
+
+#define HOUR 3600
+#define DAY (24*HOUR)
+#define MONTH (30*DAY)
#define SEND_BUFFER_SIZE 2048
@@ -538,6 +577,10 @@ static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
ISC_FORMAT_PRINTF(3, 4);
static void queue_xfrin(dns_zone_t *zone);
+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);
static void zone_unload(dns_zone_t *zone);
static void zone_expire(dns_zone_t *zone);
static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
@@ -613,6 +656,10 @@ static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
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);
+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);
+static void zone_rekey(dns_zone_t *zone);
#define ENTER zone_debuglog(zone, me, 1, "enter")
@@ -710,6 +757,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->type = dns_zone_none;
zone->flags = 0;
zone->options = 0;
+ zone->keyopts = 0;
zone->db_argc = 0;
zone->db_argv = NULL;
isc_time_settoepoch(&zone->expiretime);
@@ -721,6 +769,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
isc_time_settoepoch(&zone->keywarntime);
isc_time_settoepoch(&zone->signingtime);
isc_time_settoepoch(&zone->nsec3chaintime);
+ isc_time_settoepoch(&zone->refreshkeytime);
+ zone->refreshkeycount = 0;
zone->refresh = DNS_ZONE_DEFAULTREFRESH;
zone->retry = DNS_ZONE_DEFAULTRETRY;
zone->expire = 0;
@@ -787,6 +837,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->signatures = 10;
zone->nodes = 100;
zone->privatetype = (dns_rdatatype_t)0xffffU;
+ zone->added = ISC_FALSE;
+ zone->rpz_zone = ISC_FALSE;
zone->magic = ZONE_MAGIC;
@@ -1304,8 +1356,8 @@ dns_zone_getjournal(dns_zone_t *zone) {
* master file (if any) is written by the server, rather than being
* updated manually and read by the server.
*
- * This is true for slave zones, stub zones, and zones that allow
- * dynamic updates either by having an update policy ("ssutable")
+ * This is true for slave zones, stub zones, key zones, and zones that
+ * allow dynamic updates either by having an update policy ("ssutable")
* or an "allow-update" ACL with a value other than exactly "{ none; }".
*/
static isc_boolean_t
@@ -1314,6 +1366,7 @@ zone_isdynamic(dns_zone_t *zone) {
return (ISC_TF(zone->type == dns_zone_slave ||
zone->type == dns_zone_stub ||
+ zone->type == dns_zone_key ||
(!zone->update_disabled && zone->ssutable != NULL) ||
(!zone->update_disabled && zone->update_acl != NULL &&
!dns_acl_isnone(zone->update_acl))));
@@ -1383,11 +1436,12 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
*/
if (zone->masterfile != NULL) {
/*
- * The file is already loaded. If we are just doing a
+ * The file is already loaded. If we are just doing a
* "rndc reconfig", we are done.
*/
if (!isc_time_isepoch(&zone->loadtime) &&
- (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
+ (flags & DNS_ZONELOADFLAG_NOSTAT) != 0 &&
+ zone->rpz_zone == dns_rpz_needed()) {
result = ISC_R_SUCCESS;
goto cleanup;
}
@@ -1396,7 +1450,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
if (result == ISC_R_SUCCESS) {
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
- isc_time_compare(&filetime, &zone->loadtime) <= 0) {
+ isc_time_compare(&filetime, &zone->loadtime) <= 0 &&
+ zone->rpz_zone == dns_rpz_needed()) {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"skipping load: master file "
"older than last load");
@@ -1404,6 +1459,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
goto cleanup;
}
loadtime = filetime;
+ zone->rpz_zone = dns_rpz_needed();
}
}
@@ -1526,6 +1582,8 @@ get_master_options(dns_zone_t *zone) {
options = DNS_MASTER_ZONE;
if (zone->type == dns_zone_slave)
options |= DNS_MASTER_SLAVE;
+ if (zone->type == dns_zone_key)
+ options |= DNS_MASTER_KEY;
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
options |= DNS_MASTER_CHECKNS;
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
@@ -1541,7 +1599,8 @@ get_master_options(dns_zone_t *zone) {
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))
+ ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
+ zone->ssutable != NULL))
options |= DNS_MASTER_RESIGN;
return (options);
}
@@ -1740,11 +1799,12 @@ zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
dns_name_format(name, namebuf, sizeof namebuf);
if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
result == DNS_R_EMPTYNAME) {
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
+ level = ISC_LOG_WARNING;
dns_zone_log(zone, level,
"%s/MX '%s' has no address records (A or AAAA)",
ownerbuf, namebuf);
- /* XXX950 make fatal for 9.5.0. */
- return (ISC_TRUE);
+ return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
}
if (result == DNS_R_CNAME) {
@@ -1986,6 +2046,113 @@ zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
}
static isc_boolean_t
+zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
+ dns_rdataset_t *rdataset)
+{
+ dns_rdataset_t tmprdataset;
+ isc_result_t result;
+ isc_boolean_t answer = ISC_TRUE;
+ isc_boolean_t format = ISC_TRUE;
+ int level = ISC_LOG_WARNING;
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ unsigned int count1 = 0;
+
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
+ level = ISC_LOG_ERROR;
+
+ dns_rdataset_init(&tmprdataset);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata1 = DNS_RDATA_INIT;
+ unsigned int count2 = 0;
+
+ count1++;
+ dns_rdataset_current(rdataset, &rdata1);
+ dns_rdataset_clone(rdataset, &tmprdataset);
+ for (result = dns_rdataset_first(&tmprdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&tmprdataset)) {
+ dns_rdata_t rdata2 = DNS_RDATA_INIT;
+ count2++;
+ if (count1 >= count2)
+ continue;
+ dns_rdataset_current(&tmprdataset, &rdata2);
+ if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
+ if (format) {
+ dns_name_format(owner, ownerbuf,
+ sizeof ownerbuf);
+ dns_rdatatype_format(rdata1.type,
+ typebuf,
+ sizeof(typebuf));
+ format = ISC_FALSE;
+ }
+ dns_zone_log(zone, level, "%s/%s has "
+ "semantically identical records",
+ ownerbuf, typebuf);
+ if (level == ISC_LOG_ERROR)
+ answer = ISC_FALSE;
+ break;
+ }
+ }
+ dns_rdataset_disassociate(&tmprdataset);
+ if (!format)
+ break;
+ }
+ return (answer);
+}
+
+static isc_boolean_t
+zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
+ dns_dbiterator_t *dbiterator = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ dns_rdataset_t rdataset;
+ dns_rdatasetiter_t *rdsit = NULL;
+ isc_boolean_t ok = ISC_TRUE;
+ isc_result_t result;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_createiterator(db, 0, &dbiterator);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_TRUE);
+
+ for (result = dns_dbiterator_first(dbiterator);
+ result == ISC_R_SUCCESS;
+ result = dns_dbiterator_next(dbiterator)) {
+ result = dns_dbiterator_current(dbiterator, &node, name);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ for (result = dns_rdatasetiter_first(rdsit);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsit)) {
+ dns_rdatasetiter_current(rdsit, &rdataset);
+ if (!zone_rrset_check_dup(zone, name, &rdataset))
+ ok = ISC_FALSE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ dns_rdatasetiter_destroy(&rdsit);
+ dns_db_detachnode(db, &node);
+ }
+
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_dbiterator_destroy(&dbiterator);
+
+ return (ok);
+}
+
+static isc_boolean_t
integrity_checks(dns_zone_t *zone, dns_db_t *db) {
dns_dbiterator_t *dbiterator = NULL;
dns_dbnode_t *node = NULL;
@@ -2052,6 +2219,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
result = dns_rdataset_next(&rdataset);
}
dns_rdataset_disassociate(&rdataset);
+ goto next;
checkmx:
result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
@@ -2104,7 +2272,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
/*
* OpenSSL verification of RSA keys with exponent 3 is known to be
- * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
+ * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
* if they are in use.
*/
static void
@@ -2168,7 +2336,6 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
dns_db_detachnode(db, &node);
if (version != NULL)
dns_db_closeversion(db, &version, ISC_FALSE);
-
}
static void
@@ -2189,15 +2356,18 @@ resume_signingwithkey(dns_zone_t *zone) {
zone->privatetype,
dns_rdatatype_none, 0,
&rdataset, NULL);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
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) {
+ if (rdata.length != 5 ||
+ rdata.data[0] == 0 || rdata.data[4] != 0) {
dns_rdata_reset(&rdata);
continue;
}
@@ -2219,7 +2389,6 @@ resume_signingwithkey(dns_zone_t *zone) {
dns_db_detachnode(zone->db, &node);
if (version != NULL)
dns_db_closeversion(zone->db, &version, ISC_FALSE);
-
}
static isc_result_t
@@ -2228,6 +2397,9 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
isc_result_t result;
isc_time_t now;
unsigned int options = 0;
+ char saltbuf[255*2+1];
+ char flags[sizeof("REMOVE|CREATE|NONSEC|OPTOUT")];
+ int i;
nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
if (nsec3chain == NULL)
@@ -2249,6 +2421,40 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
nsec3chain->delete_nsec = ISC_FALSE;
nsec3chain->save_delete_nsec = ISC_FALSE;
+ if (nsec3param->flags == 0)
+ strlcpy(flags, "NONE", sizeof(flags));
+ else {
+ flags[0] = '\0';
+ if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
+ strlcat(flags, "REMOVE", sizeof(flags));
+ if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
+ if (flags[0] == '\0')
+ strlcpy(flags, "CREATE", sizeof(flags));
+ else
+ strlcat(flags, "|CREATE", sizeof(flags));
+ }
+ if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
+ if (flags[0] == '\0')
+ strlcpy(flags, "NONSEC", sizeof(flags));
+ else
+ strlcat(flags, "|NONSEC", sizeof(flags));
+ }
+ if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
+ if (flags[0] == '\0')
+ strlcpy(flags, "OPTOUT", sizeof(flags));
+ else
+ strlcat(flags, "|OPTOUT", sizeof(flags));
+ }
+ }
+ if (nsec3param->salt_length == 0)
+ strlcpy(saltbuf, "-", sizeof(saltbuf));
+ else
+ for (i = 0; i < nsec3param->salt_length; i++)
+ sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
+ dns_zone_log(zone, ISC_LOG_INFO,
+ "zone_addnsec3chain(%u,%s,%u,%s)",
+ nsec3param->hash, flags, nsec3param->iterations,
+ saltbuf);
for (current = ISC_LIST_HEAD(zone->nsec3chain);
current != NULL;
current = ISC_LIST_NEXT(current, link)) {
@@ -2298,11 +2504,13 @@ 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;
+ if (zone->privatetype == 0)
+ return;
+
result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
if (result != ISC_R_SUCCESS)
goto cleanup;
@@ -2310,17 +2518,25 @@ resume_addnsec3chain(dns_zone_t *zone) {
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)
+ zone->privatetype, dns_rdatatype_none,
+ 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
goto cleanup;
+ }
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset))
{
- dns_rdataset_current(&rdataset, &rdata);
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t private = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&rdataset, &private);
+ if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
+ sizeof(buf)))
+ continue;
result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
@@ -2332,10 +2548,8 @@ resume_addnsec3chain(dns_zone_t *zone) {
dns_result_totext(result));
}
}
- dns_rdata_reset(&rdata);
}
dns_rdataset_disassociate(&rdataset);
-
cleanup:
if (node != NULL)
dns_db_detachnode(zone->db, &node);
@@ -2353,8 +2567,8 @@ set_resigntime(dns_zone_t *zone) {
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
- result = dns_db_getsigningtime(zone->db, &rdataset,
- dns_fixedname_name(&fixed));
+ result = dns_db_getsigningtime(zone->db, &rdataset,
+ dns_fixedname_name(&fixed));
if (result != ISC_R_SUCCESS) {
isc_time_settoepoch(&zone->resigntime);
return;
@@ -2392,10 +2606,12 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
dns_rdatatype_nsec3param,
dns_rdatatype_none, 0, &rdataset, NULL);
if (result == ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
result = ISC_R_SUCCESS;
goto cleanup;
}
if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
dns_zone_log(zone, ISC_LOG_ERROR,
"nsec3param lookup failure: %s",
dns_result_totext(result));
@@ -2456,6 +2672,642 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
return (result);
}
+/*
+ * Set the timer for refreshing the key zone to the soonest future time
+ * of the set (current timer, keydata->refresh, keydata->addhd,
+ * keydata->removehd).
+ */
+static void
+set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
+ isc_stdtime_t now) {
+ const char me[] = "set_refreshkeytimer";
+ isc_stdtime_t then;
+ isc_time_t timenow, timethen;
+ char timebuf[80];
+
+ ENTER;
+ then = key->refresh;
+ if (key->addhd > now && key->addhd < then)
+ then = key->addhd;
+ if (key->removehd > now && key->removehd < then)
+ then = key->removehd;
+
+ TIME_NOW(&timenow);
+ if (then > now)
+ DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
+ else
+ timethen = timenow;
+ if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
+ isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
+ zone->refreshkeytime = timethen;
+
+ isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
+ dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
+ zone_settimer(zone, &timenow);
+}
+
+/*
+ * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
+ * If the key zone is changed, set '*changed' to ISC_TRUE.
+ */
+static isc_result_t
+create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff, dns_keytable_t *keytable,
+ dns_keynode_t **keynodep, isc_boolean_t *changed)
+{
+ const char me[] = "create_keydata";
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_buffer_t keyb, dstb;
+ unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
+ dns_rdata_keydata_t keydata;
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_keynode_t *keynode;
+ isc_stdtime_t now;
+ isc_region_t r;
+ dst_key_t *key;
+
+ REQUIRE(keynodep != NULL);
+ keynode = *keynodep;
+
+ ENTER;
+ isc_stdtime_get(&now);
+
+ /* Loop in case there's more than one key. */
+ while (result == ISC_R_SUCCESS) {
+ dns_keynode_t *nextnode = NULL;
+
+ key = dns_keynode_key(keynode);
+ if (key == NULL)
+ goto skip;
+
+ isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
+ CHECK(dst_key_todns(key, &dstb));
+
+ /* Convert DST key to DNSKEY. */
+ dns_rdata_reset(&rdata);
+ isc_buffer_usedregion(&dstb, &r);
+ dns_rdata_fromregion(&rdata, dst_key_class(key),
+ dns_rdatatype_dnskey, &r);
+
+ /* DSTKEY to KEYDATA. */
+ CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
+ CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
+ NULL));
+
+ /* KEYDATA to rdata. */
+ dns_rdata_reset(&rdata);
+ isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+ CHECK(dns_rdata_fromstruct(&rdata,
+ zone->rdclass, dns_rdatatype_keydata,
+ &keydata, &keyb));
+
+ /* Add rdata to zone. */
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
+ dst_key_name(key), 0, &rdata));
+ *changed = ISC_TRUE;
+
+ skip:
+ result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
+ if (result != ISC_R_NOTFOUND) {
+ dns_keytable_detachkeynode(keytable, &keynode);
+ keynode = nextnode;
+ }
+ }
+
+ /* Refresh new keys from the zone apex as soon as possible. */
+ if (*changed)
+ set_refreshkeytimer(zone, &keydata, now);
+
+ if (keynode != NULL)
+ dns_keytable_detachkeynode(keytable, &keynode);
+ *keynodep = NULL;
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ return (result);
+}
+
+/*
+ * Remove from the key zone all the KEYDATA records found in rdataset.
+ */
+static isc_result_t
+delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
+ dns_name_t *name, dns_rdataset_t *rdataset)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result, uresult;
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
+ name, 0, &rdata);
+ if (uresult != ISC_R_SUCCESS)
+ return (uresult);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+/*
+ * Compute the DNSSEC key ID for a DNSKEY record.
+ */
+static isc_result_t
+compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
+ dns_keytag_t *tag)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned char data[4096];
+ isc_buffer_t buffer;
+ dst_key_t *dstkey = NULL;
+
+ isc_buffer_init(&buffer, data, sizeof(data));
+ dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
+ dns_rdatatype_dnskey, dnskey, &buffer);
+
+ result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
+ if (result == ISC_R_SUCCESS)
+ *tag = dst_key_id(dstkey);
+ dst_key_free(&dstkey);
+
+ return (result);
+}
+
+/*
+ * Add key to the security roots for all views.
+ */
+static void
+trust_key(dns_viewlist_t *viewlist, dns_name_t *keyname,
+ dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned char data[4096];
+ isc_buffer_t buffer;
+ dns_view_t *view;
+ dns_keytable_t *sr = NULL;
+ dst_key_t *dstkey = NULL;
+
+ /* Convert dnskey to DST key. */
+ isc_buffer_init(&buffer, data, sizeof(data));
+ dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
+ dns_rdatatype_dnskey, dnskey, &buffer);
+
+ for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+
+ result = dns_view_getsecroots(view, &sr);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
+ CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
+ dns_keytable_detach(&sr);
+ }
+
+ failure:
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+ if (sr != NULL)
+ dns_keytable_detach(&sr);
+ return;
+}
+
+/*
+ * Remove key from the security roots for all views.
+ */
+static void
+untrust_key(dns_viewlist_t *viewlist, dns_name_t *keyname, isc_mem_t *mctx,
+ dns_rdata_dnskey_t *dnskey)
+{
+ dns_view_t *view;
+
+ for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ dns_view_untrust(view, keyname, dnskey, mctx);
+}
+
+/*
+ * Add a null key to the security roots for all views, so that all queries
+ * to the zone will fail.
+ */
+static void
+fail_secure(dns_viewlist_t *viewlist, dns_name_t *keyname) {
+ isc_result_t result;
+ dns_view_t *view;
+
+ for (view = ISC_LIST_HEAD(*viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ dns_keytable_t *sr = NULL;
+
+ result = dns_view_getsecroots(view, &sr);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ dns_keytable_marksecure(sr, keyname);
+ dns_keytable_detach(&sr);
+ }
+}
+
+/*
+ * Scan a set of KEYDATA records from the key zone. The ones that are
+ * valid (i.e., the add holddown timer has expired) become trusted keys for
+ * all views.
+ */
+static void
+load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_keydata_t keydata;
+ dns_rdata_dnskey_t dnskey;
+ isc_mem_t *mctx = zone->mctx;
+ dns_view_t *view = zone->view;
+ dns_viewlist_t *viewlist = view->viewlist;
+ int trusted = 0, revoked = 0, pending = 0;
+ isc_stdtime_t now;
+
+ isc_stdtime_get(&now);
+
+ /* For each view, delete references to this key from secroots. */
+ for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ dns_keytable_t *sr = NULL;
+
+ result = dns_view_getsecroots(view, &sr);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ dns_keytable_delete(sr, name);
+ dns_keytable_detach(&sr);
+ }
+
+ /* Now insert all the accepted trust anchors from this keydata set. */
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+
+ /* Convert rdata to keydata. */
+ dns_rdata_tostruct(&rdata, &keydata, NULL);
+
+ /* Set the key refresh timer. */
+ set_refreshkeytimer(zone, &keydata, now);
+
+ /* If the removal timer is nonzero, this key was revoked. */
+ if (keydata.removehd != 0) {
+ revoked++;
+ continue;
+ }
+
+ /*
+ * If the add timer is still pending, this key is not
+ * trusted yet.
+ */
+ if (now < keydata.addhd) {
+ pending++;
+ continue;
+ }
+
+ /* Convert keydata to dnskey. */
+ dns_keydata_todnskey(&keydata, &dnskey, NULL);
+
+ /* Add to keytables. */
+ trusted++;
+ trust_key(viewlist, name, &dnskey, mctx);
+ }
+
+ if (trusted == 0 && pending != 0) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namebuf, sizeof namebuf);
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "No valid trust anchors for '%s'!", namebuf);
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%d key(s) revoked, %d still pending",
+ revoked, pending);
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "All queries to '%s' will fail", namebuf);
+ fail_secure(viewlist, name);
+ }
+}
+
+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
+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_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);
+}
+
+/*
+ * Write all transactions in 'diff' to the zone journal file.
+ */
+static isc_result_t
+zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) {
+ const char me[] = "zone_journal";
+ const char *journalfile;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_journal_t *journal = NULL;
+
+ ENTER;
+ journalfile = dns_zone_getjournal(zone);
+ if (journalfile != NULL) {
+ result = dns_journal_open(zone->mctx, journalfile,
+ ISC_TRUE, &journal);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s:dns_journal_open -> %s\n",
+ caller, dns_result_totext(result));
+ return (result);
+ }
+
+ result = dns_journal_write_transaction(journal, diff);
+ dns_journal_destroy(&journal);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s:dns_journal_write_transaction -> %s\n",
+ caller, dns_result_totext(result));
+ return (result);
+ }
+ }
+ return (result);
+}
+
+/*
+ * Create an SOA record for a newly-created zone
+ */
+static isc_result_t
+add_soa(dns_zone_t *zone, dns_db_t *db) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned char buf[DNS_SOA_BUFFERSIZE];
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff;
+
+ dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
+
+ dns_diff_init(zone->mctx, &diff);
+ result = dns_db_newversion(db, &ver);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "add_soa:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ /* Build SOA record */
+ result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
+ 0, 0, 0, 0, 0, buf, &rdata);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "add_soa:dns_soa_buildrdata -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
+ &zone->origin, 0, &rdata);
+
+failure:
+ dns_diff_clear(&diff);
+ if (ver != NULL)
+ dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
+
+ return (result);
+}
+
+/*
+ * Synchronize the set of initializing keys found in managed-keys {}
+ * statements with the set of trust anchors found in the managed-keys.bind
+ * zone. If a domain is no longer named in managed-keys, delete all keys
+ * from that domain from the key zone. If a domain is mentioned in in
+ * managed-keys but there are no references to it in the key zone, load
+ * the key zone with the initializing key(s) for that domain.
+ */
+static isc_result_t
+sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t changed = ISC_FALSE;
+ dns_rbtnodechain_t chain;
+ dns_fixedname_t fn;
+ dns_name_t foundname, *origin;
+ dns_keynode_t *keynode = NULL;
+ dns_view_t *view = zone->view;
+ dns_keytable_t *sr = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff;
+ dns_rriterator_t rrit;
+
+ dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
+
+ dns_name_init(&foundname, NULL);
+ dns_fixedname_init(&fn);
+ origin = dns_fixedname_name(&fn);
+
+ dns_diff_init(zone->mctx, &diff);
+
+ CHECK(dns_view_getsecroots(view, &sr));
+
+ result = dns_db_newversion(db, &ver);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "sync_keyzone:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ /*
+ * Walk the zone DB. If we find any keys whose names are no longer
+ * in managed-keys (or *are* in trusted-keys, meaning they are
+ * permanent and not RFC5011-maintained), delete them from the
+ * zone. Otherwise call load_secroots(), which loads keys into
+ * secroots as appropriate.
+ */
+ dns_rriterator_init(&rrit, db, ver, 0);
+ for (result = dns_rriterator_first(&rrit);
+ result == ISC_R_SUCCESS;
+ result = dns_rriterator_nextrrset(&rrit)) {
+ dns_rdataset_t *rdataset;
+ dns_name_t *rrname = NULL;
+ isc_uint32_t ttl;
+
+ dns_rriterator_current(&rrit, &rrname, &ttl,
+ &rdataset, NULL);
+ if (!dns_rdataset_isassociated(rdataset)) {
+ dns_rriterator_destroy(&rrit);
+ goto failure;
+ }
+
+ if (rdataset->type != dns_rdatatype_keydata)
+ continue;
+
+ result = dns_keytable_find(sr, rrname, &keynode);
+ if ((result != ISC_R_SUCCESS &&
+ result != DNS_R_PARTIALMATCH) ||
+ dns_keynode_managed(keynode) == ISC_FALSE) {
+ CHECK(delete_keydata(db, ver, &diff,
+ rrname, rdataset));
+ changed = ISC_TRUE;
+ } else {
+ load_secroots(zone, rrname, rdataset);
+ }
+
+ if (keynode != NULL)
+ dns_keytable_detachkeynode(sr, &keynode);
+ }
+ dns_rriterator_destroy(&rrit);
+
+ /*
+ * Now walk secroots to find any managed keys that aren't
+ * in the zone. If we find any, we add them to the zone.
+ */
+ RWLOCK(&sr->rwlock, isc_rwlocktype_write);
+ dns_rbtnodechain_init(&chain, zone->mctx);
+ result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_NOMORE;
+ while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
+ dns_rbtnode_t *rbtnode = NULL;
+
+ dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
+ if (rbtnode->data == NULL)
+ goto skip;
+
+ dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
+ if (dns_keynode_managed(keynode)) {
+ dns_fixedname_t fname;
+ dns_name_t *keyname;
+ dst_key_t *key;
+
+ key = dns_keynode_key(keynode);
+ dns_fixedname_init(&fname);
+
+ if (key == NULL) /* fail_secure() was called. */
+ goto skip;
+
+ keyname = dst_key_name(key);
+ result = dns_db_find(db, keyname, ver,
+ dns_rdatatype_keydata,
+ DNS_DBFIND_NOWILD, 0, NULL,
+ dns_fixedname_name(&fname),
+ NULL, NULL);
+ if (result != ISC_R_SUCCESS)
+ result = create_keydata(zone, db, ver, &diff,
+ sr, &keynode, &changed);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ skip:
+ result = dns_rbtnodechain_next(&chain, &foundname, origin);
+ if (keynode != NULL)
+ dns_keytable_detachkeynode(sr, &keynode);
+ }
+ RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ if (changed) {
+ /* Write changes to journal file. */
+ result = increment_soa_serial(db, ver, &diff, zone->mctx);
+ if (result == ISC_R_SUCCESS)
+ zone_journal(zone, &diff, "sync_keyzone");
+
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
+ zone_needdump(zone, 30);
+ }
+
+ failure:
+ if (keynode != NULL)
+ dns_keytable_detachkeynode(sr, &keynode);
+ if (sr != NULL)
+ dns_keytable_detach(&sr);
+ if (ver != NULL)
+ dns_db_closeversion(db, &ver, changed);
+ dns_diff_clear(&diff);
+
+ return (result);
+}
+
static isc_result_t
zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
isc_result_t result)
@@ -2467,6 +3319,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);
+ isc_boolean_t nomaster = ISC_FALSE;
unsigned int options;
TIME_NOW(&now);
@@ -2488,12 +3341,16 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
"failed: %s",
zone->masterfile,
dns_result_totext(result));
- } else
+ } else {
dns_zone_log(zone, ISC_LOG_ERROR,
"loading from master file %s failed: %s",
zone->masterfile,
dns_result_totext(result));
- goto cleanup;
+ nomaster = ISC_TRUE;
+ }
+
+ if (zone->type != dns_zone_key)
+ goto cleanup;
}
dns_zone_log(zone, ISC_LOG_DEBUG(2),
@@ -2506,6 +3363,18 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
/*
+ * If there's no master file for a key zone, then the zone is new:
+ * create an SOA record. (We do this now, instead of later, so that
+ * if there happens to be a journal file, we can roll forward from
+ * a sane starting point.)
+ */
+ if (nomaster && zone->type == dns_zone_key) {
+ result = add_soa(zone, db);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ /*
* Apply update log, if any, on initial load.
*/
if (zone->journal != NULL &&
@@ -2552,7 +3421,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
&refresh, &retry, &expire, &minimum,
&errors);
- if (result != ISC_R_SUCCESS) {
+ if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
dns_zone_log(zone, ISC_LOG_ERROR,
"could not find NS and/or SOA records");
}
@@ -2563,6 +3432,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
*/
switch (zone->type) {
+ case dns_zone_dlz:
case dns_zone_master:
case dns_zone_slave:
case dns_zone_stub:
@@ -2594,6 +3464,13 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
goto cleanup;
}
+ if (zone->type == dns_zone_master &&
+ DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
+ !zone_check_dup(zone, db)) {
+ result = DNS_R_BADZONE;
+ goto cleanup;
+ }
+
if (zone->db != NULL) {
/*
* This is checked in zone_replacedb() for slave zones
@@ -2621,12 +3498,13 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
goto cleanup;
} else if (!isc_serial_ge(serial, oldserial))
dns_zone_log(zone, ISC_LOG_ERROR,
- "zone serial has gone backwards");
+ "zone serial (%u/%u) has gone "
+ "backwards", serial, oldserial);
else if (serial == oldserial && !hasinclude)
dns_zone_log(zone, ISC_LOG_ERROR,
- "zone serial unchanged. "
+ "zone serial (%u) unchanged. "
"zone may fail to transfer "
- "to slaves.");
+ "to slaves.", serial);
}
if (zone->type == dns_zone_master &&
@@ -2672,6 +3550,13 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
zone->refreshtime = now;
}
break;
+
+ case dns_zone_key:
+ result = sync_keyzone(zone, db);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ break;
+
default:
UNEXPECTED_ERROR(__FILE__, __LINE__,
"unexpected zone type %d", zone->type);
@@ -2685,6 +3570,13 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
if (zone->type == dns_zone_master)
zone_check_dnskeys(zone, db);
+ /*
+ * Schedule DNSSEC key refresh.
+ */
+ if (zone->type == dns_zone_master &&
+ DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
+ zone->refreshkeytime = now;
+
#if 0
/* destroy notification example. */
{
@@ -2709,9 +3601,16 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
DNS_ZONE_SETFLAG(zone,
DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
}
+
result = ISC_R_SUCCESS;
- if (needdump)
- zone_needdump(zone, DNS_DUMP_DELAY);
+
+ if (needdump) {
+ if (zone->type == dns_zone_key)
+ zone_needdump(zone, 30);
+ else
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ }
+
if (zone->task != NULL) {
if (zone->type == dns_zone_master) {
set_resigntime(zone);
@@ -2723,13 +3622,14 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
if (! dns_db_ispersistent(db))
dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
- dns_db_issecure(db) ? " (signed)" : "");
+ dns_db_issecure(db) ? " (DNSSEC signed)" : "");
return (result);
cleanup:
if (zone->type == dns_zone_slave ||
- zone->type == dns_zone_stub) {
+ zone->type == dns_zone_stub ||
+ zone->type == dns_zone_key) {
if (zone->journal != NULL)
zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
if (zone->masterfile != NULL)
@@ -2763,7 +3663,9 @@ exit_check(dns_zone_t *zone) {
}
static isc_boolean_t
-zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
+zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, isc_boolean_t logit)
+{
isc_result_t result;
char namebuf[DNS_NAME_FORMATSIZE];
char altbuf[DNS_NAME_FORMATSIZE];
@@ -2782,42 +3684,45 @@ zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
dns_fixedname_init(&fixed);
foundname = dns_fixedname_name(&fixed);
- result = dns_db_find(db, name, NULL, dns_rdatatype_a,
+ result = dns_db_find(db, name, version, dns_rdatatype_a,
0, 0, NULL, foundname, NULL, NULL);
if (result == ISC_R_SUCCESS)
return (ISC_TRUE);
if (result == DNS_R_NXRRSET) {
- result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
+ result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
0, 0, NULL, foundname, NULL, NULL);
if (result == ISC_R_SUCCESS)
return (ISC_TRUE);
}
- dns_name_format(name, namebuf, sizeof namebuf);
if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
result == DNS_R_EMPTYNAME) {
- dns_zone_log(zone, level,
- "NS '%s' has no address records (A or AAAA)",
- namebuf);
- /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
- return (ISC_TRUE);
+ if (logit) {
+ dns_name_format(name, namebuf, sizeof namebuf);
+ dns_zone_log(zone, level, "NS '%s' has no address "
+ "records (A or AAAA)", namebuf);
+ }
+ return (ISC_FALSE);
}
if (result == DNS_R_CNAME) {
- dns_zone_log(zone, level, "NS '%s' is a CNAME (illegal)",
- namebuf);
- /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
- return (ISC_TRUE);
+ if (logit) {
+ dns_name_format(name, namebuf, sizeof namebuf);
+ dns_zone_log(zone, level, "NS '%s' is a CNAME "
+ "(illegal)", namebuf);
+ }
+ return (ISC_FALSE);
}
if (result == DNS_R_DNAME) {
- dns_name_format(foundname, altbuf, sizeof altbuf);
- dns_zone_log(zone, level,
- "NS '%s' is below a DNAME '%s' (illegal)",
- namebuf, altbuf);
- /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
- return (ISC_TRUE);
+ if (logit) {
+ dns_name_format(name, namebuf, sizeof namebuf);
+ dns_name_format(foundname, altbuf, sizeof altbuf);
+ dns_zone_log(zone, level, "NS '%s' is below a DNAME "
+ "'%s' (illegal)", namebuf, altbuf);
+ }
+ return (ISC_FALSE);
}
return (ISC_TRUE);
@@ -2826,7 +3731,7 @@ zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
static isc_result_t
zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
dns_dbversion_t *version, unsigned int *nscount,
- unsigned int *errors)
+ unsigned int *errors, isc_boolean_t logit)
{
isc_result_t result;
unsigned int count = 0;
@@ -2838,10 +3743,14 @@ zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
dns_rdataset_init(&rdataset);
result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
dns_rdatatype_none, 0, &rdataset, NULL);
- if (result == ISC_R_NOTFOUND)
+ if (result == ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
goto success;
- if (result != ISC_R_SUCCESS)
+ }
+ if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
goto invalidate_rdataset;
+ }
result = dns_rdataset_first(&rdataset);
while (result == ISC_R_SUCCESS) {
@@ -2853,7 +3762,7 @@ zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
result = dns_rdata_tostruct(&rdata, &ns, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (dns_name_issubdomain(&ns.name, &zone->origin) &&
- !zone_check_ns(zone, db, &ns.name))
+ !zone_check_ns(zone, db, version, &ns.name, logit))
ecount++;
}
count++;
@@ -2892,6 +3801,7 @@ zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
dns_rdatatype_none, 0, &rdataset, NULL);
if (result == ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
if (soacount != NULL)
*soacount = 0;
if (serial != NULL)
@@ -2907,8 +3817,10 @@ zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
result = ISC_R_SUCCESS;
goto invalidate_rdataset;
}
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
goto invalidate_rdataset;
+ }
count = 0;
result = dns_rdataset_first(&rdataset);
@@ -2960,15 +3872,14 @@ zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
isc_uint32_t *expire, isc_uint32_t *minimum,
unsigned int *errors)
{
- dns_dbversion_t *version;
isc_result_t result;
isc_result_t answer = ISC_R_SUCCESS;
+ dns_dbversion_t *version = NULL;
dns_dbnode_t *node;
REQUIRE(db != NULL);
REQUIRE(zone != NULL);
- version = NULL;
dns_db_currentversion(db, &version);
node = NULL;
@@ -2980,7 +3891,7 @@ zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
if (nscount != NULL || errors != NULL) {
result = zone_count_ns_rr(zone, db, node, version,
- nscount, errors);
+ nscount, errors, ISC_TRUE);
if (result != ISC_R_SUCCESS)
answer = result;
}
@@ -3028,7 +3939,7 @@ dns_zone_detach(dns_zone_t **zonep) {
*/
if (zone->task != NULL) {
/*
- * This zone is being managed. Post
+ * This zone is being managed. Post
* its control event and let it clean
* up synchronously in the context of
* its task.
@@ -3163,6 +4074,27 @@ dns_zone_getoptions(dns_zone_t *zone) {
return (zone->options);
}
+void
+dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
+{
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (value)
+ zone->keyopts |= keyopt;
+ else
+ zone->keyopts &= ~keyopt;
+ UNLOCK_ZONE(zone);
+}
+
+unsigned int
+dns_zone_getkeyopts(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->keyopts);
+}
+
isc_result_t
dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
REQUIRE(DNS_ZONE_VALID(zone));
@@ -3499,6 +4431,17 @@ dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
return (result);
}
+void
+dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(zone->type == dns_zone_staticstub);
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
+ REQUIRE(zone->db == NULL);
+ dns_db_attach(db, &zone->db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
+}
+
/*
* Co-ordinates the starting of routine jobs.
*/
@@ -3535,126 +4478,6 @@ was_dumping(dns_zone_t *zone) {
#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)
@@ -3752,10 +4575,14 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
(isc_stdtime_t) 0, &rdataset, NULL);
dns_db_detachnode(db, &node);
- if (result == ISC_R_NOTFOUND)
+ if (result == ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
return (ISC_R_SUCCESS);
- if (result != ISC_R_SUCCESS)
+ }
+ if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
goto failure;
+ }
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
@@ -3841,7 +4668,8 @@ 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_stdtime_t expire, isc_boolean_t check_ksk,
+ isc_boolean_t keyset_kskonly)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
@@ -3849,7 +4677,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_rdata_t sig_rdata = DNS_RDATA_INIT;
unsigned char data[1024]; /* XXX */
isc_buffer_t buffer;
- unsigned int i;
+ unsigned int i, j;
dns_rdataset_init(&rdataset);
isc_buffer_init(&buffer, data, sizeof(data));
@@ -3865,18 +4693,59 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
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)
+ if (result == ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
return (ISC_R_SUCCESS);
- if (result != ISC_R_SUCCESS)
+ }
+ if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
goto failure;
+ }
+
+#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
+#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
+#define ALG(x) dst_key_alg(x)
for (i = 0; i < nkeys; i++) {
- if (check_ksk && type != dns_rdatatype_dnskey &&
- (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
- continue;
+ isc_boolean_t both = ISC_FALSE;
+
if (!dst_key_isprivate(keys[i]))
continue;
+
+ if (check_ksk && !REVOKE(keys[i])) {
+ isc_boolean_t have_ksk, have_nonksk;
+ if (KSK(keys[i])) {
+ have_ksk = ISC_TRUE;
+ have_nonksk = ISC_FALSE;
+ } else {
+ have_ksk = ISC_FALSE;
+ have_nonksk = ISC_TRUE;
+ }
+ for (j = 0; j < nkeys; j++) {
+ if (j == i || ALG(keys[i]) != ALG(keys[j]))
+ continue;
+ if (REVOKE(keys[j]))
+ continue;
+ if (KSK(keys[j]))
+ have_ksk = ISC_TRUE;
+ else
+ have_nonksk = ISC_TRUE;
+ both = have_ksk && have_nonksk;
+ if (both)
+ break;
+ }
+ }
+ if (both) {
+ if (type == dns_rdatatype_dnskey) {
+ if (!KSK(keys[i]) && keyset_kskonly)
+ continue;
+ } else if (KSK(keys[i]))
+ continue;
+ } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
+ continue;
+
/* Calculate the signature, creating a RRSIG RDATA. */
+ isc_buffer_clear(&buffer);
CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
&inception, &expire,
mctx, &buffer, &sig_rdata));
@@ -3898,7 +4767,6 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
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;
@@ -3907,7 +4775,7 @@ zone_resigninc(dns_zone_t *zone) {
dns_rdataset_t rdataset;
dns_rdatatype_t covers;
dst_key_t *zone_keys[MAXZONEKEYS];
- isc_boolean_t check_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
isc_result_t result;
isc_stdtime_t now, inception, soaexpire, expire, stop;
isc_uint32_t jitter;
@@ -3962,8 +4830,7 @@ zone_resigninc(dns_zone_t *zone) {
stop = now + 5;
check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
- if (check_ksk)
- check_ksk = ksk_sanity(db, version);
+ keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
name = dns_fixedname_name(&fixed);
result = dns_db_getsigningtime(db, &rdataset, name);
@@ -4007,14 +4874,14 @@ zone_resigninc(dns_zone_t *zone) {
}
result = add_sigs(db, version, name, covers, &sig_diff,
zone_keys, nkeys, zone->mctx, inception,
- expire, check_ksk);
+ expire, check_ksk, keyset_kskonly);
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,
+ result = dns_db_getsigningtime(db, &rdataset,
dns_fixedname_name(&fixed));
if (nkeys == 0 && result == ISC_R_NOTFOUND) {
result = ISC_R_SUCCESS;
@@ -4052,7 +4919,7 @@ zone_resigninc(dns_zone_t *zone) {
*/
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
&sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk);
+ soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_resigninc:add_sigs -> %s\n",
@@ -4060,31 +4927,10 @@ zone_resigninc(dns_zone_t *zone) {
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;
- }
- }
+ /* Write changes to journal file. */
+ zone_journal(zone, &sig_diff, "zone_resigninc");
- /*
- * Everything has succeeded. Commit the changes.
- */
+ /* Everything has succeeded. Commit the changes. */
dns_db_closeversion(db, &version, ISC_TRUE);
failure:
@@ -4151,16 +4997,6 @@ next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
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)
@@ -4173,8 +5009,10 @@ signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_rdataset_init(&rdataset);
result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
type, 0, &rdataset, NULL);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
return (ISC_FALSE);
+ }
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
@@ -4209,21 +5047,6 @@ add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
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:
@@ -4236,8 +5059,8 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
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_boolean_t keyset_kskonly, 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;
@@ -4255,6 +5078,7 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
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 =
@@ -4275,7 +5099,8 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
seen_nsec = ISC_TRUE;
else if (rdataset.type == dns_rdatatype_nsec3)
seen_nsec3 = ISC_TRUE;
- seen_rr = ISC_TRUE;
+ if (rdataset.type != dns_rdatatype_rrsig)
+ seen_rr = ISC_TRUE;
dns_rdataset_disassociate(&rdataset);
}
if (result != ISC_R_NOMORE)
@@ -4299,9 +5124,15 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
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)--;
+ /*
+ * Build a NSEC record except at the origin.
+ */
+ if (!dns_name_equal(name, dns_db_origin(db))) {
+ 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) {
@@ -4309,7 +5140,10 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
if (rdataset.type == dns_rdatatype_soa ||
rdataset.type == dns_rdatatype_rrsig)
goto next_rdataset;
- if (is_ksk && rdataset.type != dns_rdatatype_dnskey)
+ if (rdataset.type == dns_rdatatype_dnskey) {
+ if (!is_ksk && keyset_kskonly)
+ goto next_rdataset;
+ } else if (is_ksk)
goto next_rdataset;
if (*delegation &&
rdataset.type != dns_rdatatype_ds &&
@@ -4318,6 +5152,7 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
if (signed_with_key(db, node, version, rdataset.type, key))
goto next_rdataset;
/* Calculate the signature, creating a RRSIG RDATA. */
+ isc_buffer_clear(&buffer);
CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
&expire, mctx, &buffer, &rdata));
/* Update the database and journal with the RRSIG. */
@@ -4334,7 +5169,7 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
result = ISC_R_SUCCESS;
if (seen_dname)
*delegation = ISC_TRUE;
-failure:
+ failure:
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
if (iterator != NULL)
@@ -4342,63 +5177,45 @@ failure:
return (result);
}
+/*
+ * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
+ */
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)
+ dns_ttl_t minimum, isc_boolean_t update_only, 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;
-
+ if (update_only) {
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec,
+ dns_rdatatype_none,
+ 0, &rdataset, NULL);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+ CHECK(delete_nsec(db, version, node, name, diff));
+ CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
+ success:
+ result = ISC_R_SUCCESS;
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)
+updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
+ dns_dbversion_t *version, isc_boolean_t build_nsec3,
+ dns_ttl_t minimum, dns_diff_t *diff)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
@@ -4406,43 +5223,68 @@ updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version,
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned char data[5];
isc_boolean_t seen_done = ISC_FALSE;
+ isc_boolean_t have_rr = 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);
+ result = dns_db_findrdataset(signing->db, node, version,
+ zone->privatetype, dns_rdatatype_none,
+ 0, &rdataset, NULL);
if (result == ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
result = ISC_R_SUCCESS;
goto failure;
}
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
goto failure;
+ }
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
dns_rdataset_current(&rdataset, &rdata);
+ /*
+ * If we don't match the algorithm or keyid skip the record.
+ */
if (rdata.length != 5 ||
rdata.data[0] != signing->algorithm ||
rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
rdata.data[2] != (signing->keyid & 0xff)) {
+ have_rr = ISC_TRUE;
dns_rdata_reset(&rdata);
continue;
}
- if (!signing->delete && rdata.data[4] != 0)
+ /*
+ * We have a match. If we were signing (!signing->delete)
+ * and we already have a record indicating that we have
+ * finished signing (rdata.data[4] != 0) then keep it.
+ * Otherwise it needs to be deleted as we have removed all
+ * the signatures (signing->delete), so any record indicating
+ * completion is now out of date, or we have finished signing
+ * with the new record so we no longer need to remember that
+ * we need to sign the zone with the matching key across a
+ * nameserver re-start.
+ */
+ if (!signing->delete && rdata.data[4] != 0) {
seen_done = ISC_TRUE;
- else
+ have_rr = ISC_TRUE;
+ } else
CHECK(update_one_rr(signing->db, version, diff,
- DNS_DIFFOP_DEL, name,
+ DNS_DIFFOP_DEL, &zone->origin,
rdataset.ttl, &rdata));
dns_rdata_reset(&rdata);
}
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
if (!signing->delete && !seen_done) {
-
+ /*
+ * If we were signing then we need to indicate that we have
+ * finished signing the zone with this key. If it is already
+ * there we don't need to add it a second time.
+ */
data[0] = signing->algorithm;
data[1] = (signing->keyid >> 8) & 0xff;
data[2] = signing->keyid & 0xff;
@@ -4450,11 +5292,23 @@ updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version,
data[4] = 1;
rdata.length = sizeof(data);
rdata.data = data;
- rdata.type = privatetype;
+ rdata.type = zone->privatetype;
rdata.rdclass = dns_db_class(signing->db);
CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
- name, rdataset.ttl, &rdata));
+ &zone->origin, rdataset.ttl, &rdata));
+ } else if (!have_rr) {
+ dns_name_t *origin = dns_db_origin(signing->db);
+ /*
+ * Rebuild the NSEC/NSEC3 record for the origin as we no
+ * longer have any private records.
+ */
+ if (build_nsec3)
+ CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
+ minimum, ISC_FALSE, diff));
+ CHECK(updatesecure(signing->db, version, origin, minimum,
+ ISC_TRUE, diff));
}
+
failure:
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
@@ -4463,9 +5317,15 @@ updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version,
return (result);
}
+/*
+ * If 'active' is set then we are not done with the chain yet so only
+ * delete the nsec3param record which indicates a full chain exists
+ * (flags == 0).
+ */
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)
+ isc_boolean_t active, dns_rdatatype_t privatetype,
+ dns_diff_t *diff)
{
dns_dbnode_t *node = NULL;
dns_name_t *name = dns_db_origin(db);
@@ -4484,7 +5344,7 @@ fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
0, 0, &rdataset, NULL);
if (result == ISC_R_NOTFOUND)
- goto add;
+ goto try_private;
if (result != ISC_R_SUCCESS)
goto failure;
@@ -4520,6 +5380,50 @@ fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
if (result != ISC_R_NOMORE)
goto failure;
+ dns_rdataset_disassociate(&rdataset);
+
+ try_private:
+
+ if (active)
+ goto add;
+ /*
+ * Delete all private records which match that in nsec3chain.
+ */
+ result = dns_db_findrdataset(db, node, ver, privatetype,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto add;
+ 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 private = DNS_RDATA_INIT;
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+
+ dns_rdataset_current(&rdataset, &private);
+ if (!dns_nsec3param_fromprivate(&private, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
+
+ if (nsec3param.hash != chain->nsec3param.hash ||
+ 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, &private));
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
add:
if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
result = ISC_R_SUCCESS;
@@ -4620,7 +5524,7 @@ deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
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)
+ isc_boolean_t *answer)
{
dns_dbnode_t *node = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
@@ -4634,29 +5538,19 @@ need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
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;
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ return (result);
+ }
+ if (result != ISC_R_NOTFOUND) {
+ dns_db_detachnode(db, &node);
+ return (result);
}
- 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) {
@@ -4705,13 +5599,60 @@ need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
return (result);
}
+static isc_result_t
+update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
+ dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
+ isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
+ isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
+ dns_diff_t *sig_diff)
+{
+ dns_difftuple_t *tuple;
+ isc_result_t result;
+
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_HEAD(diff->tuples)) {
+ result = del_sigs(zone, db, version, &tuple->name,
+ tuple->rdata.type, sig_diff,
+ zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "update_sigs:del_sigs -> %s\n",
+ dns_result_totext(result));
+ return (result);
+ }
+ result = add_sigs(db, version, &tuple->name,
+ tuple->rdata.type, sig_diff,
+ zone_keys, nkeys, zone->mctx, inception,
+ expire, check_ksk, keyset_kskonly);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "update_sigs:add_sigs -> %s\n",
+ dns_result_totext(result));
+ return (result);
+ }
+
+ do {
+ dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
+ while (next != NULL &&
+ (tuple->rdata.type != next->rdata.type ||
+ !dns_name_equal(&tuple->name, &next->name)))
+ next = ISC_LIST_NEXT(next, link);
+ ISC_LIST_UNLINK(diff->tuples, tuple, link);
+ dns_diff_appendminimal(sig_diff, &tuple);
+ INSIST(tuple == NULL);
+ tuple = next;
+ } while (tuple != NULL);
+ }
+ return (ISC_R_SUCCESS);
+}
+
/*
* 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;
@@ -4727,7 +5668,7 @@ zone_nsec3chain(dns_zone_t *zone) {
dns_nsec3chainlist_t cleanup;
dst_key_t *zone_keys[MAXZONEKEYS];
isc_int32_t signatures;
- isc_boolean_t check_ksk, is_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
isc_boolean_t delegation;
isc_boolean_t first;
isc_result_t result;
@@ -4740,9 +5681,9 @@ zone_nsec3chain(dns_zone_t *zone) {
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_rdatatype_t privatetype = zone->privatetype;
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
@@ -4799,8 +5740,7 @@ zone_nsec3chain(dns_zone_t *zone) {
stop = now + 5;
check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
- if (check_ksk)
- check_ksk = ksk_sanity(db, version);
+ keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
/*
* We keep pulling nodes off each iterator in turn until
@@ -4924,9 +5864,17 @@ zone_nsec3chain(dns_zone_t *zone) {
* Process one node.
*/
dns_dbiterator_pause(nsec3chain->dbiterator);
- CHECK(dns_nsec3_addnsec3(db, version, name,
- &nsec3chain->nsec3param,
- zone->minimum, unsecure, &nsec3_diff));
+ result = dns_nsec3_addnsec3(db, version, name,
+ &nsec3chain->nsec3param,
+ zone->minimum, unsecure,
+ &nsec3_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "dns_nsec3_addnsec3 -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
/*
* Treat each call to dns_nsec3_addnsec3() as if it's cost is
* two signatures. Additionally there will, in general, be
@@ -4948,7 +5896,8 @@ zone_nsec3chain(dns_zone_t *zone) {
if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
CHECK(fixup_nsec3param(db, version, nsec3chain,
- ISC_FALSE, &param_diff));
+ ISC_FALSE, privatetype,
+ &param_diff));
LOCK_ZONE(zone);
ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
link);
@@ -4962,12 +5911,14 @@ zone_nsec3chain(dns_zone_t *zone) {
CHECK(fixup_nsec3param(db, version,
nsec3chain,
ISC_TRUE,
+ privatetype,
&param_diff));
nsec3chain->delete_nsec = ISC_TRUE;
goto same_addchain;
}
CHECK(fixup_nsec3param(db, version, nsec3chain,
- ISC_FALSE, &param_diff));
+ ISC_FALSE, privatetype,
+ &param_diff));
LOCK_ZONE(zone);
ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
link);
@@ -5028,10 +5979,22 @@ zone_nsec3chain(dns_zone_t *zone) {
* 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));
+ (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) {
+ result = need_nsec_chain(db, version,
+ &nsec3chain->nsec3param,
+ &buildnsecchain);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "need_nsec_chain -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+
+ if (first)
+ dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
+ "buildnsecchain = %u\n", buildnsecchain);
dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
delegation = ISC_FALSE;
@@ -5040,16 +6003,33 @@ zone_nsec3chain(dns_zone_t *zone) {
/*
* Delete the NSECPARAM record that matches this chain.
*/
- if (first)
- CHECK(fixup_nsec3param(db, version, nsec3chain,
- ISC_TRUE, &param_diff));
+ if (first) {
+ result = fixup_nsec3param(db, version,
+ nsec3chain,
+ ISC_TRUE, privatetype,
+ &param_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "fixup_nsec3param -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
/*
* Delete the NSEC3 records.
*/
- CHECK(deletematchingnsec3(db, version, node, name,
- &nsec3chain->nsec3param,
- &nsec3_diff));
+ result = deletematchingnsec3(db, version, node, name,
+ &nsec3chain->nsec3param,
+ &nsec3_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "deletematchingnsec3 -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
goto next_removenode;
}
@@ -5100,7 +6080,8 @@ zone_nsec3chain(dns_zone_t *zone) {
seen_nsec = ISC_TRUE;
else if (rdataset.type == dns_rdatatype_nsec3)
seen_nsec3 = ISC_TRUE;
- seen_rr = ISC_TRUE;
+ if (rdataset.type != dns_rdatatype_rrsig)
+ seen_rr = ISC_TRUE;
dns_rdataset_disassociate(&rdataset);
}
dns_rdatasetiter_destroy(&iterator);
@@ -5110,8 +6091,14 @@ zone_nsec3chain(dns_zone_t *zone) {
if ((seen_ns && !seen_soa) || seen_dname)
delegation = ISC_TRUE;
- CHECK(add_nsec(db, version, name, node, zone->minimum,
- delegation, &nsec_diff));
+ /*
+ * Add a NSEC record except at the origin.
+ */
+ if (!dns_name_equal(name, dns_db_origin(db))) {
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ CHECK(add_nsec(db, version, name, node, zone->minimum,
+ delegation, &nsec_diff));
+ }
next_removenode:
first = ISC_FALSE;
@@ -5133,8 +6120,17 @@ zone_nsec3chain(dns_zone_t *zone) {
UNLOCK_ZONE(zone);
ISC_LIST_APPEND(cleanup, nsec3chain, link);
dns_dbiterator_pause(nsec3chain->dbiterator);
- CHECK(fixup_nsec3param(db, version, nsec3chain,
- ISC_FALSE, &param_diff));
+ result = fixup_nsec3param(db, version,
+ nsec3chain, ISC_FALSE,
+ privatetype,
+ &param_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "fixup_nsec3param -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
goto next_removechain;
} else if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -5166,107 +6162,101 @@ zone_nsec3chain(dns_zone_t *zone) {
}
/*
- * Add / update signatures for the NSEC3 records.
+ * We may need to update the NSEC/NSEC3 records for the zone apex.
*/
- 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;
+ if (!ISC_LIST_EMPTY(param_diff.tuples)) {
+ isc_boolean_t rebuild_nsec = ISC_FALSE,
+ rebuild_nsec3 = ISC_FALSE;
+ result = dns_db_getoriginnode(db, &node);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ 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_nsec)
+ rebuild_nsec = ISC_TRUE;
+ if (rdataset.type == dns_rdatatype_nsec3param)
+ rebuild_nsec3 = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
}
+ dns_rdatasetiter_destroy(&iterator);
+ dns_db_detachnode(db, &node);
- 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;
+ if (rebuild_nsec) {
+ if (nsec3chain != NULL)
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ result = updatesecure(db, version, &zone->origin,
+ zone->minimum, ISC_TRUE,
+ &nsec_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "updatesecure -> %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;
+ if (rebuild_nsec3) {
+ result = dns_nsec3_addnsec3s(db, version,
+ dns_db_origin(db),
+ zone->minimum, ISC_FALSE,
+ &nsec3_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "dns_nsec3_addnsec3s -> %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));
+ /*
+ * Add / update signatures for the NSEC3 records.
+ */
+ result = update_sigs(&nsec3_diff, db, version, zone_keys,
+ nkeys, zone, inception, expire, now,
+ check_ksk, keyset_kskonly, &sig_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "update_sigs -> %s\n", dns_result_totext(result));
+ goto failure;
+ }
- 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);
+ /*
+ * We have changed the NSEC3PARAM or private RRsets
+ * above so we need to update the signatures.
+ */
+ result = update_sigs(&param_diff, db, version, zone_keys,
+ nkeys, zone, inception, expire, now,
+ check_ksk, keyset_kskonly, &sig_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "update_sigs -> %s\n", dns_result_totext(result));
+ goto failure;
+ }
+
+ if (updatensec) {
+ if (nsec3chain != NULL)
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ result = updatesecure(db, version, &zone->origin,
+ zone->minimum, ISC_FALSE, &nsec_diff);
if (result != ISC_R_SUCCESS) {
- dns_zone_log(zone, ISC_LOG_ERROR,
- "zone_nsec3chain:add_sigs -> %s\n",
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "updatesecure -> %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);
+ }
+
+ result = update_sigs(&nsec_diff, db, version, zone_keys,
+ nkeys, zone, inception, expire, now,
+ check_ksk, keyset_kskonly, &sig_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "update_sigs -> %s\n", dns_result_totext(result));
+ goto failure;
}
/*
@@ -5294,34 +6284,15 @@ zone_nsec3chain(dns_zone_t *zone) {
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
&sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk);
+ soaexpire, check_ksk, keyset_kskonly);
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;
- }
- }
+ /* Write changes to journal file. */
+ zone_journal(zone, &sig_diff, "zone_nsec3chain");
LOCK_ZONE(zone);
zone_needdump(zone, DNS_DUMP_DELAY);
@@ -5358,6 +6329,9 @@ zone_nsec3chain(dns_zone_t *zone) {
set_resigntime(zone);
failure:
+ if (result != ISC_R_SUCCESS)
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s\n",
+ dns_result_totext(result));
/*
* On error roll back the current nsec3chain.
*/
@@ -5414,6 +6388,8 @@ zone_nsec3chain(dns_zone_t *zone) {
for (i = 0; i < nkeys; i++)
dst_key_free(&zone_keys[i]);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
if (version != NULL) {
dns_db_closeversion(db, &version, ISC_FALSE);
dns_db_detach(&db);
@@ -5506,11 +6482,11 @@ del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
*/
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_diff_t post_diff;
dns_fixedname_t fixed;
dns_fixedname_t nextfixed;
dns_name_t *name, *nextname;
@@ -5519,19 +6495,19 @@ zone_sign(dns_zone_t *zone) {
dns_signinglist_t cleanup;
dst_key_t *zone_keys[MAXZONEKEYS];
isc_int32_t signatures;
- isc_boolean_t check_ksk, is_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
isc_boolean_t commit = ISC_FALSE;
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 build_nsec = ISC_FALSE;
+ isc_boolean_t build_nsec3 = 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 i, j;
unsigned int nkeys = 0;
isc_uint32_t nodes;
+ isc_boolean_t was_ksk;
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
@@ -5540,6 +6516,7 @@ zone_sign(dns_zone_t *zone) {
nextname = dns_fixedname_name(&nextfixed);
dns_diff_init(zone->mctx, &sig_diff);
sig_diff.resign = zone->sigresigninginterval;
+ dns_diff_init(zone->mctx, &post_diff);
ISC_LIST_INIT(cleanup);
/*
@@ -5584,10 +6561,6 @@ zone_sign(dns_zone_t *zone) {
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
@@ -5597,39 +6570,17 @@ zone_sign(dns_zone_t *zone) {
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) {
+
+ check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
+ keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
+
+ /* Determine which type of chain to build */
+ CHECK(dns_private_chains(db, version, zone->privatetype,
+ &build_nsec, &build_nsec3));
+
+ /* If neither chain is found, default to NSEC */
+ if (!build_nsec && !build_nsec3)
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);
@@ -5637,7 +6588,7 @@ zone_sign(dns_zone_t *zone) {
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
if (signing->done || signing->db != zone->db) {
/*
- * The zone has been reloaded. We will have
+ * The zone has been reloaded. We will have
* created new signings as part of the reload
* process so we can destroy this one.
*/
@@ -5651,9 +6602,31 @@ zone_sign(dns_zone_t *zone) {
if (signing->db != db)
goto next_signing;
- is_ksk = ISC_FALSE;
delegation = ISC_FALSE;
+ was_ksk = ISC_FALSE;
+
+ if (first && signing->delete) {
+ /*
+ * Remove the key we are deleting from consideration.
+ */
+ for (i = 0, j = 0; i < nkeys; i++) {
+ /*
+ * Find the key we want to remove.
+ */
+ if (ALG(zone_keys[i]) == signing->algorithm &&
+ dst_key_id(zone_keys[i]) == signing->keyid)
+ {
+ if (KSK(zone_keys[i]))
+ dst_key_free(&zone_keys[i]);
+ continue;
+ }
+ zone_keys[j] = zone_keys[i];
+ j++;
+ }
+ nkeys = j;
+ }
+
dns_dbiterator_current(signing->dbiterator, &node, name);
if (signing->delete) {
@@ -5661,8 +6634,8 @@ zone_sign(dns_zone_t *zone) {
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.
@@ -5694,26 +6667,77 @@ zone_sign(dns_zone_t *zone) {
*/
dns_dbiterator_pause(signing->dbiterator);
for (i = 0; i < nkeys; i++) {
+ isc_boolean_t both = ISC_FALSE;
+
+ /*
+ * Find the keys we want to sign with.
+ */
+ if (!dst_key_isprivate(zone_keys[i]))
+ continue;
+
+ /*
+ * When adding look for the specific key.
+ */
+ if (!signing->delete &&
+ (dst_key_alg(zone_keys[i]) != signing->algorithm ||
+ dst_key_id(zone_keys[i]) != signing->keyid))
+ continue;
+
/*
- * Find the key we want to sign with.
+ * When deleting make sure we are properly signed
+ * with the algorithm that was being removed.
*/
- if (dst_key_alg(zone_keys[i]) != signing->algorithm ||
- dst_key_id(zone_keys[i]) != signing->keyid ||
- !dst_key_isprivate(zone_keys[i]))
+ if (signing->delete &&
+ ALG(zone_keys[i]) != signing->algorithm)
continue;
+
/*
* Do we do KSK processing?
*/
- if (check_ksk &&
- (dst_key_flags(zone_keys[i]) & DNS_KEYFLAG_KSK) != 0)
- is_ksk = ISC_TRUE;
+ if (check_ksk && !REVOKE(zone_keys[i])) {
+ isc_boolean_t have_ksk, have_nonksk;
+ if (KSK(zone_keys[i])) {
+ have_ksk = ISC_TRUE;
+ have_nonksk = ISC_FALSE;
+ } else {
+ have_ksk = ISC_FALSE;
+ have_nonksk = ISC_TRUE;
+ }
+ for (j = 0; j < nkeys; j++) {
+ if (j == i ||
+ ALG(zone_keys[i]) !=
+ ALG(zone_keys[j]))
+ continue;
+ if (REVOKE(zone_keys[j]))
+ continue;
+ if (KSK(zone_keys[j]))
+ have_ksk = ISC_TRUE;
+ else
+ have_nonksk = ISC_TRUE;
+ both = have_ksk && have_nonksk;
+ if (both)
+ break;
+ }
+ }
+ if (both || REVOKE(zone_keys[i]))
+ is_ksk = KSK(zone_keys[i]);
+ else
+ is_ksk = ISC_FALSE;
+
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;
+ ISC_TF(both && keyset_kskonly),
+ &delegation, &sig_diff,
+ &signatures, zone->mctx));
+ /*
+ * If we are adding we are done. Look for other keys
+ * of the same algorithm if deleting.
+ */
+ if (!signing->delete)
+ break;
}
+
/*
* Go onto next node.
*/
@@ -5726,9 +6750,7 @@ zone_sign(dns_zone_t *zone) {
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) {
+ if (nkeys != 0 && build_nsec) {
/*
* We have finished regenerating the
* zone with a zone signing key.
@@ -5740,8 +6762,8 @@ zone_sign(dns_zone_t *zone) {
result = updatesecure(db, version,
&zone->origin,
zone->minimum,
- &secureupdated,
- &sig_diff);
+ ISC_FALSE,
+ &post_diff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone,
ISC_LOG_ERROR,
@@ -5750,16 +6772,19 @@ zone_sign(dns_zone_t *zone) {
goto failure;
}
}
- result = updatesignwithkey(signing, version,
- &zone->origin,
- zone->privatetype,
- &sig_diff);
+ result = updatesignwithkey(zone, signing,
+ version,
+ build_nsec3,
+ zone->minimum,
+ &post_diff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
- "updatesignwithkey -> %s\n",
+ "updatesignwithkey "
+ "-> %s\n",
dns_result_totext(result));
goto failure;
}
+ build_nsec = ISC_FALSE;
goto next_signing;
} else if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -5783,53 +6808,13 @@ zone_sign(dns_zone_t *zone) {
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 (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
+ result = update_sigs(&post_diff, db, version, zone_keys,
+ nkeys, zone, inception, expire, now,
+ check_ksk, keyset_kskonly, &sig_diff);
if (result != ISC_R_SUCCESS) {
- dns_zone_log(zone, ISC_LOG_ERROR,
- "zone_sign:add_sigs -> %s\n",
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
+ "update_sigs -> %s\n",
dns_result_totext(result));
goto failure;
}
@@ -5838,8 +6823,10 @@ zone_sign(dns_zone_t *zone) {
/*
* Have we changed anything?
*/
- if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
+ if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) {
+ result = ISC_R_SUCCESS;
goto pauseall;
+ }
commit = ISC_TRUE;
@@ -5866,7 +6853,7 @@ zone_sign(dns_zone_t *zone) {
*/
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
&sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk);
+ soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:add_sigs -> %s\n",
@@ -5877,27 +6864,9 @@ zone_sign(dns_zone_t *zone) {
/*
* Write changes to journal file.
*/
- 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;
- }
- }
+ result = zone_journal(zone, &sig_diff, "zone_sign");
+ if (result != ISC_R_SUCCESS)
+ goto failure;
pauseall:
/*
@@ -5934,6 +6903,7 @@ zone_sign(dns_zone_t *zone) {
if (commit) {
LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
zone_needdump(zone, DNS_DUMP_DELAY);
UNLOCK_ZONE(zone);
}
@@ -5945,7 +6915,7 @@ zone_sign(dns_zone_t *zone) {
signing = ISC_LIST_HEAD(cleanup);
while (signing != NULL) {
ISC_LIST_UNLINK(cleanup, signing, link);
- ISC_LIST_APPEND(zone->signing, signing, link);
+ ISC_LIST_PREPEND(zone->signing, signing, link);
dns_dbiterator_first(signing->dbiterator);
dns_dbiterator_pause(signing->dbiterator);
signing = ISC_LIST_HEAD(cleanup);
@@ -5961,6 +6931,9 @@ zone_sign(dns_zone_t *zone) {
for (i = 0; i < nkeys; i++)
dst_key_free(&zone_keys[i]);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
if (version != NULL) {
dns_db_closeversion(db, &version, ISC_FALSE);
dns_db_detach(&db);
@@ -5979,6 +6952,832 @@ zone_sign(dns_zone_t *zone) {
}
static void
+normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
+ unsigned char *data, int size) {
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_keydata_t keydata;
+ isc_buffer_t buf;
+
+ dns_rdata_reset(target);
+ isc_buffer_init(&buf, data, size);
+
+ switch (rr->type) {
+ case dns_rdatatype_dnskey:
+ dns_rdata_tostruct(rr, &dnskey, NULL);
+ dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
+ dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
+ &dnskey, &buf);
+ break;
+ case dns_rdatatype_keydata:
+ dns_rdata_tostruct(rr, &keydata, NULL);
+ dns_keydata_todnskey(&keydata, &dnskey, NULL);
+ dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
+ &dnskey, &buf);
+ break;
+ default:
+ INSIST(0);
+ }
+}
+
+/*
+ * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
+ * a KEYDATA rdataset from the key zone.
+ *
+ * 'rr' contains either a DNSKEY record, or a KEYDATA record
+ *
+ * After normalizing keys to the same format (DNSKEY, with revoke bit
+ * cleared), return ISC_TRUE if a key that matches 'rr' is found in
+ * 'rdset', or ISC_FALSE if not.
+ */
+
+static isc_boolean_t
+matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
+ unsigned char data1[4096], data2[4096];
+ dns_rdata_t rdata, rdata1, rdata2;
+ isc_result_t result;
+
+ dns_rdata_init(&rdata);
+ dns_rdata_init(&rdata1);
+ dns_rdata_init(&rdata2);
+
+ normalize_key(rr, &rdata1, data1, sizeof(data1));
+
+ for (result = dns_rdataset_first(rdset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdset)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdset, &rdata);
+ normalize_key(&rdata, &rdata2, data2, sizeof(data2));
+ if (dns_rdata_compare(&rdata1, &rdata2) == 0)
+ return (ISC_TRUE);
+ }
+
+ return (ISC_FALSE);
+}
+
+/*
+ * Calculate the refresh interval for a keydata zone, per
+ * RFC5011: MAX(1 hr,
+ * MIN(15 days,
+ * 1/2 * OrigTTL,
+ * 1/2 * RRSigExpirationInterval))
+ * or for retries: MAX(1 hr,
+ * MIN(1 day,
+ * 1/10 * OrigTTL,
+ * 1/10 * RRSigExpirationInterval))
+ */
+static inline isc_stdtime_t
+refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
+ isc_result_t result;
+ isc_uint32_t t;
+ dns_rdataset_t *rdset;
+ dns_rdata_t sigrr = DNS_RDATA_INIT;
+ dns_rdata_sig_t sig;
+ isc_stdtime_t now;
+
+ isc_stdtime_get(&now);
+
+ if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
+ rdset = &kfetch->dnskeysigset;
+ else
+ return (now + HOUR);
+
+ result = dns_rdataset_first(rdset);
+ if (result != ISC_R_SUCCESS)
+ return (now + HOUR);
+
+ dns_rdataset_current(rdset, &sigrr);
+ result = dns_rdata_tostruct(&sigrr, &sig, NULL);
+
+ if (!retry) {
+ t = sig.originalttl / 2;
+
+ if (isc_serial_gt(sig.timeexpire, now)) {
+ isc_uint32_t exp = (sig.timeexpire - now) / 2;
+ if (t > exp)
+ t = exp;
+ }
+
+ if (t > (15*DAY))
+ t = (15*DAY);
+
+ if (t < HOUR)
+ t = HOUR;
+ } else {
+ t = sig.originalttl / 10;
+
+ if (isc_serial_gt(sig.timeexpire, now)) {
+ isc_uint32_t exp = (sig.timeexpire - now) / 10;
+ if (t > exp)
+ t = exp;
+ }
+
+ if (t > DAY)
+ t = DAY;
+
+ if (t < HOUR)
+ t = HOUR;
+ }
+
+ return (now + t);
+}
+
+/*
+ * This routine is called when no changes are needed in a KEYDATA
+ * record except to simply update the refresh timer. Caller should
+ * hold zone lock.
+ */
+static isc_result_t
+minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
+{
+ isc_result_t result;
+ isc_buffer_t keyb;
+ unsigned char key_buf[4096];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_keydata_t keydata;
+ dns_name_t *name;
+ dns_zone_t *zone = kfetch->zone;
+ isc_stdtime_t now;
+
+ name = dns_fixedname_name(&kfetch->name);
+ isc_stdtime_get(&now);
+
+ for (result = dns_rdataset_first(&kfetch->keydataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&kfetch->keydataset)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&kfetch->keydataset, &rdata);
+
+ /* Delete old version */
+ CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
+ name, 0, &rdata));
+
+ /* Update refresh timer */
+ CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL));
+ keydata.refresh = refresh_time(kfetch, ISC_TRUE);
+ set_refreshkeytimer(zone, &keydata, now);
+
+ dns_rdata_reset(&rdata);
+ isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+ CHECK(dns_rdata_fromstruct(&rdata,
+ zone->rdclass, dns_rdatatype_keydata,
+ &keydata, &keyb));
+
+ /* Insert updated version */
+ CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
+ name, 0, &rdata));
+ }
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+/*
+ * Verify that DNSKEY set is signed by the key specified in 'keydata'.
+ */
+static isc_boolean_t
+revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
+ isc_result_t result;
+ dns_name_t *keyname;
+ isc_mem_t *mctx;
+ dns_rdata_t sigrr = DNS_RDATA_INIT;
+ dns_rdata_t rr = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t sig;
+ dns_rdata_dnskey_t dnskey;
+ dst_key_t *dstkey = NULL;
+ unsigned char key_buf[4096];
+ isc_buffer_t keyb;
+ isc_boolean_t answer = ISC_FALSE;
+
+ REQUIRE(kfetch != NULL && keydata != NULL);
+ REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
+
+ keyname = dns_fixedname_name(&kfetch->name);
+ mctx = kfetch->zone->view->mctx;
+
+ /* Generate a key from keydata */
+ isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+ dns_keydata_todnskey(keydata, &dnskey, NULL);
+ dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
+ &dnskey, &keyb);
+ result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+
+ /* See if that key generated any of the signatures */
+ for (result = dns_rdataset_first(&kfetch->dnskeysigset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&kfetch->dnskeysigset)) {
+ dns_fixedname_t fixed;
+ dns_fixedname_init(&fixed);
+
+ dns_rdata_reset(&sigrr);
+ dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
+ result = dns_rdata_tostruct(&sigrr, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (dst_key_alg(dstkey) == sig.algorithm &&
+ (dst_key_id(dstkey) == sig.keyid ||
+ (sig.algorithm != 1 && sig.keyid ==
+ ((dst_key_id(dstkey) + 128) & 0xffff)))) {
+ result = dns_dnssec_verify2(keyname,
+ &kfetch->dnskeyset,
+ dstkey, ISC_FALSE, mctx, &sigrr,
+ dns_fixedname_name(&fixed));
+
+ dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
+ "Confirm revoked DNSKEY is self-signed: "
+ "%s", dns_result_totext(result));
+
+ if (result == ISC_R_SUCCESS) {
+ answer = ISC_TRUE;
+ break;
+ }
+ }
+ }
+
+ dst_key_free(&dstkey);
+ return (answer);
+}
+
+/*
+ * A DNSKEY set has been fetched from the zone apex of a zone whose trust
+ * anchors are being managed; scan the keyset, and update the key zone and the
+ * local trust anchors according to RFC5011.
+ */
+static void
+keyfetch_done(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result, eresult;
+ dns_fetchevent_t *devent;
+ dns_keyfetch_t *kfetch;
+ dns_zone_t *zone;
+ isc_mem_t *mctx = NULL;
+ dns_keytable_t *secroots = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff;
+ isc_boolean_t changed = ISC_FALSE;
+ isc_boolean_t alldone = ISC_FALSE;
+ dns_name_t *keyname;
+ dns_rdata_t sigrr = DNS_RDATA_INIT;
+ dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
+ dns_rdata_t keydatarr = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t sig;
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_keydata_t keydata;
+ isc_boolean_t initializing;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ unsigned char key_buf[4096];
+ isc_buffer_t keyb;
+ dst_key_t *dstkey;
+ isc_stdtime_t now;
+ int pending = 0;
+ isc_boolean_t secure;
+
+ UNUSED(task);
+ INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
+ INSIST(event->ev_arg != NULL);
+
+ kfetch = event->ev_arg;
+ zone = kfetch->zone;
+ isc_mem_attach(zone->mctx, &mctx);
+ keyname = dns_fixedname_name(&kfetch->name);
+
+ devent = (dns_fetchevent_t *) event;
+ eresult = devent->result;
+
+ /* Free resources which are not of interest */
+ if (devent->node != NULL)
+ dns_db_detachnode(devent->db, &devent->node);
+ if (devent->db != NULL)
+ dns_db_detach(&devent->db);
+ isc_event_free(&event);
+ dns_resolver_destroyfetch(&kfetch->fetch);
+
+ isc_stdtime_get(&now);
+ dns_name_format(keyname, namebuf, sizeof(namebuf));
+
+ result = dns_view_getsecroots(zone->view, &secroots);
+ INSIST(result == ISC_R_SUCCESS);
+
+ LOCK_ZONE(zone);
+ dns_db_newversion(kfetch->db, &ver);
+ dns_diff_init(mctx, &diff);
+
+ zone->refreshkeycount--;
+ alldone = ISC_TF(zone->refreshkeycount == 0);
+
+ if (alldone)
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
+
+ /* Fetch failed */
+ if (eresult != ISC_R_SUCCESS ||
+ !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "Unable to fetch DNSKEY set "
+ "'%s': %s", namebuf, dns_result_totext(eresult));
+ CHECK(minimal_update(kfetch, ver, &diff));
+ changed = ISC_TRUE;
+ goto failure;
+ }
+
+ /* No RRSIGs found */
+ if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "No DNSKEY RRSIGs found for "
+ "'%s': %s", namebuf, dns_result_totext(eresult));
+ CHECK(minimal_update(kfetch, ver, &diff));
+ changed = ISC_TRUE;
+ goto failure;
+ }
+
+ /*
+ * Validate the dnskeyset against the current trusted keys.
+ */
+ for (result = dns_rdataset_first(&kfetch->dnskeysigset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&kfetch->dnskeysigset)) {
+ dns_keynode_t *keynode = NULL;
+
+ dns_rdata_reset(&sigrr);
+ dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
+ result = dns_rdata_tostruct(&sigrr, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ result = dns_keytable_find(secroots, keyname, &keynode);
+ while (result == ISC_R_SUCCESS) {
+ dns_keynode_t *nextnode = NULL;
+ dns_fixedname_t fixed;
+ dns_fixedname_init(&fixed);
+
+ dstkey = dns_keynode_key(keynode);
+ if (dstkey == NULL) /* fail_secure() was called */
+ break;
+
+ if (dst_key_alg(dstkey) == sig.algorithm &&
+ dst_key_id(dstkey) == sig.keyid) {
+ result = dns_dnssec_verify2(keyname,
+ &kfetch->dnskeyset,
+ dstkey, ISC_FALSE,
+ zone->view->mctx, &sigrr,
+ dns_fixedname_name(&fixed));
+
+ dns_zone_log(zone, ISC_LOG_DEBUG(3),
+ "Verifying DNSKEY set for zone "
+ "'%s': %s", namebuf,
+ dns_result_totext(result));
+
+ if (result == ISC_R_SUCCESS) {
+ kfetch->dnskeyset.trust =
+ dns_trust_secure;
+ kfetch->dnskeysigset.trust =
+ dns_trust_secure;
+ dns_keytable_detachkeynode(secroots,
+ &keynode);
+ break;
+ }
+ }
+
+ result = dns_keytable_nextkeynode(secroots,
+ keynode, &nextnode);
+ dns_keytable_detachkeynode(secroots, &keynode);
+ keynode = nextnode;
+ }
+
+ if (kfetch->dnskeyset.trust == dns_trust_secure)
+ break;
+ }
+
+ /*
+ * If we were not able to verify the answer using the current
+ * trusted keys then all we can do is look at any revoked keys.
+ */
+ secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
+
+ /*
+ * First scan keydataset to find keys that are not in dnskeyset
+ * - Missing keys which are not scheduled for removal,
+ * log a warning
+ * - Missing keys which are scheduled for removal and
+ * the remove hold-down timer has completed should
+ * be removed from the key zone
+ * - Missing keys whose acceptance timers have not yet
+ * completed, log a warning and reset the acceptance
+ * timer to 30 days in the future
+ * - All keys not being removed have their refresh timers
+ * updated
+ */
+ initializing = ISC_TRUE;
+ for (result = dns_rdataset_first(&kfetch->keydataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&kfetch->keydataset)) {
+ dns_rdata_reset(&keydatarr);
+ dns_rdataset_current(&kfetch->keydataset, &keydatarr);
+ dns_rdata_tostruct(&keydatarr, &keydata, NULL);
+
+ /*
+ * If any keydata record has a nonzero add holddown, then
+ * there was a pre-existing trust anchor for this domain;
+ * that means we are *not* initializing it and shouldn't
+ * automatically trust all the keys we find at the zone apex.
+ */
+ initializing = initializing && ISC_TF(keydata.addhd == 0);
+
+ if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
+ isc_boolean_t deletekey = ISC_FALSE;
+
+ if (!secure) {
+ if (now > keydata.removehd)
+ deletekey = ISC_TRUE;
+ } else if (now < keydata.addhd) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "Pending key unexpectedly missing "
+ "from %s; restarting acceptance "
+ "timer", namebuf);
+ keydata.addhd = now + MONTH;
+ keydata.refresh = refresh_time(kfetch,
+ ISC_FALSE);
+ } else if (keydata.addhd == 0) {
+ keydata.addhd = now;
+ } else if (keydata.removehd == 0) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "Active key unexpectedly missing "
+ "from %s", namebuf);
+ keydata.refresh = now + HOUR;
+ } else if (now > keydata.removehd) {
+ deletekey = ISC_TRUE;
+ } else {
+ keydata.refresh = refresh_time(kfetch,
+ ISC_FALSE);
+ }
+
+ if (secure || deletekey) {
+ /* Delete old version */
+ CHECK(update_one_rr(kfetch->db, ver, &diff,
+ DNS_DIFFOP_DEL, keyname, 0,
+ &keydatarr));
+ changed = ISC_TRUE;
+ }
+
+ if (!secure || deletekey)
+ continue;
+
+ dns_rdata_reset(&keydatarr);
+ isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+ dns_rdata_fromstruct(&keydatarr, zone->rdclass,
+ dns_rdatatype_keydata,
+ &keydata, &keyb);
+
+ /* Insert updated version */
+ CHECK(update_one_rr(kfetch->db, ver, &diff,
+ DNS_DIFFOP_ADD, keyname, 0,
+ &keydatarr));
+ changed = ISC_TRUE;
+
+ set_refreshkeytimer(zone, &keydata, now);
+ }
+ }
+
+ /*
+ * Next scan dnskeyset:
+ * - If new keys are found (i.e., lacking a match in keydataset)
+ * add them to the key zone and set the acceptance timer
+ * to 30 days in the future (or to immediately if we've
+ * determined that we're initializing the zone for the
+ * first time)
+ * - Previously-known keys that have been revoked
+ * must be scheduled for removal from the key zone (or,
+ * if they hadn't been accepted as trust anchors yet
+ * anyway, removed at once)
+ * - Previously-known unrevoked keys whose acceptance timers
+ * have completed are promoted to trust anchors
+ * - All keys not being removed have their refresh
+ * timers updated
+ */
+ for (result = dns_rdataset_first(&kfetch->dnskeyset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&kfetch->dnskeyset)) {
+ isc_boolean_t revoked = ISC_FALSE;
+ isc_boolean_t newkey = ISC_FALSE;
+ isc_boolean_t updatekey = ISC_FALSE;
+ isc_boolean_t deletekey = ISC_FALSE;
+ isc_boolean_t trustkey = ISC_FALSE;
+
+ dns_rdata_reset(&dnskeyrr);
+ dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
+ dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+
+ /* Skip ZSK's */
+ if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
+ continue;
+
+ revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
+
+ if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
+ dns_rdata_reset(&keydatarr);
+ dns_rdataset_current(&kfetch->keydataset, &keydatarr);
+ dns_rdata_tostruct(&keydatarr, &keydata, NULL);
+
+ if (revoked && revocable(kfetch, &keydata)) {
+ if (keydata.addhd > now) {
+ /*
+ * Key wasn't trusted yet, and now
+ * it's been revoked? Just remove it
+ */
+ deletekey = ISC_TRUE;
+ } else if (keydata.removehd == 0) {
+ /* Remove from secroots */
+ untrust_key(zone->view->viewlist,
+ keyname, mctx, &dnskey);
+
+ /* If initializing, delete now */
+ if (keydata.addhd == 0)
+ deletekey = ISC_TRUE;
+ else
+ keydata.removehd = now + MONTH;
+ } else if (keydata.removehd < now) {
+ /* Scheduled for removal */
+ deletekey = ISC_TRUE;
+ }
+ } else if (revoked) {
+ if (secure && keydata.removehd == 0) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "Active key for zone "
+ "'%s' is revoked but "
+ "did not self-sign; "
+ "ignoring.", namebuf);
+ continue;
+ }
+ } else if (secure) {
+ if (keydata.removehd != 0) {
+ /*
+ * Key isn't revoked--but it
+ * seems it used to be.
+ * Remove it now and add it
+ * back as if it were a fresh key.
+ */
+ deletekey = ISC_TRUE;
+ newkey = ISC_TRUE;
+ } else if (keydata.addhd > now)
+ pending++;
+ else if (keydata.addhd == 0)
+ keydata.addhd = now;
+
+ if (keydata.addhd <= now)
+ trustkey = ISC_TRUE;
+ }
+
+ if (!deletekey && !newkey)
+ updatekey = ISC_TRUE;
+ } else if (secure) {
+ /*
+ * Key wasn't in the key zone but it's
+ * revoked now anyway, so just skip it
+ */
+ if (revoked)
+ continue;
+
+ /* Key wasn't in the key zone: add it */
+ newkey = ISC_TRUE;
+
+ if (initializing) {
+ dns_keytag_t tag = 0;
+ CHECK(compute_tag(keyname, &dnskey,
+ mctx, &tag));
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "Initializing automatic trust "
+ "anchor management for zone '%s'; "
+ "DNSKEY ID %d is now trusted, "
+ "waiving the normal 30-day "
+ "waiting period.",
+ namebuf, tag);
+ trustkey = ISC_TRUE;
+ }
+ }
+
+ /* Delete old version */
+ if (deletekey || !newkey) {
+ CHECK(update_one_rr(kfetch->db, ver, &diff,
+ DNS_DIFFOP_DEL, keyname, 0,
+ &keydatarr));
+ changed = ISC_TRUE;
+ }
+
+ if (updatekey) {
+ /* Set refresh timer */
+ keydata.refresh = refresh_time(kfetch, ISC_FALSE);
+ dns_rdata_reset(&keydatarr);
+ isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+ dns_rdata_fromstruct(&keydatarr, zone->rdclass,
+ dns_rdatatype_keydata,
+ &keydata, &keyb);
+
+ /* Insert updated version */
+ CHECK(update_one_rr(kfetch->db, ver, &diff,
+ DNS_DIFFOP_ADD, keyname, 0,
+ &keydatarr));
+ changed = ISC_TRUE;
+ } else if (newkey) {
+ /* Convert DNSKEY to KEYDATA */
+ dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+ dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
+ NULL);
+ keydata.addhd = initializing ? now : now + MONTH;
+ keydata.refresh = refresh_time(kfetch, ISC_FALSE);
+ dns_rdata_reset(&keydatarr);
+ isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+ dns_rdata_fromstruct(&keydatarr, zone->rdclass,
+ dns_rdatatype_keydata,
+ &keydata, &keyb);
+
+ /* Insert into key zone */
+ CHECK(update_one_rr(kfetch->db, ver, &diff,
+ DNS_DIFFOP_ADD, keyname, 0,
+ &keydatarr));
+ changed = ISC_TRUE;
+ }
+
+ if (trustkey) {
+ /* Trust this key in all views */
+ dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+ trust_key(zone->view->viewlist, keyname, &dnskey,
+ mctx);
+ }
+
+ if (!deletekey)
+ set_refreshkeytimer(zone, &keydata, now);
+ }
+
+ /*
+ * RFC5011 says, "A trust point that has all of its trust anchors
+ * revoked is considered deleted and is treated as if the trust
+ * point was never configured." But if someone revoked their
+ * active key before the standby was trusted, that would mean the
+ * zone would suddenly be nonsecured. We avoid this by checking to
+ * see if there's pending keydata. If so, we put a null key in
+ * the security roots; then all queries to the zone will fail.
+ */
+ if (pending != 0)
+ fail_secure(zone->view->viewlist, keyname);
+
+ failure:
+ if (changed) {
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
+ zone_needdump(zone, 30);
+ }
+
+ UNLOCK_ZONE(zone);
+
+ /* Write changes to journal file. */
+ if (alldone) {
+ result = increment_soa_serial(kfetch->db, ver, &diff, mctx);
+ if (result == ISC_R_SUCCESS)
+ result = zone_journal(zone, &diff, "keyfetch_done");
+ }
+
+ dns_diff_clear(&diff);
+ dns_db_closeversion(kfetch->db, &ver, changed);
+ dns_db_detach(&kfetch->db);
+ dns_zone_detach(&kfetch->zone);
+
+ if (dns_rdataset_isassociated(&kfetch->keydataset))
+ dns_rdataset_disassociate(&kfetch->keydataset);
+ if (dns_rdataset_isassociated(&kfetch->dnskeyset))
+ dns_rdataset_disassociate(&kfetch->dnskeyset);
+ if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
+ dns_rdataset_disassociate(&kfetch->dnskeysigset);
+
+ dns_name_free(keyname, mctx);
+ isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
+ isc_mem_detach(&mctx);
+
+ if (secroots != NULL)
+ dns_keytable_detach(&secroots);
+}
+
+/*
+ * Refresh the data in the key zone. Initiate a fetch to get new DNSKEY
+ * records from the zone apex.
+ */
+static void
+zone_refreshkeys(dns_zone_t *zone) {
+ const char me[] = "zone_refreshkeys";
+ isc_result_t result;
+ dns_rriterator_t rrit;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_keydata_t kd;
+ isc_stdtime_t now;
+ isc_boolean_t commit = ISC_FALSE;
+
+ ENTER;
+ REQUIRE(zone->db != NULL);
+
+ isc_stdtime_get(&now);
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ LOCK_ZONE(zone);
+ dns_db_newversion(db, &ver);
+ dns_diff_init(zone->mctx, &diff);
+
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
+
+ dns_rriterator_init(&rrit, db, ver, 0);
+ for (result = dns_rriterator_first(&rrit);
+ result == ISC_R_SUCCESS;
+ result = dns_rriterator_nextrrset(&rrit)) {
+ isc_stdtime_t timer = 0xffffffff;
+ dns_keyfetch_t *kfetch;
+ dns_rdataset_t *kdset;
+ dns_name_t *name = NULL;
+ isc_uint32_t ttl;
+
+ dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
+ if (!dns_rdataset_isassociated(kdset))
+ continue;
+
+ if (kdset->type != dns_rdatatype_keydata)
+ continue;
+
+ /*
+ * Scan the stored keys looking for ones that need
+ * removal or refreshing
+ */
+ for (result = dns_rdataset_first(kdset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(kdset)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(kdset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &kd, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ /* Removal timer expired? */
+ if (kd.removehd != 0 && kd.removehd < now) {
+ CHECK(update_one_rr(db, ver, &diff,
+ DNS_DIFFOP_DEL, name, ttl,
+ &rdata));
+ continue;
+ }
+
+ /* Acceptance timer expired? */
+ if (kd.addhd != 0 && kd.addhd < now)
+ timer = kd.addhd;
+
+ /* Or do we just need to refresh the keyset? */
+ if (timer > kd.refresh)
+ timer = kd.refresh;
+ }
+
+ if (timer > now)
+ continue;
+
+ zone->refreshkeycount++;
+
+ kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
+ kfetch->zone = NULL;
+ dns_zone_attach(zone, &kfetch->zone);
+ dns_fixedname_init(&kfetch->name);
+ dns_name_dup(name, zone->mctx,
+ dns_fixedname_name(&kfetch->name));
+ dns_rdataset_init(&kfetch->dnskeyset);
+ dns_rdataset_init(&kfetch->dnskeysigset);
+ dns_rdataset_init(&kfetch->keydataset);
+ dns_rdataset_clone(kdset, &kfetch->keydataset);
+ kfetch->db = NULL;
+ dns_db_attach(db, &kfetch->db);
+ kfetch->fetch = NULL;
+
+ dns_resolver_createfetch(zone->view->resolver,
+ dns_fixedname_name(&kfetch->name),
+ dns_rdatatype_dnskey,
+ NULL, NULL, NULL,
+ DNS_FETCHOPT_NOVALIDATE,
+ zone->task, keyfetch_done, kfetch,
+ &kfetch->dnskeyset,
+ &kfetch->dnskeysigset,
+ &kfetch->fetch);
+ }
+ if (!ISC_LIST_EMPTY(diff.tuples)) {
+ CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
+ commit = ISC_TRUE;
+ zone_journal(zone, &diff, "sync_keyzone");
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
+ zone_needdump(zone, 30);
+ }
+ failure:
+ UNLOCK_ZONE(zone);
+
+ dns_rriterator_destroy(&rrit);
+ dns_diff_clear(&diff);
+ dns_db_closeversion(db, &ver, commit);
+ dns_db_detach(&db);
+}
+
+static void
zone_maintenance(dns_zone_t *zone) {
const char me[] = "zone_maintenance";
isc_time_t now;
@@ -5991,7 +7790,7 @@ zone_maintenance(dns_zone_t *zone) {
/*
* Configuring the view of this zone may have
* failed, for example because the config file
- * had a syntax error. In that case, the view
+ * had a syntax error. In that case, the view
* adb or resolver, and we had better not try
* to do maintenance on it.
*/
@@ -6038,6 +7837,7 @@ zone_maintenance(dns_zone_t *zone) {
switch (zone->type) {
case dns_zone_master:
case dns_zone_slave:
+ case dns_zone_key:
LOCK_ZONE(zone);
if (zone->masterfile != NULL &&
isc_time_compare(&now, &zone->dumptime) >= 0 &&
@@ -6059,6 +7859,24 @@ zone_maintenance(dns_zone_t *zone) {
break;
}
+ /*
+ * Do we need to refresh keys?
+ */
+ switch (zone->type) {
+ case dns_zone_key:
+ if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
+ zone_refreshkeys(zone);
+ break;
+ case dns_zone_master:
+ if (!isc_time_isepoch(&zone->refreshkeytime) &&
+ isc_time_compare(&now, &zone->refreshkeytime) >= 0)
+ zone_rekey(zone);
+ default:
+ break;
+ }
+
switch (zone->type) {
case dns_zone_master:
case dns_zone_slave:
@@ -6098,7 +7916,8 @@ void
dns_zone_markdirty(dns_zone_t *zone) {
LOCK_ZONE(zone);
- set_resigntime(zone); /* XXXMPA make separate call back */
+ if (zone->type == dns_zone_master)
+ set_resigntime(zone); /* XXXMPA make separate call back */
zone_needdump(zone, DNS_DUMP_DELAY);
UNLOCK_ZONE(zone);
}
@@ -8474,7 +10293,7 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) {
/*
* We have now canceled everything set the flag to allow exit_check()
- * to succeed. We must not unlock between setting this flag and
+ * to succeed. We must not unlock between setting this flag and
* calling exit_check().
*/
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
@@ -8505,6 +10324,7 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) {
isc_time_t next;
isc_result_t result;
+ ENTER;
REQUIRE(DNS_ZONE_VALID(zone));
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
return;
@@ -8522,6 +10342,12 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) {
isc_time_compare(&zone->dumptime, &next) < 0)
next = zone->dumptime;
}
+ if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
+ !isc_time_isepoch(&zone->refreshkeytime)) {
+ if (isc_time_isepoch(&next) ||
+ isc_time_compare(&zone->refreshkeytime, &next) < 0)
+ next = zone->refreshkeytime;
+ }
if (!isc_time_isepoch(&zone->resigntime)) {
if (isc_time_isepoch(&next) ||
isc_time_compare(&zone->resigntime, &next) < 0)
@@ -8574,6 +10400,22 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) {
}
break;
+ case dns_zone_key:
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
+ INSIST(!isc_time_isepoch(&zone->dumptime));
+ if (isc_time_isepoch(&next) ||
+ isc_time_compare(&zone->dumptime, &next) < 0)
+ next = zone->dumptime;
+ }
+ if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
+ if (isc_time_isepoch(&next) ||
+ (!isc_time_isepoch(&zone->refreshkeytime) &&
+ isc_time_compare(&zone->refreshkeytime, &next) < 0))
+ next = zone->refreshkeytime;
+ }
+ break;
+
default:
break;
}
@@ -8786,7 +10628,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
REQUIRE(DNS_ZONE_VALID(zone));
/*
- * If type != T_SOA return DNS_R_REFUSED. We don't yet support
+ * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
* ROLLOVER.
*
* SOA: RFC1996
@@ -8905,7 +10747,8 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
NULL, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (isc_serial_le(serial, oldserial)) {
- dns_zone_log(zone, ISC_LOG_INFO,
+ dns_zone_log(zone,
+ ISC_LOG_INFO,
"notify from %s: "
"zone is up to date",
fromtext);
@@ -9309,7 +11152,8 @@ dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
vsnprintf(message, sizeof(message), fmt, ap);
va_end(ap);
isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
- level, "zone %s: %s", zone->strnamerd, message);
+ level, "%s %s: %s", (zone->type == dns_zone_key) ?
+ "managed-keys-zone" : "zone", zone->strnamerd, message);
}
void
@@ -9324,7 +11168,8 @@ dns_zone_log(dns_zone_t *zone, int level, const char *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", zone->strnamerd, message);
+ level, "%s %s: %s", (zone->type == dns_zone_key) ?
+ "managed-keys-zone" : "zone", zone->strnamerd, message);
}
static void
@@ -9342,7 +11187,8 @@ zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
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, zone->strnamerd, message);
+ level, "%s: %s %s: %s", me, zone->type != dns_zone_key ?
+ "zone" : "managed-keys-zone", zone->strnamerd, message);
}
static int
@@ -9499,7 +11345,7 @@ notify_done(isc_task_t *task, isc_event_t *event) {
dns_result_totext(result));
/*
- * Old bind's return formerr if they see a soa record. Retry w/o
+ * Old bind's return formerr if they see a soa record. Retry w/o
* the soa if we see a formerr and had sent a SOA.
*/
isc_event_free(&event);
@@ -9554,7 +11400,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
"has %d SOA records", soacount);
result = DNS_R_BADZONE;
}
- if (nscount == 0) {
+ if (nscount == 0 && zone->type != dns_zone_key) {
dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
result = DNS_R_BADZONE;
}
@@ -9640,24 +11486,27 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
}
} else {
if (dump && zone->masterfile != NULL) {
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
- DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
- "dumping new zone version");
- result = dns_db_dump2(db, ver, zone->masterfile,
- zone->masterformat);
- if (result != ISC_R_SUCCESS)
- goto fail;
-
/*
- * Update the time the zone was updated, so
- * dns_zone_load can avoid loading it when
- * the server is reloaded. If isc_time_now
- * fails for some reason, all that happens is
- * the timestamp is not updated.
+ * If DNS_ZONEFLG_FORCEXFER was set we don't want
+ * to keep the old masterfile.
*/
- TIME_NOW(&zone->loadtime);
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
+ remove(zone->masterfile) < 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 masterfile "
+ "'%s': '%s'",
+ zone->masterfile, strbuf);
+ }
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
+ else
+ zone_needdump(zone, 0);
}
-
if (dump && zone->journal != NULL) {
/*
* The in-memory database just changed, and
@@ -9665,7 +11514,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
* being loaded from disk. Also, we have not
* journaled diffs for this change.
* Therefore, the on-disk journal is missing
- * the deltas for this change. Since it can
+ * the deltas for this change. Since it can
* no longer be used to bring the zone
* up-to-date, it is useless and should be
* removed.
@@ -9853,16 +11702,19 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
&now);
/* Someone removed the file from underneath us! */
if (result == ISC_R_FILENOTFOUND &&
- zone->masterfile != NULL)
- zone_needdump(zone, DNS_DUMP_DELAY);
- else if (result != ISC_R_SUCCESS)
+ zone->masterfile != NULL) {
+ unsigned int delay = DNS_DUMP_DELAY;
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY))
+ delay = 0;
+ zone_needdump(zone, delay);
+ } else if (result != ISC_R_SUCCESS)
dns_zone_log(zone, ISC_LOG_ERROR,
"transfer: could not set file "
"modification time of '%s': %s",
zone->masterfile,
dns_result_totext(result));
}
-
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
inc_stats(zone, dns_zonestatscounter_xfrsuccess);
break;
@@ -11313,7 +13165,7 @@ dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
case dns_dialuptype_no:
break;
case dns_dialuptype_yes:
- DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
+ DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
DNS_ZONEFLG_DIALREFRESH |
DNS_ZONEFLG_NOREFRESH));
break;
@@ -11642,3 +13494,778 @@ zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
}
return (result);
}
+
+static void
+logmsg(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
+ ISC_LOG_DEBUG(1), format, args);
+ va_end(args);
+}
+
+static void
+clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
+ dns_dnsseckey_t *key;
+ while (!ISC_LIST_EMPTY(*list)) {
+ key = ISC_LIST_HEAD(*list);
+ ISC_LIST_UNLINK(*list, key, link);
+ dns_dnsseckey_destroy(mctx, &key);
+ }
+}
+
+/* Called once; *timep should be set to the current time. */
+static isc_result_t
+next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
+ isc_result_t result;
+ isc_stdtime_t now, then = 0, event;
+ int i;
+
+ now = *timep;
+
+ for (i = 0; i <= DST_MAX_TIMES; i++) {
+ result = dst_key_gettime(key, i, &event);
+ if (result == ISC_R_SUCCESS && event > now &&
+ (then == 0 || event < then))
+ then = event;
+ }
+
+ if (then != 0) {
+ *timep = then;
+ return (ISC_R_SUCCESS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ const dns_rdata_t *rdata, isc_boolean_t *flag)
+{
+ dns_rdataset_t rdataset;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ if (rdata->type == dns_rdatatype_nsec3)
+ CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
+ else
+ CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
+ result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ *flag = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ goto failure;
+ }
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t myrdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &myrdata);
+ if (!dns_rdata_compare(&myrdata, rdata))
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS) {
+ *flag = ISC_TRUE;
+ } else if (result == ISC_R_NOMORE) {
+ *flag = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ }
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+/*
+ * Add records to signal the state of signing or of key removal.
+ */
+static isc_result_t
+add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
+ dns_dbversion_t *ver, dns_diff_t *diff)
+{
+ dns_difftuple_t *tuple, *newtuple = NULL;
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_boolean_t flag;
+ isc_region_t r;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_uint16_t keyid;
+ unsigned char buf[5];
+ dns_name_t *name = dns_db_origin(db);
+
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ if (tuple->rdata.type != dns_rdatatype_dnskey)
+ continue;
+
+ result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if ((dnskey.flags &
+ (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
+ != DNS_KEYOWNER_ZONE)
+ continue;
+
+ dns_rdata_toregion(&tuple->rdata, &r);
+
+ keyid = dst_region_computeid(&r, dnskey.algorithm);
+
+ buf[0] = dnskey.algorithm;
+ buf[1] = (keyid & 0xff00) >> 8;
+ buf[2] = (keyid & 0xff);
+ buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
+ buf[4] = 0;
+ rdata.data = buf;
+ rdata.length = sizeof(buf);
+ rdata.type = privatetype;
+ rdata.rdclass = tuple->rdata.rdclass;
+
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ if (flag)
+ continue;
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ name, 0, &rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ INSIST(newtuple == NULL);
+ /*
+ * Remove any record which says this operation has already
+ * completed.
+ */
+ buf[4] = 1;
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ if (flag) {
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
+ name, 0, &rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ INSIST(newtuple == NULL);
+ }
+ }
+ failure:
+ return (result);
+}
+
+static isc_result_t
+sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff, dns_diff_t *sig_diff)
+{
+ isc_result_t result;
+ isc_stdtime_t now, inception, soaexpire;
+ isc_boolean_t check_ksk, keyset_kskonly;
+ dst_key_t *zone_keys[MAXZONEKEYS];
+ unsigned int nkeys = 0, i;
+ dns_difftuple_t *tuple;
+
+ result = find_zone_keys(zone, db, ver, zone->mctx, MAXZONEKEYS,
+ zone_keys, &nkeys);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "sign_apex:find_zone_keys -> %s\n",
+ dns_result_totext(result));
+ return (result);
+ }
+
+ isc_stdtime_get(&now);
+ inception = now - 3600; /* Allow for clock skew. */
+ soaexpire = now + dns_zone_getsigvalidityinterval(zone);
+
+ check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
+ keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
+
+ /*
+ * See if update_sigs will update DNSKEY signature and if not
+ * cause them to sign so that so that newly activated keys
+ * are used.
+ */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ if (tuple->rdata.type == dns_rdatatype_dnskey &&
+ dns_name_equal(&tuple->name, &zone->origin))
+ break;
+ }
+
+ if (tuple == NULL) {
+ result = del_sigs(zone, db, ver, &zone->origin,
+ dns_rdatatype_dnskey, sig_diff,
+ zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "sign_apex:del_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
+ sig_diff, zone_keys, nkeys, zone->mctx,
+ inception, soaexpire, check_ksk,
+ keyset_kskonly);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "sign_apex:add_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+
+ result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
+ inception, soaexpire, now, check_ksk,
+ keyset_kskonly, sig_diff);
+
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "sign_apex:update_sigs -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ failure:
+ for (i = 0; i < nkeys; i++)
+ dst_key_free(&zone_keys[i]);
+ return (result);
+}
+
+/*
+ * Prevent the zone entering a inconsistent state where
+ * NSEC only DNSKEYs are present with NSEC3 chains.
+ * See update.c:check_dnssec()
+ */
+static isc_boolean_t
+dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff)
+{
+ isc_result_t result;
+ dns_difftuple_t *tuple;
+ isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
+
+ /* Scan the tuples for an NSEC-only DNSKEY */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ isc_uint8_t alg;
+ if (tuple->rdata.type != dns_rdatatype_dnskey ||
+ tuple->op != DNS_DIFFOP_ADD)
+ continue;
+
+ alg = tuple->rdata.data[3];
+ if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
+ alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
+ nseconly = ISC_TRUE;
+ break;
+ }
+ }
+
+ /* Check existing DB for NSEC-only DNSKEY */
+ if (!nseconly)
+ CHECK(dns_nsec_nseconly(db, ver, &nseconly));
+
+ /* Check existing DB for NSEC3 */
+ if (!nsec3)
+ CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
+ privatetype, &nsec3));
+
+ /* Refuse to allow NSEC3 with NSEC-only keys */
+ if (nseconly && nsec3) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "NSEC only DNSKEYs and NSEC3 chains not allowed");
+ goto failure;
+ }
+
+ return (ISC_TRUE);
+
+ failure:
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ CHECK(dns_db_getoriginnode(db, &node));
+
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
+ dns_rdatatype_none, 0, &rdataset, NULL);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOTFOUND)
+ goto failure;
+
+ result = dns_nsec3param_deletechains(db, ver, zone, diff);
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+/*
+ * Given an RRSIG rdataset and an algorithm, determine whether there
+ * are any signatures using that algorithm.
+ */
+static isc_boolean_t
+signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t rrsig;
+ isc_result_t result;
+
+ REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
+ if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
+ 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);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdata_reset(&rdata);
+ if (rrsig.algorithm == alg)
+ return (ISC_TRUE);
+ }
+
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff)
+{
+ dns_name_t *origin;
+ isc_boolean_t build_nsec3;
+ isc_result_t result;
+
+ origin = dns_db_origin(db);
+ CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
+ &build_nsec3));
+ if (build_nsec3)
+ CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
+ ISC_FALSE, zone->privatetype, diff));
+ CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
+
+ failure:
+ return (result);
+}
+
+static void
+zone_rekey(dns_zone_t *zone) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_rdataset_t soaset, soasigs, keyset, keysigs;
+ dns_dnsseckeylist_t dnskeys, keys, rmkeys;
+ dns_dnsseckey_t *key;
+ dns_diff_t diff, sig_diff;
+ isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
+ isc_boolean_t fullsign;
+ dns_ttl_t ttl = 3600;
+ const char *dir;
+ isc_mem_t *mctx;
+ isc_stdtime_t now;
+ isc_time_t timenow;
+ isc_interval_t ival;
+ char timebuf[80];
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ ISC_LIST_INIT(dnskeys);
+ ISC_LIST_INIT(keys);
+ ISC_LIST_INIT(rmkeys);
+ dns_rdataset_init(&soaset);
+ dns_rdataset_init(&soasigs);
+ dns_rdataset_init(&keyset);
+ dns_rdataset_init(&keysigs);
+ dir = dns_zone_getkeydirectory(zone);
+ mctx = zone->mctx;
+ dns_diff_init(mctx, &diff);
+ dns_diff_init(mctx, &sig_diff);
+
+ CHECK(dns_zone_getdb(zone, &db));
+ CHECK(dns_db_newversion(db, &ver));
+ CHECK(dns_db_getoriginnode(db, &node));
+
+ dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
+
+ /* Get the SOA record's TTL */
+ CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
+ dns_rdatatype_none, 0, &soaset, &soasigs));
+ ttl = soaset.ttl;
+ dns_rdataset_disassociate(&soaset);
+
+ /* Get the DNSKEY rdataset */
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
+ dns_rdatatype_none, 0, &keyset, &keysigs);
+ if (result == ISC_R_SUCCESS) {
+ ttl = keyset.ttl;
+ result = dns_dnssec_keylistfromrdataset(&zone->origin, dir,
+ mctx, &keyset,
+ &keysigs, &soasigs,
+ ISC_FALSE, ISC_FALSE,
+ &dnskeys);
+ /* Can't get keys for some reason; try again later. */
+ if (result != ISC_R_SUCCESS)
+ goto trylater;
+ } else if (result != ISC_R_NOTFOUND)
+ goto failure;
+
+ /*
+ * True when called from "rndc sign". Indicates the zone should be
+ * fully signed now.
+ */
+ fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
+
+ result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
+ if (result == ISC_R_SUCCESS) {
+ isc_boolean_t check_ksk;
+ check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
+
+ result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
+ &zone->origin, ttl, &diff,
+ ISC_TF(!check_ksk),
+ mctx, logmsg);
+
+ /* Keys couldn't be updated for some reason;
+ * try again later. */
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
+ "couldn't update zone keys: %s",
+ isc_result_totext(result));
+ goto trylater;
+ }
+
+ /* See if any pre-existing keys have newly become active */
+ for (key = ISC_LIST_HEAD(dnskeys);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ if (key->first_sign) {
+ newactive = ISC_TRUE;
+ break;
+ }
+ }
+
+ if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
+ dnskey_sane(zone, db, ver, &diff)) {
+ CHECK(dns_diff_apply(&diff, db, ver));
+ CHECK(clean_nsec3param(zone, db, ver, &diff));
+ CHECK(add_signing_records(db, zone->privatetype, ver,
+ &diff));
+ CHECK(increment_soa_serial(db, ver, &diff, mctx));
+ CHECK(add_chains(zone, db, ver, &diff));
+ CHECK(sign_apex(zone, db, ver, &diff, &sig_diff));
+ CHECK(zone_journal(zone, &sig_diff, "zone_rekey"));
+ commit = ISC_TRUE;
+ }
+ }
+
+ dns_db_closeversion(db, &ver, commit);
+
+ if (commit) {
+ isc_time_t timenow;
+ dns_difftuple_t *tuple;
+ isc_boolean_t newkey = ISC_FALSE;
+ isc_boolean_t newalg = ISC_FALSE;
+
+ LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
+
+ zone_needdump(zone, DNS_DUMP_DELAY);
+
+ TIME_NOW(&timenow);
+ zone_settimer(zone, &timenow);
+
+ /*
+ * Has a new key become active? If so, is it for
+ * a new algorithm?
+ */
+ for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ dns_rdata_dnskey_t dnskey;
+
+ if (tuple->rdata.type != dns_rdatatype_dnskey)
+ continue;
+
+ newkey = ISC_TRUE;
+ if (!dns_rdataset_isassociated(&keysigs)) {
+ newalg = ISC_TRUE;
+ break;
+ }
+
+ result = dns_rdata_tostruct(&tuple->rdata,
+ &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (!signed_with_alg(&keysigs,
+ dnskey.algorithm)) {
+ newalg = ISC_TRUE;
+ break;
+ }
+ }
+
+ /*
+ * If we found a new algorithm, we need to sign the
+ * zone fully. If there's a new key, but it's for an
+ * already-existing algorithm, then the zone signing
+ * can be handled incrementally.
+ */
+ if (newkey && !newalg)
+ set_resigntime(zone);
+
+ /* Remove any signatures from removed keys. */
+ if (!ISC_LIST_EMPTY(rmkeys)) {
+ for (key = ISC_LIST_HEAD(rmkeys);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ result = zone_signwithkey(zone,
+ dst_key_alg(key->key),
+ dst_key_id(key->key),
+ ISC_TRUE);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_signwithkey failed: %s",
+ dns_result_totext(result));
+ }
+ }
+ }
+
+
+ if (fullsign) {
+ /*
+ * "rndc sign" was called, so we now sign the zone
+ * with all active keys, whether they're new or not.
+ */
+ for (key = ISC_LIST_HEAD(dnskeys);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ if (!key->force_sign && !key->hint_sign)
+ continue;
+
+ result = zone_signwithkey(zone,
+ dst_key_alg(key->key),
+ dst_key_id(key->key),
+ ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_signwithkey failed: %s",
+ dns_result_totext(result));
+ }
+ }
+ } else if (newalg) {
+ /*
+ * We haven't been told to sign fully, but a new
+ * algorithm was added to the DNSKEY. We sign
+ * the full zone, but only with the newly-added
+ * keys.
+ */
+ for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ dns_rdata_dnskey_t dnskey;
+ dns_secalg_t algorithm;
+ isc_region_t r;
+ isc_uint16_t keyid;
+
+ if (tuple->rdata.type != dns_rdatatype_dnskey ||
+ tuple->op == DNS_DIFFOP_DEL)
+ continue;
+
+ result = dns_rdata_tostruct(&tuple->rdata,
+ &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdata_toregion(&tuple->rdata, &r);
+ algorithm = dnskey.algorithm;
+ keyid = dst_region_computeid(&r, algorithm);
+
+ result = zone_signwithkey(zone, algorithm,
+ keyid, ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_signwithkey failed: %s",
+ dns_result_totext(result));
+ }
+ }
+ }
+
+ /*
+ * Clear fullsign flag, if it was set, so we don't do
+ * another full signing next time
+ */
+ zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
+
+ /*
+ * Cause the zone to add/delete NSEC3 chains for the
+ * deferred NSEC3PARAM changes.
+ */
+ for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3param_t nsec3param;
+
+ if (tuple->rdata.type != zone->privatetype ||
+ tuple->op != DNS_DIFFOP_ADD)
+ continue;
+
+ if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (nsec3param.flags == 0)
+ continue;
+
+ 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));
+ }
+ }
+ UNLOCK_ZONE(zone);
+ }
+
+ isc_stdtime_get(&now);
+ TIME_NOW(&timenow);
+ isc_time_settoepoch(&zone->refreshkeytime);
+ for (key = ISC_LIST_HEAD(dnskeys);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ isc_stdtime_t then;
+ isc_time_t timethen;
+
+ /*
+ * If we are doing automatic key maintenance and the
+ * key metadata indicates there is a key change event
+ * scheduled in the future, set the key refresh timer.
+ */
+ if (!DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
+ break;
+
+ then = now;
+ result = next_keyevent(key->key, &then);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
+ LOCK_ZONE(zone);
+ if (isc_time_isepoch(&zone->refreshkeytime) ||
+ isc_time_compare(&timethen, &zone->refreshkeytime) < 0) {
+ zone->refreshkeytime = timethen;
+ zone_settimer(zone, &timenow);
+ }
+ UNLOCK_ZONE(zone);
+ }
+
+ /*
+ * If no key event is scheduled, we should still check the key
+ * repository for updates every so often. (Currently this is
+ * hard-coded to 12 hours, but it could be configurable.)
+ */
+ if (isc_time_isepoch(&zone->refreshkeytime))
+ DNS_ZONE_TIME_ADD(&timenow, (3600 * 12), &zone->refreshkeytime);
+
+ isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
+ dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
+
+ failure:
+ dns_diff_clear(&diff);
+ dns_diff_clear(&sig_diff);
+
+ clear_keylist(&dnskeys, mctx);
+ clear_keylist(&keys, mctx);
+ clear_keylist(&rmkeys, mctx);
+
+ if (ver != NULL)
+ dns_db_closeversion(db, &ver, ISC_FALSE);
+ if (dns_rdataset_isassociated(&keyset))
+ dns_rdataset_disassociate(&keyset);
+ if (dns_rdataset_isassociated(&keysigs))
+ dns_rdataset_disassociate(&keysigs);
+ if (dns_rdataset_isassociated(&soasigs))
+ dns_rdataset_disassociate(&soasigs);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ return;
+
+ trylater:
+ isc_interval_set(&ival, HOUR, 0);
+ isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
+ goto failure;
+}
+
+void
+dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
+ isc_time_t now;
+
+ if (zone->type == dns_zone_master && zone->task != NULL) {
+ LOCK_ZONE(zone);
+
+ if (fullsign)
+ zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
+
+ TIME_NOW(&now);
+ zone->refreshkeytime = now;
+ zone_settimer(zone, &now);
+
+ UNLOCK_ZONE(zone);
+ }
+}
+
+isc_result_t
+dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ unsigned int *errors)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(errors != NULL);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
+ ISC_FALSE);
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+void
+dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ LOCK_ZONE(zone);
+ zone->added = added;
+ UNLOCK_ZONE(zone);
+}
+
+isc_boolean_t
+dns_zone_getadded(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ return (zone->added);
+}
+
+isc_result_t
+dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
+{
+ isc_time_t loadtime;
+ isc_result_t result;
+ TIME_NOW(&loadtime);
+
+ LOCK_ZONE(zone);
+ result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
+ UNLOCK_ZONE(zone);
+ return result;
+}
diff --git a/contrib/bind9/lib/export/Makefile.in b/contrib/bind9/lib/export/Makefile.in
new file mode 100644
index 0000000..5a9e633
--- /dev/null
+++ b/contrib/bind9/lib/export/Makefile.in
@@ -0,0 +1,27 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+# Note: the order of SUBDIRS is important.
+# Attempt to disable parallel processing.
+.NOTPARALLEL:
+.NO_PARALLEL:
+SUBDIRS = isc dns isccfg irs samples
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/dns/Makefile.in b/contrib/bind9/lib/export/dns/Makefile.in
new file mode 100644
index 0000000..15b0d3f
--- /dev/null
+++ b/contrib/bind9/lib/export/dns/Makefile.in
@@ -0,0 +1,179 @@
+# Copyright (C) 2009, 2010 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: Makefile.in,v 1.8 2010-12-23 04:07:59 marka Exp $
+
+top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/dns
+export_srcdir = @top_srcdir@/lib/export
+
+# Attempt to disable parallel processing.
+.NOTPARALLEL:
+.NO_PARALLEL:
+
+@BIND9_VERSION@
+
+@LIBDNS_API@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} -I${export_srcdir}/isc/include \
+ ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
+
+CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@
+
+CWARNINGS =
+
+ISCLIBS = ../isc/libisc.@A@
+
+ISCDEPLIBS = ../isc/libisc.@A@
+
+LIBS = @LIBS@
+
+# Alphabetically
+
+OPENSSLLINKOBJS = openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \
+ opensslgost_link.@O@ opensslrsa_link.@O@
+
+DSTOBJS = @OPENSSLLINKOBJS@ \
+ dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
+ gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@
+
+DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \
+ cache.@O@ callbacks.@O@ client.@O@ compress.@O@ \
+ db.@O@ dbiterator.@O@ diff.@O@ dispatch.@O@ dlz.@O@ dnssec.@O@ \
+ ds.@O@ \
+ forward.@O@ iptable.@O@ \
+ keytable.@O@ \
+ lib.@O@ log.@O@ \
+ master.@O@ masterdump.@O@ message.@O@ \
+ name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ \
+ peer.@O@ portlist.@O@ \
+ rbt.@O@ rbtdb.@O@ rcode.@O@ rdata.@O@ \
+ rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \
+ request.@O@ resolver.@O@ result.@O@ soa.@O@ stats.@O@ \
+ tcpmsg.@O@ time.@O@ tsec.@O@ tsig.@O@ ttl.@O@ \
+ validator.@O@ version.@O@ view.@O@
+PORTDNSOBJS = ecdb.@O@
+
+OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} ${PORTDNSOBJS}
+
+# Alphabetically
+
+OPENSSLLINKSRCS = openssl_link.c openssldh_link.c openssldsa_link.c \
+ opensslgost_link.c opensslrsa_link.c
+
+DSTSRCS = @OPENSSLLINKSRCS@ \
+ dst_api.c dst_lib.c dst_parse.c \
+ dst_result.c gssapi_link.c gssapictx.c \
+ hmac_link.c key.c
+
+DNSSRCS = acl.c adb.c byaddr.c \
+ cache.c callbacks.c client.c compress.c \
+ db.c dbiterator.c diff.c dispatch.c dlz.c dnssec.c ds.c \
+ forward.c iptable.c \
+ keytable.c \
+ lib.c log.c \
+ master.c masterdump.c message.c \
+ name.c ncache.c nsec.c nsec3.c \
+ peer.c portlist.c \
+ rbt.c rbtdb.c rcode.c rdata.c \
+ rdatalist.c rdataset.c rdatasetiter.c rdataslab.c \
+ request.c res.c resolver.c result.c soa.c stats.c \
+ tcpmsg.c time.c tsec.c tsig.c ttl.c \
+ validator.c version.c view.c
+PORTDNSSRCS = ecdb.c
+
+SRCS = ${DSTSRCS} ${DNSSRCS} ${PORTDNSSRCS}
+
+SUBDIRS = include
+TARGETS = include/dns/enumtype.h include/dns/enumclass.h \
+ include/dns/rdatastruct.h timestamp
+
+DEPENDEXTRA = ./gen -F include/dns/rdatastruct.h \
+ -s ${srcdir} -d >> Makefile ;
+
+@BIND9_MAKE_RULES@
+
+version.@O@: ${srcdir}/version.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DLIBINTERFACE=${LIBINTERFACE} \
+ -DLIBREVISION=${LIBREVISION} \
+ -DLIBAGE=${LIBAGE} \
+ -c ${srcdir}/version.c
+
+libdns.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+libdns.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns.la \
+ -rpath ${export_libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS}
+
+timestamp: libdns.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libdns.@A@ \
+ ${DESTDIR}${export_libdir}
+
+clean distclean::
+ rm -f libdns.@A@ timestamp
+ rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h
+ rm -f include/dns/rdatastruct.h
+
+newrr::
+ rm -f code.h include/dns/enumtype.h include/dns/enumclass.h
+ rm -f include/dns/rdatastruct.h
+
+include: include/dns/enumtype.h include/dns/enumclass.h \
+ include/dns/rdatastruct.h
+
+rdata.@O@: code.h
+
+include/dns/enumtype.h: gen
+ ./gen -s ${srcdir} -t > $@
+
+include/dns/enumclass.h: gen
+ ./gen -s ${srcdir} -c > $@
+
+include/dns/rdatastruct.h: gen \
+ ${srcdir}/rdata/rdatastructpre.h \
+ ${srcdir}/rdata/rdatastructsuf.h
+ ./gen -s ${srcdir} -i \
+ -P ${srcdir}/rdata/rdatastructpre.h \
+ -S ${srcdir}/rdata/rdatastructsuf.h > $@
+
+code.h: gen
+ ./gen -s ${srcdir} > code.h
+
+gen: ${srcdir}/gen.c
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ ${srcdir}/gen.c ${LIBS}
+
+#We don't need rbtdb64 for this library
+#rbtdb64.@O@: rbtdb.c
+
+depend: include/dns/enumtype.h include/dns/enumclass.h \
+ include/dns/rdatastruct.h code.h
+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
diff --git a/contrib/bind9/lib/export/dns/include/Makefile.in b/contrib/bind9/lib/export/dns/include/Makefile.in
new file mode 100644
index 0000000..ecd9c8a
--- /dev/null
+++ b/contrib/bind9/lib/export/dns/include/Makefile.in
@@ -0,0 +1,23 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = dns dst
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/dns/include/dns/Makefile.in b/contrib/bind9/lib/export/dns/include/dns/Makefile.in
new file mode 100644
index 0000000..ccaae41
--- /dev/null
+++ b/contrib/bind9/lib/export/dns/include/dns/Makefile.in
@@ -0,0 +1,56 @@
+# Copyright (C) 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: Makefile.in,v 1.4 2009-09-18 07:18:04 jinmei Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = acl.h adb.h byaddr.h \
+ cache.h callbacks.h cert.h client.h compress.h \
+ db.h dbiterator.h diff.h dispatch.h dlz.h dnssec.h \
+ ds.h events.h fixedname.h ecdb.h \
+ forward.h iptable.h \
+ keytable.h keyvalues.h \
+ lib.h log.h \
+ master.h masterdump.h message.h \
+ name.h ncache.h nsec.h nsec3.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 \
+ secalg.h secproto.h soa.h stats.h \
+ tcpmsg.h time.h tsec.h tsig.h ttl.h types.h \
+ validator.h version.h view.h
+
+GENHEADERS = enumclass.h enumtype.h rdatastruct.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/dns
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${top_srcdir}/lib/dns/include/dns/$$i \
+ ${DESTDIR}${export_includedir}/dns ; \
+ done
+ for i in ${GENHEADERS}; do \
+ ${INSTALL_DATA} $$i ${DESTDIR}${export_includedir}/dns ; \
+ done
diff --git a/contrib/bind9/lib/export/dns/include/dst/Makefile.in b/contrib/bind9/lib/export/dns/include/dst/Makefile.in
new file mode 100644
index 0000000..cebc726
--- /dev/null
+++ b/contrib/bind9/lib/export/dns/include/dst/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = dst.h gssapi.h lib.h result.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/dst
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${top_srcdir}/lib/dns/include/dst/$$i \
+ ${DESTDIR}${export_includedir}/dst ; \
+ done
diff --git a/contrib/bind9/lib/export/irs/Makefile.in b/contrib/bind9/lib/export/irs/Makefile.in
new file mode 100644
index 0000000..aad9400
--- /dev/null
+++ b/contrib/bind9/lib/export/irs/Makefile.in
@@ -0,0 +1,86 @@
+# Copyright (C) 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: Makefile.in,v 1.4 2009-12-05 23:31:40 each Exp $
+
+top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/irs
+export_srcdir = @top_srcdir@/lib/export
+
+@BIND9_VERSION@
+
+@LIBIRS_API@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I. -I./include -I${srcdir}/include \
+ ${ISCCFG_INCLUDES} -I../dns/include ${DNS_INCLUDES} \
+ -I${export_srcdir}/isc/include ${ISC_INCLUDES}
+CDEFINES =
+CWARNINGS =
+
+# Alphabetically
+OBJS = context.@O@ \
+ dnsconf.@O@ \
+ gai_strerror.@O@ getaddrinfo.@O@ getnameinfo.@O@ \
+ resconf.@O@
+
+# Alphabetically
+SRCS = context.c \
+ dnsconf.c \
+ gai_sterror.c getaddrinfo.c getnameinfo.c \
+ resconf.c
+
+ISCLIBS = ../isc/libisc.@A@
+DNSLIBS = ../dns/libdns.@A@
+ISCCFGLIBS = ../isccfg/libisccfg.@A@
+
+LIBS = @LIBS@
+
+SUBDIRS = include
+TARGETS = timestamp
+
+@BIND9_MAKE_RULES@
+
+version.@O@: ${srcdir}/version.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DLIBINTERFACE=${LIBINTERFACE} \
+ -DLIBREVISION=${LIBREVISION} \
+ -DLIBAGE=${LIBAGE} \
+ -c ${srcdir}/version.c
+
+libirs.@SA@: ${OBJS} version.@O@
+ ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@
+ ${RANLIB} $@
+
+libirs.la: ${OBJS} version.@O@
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs.la \
+ -rpath ${export_libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} version.@O@ ${LIBS} ${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS}
+
+timestamp: libirs.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libirs.@A@ \
+ ${DESTDIR}${export_libdir}
+
+clean distclean::
+ rm -f libirs.@A@ libirs.la timestamp
diff --git a/contrib/bind9/lib/export/irs/include/Makefile.in b/contrib/bind9/lib/export/irs/include/Makefile.in
new file mode 100644
index 0000000..e6d4eae
--- /dev/null
+++ b/contrib/bind9/lib/export/irs/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srdir@
+top_srcdir = @top_srcdir@
+
+
+SUBDIRS = irs
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/irs/include/irs/Makefile.in b/contrib/bind9/lib/export/irs/include/irs/Makefile.in
new file mode 100644
index 0000000..93f4200
--- /dev/null
+++ b/contrib/bind9/lib/export/irs/include/irs/Makefile.in
@@ -0,0 +1,46 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+#
+# Only list headers that are to be installed and are not
+# machine generated. The latter are handled specially in the
+# install target below.
+#
+HEADERS = context.h dnsconf.h resconf.h types.h version.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/irs
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/$$i \
+ ${DESTDIR}${export_includedir}/irs ; \
+ done
+ ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/netdb.h \
+ ${DESTDIR}${export_includedir}/irs
+ ${INSTALL_DATA} ${top_srcdir}/lib/irs/include/irs/platform.h \
+ ${DESTDIR}${export_includedir}/irs
+
+distclean::
+ rm -f netdb.h platform.h
diff --git a/contrib/bind9/lib/export/isc/Makefile.in b/contrib/bind9/lib/export/isc/Makefile.in
new file mode 100644
index 0000000..fa1c367
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/Makefile.in
@@ -0,0 +1,139 @@
+# Copyright (C) 2009, 2010 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: Makefile.in,v 1.8 2010-06-09 23:50:58 tbox Exp $
+
+top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/isc
+export_srcdir = @top_srcdir@/lib/export
+
+@BIND9_VERSION@
+
+@LIBISC_API@
+
+CINCLUDES = -I${srcdir}/unix/include \
+ -I${srcdir}/@ISC_THREAD_DIR@/include \
+ -I${srcdir}/@ISC_ARCH_DIR@/include \
+ -I${export_srcdir}/isc/include -I${srcdir}/include \
+ @ISC_OPENSSL_INC@
+CDEFINES = @USE_OPENSSL@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \
+ -DUSE_SOCKETIMPREGISTER -DUSE_TASKIMPREGISTER \
+ -DUSE_TIMERIMPREGISTER
+CWARNINGS =
+
+# Alphabetically
+# {file,dir}.c is necessary for isclog
+# symtab.c is necessary for isccfg
+APIOBJS = app_api.@O@ mem_api.@O@ socket_api.@O@ \
+ task_api.@O@ timer_api.@O@
+
+ISCDRIVEROBJS = mem.@O@ unix/socket.@O@ task.@O@ timer.@O@ lib.@O@ \
+ heap.@O@ #timer module depends on this
+
+UNIXOBJS = @ISC_ISCIPV6_O@ \
+ unix/app.@O@ \
+ unix/dir.@O@ \
+ unix/errno2result.@O@ \
+ unix/file.@O@ \
+ unix/fsaccess.@O@ \
+ unix/stdio.@O@ \
+ unix/stdtime.@O@ unix/strerror.@O@ unix/time.@O@
+
+NLSOBJS = nls/msgcat.@O@
+
+THREADOPTOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@
+
+THREADOBJS = @THREADOPTOBJS@ @ISC_THREAD_DIR@/thread.@O@
+
+WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \
+ win32/fsaccess.@O@ win32/once.@O@ win32/stdtime.@O@ \
+ win32/thread.@O@ win32/time.@O@
+
+# Alphabetically
+OBJS = @ISC_EXTRA_OBJS@ \
+ assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \
+ base64.@O@ buffer.@O@ bufferlist.@O@ \
+ error.@O@ event.@O@ \
+ hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \
+ inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \
+ md5.@O@ mutexblock.@O@ \
+ netaddr.@O@ netscope.@O@ \
+ ondestroy.@O@ \
+ parseint.@O@ portset.@O@ radix.@O@ \
+ random.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \
+ serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ string.@O@ \
+ symtab.@O@ \
+ version.@O@ \
+ ${APIOBJS} ${ISCDRIVEROBJS} \
+ ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS}
+
+# Alphabetically
+APISRCS = app_api.c mem_api.c socket_api.c \
+ task_api.c timer_api.c
+
+ISCDRIVERSRCS = mem.c task.c lib.c timer.c heap.c
+
+SRCS = @ISC_EXTRA_SRCS@ \
+ assertions.c backtrace.c backtrace-emptytbl.c base32.c \
+ base64.c buffer.c bufferlist.c \
+ error.c event.c \
+ hash.c hex.c hmacmd5.c hmacsha.c \
+ inet_aton.c iterated_hash.c lex.c log.c lfsr.c \
+ md5.c mutexblock.c \
+ netaddr.c netscope.c \
+ ondestroy.c \
+ parseint.c portset.c radix.c \
+ random.c refcount.c region.c result.c rwlock.c \
+ serial.c sha1.c sha2.c sockaddr.c stats.c string.c symtab.c \
+ version.c \
+ ${APISRCS} ${ISCDRIVERSRCS}
+
+LIBS = @LIBS@
+
+SUBDIRS = include unix nls @ISC_THREAD_DIR@
+TARGETS = timestamp
+
+@BIND9_MAKE_RULES@
+
+version.@O@: ${srcdir}/version.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DLIBINTERFACE=${LIBINTERFACE} \
+ -DLIBREVISION=${LIBREVISION} \
+ -DLIBAGE=${LIBAGE} \
+ -c ${srcdir}/version.c
+
+libisc.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+libisc.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la \
+ -rpath ${export_libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${LIBS}
+
+timestamp: libisc.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ \
+ ${DESTDIR}${export_libdir}
+
+clean distclean::
+ rm -f libisc.@A@ libisc.la timestamp
diff --git a/contrib/bind9/lib/export/isc/include/Makefile.in b/contrib/bind9/lib/export/isc/include/Makefile.in
new file mode 100644
index 0000000..f89628b
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srdir@
+top_srcdir = @top_srcdir@
+
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isc/include/isc/Makefile.in b/contrib/bind9/lib/export/isc/include/isc/Makefile.in
new file mode 100644
index 0000000..0336ba2
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/include/isc/Makefile.in
@@ -0,0 +1,66 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-12-05 23:31:41 each Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+export_srcdir = @top_srcdir@/lib/export
+
+@BIND9_VERSION@
+
+#
+# Only list headers that are to be installed and are not
+# machine generated. The latter are handled specially in the
+# install target below.
+#
+HEADERS = app.h assertions.h base64.h bitstring.h boolean.h \
+ buffer.h bufferlist.h commandline.h entropy.h error.h event.h \
+ eventclass.h file.h formatcheck.h fsaccess.h \
+ hash.h heap.h hex.h hmacmd5.h \
+ httpd.h \
+ interfaceiter.h @ISC_IPV6_H@ iterated_hash.h lang.h lex.h \
+ lfsr.h lib.h list.h log.h \
+ magic.h md5.h mem.h msgcat.h msgs.h \
+ mutexblock.h namespace.h netaddr.h ondestroy.h os.h parseint.h \
+ print.h quota.h radix.h random.h ratelimiter.h \
+ refcount.h region.h resource.h \
+ result.h resultclass.h rwlock.h serial.h sha1.h sha2.h \
+ sockaddr.h socket.h stdio.h stdlib.h string.h \
+ symtab.h \
+ task.h taskpool.h timer.h types.h util.h version.h \
+ xml.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${top_srcdir}/lib/isc/include/isc/$$i \
+ ${DESTDIR}${export_includedir}/isc ; \
+ done
+ ${INSTALL_DATA} ${top_srcdir}/lib/isc/include/isc/platform.h \
+ ${DESTDIR}${export_includedir}/isc
+ ${INSTALL_DATA} ${top_srcdir}/lib/isc/@ISC_ARCH_DIR@/include/isc/atomic.h \
+ ${DESTDIR}${export_includedir}/isc
+ ${INSTALL_DATA} ${export_srcdir}/isc/include/isc/bind9.h \
+ ${DESTDIR}${export_includedir}/isc
+
+distclean::
+ rm -f platform.h
diff --git a/contrib/bind9/lib/export/isc/include/isc/bind9.h b/contrib/bind9/lib/export/isc/include/isc/bind9.h
new file mode 100644
index 0000000..380ca85
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/include/isc/bind9.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 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: bind9.h,v 1.2 2009-12-05 23:31:41 each Exp $ */
+
+#ifndef ISC_BIND9_H
+#define ISC_BIND9_H 1
+
+/*
+ * This determines whether we are building BIND9 or using the exported
+ * libisc/libdns libraries. The version of this file included in the
+ * standard BIND9 build defines BIND9; the version included with the
+ * exportable libraries does not.
+ */
+#undef BIND9
+
+#endif /* ISC_BIND9_H */
diff --git a/contrib/bind9/lib/export/isc/nls/Makefile.in b/contrib/bind9/lib/export/isc/nls/Makefile.in
new file mode 100644
index 0000000..da2513f
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/nls/Makefile.in
@@ -0,0 +1,35 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/isc/nls
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/unix/include \
+ ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+OBJS = msgcat.@O@
+
+SRCS = msgcat.c
+
+SUBDIRS =
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isc/nothreads/Makefile.in b/contrib/bind9/lib/export/isc/nothreads/Makefile.in
new file mode 100644
index 0000000..3bffb4e
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/nothreads/Makefile.in
@@ -0,0 +1,40 @@
+# Copyright (C) 2009, 2010 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: Makefile.in,v 1.5 2010-06-09 23:50:58 tbox Exp $
+
+top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/isc/nothreads
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include \
+ -I${srcdir}/../unix/include \
+ -I../include \
+ -I${srcdir}/../include \
+ -I${srcdir}/..
+
+CDEFINES =
+CWARNINGS =
+
+THREADOPTOBJS = condition.@O@ mutex.@O@
+OBJS = @THREADOPTOBJS@ thread.@O@
+
+THREADOPTSRCS = condition.c mutex.c
+SRCS = @THREADOPTSRCS@ thread.c
+
+SUBDIRS = include
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isc/nothreads/include/Makefile.in b/contrib/bind9/lib/export/isc/nothreads/include/Makefile.in
new file mode 100644
index 0000000..f89628b
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/nothreads/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srdir@
+top_srcdir = @top_srcdir@
+
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isc/nothreads/include/isc/Makefile.in b/contrib/bind9/lib/export/isc/nothreads/include/isc/Makefile.in
new file mode 100644
index 0000000..423f10a
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/nothreads/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = condition.h mutex.h once.h thread.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(top_srcdir)/lib/isc/nothreads/include/isc/$$i \
+ ${DESTDIR}${export_includedir}/isc ; \
+ done
diff --git a/contrib/bind9/lib/export/isc/pthreads/Makefile.in b/contrib/bind9/lib/export/isc/pthreads/Makefile.in
new file mode 100644
index 0000000..5fac018
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/pthreads/Makefile.in
@@ -0,0 +1,38 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/isc/pthreads
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include \
+ -I${srcdir}/../unix/include \
+ -I../include \
+ -I${srcdir}/../include \
+ -I${srcdir}/..
+
+CDEFINES =
+CWARNINGS =
+
+OBJS = condition.@O@ mutex.@O@ thread.@O@
+
+SRCS = condition.c mutex.c thread.c
+
+SUBDIRS = include
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isc/pthreads/include/Makefile.in b/contrib/bind9/lib/export/isc/pthreads/include/Makefile.in
new file mode 100644
index 0000000..f89628b
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/pthreads/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srdir@
+top_srcdir = @top_srcdir@
+
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isc/pthreads/include/isc/Makefile.in b/contrib/bind9/lib/export/isc/pthreads/include/isc/Makefile.in
new file mode 100644
index 0000000..807de94
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/pthreads/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = condition.h mutex.h once.h thread.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(top_srcdir)/lib/isc/pthreads/include/isc/$$i \
+ ${DESTDIR}${export_includedir}/isc ; \
+ done
diff --git a/contrib/bind9/lib/export/isc/unix/Makefile.in b/contrib/bind9/lib/export/isc/unix/Makefile.in
new file mode 100644
index 0000000..81746a4
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/unix/Makefile.in
@@ -0,0 +1,57 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/isc/unix
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include \
+ -I${srcdir}/../@ISC_THREAD_DIR@/include \
+ -I../include \
+ -I${srcdir}/../include \
+ -I${srcdir}/..
+
+CDEFINES = -DUSE_SOCKETIMPREGISTER -DUSE_APPIMPREGISTER
+
+CWARNINGS =
+
+# Alphabetically
+ISCDRIVEROBJS = app.@O@ socket.@O@
+
+OBJS = @ISC_IPV6_O@ \
+ dir.@O@ \
+ errno2result.@O@ \
+ file.@O@ fsaccess.@O@ \
+ stdio.@O@ stdtime.@O@ strerror.@O@ \
+ time.@O@ \
+ ${ISCDRIVEROBJS}
+
+# Alphabetically
+ISCDRIVERSRCS = app.c socket.c
+
+SRCS = @ISC_IPV6_C@ \
+ dir.c \
+ errno2result.c \
+ file.c fsaccess.c \
+ stdio.c stdtime.c strerror.c \
+ time.c \
+ ${ISCDRIVERSRCS}
+
+SUBDIRS = include
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isc/unix/include/Makefile.in b/contrib/bind9/lib/export/isc/unix/include/Makefile.in
new file mode 100644
index 0000000..f89628b
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/unix/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srdir@
+top_srcdir = @top_srcdir@
+
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isc/unix/include/isc/Makefile.in b/contrib/bind9/lib/export/isc/unix/include/isc/Makefile.in
new file mode 100644
index 0000000..21ce049
--- /dev/null
+++ b/contrib/bind9/lib/export/isc/unix/include/isc/Makefile.in
@@ -0,0 +1,37 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = dir.h int.h net.h netdb.h offset.h stdtime.h \
+ syslog.h time.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(top_srcdir)/lib/isc/unix/include/isc/$$i \
+ ${DESTDIR}${export_includedir}/isc ; \
+ done
diff --git a/contrib/bind9/lib/export/isccfg/Makefile.in b/contrib/bind9/lib/export/isccfg/Makefile.in
new file mode 100644
index 0000000..ed2b2cf
--- /dev/null
+++ b/contrib/bind9/lib/export/isccfg/Makefile.in
@@ -0,0 +1,83 @@
+# Copyright (C) 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: Makefile.in,v 1.4 2009-12-05 23:31:41 each Exp $
+
+top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/isccfg
+export_srcdir = @top_srcdir@/lib/export
+
+@BIND9_VERSION@
+
+@LIBISCCFG_API@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I. ${DNS_INCLUDES} -I${export_srcdir}/isc/include \
+ ${ISC_INCLUDES} ${ISCCFG_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../isc/libisc.@A@
+DNSLIBS = ../dns/libdns.@A@
+
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS = libisccfg.@A@
+
+LIBS = @LIBS@
+
+SUBDIRS = include
+
+# Alphabetically
+OBJS = dnsconf.@O@ log.@O@ parser.@O@ version.@O@
+
+# Alphabetically
+SRCS = dnsconf.c log.c parser.c version.c
+
+TARGETS = timestamp
+
+@BIND9_MAKE_RULES@
+
+version.@O@: ${srcdir}/version.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DLIBINTERFACE=${LIBINTERFACE} \
+ -DLIBREVISION=${LIBREVISION} \
+ -DLIBAGE=${LIBAGE} \
+ -c ${srcdir}/version.c
+
+libisccfg.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+libisccfg.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccfg.la \
+ -rpath ${export_libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${LIBS} ${DNSLIBS} ${ISCLIBS}
+
+timestamp: libisccfg.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisccfg.@A@ \
+ ${DESTDIR}${export_libdir}
+
+clean distclean::
+ rm -f libisccfg.@A@ timestamp
diff --git a/contrib/bind9/lib/export/isccfg/include/Makefile.in b/contrib/bind9/lib/export/isccfg/include/Makefile.in
new file mode 100644
index 0000000..896c467
--- /dev/null
+++ b/contrib/bind9/lib/export/isccfg/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 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: Makefile.in,v 1.2 2009-09-01 00:22:27 jinmei Exp $
+
+srcdir = @srdir@
+top_srcdir = @top_srcdir@
+
+
+SUBDIRS = isccfg
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/export/isccfg/include/isccfg/Makefile.in b/contrib/bind9/lib/export/isccfg/include/isccfg/Makefile.in
new file mode 100644
index 0000000..3f97894
--- /dev/null
+++ b/contrib/bind9/lib/export/isccfg/include/isccfg/Makefile.in
@@ -0,0 +1,42 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+#
+# Only list headers that are to be installed and are not
+# machine generated. The latter are handled specially in the
+# install target below.
+#
+HEADERS = cfg.h grammar.h log.h dnsconf.h version.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs \
+ ${DESTDIR}${export_includedir}/isccfg
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${top_srcdir}/lib/isccfg/include/isccfg/$$i \
+ ${DESTDIR}${export_includedir}/isccfg ; \
+ done
diff --git a/contrib/bind9/lib/export/samples/Makefile-postinstall.in b/contrib/bind9/lib/export/samples/Makefile-postinstall.in
new file mode 100644
index 0000000..10a26f4
--- /dev/null
+++ b/contrib/bind9/lib/export/samples/Makefile-postinstall.in
@@ -0,0 +1,78 @@
+# Copyright (C) 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: Makefile-postinstall.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+#prefix = @prefix@
+#exec_prefix = @exec_prefix@
+
+CDEFINES =
+CWARNINGS =
+
+DNSLIBS = -ldns @DNS_CRYPTO_LIBS@
+ISCLIBS = -lisc
+ISCCFGLIBS = -lisccfg
+IRSLIBS = -lirs
+
+LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@
+
+SUBDIRS =
+
+TARGETS = sample@EXEEXT@ sample-async@EXEEXT@ sample-gai@EXEEXT@ \
+ sample-update@EXEEXT@ sample-request@EXEEXT@ nsprobe@EXEEXT@ \
+ dlvchecks@EXEEXT@
+
+OBJS = sample.@O@ sample-async.@O@ sample-gai.@O@ sample-update.@O@ \
+ sample-request.@O@ nsprobe.@O@ dlvchecks.@O@
+
+SRCS = sample.c sample-async.c sample-gai.c sample-update.c \
+ sample-request.c nsprobe.c dlvchecks..c
+
+@BIND9_MAKE_RULES@
+
+# The following two may depend on BIND9_MAKE_RULES
+CINCLUDES = -I@export_includedir@
+LDFLAGS = -L@export_libdir@
+
+sample@EXEEXT@: sample.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample.@O@ ${LIBS}
+
+sample-async@EXEEXT@: sample-async.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample-async.@O@ ${LIBS}
+
+sample-gai@EXEEXT@: sample-gai.@O@ ${IRSDEPLIBS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample-gai.@O@ ${IRSLIBS} ${LIBS}
+
+sample-update@EXEEXT@: sample-update.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample-update.@O@ ${LIBS}
+
+sample-request@EXEEXT@: sample-request.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample-request.@O@ ${LIBS}
+
+nsprobe@EXEEXT@: nsprobe.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ nsprobe.@O@ ${LIBS}
+
+dlvchecks@EXEEXT@: dlvchecks.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dlvchecks.@O@ ${LIBS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
diff --git a/contrib/bind9/lib/export/samples/Makefile.in b/contrib/bind9/lib/export/samples/Makefile.in
new file mode 100644
index 0000000..ff8e916
--- /dev/null
+++ b/contrib/bind9/lib/export/samples/Makefile.in
@@ -0,0 +1,98 @@
+# Copyright (C) 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: Makefile.in,v 1.4 2009-12-05 23:31:41 each Exp $
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+export_srcdir = @top_srcdir@/lib/export
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include -I../dns/include \
+ -I${export_srcdir}/isc/include \
+ ${DNS_INCLUDES} ${ISC_INCLUDES} \
+ -I${top_srcdir}/lib/irs/include
+
+CDEFINES =
+CWARNINGS =
+
+DNSLIBS = ../dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../isc/libisc.@A@
+ISCCFGLIBS = ../isccfg/libisccfg.@A@
+IRSLIBS = ../irs/libirs.@A@
+
+DNSDEPLIBS = ../dns/libdns.@A@
+ISCDEPLIBS = ../isc/libisc.@A@
+ISCCFGDEPLIBS = ../isccfg/libisccfg.@A@
+IRSDEPLIBS = ../irs/libirs.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@
+
+SUBDIRS =
+
+TARGETS = sample@EXEEXT@ sample-async@EXEEXT@ sample-gai@EXEEXT@ \
+ sample-update@EXEEXT@ sample-request@EXEEXT@ nsprobe@EXEEXT@
+
+OBJS = sample.@O@ sample-async.@O@ sample-gai.@O@ sample-update.@O@ \
+ sample-request.@O@ nsprobe.@O@
+
+UOBJS =
+
+SRCS = sample.c sample-async.c sample-gai.c sample-update.c \
+ sample-request.c nsprobe.c
+
+MANPAGES =
+
+HTMLPAGES =
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+sample@EXEEXT@: sample.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample.@O@ ${LIBS}
+
+sample-async@EXEEXT@: sample-async.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample-async.@O@ ${LIBS}
+
+sample-gai@EXEEXT@: sample-gai.@O@ ${IRSDEPLIBS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample-gai.@O@ ${IRSLIBS} ${LIBS}
+
+sample-update@EXEEXT@: sample-update.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample-update.@O@ ${LIBS}
+
+sample-request@EXEEXT@: sample-request.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ sample-request.@O@ ${LIBS}
+
+nsprobe@EXEEXT@: nsprobe.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ nsprobe.@O@ ${LIBS}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
diff --git a/contrib/bind9/lib/export/samples/nsprobe.c b/contrib/bind9/lib/export/samples/nsprobe.c
new file mode 100644
index 0000000..85c572d
--- /dev/null
+++ b/contrib/bind9/lib/export/samples/nsprobe.c
@@ -0,0 +1,1220 @@
+/*
+ * Copyright (C) 2009, 2010 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: nsprobe.c,v 1.7 2010-01-07 23:48:54 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/socket.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/lib.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+#define MAX_PROBES 1000
+
+static dns_client_t *client = NULL;
+static isc_task_t *probe_task = NULL;
+static isc_appctx_t *actx = NULL;
+static isc_mem_t *mctx = NULL;
+static unsigned int outstanding_probes = 0;
+const char *cacheserver = "127.0.0.1";
+static FILE *fp;
+
+typedef enum {
+ none,
+ exist,
+ nxdomain,
+ othererr,
+ multiplesoa,
+ multiplecname,
+ brokenanswer,
+ lame,
+ timedout,
+ notype,
+ unexpected
+} query_result_t;
+
+struct server {
+ ISC_LINK(struct server) link;
+
+ isc_sockaddr_t address;
+ query_result_t result_a;
+ query_result_t result_aaaa;
+};
+
+struct probe_ns {
+ ISC_LINK(struct probe_ns) link;
+
+ dns_fixedname_t fixedname;
+ dns_name_t *name;
+ struct server *current_server;
+ ISC_LIST(struct server) servers;
+};
+
+struct probe_trans {
+ isc_boolean_t inuse;
+ char *domain;
+ dns_fixedname_t fixedname;
+ dns_name_t *qname;
+ const char **qlabel;
+ isc_boolean_t qname_found;
+ dns_clientrestrans_t *resid;
+ dns_message_t *qmessage;
+ dns_message_t *rmessage;
+ dns_clientreqtrans_t *reqid;
+
+ /* NS list */
+ struct probe_ns *current_ns;
+ ISC_LIST(struct probe_ns) nslist;
+};
+
+struct lcl_stat {
+ unsigned long valid;
+ unsigned long ignore;
+ unsigned long nxdomain;
+ unsigned long othererr;
+ unsigned long multiplesoa;
+ unsigned long multiplecname;
+ unsigned long brokenanswer;
+ unsigned long lame;
+ unsigned long unknown;
+} server_stat, domain_stat;
+
+static unsigned long number_of_domains = 0;
+static unsigned long number_of_servers = 0;
+static unsigned long multiple_error_domains = 0;
+static isc_boolean_t debug_mode = ISC_FALSE;
+static int verbose_level = 0;
+static const char *qlabels[] = {"www.", "ftp.", NULL};
+static struct probe_trans probes[MAX_PROBES];
+
+static isc_result_t probe_domain(struct probe_trans *trans);
+static void reset_probe(struct probe_trans *trans);
+static isc_result_t fetch_nsaddress(struct probe_trans *trans);
+static isc_result_t probe_name(struct probe_trans *trans,
+ dns_rdatatype_t type);
+
+/* Dump an rdataset for debug */
+static isc_result_t
+print_rdataset(dns_rdataset_t *rdataset, dns_name_t *owner) {
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char t[4096];
+
+ if (!debug_mode)
+ return (ISC_R_SUCCESS);
+
+ isc_buffer_init(&target, t, sizeof(t));
+
+ if (!dns_rdataset_isassociated(rdataset))
+ return (ISC_R_SUCCESS);
+ result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+print_name(dns_name_t *name) {
+ isc_result_t result;
+ isc_buffer_t target;
+ isc_region_t r;
+ char t[4096];
+
+ isc_buffer_init(&target, t, sizeof(t));
+ result = dns_name_totext(name, ISC_TRUE, &target);
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+ } else
+ printf("(invalid name)");
+
+ return (result);
+}
+
+static isc_result_t
+print_address(FILE *fp, isc_sockaddr_t *addr) {
+ char buf[NI_MAXHOST];
+
+ if (getnameinfo(&addr->type.sa, addr->length, buf, sizeof(buf),
+ NULL, 0, NI_NUMERICHOST) == 0) {
+ fprintf(fp, "%s", buf);
+ } else {
+ fprintf(fp, "(invalid address)");
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp,
+ isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
+ isc_timermgr_t **timermgrp)
+{
+ if (*taskmgrp != NULL)
+ isc_taskmgr_destroy(taskmgrp);
+
+ if (*timermgrp != NULL)
+ isc_timermgr_destroy(timermgrp);
+
+ if (*socketmgrp != NULL)
+ isc_socketmgr_destroy(socketmgrp);
+
+ if (*actxp != NULL)
+ isc_appctx_destroy(actxp);
+
+ if (*mctxp != NULL)
+ isc_mem_destroy(mctxp);
+}
+
+static isc_result_t
+ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp,
+ isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
+ isc_timermgr_t **timermgrp)
+{
+ isc_result_t result;
+
+ result = isc_mem_create(0, 0, mctxp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_appctx_create(*mctxp, actxp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp);
+
+ return (result);
+}
+
+/*
+ * Common routine to make query data
+ */
+static isc_result_t
+make_querymessage(dns_message_t *message, dns_name_t *qname0,
+ dns_rdatatype_t rdtype)
+{
+ dns_name_t *qname = NULL;
+ dns_rdataset_t *qrdataset = NULL;
+ isc_result_t result;
+
+ message->opcode = dns_opcode_query;
+ message->rdclass = dns_rdataclass_in;
+
+ result = dns_message_gettempname(message, &qname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_name_init(qname, NULL);
+ dns_name_clone(qname0, qname);
+ dns_rdataset_init(qrdataset);
+ dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ dns_message_addname(message, qname, DNS_SECTION_QUESTION);
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (qname != NULL)
+ dns_message_puttempname(message, &qname);
+ if (qrdataset != NULL)
+ dns_message_puttemprdataset(message, &qrdataset);
+ if (message != NULL)
+ dns_message_destroy(&message);
+ return (result);
+}
+
+/*
+ * Update statistics
+ */
+static inline void
+increment_entry(unsigned long *entryp) {
+ (*entryp)++;
+ INSIST(*entryp != 0); /* check overflow */
+}
+
+static void
+update_stat(struct probe_trans *trans) {
+ struct probe_ns *pns;
+ struct server *server;
+ struct lcl_stat local_stat;
+ unsigned int err_count = 0;
+ const char *stattype;
+
+ increment_entry(&number_of_domains);
+ memset(&local_stat, 0, sizeof(local_stat));
+
+ /* Update per sever statistics */
+ for (pns = ISC_LIST_HEAD(trans->nslist); pns != NULL;
+ pns = ISC_LIST_NEXT(pns, link)) {
+ for (server = ISC_LIST_HEAD(pns->servers); server != NULL;
+ server = ISC_LIST_NEXT(server, link)) {
+ increment_entry(&number_of_servers);
+
+ if (server->result_aaaa == exist ||
+ server->result_aaaa == notype) {
+ /*
+ * Don't care about the result of A query if
+ * the answer to AAAA query was expected.
+ */
+ stattype = "valid";
+ increment_entry(&server_stat.valid);
+ increment_entry(&local_stat.valid);
+ } else if (server->result_a == exist) {
+ switch (server->result_aaaa) {
+ case exist:
+ case notype:
+ stattype = "valid";
+ increment_entry(&server_stat.valid);
+ increment_entry(&local_stat.valid);
+ break;
+ case timedout:
+ stattype = "ignore";
+ increment_entry(&server_stat.ignore);
+ increment_entry(&local_stat.ignore);
+ break;
+ case nxdomain:
+ stattype = "nxdomain";
+ increment_entry(&server_stat.nxdomain);
+ increment_entry(&local_stat.nxdomain);
+ break;
+ case othererr:
+ stattype = "othererr";
+ increment_entry(&server_stat.othererr);
+ increment_entry(&local_stat.othererr);
+ break;
+ case multiplesoa:
+ stattype = "multiplesoa";
+ increment_entry(&server_stat.multiplesoa);
+ increment_entry(&local_stat.multiplesoa);
+ break;
+ case multiplecname:
+ stattype = "multiplecname";
+ increment_entry(&server_stat.multiplecname);
+ increment_entry(&local_stat.multiplecname);
+ break;
+ case brokenanswer:
+ stattype = "brokenanswer";
+ increment_entry(&server_stat.brokenanswer);
+ increment_entry(&local_stat.brokenanswer);
+ break;
+ case lame:
+ stattype = "lame";
+ increment_entry(&server_stat.lame);
+ increment_entry(&local_stat.lame);
+ break;
+ default:
+ stattype = "unknown";
+ increment_entry(&server_stat.unknown);
+ increment_entry(&local_stat.unknown);
+ break;
+ }
+ } else {
+ stattype = "unknown";
+ increment_entry(&server_stat.unknown);
+ increment_entry(&local_stat.unknown);
+ }
+
+ if (verbose_level > 1 ||
+ (verbose_level == 1 &&
+ strcmp(stattype, "valid") != 0 &&
+ strcmp(stattype, "unknown") != 0)) {
+ print_name(pns->name);
+ putchar('(');
+ print_address(stdout, &server->address);
+ printf(") for %s:%s\n", trans->domain,
+ stattype);
+ }
+ }
+ }
+
+ /* Update per domain statistics */
+ if (local_stat.ignore > 0) {
+ if (verbose_level > 0)
+ printf("%s:ignore\n", trans->domain);
+ increment_entry(&domain_stat.ignore);
+ err_count++;
+ }
+ if (local_stat.nxdomain > 0) {
+ if (verbose_level > 0)
+ printf("%s:nxdomain\n", trans->domain);
+ increment_entry(&domain_stat.nxdomain);
+ err_count++;
+ }
+ if (local_stat.othererr > 0) {
+ if (verbose_level > 0)
+ printf("%s:othererr\n", trans->domain);
+ increment_entry(&domain_stat.othererr);
+ err_count++;
+ }
+ if (local_stat.multiplesoa > 0) {
+ if (verbose_level > 0)
+ printf("%s:multiplesoa\n", trans->domain);
+ increment_entry(&domain_stat.multiplesoa);
+ err_count++;
+ }
+ if (local_stat.multiplecname > 0) {
+ if (verbose_level > 0)
+ printf("%s:multiplecname\n", trans->domain);
+ increment_entry(&domain_stat.multiplecname);
+ err_count++;
+ }
+ if (local_stat.brokenanswer > 0) {
+ if (verbose_level > 0)
+ printf("%s:brokenanswer\n", trans->domain);
+ increment_entry(&domain_stat.brokenanswer);
+ err_count++;
+ }
+ if (local_stat.lame > 0) {
+ if (verbose_level > 0)
+ printf("%s:lame\n", trans->domain);
+ increment_entry(&domain_stat.lame);
+ err_count++;
+ }
+
+ if (err_count > 1)
+ increment_entry(&multiple_error_domains);
+
+ /*
+ * We regard the domain as valid if and only if no authoritative server
+ * has a problem and at least one server is known to be valid.
+ */
+ if (local_stat.valid > 0 && err_count == 0) {
+ if (verbose_level > 1)
+ printf("%s:valid\n", trans->domain);
+ increment_entry(&domain_stat.valid);
+ }
+
+ /*
+ * If the domain has no available server or all servers have the
+ * 'unknown' result, the domain's result is also regarded as unknown.
+ */
+ if (local_stat.valid == 0 && err_count == 0) {
+ if (verbose_level > 1)
+ printf("%s:unknown\n", trans->domain);
+ increment_entry(&domain_stat.unknown);
+ }
+}
+
+/*
+ * Search for an existent name with an A RR
+ */
+
+static isc_result_t
+set_nextqname(struct probe_trans *trans) {
+ isc_result_t result;
+ size_t domainlen;
+ isc_buffer_t b;
+ char buf[4096]; /* XXX ad-hoc constant, but should be enough */
+
+ if (*trans->qlabel == NULL)
+ return (ISC_R_NOMORE);
+
+ result = isc_string_copy(buf, sizeof(buf), *trans->qlabel);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = isc_string_append(buf, sizeof(buf), trans->domain);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ domainlen = strlen(buf);
+ isc_buffer_init(&b, buf, domainlen);
+ isc_buffer_add(&b, domainlen);
+ dns_fixedname_init(&trans->fixedname);
+ trans->qname = dns_fixedname_name(&trans->fixedname);
+ result = dns_name_fromtext(trans->qname, &b, dns_rootname,
+ 0, NULL);
+
+ trans->qlabel++;
+
+ return (result);
+}
+
+static void
+request_done(isc_task_t *task, isc_event_t *event) {
+ struct probe_trans *trans = event->ev_arg;
+ dns_clientreqevent_t *rev = (dns_clientreqevent_t *)event;
+ dns_message_t *rmessage;
+ struct probe_ns *pns;
+ struct server *server;
+ isc_result_t result;
+ query_result_t *resultp;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ dns_rdatatype_t type;
+
+ REQUIRE(task == probe_task);
+ REQUIRE(trans != NULL && trans->inuse == ISC_TRUE);
+ rmessage = rev->rmessage;
+ REQUIRE(rmessage == trans->rmessage);
+ INSIST(outstanding_probes > 0);
+
+ server = trans->current_ns->current_server;
+ INSIST(server != NULL);
+
+ if (server->result_a == none) {
+ type = dns_rdatatype_a;
+ resultp = &server->result_a;
+ } else {
+ resultp = &server->result_aaaa;
+ type = dns_rdatatype_aaaa;
+ }
+
+ if (rev->result == ISC_R_SUCCESS) {
+ if ((rmessage->flags & DNS_MESSAGEFLAG_AA) == 0)
+ *resultp = lame;
+ else if (rmessage->rcode == dns_rcode_nxdomain)
+ *resultp = nxdomain;
+ else if (rmessage->rcode != dns_rcode_noerror)
+ *resultp = othererr;
+ else if (rmessage->counts[DNS_SECTION_ANSWER] == 0) {
+ /* no error but empty answer */
+ *resultp = notype;
+ } else {
+ result = dns_message_firstname(rmessage,
+ DNS_SECTION_ANSWER);
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(rmessage,
+ DNS_SECTION_ANSWER,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset,
+ link)) {
+ (void)print_rdataset(rdataset, name);
+
+ if (rdataset->type ==
+ dns_rdatatype_cname ||
+ rdataset->type ==
+ dns_rdatatype_dname) {
+ /* Should chase the chain? */
+ *resultp = exist;
+ goto found;
+ } else if (rdataset->type == type) {
+ *resultp = exist;
+ goto found;
+ }
+ }
+ result = dns_message_nextname(rmessage,
+ DNS_SECTION_ANSWER);
+ }
+
+ /*
+ * Something unexpected happened: the response
+ * contained a non-empty authoritative answer, but we
+ * could not find an expected result.
+ */
+ *resultp = unexpected;
+ }
+ } else if (rev->result == DNS_R_RECOVERABLE ||
+ rev->result == DNS_R_BADLABELTYPE) {
+ /* Broken response. Try identifying known cases. */
+ *resultp = brokenanswer;
+
+ if (rmessage->counts[DNS_SECTION_ANSWER] > 0) {
+ result = dns_message_firstname(rmessage,
+ DNS_SECTION_ANSWER);
+ while (result == ISC_R_SUCCESS) {
+ /*
+ * Check to see if the response has multiple
+ * CNAME RRs. Update the result code if so.
+ */
+ name = NULL;
+ dns_message_currentname(rmessage,
+ DNS_SECTION_ANSWER,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset,
+ link)) {
+ if (rdataset->type ==
+ dns_rdatatype_cname &&
+ dns_rdataset_count(rdataset) > 1) {
+ *resultp = multiplecname;
+ goto found;
+ }
+ }
+ result = dns_message_nextname(rmessage,
+ DNS_SECTION_ANSWER);
+ }
+ }
+
+ if (rmessage->counts[DNS_SECTION_AUTHORITY] > 0) {
+ result = dns_message_firstname(rmessage,
+ DNS_SECTION_AUTHORITY);
+ while (result == ISC_R_SUCCESS) {
+ /*
+ * Check to see if the response has multiple
+ * SOA RRs. Update the result code if so.
+ */
+ name = NULL;
+ dns_message_currentname(rmessage,
+ DNS_SECTION_AUTHORITY,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset,
+ link)) {
+ if (rdataset->type ==
+ dns_rdatatype_soa &&
+ dns_rdataset_count(rdataset) > 1) {
+ *resultp = multiplesoa;
+ goto found;
+ }
+ }
+ result = dns_message_nextname(rmessage,
+ DNS_SECTION_AUTHORITY);
+ }
+ }
+ } else if (rev->result == ISC_R_TIMEDOUT)
+ *resultp = timedout;
+ else {
+ fprintf(stderr, "unexpected result: %d (domain=%s, server=",
+ rev->result, trans->domain);
+ print_address(stderr, &server->address);
+ fputc('\n', stderr);
+ *resultp = unexpected;
+ }
+
+ found:
+ INSIST(*resultp != none);
+ if (type == dns_rdatatype_a && *resultp == exist)
+ trans->qname_found = ISC_TRUE;
+
+ dns_client_destroyreqtrans(&trans->reqid);
+ isc_event_free(&event);
+ dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE);
+
+ result = probe_name(trans, type);
+ if (result == ISC_R_NOMORE) {
+ /* We've tried all addresses of all servers. */
+ if (type == dns_rdatatype_a && trans->qname_found) {
+ /*
+ * If we've explored A RRs and found an existent
+ * record, we can move to AAAA.
+ */
+ trans->current_ns = ISC_LIST_HEAD(trans->nslist);
+ probe_name(trans, dns_rdatatype_aaaa);
+ result = ISC_R_SUCCESS;
+ } else if (type == dns_rdatatype_a) {
+ /*
+ * No server provided an existent A RR of this name.
+ * Try next label.
+ */
+ dns_fixedname_invalidate(&trans->fixedname);
+ trans->qname = NULL;
+ result = set_nextqname(trans);
+ if (result == ISC_R_SUCCESS) {
+ trans->current_ns =
+ ISC_LIST_HEAD(trans->nslist);
+ for (pns = trans->current_ns; pns != NULL;
+ pns = ISC_LIST_NEXT(pns, link)) {
+ for (server = ISC_LIST_HEAD(pns->servers);
+ server != NULL;
+ server = ISC_LIST_NEXT(server,
+ link)) {
+ INSIST(server->result_aaaa ==
+ none);
+ server->result_a = none;
+ }
+ }
+ result = probe_name(trans, dns_rdatatype_a);
+ }
+ }
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * We've explored AAAA RRs or failed to find a valid
+ * query label. Wrap up the result and move to the
+ * next domain.
+ */
+ reset_probe(trans);
+ }
+ } else if (result != ISC_R_SUCCESS)
+ reset_probe(trans); /* XXX */
+}
+
+static isc_result_t
+probe_name(struct probe_trans *trans, dns_rdatatype_t type) {
+ isc_result_t result;
+ struct probe_ns *pns;
+ struct server *server;
+
+ REQUIRE(trans->reqid == NULL);
+ REQUIRE(type == dns_rdatatype_a || type == dns_rdatatype_aaaa);
+
+ for (pns = trans->current_ns; pns != NULL;
+ pns = ISC_LIST_NEXT(pns, link)) {
+ for (server = ISC_LIST_HEAD(pns->servers); server != NULL;
+ server = ISC_LIST_NEXT(server, link)) {
+ if ((type == dns_rdatatype_a &&
+ server->result_a == none) ||
+ (type == dns_rdatatype_aaaa &&
+ server->result_aaaa == none)) {
+ pns->current_server = server;
+ goto found;
+ }
+ }
+ }
+
+ found:
+ trans->current_ns = pns;
+ if (pns == NULL)
+ return (ISC_R_NOMORE);
+
+ INSIST(pns->current_server != NULL);
+ dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER);
+ result = make_querymessage(trans->qmessage, trans->qname, type);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_client_startrequest(client, trans->qmessage,
+ trans->rmessage,
+ &pns->current_server->address,
+ 0, DNS_MESSAGEPARSE_BESTEFFORT,
+ NULL, 120, 0, 4,
+ probe_task, request_done, trans,
+ &trans->reqid);
+
+ return (result);
+}
+
+/*
+ * Get IP addresses of NSes
+ */
+
+static void
+resolve_nsaddress(isc_task_t *task, isc_event_t *event) {
+ struct probe_trans *trans = event->ev_arg;
+ dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ struct probe_ns *pns = trans->current_ns;
+ isc_result_t result;
+
+ REQUIRE(task == probe_task);
+ REQUIRE(trans->inuse == ISC_TRUE);
+ REQUIRE(pns != NULL);
+ INSIST(outstanding_probes > 0);
+
+ for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ (void)print_rdataset(rdataset, name);
+
+ if (rdataset->type != dns_rdatatype_a)
+ continue;
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_in_a_t rdata_a;
+ struct server *server;
+
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &rdata_a,
+ NULL);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ server = isc_mem_get(mctx, sizeof(*server));
+ if (server == NULL) {
+ fprintf(stderr, "resolve_nsaddress: "
+ "mem_get failed");
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ isc_sockaddr_fromin(&server->address,
+ &rdata_a.in_addr, 53);
+ ISC_LINK_INIT(server, link);
+ server->result_a = none;
+ server->result_aaaa = none;
+ ISC_LIST_APPEND(pns->servers, server, link);
+ }
+ }
+ }
+
+ cleanup:
+ dns_client_freeresanswer(client, &rev->answerlist);
+ dns_client_destroyrestrans(&trans->resid);
+ isc_event_free(&event);
+
+ next_ns:
+ trans->current_ns = ISC_LIST_NEXT(pns, link);
+ if (trans->current_ns == NULL) {
+ trans->current_ns = ISC_LIST_HEAD(trans->nslist);
+ dns_fixedname_invalidate(&trans->fixedname);
+ trans->qname = NULL;
+ result = set_nextqname(trans);
+ if (result == ISC_R_SUCCESS)
+ result = probe_name(trans, dns_rdatatype_a);
+ } else {
+ result = fetch_nsaddress(trans);
+ if (result != ISC_R_SUCCESS)
+ goto next_ns; /* XXX: this is unlikely to succeed */
+ }
+
+ if (result != ISC_R_SUCCESS)
+ reset_probe(trans);
+}
+
+static isc_result_t
+fetch_nsaddress(struct probe_trans *trans) {
+ struct probe_ns *pns;
+
+ pns = trans->current_ns;
+ REQUIRE(pns != NULL);
+
+ return (dns_client_startresolve(client, pns->name, dns_rdataclass_in,
+ dns_rdatatype_a, 0, probe_task,
+ resolve_nsaddress, trans,
+ &trans->resid));
+}
+
+/*
+ * Get NS RRset for a given domain
+ */
+
+static void
+reset_probe(struct probe_trans *trans) {
+ struct probe_ns *pns;
+ struct server *server;
+ isc_result_t result;
+
+ REQUIRE(trans->resid == NULL);
+ REQUIRE(trans->reqid == NULL);
+
+ update_stat(trans);
+
+ dns_message_reset(trans->qmessage, DNS_MESSAGE_INTENTRENDER);
+ dns_message_reset(trans->rmessage, DNS_MESSAGE_INTENTPARSE);
+
+ trans->inuse = ISC_FALSE;
+ if (trans->domain != NULL)
+ isc_mem_free(mctx, trans->domain);
+ trans->domain = NULL;
+ if (trans->qname != NULL)
+ dns_fixedname_invalidate(&trans->fixedname);
+ trans->qname = NULL;
+ trans->qlabel = qlabels;
+ trans->qname_found = ISC_FALSE;
+ trans->current_ns = NULL;
+
+ while ((pns = ISC_LIST_HEAD(trans->nslist)) != NULL) {
+ ISC_LIST_UNLINK(trans->nslist, pns, link);
+ while ((server = ISC_LIST_HEAD(pns->servers)) != NULL) {
+ ISC_LIST_UNLINK(pns->servers, server, link);
+ isc_mem_put(mctx, server, sizeof(*server));
+ }
+ isc_mem_put(mctx, pns, sizeof(*pns));
+ }
+
+ outstanding_probes--;
+
+ result = probe_domain(trans);
+ if (result == ISC_R_NOMORE && outstanding_probes == 0)
+ isc_app_ctxshutdown(actx);
+}
+
+static void
+resolve_ns(isc_task_t *task, isc_event_t *event) {
+ struct probe_trans *trans = event->ev_arg;
+ dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ struct probe_ns *pns;
+
+ REQUIRE(task == probe_task);
+ REQUIRE(trans->inuse == ISC_TRUE);
+ INSIST(outstanding_probes > 0);
+
+ for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ (void)print_rdataset(rdataset, name);
+
+ if (rdataset->type != dns_rdatatype_ns)
+ continue;
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_ns_t ns;
+
+ dns_rdataset_current(rdataset, &rdata);
+ /*
+ * Extract the name from the NS record.
+ */
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ pns = isc_mem_get(mctx, sizeof(*pns));
+ if (pns == NULL) {
+ fprintf(stderr,
+ "resolve_ns: mem_get failed");
+ result = ISC_R_NOMEMORY;
+ /*
+ * XXX: should we continue with the
+ * available servers anyway?
+ */
+ goto cleanup;
+ }
+
+ dns_fixedname_init(&pns->fixedname);
+ pns->name =
+ dns_fixedname_name(&pns->fixedname);
+ ISC_LINK_INIT(pns, link);
+ ISC_LIST_APPEND(trans->nslist, pns, link);
+ ISC_LIST_INIT(pns->servers);
+
+ dns_name_copy(&ns.name, pns->name, NULL);
+ dns_rdata_reset(&rdata);
+ dns_rdata_freestruct(&ns);
+ }
+ }
+ }
+
+ cleanup:
+ dns_client_freeresanswer(client, &rev->answerlist);
+ dns_client_destroyrestrans(&trans->resid);
+ isc_event_free(&event);
+
+ if (!ISC_LIST_EMPTY(trans->nslist)) {
+ /* Go get addresses of NSes */
+ trans->current_ns = ISC_LIST_HEAD(trans->nslist);
+ result = fetch_nsaddress(trans);
+ } else
+ result = ISC_R_FAILURE;
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ reset_probe(trans);
+}
+
+static isc_result_t
+probe_domain(struct probe_trans *trans) {
+ isc_result_t result;
+ size_t domainlen;
+ isc_buffer_t b;
+ char buf[4096]; /* XXX ad hoc constant, but should be enough */
+ char *cp;
+
+ REQUIRE(trans != NULL);
+ REQUIRE(trans->inuse == ISC_FALSE);
+ REQUIRE(outstanding_probes < MAX_PROBES);
+
+ /* Construct domain */
+ cp = fgets(buf, sizeof(buf), fp);
+ if (cp == NULL)
+ return (ISC_R_NOMORE);
+ if ((cp = strchr(buf, '\n')) != NULL) /* zap NL if any */
+ *cp = '\0';
+ trans->domain = isc_mem_strdup(mctx, buf);
+ if (trans->domain == NULL) {
+ fprintf(stderr,
+ "failed to allocate memory for domain: %s", cp);
+ return (ISC_R_NOMEMORY);
+ }
+
+ /* Start getting NS for the domain */
+ domainlen = strlen(buf);
+ isc_buffer_init(&b, buf, domainlen);
+ isc_buffer_add(&b, domainlen);
+ dns_fixedname_init(&trans->fixedname);
+ trans->qname = dns_fixedname_name(&trans->fixedname);
+ result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_client_startresolve(client, trans->qname,
+ dns_rdataclass_in, dns_rdatatype_ns,
+ 0, probe_task, resolve_ns, trans,
+ &trans->resid);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ trans->inuse = ISC_TRUE;
+ outstanding_probes++;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_mem_free(mctx, trans->domain);
+ dns_fixedname_invalidate(&trans->fixedname);
+
+ return (result);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: nsprobe [-d] [-v [-v...]] [-c cache_address] "
+ "[input_file]\n");
+
+ exit(1);
+}
+
+int
+main(int argc, char *argv[]) {
+ int i, ch, error;
+ struct addrinfo hints, *res;
+ isc_result_t result;
+ isc_sockaddr_t sa;
+ isc_sockaddrlist_t servers;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_socketmgr_t *socketmgr = NULL;
+ isc_timermgr_t *timermgr = NULL;
+
+ while ((ch = getopt(argc, argv, "c:dhv")) != -1) {
+ switch (ch) {
+ case 'c':
+ cacheserver = optarg;
+ break;
+ case 'd':
+ debug_mode = ISC_TRUE;
+ break;
+ case 'h':
+ usage();
+ break;
+ case 'v':
+ verbose_level++;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Common set up */
+ isc_lib_register();
+ result = dns_lib_init();
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_lib_init failed: %d\n", result);
+ exit(1);
+ }
+
+ result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr,
+ &timermgr);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "ctx create failed: %d\n", result);
+ exit(1);
+ }
+
+ isc_app_ctxstart(actx);
+
+ result = dns_client_createx(mctx, actx, taskmgr, socketmgr,
+ timermgr, 0, &client);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_client_createx failed: %d\n", result);
+ exit(1);
+ }
+
+ /* Set local cache server */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ error = getaddrinfo(cacheserver, "53", &hints, &res);
+ if (error != 0) {
+ fprintf(stderr, "failed to convert server name (%s): %s\n",
+ cacheserver, gai_strerror(error));
+ exit(1);
+ }
+
+ if (res->ai_addrlen > sizeof(sa.type)) {
+ fprintf(stderr,
+ "assumption failure: addrlen is too long: %d\n",
+ res->ai_addrlen);
+ exit(1);
+ }
+ memcpy(&sa.type.sa, res->ai_addr, res->ai_addrlen);
+ sa.length = res->ai_addrlen;
+ freeaddrinfo(res);
+ ISC_LINK_INIT(&sa, link);
+ ISC_LIST_INIT(servers);
+ ISC_LIST_APPEND(servers, &sa, link);
+ result = dns_client_setservers(client, dns_rdataclass_in, NULL,
+ &servers);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to set server: %d\n", result);
+ exit(1);
+ }
+
+ /* Create the main task */
+ probe_task = NULL;
+ result = isc_task_create(taskmgr, 0, &probe_task);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to create task: %d\n", result);
+ exit(1);
+ }
+
+ /* Open input file */
+ if (argc == 0)
+ fp = stdin;
+ else {
+ fp = fopen(argv[0], "r");
+ if (fp == NULL) {
+ fprintf(stderr, "failed to open input file: %s\n",
+ argv[0]);
+ exit(1);
+ }
+ }
+
+ /* Set up and start probe */
+ for (i = 0; i < MAX_PROBES; i++) {
+ probes[i].inuse = ISC_FALSE;
+ probes[i].domain = NULL;
+ dns_fixedname_init(&probes[i].fixedname);
+ probes[i].qname = NULL;
+ probes[i].qlabel = qlabels;
+ probes[i].qname_found = ISC_FALSE;
+ probes[i].resid = NULL;
+ ISC_LIST_INIT(probes[i].nslist);
+ probes[i].reqid = NULL;
+
+ probes[i].qmessage = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
+ &probes[i].qmessage);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_message_create(mctx,
+ DNS_MESSAGE_INTENTPARSE,
+ &probes[i].rmessage);
+ }
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "initialization failure\n");
+ exit(1);
+ }
+ }
+ for (i = 0; i < MAX_PROBES; i++) {
+ result = probe_domain(&probes[i]);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to issue an initial probe\n");
+ exit(1);
+ }
+ }
+
+ /* Start event loop */
+ isc_app_ctxrun(actx);
+
+ /* Dump results */
+ printf("Per domain results (out of %lu domains):\n",
+ number_of_domains);
+ printf(" valid: %lu\n"
+ " ignore: %lu\n"
+ " nxdomain: %lu\n"
+ " othererr: %lu\n"
+ " multiplesoa: %lu\n"
+ " multiplecname: %lu\n"
+ " brokenanswer: %lu\n"
+ " lame: %lu\n"
+ " unknown: %lu\n"
+ " multiple errors: %lu\n",
+ domain_stat.valid, domain_stat.ignore, domain_stat.nxdomain,
+ domain_stat.othererr, domain_stat.multiplesoa,
+ domain_stat.multiplecname, domain_stat.brokenanswer,
+ domain_stat.lame, domain_stat.unknown, multiple_error_domains);
+ printf("Per server results (out of %lu servers):\n",
+ number_of_servers);
+ printf(" valid: %lu\n"
+ " ignore: %lu\n"
+ " nxdomain: %lu\n"
+ " othererr: %lu\n"
+ " multiplesoa: %lu\n"
+ " multiplecname: %lu\n"
+ " brokenanswer: %lu\n"
+ " lame: %lu\n"
+ " unknown: %lu\n",
+ server_stat.valid, server_stat.ignore, server_stat.nxdomain,
+ server_stat.othererr, server_stat.multiplesoa,
+ server_stat.multiplecname, server_stat.brokenanswer,
+ server_stat.lame, server_stat.unknown);
+
+ /* Cleanup */
+ for (i = 0; i < MAX_PROBES; i++) {
+ dns_message_destroy(&probes[i].qmessage);
+ dns_message_destroy(&probes[i].rmessage);
+ }
+ isc_task_detach(&probe_task);
+ dns_client_destroy(&client);
+ dns_lib_shutdown();
+ isc_app_ctxfinish(actx);
+ ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
+
+ exit(0);
+}
diff --git a/contrib/bind9/lib/export/samples/sample-async.c b/contrib/bind9/lib/export/samples/sample-async.c
new file mode 100644
index 0000000..19c0bba
--- /dev/null
+++ b/contrib/bind9/lib/export/samples/sample-async.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 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: sample-async.c,v 1.5 2009-09-29 15:06:07 fdupont Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/socket.h>
+#include <isc/sockaddr.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/lib.h>
+#include <dns/name.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+#define MAX_SERVERS 10
+#define MAX_QUERIES 100
+
+static dns_client_t *client = NULL;
+static isc_task_t *query_task = NULL;
+static isc_appctx_t *query_actx = NULL;
+static unsigned int outstanding_queries = 0;
+static const char *def_server = "127.0.0.1";
+static FILE *fp;
+
+struct query_trans {
+ int id;
+ isc_boolean_t inuse;
+ dns_rdatatype_t type;
+ dns_fixedname_t fixedname;
+ dns_name_t *qname;
+ dns_namelist_t answerlist;
+ dns_clientrestrans_t *xid;
+};
+
+static struct query_trans query_array[MAX_QUERIES];
+
+static isc_result_t dispatch_query(struct query_trans *trans);
+
+static void
+ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp,
+ isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
+ isc_timermgr_t **timermgrp)
+{
+ if (*taskmgrp != NULL)
+ isc_taskmgr_destroy(taskmgrp);
+
+ if (*timermgrp != NULL)
+ isc_timermgr_destroy(timermgrp);
+
+ if (*socketmgrp != NULL)
+ isc_socketmgr_destroy(socketmgrp);
+
+ if (*actxp != NULL)
+ isc_appctx_destroy(actxp);
+
+ if (*mctxp != NULL)
+ isc_mem_destroy(mctxp);
+}
+
+static isc_result_t
+ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp,
+ isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
+ isc_timermgr_t **timermgrp)
+{
+ isc_result_t result;
+
+ result = isc_mem_create(0, 0, mctxp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_appctx_create(*mctxp, actxp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp);
+
+ return (result);
+}
+
+static isc_result_t
+printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char t[4096];
+
+ isc_buffer_init(&target, t, sizeof(t));
+
+ if (!dns_rdataset_isassociated(rdataset))
+ return (ISC_R_SUCCESS);
+ result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(&target, &r);
+ printf(" %.*s", (int)r.length, (char *)r.base);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+process_answer(isc_task_t *task, isc_event_t *event) {
+ struct query_trans *trans = event->ev_arg;
+ dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ REQUIRE(task == query_task);
+ REQUIRE(trans->inuse == ISC_TRUE);
+ REQUIRE(outstanding_queries > 0);
+
+ printf("answer[%2d]\n", trans->id);
+
+ if (rev->result != ISC_R_SUCCESS)
+ printf(" failed: %d(%s)\n", rev->result,
+ dns_result_totext(rev->result));
+
+ for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ (void)printdata(rdataset, name);
+ }
+ }
+
+ dns_client_freeresanswer(client, &rev->answerlist);
+ dns_client_destroyrestrans(&trans->xid);
+
+ isc_event_free(&event);
+
+ trans->inuse = ISC_FALSE;
+ dns_fixedname_invalidate(&trans->fixedname);
+ trans->qname = NULL;
+ outstanding_queries--;
+
+ result = dispatch_query(trans);
+#if 0 /* for cancel test */
+ if (result == ISC_R_SUCCESS) {
+ static int count = 0;
+
+ if ((++count) % 10 == 0)
+ dns_client_cancelresolve(trans->xid);
+ }
+#endif
+ if (result == ISC_R_NOMORE && outstanding_queries == 0)
+ isc_app_ctxshutdown(query_actx);
+}
+
+static isc_result_t
+dispatch_query(struct query_trans *trans) {
+ isc_result_t result;
+ size_t namelen;
+ isc_buffer_t b;
+ char buf[4096]; /* XXX ad hoc constant, but should be enough */
+ char *cp;
+
+ REQUIRE(trans != NULL);
+ REQUIRE(trans->inuse == ISC_FALSE);
+ REQUIRE(ISC_LIST_EMPTY(trans->answerlist));
+ REQUIRE(outstanding_queries < MAX_QUERIES);
+
+ /* Construct qname */
+ cp = fgets(buf, sizeof(buf), fp);
+ if (cp == NULL)
+ return (ISC_R_NOMORE);
+ /* zap NL if any */
+ if ((cp = strchr(buf, '\n')) != NULL)
+ *cp = '\0';
+ namelen = strlen(buf);
+ isc_buffer_init(&b, buf, namelen);
+ isc_buffer_add(&b, namelen);
+ dns_fixedname_init(&trans->fixedname);
+ trans->qname = dns_fixedname_name(&trans->fixedname);
+ result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Start resolution */
+ result = dns_client_startresolve(client, trans->qname,
+ dns_rdataclass_in, trans->type, 0,
+ query_task, process_answer, trans,
+ &trans->xid);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ trans->inuse = ISC_TRUE;
+ outstanding_queries++;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_fixedname_invalidate(&trans->fixedname);
+
+ return (result);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: sample-async [-s server_address] [-t RR type] "
+ "input_file\n");
+
+ exit(1);
+}
+
+int
+main(int argc, char *argv[]) {
+ int ch;
+ isc_textregion_t tr;
+ isc_mem_t *mctx = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_socketmgr_t *socketmgr = NULL;
+ isc_timermgr_t *timermgr = NULL;
+ int nservers = 0;
+ const char *serveraddr[MAX_SERVERS];
+ isc_sockaddr_t sa[MAX_SERVERS];
+ isc_sockaddrlist_t servers;
+ dns_rdatatype_t type = dns_rdatatype_a;
+ struct in_addr inaddr;
+ isc_result_t result;
+ int i;
+
+ while ((ch = getopt(argc, argv, "s:t:")) != -1) {
+ switch (ch) {
+ case 't':
+ tr.base = optarg;
+ tr.length = strlen(optarg);
+ result = dns_rdatatype_fromtext(&type, &tr);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "invalid RRtype: %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 's':
+ if (nservers == MAX_SERVERS) {
+ fprintf(stderr,
+ "too many servers (up to %d)\n",
+ MAX_SERVERS);
+ exit(1);
+ }
+ serveraddr[nservers++] = (const char *)optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 1)
+ usage();
+
+ if (nservers == 0) {
+ nservers = 1;
+ serveraddr[0] = def_server;
+ }
+
+ for (i = 0; i < MAX_QUERIES; i++) {
+ query_array[i].id = i;
+ query_array[i].inuse = ISC_FALSE;
+ query_array[i].type = type;
+ dns_fixedname_init(&query_array[i].fixedname);
+ query_array[i].qname = NULL;
+ ISC_LIST_INIT(query_array[i].answerlist);
+ query_array[i].xid = NULL;
+ }
+
+ isc_lib_register();
+ result = dns_lib_init();
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_lib_init failed: %d\n", result);
+ exit(1);
+ }
+
+ result = ctxs_init(&mctx, &query_actx, &taskmgr, &socketmgr,
+ &timermgr);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "ctx create failed: %d\n", result);
+ exit(1);
+ }
+
+ isc_app_ctxstart(query_actx);
+
+ result = dns_client_createx(mctx, query_actx, taskmgr, socketmgr,
+ timermgr, 0, &client);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_client_createx failed: %d\n", result);
+ exit(1);
+ }
+
+ /* Set nameservers */
+ ISC_LIST_INIT(servers);
+ for (i = 0; i < nservers; i++) {
+ if (inet_pton(AF_INET, serveraddr[i], &inaddr) != 1) {
+ fprintf(stderr, "failed to parse IPv4 address %s\n",
+ serveraddr[i]);
+ exit(1);
+ }
+ isc_sockaddr_fromin(&sa[i], &inaddr, 53);
+ ISC_LIST_APPEND(servers, &sa[i], link);
+ }
+ result = dns_client_setservers(client, dns_rdataclass_in, NULL,
+ &servers);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "set server failed: %d\n", result);
+ exit(1);
+ }
+
+ /* Create the main task */
+ query_task = NULL;
+ result = isc_task_create(taskmgr, 0, &query_task);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to create task: %d\n", result);
+ exit(1);
+ }
+
+ /* Open input file */
+ fp = fopen(argv[0], "r");
+ if (fp == NULL) {
+ fprintf(stderr, "failed to open input file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ /* Dispatch initial queries */
+ for (i = 0; i < MAX_QUERIES; i++) {
+ result = dispatch_query(&query_array[i]);
+ if (result == ISC_R_NOMORE)
+ break;
+ }
+
+ /* Start event loop */
+ isc_app_ctxrun(query_actx);
+
+ /* Sanity check */
+ for (i = 0; i < MAX_QUERIES; i++)
+ INSIST(query_array[i].inuse == ISC_FALSE);
+
+ /* Cleanup */
+ isc_task_detach(&query_task);
+ dns_client_destroy(&client);
+ dns_lib_shutdown();
+ isc_app_ctxfinish(query_actx);
+ ctxs_destroy(&mctx, &query_actx, &taskmgr, &socketmgr, &timermgr);
+
+ exit(0);
+}
diff --git a/contrib/bind9/lib/export/samples/sample-gai.c b/contrib/bind9/lib/export/samples/sample-gai.c
new file mode 100644
index 0000000..7c07f1b
--- /dev/null
+++ b/contrib/bind9/lib/export/samples/sample-gai.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 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: sample-gai.c,v 1.4 2009-09-02 23:48:02 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <irs/netdb.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+static void
+do_gai(int family, char *hostname) {
+ struct addrinfo hints, *res, *res0;
+ int error;
+ char namebuf[1024], addrbuf[1024], servbuf[1024];
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+ error = getaddrinfo(hostname, "http", &hints, &res0);
+ if (error) {
+ fprintf(stderr, "getaddrinfo failed for %s,family=%d: %s\n",
+ hostname, family, gai_strerror(error));
+ return;
+ }
+
+ for (res = res0; res; res = res->ai_next) {
+ error = getnameinfo(res->ai_addr, res->ai_addrlen,
+ addrbuf, sizeof(addrbuf),
+ NULL, 0, NI_NUMERICHOST);
+ if (error == 0)
+ error = getnameinfo(res->ai_addr, res->ai_addrlen,
+ namebuf, sizeof(namebuf),
+ servbuf, sizeof(servbuf), 0);
+ if (error != 0) {
+ fprintf(stderr, "getnameinfo failed: %s\n",
+ gai_strerror(error));
+ } else {
+ printf("%s(%s/%s)=%s:%s\n", hostname,
+ res->ai_canonname, addrbuf, namebuf, servbuf);
+ }
+ }
+
+ freeaddrinfo(res);
+}
+
+int
+main(int argc, char *argv[]) {
+ if (argc < 2)
+ exit(1);
+
+ do_gai(AF_INET, argv[1]);
+ do_gai(AF_INET6, argv[1]);
+ do_gai(AF_UNSPEC, argv[1]);
+
+ exit(0);
+}
diff --git a/contrib/bind9/lib/export/samples/sample-request.c b/contrib/bind9/lib/export/samples/sample-request.c
new file mode 100644
index 0000000..4331498
--- /dev/null
+++ b/contrib/bind9/lib/export/samples/sample-request.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 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: sample-request.c,v 1.5 2009-09-29 15:06:07 fdupont Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/sockaddr.h>
+#include <isc/util.h>
+
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/lib.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+static isc_mem_t *mctx;
+static dns_fixedname_t fixedqname;
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "sample-request [-t RRtype] server_address hostname\n");
+
+ exit(1);
+}
+
+static isc_result_t
+make_querymessage(dns_message_t *message, const char *namestr,
+ dns_rdatatype_t rdtype)
+{
+ dns_name_t *qname = NULL, *qname0;
+ dns_rdataset_t *qrdataset = NULL;
+ isc_result_t result;
+ isc_buffer_t b;
+ size_t namelen;
+
+ /* Construct qname */
+ namelen = strlen(namestr);
+ isc_buffer_init(&b, namestr, namelen);
+ isc_buffer_add(&b, namelen);
+ dns_fixedname_init(&fixedqname);
+ qname0 = dns_fixedname_name(&fixedqname);
+ result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to convert qname: %d\n", result);
+ return (result);
+ }
+
+ /* Construct query message */
+ message->opcode = dns_opcode_query;
+ message->rdclass = dns_rdataclass_in;
+
+ result = dns_message_gettempname(message, &qname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_name_init(qname, NULL);
+ dns_name_clone(qname0, qname);
+ dns_rdataset_init(qrdataset);
+ dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ dns_message_addname(message, qname, DNS_SECTION_QUESTION);
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (qname != NULL)
+ dns_message_puttempname(message, &qname);
+ if (qrdataset != NULL)
+ dns_message_puttemprdataset(message, &qrdataset);
+ if (message != NULL)
+ dns_message_destroy(&message);
+ return (result);
+}
+
+static void
+print_section(dns_message_t *message, int section, isc_buffer_t *buf) {
+ isc_result_t result;
+ isc_region_t r;
+
+ result = dns_message_sectiontotext(message, section,
+ &dns_master_style_full, 0, buf);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ isc_buffer_usedregion(buf, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ return;
+
+ fail:
+ fprintf(stderr, "failed to convert a section\n");
+}
+
+int
+main(int argc, char *argv[]) {
+ int ch, i, gai_error;
+ struct addrinfo hints, *res;
+ isc_textregion_t tr;
+ dns_client_t *client = NULL;
+ isc_result_t result;
+ isc_sockaddr_t sa;
+ dns_message_t *qmessage, *rmessage;
+ dns_rdatatype_t type = dns_rdatatype_a;
+ isc_buffer_t *outputbuf;
+
+ while ((ch = getopt(argc, argv, "t:")) != -1) {
+ switch (ch) {
+ case 't':
+ tr.base = optarg;
+ tr.length = strlen(optarg);
+ result = dns_rdatatype_fromtext(&type, &tr);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "invalid RRtype: %s\n", optarg);
+ exit(1);
+ }
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 2)
+ usage();
+
+ isc_lib_register();
+ result = dns_lib_init();
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_lib_init failed: %d\n", result);
+ exit(1);
+ }
+
+ result = dns_client_create(&client, 0);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_client_create failed: %d\n", result);
+ exit(1);
+ }
+
+ /* Prepare message structures */
+ mctx = NULL;
+ qmessage = NULL;
+ rmessage = NULL;
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to create a memory context\n");
+ exit(1);
+ }
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
+ &rmessage);
+ }
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to create messages\n");
+ exit(1);
+ }
+
+ /* Initialize the nameserver address */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICHOST;
+ gai_error = getaddrinfo(argv[0], "53", &hints, &res);
+ if (gai_error != 0) {
+ fprintf(stderr, "getaddrinfo failed: %s\n",
+ gai_strerror(gai_error));
+ exit(1);
+ }
+ INSIST(res->ai_addrlen <= sizeof(sa.type));
+ memcpy(&sa.type, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ sa.length = res->ai_addrlen;
+ ISC_LINK_INIT(&sa, link);
+
+ /* Construct qname */
+ result = make_querymessage(qmessage, argv[1], type);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to create a query\n");
+ exit(1);
+ }
+
+ /* Send request and wait for a response */
+ result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0,
+ NULL, 60, 0, 3);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to get a response: %s\n",
+ dns_result_totext(result));
+ }
+
+ /* Dump the response */
+ outputbuf = NULL;
+ result = isc_buffer_allocate(mctx, &outputbuf, 65535);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to allocate a result buffer\n");
+ exit(1);
+ }
+ for (i = 0; i < DNS_SECTION_MAX; i++) {
+ print_section(rmessage, i, outputbuf);
+ isc_buffer_clear(outputbuf);
+ }
+ isc_buffer_free(&outputbuf);
+
+ /* Cleanup */
+ dns_message_destroy(&qmessage);
+ dns_message_destroy(&rmessage);
+ isc_mem_destroy(&mctx);
+ dns_client_destroy(&client);
+ dns_lib_shutdown();
+
+ exit(0);
+}
diff --git a/contrib/bind9/lib/export/samples/sample-update.c b/contrib/bind9/lib/export/samples/sample-update.c
new file mode 100644
index 0000000..eef0a58
--- /dev/null
+++ b/contrib/bind9/lib/export/samples/sample-update.c
@@ -0,0 +1,755 @@
+/*
+ * Copyright (C) 2009, 2010 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: sample-update.c,v 1.10 2010-12-09 00:54:34 marka Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/parseint.h>
+#include <isc/sockaddr.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/lib.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+#include <dns/tsec.h>
+
+#include <dst/dst.h>
+
+static dns_tsec_t *tsec = NULL;
+static const dns_rdataclass_t default_rdataclass = dns_rdataclass_in;
+static isc_bufferlist_t usedbuffers;
+static ISC_LIST(dns_rdatalist_t) usedrdatalists;
+
+static void setup_tsec(char *keyfile, isc_mem_t *mctx);
+static void update_addordelete(isc_mem_t *mctx, char *cmdline,
+ isc_boolean_t isdelete, dns_name_t *name);
+static void evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name);
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "sample-update "
+ "[-a auth_server] "
+ "[-k keyfile] "
+ "[-p prerequisite] "
+ "[-r recursive_server] "
+ "[-z zonename] "
+ "(add|delete) \"name TTL RRtype RDATA\"\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[]) {
+ int ch;
+ struct addrinfo hints, *res;
+ int gai_error;
+ dns_client_t *client = NULL;
+ char *zonenamestr = NULL;
+ char *keyfilename = NULL;
+ char *prereqstr = NULL;
+ isc_sockaddrlist_t auth_servers;
+ char *auth_server = NULL;
+ char *recursive_server = NULL;
+ isc_sockaddr_t sa_auth, sa_recursive;
+ isc_sockaddrlist_t rec_servers;
+ isc_result_t result;
+ isc_boolean_t isdelete;
+ isc_buffer_t b, *buf;
+ dns_fixedname_t zname0, pname0, uname0;
+ size_t namelen;
+ dns_name_t *zname = NULL, *uname, *pname;
+ dns_rdataset_t *rdataset;
+ dns_rdatalist_t *rdatalist;
+ dns_rdata_t *rdata;
+ dns_namelist_t updatelist, prereqlist, *prereqlistp = NULL;
+ isc_mem_t *umctx = NULL;
+
+ while ((ch = getopt(argc, argv, "a:k:p:r:z:")) != -1) {
+ switch (ch) {
+ case 'k':
+ keyfilename = optarg;
+ break;
+ case 'a':
+ auth_server = optarg;
+ break;
+ case 'p':
+ prereqstr = optarg;
+ break;
+ case 'r':
+ recursive_server = optarg;
+ break;
+ case 'z':
+ zonenamestr = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 2)
+ usage();
+
+ /* command line argument validation */
+ if (strcmp(argv[0], "delete") == 0)
+ isdelete = ISC_TRUE;
+ else if (strcmp(argv[0], "add") == 0)
+ isdelete = ISC_FALSE;
+ else {
+ fprintf(stderr, "invalid update command: %s\n", argv[0]);
+ exit(1);
+ }
+
+ if (auth_server == NULL && recursive_server == NULL) {
+ fprintf(stderr, "authoritative or recursive server "
+ "must be specified\n");
+ usage();
+ }
+
+ /* Initialization */
+ ISC_LIST_INIT(usedbuffers);
+ ISC_LIST_INIT(usedrdatalists);
+ ISC_LIST_INIT(prereqlist);
+ ISC_LIST_INIT(auth_servers);
+ isc_lib_register();
+ result = dns_lib_init();
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_lib_init failed: %d\n", result);
+ exit(1);
+ }
+ result = isc_mem_create(0, 0, &umctx);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to crate mctx\n");
+ exit(1);
+ }
+
+ result = dns_client_create(&client, 0);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_client_create failed: %d\n", result);
+ exit(1);
+ }
+
+ /* Set the authoritative server */
+ if (auth_server != NULL) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICHOST;
+ gai_error = getaddrinfo(auth_server, "53", &hints, &res);
+ if (gai_error != 0) {
+ fprintf(stderr, "getaddrinfo failed: %s\n",
+ gai_strerror(gai_error));
+ exit(1);
+ }
+ INSIST(res->ai_addrlen <= sizeof(sa_auth.type));
+ memcpy(&sa_auth.type, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ sa_auth.length = res->ai_addrlen;
+ ISC_LINK_INIT(&sa_auth, link);
+
+ ISC_LIST_APPEND(auth_servers, &sa_auth, link);
+ }
+
+ /* Set the recursive server */
+ if (recursive_server != NULL) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICHOST;
+ gai_error = getaddrinfo(recursive_server, "53", &hints, &res);
+ if (gai_error != 0) {
+ fprintf(stderr, "getaddrinfo failed: %s\n",
+ gai_strerror(gai_error));
+ exit(1);
+ }
+ INSIST(res->ai_addrlen <= sizeof(sa_recursive.type));
+ memcpy(&sa_recursive.type, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ sa_recursive.length = res->ai_addrlen;
+ ISC_LINK_INIT(&sa_recursive, link);
+ ISC_LIST_INIT(rec_servers);
+ ISC_LIST_APPEND(rec_servers, &sa_recursive, link);
+ result = dns_client_setservers(client, dns_rdataclass_in,
+ NULL, &rec_servers);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "set server failed: %d\n", result);
+ exit(1);
+ }
+ }
+
+ /* Construct zone name */
+ zname = NULL;
+ if (zonenamestr != NULL) {
+ namelen = strlen(zonenamestr);
+ isc_buffer_init(&b, zonenamestr, namelen);
+ isc_buffer_add(&b, namelen);
+ dns_fixedname_init(&zname0);
+ zname = dns_fixedname_name(&zname0);
+ result = dns_name_fromtext(zname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stderr, "failed to convert zone name: %d\n",
+ result);
+ }
+
+ /* Construct prerequisite name (if given) */
+ if (prereqstr != NULL) {
+ dns_fixedname_init(&pname0);
+ pname = dns_fixedname_name(&pname0);
+ evaluate_prereq(umctx, prereqstr, pname);
+ ISC_LIST_APPEND(prereqlist, pname, link);
+ prereqlistp = &prereqlist;
+ }
+
+ /* Construct update name */
+ ISC_LIST_INIT(updatelist);
+ dns_fixedname_init(&uname0);
+ uname = dns_fixedname_name(&uname0);
+ update_addordelete(umctx, argv[1], isdelete, uname);
+ ISC_LIST_APPEND(updatelist, uname, link);
+
+ /* Set up TSIG/SIG(0) key (if given) */
+ if (keyfilename != NULL)
+ setup_tsec(keyfilename, umctx);
+
+ /* Perform update */
+ result = dns_client_update(client,
+ default_rdataclass, /* XXX: fixed */
+ zname, prereqlistp, &updatelist,
+ (auth_server == NULL) ? NULL :
+ &auth_servers, tsec, 0);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "update failed: %s\n", dns_result_totext(result));
+ } else
+ fprintf(stderr, "update succeeded\n");
+
+ /* Cleanup */
+ while ((pname = ISC_LIST_HEAD(prereqlist)) != NULL) {
+ while ((rdataset = ISC_LIST_HEAD(pname->list)) != NULL) {
+ ISC_LIST_UNLINK(pname->list, rdataset, link);
+ dns_rdataset_disassociate(rdataset);
+ isc_mem_put(umctx, rdataset, sizeof(*rdataset));
+ }
+ ISC_LIST_UNLINK(prereqlist, pname, link);
+ }
+ while ((uname = ISC_LIST_HEAD(updatelist)) != NULL) {
+ while ((rdataset = ISC_LIST_HEAD(uname->list)) != NULL) {
+ ISC_LIST_UNLINK(uname->list, rdataset, link);
+ dns_rdataset_disassociate(rdataset);
+ isc_mem_put(umctx, rdataset, sizeof(*rdataset));
+ }
+ ISC_LIST_UNLINK(updatelist, uname, link);
+ }
+ while ((rdatalist = ISC_LIST_HEAD(usedrdatalists)) != NULL) {
+ while ((rdata = ISC_LIST_HEAD(rdatalist->rdata)) != NULL) {
+ ISC_LIST_UNLINK(rdatalist->rdata, rdata, link);
+ isc_mem_put(umctx, rdata, sizeof(*rdata));
+ }
+ ISC_LIST_UNLINK(usedrdatalists, rdatalist, link);
+ isc_mem_put(umctx, rdatalist, sizeof(*rdatalist));
+ }
+ while ((buf = ISC_LIST_HEAD(usedbuffers)) != NULL) {
+ ISC_LIST_UNLINK(usedbuffers, buf, link);
+ isc_buffer_free(&buf);
+ }
+ if (tsec != NULL)
+ dns_tsec_destroy(&tsec);
+ isc_mem_destroy(&umctx);
+ dns_client_destroy(&client);
+ dns_lib_shutdown();
+
+ exit(0);
+}
+
+/*
+ * Subroutines borrowed from nsupdate.c
+ */
+#define MAXWIRE (64 * 1024)
+#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
+
+static char *
+nsu_strsep(char **stringp, const char *delim) {
+ char *string = *stringp;
+ char *s;
+ const char *d;
+ char sc, dc;
+
+ if (string == NULL)
+ return (NULL);
+
+ for (; *string != '\0'; string++) {
+ sc = *string;
+ for (d = delim; (dc = *d) != '\0'; d++) {
+ if (sc == dc)
+ break;
+ }
+ if (dc == 0)
+ break;
+ }
+
+ for (s = string; *s != '\0'; s++) {
+ sc = *s;
+ for (d = delim; (dc = *d) != '\0'; d++) {
+ if (sc == dc) {
+ *s++ = '\0';
+ *stringp = s;
+ return (string);
+ }
+ }
+ }
+ *stringp = NULL;
+ return (string);
+}
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static inline void
+check_result(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS)
+ fatal("%s: %s", msg, isc_result_totext(result));
+}
+
+static void
+parse_name(char **cmdlinep, dns_name_t *name) {
+ isc_result_t result;
+ char *word;
+ isc_buffer_t source;
+
+ word = nsu_strsep(cmdlinep, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read owner name\n");
+ exit(1);
+ }
+
+ isc_buffer_init(&source, word, strlen(word));
+ isc_buffer_add(&source, strlen(word));
+ result = dns_name_fromtext(name, &source, dns_rootname, 0, NULL);
+ check_result(result, "dns_name_fromtext");
+ isc_buffer_invalidate(&source);
+}
+
+static void
+parse_rdata(isc_mem_t *mctx, char **cmdlinep, dns_rdataclass_t rdataclass,
+ dns_rdatatype_t rdatatype, dns_rdata_t *rdata)
+{
+ char *cmdline = *cmdlinep;
+ isc_buffer_t source, *buf = NULL, *newbuf = NULL;
+ isc_region_t r;
+ isc_lex_t *lex = NULL;
+ dns_rdatacallbacks_t callbacks;
+ isc_result_t result;
+
+ while (cmdline != NULL && *cmdline != 0 &&
+ isspace((unsigned char)*cmdline))
+ cmdline++;
+
+ if (cmdline != NULL && *cmdline != 0) {
+ dns_rdatacallbacks_init(&callbacks);
+ result = isc_lex_create(mctx, strlen(cmdline), &lex);
+ check_result(result, "isc_lex_create");
+ isc_buffer_init(&source, cmdline, strlen(cmdline));
+ isc_buffer_add(&source, strlen(cmdline));
+ result = isc_lex_openbuffer(lex, &source);
+ check_result(result, "isc_lex_openbuffer");
+ result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex,
+ dns_rootname, 0, mctx, buf,
+ &callbacks);
+ isc_lex_destroy(&lex);
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_usedregion(buf, &r);
+ result = isc_buffer_allocate(mctx, &newbuf, r.length);
+ check_result(result, "isc_buffer_allocate");
+ isc_buffer_putmem(newbuf, r.base, r.length);
+ isc_buffer_usedregion(newbuf, &r);
+ dns_rdata_reset(rdata);
+ dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
+ isc_buffer_free(&buf);
+ ISC_LIST_APPEND(usedbuffers, newbuf, link);
+ } else {
+ fprintf(stderr, "invalid rdata format: %s\n",
+ isc_result_totext(result));
+ isc_buffer_free(&buf);
+ exit(1);
+ }
+ } else {
+ rdata->flags = DNS_RDATA_UPDATE;
+ }
+ *cmdlinep = cmdline;
+}
+
+static void
+update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete,
+ dns_name_t *name)
+{
+ isc_result_t result;
+ isc_uint32_t ttl;
+ char *word;
+ dns_rdataclass_t rdataclass;
+ dns_rdatatype_t rdatatype;
+ dns_rdata_t *rdata = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ isc_textregion_t region;
+
+ /*
+ * Read the owner name.
+ */
+ parse_name(&cmdline, name);
+
+ rdata = isc_mem_get(mctx, sizeof(*rdata));
+ if (rdata == NULL) {
+ fprintf(stderr, "memory allocation for rdata failed\n");
+ exit(1);
+ }
+ dns_rdata_init(rdata);
+
+ /*
+ * If this is an add, read the TTL and verify that it's in range.
+ * If it's a delete, ignore a TTL if present (for compatibility).
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ if (!isdelete) {
+ fprintf(stderr, "could not read owner ttl\n");
+ exit(1);
+ }
+ else {
+ ttl = 0;
+ rdataclass = dns_rdataclass_any;
+ rdatatype = dns_rdatatype_any;
+ rdata->flags = DNS_RDATA_UPDATE;
+ goto doneparsing;
+ }
+ }
+ result = isc_parse_uint32(&ttl, word, 10);
+ if (result != ISC_R_SUCCESS) {
+ if (isdelete) {
+ ttl = 0;
+ goto parseclass;
+ } else {
+ fprintf(stderr, "ttl '%s': %s\n", word,
+ isc_result_totext(result));
+ exit(1);
+ }
+ }
+
+ if (isdelete)
+ ttl = 0;
+ else if (ttl > TTL_MAX) {
+ fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
+ word, TTL_MAX);
+ exit(1);
+ }
+
+ /*
+ * Read the class or type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ parseclass:
+ if (word == NULL || *word == 0) {
+ if (isdelete) {
+ rdataclass = dns_rdataclass_any;
+ rdatatype = dns_rdatatype_any;
+ rdata->flags = DNS_RDATA_UPDATE;
+ goto doneparsing;
+ } else {
+ fprintf(stderr, "could not read class or type\n");
+ exit(1);
+ }
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdataclass_fromtext(&rdataclass, &region);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Now read the type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ if (isdelete) {
+ rdataclass = dns_rdataclass_any;
+ rdatatype = dns_rdatatype_any;
+ rdata->flags = DNS_RDATA_UPDATE;
+ goto doneparsing;
+ } else {
+ fprintf(stderr, "could not read type\n");
+ exit(1);
+ }
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "'%s' is not a valid type: %s\n",
+ word, isc_result_totext(result));
+ exit(1);
+ }
+ } else {
+ rdataclass = default_rdataclass;
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "'%s' is not a valid class or type: "
+ "%s\n", word, isc_result_totext(result));
+ exit(1);
+ }
+ }
+
+ parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);
+
+ if (isdelete) {
+ if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
+ rdataclass = dns_rdataclass_any;
+ else
+ rdataclass = dns_rdataclass_none;
+ } else {
+ if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
+ fprintf(stderr, "could not read rdata\n");
+ exit(1);
+ }
+ }
+
+ doneparsing:
+
+ rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
+ if (rdatalist == NULL) {
+ fprintf(stderr, "memory allocation for rdatalist failed\n");
+ exit(1);
+ }
+ dns_rdatalist_init(rdatalist);
+ rdatalist->type = rdatatype;
+ rdatalist->rdclass = rdataclass;
+ rdatalist->covers = rdatatype;
+ rdatalist->ttl = (dns_ttl_t)ttl;
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ ISC_LIST_APPEND(usedrdatalists, rdatalist, link);
+
+ rdataset = isc_mem_get(mctx, sizeof(*rdataset));
+ if (rdataset == NULL) {
+ fprintf(stderr, "memory allocation for rdataset failed\n");
+ exit(1);
+ }
+ dns_rdataset_init(rdataset);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+}
+
+static void
+make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive,
+ isc_boolean_t isrrset, dns_name_t *name)
+{
+ isc_result_t result;
+ char *word;
+ isc_textregion_t region;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdataclass_t rdataclass;
+ dns_rdatatype_t rdatatype;
+ dns_rdata_t *rdata = NULL;
+
+ /*
+ * Read the owner name
+ */
+ parse_name(&cmdline, name);
+
+ /*
+ * If this is an rrset prereq, read the class or type.
+ */
+ if (isrrset) {
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read class or type\n");
+ exit(1);
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdataclass_fromtext(&rdataclass, &region);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Now read the type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read type\n");
+ exit(1);
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "invalid type: %s\n", word);
+ exit(1);
+ }
+ } else {
+ rdataclass = default_rdataclass;
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "invalid type: %s\n", word);
+ exit(1);
+ }
+ }
+ } else
+ rdatatype = dns_rdatatype_any;
+
+ rdata = isc_mem_get(mctx, sizeof(*rdata));
+ if (rdata == NULL) {
+ fprintf(stderr, "memory allocation for rdata failed\n");
+ exit(1);
+ }
+ dns_rdata_init(rdata);
+
+ if (isrrset && ispositive)
+ parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);
+ else
+ rdata->flags = DNS_RDATA_UPDATE;
+
+ rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
+ if (rdatalist == NULL) {
+ fprintf(stderr, "memory allocation for rdatalist failed\n");
+ exit(1);
+ }
+ dns_rdatalist_init(rdatalist);
+ rdatalist->type = rdatatype;
+ if (ispositive) {
+ if (isrrset && rdata->data != NULL)
+ rdatalist->rdclass = rdataclass;
+ else
+ rdatalist->rdclass = dns_rdataclass_any;
+ } else
+ rdatalist->rdclass = dns_rdataclass_none;
+ rdatalist->covers = 0;
+ rdatalist->ttl = 0;
+ rdata->rdclass = rdatalist->rdclass;
+ rdata->type = rdatatype;
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ ISC_LIST_APPEND(usedrdatalists, rdatalist, link);
+
+ rdataset = isc_mem_get(mctx, sizeof(*rdataset));
+ if (rdataset == NULL) {
+ fprintf(stderr, "memory allocation for rdataset failed\n");
+ exit(1);
+ }
+ dns_rdataset_init(rdataset);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+}
+
+static void
+evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name) {
+ char *word;
+ isc_boolean_t ispositive, isrrset;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (word == NULL || *word == 0) {
+ fprintf(stderr, "could not read operation code\n");
+ exit(1);
+ }
+ if (strcasecmp(word, "nxdomain") == 0) {
+ ispositive = ISC_FALSE;
+ isrrset = ISC_FALSE;
+ } else if (strcasecmp(word, "yxdomain") == 0) {
+ ispositive = ISC_TRUE;
+ isrrset = ISC_FALSE;
+ } else if (strcasecmp(word, "nxrrset") == 0) {
+ ispositive = ISC_FALSE;
+ isrrset = ISC_TRUE;
+ } else if (strcasecmp(word, "yxrrset") == 0) {
+ ispositive = ISC_TRUE;
+ isrrset = ISC_TRUE;
+ } else {
+ fprintf(stderr, "incorrect operation code: %s\n", word);
+ exit(1);
+ }
+
+ make_prereq(mctx, cmdline, ispositive, isrrset, name);
+}
+
+static void
+setup_tsec(char *keyfile, isc_mem_t *mctx) {
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+ dns_tsectype_t tsectype;
+
+ result = dst_key_fromnamedfile(keyfile, NULL,
+ DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
+ &dstkey);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not read key from %s: %s\n",
+ keyfile, isc_result_totext(result));
+ exit(1);
+ }
+
+ if (dst_key_alg(dstkey) == DST_ALG_HMACMD5)
+ tsectype = dns_tsectype_tsig;
+ else
+ tsectype = dns_tsectype_sig0;
+
+ result = dns_tsec_create(mctx, tsectype, dstkey, &tsec);
+ dst_key_free(&dstkey);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create tsec: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+}
diff --git a/contrib/bind9/lib/export/samples/sample.c b/contrib/bind9/lib/export/samples/sample.c
new file mode 100644
index 0000000..6564f0e
--- /dev/null
+++ b/contrib/bind9/lib/export/samples/sample.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 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: sample.c,v 1.5 2009-09-29 15:06:07 fdupont Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/sockaddr.h>
+#include <isc/util.h>
+
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/lib.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+static char *algname;
+
+static isc_result_t
+printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char t[4096];
+
+ if (!dns_rdataset_isassociated(rdataset)) {
+ printf("[WARN: empty]\n");
+ return (ISC_R_SUCCESS);
+ }
+
+ isc_buffer_init(&target, t, sizeof(t));
+
+ result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ return (ISC_R_SUCCESS);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "sample [-t RRtype] "
+ "[[-a algorithm] [-e] -k keyname -K keystring] "
+ "[-s domain:serveraddr_for_domain ] "
+ "server_address hostname\n");
+
+ exit(1);
+}
+
+static void
+set_key(dns_client_t *client, char *keynamestr, char *keystr,
+ isc_boolean_t is_sep, isc_mem_t **mctxp)
+{
+ isc_result_t result;
+ dns_fixedname_t fkeyname;
+ size_t namelen;
+ dns_name_t *keyname;
+ dns_rdata_dnskey_t keystruct;
+ unsigned char keydata[4096];
+ isc_buffer_t keydatabuf;
+ unsigned char rrdata[4096];
+ isc_buffer_t rrdatabuf;
+ isc_buffer_t b;
+ isc_textregion_t tr;
+ isc_region_t r;
+ dns_secalg_t alg;
+
+ result = isc_mem_create(0, 0, mctxp);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to crate mctx\n");
+ exit(1);
+ }
+
+ if (algname != NULL) {
+ tr.base = algname;
+ tr.length = strlen(algname);
+ result = dns_secalg_fromtext(&alg, &tr);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to identify the algorithm\n");
+ exit(1);
+ }
+ } else
+ alg = DNS_KEYALG_RSASHA1;
+
+ keystruct.common.rdclass = dns_rdataclass_in;
+ keystruct.common.rdtype = dns_rdatatype_dnskey;
+ keystruct.flags = DNS_KEYOWNER_ZONE; /* fixed */
+ if (is_sep)
+ keystruct.flags |= DNS_KEYFLAG_KSK;
+ keystruct.protocol = DNS_KEYPROTO_DNSSEC; /* fixed */
+ keystruct.algorithm = alg;
+
+ isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+ result = isc_base64_decodestring(keystr, &keydatabuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "base64 decode failed\n");
+ exit(1);
+ }
+ isc_buffer_usedregion(&keydatabuf, &r);
+ keystruct.datalen = r.length;
+ keystruct.data = r.base;
+
+ result = dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
+ keystruct.common.rdtype,
+ &keystruct, &rrdatabuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to construct key rdata\n");
+ exit(1);
+ }
+ namelen = strlen(keynamestr);
+ isc_buffer_init(&b, keynamestr, namelen);
+ isc_buffer_add(&b, namelen);
+ dns_fixedname_init(&fkeyname);
+ keyname = dns_fixedname_name(&fkeyname);
+ result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to construct key name\n");
+ exit(1);
+ }
+ result = dns_client_addtrustedkey(client, dns_rdataclass_in,
+ keyname, &rrdatabuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to add key for %s\n",
+ keynamestr);
+ exit(1);
+ }
+}
+
+static void
+addserver(dns_client_t *client, const char *addrstr, const char *namespace) {
+ struct addrinfo hints, *res;
+ int gai_error;
+ isc_sockaddr_t sa;
+ isc_sockaddrlist_t servers;
+ isc_result_t result;
+ size_t namelen;
+ isc_buffer_t b;
+ dns_fixedname_t fname;
+ dns_name_t *name = NULL;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICHOST;
+ gai_error = getaddrinfo(addrstr, "53", &hints, &res);
+ if (gai_error != 0) {
+ fprintf(stderr, "getaddrinfo failed: %s\n",
+ gai_strerror(gai_error));
+ exit(1);
+ }
+ INSIST(res->ai_addrlen <= sizeof(sa.type));
+ memcpy(&sa.type, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ sa.length = res->ai_addrlen;
+ ISC_LINK_INIT(&sa, link);
+ ISC_LIST_INIT(servers);
+ ISC_LIST_APPEND(servers, &sa, link);
+
+ if (namespace != NULL) {
+ namelen = strlen(namespace);
+ isc_buffer_init(&b, namespace, namelen);
+ isc_buffer_add(&b, namelen);
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "failed to convert qname: %d\n",
+ result);
+ exit(1);
+ }
+ }
+
+ result = dns_client_setservers(client, dns_rdataclass_in, name,
+ &servers);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "set server failed: %d\n", result);
+ exit(1);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ int ch;
+ isc_textregion_t tr;
+ char *altserver = NULL;
+ char *altserveraddr = NULL;
+ char *altservername = NULL;
+ dns_client_t *client = NULL;
+ char *keynamestr = NULL;
+ char *keystr = NULL;
+ isc_result_t result;
+ isc_buffer_t b;
+ dns_fixedname_t qname0;
+ size_t namelen;
+ dns_name_t *qname, *name;
+ dns_rdatatype_t type = dns_rdatatype_a;
+ dns_rdataset_t *rdataset;
+ dns_namelist_t namelist;
+ isc_mem_t *keymctx = NULL;
+ unsigned int clientopt, resopt;
+ isc_boolean_t is_sep = ISC_FALSE;
+
+ while ((ch = getopt(argc, argv, "a:es:t:k:K:")) != -1) {
+ switch (ch) {
+ case 't':
+ tr.base = optarg;
+ tr.length = strlen(optarg);
+ result = dns_rdatatype_fromtext(&type, &tr);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "invalid RRtype: %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'a':
+ algname = optarg;
+ break;
+ case 'e':
+ is_sep = ISC_TRUE;
+ break;
+ case 's':
+ if (altserver != NULL) {
+ fprintf(stderr, "alternate server "
+ "already defined: %s\n",
+ altserver);
+ exit(1);
+ }
+ altserver = optarg;
+ break;
+ case 'k':
+ keynamestr = optarg;
+ break;
+ case 'K':
+ keystr = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 2)
+ usage();
+
+ if (altserver != NULL) {
+ char *cp;
+
+ cp = strchr(altserver, ':');
+ if (cp == NULL) {
+ fprintf(stderr, "invalid alternate server: %s\n",
+ altserver);
+ exit(1);
+ }
+ *cp = '\0';
+ altservername = altserver;
+ altserveraddr = cp + 1;
+ }
+
+ isc_lib_register();
+ result = dns_lib_init();
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_lib_init failed: %d\n", result);
+ exit(1);
+ }
+
+ clientopt = 0;
+ result = dns_client_create(&client, clientopt);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "dns_client_create failed: %d\n", result);
+ exit(1);
+ }
+
+ /* Set the nameserver */
+ addserver(client, argv[0], NULL);
+
+ /* Set the alternate nameserver (when specified) */
+ if (altserver != NULL)
+ addserver(client, altserveraddr, altservername);
+
+ /* Install DNSSEC key (if given) */
+ if (keynamestr != NULL) {
+ if (keystr == NULL) {
+ fprintf(stderr,
+ "key string is missing "
+ "while key name is provided\n");
+ exit(1);
+ }
+ set_key(client, keynamestr, keystr, is_sep, &keymctx);
+ }
+
+ /* Construct qname */
+ namelen = strlen(argv[1]);
+ isc_buffer_init(&b, argv[1], namelen);
+ isc_buffer_add(&b, namelen);
+ dns_fixedname_init(&qname0);
+ qname = dns_fixedname_name(&qname0);
+ result = dns_name_fromtext(qname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stderr, "failed to convert qname: %d\n", result);
+
+ /* Perform resolution */
+ resopt = 0;
+ if (keynamestr == NULL)
+ resopt |= DNS_CLIENTRESOPT_NODNSSEC;
+ ISC_LIST_INIT(namelist);
+ result = dns_client_resolve(client, qname, dns_rdataclass_in, type,
+ resopt, &namelist);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr,
+ "resolution failed: %s\n", dns_result_totext(result));
+ }
+ for (name = ISC_LIST_HEAD(namelist); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (printdata(rdataset, name) != ISC_R_SUCCESS)
+ fprintf(stderr, "print data failed\n");
+ }
+ }
+
+ dns_client_freeresanswer(client, &namelist);
+
+ /* Cleanup */
+ dns_client_destroy(&client);
+ if (keynamestr != NULL)
+ isc_mem_destroy(&keymctx);
+ dns_lib_shutdown();
+
+ exit(0);
+}
diff --git a/contrib/bind9/lib/irs/Makefile.in b/contrib/bind9/lib/irs/Makefile.in
new file mode 100644
index 0000000..3f9bfb3
--- /dev/null
+++ b/contrib/bind9/lib/irs/Makefile.in
@@ -0,0 +1,80 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@LIBIRS_API@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I. -I./include -I${srcdir}/include \
+ ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+# Alphabetically
+OBJS = context.@O@ \
+ dnsconf.@O@ \
+ gai_strerror.@O@ getaddrinfo.@O@ getnameinfo.@O@ \
+ resconf.@O@
+
+# Alphabetically
+SRCS = context.c \
+ dnsconf.c \
+ gai_sterror.c getaddrinfo.c getnameinfo.c \
+ resconf.c
+
+LIBS = @LIBS@
+
+SUBDIRS = include
+TARGETS = timestamp
+
+@BIND9_MAKE_RULES@
+
+version.@O@: version.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DLIBINTERFACE=${LIBINTERFACE} \
+ -DLIBREVISION=${LIBREVISION} \
+ -DLIBAGE=${LIBAGE} \
+ -c ${srcdir}/version.c
+
+libirs.@SA@: ${OBJS} version.@O@
+ ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@
+ ${RANLIB} $@
+
+libirs.la: ${OBJS} version.@O@
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} version.@O@ ${LIBS}
+
+timestamp: libirs.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libirs.@A@ ${DESTDIR}${libdir}
+
+clean distclean::
+ rm -f libirs.@A@ libirs.la timestamp
diff --git a/contrib/bind9/lib/irs/api b/contrib/bind9/lib/irs/api
new file mode 100644
index 0000000..94575eb
--- /dev/null
+++ b/contrib/bind9/lib/irs/api
@@ -0,0 +1,3 @@
+LIBINTERFACE = 80
+LIBREVISION = 0
+LIBAGE = 0
diff --git a/contrib/bind9/lib/irs/context.c b/contrib/bind9/lib/irs/context.c
new file mode 100644
index 0000000..0c6d856
--- /dev/null
+++ b/contrib/bind9/lib/irs/context.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 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: context.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/app.h>
+#include <isc/lib.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/client.h>
+#include <dns/lib.h>
+
+#include <irs/context.h>
+#include <irs/dnsconf.h>
+#include <irs/resconf.h>
+
+#define IRS_CONTEXT_MAGIC ISC_MAGIC('I', 'R', 'S', 'c')
+#define IRS_CONTEXT_VALID(c) ISC_MAGIC_VALID(c, IRS_CONTEXT_MAGIC)
+
+#ifndef RESOLV_CONF
+/*% location of resolve.conf */
+#define RESOLV_CONF "/etc/resolv.conf"
+#endif
+
+#ifndef DNS_CONF
+/*% location of dns.conf */
+#define DNS_CONF "/etc/dns.conf"
+#endif
+
+#ifndef ISC_PLATFORM_USETHREADS
+irs_context_t *irs_g_context = NULL;
+#else
+static isc_boolean_t thread_key_initialized = ISC_FALSE;
+static isc_mutex_t thread_key_mutex;
+static isc_thread_key_t irs_context_key;
+static isc_once_t once = ISC_ONCE_INIT;
+#endif
+
+
+struct irs_context {
+ /*
+ * An IRS context is a thread-specific object, and does not need to
+ * be locked.
+ */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_appctx_t *actx;
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *task;
+ isc_socketmgr_t *socketmgr;
+ isc_timermgr_t *timermgr;
+ dns_client_t *dnsclient;
+ irs_resconf_t *resconf;
+ irs_dnsconf_t *dnsconf;
+};
+
+static void
+ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp,
+ isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
+ isc_timermgr_t **timermgrp)
+{
+ if (taskmgrp != NULL)
+ isc_taskmgr_destroy(taskmgrp);
+
+ if (timermgrp != NULL)
+ isc_timermgr_destroy(timermgrp);
+
+ if (socketmgrp != NULL)
+ isc_socketmgr_destroy(socketmgrp);
+
+ if (actxp != NULL)
+ isc_appctx_destroy(actxp);
+
+ if (mctxp != NULL)
+ isc_mem_destroy(mctxp);
+}
+
+static isc_result_t
+ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp,
+ isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
+ isc_timermgr_t **timermgrp)
+{
+ isc_result_t result;
+
+ result = isc_mem_create(0, 0, mctxp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_appctx_create(*mctxp, actxp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp);
+
+ return (result);
+}
+
+#ifdef ISC_PLATFORM_USETHREADS
+static void
+free_specific_context(void *arg) {
+ irs_context_t *context = arg;
+
+ irs_context_destroy(&context);
+
+ isc_thread_key_setspecific(irs_context_key, NULL);
+}
+
+static void
+thread_key_mutex_init(void) {
+ RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
+}
+
+static isc_result_t
+thread_key_init() {
+ isc_result_t result;
+
+ result = isc_once_do(&once, thread_key_mutex_init);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (!thread_key_initialized) {
+ LOCK(&thread_key_mutex);
+
+ if (!thread_key_initialized &&
+ isc_thread_key_create(&irs_context_key,
+ free_specific_context) != 0) {
+ result = ISC_R_FAILURE;
+ } else
+ thread_key_initialized = ISC_TRUE;
+
+ UNLOCK(&thread_key_mutex);
+ }
+
+ return (result);
+}
+#endif /* ISC_PLATFORM_USETHREADS */
+
+isc_result_t
+irs_context_get(irs_context_t **contextp) {
+ irs_context_t *context;
+ isc_result_t result;
+
+ REQUIRE(contextp != NULL && *contextp == NULL);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ if (irs_g_context == NULL) {
+ result = irs_context_create(&irs_g_context);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ context = irs_g_context;
+#else
+ result = thread_key_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ context = isc_thread_key_getspecific(irs_context_key);
+ if (context == NULL) {
+ result = irs_context_create(&context);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = isc_thread_key_setspecific(irs_context_key, context);
+ if (result != ISC_R_SUCCESS) {
+ irs_context_destroy(&context);
+ return (result);
+ }
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ *contextp = context;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+irs_context_create(irs_context_t **contextp) {
+ isc_result_t result;
+ irs_context_t *context;
+ isc_appctx_t *actx = NULL;
+ isc_mem_t *mctx = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_socketmgr_t *socketmgr = NULL;
+ isc_timermgr_t *timermgr = NULL;
+ dns_client_t *client = NULL;
+ isc_sockaddrlist_t *nameservers;
+ irs_dnsconf_dnskeylist_t *trustedkeys;
+ irs_dnsconf_dnskey_t *trustedkey;
+
+ isc_lib_register();
+ result = dns_lib_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = isc_app_ctxstart(actx);
+ if (result != ISC_R_SUCCESS) {
+ ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
+ return (result);
+ }
+
+ context = isc_mem_get(mctx, sizeof(*context));
+ if (context == NULL) {
+ ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
+ return (ISC_R_NOMEMORY);
+ }
+
+ context->mctx = mctx;
+ context->actx = actx;
+ context->taskmgr = taskmgr;
+ context->socketmgr = socketmgr;
+ context->timermgr = timermgr;
+ context->resconf = NULL;
+ context->dnsconf = NULL;
+ context->task = NULL;
+ result = isc_task_create(taskmgr, 0, &context->task);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ /* Create a DNS client object */
+ result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr,
+ 0, &client);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ context->dnsclient = client;
+
+ /* Read resolver configuration file */
+ result = irs_resconf_load(mctx, RESOLV_CONF, &context->resconf);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ /* Set nameservers */
+ nameservers = irs_resconf_getnameservers(context->resconf);
+ result = dns_client_setservers(client, dns_rdataclass_in, NULL,
+ nameservers);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ /* Read advanced DNS configuration (if any) */
+ result = irs_dnsconf_load(mctx, DNS_CONF, &context->dnsconf);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ trustedkeys = irs_dnsconf_gettrustedkeys(context->dnsconf);
+ for (trustedkey = ISC_LIST_HEAD(*trustedkeys);
+ trustedkey != NULL;
+ trustedkey = ISC_LIST_NEXT(trustedkey, link)) {
+ result = dns_client_addtrustedkey(client, dns_rdataclass_in,
+ trustedkey->keyname,
+ trustedkey->keydatabuf);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ }
+
+ context->magic = IRS_CONTEXT_MAGIC;
+ *contextp = context;
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ if (context->task != NULL)
+ isc_task_detach(&context->task);
+ if (context->resconf != NULL)
+ irs_resconf_destroy(&context->resconf);
+ if (context->dnsconf != NULL)
+ irs_dnsconf_destroy(&context->dnsconf);
+ if (client != NULL)
+ dns_client_destroy(&client);
+ ctxs_destroy(NULL, &actx, &taskmgr, &socketmgr, &timermgr);
+ isc_mem_putanddetach(&mctx, context, sizeof(*context));
+
+ return (result);
+}
+
+void
+irs_context_destroy(irs_context_t **contextp) {
+ irs_context_t *context;
+
+ REQUIRE(contextp != NULL);
+ context = *contextp;
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ isc_task_detach(&context->task);
+ irs_dnsconf_destroy(&context->dnsconf);
+ irs_resconf_destroy(&context->resconf);
+ dns_client_destroy(&context->dnsclient);
+
+ ctxs_destroy(NULL, &context->actx, &context->taskmgr,
+ &context->socketmgr, &context->timermgr);
+
+ context->magic = 0;
+
+ isc_mem_putanddetach(&context->mctx, context, sizeof(*context));
+
+ *contextp = NULL;
+
+#ifndef ISC_PLATFORM_USETHREADS
+ irs_g_context = NULL;
+#else
+ (void)isc_thread_key_setspecific(irs_context_key, NULL);
+#endif
+}
+
+isc_mem_t *
+irs_context_getmctx(irs_context_t *context) {
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ return (context->mctx);
+}
+
+isc_appctx_t *
+irs_context_getappctx(irs_context_t *context) {
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ return (context->actx);
+}
+
+isc_taskmgr_t *
+irs_context_gettaskmgr(irs_context_t *context) {
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ return (context->taskmgr);
+}
+
+isc_timermgr_t *
+irs_context_gettimermgr(irs_context_t *context) {
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ return (context->timermgr);
+}
+
+isc_task_t *
+irs_context_gettask(irs_context_t *context) {
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ return (context->task);
+}
+
+dns_client_t *
+irs_context_getdnsclient(irs_context_t *context) {
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ return (context->dnsclient);
+}
+
+irs_resconf_t *
+irs_context_getresconf(irs_context_t *context) {
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ return (context->resconf);
+}
+
+irs_dnsconf_t *
+irs_context_getdnsconf(irs_context_t *context) {
+ REQUIRE(IRS_CONTEXT_VALID(context));
+
+ return (context->dnsconf);
+}
diff --git a/contrib/bind9/lib/irs/dnsconf.c b/contrib/bind9/lib/irs/dnsconf.c
new file mode 100644
index 0000000..8464d6d
--- /dev/null
+++ b/contrib/bind9/lib/irs/dnsconf.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 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: dnsconf.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <isccfg/dnsconf.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdatastruct.h>
+
+#include <irs/dnsconf.h>
+
+#define IRS_DNSCONF_MAGIC ISC_MAGIC('D', 'c', 'f', 'g')
+#define IRS_DNSCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_DNSCONF_MAGIC)
+
+/*!
+ * configuration data structure
+ */
+
+struct irs_dnsconf {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ irs_dnsconf_dnskeylist_t trusted_keylist;
+};
+
+static isc_result_t
+configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj,
+ dns_rdataclass_t rdclass)
+{
+ isc_mem_t *mctx = conf->mctx;
+ const cfg_obj_t *keys = NULL;
+ const cfg_obj_t *key, *keylist;
+ dns_fixedname_t fkeyname;
+ dns_name_t *keyname_base, *keyname;
+ const cfg_listelt_t *element, *element2;
+ isc_result_t result;
+ isc_uint32_t flags, proto, alg;
+ const char *keystr, *keynamestr;
+ unsigned char keydata[4096];
+ isc_buffer_t keydatabuf_base, *keydatabuf;
+ dns_rdata_dnskey_t keystruct;
+ unsigned char rrdata[4096];
+ isc_buffer_t rrdatabuf;
+ isc_region_t r;
+ isc_buffer_t namebuf;
+ irs_dnsconf_dnskey_t *keyent;
+
+ cfg_map_get(cfgobj, "trusted-keys", &keys);
+ if (keys == NULL)
+ return (ISC_R_SUCCESS);
+
+ for (element = cfg_list_first(keys);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ keylist = cfg_listelt_value(element);
+ for (element2 = cfg_list_first(keylist);
+ element2 != NULL;
+ element2 = cfg_list_next(element2))
+ {
+ keydatabuf = NULL;
+ keyname = NULL;
+
+ key = cfg_listelt_value(element2);
+
+ flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
+ proto = cfg_obj_asuint32(cfg_tuple_get(key,
+ "protocol"));
+ alg = cfg_obj_asuint32(cfg_tuple_get(key,
+ "algorithm"));
+ keynamestr = cfg_obj_asstring(cfg_tuple_get(key,
+ "name"));
+
+ keystruct.common.rdclass = rdclass;
+ keystruct.common.rdtype = dns_rdatatype_dnskey;
+ keystruct.mctx = NULL;
+ ISC_LINK_INIT(&keystruct.common, link);
+
+ if (flags > 0xffff)
+ return (ISC_R_RANGE);
+ if (proto > 0xff)
+ return (ISC_R_RANGE);
+ if (alg > 0xff)
+ return (ISC_R_RANGE);
+ keystruct.flags = (isc_uint16_t)flags;
+ keystruct.protocol = (isc_uint8_t)proto;
+ keystruct.algorithm = (isc_uint8_t)alg;
+
+ isc_buffer_init(&keydatabuf_base, keydata,
+ sizeof(keydata));
+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+
+ /* Configure key value */
+ keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
+ result = isc_base64_decodestring(keystr,
+ &keydatabuf_base);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(&keydatabuf_base, &r);
+ keystruct.datalen = r.length;
+ keystruct.data = r.base;
+
+ result = dns_rdata_fromstruct(NULL,
+ keystruct.common.rdclass,
+ keystruct.common.rdtype,
+ &keystruct, &rrdatabuf);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(&rrdatabuf, &r);
+ result = isc_buffer_allocate(mctx, &keydatabuf,
+ r.length);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = isc_buffer_copyregion(keydatabuf, &r);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Configure key name */
+ dns_fixedname_init(&fkeyname);
+ keyname_base = dns_fixedname_name(&fkeyname);
+ isc_buffer_init(&namebuf, keynamestr,
+ strlen(keynamestr));
+ isc_buffer_add(&namebuf, strlen(keynamestr));
+ result = dns_name_fromtext(keyname_base, &namebuf,
+ dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ keyname = isc_mem_get(mctx, sizeof(*keyname));
+ if (keyname == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ dns_name_init(keyname, NULL);
+ result = dns_name_dup(keyname_base, mctx, keyname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Add the key data to the list */
+ keyent = isc_mem_get(mctx, sizeof(*keyent));
+ if (keyent == NULL) {
+ dns_name_free(keyname, mctx);
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ keyent->keyname = keyname;
+ keyent->keydatabuf = keydatabuf;
+
+ ISC_LIST_APPEND(conf->trusted_keylist, keyent, link);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (keydatabuf != NULL)
+ isc_buffer_free(&keydatabuf);
+ if (keyname != NULL)
+ isc_mem_put(mctx, keyname, sizeof(*keyname));
+
+ return (result);
+}
+
+isc_result_t
+irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp)
+{
+ irs_dnsconf_t *conf;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *cfgobj = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(confp != NULL && *confp == NULL);
+
+ conf = isc_mem_get(mctx, sizeof(*conf));
+ if (conf == NULL)
+ return (ISC_R_NOMEMORY);
+
+ conf->mctx = mctx;
+ ISC_LIST_INIT(conf->trusted_keylist);
+
+ /*
+ * If the specified file does not exist, we'll simply with an empty
+ * configuration.
+ */
+ if (!isc_file_exists(filename))
+ goto cleanup;
+
+ result = cfg_parser_create(mctx, NULL, &parser);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = cfg_parse_file(parser, filename, &cfg_type_dnsconf,
+ &cfgobj);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = configure_dnsseckeys(conf, cfgobj, dns_rdataclass_in);
+
+ cleanup:
+ if (parser != NULL) {
+ if (cfgobj != NULL)
+ cfg_obj_destroy(parser, &cfgobj);
+ cfg_parser_destroy(&parser);
+ }
+
+ conf->magic = IRS_DNSCONF_MAGIC;
+
+ if (result == ISC_R_SUCCESS)
+ *confp = conf;
+ else
+ irs_dnsconf_destroy(&conf);
+
+ return (result);
+}
+
+void
+irs_dnsconf_destroy(irs_dnsconf_t **confp) {
+ irs_dnsconf_t *conf;
+ irs_dnsconf_dnskey_t *keyent;
+
+ REQUIRE(confp != NULL);
+ conf = *confp;
+ REQUIRE(IRS_DNSCONF_VALID(conf));
+
+ while ((keyent = ISC_LIST_HEAD(conf->trusted_keylist)) != NULL) {
+ ISC_LIST_UNLINK(conf->trusted_keylist, keyent, link);
+
+ isc_buffer_free(&keyent->keydatabuf);
+ dns_name_free(keyent->keyname, conf->mctx);
+ isc_mem_put(conf->mctx, keyent->keyname, sizeof(dns_name_t));
+ isc_mem_put(conf->mctx, keyent, sizeof(*keyent));
+ }
+
+ isc_mem_put(conf->mctx, conf, sizeof(*conf));
+
+ *confp = NULL;
+}
+
+irs_dnsconf_dnskeylist_t *
+irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf) {
+ REQUIRE(IRS_DNSCONF_VALID(conf));
+
+ return (&conf->trusted_keylist);
+}
diff --git a/contrib/bind9/lib/irs/gai_strerror.c b/contrib/bind9/lib/irs/gai_strerror.c
new file mode 100644
index 0000000..aa021ef
--- /dev/null
+++ b/contrib/bind9/lib/irs/gai_strerror.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 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: gai_strerror.c,v 1.5 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file gai_strerror.c
+ * gai_strerror() returns an error message corresponding to an
+ * error code returned by getaddrinfo() and getnameinfo(). The following error
+ * codes and their meaning are defined in
+ * \link netdb.h include/irs/netdb.h.\endlink
+ * This implementation is almost an exact copy of lwres/gai_sterror.c except
+ * that it catches up the latest API standard, RFC3493.
+ *
+ * \li #EAI_ADDRFAMILY address family for hostname not supported
+ * \li #EAI_AGAIN temporary failure in name resolution
+ * \li #EAI_BADFLAGS invalid value for ai_flags
+ * \li #EAI_FAIL non-recoverable failure in name resolution
+ * \li #EAI_FAMILY ai_family not supported
+ * \li #EAI_MEMORY memory allocation failure
+ * \li #EAI_NODATA no address associated with hostname (obsoleted in RFC3493)
+ * \li #EAI_NONAME hostname nor servname provided, or not known
+ * \li #EAI_SERVICE servname not supported for ai_socktype
+ * \li #EAI_SOCKTYPE ai_socktype not supported
+ * \li #EAI_SYSTEM system error returned in errno
+ * \li #EAI_BADHINTS Invalid value for hints (non-standard)
+ * \li #EAI_PROTOCOL Resolved protocol is unknown (non-standard)
+ * \li #EAI_OVERFLOW Argument buffer overflow
+ * \li #EAI_INSECUREDATA Insecure Data (experimental)
+ *
+ * The message invalid error code is returned if ecode is out of range.
+ *
+ * ai_flags, ai_family and ai_socktype are elements of the struct
+ * addrinfo used by lwres_getaddrinfo().
+ *
+ * \section gai_strerror_see See Also
+ *
+ * strerror(), getaddrinfo(), getnameinfo(), RFC3493.
+ */
+#include <config.h>
+
+#include <irs/netdb.h>
+
+/*% Text of error messages. */
+static const char *gai_messages[] = {
+ "no error",
+ "address family for hostname not supported",
+ "temporary failure in name resolution",
+ "invalid value for ai_flags",
+ "non-recoverable failure in name resolution",
+ "ai_family not supported",
+ "memory allocation failure",
+ "no address associated with hostname",
+ "hostname nor servname provided, or not known",
+ "servname not supported for ai_socktype",
+ "ai_socktype not supported",
+ "system error returned in errno",
+ "bad hints",
+ "bad protocol",
+ "argument buffer overflow",
+ "insecure data provided"
+};
+
+/*%
+ * Returns an error message corresponding to an error code returned by
+ * getaddrinfo() and getnameinfo()
+ */
+IRS_GAISTRERROR_RETURN_T
+gai_strerror(int ecode) {
+ union {
+ const char *const_ptr;
+ char *deconst_ptr;
+ } ptr;
+
+ if ((ecode < 0) ||
+ (ecode >= (int)(sizeof(gai_messages)/sizeof(*gai_messages))))
+ ptr.const_ptr = "invalid error code";
+ else
+ ptr.const_ptr = gai_messages[ecode];
+ return (ptr.deconst_ptr);
+}
diff --git a/contrib/bind9/lib/irs/getaddrinfo.c b/contrib/bind9/lib/irs/getaddrinfo.c
new file mode 100644
index 0000000..e7075da
--- /dev/null
+++ b/contrib/bind9/lib/irs/getaddrinfo.c
@@ -0,0 +1,1295 @@
+/*
+ * Copyright (C) 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: getaddrinfo.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * getaddrinfo() is used to get a list of IP addresses and port
+ * numbers for host hostname and service servname as defined in RFC3493.
+ * hostname and servname are pointers to null-terminated strings
+ * or NULL. hostname is either a host name or a numeric host address
+ * string: a dotted decimal IPv4 address or an IPv6 address. servname is
+ * either a decimal port number or a service name as listed in
+ * /etc/services.
+ *
+ * If the operating system does not provide a struct addrinfo, the
+ * following structure is used:
+ *
+ * \code
+ * struct addrinfo {
+ * int ai_flags; // AI_PASSIVE, AI_CANONNAME
+ * int ai_family; // PF_xxx
+ * int ai_socktype; // SOCK_xxx
+ * int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6
+ * size_t ai_addrlen; // length of ai_addr
+ * char *ai_canonname; // canonical name for hostname
+ * struct sockaddr *ai_addr; // binary address
+ * struct addrinfo *ai_next; // next structure in linked list
+ * };
+ * \endcode
+ *
+ *
+ * hints is an optional pointer to a struct addrinfo. This structure can
+ * be used to provide hints concerning the type of socket that the caller
+ * supports or wishes to use. The caller can supply the following
+ * structure elements in *hints:
+ *
+ * <ul>
+ * <li>ai_family:
+ * The protocol family that should be used. When ai_family is set
+ * to PF_UNSPEC, it means the caller will accept any protocol
+ * family supported by the operating system.</li>
+ *
+ * <li>ai_socktype:
+ * denotes the type of socket -- SOCK_STREAM, SOCK_DGRAM or
+ * SOCK_RAW -- that is wanted. When ai_socktype is zero the caller
+ * will accept any socket type.</li>
+ *
+ * <li>ai_protocol:
+ * indicates which transport protocol is wanted: IPPROTO_UDP or
+ * IPPROTO_TCP. If ai_protocol is zero the caller will accept any
+ * protocol.</li>
+ *
+ * <li>ai_flags:
+ * Flag bits. If the AI_CANONNAME bit is set, a successful call to
+ * getaddrinfo() will return a null-terminated string
+ * containing the canonical name of the specified hostname in
+ * ai_canonname of the first addrinfo structure returned. Setting
+ * the AI_PASSIVE bit indicates that the returned socket address
+ * structure is intended for used in a call to bind(2). In this
+ * case, if the hostname argument is a NULL pointer, then the IP
+ * address portion of the socket address structure will be set to
+ * INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6
+ * address.<br /><br />
+ *
+ * When ai_flags does not set the AI_PASSIVE bit, the returned
+ * socket address structure will be ready for use in a call to
+ * connect(2) for a connection-oriented protocol or connect(2),
+ * sendto(2), or sendmsg(2) if a connectionless protocol was
+ * chosen. The IP address portion of the socket address structure
+ * will be set to the loopback address if hostname is a NULL
+ * pointer and AI_PASSIVE is not set in ai_flags.<br /><br />
+ *
+ * If ai_flags is set to AI_NUMERICHOST it indicates that hostname
+ * should be treated as a numeric string defining an IPv4 or IPv6
+ * address and no name resolution should be attempted.
+ * </li></ul>
+ *
+ * All other elements of the struct addrinfo passed via hints must be
+ * zero.
+ *
+ * A hints of NULL is treated as if the caller provided a struct addrinfo
+ * initialized to zero with ai_familyset to PF_UNSPEC.
+ *
+ * After a successful call to getaddrinfo(), *res is a pointer to a
+ * linked list of one or more addrinfo structures. Each struct addrinfo
+ * in this list cn be processed by following the ai_next pointer, until a
+ * NULL pointer is encountered. The three members ai_family, ai_socktype,
+ * and ai_protocol in each returned addrinfo structure contain the
+ * corresponding arguments for a call to socket(2). For each addrinfo
+ * structure in the list, the ai_addr member points to a filled-in socket
+ * address structure of length ai_addrlen.
+ *
+ * All of the information returned by getaddrinfo() is dynamically
+ * allocated: the addrinfo structures, and the socket address structures
+ * and canonical host name strings pointed to by the addrinfostructures.
+ * Memory allocated for the dynamically allocated structures created by a
+ * successful call to getaddrinfo() is released by freeaddrinfo().
+ * ai is a pointer to a struct addrinfo created by a call to getaddrinfo().
+ *
+ * \section irsreturn RETURN VALUES
+ *
+ * getaddrinfo() returns zero on success or one of the error codes
+ * listed in gai_strerror() if an error occurs. If both hostname and
+ * servname are NULL getaddrinfo() returns #EAI_NONAME.
+ *
+ * \section irssee SEE ALSO
+ *
+ * getaddrinfo(), freeaddrinfo(),
+ * gai_strerror(), RFC3493, getservbyname(3), connect(2),
+ * sendto(2), sendmsg(2), socket(2).
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/sockaddr.h>
+#include <isc/util.h>
+
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+#include <irs/context.h>
+#include <irs/netdb.h>
+#include <irs/resconf.h>
+
+#define SA(addr) ((struct sockaddr *)(addr))
+#define SIN(addr) ((struct sockaddr_in *)(addr))
+#define SIN6(addr) ((struct sockaddr_in6 *)(addr))
+#define SLOCAL(addr) ((struct sockaddr_un *)(addr))
+
+/*! \struct addrinfo
+ */
+static struct addrinfo
+ *ai_concat(struct addrinfo *ai1, struct addrinfo *ai2),
+ *ai_reverse(struct addrinfo *oai),
+ *ai_clone(struct addrinfo *oai, int family),
+ *ai_alloc(int family, int addrlen);
+#ifdef AF_LOCAL
+static int get_local(const char *name, int socktype, struct addrinfo **res);
+#endif
+
+static int
+resolve_name(int family, const char *hostname, int flags,
+ struct addrinfo **aip, int socktype, int port);
+
+static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip,
+ int socktype, int port);
+static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip,
+ int socktype, int port);
+static void set_order(int, int (**)(const char *, int, struct addrinfo **,
+ int, int));
+
+#define FOUND_IPV4 0x1
+#define FOUND_IPV6 0x2
+#define FOUND_MAX 2
+
+#define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST)
+/*%
+ * Get a list of IP addresses and port numbers for host hostname and
+ * service servname.
+ */
+int
+getaddrinfo(const char *hostname, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct servent *sp;
+ const char *proto;
+ int family, socktype, flags, protocol;
+ struct addrinfo *ai, *ai_list;
+ int err = 0;
+ int port, i;
+ int (*net_order[FOUND_MAX+1])(const char *, int, struct addrinfo **,
+ int, int);
+
+ if (hostname == NULL && servname == NULL)
+ return (EAI_NONAME);
+
+ proto = NULL;
+ if (hints != NULL) {
+ if ((hints->ai_flags & ~(ISC_AI_MASK)) != 0)
+ return (EAI_BADFLAGS);
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next) {
+ errno = EINVAL;
+ return (EAI_SYSTEM);
+ }
+ family = hints->ai_family;
+ socktype = hints->ai_socktype;
+ protocol = hints->ai_protocol;
+ flags = hints->ai_flags;
+ switch (family) {
+ case AF_UNSPEC:
+ switch (hints->ai_socktype) {
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ }
+ break;
+ case AF_INET:
+ case AF_INET6:
+ switch (hints->ai_socktype) {
+ case 0:
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_RAW:
+ break;
+ default:
+ return (EAI_SOCKTYPE);
+ }
+ break;
+#ifdef AF_LOCAL
+ case AF_LOCAL:
+ switch (hints->ai_socktype) {
+ case 0:
+ break;
+ case SOCK_STREAM:
+ break;
+ case SOCK_DGRAM:
+ break;
+ default:
+ return (EAI_SOCKTYPE);
+ }
+ break;
+#endif
+ default:
+ return (EAI_FAMILY);
+ }
+ } else {
+ protocol = 0;
+ family = 0;
+ socktype = 0;
+ flags = 0;
+ }
+
+#ifdef AF_LOCAL
+ /*!
+ * First, deal with AF_LOCAL. If the family was not set,
+ * then assume AF_LOCAL if the first character of the
+ * hostname/servname is '/'.
+ */
+
+ if (hostname != NULL &&
+ (family == AF_LOCAL || (family == 0 && *hostname == '/')))
+ return (get_local(hostname, socktype, res));
+
+ if (servname != NULL &&
+ (family == AF_LOCAL || (family == 0 && *servname == '/')))
+ return (get_local(servname, socktype, res));
+#endif
+
+ /*
+ * Ok, only AF_INET and AF_INET6 left.
+ */
+ ai_list = NULL;
+
+ /*
+ * First, look up the service name (port) if it was
+ * requested. If the socket type wasn't specified, then
+ * try and figure it out.
+ */
+ if (servname != NULL) {
+ char *e;
+
+ port = strtol(servname, &e, 10);
+ if (*e == '\0') {
+ if (socktype == 0)
+ return (EAI_SOCKTYPE);
+ if (port < 0 || port > 65535)
+ return (EAI_SERVICE);
+ port = htons((unsigned short) port);
+ } else {
+ sp = getservbyname(servname, proto);
+ if (sp == NULL)
+ return (EAI_SERVICE);
+ port = sp->s_port;
+ if (socktype == 0) {
+ if (strcmp(sp->s_proto, "tcp") == 0)
+ socktype = SOCK_STREAM;
+ else if (strcmp(sp->s_proto, "udp") == 0)
+ socktype = SOCK_DGRAM;
+ }
+ }
+ } else
+ port = 0;
+
+ /*
+ * Next, deal with just a service name, and no hostname.
+ * (we verified that one of them was non-null up above).
+ */
+ if (hostname == NULL && (flags & AI_PASSIVE) != 0) {
+ if (family == AF_INET || family == 0) {
+ ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in));
+ if (ai == NULL)
+ return (EAI_MEMORY);
+ ai->ai_socktype = socktype;
+ ai->ai_protocol = protocol;
+ SIN(ai->ai_addr)->sin_port = port;
+ ai->ai_next = ai_list;
+ ai_list = ai;
+ }
+
+ if (family == AF_INET6 || family == 0) {
+ ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6));
+ if (ai == NULL) {
+ freeaddrinfo(ai_list);
+ return (EAI_MEMORY);
+ }
+ ai->ai_socktype = socktype;
+ ai->ai_protocol = protocol;
+ SIN6(ai->ai_addr)->sin6_port = port;
+ ai->ai_next = ai_list;
+ ai_list = ai;
+ }
+
+ *res = ai_list;
+ return (0);
+ }
+
+ /*
+ * If the family isn't specified or AI_NUMERICHOST specified, check
+ * first to see if it is a numeric address.
+ * Though the gethostbyname2() routine will recognize numeric addresses,
+ * it will only recognize the format that it is being called for. Thus,
+ * a numeric AF_INET address will be treated by the AF_INET6 call as
+ * a domain name, and vice versa. Checking for both numerics here
+ * avoids that.
+ */
+ if (hostname != NULL &&
+ (family == 0 || (flags & AI_NUMERICHOST) != 0)) {
+ char abuf[sizeof(struct in6_addr)];
+ char nbuf[NI_MAXHOST];
+ int addrsize, addroff;
+#ifdef IRS_HAVE_SIN6_SCOPE_ID
+ char *p, *ep;
+ char ntmp[NI_MAXHOST];
+ isc_uint32_t scopeid;
+#endif
+
+#ifdef IRS_HAVE_SIN6_SCOPE_ID
+ /*
+ * Scope identifier portion.
+ */
+ ntmp[0] = '\0';
+ if (strchr(hostname, '%') != NULL) {
+ strncpy(ntmp, hostname, sizeof(ntmp) - 1);
+ ntmp[sizeof(ntmp) - 1] = '\0';
+ p = strchr(ntmp, '%');
+ ep = NULL;
+
+ /*
+ * Vendors may want to support non-numeric
+ * scopeid around here.
+ */
+
+ if (p != NULL)
+ scopeid = (isc_uint32_t)strtoul(p + 1,
+ &ep, 10);
+ if (p != NULL && ep != NULL && ep[0] == '\0')
+ *p = '\0';
+ else {
+ ntmp[0] = '\0';
+ scopeid = 0;
+ }
+ } else
+ scopeid = 0;
+#endif
+
+ if (inet_pton(AF_INET, hostname, (struct in_addr *)abuf)
+ == 1) {
+ if (family == AF_INET6) {
+ /*
+ * Convert to a V4 mapped address.
+ */
+ struct in6_addr *a6 = (struct in6_addr *)abuf;
+ memcpy(&a6->s6_addr[12], &a6->s6_addr[0], 4);
+ memset(&a6->s6_addr[10], 0xff, 2);
+ memset(&a6->s6_addr[0], 0, 10);
+ goto inet6_addr;
+ }
+ addrsize = sizeof(struct in_addr);
+ addroff = (char *)(&SIN(0)->sin_addr) - (char *)0;
+ family = AF_INET;
+ goto common;
+#ifdef IRS_HAVE_SIN6_SCOPE_ID
+ } else if (ntmp[0] != '\0' &&
+ inet_pton(AF_INET6, ntmp, abuf) == 1) {
+ if (family && family != AF_INET6)
+ return (EAI_NONAME);
+ addrsize = sizeof(struct in6_addr);
+ addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0;
+ family = AF_INET6;
+ goto common;
+#endif
+ } else if (inet_pton(AF_INET6, hostname, abuf) == 1) {
+ if (family != 0 && family != AF_INET6)
+ return (EAI_NONAME);
+ inet6_addr:
+ addrsize = sizeof(struct in6_addr);
+ addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0;
+ family = AF_INET6;
+
+ common:
+ ai = ai_alloc(family,
+ ((family == AF_INET6) ?
+ sizeof(struct sockaddr_in6) :
+ sizeof(struct sockaddr_in)));
+ if (ai == NULL)
+ return (EAI_MEMORY);
+ ai_list = ai;
+ ai->ai_socktype = socktype;
+ SIN(ai->ai_addr)->sin_port = port;
+ memcpy((char *)ai->ai_addr + addroff, abuf, addrsize);
+ if ((flags & AI_CANONNAME) != 0) {
+#ifdef IRS_HAVE_SIN6_SCOPE_ID
+ if (ai->ai_family == AF_INET6)
+ SIN6(ai->ai_addr)->sin6_scope_id =
+ scopeid;
+#endif
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
+ nbuf, sizeof(nbuf), NULL, 0,
+ NI_NUMERICHOST) == 0) {
+ ai->ai_canonname = strdup(nbuf);
+ if (ai->ai_canonname == NULL) {
+ freeaddrinfo(ai);
+ return (EAI_MEMORY);
+ }
+ } else {
+ /* XXX raise error? */
+ ai->ai_canonname = NULL;
+ }
+ }
+ goto done;
+ } else if ((flags & AI_NUMERICHOST) != 0) {
+ return (EAI_NONAME);
+ }
+ }
+
+ if (hostname == NULL && (flags & AI_PASSIVE) == 0) {
+ set_order(family, net_order);
+ for (i = 0; i < FOUND_MAX; i++) {
+ if (net_order[i] == NULL)
+ break;
+ err = (net_order[i])(hostname, flags, &ai_list,
+ socktype, port);
+ if (err != 0) {
+ if (ai_list != NULL)
+ freeaddrinfo(ai_list);
+ break;
+ }
+ }
+ } else
+ err = resolve_name(family, hostname, flags, &ai_list,
+ socktype, port);
+
+ if (ai_list == NULL) {
+ if (err == 0)
+ err = EAI_NONAME;
+ return (err);
+ }
+
+done:
+ ai_list = ai_reverse(ai_list);
+
+ *res = ai_list;
+ return (0);
+}
+
+typedef struct gai_restrans {
+ dns_clientrestrans_t *xid;
+ isc_boolean_t is_inprogress;
+ int error;
+ struct addrinfo ai_sentinel;
+ struct gai_resstate *resstate;
+} gai_restrans_t;
+
+typedef struct gai_resstate {
+ isc_mem_t *mctx;
+ struct gai_statehead *head;
+ dns_fixedname_t fixedname;
+ dns_name_t *qname;
+ gai_restrans_t *trans4;
+ gai_restrans_t *trans6;
+ ISC_LINK(struct gai_resstate) link;
+} gai_resstate_t;
+
+typedef struct gai_statehead {
+ int ai_family;
+ int ai_flags;
+ int ai_socktype;
+ int ai_port;
+ isc_appctx_t *actx;
+ dns_client_t *dnsclient;
+ ISC_LIST(struct gai_resstate) resstates;
+ unsigned int activestates;
+} gai_statehead_t;
+
+static isc_result_t
+make_resstate(isc_mem_t *mctx, gai_statehead_t *head, const char *hostname,
+ const char *domain, gai_resstate_t **statep)
+{
+ isc_result_t result;
+ gai_resstate_t *state;
+ dns_fixedname_t fixeddomain;
+ dns_name_t *qdomain;
+ size_t namelen;
+ isc_buffer_t b;
+ isc_boolean_t need_v4 = ISC_FALSE;
+ isc_boolean_t need_v6 = ISC_FALSE;
+
+ state = isc_mem_get(mctx, sizeof(*state));
+ if (state == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* Construct base domain name */
+ namelen = strlen(domain);
+ isc_buffer_init(&b, domain, namelen);
+ isc_buffer_add(&b, namelen);
+ dns_fixedname_init(&fixeddomain);
+ qdomain = dns_fixedname_name(&fixeddomain);
+ result = dns_name_fromtext(qdomain, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, state, sizeof(*state));
+ return (result);
+ }
+
+ /* Construct query name */
+ namelen = strlen(hostname);
+ isc_buffer_init(&b, hostname, namelen);
+ isc_buffer_add(&b, namelen);
+ dns_fixedname_init(&state->fixedname);
+ state->qname = dns_fixedname_name(&state->fixedname);
+ result = dns_name_fromtext(state->qname, &b, qdomain, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, state, sizeof(*state));
+ return (result);
+ }
+
+ if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET)
+ need_v4 = ISC_TRUE;
+ if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET6)
+ need_v6 = ISC_TRUE;
+
+ state->trans6 = NULL;
+ state->trans4 = NULL;
+ if (need_v4) {
+ state->trans4 = isc_mem_get(mctx, sizeof(gai_restrans_t));
+ if (state->trans4 == NULL) {
+ isc_mem_put(mctx, state, sizeof(*state));
+ return (ISC_R_NOMEMORY);
+ }
+ state->trans4->error = 0;
+ state->trans4->xid = NULL;
+ state->trans4->resstate = state;
+ state->trans4->is_inprogress = ISC_TRUE;
+ state->trans4->ai_sentinel.ai_next = NULL;
+ }
+ if (need_v6) {
+ state->trans6 = isc_mem_get(mctx, sizeof(gai_restrans_t));
+ if (state->trans6 == NULL) {
+ if (state->trans4 != NULL)
+ isc_mem_put(mctx, state->trans4,
+ sizeof(*state->trans4));
+ isc_mem_put(mctx, state, sizeof(*state));
+ return (ISC_R_NOMEMORY);
+ }
+ state->trans6->error = 0;
+ state->trans6->xid = NULL;
+ state->trans6->resstate = state;
+ state->trans6->is_inprogress = ISC_TRUE;
+ state->trans6->ai_sentinel.ai_next = NULL;
+ }
+
+ state->mctx = mctx;
+ state->head = head;
+ ISC_LINK_INIT(state, link);
+
+ *statep = state;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+make_resstates(isc_mem_t *mctx, const char *hostname, gai_statehead_t *head,
+ irs_resconf_t *resconf)
+{
+ isc_result_t result;
+ irs_resconf_searchlist_t *searchlist;
+ irs_resconf_search_t *searchent;
+ gai_resstate_t *resstate, *resstate0;
+
+ resstate0 = NULL;
+ result = make_resstate(mctx, head, hostname, ".", &resstate0);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ searchlist = irs_resconf_getsearchlist(resconf);
+ for (searchent = ISC_LIST_HEAD(*searchlist); searchent != NULL;
+ searchent = ISC_LIST_NEXT(searchent, link)) {
+ resstate = NULL;
+ result = make_resstate(mctx, head, hostname,
+ (const char *)searchent->domain,
+ &resstate);
+ if (result != ISC_R_SUCCESS)
+ break;
+
+ ISC_LIST_APPEND(head->resstates, resstate, link);
+ head->activestates++;
+ }
+
+ /*
+ * Insert the original hostname either at the head or the tail of the
+ * state list, depending on the number of labels contained in the
+ * original name and the 'ndots' configuration parameter.
+ */
+ if (dns_name_countlabels(resstate0->qname) >
+ irs_resconf_getndots(resconf) + 1) {
+ ISC_LIST_PREPEND(head->resstates, resstate0, link);
+ } else
+ ISC_LIST_APPEND(head->resstates, resstate0, link);
+ head->activestates++;
+
+ if (result != ISC_R_SUCCESS) {
+ while ((resstate = ISC_LIST_HEAD(head->resstates)) != NULL) {
+ ISC_LIST_UNLINK(head->resstates, resstate, link);
+ if (resstate->trans4 != NULL) {
+ isc_mem_put(mctx, resstate->trans4,
+ sizeof(*resstate->trans4));
+ }
+ if (resstate->trans6 != NULL) {
+ isc_mem_put(mctx, resstate->trans6,
+ sizeof(*resstate->trans6));
+ }
+
+ isc_mem_put(mctx, resstate, sizeof(*resstate));
+ }
+ }
+
+ return (result);
+}
+
+static void
+process_answer(isc_task_t *task, isc_event_t *event) {
+ int error = 0, family;
+ gai_restrans_t *trans = event->ev_arg;
+ gai_resstate_t *resstate;
+ dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
+ dns_rdatatype_t qtype;
+ dns_name_t *name;
+
+ REQUIRE(trans != NULL);
+ resstate = trans->resstate;
+ REQUIRE(resstate != NULL);
+ REQUIRE(task != NULL);
+
+ if (trans == resstate->trans4) {
+ family = AF_INET;
+ qtype = dns_rdatatype_a;
+ } else {
+ INSIST(trans == resstate->trans6);
+ family = AF_INET6;
+ qtype = dns_rdatatype_aaaa;
+ }
+
+ INSIST(trans->is_inprogress);
+ trans->is_inprogress = ISC_FALSE;
+
+ switch (rev->result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_NCACHENXDOMAIN: /* treat this as a fatal error? */
+ case DNS_R_NCACHENXRRSET:
+ break;
+ default:
+ switch (rev->vresult) {
+ case DNS_R_SIGINVALID:
+ case DNS_R_SIGEXPIRED:
+ case DNS_R_SIGFUTURE:
+ case DNS_R_KEYUNAUTHORIZED:
+ case DNS_R_MUSTBESECURE:
+ case DNS_R_COVERINGNSEC:
+ case DNS_R_NOTAUTHORITATIVE:
+ case DNS_R_NOVALIDKEY:
+ case DNS_R_NOVALIDDS:
+ case DNS_R_NOVALIDSIG:
+ error = EAI_INSECUREDATA;
+ break;
+ default:
+ error = EAI_FAIL;
+ }
+ goto done;
+ }
+
+ /* Parse the response and construct the addrinfo chain */
+ for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ isc_result_t result;
+ dns_rdataset_t *rdataset;
+ isc_buffer_t b;
+ isc_region_t r;
+ char t[1024];
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (!dns_rdataset_isassociated(rdataset))
+ continue;
+ if (rdataset->type != qtype)
+ continue;
+
+ if ((resstate->head->ai_flags & AI_CANONNAME) != 0) {
+ isc_buffer_init(&b, t, sizeof(t));
+ result = dns_name_totext(name, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS) {
+ error = EAI_FAIL;
+ goto done;
+ }
+ isc_buffer_putuint8(&b, '\0');
+ isc_buffer_usedregion(&b, &r);
+ }
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ struct addrinfo *ai;
+ dns_rdata_t rdata;
+ dns_rdata_in_a_t rdata_a;
+ dns_rdata_in_aaaa_t rdata_aaaa;
+
+ ai = ai_alloc(family,
+ ((family == AF_INET6) ?
+ sizeof(struct sockaddr_in6) :
+ sizeof(struct sockaddr_in)));
+ if (ai == NULL) {
+ error = EAI_MEMORY;
+ goto done;
+ }
+ ai->ai_socktype = resstate->head->ai_socktype;
+ ai->ai_next = trans->ai_sentinel.ai_next;
+ trans->ai_sentinel.ai_next = ai;
+
+ /*
+ * Set AF-specific parameters
+ * (IPv4/v6 address/port)
+ */
+ dns_rdata_init(&rdata);
+ switch (family) {
+ case AF_INET:
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &rdata_a,
+ NULL);
+
+ SIN(ai->ai_addr)->sin_port =
+ resstate->head->ai_port;
+ memcpy(&SIN(ai->ai_addr)->sin_addr,
+ &rdata_a.in_addr, 4);
+ dns_rdata_freestruct(&rdata_a);
+ break;
+ case AF_INET6:
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &rdata_aaaa,
+ NULL);
+ SIN6(ai->ai_addr)->sin6_port =
+ resstate->head->ai_port;
+ memcpy(&SIN6(ai->ai_addr)->sin6_addr,
+ &rdata_aaaa.in6_addr, 16);
+ dns_rdata_freestruct(&rdata_aaaa);
+ break;
+ }
+
+ if ((resstate->head->ai_flags & AI_CANONNAME)
+ != 0) {
+ ai->ai_canonname =
+ strdup((const char *)r.base);
+ if (ai->ai_canonname == NULL) {
+ error = EAI_MEMORY;
+ goto done;
+ }
+ }
+ }
+ }
+ }
+
+ done:
+ dns_client_freeresanswer(resstate->head->dnsclient, &rev->answerlist);
+ dns_client_destroyrestrans(&trans->xid);
+
+ isc_event_free(&event);
+
+ /* Make sure that error == 0 iff we have a non-empty list */
+ if (error == 0) {
+ if (trans->ai_sentinel.ai_next == NULL)
+ error = EAI_NONAME;
+ } else {
+ if (trans->ai_sentinel.ai_next != NULL) {
+ freeaddrinfo(trans->ai_sentinel.ai_next);
+ trans->ai_sentinel.ai_next = NULL;
+ }
+ }
+ trans->error = error;
+
+ /* Check whether we are done */
+ if ((resstate->trans4 == NULL || !resstate->trans4->is_inprogress) &&
+ (resstate->trans6 == NULL || !resstate->trans6->is_inprogress)) {
+ /*
+ * We're done for this state. If there is no other outstanding
+ * state, we can exit.
+ */
+ resstate->head->activestates--;
+ if (resstate->head->activestates == 0) {
+ isc_app_ctxsuspend(resstate->head->actx);
+ return;
+ }
+
+ /*
+ * There are outstanding states, but if we are at the head
+ * of the state list (i.e., at the highest search priority)
+ * and have any answer, we can stop now by canceling the
+ * others.
+ */
+ if (resstate == ISC_LIST_HEAD(resstate->head->resstates)) {
+ if ((resstate->trans4 != NULL &&
+ resstate->trans4->ai_sentinel.ai_next != NULL) ||
+ (resstate->trans6 != NULL &&
+ resstate->trans6->ai_sentinel.ai_next != NULL)) {
+ gai_resstate_t *rest;
+
+ for (rest = ISC_LIST_NEXT(resstate, link);
+ rest != NULL;
+ rest = ISC_LIST_NEXT(rest, link)) {
+ if (rest->trans4 != NULL &&
+ rest->trans4->xid != NULL)
+ dns_client_cancelresolve(
+ rest->trans4->xid);
+ if (rest->trans6 != NULL &&
+ rest->trans6->xid != NULL)
+ dns_client_cancelresolve(
+ rest->trans6->xid);
+ }
+ } else {
+ /*
+ * This search fails, so we move to the tail
+ * of the list so that the next entry will
+ * have the highest priority.
+ */
+ ISC_LIST_UNLINK(resstate->head->resstates,
+ resstate, link);
+ ISC_LIST_APPEND(resstate->head->resstates,
+ resstate, link);
+ }
+ }
+ }
+}
+
+static int
+resolve_name(int family, const char *hostname, int flags,
+ struct addrinfo **aip, int socktype, int port)
+{
+ isc_result_t result;
+ irs_context_t *irsctx;
+ irs_resconf_t *conf;
+ isc_mem_t *mctx;
+ isc_appctx_t *actx;
+ isc_task_t *task;
+ int terror = 0;
+ int error = 0;
+ dns_client_t *client;
+ gai_resstate_t *resstate;
+ gai_statehead_t head;
+ isc_boolean_t all_fail = ISC_TRUE;
+
+ /* get IRS context and the associated parameters */
+ irsctx = NULL;
+ result = irs_context_get(&irsctx);
+ if (result != ISC_R_SUCCESS)
+ return (EAI_FAIL);
+ actx = irs_context_getappctx(irsctx);
+
+ mctx = irs_context_getmctx(irsctx);
+ task = irs_context_gettask(irsctx);
+ conf = irs_context_getresconf(irsctx);
+ client = irs_context_getdnsclient(irsctx);
+
+ /* construct resolution states */
+ head.activestates = 0;
+ head.ai_family = family;
+ head.ai_socktype = socktype;
+ head.ai_flags = flags;
+ head.ai_port = port;
+ head.actx = actx;
+ head.dnsclient = client;
+ ISC_LIST_INIT(head.resstates);
+ result = make_resstates(mctx, hostname, &head, conf);
+ if (result != ISC_R_SUCCESS)
+ return (EAI_FAIL);
+
+ for (resstate = ISC_LIST_HEAD(head.resstates);
+ resstate != NULL; resstate = ISC_LIST_NEXT(resstate, link)) {
+ if (resstate->trans4 != NULL) {
+ result = dns_client_startresolve(client,
+ resstate->qname,
+ dns_rdataclass_in,
+ dns_rdatatype_a,
+ 0, task,
+ process_answer,
+ resstate->trans4,
+ &resstate->trans4->xid);
+ if (result == ISC_R_SUCCESS) {
+ resstate->trans4->is_inprogress = ISC_TRUE;
+ all_fail = ISC_FALSE;
+ } else
+ resstate->trans4->is_inprogress = ISC_FALSE;
+ }
+ if (resstate->trans6 != NULL) {
+ result = dns_client_startresolve(client,
+ resstate->qname,
+ dns_rdataclass_in,
+ dns_rdatatype_aaaa,
+ 0, task,
+ process_answer,
+ resstate->trans6,
+ &resstate->trans6->xid);
+ if (result == ISC_R_SUCCESS) {
+ resstate->trans6->is_inprogress = ISC_TRUE;
+ all_fail = ISC_FALSE;
+ } else
+ resstate->trans6->is_inprogress= ISC_FALSE;
+ }
+ }
+ if (!all_fail) {
+ /* Start all the events */
+ isc_app_ctxrun(actx);
+ } else
+ error = EAI_FAIL;
+
+ /* Cleanup */
+ while ((resstate = ISC_LIST_HEAD(head.resstates)) != NULL) {
+ int terror4 = 0, terror6 = 0;
+
+ ISC_LIST_UNLINK(head.resstates, resstate, link);
+
+ if (*aip == NULL) {
+ struct addrinfo *sentinel4 = NULL;
+ struct addrinfo *sentinel6 = NULL;
+
+ if (resstate->trans4 != NULL) {
+ sentinel4 =
+ resstate->trans4->ai_sentinel.ai_next;
+ resstate->trans4->ai_sentinel.ai_next = NULL;
+ }
+ if (resstate->trans6 != NULL) {
+ sentinel6 =
+ resstate->trans6->ai_sentinel.ai_next;
+ resstate->trans6->ai_sentinel.ai_next = NULL;
+ }
+ *aip = ai_concat(sentinel4, sentinel6);
+ }
+
+ if (resstate->trans4 != NULL) {
+ INSIST(resstate->trans4->xid == NULL);
+ terror4 = resstate->trans4->error;
+ isc_mem_put(mctx, resstate->trans4,
+ sizeof(*resstate->trans4));
+ }
+ if (resstate->trans6 != NULL) {
+ INSIST(resstate->trans6->xid == NULL);
+ terror6 = resstate->trans6->error;
+ isc_mem_put(mctx, resstate->trans6,
+ sizeof(*resstate->trans6));
+ }
+
+ /*
+ * If the entire lookup fails, we need to choose an appropriate
+ * error code from individual codes. We'll try to provide as
+ * specific a code as possible. In general, we are going to
+ * find an error code other than EAI_NONAME (which is too
+ * generic and may actually not be problematic in some cases).
+ * EAI_NONAME will be set below if no better code is found.
+ */
+ if (terror == 0 || terror == EAI_NONAME) {
+ if (terror4 != 0 && terror4 != EAI_NONAME)
+ terror = terror4;
+ else if (terror6 != 0 && terror6 != EAI_NONAME)
+ terror = terror6;
+ }
+
+ isc_mem_put(mctx, resstate, sizeof(*resstate));
+ }
+
+ if (*aip == NULL) {
+ error = terror;
+ if (error == 0)
+ error = EAI_NONAME;
+ }
+
+#if 1 /* XXX: enabled for finding leaks. should be cleaned up later. */
+ isc_app_ctxfinish(actx);
+ irs_context_destroy(&irsctx);
+#endif
+
+ return (error);
+}
+
+static char *
+irs_strsep(char **stringp, const char *delim) {
+ char *string = *stringp;
+ char *s;
+ const char *d;
+ char sc, dc;
+
+ if (string == NULL)
+ return (NULL);
+
+ for (s = string; *s != '\0'; s++) {
+ sc = *s;
+ for (d = delim; (dc = *d) != '\0'; d++)
+ if (sc == dc) {
+ *s++ = '\0';
+ *stringp = s;
+ return (string);
+ }
+ }
+ *stringp = NULL;
+ return (string);
+}
+
+static void
+set_order(int family, int (**net_order)(const char *, int, struct addrinfo **,
+ int, int))
+{
+ char *order, *tok;
+ int found;
+
+ if (family) {
+ switch (family) {
+ case AF_INET:
+ *net_order++ = add_ipv4;
+ break;
+ case AF_INET6:
+ *net_order++ = add_ipv6;
+ break;
+ }
+ } else {
+ order = getenv("NET_ORDER");
+ found = 0;
+ while (order != NULL) {
+ /*
+ * We ignore any unknown names.
+ */
+ tok = irs_strsep(&order, ":");
+ if (strcasecmp(tok, "inet6") == 0) {
+ if ((found & FOUND_IPV6) == 0)
+ *net_order++ = add_ipv6;
+ found |= FOUND_IPV6;
+ } else if (strcasecmp(tok, "inet") == 0 ||
+ strcasecmp(tok, "inet4") == 0) {
+ if ((found & FOUND_IPV4) == 0)
+ *net_order++ = add_ipv4;
+ found |= FOUND_IPV4;
+ }
+ }
+
+ /*
+ * Add in anything that we didn't find.
+ */
+ if ((found & FOUND_IPV4) == 0)
+ *net_order++ = add_ipv4;
+ if ((found & FOUND_IPV6) == 0)
+ *net_order++ = add_ipv6;
+ }
+ *net_order = NULL;
+ return;
+}
+
+static char v4_loop[4] = { 127, 0, 0, 1 };
+
+static int
+add_ipv4(const char *hostname, int flags, struct addrinfo **aip,
+ int socktype, int port)
+{
+ struct addrinfo *ai;
+
+ UNUSED(hostname);
+ UNUSED(flags);
+
+ ai = ai_clone(*aip, AF_INET); /* don't use ai_clone() */
+ if (ai == NULL) {
+ freeaddrinfo(*aip);
+ return (EAI_MEMORY);
+ }
+
+ *aip = ai;
+ ai->ai_socktype = socktype;
+ SIN(ai->ai_addr)->sin_port = port;
+ memcpy(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4);
+
+ return (0);
+}
+
+static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+static int
+add_ipv6(const char *hostname, int flags, struct addrinfo **aip,
+ int socktype, int port)
+{
+ struct addrinfo *ai;
+
+ UNUSED(hostname);
+ UNUSED(flags);
+
+ ai = ai_clone(*aip, AF_INET6); /* don't use ai_clone() */
+ if (ai == NULL) {
+ freeaddrinfo(*aip);
+ return (EAI_MEMORY);
+ }
+
+ *aip = ai;
+ ai->ai_socktype = socktype;
+ SIN6(ai->ai_addr)->sin6_port = port;
+ memcpy(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16);
+
+ return (0);
+}
+
+/*% Free address info. */
+void
+freeaddrinfo(struct addrinfo *ai) {
+ struct addrinfo *ai_next;
+
+ while (ai != NULL) {
+ ai_next = ai->ai_next;
+ if (ai->ai_addr != NULL)
+ free(ai->ai_addr);
+ if (ai->ai_canonname)
+ free(ai->ai_canonname);
+ free(ai);
+ ai = ai_next;
+ }
+}
+
+#ifdef AF_LOCAL
+static int
+get_local(const char *name, int socktype, struct addrinfo **res) {
+ struct addrinfo *ai;
+ struct sockaddr_un *slocal;
+
+ if (socktype == 0)
+ return (EAI_SOCKTYPE);
+
+ ai = ai_alloc(AF_LOCAL, sizeof(*slocal));
+ if (ai == NULL)
+ return (EAI_MEMORY);
+
+ slocal = SLOCAL(ai->ai_addr);
+ strncpy(slocal->sun_path, name, sizeof(slocal->sun_path));
+
+ ai->ai_socktype = socktype;
+ /*
+ * ai->ai_flags, ai->ai_protocol, ai->ai_canonname,
+ * and ai->ai_next were initialized to zero.
+ */
+
+ *res = ai;
+ return (0);
+}
+#endif
+
+/*!
+ * Allocate an addrinfo structure, and a sockaddr structure
+ * of the specificed length. We initialize:
+ * ai_addrlen
+ * ai_family
+ * ai_addr
+ * ai_addr->sa_family
+ * ai_addr->sa_len (IRS_PLATFORM_HAVESALEN)
+ * and everything else is initialized to zero.
+ */
+static struct addrinfo *
+ai_alloc(int family, int addrlen) {
+ struct addrinfo *ai;
+
+ ai = (struct addrinfo *)calloc(1, sizeof(*ai));
+ if (ai == NULL)
+ return (NULL);
+
+ ai->ai_addr = SA(calloc(1, addrlen));
+ if (ai->ai_addr == NULL) {
+ free(ai);
+ return (NULL);
+ }
+ ai->ai_addrlen = addrlen;
+ ai->ai_family = family;
+ ai->ai_addr->sa_family = family;
+#ifdef IRS_PLATFORM_HAVESALEN
+ ai->ai_addr->sa_len = addrlen;
+#endif
+ return (ai);
+}
+
+static struct addrinfo *
+ai_clone(struct addrinfo *oai, int family) {
+ struct addrinfo *ai;
+
+ ai = ai_alloc(family, ((family == AF_INET6) ?
+ sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)));
+
+ if (ai == NULL) {
+ if (oai != NULL)
+ freeaddrinfo(oai);
+ return (NULL);
+ }
+ if (oai == NULL)
+ return (ai);
+
+ ai->ai_flags = oai->ai_flags;
+ ai->ai_socktype = oai->ai_socktype;
+ ai->ai_protocol = oai->ai_protocol;
+ ai->ai_canonname = NULL;
+ ai->ai_next = oai;
+ return (ai);
+}
+
+static struct addrinfo *
+ai_reverse(struct addrinfo *oai) {
+ struct addrinfo *nai, *tai;
+
+ nai = NULL;
+
+ while (oai != NULL) {
+ /*
+ * Grab one off the old list.
+ */
+ tai = oai;
+ oai = oai->ai_next;
+ /*
+ * Put it on the front of the new list.
+ */
+ tai->ai_next = nai;
+ nai = tai;
+ }
+ return (nai);
+}
+
+
+static struct addrinfo *
+ai_concat(struct addrinfo *ai1, struct addrinfo *ai2) {
+ struct addrinfo *ai_tmp;
+
+ if (ai1 == NULL)
+ return (ai2);
+ else if (ai2 == NULL)
+ return (ai1);
+
+ for (ai_tmp = ai1; ai_tmp != NULL && ai_tmp->ai_next != NULL;
+ ai_tmp = ai_tmp->ai_next)
+ ;
+
+ ai_tmp->ai_next = ai2;
+
+ return (ai1);
+}
diff --git a/contrib/bind9/lib/irs/getnameinfo.c b/contrib/bind9/lib/irs/getnameinfo.c
new file mode 100644
index 0000000..fadd8d8
--- /dev/null
+++ b/contrib/bind9/lib/irs/getnameinfo.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 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: getnameinfo.c,v 1.4 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/**
+ * getnameinfo() returns the hostname for the struct sockaddr sa which is
+ * salen bytes long. The hostname is of length hostlen and is returned via
+ * *host. The maximum length of the hostname is 1025 bytes: #NI_MAXHOST.
+ *
+ * The name of the service associated with the port number in sa is
+ * returned in *serv. It is servlen bytes long. The maximum length of the
+ * service name is #NI_MAXSERV - 32 bytes.
+ *
+ * The flags argument sets the following bits:
+ *
+ * \li #NI_NOFQDN:
+ * A fully qualified domain name is not required for local hosts.
+ * The local part of the fully qualified domain name is returned
+ * instead.
+ *
+ * \li #NI_NUMERICHOST
+ * Return the address in numeric form, as if calling inet_ntop(),
+ * instead of a host name.
+ *
+ * \li #NI_NAMEREQD
+ * A name is required. If the hostname cannot be found in the DNS
+ * and this flag is set, a non-zero error code is returned. If the
+ * hostname is not found and the flag is not set, the address is
+ * returned in numeric form.
+ *
+ * \li #NI_NUMERICSERV
+ * The service name is returned as a digit string representing the
+ * port number.
+ *
+ * \li #NI_DGRAM
+ * Specifies that the service being looked up is a datagram
+ * service, and causes getservbyport() to be called with a second
+ * argument of "udp" instead of its default of "tcp". This is
+ * required for the few ports (512-514) that have different
+ * services for UDP and TCP.
+ *
+ * \section getnameinfo_return Return Values
+ *
+ * getnameinfo() returns 0 on success or a non-zero error code if
+ * an error occurs.
+ *
+ * \section getname_see See Also
+ *
+ * RFC3493, getservbyport(),
+ * getnamebyaddr(). inet_ntop().
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/client.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+
+#include <irs/context.h>
+#include <irs/netdb.h>
+
+#define SUCCESS 0
+
+/*% afd structure definition */
+static struct afd {
+ int a_af;
+ size_t a_addrlen;
+ size_t a_socklen;
+} afdl [] = {
+ /*!
+ * First entry is linked last...
+ */
+ { AF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in) },
+ { AF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6) },
+ {0, 0, 0},
+};
+
+/*!
+ * The test against 0 is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define ERR(code) \
+ do { result = (code); \
+ if (result != 0) goto cleanup; \
+ } while (0)
+
+int
+getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
+ IRS_GETNAMEINFO_BUFLEN_T hostlen, char *serv,
+ IRS_GETNAMEINFO_BUFLEN_T servlen, IRS_GETNAMEINFO_FLAGS_T flags)
+{
+ struct afd *afd;
+ struct servent *sp;
+ unsigned short port;
+#ifdef IRS_PLATFORM_HAVESALEN
+ size_t len;
+#endif
+ int family, i;
+ const void *addr;
+ char *p;
+#if 0
+ unsigned long v4a;
+ unsigned char pfx;
+#endif
+ char numserv[sizeof("65000")];
+ char numaddr[sizeof("abcd:abcd:abcd:abcd:abcd:abcd:255.255.255.255")
+ + 1 + sizeof("4294967295")];
+ const char *proto;
+ int result = SUCCESS;
+
+ if (sa == NULL)
+ ERR(EAI_FAIL);
+
+#ifdef IRS_PLATFORM_HAVESALEN
+ len = sa->sa_len;
+ if (len != salen)
+ ERR(EAI_FAIL);
+#endif
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ ERR(EAI_FAMILY);
+
+ found:
+ if (salen != afd->a_socklen)
+ ERR(EAI_FAIL);
+
+ switch (family) {
+ case AF_INET:
+ port = ((const struct sockaddr_in *)sa)->sin_port;
+ addr = &((const struct sockaddr_in *)sa)->sin_addr.s_addr;
+ break;
+
+ case AF_INET6:
+ port = ((const struct sockaddr_in6 *)sa)->sin6_port;
+ addr = ((const struct sockaddr_in6 *)sa)->sin6_addr.s6_addr;
+ break;
+
+ default:
+ port = 0;
+ addr = NULL;
+ INSIST(0);
+ }
+ proto = (flags & NI_DGRAM) ? "udp" : "tcp";
+
+ if (serv == NULL || servlen == 0U) {
+ /*
+ * Caller does not want service.
+ */
+ } else if ((flags & NI_NUMERICSERV) != 0 ||
+ (sp = getservbyport(port, proto)) == NULL) {
+ snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
+ if ((strlen(numserv) + 1) > servlen)
+ ERR(EAI_OVERFLOW);
+ strcpy(serv, numserv);
+ } else {
+ if ((strlen(sp->s_name) + 1) > servlen)
+ ERR(EAI_OVERFLOW);
+ strcpy(serv, sp->s_name);
+ }
+
+#if 0
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ flags |= NI_NUMERICHOST;
+ break;
+
+ case AF_INET6:
+ pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0];
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ flags |= NI_NUMERICHOST;
+ break;
+ }
+#endif
+
+ if (host == NULL || hostlen == 0U) {
+ /*
+ * do nothing in this case.
+ * in case you are wondering if "&&" is more correct than
+ * "||" here: RFC3493 says that host == NULL or hostlen == 0
+ * means that the caller does not want the result.
+ */
+ } else if ((flags & NI_NUMERICHOST) != 0) {
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ ERR(EAI_SYSTEM);
+#if defined(IRS_HAVE_SIN6_SCOPE_ID)
+ if (afd->a_af == AF_INET6 &&
+ ((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
+ char *p = numaddr + strlen(numaddr);
+ const char *stringscope = NULL;
+#ifdef VENDOR_SPECIFIC
+ /*
+ * Vendors may want to add support for
+ * non-numeric scope identifier.
+ */
+ stringscope = foo;
+#endif
+ if (stringscope == NULL) {
+ snprintf(p, sizeof(numaddr) - (p - numaddr),
+ "%%%u",
+ ((const struct sockaddr_in6 *)sa)->sin6_scope_id);
+ } else {
+ snprintf(p, sizeof(numaddr) - (p - numaddr),
+ "%%%s", stringscope);
+ }
+ }
+#endif
+ if (strlen(numaddr) + 1 > hostlen)
+ ERR(EAI_OVERFLOW);
+ strcpy(host, numaddr);
+ } else {
+ isc_netaddr_t netaddr;
+ dns_fixedname_t ptrfname;
+ dns_name_t *ptrname;
+ irs_context_t *irsctx = NULL;
+ dns_client_t *client;
+ isc_boolean_t found = ISC_FALSE;
+ dns_namelist_t answerlist;
+ dns_rdataset_t *rdataset;
+ isc_region_t hostregion;
+ char hoststr[1024]; /* is this enough? */
+ isc_result_t iresult;
+
+ /* Get IRS context and the associated DNS client object */
+ iresult = irs_context_get(&irsctx);
+ if (iresult != ISC_R_SUCCESS)
+ ERR(EAI_FAIL);
+ client = irs_context_getdnsclient(irsctx);
+
+ /* Make query name */
+ isc_netaddr_fromsockaddr(&netaddr, (const isc_sockaddr_t *)sa);
+ dns_fixedname_init(&ptrfname);
+ ptrname = dns_fixedname_name(&ptrfname);
+ iresult = dns_byaddr_createptrname2(&netaddr, 0, ptrname);
+ if (iresult != ISC_R_SUCCESS)
+ ERR(EAI_FAIL);
+
+ /* Get the PTR RRset */
+ ISC_LIST_INIT(answerlist);
+ iresult = dns_client_resolve(client, ptrname,
+ dns_rdataclass_in,
+ dns_rdatatype_ptr,
+ DNS_CLIENTRESOPT_ALLOWRUN,
+ &answerlist);
+ switch (iresult) {
+ case ISC_R_SUCCESS:
+ /*
+ * a 'non-existent' error is not necessarily fatal for
+ * getnameinfo().
+ */
+ case DNS_R_NCACHENXDOMAIN:
+ case DNS_R_NCACHENXRRSET:
+ break;
+ case DNS_R_SIGINVALID:
+ case DNS_R_SIGEXPIRED:
+ case DNS_R_SIGFUTURE:
+ case DNS_R_KEYUNAUTHORIZED:
+ case DNS_R_MUSTBESECURE:
+ case DNS_R_COVERINGNSEC:
+ case DNS_R_NOTAUTHORITATIVE:
+ case DNS_R_NOVALIDKEY:
+ case DNS_R_NOVALIDDS:
+ case DNS_R_NOVALIDSIG:
+ ERR(EAI_INSECUREDATA);
+ default:
+ ERR(EAI_FAIL);
+ }
+
+ /* Parse the answer for the hostname */
+ for (ptrname = ISC_LIST_HEAD(answerlist); ptrname != NULL;
+ ptrname = ISC_LIST_NEXT(ptrname, link)) {
+ for (rdataset = ISC_LIST_HEAD(ptrname->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (!dns_rdataset_isassociated(rdataset))
+ continue;
+ if (rdataset->type != dns_rdatatype_ptr)
+ continue;
+
+ for (iresult = dns_rdataset_first(rdataset);
+ iresult == ISC_R_SUCCESS;
+ iresult = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata;
+ dns_rdata_ptr_t rdata_ptr;
+ isc_buffer_t b;
+
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &rdata_ptr,
+ NULL);
+
+ isc_buffer_init(&b, hoststr,
+ sizeof(hoststr));
+ iresult =
+ dns_name_totext(&rdata_ptr.ptr,
+ ISC_TRUE, &b);
+ dns_rdata_freestruct(&rdata_ptr);
+ if (iresult == ISC_R_SUCCESS) {
+ /*
+ * We ignore the rest of the
+ * answer. After all,
+ * getnameinfo() can return
+ * at most one hostname.
+ */
+ found = ISC_TRUE;
+ isc_buffer_usedregion(
+ &b, &hostregion);
+ goto ptrfound;
+ }
+
+ }
+ }
+ }
+ ptrfound:
+ dns_client_freeresanswer(client, &answerlist);
+ if (found) {
+ if ((flags & NI_NOFQDN) != 0) {
+ p = strchr(hoststr, '.');
+ if (p)
+ *p = '\0';
+ }
+ if (hostregion.length + 1 > hostlen)
+ ERR(EAI_OVERFLOW);
+ snprintf(host, hostlen, "%.*s",
+ (int)hostregion.length,
+ (char *)hostregion.base);
+ } else {
+ if ((flags & NI_NAMEREQD) != 0)
+ ERR(EAI_NONAME);
+ if (inet_ntop(afd->a_af, addr, numaddr,
+ sizeof(numaddr)) == NULL)
+ ERR(EAI_SYSTEM);
+ if ((strlen(numaddr) + 1) > hostlen)
+ ERR(EAI_OVERFLOW);
+ strcpy(host, numaddr);
+ }
+ }
+ result = SUCCESS;
+
+ cleanup:
+ return (result);
+}
diff --git a/contrib/bind9/lib/irs/include/Makefile.in b/contrib/bind9/lib/irs/include/Makefile.in
new file mode 100644
index 0000000..22a63ee
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = irs
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/contrib/bind9/lib/irs/include/irs/Makefile.in b/contrib/bind9/lib/irs/include/irs/Makefile.in
new file mode 100644
index 0000000..7d50995
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/irs/Makefile.in
@@ -0,0 +1,44 @@
+# Copyright (C) 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: Makefile.in,v 1.3 2009-09-02 23:48:02 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+#
+# Only list headers that are to be installed and are not
+# machine generated. The latter are handled specially in the
+# install target below.
+#
+HEADERS = version.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/irs
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/irs ; \
+ done
+ ${INSTALL_DATA} netdb.h ${DESTDIR}${includedir}/irs
+ ${INSTALL_DATA} platform.h ${DESTDIR}${includedir}/irs
+
+distclean::
+ rm -f netdb.h platform.h
diff --git a/contrib/bind9/lib/irs/include/irs/context.h b/contrib/bind9/lib/irs/include/irs/context.h
new file mode 100644
index 0000000..c49cfcf
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/irs/context.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 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: context.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+#ifndef IRS_CONTEXT_H
+#define IRS_CONTEXT_H 1
+
+/*! \file
+ *
+ * \brief
+ * The IRS context module provides an abstract interface to the DNS library
+ * with an application. An IRS context object initializes and holds various
+ * resources used in the DNS library.
+ */
+
+#include <dns/types.h>
+#include <irs/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+irs_context_create(irs_context_t **contextp);
+/*%<
+ * Create an IRS context. It internally initializes the ISC and DNS libraries
+ * (if not yet), creates a DNS client object and initializes the client using
+ * the configuration files parsed via the 'resconf' and 'dnsconf' IRS modules.
+ * Some of the internally initialized objects can be used by the application
+ * via irs_context_getxxx() functions (see below).
+ *
+ * Requires:
+ *
+ *\li contextp != NULL && *contextp == NULL.
+ */
+
+isc_result_t
+irs_context_get(irs_context_t **contextp);
+/*%<
+ * Return an IRS context for the calling thread. If no IRS context is
+ * associated to the thread, this function creates a new one by calling
+ * irs_context_create(), and associates it with the thread as a thread specific
+ * data value. This function is provided for standard libraries that are
+ * expected to be thread-safe but do not accept an appropriate IRS context
+ * as a library parameter, e.g., getaddrinfo().
+ *
+ * Requires:
+ *
+ *\li contextp != NULL && *contextp == NULL.
+ */
+
+void
+irs_context_destroy(irs_context_t **contextp);
+/*%<
+ * Destroy an IRS context.
+ *
+ * Requires:
+ *
+ *\li '*contextp' is a valid IRS context.
+ *
+ * Ensures:
+ *\li '*contextp' == NULL.
+ */
+
+isc_mem_t *
+irs_context_getmctx(irs_context_t *context);
+/*%<
+ * Return the memory context held in the context.
+ *
+ * Requires:
+ *
+ *\li 'context' is a valid IRS context.
+ */
+
+isc_appctx_t *
+irs_context_getappctx(irs_context_t *context);
+/*%<
+ * Return the application context held in the context.
+ *
+ * Requires:
+ *
+ *\li 'context' is a valid IRS context.
+ */
+
+isc_taskmgr_t *
+irs_context_gettaskmgr(irs_context_t *context);
+/*%<
+ * Return the task manager held in the context.
+ *
+ * Requires:
+ *
+ *\li 'context' is a valid IRS context.
+ */
+
+isc_timermgr_t *
+irs_context_gettimermgr(irs_context_t *context);
+/*%<
+ * Return the timer manager held in the context.
+ *
+ * Requires:
+ *
+ *\li 'context' is a valid IRS context.
+ */
+
+isc_task_t *
+irs_context_gettask(irs_context_t *context);
+/*%<
+ * Return the task object held in the context.
+ *
+ * Requires:
+ *
+ *\li 'context' is a valid IRS context.
+ */
+
+dns_client_t *
+irs_context_getdnsclient(irs_context_t *context);
+/*%<
+ * Return the DNS client object held in the context.
+ *
+ * Requires:
+ *
+ *\li 'context' is a valid IRS context.
+ */
+
+irs_resconf_t *
+irs_context_getresconf(irs_context_t *context);
+/*%<
+ * Return the resolver configuration object held in the context.
+ *
+ * Requires:
+ *
+ *\li 'context' is a valid IRS context.
+ */
+
+irs_dnsconf_t *
+irs_context_getdnsconf(irs_context_t *context);
+/*%<
+ * Return the advanced DNS configuration object held in the context.
+ *
+ * Requires:
+ *
+ *\li 'context' is a valid IRS context.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* IRS_CONTEXT_H */
diff --git a/contrib/bind9/lib/irs/include/irs/dnsconf.h b/contrib/bind9/lib/irs/include/irs/dnsconf.h
new file mode 100644
index 0000000..0041c16
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/irs/dnsconf.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 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: dnsconf.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+#ifndef IRS_DNSCONF_H
+#define IRS_DNSCONF_H 1
+
+/*! \file
+ *
+ * \brief
+ * The IRS dnsconf module parses an "advanced" configuration file related to
+ * the DNS library, such as trusted keys for DNSSEC validation, and creates
+ * the corresponding configuration objects for the DNS library modules.
+ *
+ * Notes:
+ * This module is very experimental and the configuration syntax or library
+ * interfaces may change in future versions. Currently, only the
+ * 'trusted-keys' statement is supported, whose syntax is the same as the
+ * same name of statement for named.conf.
+ */
+
+#include <irs/types.h>
+
+/*%
+ * A compound structure storing DNS key information mainly for DNSSEC
+ * validation. A dns_key_t object will be created using the 'keyname' and
+ * 'keydatabuf' members with the dst_key_fromdns() function.
+ */
+typedef struct irs_dnsconf_dnskey {
+ dns_name_t *keyname;
+ isc_buffer_t *keydatabuf;
+ ISC_LINK(struct irs_dnsconf_dnskey) link;
+} irs_dnsconf_dnskey_t;
+
+typedef ISC_LIST(irs_dnsconf_dnskey_t) irs_dnsconf_dnskeylist_t;
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp);
+/*%<
+ * Load the "advanced" DNS configuration file 'filename' in the "dns.conf"
+ * format, and create a new irs_dnsconf_t object from the configuration.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'filename' != NULL
+ *
+ *\li 'confp' != NULL && '*confp' == NULL
+ */
+
+void
+irs_dnsconf_destroy(irs_dnsconf_t **confp);
+/*%<
+ * Destroy the dnsconf object.
+ *
+ * Requires:
+ *
+ *\li '*confp' is a valid dnsconf object.
+ *
+ * Ensures:
+ *
+ *\li *confp == NULL
+ */
+
+irs_dnsconf_dnskeylist_t *
+irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf);
+/*%<
+ * Return a list of key information stored in 'conf'.
+ *
+ * Requires:
+ *
+ *\li 'conf' is a valid dnsconf object.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* IRS_DNSCONF_H */
diff --git a/contrib/bind9/lib/irs/include/irs/netdb.h.in b/contrib/bind9/lib/irs/include/irs/netdb.h.in
new file mode 100644
index 0000000..9dda413
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/irs/netdb.h.in
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 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: netdb.h.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#ifndef IRS_NETDB_H
+#define IRS_NETDB_H 1
+
+#include <stddef.h> /* Required on FreeBSD (and others?) for size_t. */
+#include <netdb.h> /* Contractual provision. */
+
+/*
+ * Define if <netdb.h> does not declare struct addrinfo.
+ */
+@ISC_IRS_NEEDADDRINFO@
+
+#ifdef ISC_IRS_NEEDADDRINFO
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* Length of ai_addr */
+ char *ai_canonname; /* Canonical name for hostname */
+ struct sockaddr *ai_addr; /* Binary address */
+ struct addrinfo *ai_next; /* Next structure in linked list */
+};
+#endif
+
+/*
+ * Undefine all #defines we are interested in as <netdb.h> may or may not have
+ * defined them.
+ */
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+
+#undef NETDB_INTERNAL
+#undef NETDB_SUCCESS
+#undef HOST_NOT_FOUND
+#undef TRY_AGAIN
+#undef NO_RECOVERY
+#undef NO_DATA
+#undef NO_ADDRESS
+
+#define NETDB_INTERNAL -1 /* see errno */
+#define NETDB_SUCCESS 0 /* no problem */
+#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
+#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */
+#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define NO_DATA 4 /* Valid name, no data record of requested type */
+#define NO_ADDRESS NO_DATA /* no address, look for MX record */
+
+/*
+ * Error return codes from getaddrinfo(). EAI_INSECUREDATA is our own extension
+ * and it's very unlikely to be already defined, but undef it just in case; it
+ * at least doesn't do any harm.
+ */
+
+#undef EAI_ADDRFAMILY
+#undef EAI_AGAIN
+#undef EAI_BADFLAGS
+#undef EAI_FAIL
+#undef EAI_FAMILY
+#undef EAI_MEMORY
+#undef EAI_NODATA
+#undef EAI_NONAME
+#undef EAI_SERVICE
+#undef EAI_SOCKTYPE
+#undef EAI_SYSTEM
+#undef EAI_BADHINTS
+#undef EAI_PROTOCOL
+#undef EAI_OVERFLOW
+#undef EAI_INSECUREDATA
+#undef EAI_MAX
+
+#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
+#define EAI_AGAIN 2 /* temporary failure in name resolution */
+#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
+#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
+#define EAI_FAMILY 5 /* ai_family not supported */
+#define EAI_MEMORY 6 /* memory allocation failure */
+#define EAI_NODATA 7 /* no address associated with hostname */
+#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
+#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
+#define EAI_SYSTEM 11 /* system error returned in errno */
+#define EAI_BADHINTS 12
+#define EAI_PROTOCOL 13
+#define EAI_OVERFLOW 14
+#define EAI_INSECUREDATA 15
+#define EAI_MAX 16
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#undef AI_PASSIVE
+#undef AI_CANONNAME
+#undef AI_NUMERICHOST
+
+#define AI_PASSIVE 0x00000001
+#define AI_CANONNAME 0x00000002
+#define AI_NUMERICHOST 0x00000004
+
+/*
+ * Flag values for getipnodebyname()
+ */
+#undef AI_V4MAPPED
+#undef AI_ALL
+#undef AI_ADDRCONFIG
+#undef AI_DEFAULT
+
+#define AI_V4MAPPED 0x00000008
+#define AI_ALL 0x00000010
+#define AI_ADDRCONFIG 0x00000020
+#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG)
+
+/*
+ * Constants for lwres_getnameinfo()
+ */
+#undef NI_MAXHOST
+#undef NI_MAXSERV
+
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for lwres_getnameinfo()
+ */
+#undef NI_NOFQDN
+#undef NI_NUMERICHOST
+#undef NI_NAMEREQD
+#undef NI_NUMERICSERV
+#undef NI_DGRAM
+#undef NI_NUMERICSCOPE
+
+#define NI_NOFQDN 0x00000001
+#define NI_NUMERICHOST 0x00000002
+#define NI_NAMEREQD 0x00000004
+#define NI_NUMERICSERV 0x00000008
+#define NI_DGRAM 0x00000010
+
+/*
+ * Tell Emacs to use C mode on this file.
+ * Local variables:
+ * mode: c
+ * End:
+ */
+
+#endif /* IRS_NETDB_H */
diff --git a/contrib/bind9/lib/irs/include/irs/platform.h.in b/contrib/bind9/lib/irs/include/irs/platform.h.in
new file mode 100644
index 0000000..f61f671
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/irs/platform.h.in
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 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: platform.h.in,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#ifndef IRS_PLATFORM_H
+#define IRS_PLATFORM_H 1
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+#ifndef IRS_PLATFORM_USEDECLSPEC
+#define LIBIRS_EXTERNAL_DATA
+#else
+#ifdef LIBIRS_EXPORTS
+#define LIBIRS_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBIRS_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#endif
+
+/*
+ * Tell Emacs to use C mode on this file.
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
+#endif /* IRS_PLATFORM_H */
diff --git a/contrib/bind9/lib/irs/include/irs/resconf.h b/contrib/bind9/lib/irs/include/irs/resconf.h
new file mode 100644
index 0000000..8249c7b
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/irs/resconf.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 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: resconf.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+#ifndef IRS_RESCONF_H
+#define IRS_RESCONF_H 1
+
+/*! \file
+ *
+ * \brief
+ * The IRS resconf module parses the legacy "/etc/resolv.conf" file and
+ * creates the corresponding configuration objects for the DNS library
+ * modules.
+ */
+
+#include <irs/types.h>
+
+/*%
+ * A DNS search list specified in the 'domain' or 'search' statements
+ * in the "resolv.conf" file.
+ */
+typedef struct irs_resconf_search {
+ char *domain;
+ ISC_LINK(struct irs_resconf_search) link;
+} irs_resconf_search_t;
+
+typedef ISC_LIST(irs_resconf_search_t) irs_resconf_searchlist_t;
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp);
+/*%<
+ * Load the resolver configuration file 'filename' in the "resolv.conf" format,
+ * and create a new irs_resconf_t object from the configuration.
+ *
+ * Notes:
+ *
+ *\li Currently, only the following options are supported:
+ * nameserver, domain, search, sortlist, ndots, and options.
+ * In addition, 'sortlist' is not actually effective; it's parsed, but
+ * the application cannot use the configuration.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'filename' != NULL
+ *
+ *\li 'confp' != NULL && '*confp' == NULL
+ */
+
+void
+irs_resconf_destroy(irs_resconf_t **confp);
+/*%<
+ * Destroy the resconf object.
+ *
+ * Requires:
+ *
+ *\li '*confp' is a valid resconf object.
+ *
+ * Ensures:
+ *
+ *\li *confp == NULL
+ */
+
+isc_sockaddrlist_t *
+irs_resconf_getnameservers(irs_resconf_t *conf);
+/*%<
+ * Return a list of name server addresses stored in 'conf'.
+ *
+ * Requires:
+ *
+ *\li 'conf' is a valid resconf object.
+ */
+
+irs_resconf_searchlist_t *
+irs_resconf_getsearchlist(irs_resconf_t *conf);
+/*%<
+ * Return the search list stored in 'conf'.
+ *
+ * Requires:
+ *
+ *\li 'conf' is a valid resconf object.
+ */
+
+unsigned int
+irs_resconf_getndots(irs_resconf_t *conf);
+/*%<
+ * Return the 'ndots' value stored in 'conf'.
+ *
+ * Requires:
+ *
+ *\li 'conf' is a valid resconf object.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* IRS_RESCONF_H */
diff --git a/contrib/bind9/lib/irs/include/irs/types.h b/contrib/bind9/lib/irs/include/irs/types.h
new file mode 100644
index 0000000..4b8a804
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/irs/types.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 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: types.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+#ifndef IRS_TYPES_H
+#define IRS_TYPES_H 1
+
+/* Core Types. Alphabetized by defined type. */
+
+/*%< per-thread IRS context */
+typedef struct irs_context irs_context_t;
+/*%< resolv.conf configuration information */
+typedef struct irs_resconf irs_resconf_t;
+/*%< advanced DNS-related configuration information */
+typedef struct irs_dnsconf irs_dnsconf_t;
+
+#endif /* IRS_TYPES_H */
diff --git a/contrib/bind9/lib/irs/include/irs/version.h b/contrib/bind9/lib/irs/include/irs/version.h
new file mode 100644
index 0000000..f43aa14
--- /dev/null
+++ b/contrib/bind9/lib/irs/include/irs/version.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 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: version.h,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#include <irs/platform.h>
+
+LIBIRS_EXTERNAL_DATA extern const char irs_version[];
+
+LIBIRS_EXTERNAL_DATA extern const unsigned int irs_libinterface;
+LIBIRS_EXTERNAL_DATA extern const unsigned int irs_librevision;
+LIBIRS_EXTERNAL_DATA extern const unsigned int irs_libage;
diff --git a/contrib/bind9/lib/irs/resconf.c b/contrib/bind9/lib/irs/resconf.c
new file mode 100644
index 0000000..af1413b
--- /dev/null
+++ b/contrib/bind9/lib/irs/resconf.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 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: resconf.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file resconf.c */
+
+/**
+ * Module for parsing resolv.conf files (largely derived from lwconfig.c).
+ *
+ * irs_resconf_load() opens the file filename and parses it to initialize
+ * the configuration structure.
+ *
+ * \section lwconfig_return Return Values
+ *
+ * irs_resconf_load() returns #IRS_R_SUCCESS if it successfully read and
+ * parsed filename. It returns a non-0 error code if filename could not be
+ * opened or contained incorrect resolver statements.
+ *
+ * \section lwconfig_see See Also
+ *
+ * stdio(3), \link resolver resolver \endlink
+ *
+ * \section files Files
+ *
+ * /etc/resolv.conf
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+#include <isc/util.h>
+
+#include <irs/resconf.h>
+
+#define IRS_RESCONF_MAGIC ISC_MAGIC('R', 'E', 'S', 'c')
+#define IRS_RESCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_RESCONF_MAGIC)
+
+/*!
+ * protocol constants
+ */
+
+#if ! defined(NS_INADDRSZ)
+#define NS_INADDRSZ 4
+#endif
+
+#if ! defined(NS_IN6ADDRSZ)
+#define NS_IN6ADDRSZ 16
+#endif
+
+/*!
+ * resolv.conf parameters
+ */
+
+#define RESCONFMAXNAMESERVERS 3 /*%< max 3 "nameserver" entries */
+#define RESCONFMAXSEARCH 8 /*%< max 8 domains in "search" entry */
+#define RESCONFMAXLINELEN 256 /*%< max size of a line */
+#define RESCONFMAXSORTLIST 10 /*%< max 10 */
+
+/*!
+ * configuration data structure
+ */
+
+struct irs_resconf {
+ /*
+ * The configuration data is a thread-specific object, and does not
+ * need to be locked.
+ */
+ unsigned int magic;
+ isc_mem_t *mctx;
+
+ isc_sockaddrlist_t nameservers;
+ unsigned int numns; /*%< number of configured servers */
+
+ char *domainname;
+ char *search[RESCONFMAXSEARCH];
+ isc_uint8_t searchnxt; /*%< index for next free slot */
+
+ irs_resconf_searchlist_t searchlist;
+
+ struct {
+ isc_netaddr_t addr;
+ /*% mask has a non-zero 'family' if set */
+ isc_netaddr_t mask;
+ } sortlist[RESCONFMAXSORTLIST];
+ isc_uint8_t sortlistnxt;
+
+ /*%< non-zero if 'options debug' set */
+ isc_uint8_t resdebug;
+ /*%< set to n in 'options ndots:n' */
+ isc_uint8_t ndots;
+};
+
+static isc_result_t
+resconf_parsenameserver(irs_resconf_t *conf, FILE *fp);
+static isc_result_t
+resconf_parsedomain(irs_resconf_t *conf, FILE *fp);
+static isc_result_t
+resconf_parsesearch(irs_resconf_t *conf, FILE *fp);
+static isc_result_t
+resconf_parsesortlist(irs_resconf_t *conf, FILE *fp);
+static isc_result_t
+resconf_parseoption(irs_resconf_t *ctx, FILE *fp);
+
+/*!
+ * Eat characters from FP until EOL or EOF. Returns EOF or '\n'
+ */
+static int
+eatline(FILE *fp) {
+ int ch;
+
+ ch = fgetc(fp);
+ while (ch != '\n' && ch != EOF)
+ ch = fgetc(fp);
+
+ return (ch);
+}
+
+/*!
+ * Eats white space up to next newline or non-whitespace character (of
+ * EOF). Returns the last character read. Comments are considered white
+ * space.
+ */
+static int
+eatwhite(FILE *fp) {
+ int ch;
+
+ ch = fgetc(fp);
+ while (ch != '\n' && ch != EOF && isspace((unsigned char)ch))
+ ch = fgetc(fp);
+
+ if (ch == ';' || ch == '#')
+ ch = eatline(fp);
+
+ return (ch);
+}
+
+/*!
+ * Skip over any leading whitespace and then read in the next sequence of
+ * non-whitespace characters. In this context newline is not considered
+ * whitespace. Returns EOF on end-of-file, or the character
+ * that caused the reading to stop.
+ */
+static int
+getword(FILE *fp, char *buffer, size_t size) {
+ int ch;
+ char *p = buffer;
+
+ REQUIRE(buffer != NULL);
+ REQUIRE(size > 0U);
+
+ *p = '\0';
+
+ ch = eatwhite(fp);
+
+ if (ch == EOF)
+ return (EOF);
+
+ do {
+ *p = '\0';
+
+ if (ch == EOF || isspace((unsigned char)ch))
+ break;
+ else if ((size_t) (p - buffer) == size - 1)
+ return (EOF); /* Not enough space. */
+
+ *p++ = (char)ch;
+ ch = fgetc(fp);
+ } while (1);
+
+ return (ch);
+}
+
+static isc_result_t
+add_server(isc_mem_t *mctx, const char *address_str,
+ isc_sockaddrlist_t *nameservers)
+{
+ int error;
+ isc_sockaddr_t *address = NULL;
+ struct addrinfo hints, *res;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ res = NULL;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICHOST;
+ error = getaddrinfo(address_str, "53", &hints, &res);
+ if (error != 0)
+ return (ISC_R_BADADDRESSFORM);
+
+ /* XXX: special case: treat all-0 IPv4 address as loopback */
+ if (res->ai_family == AF_INET) {
+ struct in_addr *v4;
+ unsigned char zeroaddress[] = {0, 0, 0, 0};
+ unsigned char loopaddress[] = {127, 0, 0, 1};
+
+ v4 = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
+ if (memcmp(v4, zeroaddress, 4) == 0)
+ memcpy(v4, loopaddress, 4);
+ }
+
+ address = isc_mem_get(mctx, sizeof(*address));
+ if (address == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ if (res->ai_addrlen > sizeof(address->type)) {
+ isc_mem_put(mctx, address, sizeof(*address));
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ address->length = res->ai_addrlen;
+ memcpy(&address->type.sa, res->ai_addr, res->ai_addrlen);
+ ISC_LINK_INIT(address, link);
+ ISC_LIST_APPEND(*nameservers, address, link);
+
+ cleanup:
+ freeaddrinfo(res);
+
+ return (result);
+}
+
+static isc_result_t
+create_addr(const char *buffer, isc_netaddr_t *addr, int convert_zero) {
+ struct in_addr v4;
+ struct in6_addr v6;
+
+ if (inet_aton(buffer, &v4) == 1) {
+ if (convert_zero) {
+ unsigned char zeroaddress[] = {0, 0, 0, 0};
+ unsigned char loopaddress[] = {127, 0, 0, 1};
+ if (memcmp(&v4, zeroaddress, 4) == 0)
+ memcpy(&v4, loopaddress, 4);
+ }
+ addr->family = AF_INET;
+ memcpy(&addr->type.in, &v4, NS_INADDRSZ);
+ addr->zone = 0;
+ } else if (inet_pton(AF_INET6, buffer, &v6) == 1) {
+ addr->family = AF_INET6;
+ memcpy(&addr->type.in6, &v6, NS_IN6ADDRSZ);
+ addr->zone = 0;
+ } else
+ return (ISC_R_BADADDRESSFORM); /* Unrecognised format. */
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+resconf_parsenameserver(irs_resconf_t *conf, FILE *fp) {
+ char word[RESCONFMAXLINELEN];
+ int cp;
+ isc_result_t result;
+
+ if (conf->numns == RESCONFMAXNAMESERVERS)
+ return (ISC_R_SUCCESS);
+
+ cp = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (ISC_R_UNEXPECTEDEND); /* Nothing on line. */
+ else if (cp == ' ' || cp == '\t')
+ cp = eatwhite(fp);
+
+ if (cp != EOF && cp != '\n')
+ return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */
+
+ result = add_server(conf->mctx, word, &conf->nameservers);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ conf->numns++;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+resconf_parsedomain(irs_resconf_t *conf, FILE *fp) {
+ char word[RESCONFMAXLINELEN];
+ int res, i;
+
+ res = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */
+ else if (res == ' ' || res == '\t')
+ res = eatwhite(fp);
+
+ if (res != EOF && res != '\n')
+ return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */
+
+ if (conf->domainname != NULL)
+ isc_mem_free(conf->mctx, conf->domainname);
+
+ /*
+ * Search and domain are mutually exclusive.
+ */
+ for (i = 0; i < RESCONFMAXSEARCH; i++) {
+ if (conf->search[i] != NULL) {
+ isc_mem_free(conf->mctx, conf->search[i]);
+ conf->search[i] = NULL;
+ }
+ }
+ conf->searchnxt = 0;
+
+ conf->domainname = isc_mem_strdup(conf->mctx, word);
+ if (conf->domainname == NULL)
+ return (ISC_R_NOMEMORY);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+resconf_parsesearch(irs_resconf_t *conf, FILE *fp) {
+ int idx, delim;
+ char word[RESCONFMAXLINELEN];
+
+ if (conf->domainname != NULL) {
+ /*
+ * Search and domain are mutually exclusive.
+ */
+ isc_mem_free(conf->mctx, conf->domainname);
+ conf->domainname = NULL;
+ }
+
+ /*
+ * Remove any previous search definitions.
+ */
+ for (idx = 0; idx < RESCONFMAXSEARCH; idx++) {
+ if (conf->search[idx] != NULL) {
+ isc_mem_free(conf->mctx, conf->search[idx]);
+ conf->search[idx] = NULL;
+ }
+ }
+ conf->searchnxt = 0;
+
+ delim = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */
+
+ idx = 0;
+ while (strlen(word) > 0U) {
+ if (conf->searchnxt == RESCONFMAXSEARCH)
+ goto ignore; /* Too many domains. */
+
+ conf->search[idx] = isc_mem_strdup(conf->mctx, word);
+ if (conf->search[idx] == NULL)
+ return (ISC_R_NOMEMORY);
+ idx++;
+ conf->searchnxt++;
+
+ ignore:
+ if (delim == EOF || delim == '\n')
+ break;
+ else
+ delim = getword(fp, word, sizeof(word));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+resconf_parsesortlist(irs_resconf_t *conf, FILE *fp) {
+ int delim, res, idx;
+ char word[RESCONFMAXLINELEN];
+ char *p;
+
+ delim = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */
+
+ while (strlen(word) > 0U) {
+ if (conf->sortlistnxt == RESCONFMAXSORTLIST)
+ return (ISC_R_QUOTA); /* Too many values. */
+
+ p = strchr(word, '/');
+ if (p != NULL)
+ *p++ = '\0';
+
+ idx = conf->sortlistnxt;
+ res = create_addr(word, &conf->sortlist[idx].addr, 1);
+ if (res != ISC_R_SUCCESS)
+ return (res);
+
+ if (p != NULL) {
+ res = create_addr(p, &conf->sortlist[idx].mask, 0);
+ if (res != ISC_R_SUCCESS)
+ return (res);
+ } else {
+ /*
+ * Make up a mask. (XXX: is this correct?)
+ */
+ conf->sortlist[idx].mask = conf->sortlist[idx].addr;
+ memset(&conf->sortlist[idx].mask.type, 0xff,
+ sizeof(conf->sortlist[idx].mask.type));
+ }
+
+ conf->sortlistnxt++;
+
+ if (delim == EOF || delim == '\n')
+ break;
+ else
+ delim = getword(fp, word, sizeof(word));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+resconf_parseoption(irs_resconf_t *conf, FILE *fp) {
+ int delim;
+ long ndots;
+ char *p;
+ char word[RESCONFMAXLINELEN];
+
+ delim = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */
+
+ while (strlen(word) > 0U) {
+ if (strcmp("debug", word) == 0) {
+ conf->resdebug = 1;
+ } else if (strncmp("ndots:", word, 6) == 0) {
+ ndots = strtol(word + 6, &p, 10);
+ if (*p != '\0') /* Bad string. */
+ return (ISC_R_UNEXPECTEDTOKEN);
+ if (ndots < 0 || ndots > 0xff) /* Out of range. */
+ return (ISC_R_RANGE);
+ conf->ndots = (isc_uint8_t)ndots;
+ }
+
+ if (delim == EOF || delim == '\n')
+ break;
+ else
+ delim = getword(fp, word, sizeof(word));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+add_search(irs_resconf_t *conf, char *domain) {
+ irs_resconf_search_t *entry;
+
+ entry = isc_mem_get(conf->mctx, sizeof(*entry));
+ if (entry == NULL)
+ return (ISC_R_NOMEMORY);
+
+ entry->domain = domain;
+ ISC_LINK_INIT(entry, link);
+ ISC_LIST_APPEND(conf->searchlist, entry, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*% parses a file and fills in the data structure. */
+isc_result_t
+irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp)
+{
+ FILE *fp = NULL;
+ char word[256];
+ isc_result_t rval, ret;
+ irs_resconf_t *conf;
+ int i, stopchar;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(filename != NULL);
+ REQUIRE(strlen(filename) > 0U);
+ REQUIRE(confp != NULL && *confp == NULL);
+
+ conf = isc_mem_get(mctx, sizeof(*conf));
+ if (conf == NULL)
+ return (ISC_R_NOMEMORY);
+
+ conf->mctx = mctx;
+ ISC_LIST_INIT(conf->nameservers);
+ conf->numns = 0;
+ conf->domainname = NULL;
+ conf->searchnxt = 0;
+ conf->resdebug = 0;
+ conf->ndots = 1;
+ for (i = 0; i < RESCONFMAXSEARCH; i++)
+ conf->search[i] = NULL;
+
+ errno = 0;
+ if ((fp = fopen(filename, "r")) == NULL) {
+ isc_mem_put(mctx, conf, sizeof(*conf));
+ return (ISC_R_INVALIDFILE);
+ }
+
+ ret = ISC_R_SUCCESS;
+ do {
+ stopchar = getword(fp, word, sizeof(word));
+ if (stopchar == EOF) {
+ rval = ISC_R_SUCCESS;
+ break;
+ }
+
+ if (strlen(word) == 0U)
+ rval = ISC_R_SUCCESS;
+ else if (strcmp(word, "nameserver") == 0)
+ rval = resconf_parsenameserver(conf, fp);
+ else if (strcmp(word, "domain") == 0)
+ rval = resconf_parsedomain(conf, fp);
+ else if (strcmp(word, "search") == 0)
+ rval = resconf_parsesearch(conf, fp);
+ else if (strcmp(word, "sortlist") == 0)
+ rval = resconf_parsesortlist(conf, fp);
+ else if (strcmp(word, "options") == 0)
+ rval = resconf_parseoption(conf, fp);
+ else {
+ /* unrecognised word. Ignore entire line */
+ rval = ISC_R_SUCCESS;
+ stopchar = eatline(fp);
+ if (stopchar == EOF) {
+ break;
+ }
+ }
+ if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS)
+ ret = rval;
+ } while (1);
+
+ fclose(fp);
+
+ /* If we don't find a nameserver fall back to localhost */
+ if (conf->numns == 0) {
+ INSIST(ISC_LIST_EMPTY(conf->nameservers));
+
+ /* XXX: should we catch errors? */
+ (void)add_server(conf->mctx, "127.0.0.1", &conf->nameservers);
+ (void)add_server(conf->mctx, "::1", &conf->nameservers);
+ }
+
+ /*
+ * Construct unified search list from domain or configured
+ * search list
+ */
+ ISC_LIST_INIT(conf->searchlist);
+ if (conf->domainname != NULL) {
+ ret = add_search(conf, conf->domainname);
+ } else if (conf->searchnxt > 0) {
+ for (i = 0; i < conf->searchnxt; i++) {
+ ret = add_search(conf, conf->search[i]);
+ if (ret != ISC_R_SUCCESS)
+ break;
+ }
+ }
+
+ conf->magic = IRS_RESCONF_MAGIC;
+
+ if (ret != ISC_R_SUCCESS)
+ irs_resconf_destroy(&conf);
+ else
+ *confp = conf;
+
+ return (ret);
+}
+
+void
+irs_resconf_destroy(irs_resconf_t **confp) {
+ irs_resconf_t *conf;
+ isc_sockaddr_t *address;
+ irs_resconf_search_t *searchentry;
+ int i;
+
+ REQUIRE(confp != NULL);
+ conf = *confp;
+ REQUIRE(IRS_RESCONF_VALID(conf));
+
+ while ((searchentry = ISC_LIST_HEAD(conf->searchlist)) != NULL) {
+ ISC_LIST_UNLINK(conf->searchlist, searchentry, link);
+ isc_mem_put(conf->mctx, searchentry, sizeof(*searchentry));
+ }
+
+ while ((address = ISC_LIST_HEAD(conf->nameservers)) != NULL) {
+ ISC_LIST_UNLINK(conf->nameservers, address, link);
+ isc_mem_put(conf->mctx, address, sizeof(*address));
+ }
+
+ if (conf->domainname != NULL)
+ isc_mem_free(conf->mctx, conf->domainname);
+
+ for (i = 0; i < RESCONFMAXSEARCH; i++) {
+ if (conf->search[i] != NULL)
+ isc_mem_free(conf->mctx, conf->search[i]);
+ }
+
+ isc_mem_put(conf->mctx, conf, sizeof(*conf));
+
+ *confp = NULL;
+}
+
+isc_sockaddrlist_t *
+irs_resconf_getnameservers(irs_resconf_t *conf) {
+ REQUIRE(IRS_RESCONF_VALID(conf));
+
+ return (&conf->nameservers);
+}
+
+irs_resconf_searchlist_t *
+irs_resconf_getsearchlist(irs_resconf_t *conf) {
+ REQUIRE(IRS_RESCONF_VALID(conf));
+
+ return (&conf->searchlist);
+}
+
+unsigned int
+irs_resconf_getndots(irs_resconf_t *conf) {
+ REQUIRE(IRS_RESCONF_VALID(conf));
+
+ return ((unsigned int)conf->ndots);
+}
diff --git a/contrib/bind9/lib/irs/version.c b/contrib/bind9/lib/irs/version.c
new file mode 100644
index 0000000..b27de99
--- /dev/null
+++ b/contrib/bind9/lib/irs/version.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 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: version.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#include <irs/version.h>
+
+const char irs_version[] = VERSION;
+
+const unsigned int irs_libinterface = LIBINTERFACE;
+const unsigned int irs_librevision = LIBREVISION;
+const unsigned int irs_libage = LIBAGE;
diff --git a/contrib/bind9/lib/isc/Makefile.in b/contrib/bind9/lib/isc/Makefile.in
index d831fcf..d92c0b8 100644
--- a/contrib/bind9/lib/isc/Makefile.in
+++ b/contrib/bind9/lib/isc/Makefile.in
@@ -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.96.50.6 2010-06-09 01:52:54 marka Exp $
+# $Id: Makefile.in,v 1.109 2010-06-09 01:43:09 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -27,8 +27,8 @@ CINCLUDES = -I${srcdir}/unix/include \
-I${srcdir}/@ISC_THREAD_DIR@/include \
-I${srcdir}/@ISC_ARCH_DIR@/include \
-I./include \
- -I${srcdir}/include
-CDEFINES =
+ -I${srcdir}/include @ISC_OPENSSL_INC@
+CDEFINES = @USE_OPENSSL@
CWARNINGS =
# Alphabetically
@@ -39,7 +39,6 @@ UNIXOBJS = @ISC_ISCIPV6_O@ \
unix/os.@O@ unix/resource.@O@ unix/socket.@O@ unix/stdio.@O@ \
unix/stdtime.@O@ unix/strerror.@O@ unix/syslog.@O@ unix/time.@O@
-
NLSOBJS = nls/msgcat.@O@
THREADOPTOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@
@@ -52,8 +51,9 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \
# Alphabetically
OBJS = @ISC_EXTRA_OBJS@ \
- assertions.@O@ base32.@O@ base64.@O@ bitstring.@O@ buffer.@O@ \
- bufferlist.@O@ commandline.@O@ error.@O@ event.@O@ \
+ assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \
+ bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \
+ error.@O@ event.@O@ \
hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \
httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
@@ -64,11 +64,12 @@ OBJS = @ISC_EXTRA_OBJS@ \
serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ \
string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \
timer.@O@ version.@O@ ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS}
+SYMTBLOBJS = backtrace-emptytbl.@O@
# Alphabetically
SRCS = @ISC_EXTRA_SRCS@ \
- assertions.c base32.c base64.c bitstring.c buffer.c \
- bufferlist.c commandline.c error.c event.c \
+ assertions.c backtrace.c base32.c base64.c bitstring.c \
+ buffer.c bufferlist.c commandline.c error.c event.c \
heap.c hex.c hmacmd5.c hmacsha.c \
httpd.c inet_aton.c iterated_hash.c \
lex.c lfsr.c lib.c log.c \
@@ -77,7 +78,7 @@ SRCS = @ISC_EXTRA_SRCS@ \
parseint.c portset.c quota.c radix.c random.c \
ratelimiter.c refcount.c region.c result.c rwlock.c \
serial.c sha1.c sha2.c sockaddr.c stats.c string.c strtoul.c \
- symtab.c task.c taskpool.c timer.c version.c
+ symtab.c symtbl-empty.c task.c taskpool.c timer.c version.c
LIBS = @LIBS@
@@ -98,17 +99,27 @@ version.@O@: version.c
-DLIBAGE=${LIBAGE} \
-c ${srcdir}/version.c
-libisc.@SA@: ${OBJS}
+libisc.@SA@: ${OBJS} ${SYMTBLOBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS} ${SYMTBLOBJS}
+ ${RANLIB} $@
+
+libisc-nosymtbl.@SA@: ${OBJS}
${AR} ${ARFLAGS} $@ ${OBJS}
${RANLIB} $@
-libisc.la: ${OBJS}
+libisc.la: ${OBJS} ${SYMTBLOBJS}
${LIBTOOL_MODE_LINK} \
${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la -rpath ${libdir} \
-version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${SYMTBLOBJS} ${LIBS}
+
+libisc-nosymtbl.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-nosymtbl.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
${OBJS} ${LIBS}
-timestamp: libisc.@A@
+timestamp: libisc.@A@ libisc-nosymtbl.@A@
touch timestamp
installdirs:
@@ -118,4 +129,5 @@ install:: timestamp installdirs
${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ ${DESTDIR}${libdir}
clean distclean::
- rm -f libisc.@A@ libisc.la timestamp
+ rm -f libisc.@A@ libisc-nosymtbl.@A@ libisc.la \
+ libisc-nosymtbl.la timestamp
diff --git a/contrib/bind9/lib/isc/alpha/include/isc/atomic.h b/contrib/bind9/lib/isc/alpha/include/isc/atomic.h
index bb4f1ad..012c955 100644
--- a/contrib/bind9/lib/isc/alpha/include/isc/atomic.h
+++ b/contrib/bind9/lib/isc/alpha/include/isc/atomic.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: atomic.h,v 1.5.332.2 2009-04-08 06:47:32 tbox Exp $ */
+/* $Id: atomic.h,v 1.7 2009-04-08 06:48:23 tbox Exp $ */
/*
* This code was written based on FreeBSD's kernel source whose copyright
diff --git a/contrib/bind9/lib/isc/api b/contrib/bind9/lib/isc/api
index e1f7b71..b91b130 100644
--- a/contrib/bind9/lib/isc/api
+++ b/contrib/bind9/lib/isc/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 54
-LIBREVISION = 1
-LIBAGE = 4
+LIBINTERFACE = 81
+LIBREVISION = 2
+LIBAGE = 0
diff --git a/contrib/bind9/lib/isc/app_api.c b/contrib/bind9/lib/isc/app_api.c
new file mode 100644
index 0000000..b2a2f14
--- /dev/null
+++ b/contrib/bind9/lib/isc/app_api.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 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: app_api.c,v 1.5 2009-09-02 23:48:02 tbox Exp $ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_appctxcreatefunc_t appctx_createfunc = NULL;
+
+#define ISCAPI_APPMETHODS_VALID(m) ISC_MAGIC_VALID(m, ISCAPI_APPMETHODS_MAGIC)
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_register(isc_appctxcreatefunc_t createfunc) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+ LOCK(&createlock);
+ if (appctx_createfunc == NULL)
+ appctx_createfunc = createfunc;
+ else
+ result = ISC_R_EXISTS;
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+isc_result_t
+isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(appctx_createfunc != NULL);
+ result = (*appctx_createfunc)(mctx, ctxp);
+
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+void
+isc_appctx_destroy(isc_appctx_t **ctxp) {
+ REQUIRE(ctxp != NULL && ISCAPI_APPCTX_VALID(*ctxp));
+
+ (*ctxp)->methods->ctxdestroy(ctxp);
+
+ ENSURE(*ctxp == NULL);
+}
+
+isc_result_t
+isc_app_ctxstart(isc_appctx_t *ctx) {
+ REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+ return (ctx->methods->ctxstart(ctx));
+}
+
+isc_result_t
+isc_app_ctxrun(isc_appctx_t *ctx) {
+ REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+ return (ctx->methods->ctxrun(ctx));
+}
+
+isc_result_t
+isc_app_ctxsuspend(isc_appctx_t *ctx) {
+ REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+ return (ctx->methods->ctxsuspend(ctx));
+}
+
+isc_result_t
+isc_app_ctxshutdown(isc_appctx_t *ctx) {
+ REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+ return (ctx->methods->ctxshutdown(ctx));
+}
+
+void
+isc_app_ctxfinish(isc_appctx_t *ctx) {
+ REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+ ctx->methods->ctxfinish(ctx);
+}
+
+void
+isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr) {
+ REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+ REQUIRE(taskmgr != NULL);
+
+ ctx->methods->settaskmgr(ctx, taskmgr);
+}
+
+void
+isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr) {
+ REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+ REQUIRE(socketmgr != NULL);
+
+ ctx->methods->setsocketmgr(ctx, socketmgr);
+}
+
+void
+isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr) {
+ REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+ REQUIRE(timermgr != NULL);
+
+ ctx->methods->settimermgr(ctx, timermgr);
+}
diff --git a/contrib/bind9/lib/isc/assertions.c b/contrib/bind9/lib/isc/assertions.c
index b98d61d..fe082b7 100644
--- a/contrib/bind9/lib/isc/assertions.c
+++ b/contrib/bind9/lib/isc/assertions.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) 1997-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: assertions.c,v 1.23 2008-10-15 23:47:31 tbox Exp $ */
+/* $Id: assertions.c,v 1.26 2009-09-29 15:06:07 fdupont Exp $ */
/*! \file */
@@ -25,29 +25,47 @@
#include <stdlib.h>
#include <isc/assertions.h>
+#include <isc/backtrace.h>
#include <isc/msgs.h>
+#include <isc/result.h>
+
+/*
+ * The maximum number of stack frames to dump on assertion failure.
+ */
+#ifndef BACKTRACE_MAXFRAME
+#define BACKTRACE_MAXFRAME 128
+#endif
/*%
* Forward.
*/
-/* coverity[+kill] */
static void
default_callback(const char *, int, isc_assertiontype_t, const char *);
+static isc_assertioncallback_t isc_assertion_failed_cb = default_callback;
+
/*%
* Public.
*/
-LIBISC_EXTERNAL_DATA isc_assertioncallback_t isc_assertion_failed =
- default_callback;
+/*% assertion failed handler */
+/* coverity[+kill] */
+void
+isc_assertion_failed(const char *file, int line, isc_assertiontype_t type,
+ const char *cond)
+{
+ isc_assertion_failed_cb(file, line, type, cond);
+ abort();
+ /* NOTREACHED */
+}
/*% Set callback. */
void
isc_assertion_setcallback(isc_assertioncallback_t cb) {
if (cb == NULL)
- isc_assertion_failed = default_callback;
+ isc_assertion_failed_cb = default_callback;
else
- isc_assertion_failed = cb;
+ isc_assertion_failed_cb = cb;
}
/*% Type to Text */
@@ -87,11 +105,35 @@ static void
default_callback(const char *file, int line, isc_assertiontype_t type,
const char *cond)
{
- fprintf(stderr, "%s:%d: %s(%s) %s.\n",
+ void *tracebuf[BACKTRACE_MAXFRAME];
+ int i, nframes;
+ const char *logsuffix = ".";
+ const char *fname;
+ isc_result_t result;
+
+ result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes);
+ if (result == ISC_R_SUCCESS && nframes > 0)
+ logsuffix = ", back trace";
+
+ fprintf(stderr, "%s:%d: %s(%s) %s%s\n",
file, line, isc_assertion_typetotext(type), cond,
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
- ISC_MSG_FAILED, "failed"));
+ ISC_MSG_FAILED, "failed"), logsuffix);
+ if (result == ISC_R_SUCCESS) {
+ for (i = 0; i < nframes; i++) {
+ unsigned long offset;
+
+ fname = NULL;
+ result = isc_backtrace_getsymbol(tracebuf[i], &fname,
+ &offset);
+ if (result == ISC_R_SUCCESS) {
+ fprintf(stderr, "#%d %p in %s()+0x%lx\n", i,
+ tracebuf[i], fname, offset);
+ } else {
+ fprintf(stderr, "#%d %p in ??\n", i,
+ tracebuf[i]);
+ }
+ }
+ }
fflush(stderr);
- abort();
- /* NOTREACHED */
}
diff --git a/contrib/bind9/lib/isc/backtrace-emptytbl.c b/contrib/bind9/lib/isc/backtrace-emptytbl.c
new file mode 100644
index 0000000..2743030
--- /dev/null
+++ b/contrib/bind9/lib/isc/backtrace-emptytbl.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 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: backtrace-emptytbl.c,v 1.3 2009-09-01 20:13:44 each Exp $ */
+
+/*! \file */
+
+/*
+ * This file defines an empty (default) symbol table used in backtrace.c
+ * If the application wants to have a complete symbol table, it should redefine
+ * isc__backtrace_symtable with the complete table in some way, and link the
+ * version of the library not including this definition
+ * (e.g. libisc-nosymbol.a).
+ */
+
+#include <config.h>
+
+#include <isc/backtrace.h>
+
+const int isc__backtrace_nsymbols = 0;
+const isc_backtrace_symmap_t isc__backtrace_symtable[] = { { NULL, "" } };
diff --git a/contrib/bind9/lib/isc/backtrace.c b/contrib/bind9/lib/isc/backtrace.c
new file mode 100644
index 0000000..7b5ddfe
--- /dev/null
+++ b/contrib/bind9/lib/isc/backtrace.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 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: backtrace.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_LIBCTRACE
+#include <execinfo.h>
+#endif
+
+#include <isc/backtrace.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_USEBACKTRACE
+/*
+ * Getting a back trace of a running process is tricky and highly platform
+ * dependent. Our current approach is as follows:
+ * 1. If the system library supports the "backtrace()" function, use it.
+ * 2. Otherwise, if the compiler is gcc and the architecture is x86_64 or IA64,
+ * then use gcc's (hidden) Unwind_Backtrace() function. Note that this
+ * function doesn't work for C programs on many other architectures.
+ * 3. Otherwise, if the architecture x86 or x86_64, try to unwind the stack
+ * frame following frame pointers. This assumes the executable binary
+ * compiled with frame pointers; this is not always true for x86_64 (rather,
+ * compiler optimizations often disable frame pointers). The validation
+ * checks in getnextframeptr() hopefully rejects bogus values stored in
+ * the RBP register in such a case. If the backtrace function itself crashes
+ * due to this problem, the whole package should be rebuilt with
+ * --disable-backtrace.
+ */
+#ifdef HAVE_LIBCTRACE
+#define BACKTRACE_LIBC
+#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__ia64__))
+#define BACKTRACE_GCC
+#elif defined(__x86_64__) || defined(__i386__)
+#define BACKTRACE_X86STACK
+#else
+#define BACKTRACE_DISABLED
+#endif /* HAVE_LIBCTRACE */
+#else /* !ISC_PLATFORM_USEBACKTRACE */
+#define BACKTRACE_DISABLED
+#endif /* ISC_PLATFORM_USEBACKTRACE */
+
+#ifdef BACKTRACE_LIBC
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+ int n;
+
+ /*
+ * Validate the arguments: intentionally avoid using REQUIRE().
+ * See notes in backtrace.h.
+ */
+ if (addrs == NULL || nframes == NULL)
+ return (ISC_R_FAILURE);
+
+ /*
+ * backtrace(3) includes this function itself in the address array,
+ * which should be eliminated from the returned sequence.
+ */
+ n = backtrace(addrs, maxaddrs);
+ if (n < 2)
+ return (ISC_R_NOTFOUND);
+ n--;
+ memmove(addrs, &addrs[1], sizeof(void *) * n);
+ *nframes = n;
+ return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_GCC)
+extern int _Unwind_Backtrace(void* fn, void* a);
+extern void* _Unwind_GetIP(void* ctx);
+
+typedef struct {
+ void **result;
+ int max_depth;
+ int skip_count;
+ int count;
+} trace_arg_t;
+
+static int
+btcallback(void *uc, void *opq) {
+ trace_arg_t *arg = (trace_arg_t *)opq;
+
+ if (arg->skip_count > 0)
+ arg->skip_count--;
+ else
+ arg->result[arg->count++] = (void *)_Unwind_GetIP(uc);
+ if (arg->count == arg->max_depth)
+ return (5); /* _URC_END_OF_STACK */
+
+ return (0); /* _URC_NO_REASON */
+}
+
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+ trace_arg_t arg;
+
+ /* Argument validation: see above. */
+ if (addrs == NULL || nframes == NULL)
+ return (ISC_R_FAILURE);
+
+ arg.skip_count = 1;
+ arg.result = addrs;
+ arg.max_depth = maxaddrs;
+ arg.count = 0;
+ _Unwind_Backtrace(btcallback, &arg);
+
+ *nframes = arg.count;
+
+ return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_X86STACK)
+#ifdef __x86_64__
+static unsigned long
+getrbp() {
+ __asm("movq %rbp, %rax\n");
+}
+#endif
+
+static void **
+getnextframeptr(void **sp) {
+ void **newsp = (void **)*sp;
+
+ /*
+ * Perform sanity check for the new frame pointer, derived from
+ * google glog. This can actually be bogus depending on compiler.
+ */
+
+ /* prohibit the stack frames from growing downwards */
+ if (newsp <= sp)
+ return (NULL);
+
+ /* A heuristics to reject "too large" frame: this actually happened. */
+ if ((char *)newsp - (char *)sp > 100000)
+ return (NULL);
+
+ /*
+ * Not sure if other checks used in glog are needed at this moment.
+ * For our purposes we don't have to consider non-contiguous frames,
+ * for example.
+ */
+
+ return (newsp);
+}
+
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+ int i = 0;
+ void **sp;
+
+ /* Argument validation: see above. */
+ if (addrs == NULL || nframes == NULL)
+ return (ISC_R_FAILURE);
+
+#ifdef __x86_64__
+ sp = (void **)getrbp();
+ if (sp == NULL)
+ return (ISC_R_NOTFOUND);
+ /*
+ * sp is the frame ptr of this function itself due to the call to
+ * getrbp(), so need to unwind one frame for consistency.
+ */
+ sp = getnextframeptr(sp);
+#else
+ /*
+ * i386: the frame pointer is stored 2 words below the address for the
+ * first argument. Note that the body of this function cannot be
+ * inlined since it depends on the address of the function argument.
+ */
+ sp = (void **)&addrs - 2;
+#endif
+
+ while (sp != NULL && i < maxaddrs) {
+ addrs[i++] = *(sp + 1);
+ sp = getnextframeptr(sp);
+ }
+
+ *nframes = i;
+
+ return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_DISABLED)
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+ /* Argument validation: see above. */
+ if (addrs == NULL || nframes == NULL)
+ return (ISC_R_FAILURE);
+
+ UNUSED(maxaddrs);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+#endif
+
+isc_result_t
+isc_backtrace_getsymbolfromindex(int index, const void **addrp,
+ const char **symbolp)
+{
+ REQUIRE(addrp != NULL && *addrp == NULL);
+ REQUIRE(symbolp != NULL && *symbolp == NULL);
+
+ if (index < 0 || index >= isc__backtrace_nsymbols)
+ return (ISC_R_RANGE);
+
+ *addrp = isc__backtrace_symtable[index].addr;
+ *symbolp = isc__backtrace_symtable[index].symbol;
+ return (ISC_R_SUCCESS);
+}
+
+static int
+symtbl_compare(const void *addr, const void *entryarg) {
+ const isc_backtrace_symmap_t *entry = entryarg;
+ const isc_backtrace_symmap_t *end =
+ &isc__backtrace_symtable[isc__backtrace_nsymbols - 1];
+
+ if (isc__backtrace_nsymbols == 1 || entry == end) {
+ if (addr >= entry->addr) {
+ /*
+ * If addr is equal to or larger than that of the last
+ * entry of the table, we cannot be sure if this is
+ * within a valid range so we consider it valid.
+ */
+ return (0);
+ }
+ return (-1);
+ }
+
+ /* entry + 1 is a valid entry from now on. */
+ if (addr < entry->addr)
+ return (-1);
+ else if (addr >= (entry + 1)->addr)
+ return (1);
+ return (0);
+}
+
+isc_result_t
+isc_backtrace_getsymbol(const void *addr, const char **symbolp,
+ unsigned long *offsetp)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_backtrace_symmap_t *found;
+
+ /*
+ * Validate the arguments: intentionally avoid using REQUIRE().
+ * See notes in backtrace.h.
+ */
+ if (symbolp == NULL || *symbolp != NULL || offsetp == NULL)
+ return (ISC_R_FAILURE);
+
+ if (isc__backtrace_nsymbols < 1)
+ return (ISC_R_NOTFOUND);
+
+ /*
+ * Search the table for the entry that meets:
+ * entry.addr <= addr < next_entry.addr.
+ */
+ found = bsearch(addr, isc__backtrace_symtable, isc__backtrace_nsymbols,
+ sizeof(isc__backtrace_symtable[0]), symtbl_compare);
+ if (found == NULL)
+ result = ISC_R_NOTFOUND;
+ else {
+ *symbolp = found->symbol;
+ *offsetp = (const char *)addr - (char *)found->addr;
+ }
+
+ return (result);
+}
diff --git a/contrib/bind9/lib/isc/base32.c b/contrib/bind9/lib/isc/base32.c
index 5e5cbd9..7621920 100644
--- a/contrib/bind9/lib/isc/base32.c
+++ b/contrib/bind9/lib/isc/base32.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: base32.c,v 1.3.116.3 2009-10-21 01:22:47 each Exp $ */
+/* $Id: base32.c,v 1.6 2009-10-21 01:22:29 each Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isc/base64.c b/contrib/bind9/lib/isc/base64.c
index 858525f..ee34c3c 100644
--- a/contrib/bind9/lib/isc/base64.c
+++ b/contrib/bind9/lib/isc/base64.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: base64.c,v 1.32.332.2 2009-10-21 23:47:20 tbox Exp $ */
+/* $Id: base64.c,v 1.34 2009-10-21 23:48:05 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isc/entropy.c b/contrib/bind9/lib/isc/entropy.c
index af8757f..8d273d2 100644
--- a/contrib/bind9/lib/isc/entropy.c
+++ b/contrib/bind9/lib/isc/entropy.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: entropy.c,v 1.18.332.4 2010-08-10 23:46:54 tbox Exp $ */
+/* $Id: entropy.c,v 1.22 2010-08-10 23:48:19 tbox Exp $ */
/*! \file
* \brief
diff --git a/contrib/bind9/lib/isc/hash.c b/contrib/bind9/lib/isc/hash.c
index 7c0fcea..44975e7 100644
--- a/contrib/bind9/lib/isc/hash.c
+++ b/contrib/bind9/lib/isc/hash.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hash.c,v 1.13.332.3 2009-05-07 23:47:12 tbox Exp $ */
+/* $Id: hash.c,v 1.16 2009-09-01 00:22:28 jinmei Exp $ */
/*! \file
* Some portion of this code was derived from universal hash function
@@ -194,8 +194,12 @@ isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy,
hctx->vectorlen = vlen;
hctx->rndvector = rv;
+#ifdef BIND9
if (entropy != NULL)
isc_entropy_attach(entropy, &hctx->entropy);
+#else
+ UNUSED(entropy);
+#endif
*hctxp = hctx;
return (ISC_R_SUCCESS);
@@ -236,18 +240,22 @@ isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) {
void
isc_hash_ctxinit(isc_hash_t *hctx) {
- isc_result_t result;
-
LOCK(&hctx->lock);
if (hctx->initialized == ISC_TRUE)
goto out;
if (hctx->entropy) {
+#ifdef BIND9
+ isc_result_t result;
+
result = isc_entropy_getdata(hctx->entropy,
hctx->rndvector, hctx->vectorlen,
NULL, 0);
INSIST(result == ISC_R_SUCCESS);
+#else
+ INSIST(0);
+#endif
} else {
isc_uint32_t pr;
unsigned int i, copylen;
@@ -293,6 +301,7 @@ static void
destroy(isc_hash_t **hctxp) {
isc_hash_t *hctx;
isc_mem_t *mctx;
+ unsigned char canary0[4], canary1[4];
REQUIRE(hctxp != NULL && *hctxp != NULL);
hctx = *hctxp;
@@ -303,8 +312,10 @@ destroy(isc_hash_t **hctxp) {
isc_refcount_destroy(&hctx->refcnt);
mctx = hctx->mctx;
+#ifdef BIND9
if (hctx->entropy != NULL)
isc_entropy_detach(&hctx->entropy);
+#endif
if (hctx->rndvector != NULL)
isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen);
@@ -312,7 +323,10 @@ destroy(isc_hash_t **hctxp) {
DESTROYLOCK(&hctx->lock);
+ memcpy(canary0, hctx + 1, sizeof(canary0));
memset(hctx, 0, sizeof(isc_hash_t));
+ memcpy(canary1, hctx + 1, sizeof(canary1));
+ INSIST(memcmp(canary0, canary1, sizeof(canary0)) == 0);
isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
isc_mem_detach(&mctx);
}
diff --git a/contrib/bind9/lib/isc/heap.c b/contrib/bind9/lib/isc/heap.c
index 68f8ba8..4dead3f 100644
--- a/contrib/bind9/lib/isc/heap.c
+++ b/contrib/bind9/lib/isc/heap.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: heap.c,v 1.37.240.3 2010-02-04 23:47:46 tbox Exp $ */
+/* $Id: heap.c,v 1.39 2010-02-04 23:49:13 tbox Exp $ */
/*! \file
* Heap implementation of priority queues adapted from the following:
diff --git a/contrib/bind9/lib/isc/hmacmd5.c b/contrib/bind9/lib/isc/hmacmd5.c
index b1d5906..10e87c9 100644
--- a/contrib/bind9/lib/isc/hmacmd5.c
+++ b/contrib/bind9/lib/isc/hmacmd5.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hmacmd5.c,v 1.14 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: hmacmd5.c,v 1.16 2009-02-06 23:47:42 tbox Exp $ */
/*! \file
* This code implements the HMAC-MD5 keyed hash algorithm
@@ -27,10 +27,40 @@
#include <isc/assertions.h>
#include <isc/hmacmd5.h>
#include <isc/md5.h>
+#include <isc/platform.h>
#include <isc/string.h>
#include <isc/types.h>
#include <isc/util.h>
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5());
+}
+
+void
+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
+ HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
+ HMAC_Final(ctx, digest, NULL);
+ HMAC_CTX_cleanup(ctx);
+}
+
+#else
+
#define PADLEN 64
#define IPAD 0x36
#define OPAD 0x5C
@@ -98,6 +128,7 @@ isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
isc_md5_final(&ctx->md5ctx, digest);
isc_hmacmd5_invalidate(ctx);
}
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
/*!
* Verify signature - finalize MD5 operation and reapply MD5, then
diff --git a/contrib/bind9/lib/isc/hmacsha.c b/contrib/bind9/lib/isc/hmacsha.c
index 9f27163..125672d 100644
--- a/contrib/bind9/lib/isc/hmacsha.c
+++ b/contrib/bind9/lib/isc/hmacsha.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-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
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hmacsha.c,v 1.8 2007-08-27 03:27:53 marka Exp $ */
+/* $Id: hmacsha.c,v 1.10 2009-02-06 23:47:42 tbox Exp $ */
/*
* This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384
@@ -26,12 +26,172 @@
#include <isc/assertions.h>
#include <isc/hmacsha.h>
+#include <isc/platform.h>
#include <isc/sha1.h>
#include <isc/sha2.h>
#include <isc/string.h>
#include <isc/types.h>
#include <isc/util.h>
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha1());
+}
+
+void
+isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
+ HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
+
+ HMAC_Final(ctx, newdigest, NULL);
+ HMAC_CTX_cleanup(ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha224());
+}
+
+void
+isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
+ HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
+
+ HMAC_Final(ctx, newdigest, NULL);
+ HMAC_CTX_cleanup(ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha256());
+}
+
+void
+isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
+ HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
+
+ HMAC_Final(ctx, newdigest, NULL);
+ HMAC_CTX_cleanup(ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha384());
+}
+
+void
+isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
+ HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
+
+ HMAC_Final(ctx, newdigest, NULL);
+ HMAC_CTX_cleanup(ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha512());
+}
+
+void
+isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
+ HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
+
+ HMAC_Final(ctx, newdigest, NULL);
+ HMAC_CTX_cleanup(ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+#else
+
#define IPAD 0x36
#define OPAD 0x5C
@@ -105,19 +265,6 @@ isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
}
/*
- * Verify signature - finalize SHA1 operation and reapply SHA1, then
- * compare to the supplied digest.
- */
-isc_boolean_t
-isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
- unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
-
- REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
- isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
- return (ISC_TF(memcmp(digest, newdigest, len) == 0));
-}
-
-/*
* Start HMAC-SHA224 process. Initialize an sha224 context and digest the key.
*/
void
@@ -185,19 +332,6 @@ isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
}
/*
- * Verify signature - finalize SHA224 operation and reapply SHA224, then
- * compare to the supplied digest.
- */
-isc_boolean_t
-isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
- unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
-
- REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
- isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
- return (ISC_TF(memcmp(digest, newdigest, len) == 0));
-}
-
-/*
* Start HMAC-SHA256 process. Initialize an sha256 context and digest the key.
*/
void
@@ -265,19 +399,6 @@ isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
}
/*
- * Verify signature - finalize SHA256 operation and reapply SHA256, then
- * compare to the supplied digest.
- */
-isc_boolean_t
-isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
- unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
-
- REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
- isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
- return (ISC_TF(memcmp(digest, newdigest, len) == 0));
-}
-
-/*
* Start HMAC-SHA384 process. Initialize an sha384 context and digest the key.
*/
void
@@ -345,19 +466,6 @@ isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
}
/*
- * Verify signature - finalize SHA384 operation and reapply SHA384, then
- * compare to the supplied digest.
- */
-isc_boolean_t
-isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
- unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
-
- REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
- isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
- return (ISC_TF(memcmp(digest, newdigest, len) == 0));
-}
-
-/*
* Start HMAC-SHA512 process. Initialize an sha512 context and digest the key.
*/
void
@@ -423,6 +531,59 @@ isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
memcpy(digest, newdigest, len);
memset(newdigest, 0, sizeof(newdigest));
}
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
+
+/*
+ * Verify signature - finalize SHA1 operation and reapply SHA1, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
+ isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
+ return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA224 operation and reapply SHA224, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
+ isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
+ return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA256 operation and reapply SHA256, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
+ isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
+ return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA384 operation and reapply SHA384, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
+ isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
+ return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
/*
* Verify signature - finalize SHA512 operation and reapply SHA512, then
diff --git a/contrib/bind9/lib/isc/httpd.c b/contrib/bind9/lib/isc/httpd.c
index b653f79..81f118e 100644
--- a/contrib/bind9/lib/isc/httpd.c
+++ b/contrib/bind9/lib/isc/httpd.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: httpd.c,v 1.16.64.2 2010-02-04 23:47:46 tbox Exp $ */
+/* $Id: httpd.c,v 1.20 2010-11-16 05:38:31 marka Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isc/ia64/include/isc/atomic.h b/contrib/bind9/lib/isc/ia64/include/isc/atomic.h
index b2d355e..fffb0e3 100644
--- a/contrib/bind9/lib/isc/ia64/include/isc/atomic.h
+++ b/contrib/bind9/lib/isc/ia64/include/isc/atomic.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: atomic.h,v 1.4.326.3 2009-06-24 02:21:28 marka Exp $ */
+/* $Id: atomic.h,v 1.7 2009-06-24 02:22:50 marka Exp $ */
#ifndef ISC_ATOMIC_H
#define ISC_ATOMIC_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/Makefile.in b/contrib/bind9/lib/isc/include/isc/Makefile.in
index c1d71f4..12c09cd 100644
--- a/contrib/bind9/lib/isc/include/isc/Makefile.in
+++ b/contrib/bind9/lib/isc/include/isc/Makefile.in
@@ -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.64.12.2 2009-02-12 23:47:22 tbox Exp $
+# $Id: Makefile.in,v 1.68 2009-12-05 23:31:41 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -26,15 +26,15 @@ top_srcdir = @top_srcdir@
# machine generated. The latter are handled specially in the
# install target below.
#
-HEADERS = app.h assertions.h base64.h bitstring.h boolean.h buffer.h \
- bufferlist.h commandline.h entropy.h error.h event.h \
+HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \
+ buffer.h bufferlist.h commandline.h entropy.h error.h event.h \
eventclass.h file.h formatcheck.h fsaccess.h \
hash.h heap.h hex.h hmacmd5.h \
httpd.h \
interfaceiter.h @ISC_IPV6_H@ iterated_hash.h lang.h lex.h \
lfsr.h lib.h list.h log.h \
- magic.h md5.h mem.h msgcat.h msgs.h \
- mutexblock.h netaddr.h ondestroy.h os.h parseint.h \
+ magic.h md5.h mem.h msgcat.h msgs.h mutexblock.h \
+ namespace.h netaddr.h ondestroy.h os.h parseint.h \
print.h quota.h radix.h random.h ratelimiter.h \
refcount.h region.h resource.h \
result.h resultclass.h rwlock.h serial.h sha1.h sha2.h \
diff --git a/contrib/bind9/lib/isc/include/isc/app.h b/contrib/bind9/lib/isc/include/isc/app.h
index 0552758..ac8669f 100644
--- a/contrib/bind9/lib/isc/include/isc/app.h
+++ b/contrib/bind9/lib/isc/include/isc/app.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: app.h,v 1.8 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: app.h,v 1.11 2009-09-02 23:48:03 tbox Exp $ */
#ifndef ISC_APP_H
#define ISC_APP_H 1
@@ -54,12 +54,23 @@
* Use of this module is not required. In particular, isc_app_start() is
* NOT an ISC library initialization routine.
*
+ * This module also supports per-thread 'application contexts'. With this
+ * mode, a thread-based application will have a separate context, in which
+ * it uses other ISC library services such as tasks or timers. Signals are
+ * not caught in this mode, so that the application can handle the signals
+ * in its preferred way.
+ *
* \li MP:
* Clients must ensure that isc_app_start(), isc_app_run(), and
* isc_app_finish() are called at most once. isc_app_shutdown()
* is safe to use by any thread (provided isc_app_start() has been
* called previously).
*
+ * The same note applies to isc_app_ctxXXX() functions, but in this case
+ * it's a per-thread restriction. For example, a thread with an
+ * application context must ensure that isc_app_ctxstart() with the
+ * context is called at most once.
+ *
* \li Reliability:
* No anticipated impact.
*
@@ -75,17 +86,64 @@
#include <isc/eventclass.h>
#include <isc/lang.h>
+#include <isc/magic.h>
#include <isc/result.h>
+/***
+ *** Types
+ ***/
+
typedef isc_event_t isc_appevent_t;
#define ISC_APPEVENT_FIRSTEVENT (ISC_EVENTCLASS_APP + 0)
#define ISC_APPEVENT_SHUTDOWN (ISC_EVENTCLASS_APP + 1)
#define ISC_APPEVENT_LASTEVENT (ISC_EVENTCLASS_APP + 65535)
+/*%
+ * app module methods. Only app driver implementations use this structure.
+ * Other clients should use the top-level interfaces (i.e., isc_app_xxx
+ * functions). magic must be ISCAPI_APPMETHODS_MAGIC.
+ */
+typedef struct isc_appmethods {
+ void (*ctxdestroy)(isc_appctx_t **ctxp);
+ isc_result_t (*ctxstart)(isc_appctx_t *ctx);
+ isc_result_t (*ctxrun)(isc_appctx_t *ctx);
+ isc_result_t (*ctxsuspend)(isc_appctx_t *ctx);
+ isc_result_t (*ctxshutdown)(isc_appctx_t *ctx);
+ void (*ctxfinish)(isc_appctx_t *ctx);
+ void (*settaskmgr)(isc_appctx_t *ctx,
+ isc_taskmgr_t *timermgr);
+ void (*setsocketmgr)(isc_appctx_t *ctx,
+ isc_socketmgr_t *timermgr);
+ void (*settimermgr)(isc_appctx_t *ctx,
+ isc_timermgr_t *timermgr);
+} isc_appmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of an application context
+ * implementation's version of an isc_appctx_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden. app implementations
+ * may change the structure. 'magic' must be ISCAPI_APPCTX_MAGIC for any
+ * of the isc_app_ routines to work. app implementations must maintain
+ * all app context invariants.
+ */
+struct isc_appctx {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_appmethods_t *methods;
+};
+
+#define ISCAPI_APPCTX_MAGIC ISC_MAGIC('A','a','p','c')
+#define ISCAPI_APPCTX_VALID(c) ((c) != NULL && \
+ (c)->magic == ISCAPI_APPCTX_MAGIC)
+
ISC_LANG_BEGINDECLS
isc_result_t
+isc_app_ctxstart(isc_appctx_t *ctx);
+
+isc_result_t
isc_app_start(void);
/*!<
* \brief Start an ISC library application.
@@ -93,6 +151,9 @@ isc_app_start(void);
* Notes:
* This call should be made before any other ISC library call, and as
* close to the beginning of the application as possible.
+ *
+ * Requires:
+ * 'ctx' is a valid application context (for app_ctxstart()).
*/
isc_result_t
@@ -102,7 +163,7 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
* \brief Request delivery of an event when the application is run.
*
* Requires:
- * isc_app_start() has been called.
+ *\li isc_app_start() has been called.
*
* Returns:
* ISC_R_SUCCESS
@@ -110,6 +171,9 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
*/
isc_result_t
+isc_app_ctxrun(isc_appctx_t *ctx);
+
+isc_result_t
isc_app_run(void);
/*!<
* \brief Run an ISC library application.
@@ -120,11 +184,12 @@ isc_app_run(void);
* caller should start shutting down the application.
*
* Requires:
- *\li isc_app_start() has been called.
+ *\li isc_app_[ctx]start() has been called.
*
* Ensures:
*\li Any events requested via isc_app_onrun() will have been posted (in
* FIFO order) before isc_app_run() blocks.
+ *\li 'ctx' is a valid application context (for app_ctxrun()).
*
* Returns:
*\li ISC_R_SUCCESS Shutdown has been requested.
@@ -132,6 +197,9 @@ isc_app_run(void);
*/
isc_result_t
+isc_app_ctxshutdown(isc_appctx_t *ctx);
+
+isc_result_t
isc_app_shutdown(void);
/*!<
* \brief Request application shutdown.
@@ -141,7 +209,8 @@ isc_app_shutdown(void);
* only be triggered once.
*
* Requires:
- *\li isc_app_run() has been called.
+ *\li isc_app_[ctx]run() has been called.
+ *\li 'ctx' is a valid application context (for app_ctxshutdown()).
*
* Returns:
*\li ISC_R_SUCCESS
@@ -149,6 +218,12 @@ isc_app_shutdown(void);
*/
isc_result_t
+isc_app_ctxsuspend(isc_appctx_t *ctx);
+/*!<
+ * \brief This has the same behavior as isc_app_ctxsuspend().
+ */
+
+isc_result_t
isc_app_reload(void);
/*!<
* \brief Request application reload.
@@ -162,6 +237,9 @@ isc_app_reload(void);
*/
void
+isc_app_ctxfinish(isc_appctx_t *ctx);
+
+void
isc_app_finish(void);
/*!<
* \brief Finish an ISC library application.
@@ -171,6 +249,7 @@ isc_app_finish(void);
*
* Requires:
*\li isc_app_start() has been called.
+ *\li 'ctx' is a valid application context (for app_ctxfinish()).
*
* Ensures:
*\li Any resources allocated by isc_app_start() have been released.
@@ -206,6 +285,90 @@ isc_app_unblock(void);
* \li isc_app_block() has been called by the same thread.
*/
+isc_result_t
+isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp);
+/*!<
+ * \brief Create an application context.
+ *
+ * Requires:
+ *\li 'mctx' is a valid memory context.
+ *\li 'ctxp' != NULL && *ctxp == NULL.
+ */
+
+void
+isc_appctx_destroy(isc_appctx_t **ctxp);
+/*!<
+ * \brief Destroy an application context.
+ *
+ * Requires:
+ *\li '*ctxp' is a valid application context.
+ *
+ * Ensures:
+ *\li *ctxp == NULL.
+ */
+
+void
+isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr);
+/*!<
+ * \brief Associate a task manager with an application context.
+ *
+ * This must be done before running tasks within the application context.
+ *
+ * Requires:
+ *\li 'ctx' is a valid application context.
+ *\li 'taskmgr' is a valid task manager.
+ */
+
+void
+isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr);
+/*!<
+ * \brief Associate a socket manager with an application context.
+ *
+ * This must be done before handling socket events within the application
+ * context.
+ *
+ * Requires:
+ *\li 'ctx' is a valid application context.
+ *\li 'socketmgr' is a valid socket manager.
+ */
+
+void
+isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr);
+/*!<
+ * \brief Associate a socket timer with an application context.
+ *
+ * This must be done before handling timer events within the application
+ * context.
+ *
+ * Requires:
+ *\li 'ctx' is a valid application context.
+ *\li 'timermgr' is a valid timer manager.
+ */
+
+#ifdef USE_APPIMPREGISTER
+/*%<
+ * See isc_appctx_create() above.
+ */
+typedef isc_result_t
+(*isc_appctxcreatefunc_t)(isc_mem_t *mctx, isc_appctx_t **ctxp);
+
+isc_result_t
+isc_app_register(isc_appctxcreatefunc_t createfunc);
+/*%<
+ * Register a new application implementation and add it to the list of
+ * supported implementations. This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__app_register(void);
+/*%<
+ * A short cut function that specifies the application module in the ISC
+ * library for isc_app_register(). An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_APPIMPREGISTER */
ISC_LANG_ENDDECLS
diff --git a/contrib/bind9/lib/isc/include/isc/assertions.h b/contrib/bind9/lib/isc/include/isc/assertions.h
index 8a2ba7e..91217b8 100644
--- a/contrib/bind9/lib/isc/include/isc/assertions.h
+++ b/contrib/bind9/lib/isc/include/isc/assertions.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +16,7 @@
*/
/*
- * $Id: assertions.h,v 1.26 2008-10-15 23:47:31 tbox Exp $
+ * $Id: assertions.h,v 1.28 2009-09-29 23:48:04 tbox Exp $
*/
/*! \file isc/assertions.h
*/
@@ -41,7 +41,9 @@ typedef void (*isc_assertioncallback_t)(const char *, int, isc_assertiontype_t,
const char *);
/* coverity[+kill] */
-LIBISC_EXTERNAL_DATA extern isc_assertioncallback_t isc_assertion_failed;
+ISC_PLATFORM_NORETURN_PRE
+void isc_assertion_failed(const char *, int, isc_assertiontype_t,
+ const char *) ISC_PLATFORM_NORETURN_POST;
void
isc_assertion_setcallback(isc_assertioncallback_t);
diff --git a/contrib/bind9/lib/isc/include/isc/backtrace.h b/contrib/bind9/lib/isc/include/isc/backtrace.h
new file mode 100644
index 0000000..94fee61
--- /dev/null
+++ b/contrib/bind9/lib/isc/include/isc/backtrace.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 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: backtrace.h,v 1.2 2009-09-01 18:40:25 jinmei Exp $ */
+
+/*! \file isc/backtrace.h
+ * \brief provide a back trace of the running process to help debug problems.
+ *
+ * This module tries to get a back trace of the process using some platform
+ * dependent way when available. It also manages an internal symbol table
+ * that maps function addresses used in the process to their textual symbols.
+ * This module is expected to be used to help debug when some fatal error
+ * happens.
+ *
+ * IMPORTANT NOTE: since the (major) intended use case of this module is
+ * dumping a back trace on a fatal error, normally followed by self termination,
+ * functions defined in this module generally doesn't employ assertion checks
+ * (if it did, a program bug could cause infinite recursive calls to a
+ * backtrace function). These functions still perform minimal checks and return
+ * ISC_R_FAILURE if they detect an error, but the caller should therefore be
+ * very careful about the use of these functions, and generally discouraged to
+ * use them except in an exit path. The exception is
+ * isc_backtrace_getsymbolfromindex(), which is expected to be used in a
+ * non-error-handling context and validates arguments with assertion checks.
+ */
+
+#ifndef ISC_BACKTRACE_H
+#define ISC_BACKTRACE_H 1
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/types.h>
+
+/***
+ *** Types
+ ***/
+struct isc_backtrace_symmap {
+ void *addr;
+ const char *symbol;
+};
+
+extern const int isc__backtrace_nsymbols;
+extern const isc_backtrace_symmap_t isc__backtrace_symtable[];
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes);
+/*%<
+ * Get a back trace of the running process above this function itself. On
+ * success, addrs[i] will store the address of the call point of the i-th
+ * stack frame (addrs[0] is the caller of this function). *nframes will store
+ * the total number of frames.
+ *
+ * Requires (note that these are not ensured by assertion checks, see above):
+ *
+ *\li 'addrs' is a valid array containing at least 'maxaddrs' void * entries.
+ *
+ *\li 'nframes' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_FAILURE
+ *\li #ISC_R_NOTFOUND
+ *\li #ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_backtrace_getsymbolfromindex(int index, const void **addrp,
+ const char **symbolp);
+/*%<
+ * Returns the content of the internal symbol table of the given index.
+ * On success, *addrsp and *symbolp point to the address and the symbol of
+ * the 'index'th entry of the table, respectively. If 'index' is not in the
+ * range of the symbol table, ISC_R_RANGE will be returned.
+ *
+ * Requires
+ *
+ *\li 'addrp' must be non NULL && '*addrp' == NULL.
+ *
+ *\li 'symbolp' must be non NULL && '*symbolp' == NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_RANGE
+ */
+
+isc_result_t
+isc_backtrace_getsymbol(const void *addr, const char **symbolp,
+ unsigned long *offsetp);
+/*%<
+ * Searches the internal symbol table for the symbol that most matches the
+ * given 'addr'. On success, '*symbolp' will point to the name of function
+ * to which the address 'addr' belong, and '*offsetp' will store the offset
+ * from the function's entry address to 'addr'.
+ *
+ * Requires (note that these are not ensured by assertion checks, see above):
+ *
+ *\li 'symbolp' must be non NULL && '*symbolp' == NULL.
+ *
+ *\li 'offsetp' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_FAILURE
+ *\li #ISC_R_NOTFOUND
+ */
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BACKTRACE_H */
diff --git a/contrib/bind9/lib/isc/include/isc/bind9.h b/contrib/bind9/lib/isc/include/isc/bind9.h
new file mode 100644
index 0000000..dd75e91
--- /dev/null
+++ b/contrib/bind9/lib/isc/include/isc/bind9.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 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: bind9.h,v 1.2 2009-12-05 23:31:41 each Exp $ */
+
+#ifndef ISC_BIND9_H
+#define ISC_BIND9_H 1
+
+/*
+ * This determines whether we are building BIND9 or using the exported
+ * libisc/libdns libraries. The version of this file included in the
+ * standard BIND9 build defines BIND9; the version included with the
+ * exportable libraries does not.
+ */
+#define BIND9 1
+
+#endif /* ISC_BIND9_H */
diff --git a/contrib/bind9/lib/isc/include/isc/buffer.h b/contrib/bind9/lib/isc/include/isc/buffer.h
index e55c5b0..30a6e39 100644
--- a/contrib/bind9/lib/isc/include/isc/buffer.h
+++ b/contrib/bind9/lib/isc/include/isc/buffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2010 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: buffer.h,v 1.53 2008-09-25 04:02:39 tbox Exp $ */
+/* $Id: buffer.h,v 1.55 2010-12-20 23:47:21 tbox Exp $ */
#ifndef ISC_BUFFER_H
#define ISC_BUFFER_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/entropy.h b/contrib/bind9/lib/isc/include/isc/entropy.h
index 1eb8fd1..e115906 100644
--- a/contrib/bind9/lib/isc/include/isc/entropy.h
+++ b/contrib/bind9/lib/isc/include/isc/entropy.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: entropy.h,v 1.32.332.3 2009-10-19 02:46:07 marka Exp $ */
+/* $Id: entropy.h,v 1.35 2009-10-19 02:37:08 marka Exp $ */
#ifndef ISC_ENTROPY_H
#define ISC_ENTROPY_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/error.h b/contrib/bind9/lib/isc/include/isc/error.h
index a0025e0..d3dcc8b 100644
--- a/contrib/bind9/lib/isc/include/isc/error.h
+++ b/contrib/bind9/lib/isc/include/isc/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: error.h,v 1.20 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: error.h,v 1.22 2009-09-29 23:48:04 tbox Exp $ */
#ifndef ISC_ERROR_H
#define ISC_ERROR_H 1
@@ -26,6 +26,7 @@
#include <isc/formatcheck.h>
#include <isc/lang.h>
+#include <isc/platform.h>
ISC_LANG_BEGINDECLS
@@ -45,9 +46,9 @@ isc_error_unexpected(const char *, int, const char *, ...)
ISC_FORMAT_PRINTF(3, 4);
/*% fatal error */
-void
+ISC_PLATFORM_NORETURN_PRE void
isc_error_fatal(const char *, int, const char *, ...)
- ISC_FORMAT_PRINTF(3, 4);
+ISC_FORMAT_PRINTF(3, 4) ISC_PLATFORM_NORETURN_POST;
/*% runtimecheck error */
void
diff --git a/contrib/bind9/lib/isc/include/isc/file.h b/contrib/bind9/lib/isc/include/isc/file.h
index 6629a3e..be40825 100644
--- a/contrib/bind9/lib/isc/include/isc/file.h
+++ b/contrib/bind9/lib/isc/include/isc/file.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: file.h,v 1.33.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: file.h,v 1.39 2011-01-11 23:47:14 tbox Exp $ */
#ifndef ISC_FILE_H
#define ISC_FILE_H 1
@@ -100,6 +100,10 @@ isc_file_mktemplate(const char *path, char *buf, size_t buflen);
isc_result_t
isc_file_openunique(char *templet, FILE **fp);
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp);
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp);
/*!<
* \brief Create and open a file with a unique name based on 'templet'.
*
@@ -251,6 +255,29 @@ isc_file_truncate(const char *filename, isc_offset_t size);
* Truncate/extend the file specified to 'size' bytes.
*/
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp);
+/*%<
+ * Open 'filename' for writing, truncating if necessary. Ensure that
+ * if it existed it was a normal file. If creating the file, ensure
+ * that only the owner can read/write it.
+ */
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, char *path,
+ char **dirname, char **basename);
+/*%<
+ * Split a path into dirname and basename. If 'path' contains no slash
+ * (or, on windows, backslash), then '*dirname' is set to ".".
+ *
+ * Allocates memory for '*dirname', which can be freed with isc_mem_free().
+ *
+ * Returns:
+ * - ISC_R_SUCCESS on success
+ * - ISC_R_INVALIDFILE if 'path' is empty or ends with '/'
+ * - ISC_R_NOMEMORY if unable to allocate memory
+ */
+
ISC_LANG_ENDDECLS
#endif /* ISC_FILE_H */
diff --git a/contrib/bind9/lib/isc/include/isc/fsaccess.h b/contrib/bind9/lib/isc/include/isc/fsaccess.h
index 88469dd..9758242 100644
--- a/contrib/bind9/lib/isc/include/isc/fsaccess.h
+++ b/contrib/bind9/lib/isc/include/isc/fsaccess.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: fsaccess.h,v 1.14.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: fsaccess.h,v 1.16 2009-01-17 23:47:43 tbox Exp $ */
#ifndef ISC_FSACCESS_H
#define ISC_FSACCESS_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/hash.h b/contrib/bind9/lib/isc/include/isc/hash.h
index 9bfb709..543e5fd 100644
--- a/contrib/bind9/lib/isc/include/isc/hash.h
+++ b/contrib/bind9/lib/isc/include/isc/hash.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hash.h,v 1.10.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: hash.h,v 1.12 2009-01-17 23:47:43 tbox Exp $ */
#ifndef ISC_HASH_H
#define ISC_HASH_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/heap.h b/contrib/bind9/lib/isc/include/isc/heap.h
index ae346c1..943ace3 100644
--- a/contrib/bind9/lib/isc/include/isc/heap.h
+++ b/contrib/bind9/lib/isc/include/isc/heap.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: heap.h,v 1.24.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: heap.h,v 1.26 2009-01-17 23:47:43 tbox Exp $ */
#ifndef ISC_HEAP_H
#define ISC_HEAP_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/hmacmd5.h b/contrib/bind9/lib/isc/include/isc/hmacmd5.h
index 68074ae..c7d7fff 100644
--- a/contrib/bind9/lib/isc/include/isc/hmacmd5.h
+++ b/contrib/bind9/lib/isc/include/isc/hmacmd5.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hmacmd5.h,v 1.12 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: hmacmd5.h,v 1.14 2009-02-06 23:47:42 tbox Exp $ */
/*! \file isc/hmacmd5.h
* \brief This is the header file for the HMAC-MD5 keyed hash algorithm
@@ -27,14 +27,23 @@
#include <isc/lang.h>
#include <isc/md5.h>
+#include <isc/platform.h>
#include <isc/types.h>
#define ISC_HMACMD5_KEYLENGTH 64
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/hmac.h>
+
+typedef HMAC_CTX isc_hmacmd5_t;
+
+#else
+
typedef struct {
isc_md5_t md5ctx;
unsigned char key[ISC_HMACMD5_KEYLENGTH];
} isc_hmacmd5_t;
+#endif
ISC_LANG_BEGINDECLS
diff --git a/contrib/bind9/lib/isc/include/isc/hmacsha.h b/contrib/bind9/lib/isc/include/isc/hmacsha.h
index c439883..286cafc 100644
--- a/contrib/bind9/lib/isc/include/isc/hmacsha.h
+++ b/contrib/bind9/lib/isc/include/isc/hmacsha.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-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
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hmacsha.h,v 1.7 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: hmacsha.h,v 1.9 2009-02-06 23:47:42 tbox Exp $ */
/*! \file isc/hmacsha.h
* This is the header file for the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256,
@@ -25,6 +25,7 @@
#define ISC_HMACSHA_H 1
#include <isc/lang.h>
+#include <isc/platform.h>
#include <isc/sha1.h>
#include <isc/sha2.h>
#include <isc/types.h>
@@ -35,6 +36,17 @@
#define ISC_HMACSHA384_KEYLENGTH ISC_SHA384_BLOCK_LENGTH
#define ISC_HMACSHA512_KEYLENGTH ISC_SHA512_BLOCK_LENGTH
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/hmac.h>
+
+typedef HMAC_CTX isc_hmacsha1_t;
+typedef HMAC_CTX isc_hmacsha224_t;
+typedef HMAC_CTX isc_hmacsha256_t;
+typedef HMAC_CTX isc_hmacsha384_t;
+typedef HMAC_CTX isc_hmacsha512_t;
+
+#else
+
typedef struct {
isc_sha1_t sha1ctx;
unsigned char key[ISC_HMACSHA1_KEYLENGTH];
@@ -59,6 +71,7 @@ typedef struct {
isc_sha512_t sha512ctx;
unsigned char key[ISC_HMACSHA512_KEYLENGTH];
} isc_hmacsha512_t;
+#endif
ISC_LANG_BEGINDECLS
diff --git a/contrib/bind9/lib/isc/include/isc/lib.h b/contrib/bind9/lib/isc/include/isc/lib.h
index 3804a07..c8bdbc6 100644
--- a/contrib/bind9/lib/isc/include/isc/lib.h
+++ b/contrib/bind9/lib/isc/include/isc/lib.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lib.h,v 1.14 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: lib.h,v 1.16 2009-09-02 23:48:03 tbox Exp $ */
#ifndef ISC_LIB_H
#define ISC_LIB_H 1
@@ -36,6 +36,15 @@ isc_lib_initmsgcat(void);
* has not already been initialized.
*/
+void
+isc_lib_register(void);
+/*!<
+ * \brief Register the ISC library implementations for some base services
+ * such as memory or event management and handling socket or timer events.
+ * An external application that wants to use the ISC library must call this
+ * function very early in main().
+ */
+
ISC_LANG_ENDDECLS
#endif /* ISC_LIB_H */
diff --git a/contrib/bind9/lib/isc/include/isc/log.h b/contrib/bind9/lib/isc/include/isc/log.h
index fec3d9d..eac5755 100644
--- a/contrib/bind9/lib/isc/include/isc/log.h
+++ b/contrib/bind9/lib/isc/include/isc/log.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.h,v 1.54.332.5 2009-02-16 02:04:05 marka Exp $ */
+/* $Id: log.h,v 1.59 2009-02-16 02:01:16 marka Exp $ */
#ifndef ISC_LOG_H
#define ISC_LOG_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/md5.h b/contrib/bind9/lib/isc/include/isc/md5.h
index 9d5b1ec..9017115 100644
--- a/contrib/bind9/lib/isc/include/isc/md5.h
+++ b/contrib/bind9/lib/isc/include/isc/md5.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: md5.h,v 1.16 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: md5.h,v 1.20 2010-01-07 23:48:54 tbox Exp $ */
/*! \file isc/md5.h
* \brief This is the header file for the MD5 message-digest algorithm.
@@ -44,15 +44,25 @@
#define ISC_MD5_H 1
#include <isc/lang.h>
+#include <isc/platform.h>
#include <isc/types.h>
#define ISC_MD5_DIGESTLENGTH 16U
+#define ISC_MD5_BLOCK_LENGTH 64U
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
+
+typedef EVP_MD_CTX isc_md5_t;
+
+#else
typedef struct {
isc_uint32_t buf[4];
isc_uint32_t bytes[2];
isc_uint32_t in[16];
} isc_md5_t;
+#endif
ISC_LANG_BEGINDECLS
diff --git a/contrib/bind9/lib/isc/include/isc/mem.h b/contrib/bind9/lib/isc/include/isc/mem.h
index d13d912..e0a7fe5 100644
--- a/contrib/bind9/lib/isc/include/isc/mem.h
+++ b/contrib/bind9/lib/isc/include/isc/mem.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mem.h,v 1.78.120.6 2010-08-11 23:04:21 jinmei Exp $ */
+/* $Id: mem.h,v 1.89 2010-08-11 22:54:58 jinmei Exp $ */
#ifndef ISC_MEM_H
#define ISC_MEM_H 1
@@ -152,11 +152,29 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
#endif
-#define isc_mem_get(c, s) isc__mem_get((c), (s) _ISC_MEM_FILELINE)
-#define isc_mem_allocate(c, s) isc__mem_allocate((c), (s) _ISC_MEM_FILELINE)
-#define isc_mem_reallocate(c, p, s) isc__mem_reallocate((c), (p), (s) _ISC_MEM_FILELINE)
-#define isc_mem_strdup(c, p) isc__mem_strdup((c), (p) _ISC_MEM_FILELINE)
-#define isc_mempool_get(c) isc__mempool_get((c) _ISC_MEM_FILELINE)
+/*%<
+ * We use either isc___mem (three underscores) or isc__mem (two) depending on
+ * whether it's for BIND9's internal purpose (with -DBIND9) or generic export
+ * library. This condition is generally handled in isc/namespace.h, but for
+ * Windows it doesn't work if it involves multiple times of macro expansion
+ * (such as isc_mem to isc__mem then to isc___mem). The following definitions
+ * are used to work around this portability issue. Right now, we don't support
+ * the export library for Windows, so we always use the three-underscore
+ * version.
+ */
+#ifdef WIN32
+#define ISCMEMFUNC(sfx) isc___mem_ ## sfx
+#define ISCMEMPOOLFUNC(sfx) isc___mempool_ ## sfx
+#else
+#define ISCMEMFUNC(sfx) isc__mem_ ## sfx
+#define ISCMEMPOOLFUNC(sfx) isc__mempool_ ## sfx
+#endif
+
+#define isc_mem_get(c, s) ISCMEMFUNC(get)((c), (s) _ISC_MEM_FILELINE)
+#define isc_mem_allocate(c, s) ISCMEMFUNC(allocate)((c), (s) _ISC_MEM_FILELINE)
+#define isc_mem_reallocate(c, p, s) ISCMEMFUNC(reallocate)((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_strdup(c, p) ISCMEMFUNC(strdup)((c), (p) _ISC_MEM_FILELINE)
+#define isc_mempool_get(c) ISCMEMPOOLFUNC(get)((c) _ISC_MEM_FILELINE)
/*%
* isc_mem_putanddetach() is a convenience function for use where you
@@ -187,33 +205,102 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
* \endcode
*/
+/*% memory and memory pool methods */
+typedef struct isc_memmethods {
+ void (*attach)(isc_mem_t *source, isc_mem_t **targetp);
+ void (*detach)(isc_mem_t **mctxp);
+ void (*destroy)(isc_mem_t **mctxp);
+ void *(*memget)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG);
+ void (*memput)(isc_mem_t *mctx, void *ptr, size_t size _ISC_MEM_FLARG);
+ void (*memputanddetach)(isc_mem_t **mctxp, void *ptr,
+ size_t size _ISC_MEM_FLARG);
+ void *(*memallocate)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG);
+ void *(*memreallocate)(isc_mem_t *mctx, void *ptr,
+ size_t size _ISC_MEM_FLARG);
+ char *(*memstrdup)(isc_mem_t *mctx, const char *s _ISC_MEM_FLARG);
+ void (*memfree)(isc_mem_t *mctx, void *ptr _ISC_MEM_FLARG);
+ void (*setdestroycheck)(isc_mem_t *mctx, isc_boolean_t flag);
+ void (*setwater)(isc_mem_t *ctx, isc_mem_water_t water,
+ void *water_arg, size_t hiwater, size_t lowater);
+ void (*waterack)(isc_mem_t *ctx, int flag);
+ size_t (*inuse)(isc_mem_t *mctx);
+ isc_boolean_t (*isovermem)(isc_mem_t *mctx);
+ isc_result_t (*mpcreate)(isc_mem_t *mctx, size_t size,
+ isc_mempool_t **mpctxp);
+} isc_memmethods_t;
+
+typedef struct isc_mempoolmethods {
+ void (*destroy)(isc_mempool_t **mpctxp);
+ void *(*get)(isc_mempool_t *mpctx _ISC_MEM_FLARG);
+ void (*put)(isc_mempool_t *mpctx, void *mem _ISC_MEM_FLARG);
+ unsigned int (*getallocated)(isc_mempool_t *mpctx);
+ void (*setmaxalloc)(isc_mempool_t *mpctx, unsigned int limit);
+ void (*setfreemax)(isc_mempool_t *mpctx, unsigned int limit);
+ void (*setname)(isc_mempool_t *mpctx, const char *name);
+ void (*associatelock)(isc_mempool_t *mpctx, isc_mutex_t *lock);
+ void (*setfillcount)(isc_mempool_t *mpctx, unsigned int limit);
+} isc_mempoolmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a memory context
+ * implementation's version of an isc_mem_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden. mctx implementations
+ * may change the structure. 'magic' must be ISCAPI_MCTX_MAGIC for any of the
+ * isc_mem_ routines to work. mctx implementations must maintain all mctx
+ * invariants.
+ */
+struct isc_mem {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_memmethods_t *methods;
+};
+
+#define ISCAPI_MCTX_MAGIC ISC_MAGIC('A','m','c','x')
+#define ISCAPI_MCTX_VALID(m) ((m) != NULL && \
+ (m)->magic == ISCAPI_MCTX_MAGIC)
+
+/*%
+ * This is the common prefix of a memory pool context. The same note as
+ * that for the mem structure applies.
+ */
+struct isc_mempool {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_mempoolmethods_t *methods;
+};
+
+#define ISCAPI_MPOOL_MAGIC ISC_MAGIC('A','m','p','l')
+#define ISCAPI_MPOOL_VALID(mp) ((mp) != NULL && \
+ (mp)->magic == ISCAPI_MPOOL_MAGIC)
+
#if ISC_MEM_DEBUG
#define isc_mem_put(c, p, s) \
do { \
- isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE); \
+ ISCMEMFUNC(put)((c), (p), (s) _ISC_MEM_FILELINE); \
(p) = NULL; \
} while (0)
#define isc_mem_putanddetach(c, p, s) \
do { \
- isc__mem_putanddetach((c), (p), (s) _ISC_MEM_FILELINE); \
+ ISCMEMFUNC(putanddetach)((c), (p), (s) _ISC_MEM_FILELINE); \
(p) = NULL; \
} while (0)
#define isc_mem_free(c, p) \
do { \
- isc__mem_free((c), (p) _ISC_MEM_FILELINE); \
+ ISCMEMFUNC(free)((c), (p) _ISC_MEM_FILELINE); \
(p) = NULL; \
} while (0)
#define isc_mempool_put(c, p) \
do { \
- isc__mempool_put((c), (p) _ISC_MEM_FILELINE); \
+ ISCMEMPOOLFUNC(put)((c), (p) _ISC_MEM_FILELINE); \
(p) = NULL; \
} while (0)
#else
-#define isc_mem_put(c, p, s) isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_put(c, p, s) ISCMEMFUNC(put)((c), (p), (s) _ISC_MEM_FILELINE)
#define isc_mem_putanddetach(c, p, s) \
- isc__mem_putanddetach((c), (p), (s) _ISC_MEM_FILELINE)
-#define isc_mem_free(c, p) isc__mem_free((c), (p) _ISC_MEM_FILELINE)
-#define isc_mempool_put(c, p) isc__mempool_put((c), (p) _ISC_MEM_FILELINE)
+ ISCMEMFUNC(putanddetach)((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_free(c, p) ISCMEMFUNC(free)((c), (p) _ISC_MEM_FILELINE)
+#define isc_mempool_put(c, p) ISCMEMPOOLFUNC(put)((c), (p) _ISC_MEM_FILELINE)
#endif
/*@{*/
@@ -613,24 +700,50 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
* Pseudo-private functions for use via macros. Do not call directly.
*/
void *
-isc__mem_get(isc_mem_t *, size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(get)(isc_mem_t *, size_t _ISC_MEM_FLARG);
void
-isc__mem_putanddetach(isc_mem_t **, void *,
- size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(putanddetach)(isc_mem_t **, void *, size_t _ISC_MEM_FLARG);
void
-isc__mem_put(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(put)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
void *
-isc__mem_allocate(isc_mem_t *, size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG);
void *
-isc__mem_reallocate(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(reallocate)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
void
-isc__mem_free(isc_mem_t *, void * _ISC_MEM_FLARG);
+ISCMEMFUNC(free)(isc_mem_t *, void * _ISC_MEM_FLARG);
char *
-isc__mem_strdup(isc_mem_t *, const char *_ISC_MEM_FLARG);
+ISCMEMFUNC(strdup)(isc_mem_t *, const char *_ISC_MEM_FLARG);
void *
-isc__mempool_get(isc_mempool_t * _ISC_MEM_FLARG);
+ISCMEMPOOLFUNC(get)(isc_mempool_t * _ISC_MEM_FLARG);
void
-isc__mempool_put(isc_mempool_t *, void * _ISC_MEM_FLARG);
+ISCMEMPOOLFUNC(put)(isc_mempool_t *, void * _ISC_MEM_FLARG);
+
+#ifdef USE_MEMIMPREGISTER
+
+/*%<
+ * See isc_mem_create2() above.
+ */
+typedef isc_result_t
+(*isc_memcreatefunc_t)(size_t init_max_size, size_t target_size,
+ isc_mem_t **ctxp, unsigned int flags);
+
+isc_result_t
+isc_mem_register(isc_memcreatefunc_t createfunc);
+/*%<
+ * Register a new memory management implementation and add it to the list of
+ * supported implementations. This function must be called when a different
+ * memory management library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__mem_register(void);
+/*%<
+ * A short cut function that specifies the memory management module in the ISC
+ * library for isc_mem_register(). An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_MEMIMPREGISTER */
ISC_LANG_ENDDECLS
diff --git a/contrib/bind9/lib/isc/include/isc/msgs.h b/contrib/bind9/lib/isc/include/isc/msgs.h
index 674371f5..22dfde2 100644
--- a/contrib/bind9/lib/isc/include/isc/msgs.h
+++ b/contrib/bind9/lib/isc/include/isc/msgs.h
@@ -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,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: msgs.h,v 1.17 2008-08-08 06:28:59 tbox Exp $ */
+/* $Id: msgs.h,v 1.19 2009-10-01 23:48:08 tbox Exp $ */
#ifndef ISC_MSGS_H
#define ISC_MSGS_H 1
@@ -156,7 +156,7 @@
#define ISC_MSG_FILTER 1421 /*%< setsockopt(SO_ACCEPTFILTER): %s */
#define ISC_MSG_TOOMANYHANDLES 1422 /*%< %s: too many open WSA event handles: %s */
-
+#define ISC_MSG_POKED 1423 /*%< "poked flags: %d" */
#define ISC_MSG_AWAKE 1502 /*%< "awake" */
#define ISC_MSG_WORKING 1503 /*%< "working" */
diff --git a/contrib/bind9/lib/isc/include/isc/namespace.h b/contrib/bind9/lib/isc/include/isc/namespace.h
new file mode 100644
index 0000000..05a8b2c
--- /dev/null
+++ b/contrib/bind9/lib/isc/include/isc/namespace.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2009, 2010 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: namespace.h,v 1.9 2010-12-04 13:25:59 marka Exp $ */
+
+#ifndef ISCAPI_NAMESPACE_H
+#define ISCAPI_NAMESPACE_H 1
+
+/*%
+ * name space conversions
+ */
+
+#ifdef BIND9
+
+#define isc_app_start isc__app_start
+#define isc_app_ctxstart isc__app_ctxstart
+#define isc_app_onrun isc__app_onrun
+#define isc_app_run isc__app_run
+#define isc_app_ctxrun isc__app_ctxrun
+#define isc_app_shutdown isc__app_shutdown
+#define isc_app_ctxshutdown isc__app_ctxshutdown
+#define isc_app_ctxsuspend isc__app_ctxsuspend
+#define isc_app_reload isc__app_reload
+#define isc_app_finish isc__app_finish
+#define isc_app_block isc__app_block
+#define isc_app_unblock isc__app_unblock
+#define isc_appctx_create isc__appctx_create
+#define isc_appctx_destroy isc__appctx_destroy
+#define isc_appctx_settaskmgr isc__appctx_settaskmgr
+#define isc_appctx_setsocketmgr isc__appctx_setsocketmgr
+#define isc_appctx_settimermgr isc__appctx_settimermgr
+
+#define isc_mem_checkdestroyed isc__mem_checkdestroyed
+#define isc_mem_createx isc__mem_createx
+#define isc_mem_createx2 isc__mem_createx2
+#define isc_mem_create isc__mem_create
+#define isc_mem_create2 isc__mem_create2
+#define isc_mem_attach isc__mem_attach
+#define isc_mem_detach isc__mem_detach
+#define isc__mem_putanddetach isc___mem_putanddetach
+#define isc_mem_destroy isc__mem_destroy
+#define isc_mem_ondestroy isc__mem_ondestroy
+#define isc__mem_get isc___mem_get
+#define isc__mem_put isc___mem_put
+#define isc_mem_stats isc__mem_stats
+#define isc__mem_allocate isc___mem_allocate
+#define isc__mem_free isc___mem_free
+#define isc__mem_strdup isc___mem_strdup
+#define isc__mem_reallocate isc___mem_reallocate
+#define isc_mem_references isc__mem_references
+#define isc_mem_setdestroycheck isc__mem_setdestroycheck
+#define isc_mem_setquota isc__mem_setquota
+#define isc_mem_getname isc__mem_getname
+#define isc_mem_getquota isc__mem_getquota
+#define isc_mem_gettag isc__mem_gettag
+#define isc_mem_inuse isc__mem_inuse
+#define isc_mem_isovermem isc__mem_isovermem
+#define isc_mem_setname isc__mem_setname
+#define isc_mem_setwater isc__mem_setwater
+#define isc_mem_printallactive isc__mem_printallactive
+#define isc_mem_waterack isc__mem_waterack
+#define isc_mempool_create isc__mempool_create
+#define isc_mempool_setname isc__mempool_setname
+#define isc_mempool_destroy isc__mempool_destroy
+#define isc_mempool_associatelock isc__mempool_associatelock
+#define isc__mempool_get isc___mempool_get
+#define isc__mempool_put isc___mempool_put
+#define isc_mempool_setfreemax isc__mempool_setfreemax
+#define isc_mempool_getfreemax isc__mempool_getfreemax
+#define isc_mempool_getfreecount isc__mempool_getfreecount
+#define isc_mempool_setmaxalloc isc__mempool_setmaxalloc
+#define isc_mempool_getmaxalloc isc__mempool_getmaxalloc
+#define isc_mempool_getallocated isc__mempool_getallocated
+#define isc_mempool_setfillcount isc__mempool_setfillcount
+#define isc_mempool_getfillcount isc__mempool_getfillcount
+
+#define isc_socket_create isc__socket_create
+#define isc_socket_attach isc__socket_attach
+#define isc_socket_detach isc__socket_detach
+#define isc_socketmgr_create isc__socketmgr_create
+#define isc_socketmgr_create2 isc__socketmgr_create2
+#define isc_socketmgr_destroy isc__socketmgr_destroy
+#define isc_socket_open isc__socket_open
+#define isc_socket_close isc__socket_close
+#define isc_socket_recvv isc__socket_recvv
+#define isc_socket_recv isc__socket_recv
+#define isc_socket_recv2 isc__socket_recv2
+#define isc_socket_send isc__socket_send
+#define isc_socket_sendto isc__socket_sendto
+#define isc_socket_sendv isc__socket_sendv
+#define isc_socket_sendtov isc__socket_sendtov
+#define isc_socket_sendto2 isc__socket_sendto2
+#define isc_socket_cleanunix isc__socket_cleanunix
+#define isc_socket_permunix isc__socket_permunix
+#define isc_socket_bind isc__socket_bind
+#define isc_socket_filter isc__socket_filter
+#define isc_socket_listen isc__socket_listen
+#define isc_socket_accept isc__socket_accept
+#define isc_socket_connect isc__socket_connect
+#define isc_socket_getname isc__socket_getname
+#define isc_socket_gettag isc__socket_gettag
+#define isc_socket_getpeername isc__socket_getpeername
+#define isc_socket_getsockname isc__socket_getsockname
+#define isc_socket_cancel isc__socket_cancel
+#define isc_socket_gettype isc__socket_gettype
+#define isc_socket_isbound isc__socket_isbound
+#define isc_socket_ipv6only isc__socket_ipv6only
+#define isc_socket_setname isc__socket_setname
+#define isc_socketmgr_getmaxsockets isc__socketmgr_getmaxsockets
+#define isc_socketmgr_setstats isc__socketmgr_setstats
+#define isc_socketmgr_setreserved isc__socketmgr_setreserved
+#define isc__socketmgr_maxudp isc___socketmgr_maxudp
+#define isc_socket_fdwatchcreate isc__socket_fdwatchcreate
+#define isc_socket_fdwatchpoke isc__socket_fdwatchpoke
+
+#define isc_task_create isc__task_create
+#define isc_task_attach isc__task_attach
+#define isc_task_detach isc__task_detach
+/* #define isc_task_exiting isc__task_exiting XXXMPA */
+#define isc_task_send isc__task_send
+#define isc_task_sendanddetach isc__task_sendanddetach
+#define isc_task_purgerange isc__task_purgerange
+#define isc_task_purge isc__task_purge
+#define isc_task_purgeevent isc__task_purgeevent
+#define isc_task_unsendrange isc__task_unsendrange
+#define isc_task_unsend isc__task_unsend
+#define isc_task_onshutdown isc__task_onshutdown
+#define isc_task_shutdown isc__task_shutdown
+#define isc_task_destroy isc__task_destroy
+#define isc_task_setname isc__task_setname
+#define isc_task_getname isc__task_getname
+#define isc_task_gettag isc__task_gettag
+#define isc_task_getcurrenttime isc__task_getcurrenttime
+#define isc_taskmgr_create isc__taskmgr_create
+#define isc_taskmgr_destroy isc__taskmgr_destroy
+#define isc_task_beginexclusive isc__task_beginexclusive
+#define isc_task_endexclusive isc__task_endexclusive
+
+#define isc_timer_create isc__timer_create
+#define isc_timer_reset isc__timer_reset
+#define isc_timer_gettype isc__timer_gettype
+#define isc_timer_touch isc__timer_touch
+#define isc_timer_attach isc__timer_attach
+#define isc_timer_detach isc__timer_detach
+#define isc_timermgr_create isc__timermgr_create
+#define isc_timermgr_poke isc__timermgr_poke
+#define isc_timermgr_destroy isc__timermgr_destroy
+
+#endif /* BIND9 */
+
+#endif /* ISCAPI_NAMESPACE_H */
diff --git a/contrib/bind9/lib/isc/include/isc/netaddr.h b/contrib/bind9/lib/isc/include/isc/netaddr.h
index 52418ec..04b7ec1 100644
--- a/contrib/bind9/lib/isc/include/isc/netaddr.h
+++ b/contrib/bind9/lib/isc/include/isc/netaddr.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: netaddr.h,v 1.35.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: netaddr.h,v 1.37 2009-01-17 23:47:43 tbox Exp $ */
#ifndef ISC_NETADDR_H
#define ISC_NETADDR_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/netscope.h b/contrib/bind9/lib/isc/include/isc/netscope.h
index 7b2c13c..1a50816 100644
--- a/contrib/bind9/lib/isc/include/isc/netscope.h
+++ b/contrib/bind9/lib/isc/include/isc/netscope.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: netscope.h,v 1.11.332.2 2009-06-25 23:47:24 tbox Exp $ */
+/* $Id: netscope.h,v 1.13 2009-06-25 23:48:02 tbox Exp $ */
#ifndef ISC_NETSCOPE_H
#define ISC_NETSCOPE_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/platform.h.in b/contrib/bind9/lib/isc/include/isc/platform.h.in
index 99c887b..2491274 100644
--- a/contrib/bind9/lib/isc/include/isc/platform.h.in
+++ b/contrib/bind9/lib/isc/include/isc/platform.h.in
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: platform.h.in,v 1.48.84.4 2010-06-03 23:47:49 tbox Exp $ */
+/* $Id: platform.h.in,v 1.56 2010-12-18 01:56:23 each Exp $ */
#ifndef ISC_PLATFORM_H
#define ISC_PLATFORM_H 1
@@ -146,6 +146,11 @@
*/
@ISC_PLATFORM_HAVEDEVPOLL@
+/*! \brief
+ * Define if we want to log backtrace
+ */
+@ISC_PLATFORM_USEBACKTRACE@
+
/*
*** Printing.
***/
@@ -215,6 +220,12 @@
@ISC_PLATFORM_GSSAPIHEADER@
/*
+ * Defined to <gssapi_krb5.h> or <gssapi/gssapi_krb5.h> for how to
+ * include the GSSAPI KRB5 header.
+ */
+@ISC_PLATFORM_GSSAPI_KRB5_HEADER@
+
+/*
* Defined to <krb5.h> or <krb5/krb5.h> for how to include
* the KRB5 header.
*/
@@ -290,6 +301,17 @@
*/
@ISC_PLATFORM_HAVESTRINGSH@
+/*
+ * Define if the hash functions must be provided by OpenSSL.
+ */
+@ISC_PLATFORM_OPENSSLHASH@
+
+/*
+ * Defines for the noreturn attribute.
+ */
+@ISC_PLATFORM_NORETURN_PRE@
+@ISC_PLATFORM_NORETURN_POST@
+
/***
*** Windows dll support.
***/
diff --git a/contrib/bind9/lib/isc/include/isc/portset.h b/contrib/bind9/lib/isc/include/isc/portset.h
index a257322..2e27467 100644
--- a/contrib/bind9/lib/isc/include/isc/portset.h
+++ b/contrib/bind9/lib/isc/include/isc/portset.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: portset.h,v 1.3.90.3 2009-06-25 05:31:51 marka Exp $ */
+/* $Id: portset.h,v 1.6 2009-06-25 05:28:34 marka Exp $ */
/*! \file isc/portset.h
* \brief Transport Protocol Port Manipulation Module
diff --git a/contrib/bind9/lib/isc/include/isc/radix.h b/contrib/bind9/lib/isc/include/isc/radix.h
index fa5e294..ed8aaf2 100644
--- a/contrib/bind9/lib/isc/include/isc/radix.h
+++ b/contrib/bind9/lib/isc/include/isc/radix.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: radix.h,v 1.11.44.2 2008-12-24 23:47:02 tbox Exp $ */
+/* $Id: radix.h,v 1.13 2008-12-01 23:47:45 tbox Exp $ */
/*
* This source was adapted from MRT's RCS Ids:
diff --git a/contrib/bind9/lib/isc/include/isc/random.h b/contrib/bind9/lib/isc/include/isc/random.h
index 9743cb4..e05b204 100644
--- a/contrib/bind9/lib/isc/include/isc/random.h
+++ b/contrib/bind9/lib/isc/include/isc/random.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: random.h,v 1.18.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: random.h,v 1.20 2009-01-17 23:47:43 tbox Exp $ */
#ifndef ISC_RANDOM_H
#define ISC_RANDOM_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/ratelimiter.h b/contrib/bind9/lib/isc/include/isc/ratelimiter.h
index 7ed312a..f8a9819 100644
--- a/contrib/bind9/lib/isc/include/isc/ratelimiter.h
+++ b/contrib/bind9/lib/isc/include/isc/ratelimiter.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ratelimiter.h,v 1.21.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: ratelimiter.h,v 1.23 2009-01-18 23:48:14 tbox Exp $ */
#ifndef ISC_RATELIMITER_H
#define ISC_RATELIMITER_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/refcount.h b/contrib/bind9/lib/isc/include/isc/refcount.h
index 8e83a13..71f35f1 100644
--- a/contrib/bind9/lib/isc/include/isc/refcount.h
+++ b/contrib/bind9/lib/isc/include/isc/refcount.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 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: refcount.h,v 1.15 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: refcount.h,v 1.17 2009-09-29 23:48:04 tbox Exp $ */
#ifndef ISC_REFCOUNT_H
#define ISC_REFCOUNT_H 1
@@ -28,7 +28,7 @@
#include <isc/util.h>
/*! \file isc/refcount.h
- * \brief Implements a locked reference counter.
+ * \brief Implements a locked reference counter.
*
* These functions may actually be
* implemented using macros, and implementations of these macros are below.
@@ -42,7 +42,7 @@ ISC_LANG_BEGINDECLS
* Function prototypes
*/
-/*
+/*
* isc_result_t
* isc_refcount_init(isc_refcount_t *ref, unsigned int n);
*
@@ -103,7 +103,7 @@ typedef struct isc_refcount {
isc_int32_t refs;
} isc_refcount_t;
-#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
+#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0)
#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
#define isc_refcount_increment0(rp, tp) \
@@ -192,7 +192,7 @@ typedef struct isc_refcount {
int refs;
} isc_refcount_t;
-#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
+#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0)
#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
#define isc_refcount_increment0(rp, tp) \
diff --git a/contrib/bind9/lib/isc/include/isc/result.h b/contrib/bind9/lib/isc/include/isc/result.h
index 804ab5e..cc591dc 100644
--- a/contrib/bind9/lib/isc/include/isc/result.h
+++ b/contrib/bind9/lib/isc/include/isc/result.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: result.h,v 1.71 2008-09-25 04:02:39 tbox Exp $ */
+/* $Id: result.h,v 1.73 2009-09-02 23:48:03 tbox Exp $ */
#ifndef ISC_RESULT_H
#define ISC_RESULT_H 1
@@ -42,6 +42,7 @@
#define ISC_R_EOF 14 /*%< end of file */
#define ISC_R_BOUND 15 /*%< socket already bound */
#define ISC_R_RELOAD 16 /*%< reload */
+#define ISC_R_SUSPEND ISC_R_RELOAD /*%< alias of 'reload' */
#define ISC_R_LOCKBUSY 17 /*%< lock busy */
#define ISC_R_EXISTS 18 /*%< already exists */
#define ISC_R_NOSPACE 19 /*%< ran out of space */
diff --git a/contrib/bind9/lib/isc/include/isc/resultclass.h b/contrib/bind9/lib/isc/include/isc/resultclass.h
index 86c55b6..84f6c64 100644
--- a/contrib/bind9/lib/isc/include/isc/resultclass.h
+++ b/contrib/bind9/lib/isc/include/isc/resultclass.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resultclass.h,v 1.18 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: resultclass.h,v 1.20 2009-09-02 23:48:03 tbox Exp $ */
#ifndef ISC_RESULTCLASS_H
#define ISC_RESULTCLASS_H 1
@@ -45,6 +45,7 @@
#define ISC_RESULTCLASS_DNSRCODE ISC_RESULTCLASS_FROMNUM(3)
#define ISC_RESULTCLASS_OMAPI ISC_RESULTCLASS_FROMNUM(4)
#define ISC_RESULTCLASS_ISCCC ISC_RESULTCLASS_FROMNUM(5)
+#define ISC_RESULTCLASS_DHCP ISC_RESULTCLASS_FROMNUM(6)
#endif /* ISC_RESULTCLASS_H */
diff --git a/contrib/bind9/lib/isc/include/isc/serial.h b/contrib/bind9/lib/isc/include/isc/serial.h
index 97d5fe1..332709d 100644
--- a/contrib/bind9/lib/isc/include/isc/serial.h
+++ b/contrib/bind9/lib/isc/include/isc/serial.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: serial.h,v 1.16.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: serial.h,v 1.18 2009-01-18 23:48:14 tbox Exp $ */
#ifndef ISC_SERIAL_H
#define ISC_SERIAL_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/sha1.h b/contrib/bind9/lib/isc/include/isc/sha1.h
index 4da682a..a9d08b9 100644
--- a/contrib/bind9/lib/isc/include/isc/sha1.h
+++ b/contrib/bind9/lib/isc/include/isc/sha1.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 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/or distribute this software for any
@@ -18,7 +18,7 @@
#ifndef ISC_SHA1_H
#define ISC_SHA1_H 1
-/* $Id: sha1.h,v 1.17 2007-06-19 23:47:18 tbox Exp $ */
+/* $Id: sha1.h,v 1.19 2009-02-06 23:47:42 tbox Exp $ */
/* $NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $ */
@@ -29,16 +29,25 @@
*/
#include <isc/lang.h>
+#include <isc/platform.h>
#include <isc/types.h>
#define ISC_SHA1_DIGESTLENGTH 20U
#define ISC_SHA1_BLOCK_LENGTH 64U
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
+
+typedef EVP_MD_CTX isc_sha1_t;
+
+#else
+
typedef struct {
isc_uint32_t state[5];
isc_uint32_t count[2];
unsigned char buffer[ISC_SHA1_BLOCK_LENGTH];
} isc_sha1_t;
+#endif
ISC_LANG_BEGINDECLS
diff --git a/contrib/bind9/lib/isc/include/isc/sha2.h b/contrib/bind9/lib/isc/include/isc/sha2.h
index c3130a8..8d4ffa6 100644
--- a/contrib/bind9/lib/isc/include/isc/sha2.h
+++ b/contrib/bind9/lib/isc/include/isc/sha2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-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
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sha2.h,v 1.9.332.2 2010-01-15 23:47:34 tbox Exp $ */
+/* $Id: sha2.h,v 1.12 2009-10-22 02:21:31 each Exp $ */
/* $FreeBSD$ */
/* $KAME: sha2.h,v 1.3 2001/03/12 08:27:48 itojun Exp $ */
@@ -58,6 +58,7 @@
#define ISC_SHA2_H
#include <isc/lang.h>
+#include <isc/platform.h>
#include <isc/types.h>
/*** SHA-224/256/384/512 Various Length Definitions ***********************/
@@ -75,10 +76,15 @@
#define ISC_SHA512_DIGESTLENGTH 64U
#define ISC_SHA512_DIGESTSTRINGLENGTH (ISC_SHA512_DIGESTLENGTH * 2 + 1)
+/*** SHA-256/384/512 Context Structures *******************************/
-ISC_LANG_BEGINDECLS
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
-/*** SHA-256/384/512 Context Structures *******************************/
+typedef EVP_MD_CTX isc_sha256_t;
+typedef EVP_MD_CTX isc_sha512_t;
+
+#else
/*
* Keep buffer immediately after bitcount to preserve alignment.
@@ -97,10 +103,13 @@ typedef struct {
isc_uint64_t bitcount[2];
isc_uint8_t buffer[ISC_SHA512_BLOCK_LENGTH];
} isc_sha512_t;
+#endif
typedef isc_sha256_t isc_sha224_t;
typedef isc_sha512_t isc_sha384_t;
+ISC_LANG_BEGINDECLS
+
/*** SHA-224/256/384/512 Function Prototypes ******************************/
void isc_sha224_init (isc_sha224_t *);
diff --git a/contrib/bind9/lib/isc/include/isc/sockaddr.h b/contrib/bind9/lib/isc/include/isc/sockaddr.h
index 758cef7..c83655e 100644
--- a/contrib/bind9/lib/isc/include/isc/sockaddr.h
+++ b/contrib/bind9/lib/isc/include/isc/sockaddr.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sockaddr.h,v 1.55.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: sockaddr.h,v 1.57 2009-01-18 23:48:14 tbox Exp $ */
#ifndef ISC_SOCKADDR_H
#define ISC_SOCKADDR_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/socket.h b/contrib/bind9/lib/isc/include/isc/socket.h
index 749ee52..0aa71da 100644
--- a/contrib/bind9/lib/isc/include/isc/socket.h
+++ b/contrib/bind9/lib/isc/include/isc/socket.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: socket.h,v 1.85.58.3 2009-01-29 22:40:35 jinmei Exp $ */
+/* $Id: socket.h,v 1.94 2009-10-01 01:30:01 sar Exp $ */
#ifndef ISC_SOCKET_H
#define ISC_SOCKET_H 1
@@ -260,6 +260,85 @@ typedef enum {
#define ISC_SOCKFDWATCH_WRITE 0x00000002 /*%< watch for writable */
/*@}*/
+/*% Socket and socket manager methods */
+typedef struct isc_socketmgrmethods {
+ void (*destroy)(isc_socketmgr_t **managerp);
+ isc_result_t (*socketcreate)(isc_socketmgr_t *manager, int pf,
+ isc_sockettype_t type,
+ isc_socket_t **socketp);
+ isc_result_t (*fdwatchcreate)(isc_socketmgr_t *manager, int fd,
+ int flags,
+ isc_sockfdwatch_t callback,
+ void *cbarg, isc_task_t *task,
+ isc_socket_t **socketp);
+} isc_socketmgrmethods_t;
+
+typedef struct isc_socketmethods {
+ void (*attach)(isc_socket_t *socket,
+ isc_socket_t **socketp);
+ void (*detach)(isc_socket_t **socketp);
+ isc_result_t (*bind)(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+ unsigned int options);
+ isc_result_t (*sendto)(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action,
+ const void *arg, isc_sockaddr_t *address,
+ struct in6_pktinfo *pktinfo);
+ isc_result_t (*connect)(isc_socket_t *sock, isc_sockaddr_t *addr,
+ isc_task_t *task, isc_taskaction_t action,
+ const void *arg);
+ isc_result_t (*recv)(isc_socket_t *sock, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_taskaction_t action, const void *arg);
+ void (*cancel)(isc_socket_t *sock, isc_task_t *task,
+ unsigned int how);
+ isc_result_t (*getsockname)(isc_socket_t *sock,
+ isc_sockaddr_t *addressp);
+ isc_sockettype_t (*gettype)(isc_socket_t *sock);
+ void (*ipv6only)(isc_socket_t *sock, isc_boolean_t yes);
+ isc_result_t (*fdwatchpoke)(isc_socket_t *sock, int flags);
+} isc_socketmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a socket manager
+ * object implementation's version of an isc_socketmgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden. socket implementations
+ * may change the structure. 'magic' must be ISCAPI_SOCKETMGR_MAGIC for any
+ * of the isc_socket_ routines to work. socket implementations must maintain
+ * all socket invariants.
+ * In effect, this definition is used only for non-BIND9 version ("export")
+ * of the library, and the export version does not work for win32. So, to avoid
+ * the definition conflict with win32/socket.c, we enable this definition only
+ * for non-Win32 (i.e. Unix) platforms.
+ */
+#ifndef WIN32
+struct isc_socketmgr {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_socketmgrmethods_t *methods;
+};
+#endif
+
+#define ISCAPI_SOCKETMGR_MAGIC ISC_MAGIC('A','s','m','g')
+#define ISCAPI_SOCKETMGR_VALID(m) ((m) != NULL && \
+ (m)->magic == ISCAPI_SOCKETMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a socket object. The same note as
+ * that for the socketmgr structure applies.
+ */
+#ifndef WIN32
+struct isc_socket {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_socketmethods_t *methods;
+};
+#endif
+
+#define ISCAPI_SOCKET_MAGIC ISC_MAGIC('A','s','c','t')
+#define ISCAPI_SOCKET_VALID(s) ((s) != NULL && \
+ (s)->magic == ISCAPI_SOCKET_MAGIC)
+
/***
*** Socket and Socket Manager Functions
***
@@ -307,6 +386,35 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager,
*/
isc_result_t
+isc_socket_fdwatchpoke(isc_socket_t *sock,
+ int flags);
+/*%<
+ * Poke a file descriptor watch socket informing the manager that it
+ * should restart watching the socket
+ *
+ * Note:
+ *
+ *\li 'sock' is the socket returned by isc_socket_fdwatchcreate
+ *
+ *\li 'flags' indicates what the manager should watch for on the socket
+ * in addition to what it may already be watching. It can be one or
+ * both of ISC_SOCKFDWATCH_READ and ISC_SOCKFDWATCH_WRITE. To
+ * temporarily disable watching on a socket the value indicating
+ * no more data should be returned from the call back routine.
+ *
+ *\li This function is not available on Windows.
+ *
+ * Requires:
+ *
+ *\li 'sock' is a valid isc socket
+ *
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ */
+
+isc_result_t
isc_socket_create(isc_socketmgr_t *manager,
int pf,
isc_sockettype_t type,
@@ -821,6 +929,10 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
/*@}*/
isc_result_t
+isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+ isc_socketmgr_t **managerp);
+
+isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
isc_result_t
@@ -831,6 +943,8 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
* maximum number of sockets that the created manager should handle.
* isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with
* "maxsocks" being zero.
+ * isc_socketmgr_createinctx() also associates the new manager with the
+ * specified application context.
*
* Notes:
*
@@ -842,6 +956,8 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
*
*\li 'managerp' points to a NULL isc_socketmgr_t.
*
+ *\li 'actx' is a valid application context (for createinctx()).
+ *
* Ensures:
*
*\li '*managerp' is a valid isc_socketmgr_t.
@@ -992,6 +1108,12 @@ isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t);
* Temporary. For use by named only.
*/
+void
+isc__socketmgr_maxudp(isc_socketmgr_t *mgr, int maxudp);
+/*%<
+ * Test interface. Drop UDP packet > 'maxudp'.
+ */
+
#ifdef HAVE_LIBXML2
void
@@ -1002,6 +1124,31 @@ isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer);
#endif /* HAVE_LIBXML2 */
+#ifdef USE_SOCKETIMPREGISTER
+/*%<
+ * See isc_socketmgr_create() above.
+ */
+typedef isc_result_t
+(*isc_socketmgrcreatefunc_t)(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+
+isc_result_t
+isc_socket_register(isc_socketmgrcreatefunc_t createfunc);
+/*%<
+ * Register a new socket I/O implementation and add it to the list of
+ * supported implementations. This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__socket_register(void);
+/*%<
+ * A short cut function that specifies the socket I/O module in the ISC
+ * library for isc_socket_register(). An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_SOCKETIMPREGISTER */
+
ISC_LANG_ENDDECLS
#endif /* ISC_SOCKET_H */
diff --git a/contrib/bind9/lib/isc/include/isc/stats.h b/contrib/bind9/lib/isc/include/isc/stats.h
index 1148a16..226bc08 100644
--- a/contrib/bind9/lib/isc/include/isc/stats.h
+++ b/contrib/bind9/lib/isc/include/isc/stats.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: stats.h,v 1.4.2.2 2009-01-29 23:47:44 tbox Exp $ */
+/* $Id: stats.h,v 1.4 2009-01-29 01:03:56 jinmei Exp $ */
#ifndef ISC_STATS_H
#define ISC_STATS_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/symtab.h b/contrib/bind9/lib/isc/include/isc/symtab.h
index a1d7102..c61d0ea 100644
--- a/contrib/bind9/lib/isc/include/isc/symtab.h
+++ b/contrib/bind9/lib/isc/include/isc/symtab.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: symtab.h,v 1.24.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: symtab.h,v 1.26 2009-01-18 23:48:14 tbox Exp $ */
#ifndef ISC_SYMTAB_H
#define ISC_SYMTAB_H 1
diff --git a/contrib/bind9/lib/isc/include/isc/task.h b/contrib/bind9/lib/isc/include/isc/task.h
index a8c7569..a2a1bbe 100644
--- a/contrib/bind9/lib/isc/include/isc/task.h
+++ b/contrib/bind9/lib/isc/include/isc/task.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: task.h,v 1.61.332.4 2010-12-03 23:45:47 tbox Exp $ */
+/* $Id: task.h,v 1.69.14.1.2.1 2011-06-02 23:47:36 tbox Exp $ */
#ifndef ISC_TASK_H
#define ISC_TASK_H 1
@@ -96,6 +96,72 @@
ISC_LANG_BEGINDECLS
+/***
+ *** Types
+ ***/
+
+/*% Task and task manager methods */
+typedef struct isc_taskmgrmethods {
+ void (*destroy)(isc_taskmgr_t **managerp);
+ isc_result_t (*taskcreate)(isc_taskmgr_t *manager,
+ unsigned int quantum,
+ isc_task_t **taskp);
+} isc_taskmgrmethods_t;
+
+typedef struct isc_taskmethods {
+ void (*attach)(isc_task_t *source, isc_task_t **targetp);
+ void (*detach)(isc_task_t **taskp);
+ void (*destroy)(isc_task_t **taskp);
+ void (*send)(isc_task_t *task, isc_event_t **eventp);
+ void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp);
+ unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type,
+ void *tag, isc_eventlist_t *events);
+ isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action,
+ const void *arg);
+ void (*shutdown)(isc_task_t *task);
+ void (*setname)(isc_task_t *task, const char *name, void *tag);
+ unsigned int (*purgeevents)(isc_task_t *task, void *sender,
+ isc_eventtype_t type, void *tag);
+ unsigned int (*purgerange)(isc_task_t *task, void *sender,
+ isc_eventtype_t first, isc_eventtype_t last,
+ void *tag);
+ isc_result_t (*beginexclusive)(isc_task_t *task);
+ void (*endexclusive)(isc_task_t *task);
+} isc_taskmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a task manager
+ * object implementation's version of an isc_taskmgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden. task implementations
+ * may change the structure. 'magic' must be ISCAPI_TASKMGR_MAGIC for any
+ * of the isc_task_ routines to work. task implementations must maintain
+ * all task invariants.
+ */
+struct isc_taskmgr {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_taskmgrmethods_t *methods;
+};
+
+#define ISCAPI_TASKMGR_MAGIC ISC_MAGIC('A','t','m','g')
+#define ISCAPI_TASKMGR_VALID(m) ((m) != NULL && \
+ (m)->magic == ISCAPI_TASKMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a task object. The same note as
+ * that for the taskmgr structure applies.
+ */
+struct isc_task {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_taskmethods_t *methods;
+};
+
+#define ISCAPI_TASK_MAGIC ISC_MAGIC('A','t','s','t')
+#define ISCAPI_TASK_VALID(s) ((s) != NULL && \
+ (s)->magic == ISCAPI_TASK_MAGIC)
+
isc_result_t
isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
isc_task_t **taskp);
@@ -550,10 +616,15 @@ isc_task_exiting(isc_task_t *t);
*****/
isc_result_t
+isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+ unsigned int workers, unsigned int default_quantum,
+ isc_taskmgr_t **managerp);
+isc_result_t
isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
unsigned int default_quantum, isc_taskmgr_t **managerp);
/*%<
- * Create a new task manager.
+ * Create a new task manager. isc_taskmgr_createinctx() also associates
+ * the new manager with the specified application context.
*
* Notes:
*
@@ -575,6 +646,8 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
*
*\li managerp != NULL && *managerp == NULL
*
+ *\li 'actx' is a valid application context (for createinctx()).
+ *
* Ensures:
*
*\li On success, '*managerp' will be attached to the newly created task
@@ -584,8 +657,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
*
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOMEMORY
- *\li #ISC_R_NOTHREADS No threads could be created.
+ *\li #ISC_R_NOTHREADS No threads could be created.
*\li #ISC_R_UNEXPECTED An unexpected error occurred.
+ *\li #ISC_R_SHUTTINGDOWN The non-threaded, shared, task
+ * manager shutting down.
*/
void
@@ -629,6 +704,31 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
#endif
+/*%<
+ * See isc_taskmgr_create() above.
+ */
+typedef isc_result_t
+(*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers,
+ unsigned int default_quantum,
+ isc_taskmgr_t **managerp);
+
+isc_result_t
+isc_task_register(isc_taskmgrcreatefunc_t createfunc);
+/*%<
+ * Register a new task management implementation and add it to the list of
+ * supported implementations. This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__task_register(void);
+/*%<
+ * A short cut function that specifies the task management module in the ISC
+ * library for isc_task_register(). An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+
ISC_LANG_ENDDECLS
#endif /* ISC_TASK_H */
diff --git a/contrib/bind9/lib/isc/include/isc/timer.h b/contrib/bind9/lib/isc/include/isc/timer.h
index 052e25b..a54e73b 100644
--- a/contrib/bind9/lib/isc/include/isc/timer.h
+++ b/contrib/bind9/lib/isc/include/isc/timer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 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: timer.h,v 1.40 2008-06-23 23:47:11 tbox Exp $ */
+/* $Id: timer.h,v 1.43 2009-09-02 23:48:03 tbox Exp $ */
#ifndef ISC_TIMER_H
#define ISC_TIMER_H 1
@@ -103,6 +103,61 @@ typedef struct isc_timerevent {
#define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3)
#define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535)
+/*% Timer and timer manager methods */
+typedef struct {
+ void (*destroy)(isc_timermgr_t **managerp);
+ isc_result_t (*timercreate)(isc_timermgr_t *manager,
+ isc_timertype_t type,
+ isc_time_t *expires,
+ isc_interval_t *interval,
+ isc_task_t *task,
+ isc_taskaction_t action,
+ const void *arg,
+ isc_timer_t **timerp);
+} isc_timermgrmethods_t;
+
+typedef struct {
+ void (*attach)(isc_timer_t *timer, isc_timer_t **timerp);
+ void (*detach)(isc_timer_t **timerp);
+ isc_result_t (*reset)(isc_timer_t *timer, isc_timertype_t type,
+ isc_time_t *expires, isc_interval_t *interval,
+ isc_boolean_t purge);
+ isc_result_t (*touch)(isc_timer_t *timer);
+} isc_timermethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a timer manager
+ * object implementation's version of an isc_timermgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden. timer implementations
+ * may change the structure. 'magic' must be ISCAPI_TIMERMGR_MAGIC for any
+ * of the isc_timer_ routines to work. timer implementations must maintain
+ * all timer invariants.
+ */
+struct isc_timermgr {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_timermgrmethods_t *methods;
+};
+
+#define ISCAPI_TIMERMGR_MAGIC ISC_MAGIC('A','t','m','g')
+#define ISCAPI_TIMERMGR_VALID(m) ((m) != NULL && \
+ (m)->magic == ISCAPI_TIMERMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a timer object. The same note as
+ * that for the timermgr structure applies.
+ */
+struct isc_timer {
+ unsigned int impmagic;
+ unsigned int magic;
+ isc_timermethods_t *methods;
+};
+
+#define ISCAPI_TIMER_MAGIC ISC_MAGIC('A','t','m','r')
+#define ISCAPI_TIMER_VALID(s) ((s) != NULL && \
+ (s)->magic == ISCAPI_TIMER_MAGIC)
+
/***
*** Timer and Timer Manager Functions
***
@@ -289,9 +344,14 @@ isc_timer_gettype(isc_timer_t *timer);
*/
isc_result_t
+isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+ isc_timermgr_t **managerp);
+
+isc_result_t
isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
/*%<
- * Create a timer manager.
+ * Create a timer manager. isc_timermgr_createinctx() also associates
+ * the new manager with the specified application context.
*
* Notes:
*
@@ -303,6 +363,8 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
*
*\li 'managerp' points to a NULL isc_timermgr_t.
*
+ *\li 'actx' is a valid application context (for createinctx()).
+ *
* Ensures:
*
*\li '*managerp' is a valid isc_timermgr_t.
@@ -339,6 +401,31 @@ isc_timermgr_destroy(isc_timermgr_t **managerp);
void isc_timermgr_poke(isc_timermgr_t *m);
+#ifdef USE_TIMERIMPREGISTER
+/*%<
+ * See isc_timermgr_create() above.
+ */
+typedef isc_result_t
+(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
+
+isc_result_t
+isc__timer_register(void);
+/*%<
+ * Register a new timer management implementation and add it to the list of
+ * supported implementations. This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc_timer_register(isc_timermgrcreatefunc_t createfunc);
+/*%<
+ * A short cut function that specifies the timer management module in the ISC
+ * library for isc_timer_register(). An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_TIMERIMPREGISTER */
+
ISC_LANG_ENDDECLS
#endif /* ISC_TIMER_H */
diff --git a/contrib/bind9/lib/isc/include/isc/types.h b/contrib/bind9/lib/isc/include/isc/types.h
index 01362b8..10da62b 100644
--- a/contrib/bind9/lib/isc/include/isc/types.h
+++ b/contrib/bind9/lib/isc/include/isc/types.h
@@ -15,11 +15,14 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: types.h,v 1.46.84.2 2009-01-29 23:47:44 tbox Exp $ */
+/* $Id: types.h,v 1.52 2009-12-05 23:31:41 each Exp $ */
#ifndef ISC_TYPES_H
#define ISC_TYPES_H 1
+#include <isc/bind9.h>
+#include <isc/namespace.h>
+
/*! \file isc/types.h
* \brief
* OS-specific types, from the OS-specific include directories.
@@ -40,6 +43,8 @@
/* Core Types. Alphabetized by defined type. */
+typedef struct isc_appctx isc_appctx_t; /*%< Application context */
+typedef struct isc_backtrace_symmap isc_backtrace_symmap_t; /*%< Symbol Table Entry */
typedef struct isc_bitstring isc_bitstring_t; /*%< Bitstring */
typedef struct isc_buffer isc_buffer_t; /*%< Buffer */
typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */
@@ -94,7 +99,7 @@ typedef struct isc_timer isc_timer_t; /*%< Timer */
typedef struct isc_timermgr isc_timermgr_t; /*%< Timer Manager */
typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *);
-typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *);
+typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int);
/* The following cannot be listed alphabetically due to forward reference */
typedef isc_result_t (isc_httpdaction_t)(const char *url,
diff --git a/contrib/bind9/lib/isc/include/isc/util.h b/contrib/bind9/lib/isc/include/isc/util.h
index 8ccad8d..11d0044 100644
--- a/contrib/bind9/lib/isc/include/isc/util.h
+++ b/contrib/bind9/lib/isc/include/isc/util.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: util.h,v 1.30.332.2 2010-01-11 23:47:22 tbox Exp $ */
+/* $Id: util.h,v 1.32 2010-01-11 23:48:37 tbox Exp $ */
#ifndef ISC_UTIL_H
#define ISC_UTIL_H 1
diff --git a/contrib/bind9/lib/isc/inet_aton.c b/contrib/bind9/lib/isc/inet_aton.c
index 3c25ca3..9e35a36 100644
--- a/contrib/bind9/lib/isc/inet_aton.c
+++ b/contrib/bind9/lib/isc/inet_aton.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1996-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -71,7 +71,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
-static char rcsid[] = "$Id: inet_aton.c,v 1.21.332.2 2009-03-05 23:47:03 tbox Exp $";
+static char rcsid[] = "$Id: inet_aton.c,v 1.23 2008-12-01 23:47:45 tbox Exp $";
#endif /* LIBC_SCCS and not lint */
#include <config.h>
diff --git a/contrib/bind9/lib/isc/inet_ntop.c b/contrib/bind9/lib/isc/inet_ntop.c
index 22930f3..581ebe8 100644
--- a/contrib/bind9/lib/isc/inet_ntop.c
+++ b/contrib/bind9/lib/isc/inet_ntop.c
@@ -19,7 +19,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static char rcsid[] =
- "$Id: inet_ntop.c,v 1.19.332.2 2009-07-18 23:47:25 tbox Exp $";
+ "$Id: inet_ntop.c,v 1.21 2009-07-17 23:47:41 tbox Exp $";
#endif /* LIBC_SCCS and not lint */
#include <config.h>
diff --git a/contrib/bind9/lib/isc/iterated_hash.c b/contrib/bind9/lib/isc/iterated_hash.c
index ebc5076..7185075 100644
--- a/contrib/bind9/lib/isc/iterated_hash.c
+++ b/contrib/bind9/lib/isc/iterated_hash.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: iterated_hash.c,v 1.4.48.2 2009-02-18 23:47:12 tbox Exp $ */
+/* $Id: iterated_hash.c,v 1.6 2009-02-18 23:47:48 tbox Exp $ */
#include "config.h"
diff --git a/contrib/bind9/lib/isc/lib.c b/contrib/bind9/lib/isc/lib.c
index 99b0178..1b6ccc0 100644
--- a/contrib/bind9/lib/isc/lib.c
+++ b/contrib/bind9/lib/isc/lib.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lib.c,v 1.14 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: lib.c,v 1.16 2009-09-02 23:48:02 tbox Exp $ */
/*! \file */
@@ -24,9 +24,15 @@
#include <stdio.h>
#include <stdlib.h>
-#include <isc/once.h>
-#include <isc/msgs.h>
+#include <isc/app.h>
#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/once.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
/***
*** Globals
@@ -41,7 +47,6 @@ LIBISC_EXTERNAL_DATA isc_msgcat_t * isc_msgcat = NULL;
static isc_once_t msgcat_once = ISC_ONCE_INIT;
-
/***
*** Functions
***/
@@ -77,3 +82,22 @@ isc_lib_initmsgcat(void) {
abort();
}
}
+
+#ifndef BIND9
+static isc_once_t register_once = ISC_ONCE_INIT;
+
+static void
+do_register(void) {
+ RUNTIME_CHECK(isc__mem_register() == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc__app_register() == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc__task_register() == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc__socket_register() == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc__timer_register() == ISC_R_SUCCESS);
+}
+
+void
+isc_lib_register() {
+ RUNTIME_CHECK(isc_once_do(&register_once, do_register)
+ == ISC_R_SUCCESS);
+}
+#endif
diff --git a/contrib/bind9/lib/isc/log.c b/contrib/bind9/lib/isc/log.c
index 121bd25..7ef6692 100644
--- a/contrib/bind9/lib/isc/log.c
+++ b/contrib/bind9/lib/isc/log.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.c,v 1.94.332.5 2009-02-16 02:04:05 marka Exp $ */
+/* $Id: log.c,v 1.99 2009-02-16 02:01:16 marka Exp $ */
/*! \file
* \author Principal Authors: DCL */
diff --git a/contrib/bind9/lib/isc/md5.c b/contrib/bind9/lib/isc/md5.c
index b9ec42c..b778177 100644
--- a/contrib/bind9/lib/isc/md5.c
+++ b/contrib/bind9/lib/isc/md5.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: md5.c,v 1.14 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: md5.c,v 1.16 2009-02-06 23:47:42 tbox Exp $ */
/*! \file
* This code implements the MD5 message-digest algorithm.
@@ -38,10 +38,35 @@
#include <isc/assertions.h>
#include <isc/md5.h>
+#include <isc/platform.h>
#include <isc/string.h>
#include <isc/types.h>
#include <isc/util.h>
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_md5_init(isc_md5_t *ctx) {
+ EVP_DigestInit(ctx, EVP_md5());
+}
+
+void
+isc_md5_invalidate(isc_md5_t *ctx) {
+ EVP_MD_CTX_cleanup(ctx);
+}
+
+void
+isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
+ EVP_DigestUpdate(ctx, (const void *) buf, (size_t) len);
+}
+
+void
+isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
+ EVP_DigestFinal(ctx, digest, NULL);
+}
+
+#else
+
static void
byteSwap(isc_uint32_t *buf, unsigned words)
{
@@ -249,3 +274,4 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(isc_md5_t)); /* In case it's sensitive */
}
+#endif
diff --git a/contrib/bind9/lib/isc/mem.c b/contrib/bind9/lib/isc/mem.c
index aeacfc0..8311569 100644
--- a/contrib/bind9/lib/isc/mem.c
+++ b/contrib/bind9/lib/isc/mem.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mem.c,v 1.145.120.9 2010-08-11 23:45:49 tbox Exp $ */
+/* $Id: mem.c,v 1.160 2010-12-08 02:46:16 marka Exp $ */
/*! \file */
@@ -60,6 +60,9 @@ LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
/*
* Types.
*/
+typedef struct isc__mem isc__mem_t;
+typedef struct isc__mempool isc__mempool_t;
+
#if ISC_MEM_TRACKLINES
typedef struct debuglink debuglink_t;
struct debuglink {
@@ -89,7 +92,7 @@ typedef struct {
*/
union {
size_t size;
- isc_mem_t *ctx;
+ isc__mem_t *ctx;
char bytes[ALIGNMENT_SIZE];
} u;
} size_info;
@@ -110,7 +113,7 @@ typedef ISC_LIST(debuglink_t) debuglist_t;
/* List of all active memory contexts. */
-static ISC_LIST(isc_mem_t) contexts;
+static ISC_LIST(isc__mem_t) contexts;
static isc_once_t once = ISC_ONCE_INIT;
static isc_mutex_t lock;
@@ -120,8 +123,8 @@ static isc_mutex_t lock;
*/
static isc_uint64_t totallost;
-struct isc_mem {
- unsigned int magic;
+struct isc__mem {
+ isc_mem_t common;
isc_ondestroy_t ondestroy;
unsigned int flags;
isc_mutex_t lock;
@@ -144,7 +147,7 @@ struct isc_mem {
isc_boolean_t is_overmem;
isc_mem_water_t water;
void * water_arg;
- ISC_LIST(isc_mempool_t) pools;
+ ISC_LIST(isc__mempool_t) pools;
unsigned int poolcnt;
/* ISC_MEMFLAG_INTERNAL */
@@ -163,19 +166,19 @@ struct isc_mem {
#endif
unsigned int memalloc_failures;
- ISC_LINK(isc_mem_t) link;
+ ISC_LINK(isc__mem_t) link;
};
#define MEMPOOL_MAGIC ISC_MAGIC('M', 'E', 'M', 'p')
#define VALID_MEMPOOL(c) ISC_MAGIC_VALID(c, MEMPOOL_MAGIC)
-struct isc_mempool {
+struct isc__mempool {
/* always unlocked */
- unsigned int magic; /*%< magic number */
+ isc_mempool_t common; /*%< common header of mempool's */
isc_mutex_t *lock; /*%< optional lock */
- isc_mem_t *mctx; /*%< our memory context */
+ isc__mem_t *mctx; /*%< our memory context */
/*%< locked via the memory context's lock */
- ISC_LINK(isc_mempool_t) link; /*%< next pool in this mem context */
+ ISC_LINK(isc__mempool_t) link; /*%< next pool in this mem context */
/*%< optionally locked from here down */
element *items; /*%< low water item list */
size_t size; /*%< size of each item on this pool */
@@ -210,13 +213,187 @@ struct isc_mempool {
#define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e)
static void
-print_active(isc_mem_t *ctx, FILE *out);
+print_active(isc__mem_t *ctx, FILE *out);
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_MEMFUNC_SCOPE
+#else
+#define ISC_MEMFUNC_SCOPE static
+#endif
+
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_createx(size_t init_max_size, size_t target_size,
+ isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+ isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_createx2(size_t init_max_size, size_t target_size,
+ isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+ isc_mem_t **ctxp, unsigned int flags);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create2(size_t init_max_size, size_t target_size,
+ isc_mem_t **ctxp, unsigned int flags);
+ISC_MEMFUNC_SCOPE void
+isc__mem_attach(isc_mem_t *source, isc_mem_t **targetp);
+ISC_MEMFUNC_SCOPE void
+isc__mem_detach(isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE void
+isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_destroy(isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_get(isc_mem_t *ctx, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_stats(isc_mem_t *ctx, FILE *out);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_allocate(isc_mem_t *ctx, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mem_free(isc_mem_t *ctx, void *ptr FLARG);
+ISC_MEMFUNC_SCOPE char *
+isc___mem_strdup(isc_mem_t *mctx, const char *s FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setquota(isc_mem_t *ctx, size_t quota);
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_getquota(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_inuse(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE isc_boolean_t
+isc__mem_isovermem(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+ size_t hiwater, size_t lowater);
+ISC_MEMFUNC_SCOPE void
+isc__mem_waterack(isc_mem_t *ctx0, int flag);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setname(isc_mem_t *ctx, const char *name, void *tag);
+ISC_MEMFUNC_SCOPE const char *
+isc__mem_getname(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE void *
+isc__mem_gettag(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setname(isc_mempool_t *mpctx, const char *name);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_destroy(isc_mempool_t **mpctxp);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock);
+ISC_MEMFUNC_SCOPE void *
+isc___mempool_get(isc_mempool_t *mpctx FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mempool_put(isc_mempool_t *mpctx, void *mem FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreemax(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreecount(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getmaxalloc(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getallocated(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfillcount(isc_mempool_t *mpctx);
+#ifdef BIND9
+ISC_MEMFUNC_SCOPE void
+isc__mem_printactive(isc_mem_t *ctx0, FILE *file);
+ISC_MEMFUNC_SCOPE void
+isc__mem_printallactive(FILE *file);
+ISC_MEMFUNC_SCOPE void
+isc__mem_checkdestroyed(FILE *file);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mem_references(isc_mem_t *ctx0);
+#endif
+
+static struct isc__memmethods {
+ isc_memmethods_t methods;
+
+ /*%
+ * The following are defined just for avoiding unused static functions.
+ */
+#ifndef BIND9
+ void *createx, *create, *create2, *ondestroy, *stats,
+ *setquota, *getquota, *setname, *getname, *gettag;
+#endif
+} memmethods = {
+ {
+ isc__mem_attach,
+ isc__mem_detach,
+ isc__mem_destroy,
+ isc___mem_get,
+ isc___mem_put,
+ isc___mem_putanddetach,
+ isc___mem_allocate,
+ isc___mem_reallocate,
+ isc___mem_strdup,
+ isc___mem_free,
+ isc__mem_setdestroycheck,
+ isc__mem_setwater,
+ isc__mem_waterack,
+ isc__mem_inuse,
+ isc__mem_isovermem,
+ isc__mempool_create
+ }
+#ifndef BIND9
+ ,
+ (void *)isc__mem_createx, (void *)isc__mem_create,
+ (void *)isc__mem_create2, (void *)isc__mem_ondestroy,
+ (void *)isc__mem_stats, (void *)isc__mem_setquota,
+ (void *)isc__mem_getquota, (void *)isc__mem_setname,
+ (void *)isc__mem_getname, (void *)isc__mem_gettag
+#endif
+};
+
+static struct isc__mempoolmethods {
+ isc_mempoolmethods_t methods;
+
+ /*%
+ * The following are defined just for avoiding unused static functions.
+ */
+#ifndef BIND9
+ void *getfreemax, *getfreecount, *getmaxalloc, *getfillcount;
+#endif
+} mempoolmethods = {
+ {
+ isc__mempool_destroy,
+ isc___mempool_get,
+ isc___mempool_put,
+ isc__mempool_getallocated,
+ isc__mempool_setmaxalloc,
+ isc__mempool_setfreemax,
+ isc__mempool_setname,
+ isc__mempool_associatelock,
+ isc__mempool_setfillcount
+ }
+#ifndef BIND9
+ ,
+ (void *)isc__mempool_getfreemax, (void *)isc__mempool_getfreecount,
+ (void *)isc__mempool_getmaxalloc, (void *)isc__mempool_getfillcount
+#endif
+};
/*!
* mctx must be locked.
*/
static inline void
-add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
+add_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size
FLARG)
{
debuglink_t *dl;
@@ -276,7 +453,7 @@ add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
}
static inline void
-delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size,
+delete_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size,
const char *file, unsigned int line)
{
debuglink_t *dl;
@@ -347,7 +524,7 @@ quantize(size_t size) {
}
static inline isc_boolean_t
-more_basic_blocks(isc_mem_t *ctx) {
+more_basic_blocks(isc__mem_t *ctx) {
void *new;
unsigned char *curr, *next;
unsigned char *first, *last;
@@ -417,7 +594,7 @@ more_basic_blocks(isc_mem_t *ctx) {
}
static inline isc_boolean_t
-more_frags(isc_mem_t *ctx, size_t new_size) {
+more_frags(isc__mem_t *ctx, size_t new_size) {
int i, frags;
size_t total_size;
void *new;
@@ -479,7 +656,7 @@ more_frags(isc_mem_t *ctx, size_t new_size) {
}
static inline void *
-mem_getunlocked(isc_mem_t *ctx, size_t size) {
+mem_getunlocked(isc__mem_t *ctx, size_t size) {
size_t new_size = quantize(size);
void *ret;
@@ -560,7 +737,7 @@ check_overrun(void *mem, size_t size, size_t new_size) {
#endif
static inline void
-mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
+mem_putunlocked(isc__mem_t *ctx, void *mem, size_t size) {
size_t new_size = quantize(size);
if (size == ctx->max_size || new_size >= ctx->max_size) {
@@ -608,7 +785,7 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
* Perform a malloc, doing memory filling and overrun detection as necessary.
*/
static inline void *
-mem_get(isc_mem_t *ctx, size_t size) {
+mem_get(isc__mem_t *ctx, size_t size) {
char *ret;
#if ISC_MEM_CHECKOVERRUN
@@ -636,7 +813,7 @@ mem_get(isc_mem_t *ctx, size_t size) {
* Perform a free, doing memory filling and overrun detection as necessary.
*/
static inline void
-mem_put(isc_mem_t *ctx, void *mem, size_t size) {
+mem_put(isc__mem_t *ctx, void *mem, size_t size) {
#if ISC_MEM_CHECKOVERRUN
INSIST(((unsigned char *)mem)[size] == 0xbe);
#endif
@@ -652,7 +829,7 @@ mem_put(isc_mem_t *ctx, void *mem, size_t size) {
* Update internal counters after a memory get.
*/
static inline void
-mem_getstats(isc_mem_t *ctx, size_t size) {
+mem_getstats(isc__mem_t *ctx, size_t size) {
ctx->total += size;
ctx->inuse += size;
@@ -669,7 +846,7 @@ mem_getstats(isc_mem_t *ctx, size_t size) {
* Update internal counters after a memory put.
*/
static inline void
-mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) {
+mem_putstats(isc__mem_t *ctx, void *ptr, size_t size) {
UNUSED(ptr);
INSIST(ctx->inuse >= size);
@@ -713,22 +890,22 @@ initialize_action(void) {
* Public.
*/
-isc_result_t
-isc_mem_createx(size_t init_max_size, size_t target_size,
- isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
- isc_mem_t **ctxp)
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_createx(size_t init_max_size, size_t target_size,
+ isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+ isc_mem_t **ctxp)
{
- return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree,
- arg, ctxp, ISC_MEMFLAG_DEFAULT));
+ return (isc__mem_createx2(init_max_size, target_size, memalloc, memfree,
+ arg, ctxp, ISC_MEMFLAG_DEFAULT));
}
-isc_result_t
-isc_mem_createx2(size_t init_max_size, size_t target_size,
- isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
- isc_mem_t **ctxp, unsigned int flags)
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_createx2(size_t init_max_size, size_t target_size,
+ isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+ isc_mem_t **ctxp, unsigned int flags)
{
- isc_mem_t *ctx;
+ isc__mem_t *ctx;
isc_result_t result;
REQUIRE(ctxp != NULL && *ctxp == NULL);
@@ -769,7 +946,9 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
ctx->is_overmem = ISC_FALSE;
ctx->water = NULL;
ctx->water_arg = NULL;
- ctx->magic = MEM_MAGIC;
+ ctx->common.impmagic = MEM_MAGIC;
+ ctx->common.magic = ISCAPI_MCTX_MAGIC;
+ ctx->common.methods = (isc_memmethods_t *)&memmethods;
isc_ondestroy_init(&ctx->ondestroy);
ctx->memalloc = memalloc;
ctx->memfree = memfree;
@@ -834,7 +1013,7 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
ISC_LIST_INITANDAPPEND(contexts, ctx, link);
UNLOCK(&lock);
- *ctxp = ctx;
+ *ctxp = (isc_mem_t *)ctx;
return (ISC_R_SUCCESS);
error:
@@ -855,26 +1034,24 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
return (result);
}
-isc_result_t
-isc_mem_create(size_t init_max_size, size_t target_size,
- isc_mem_t **ctxp)
-{
- return (isc_mem_createx2(init_max_size, target_size,
- default_memalloc, default_memfree, NULL,
- ctxp, ISC_MEMFLAG_DEFAULT));
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp) {
+ return (isc__mem_createx2(init_max_size, target_size,
+ default_memalloc, default_memfree, NULL,
+ ctxp, ISC_MEMFLAG_DEFAULT));
}
-isc_result_t
-isc_mem_create2(size_t init_max_size, size_t target_size,
- isc_mem_t **ctxp, unsigned int flags)
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create2(size_t init_max_size, size_t target_size,
+ isc_mem_t **ctxp, unsigned int flags)
{
- return (isc_mem_createx2(init_max_size, target_size,
- default_memalloc, default_memfree, NULL,
- ctxp, flags));
+ return (isc__mem_createx2(init_max_size, target_size,
+ default_memalloc, default_memfree, NULL,
+ ctxp, flags));
}
static void
-destroy(isc_mem_t *ctx) {
+destroy(isc__mem_t *ctx) {
unsigned int i;
isc_ondestroy_t ondest;
@@ -883,7 +1060,8 @@ destroy(isc_mem_t *ctx) {
totallost += ctx->inuse;
UNLOCK(&lock);
- ctx->magic = 0;
+ ctx->common.impmagic = 0;
+ ctx->common.magic = 0;
INSIST(ISC_LIST_EMPTY(ctx->pools));
@@ -941,8 +1119,10 @@ destroy(isc_mem_t *ctx) {
isc_ondestroy_notify(&ondest, ctx);
}
-void
-isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) {
+ isc__mem_t *source = (isc__mem_t *)source0;
+
REQUIRE(VALID_CONTEXT(source));
REQUIRE(targetp != NULL && *targetp == NULL);
@@ -950,16 +1130,16 @@ isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
source->references++;
MCTXUNLOCK(source, &source->lock);
- *targetp = source;
+ *targetp = (isc_mem_t *)source;
}
-void
-isc_mem_detach(isc_mem_t **ctxp) {
- isc_mem_t *ctx;
+ISC_MEMFUNC_SCOPE void
+isc__mem_detach(isc_mem_t **ctxp) {
+ isc__mem_t *ctx;
isc_boolean_t want_destroy = ISC_FALSE;
REQUIRE(ctxp != NULL);
- ctx = *ctxp;
+ ctx = (isc__mem_t *)*ctxp;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
@@ -985,15 +1165,15 @@ isc_mem_detach(isc_mem_t **ctxp) {
* isc_mem_detach(&mctx);
*/
-void
-isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
- isc_mem_t *ctx;
+ISC_MEMFUNC_SCOPE void
+isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
+ isc__mem_t *ctx;
isc_boolean_t want_destroy = ISC_FALSE;
size_info *si;
size_t oldsize;
REQUIRE(ctxp != NULL);
- ctx = *ctxp;
+ ctx = (isc__mem_t *)*ctxp;
REQUIRE(VALID_CONTEXT(ctx));
REQUIRE(ptr != NULL);
@@ -1011,7 +1191,7 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
oldsize -= ALIGNMENT_SIZE;
INSIST(oldsize == size);
}
- isc__mem_free(ctx, ptr FLARG_PASS);
+ isc_mem_free((isc_mem_t *)ctx, ptr);
MCTXLOCK(ctx, &ctx->lock);
ctx->references--;
@@ -1045,9 +1225,9 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
destroy(ctx);
}
-void
-isc_mem_destroy(isc_mem_t **ctxp) {
- isc_mem_t *ctx;
+ISC_MEMFUNC_SCOPE void
+isc__mem_destroy(isc_mem_t **ctxp) {
+ isc__mem_t *ctx;
/*
* This routine provides legacy support for callers who use mctxs
@@ -1055,7 +1235,7 @@ isc_mem_destroy(isc_mem_t **ctxp) {
*/
REQUIRE(ctxp != NULL);
- ctx = *ctxp;
+ ctx = (isc__mem_t *)*ctxp;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
@@ -1072,8 +1252,9 @@ isc_mem_destroy(isc_mem_t **ctxp) {
*ctxp = NULL;
}
-isc_result_t
-isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_ondestroy(isc_mem_t *ctx0, isc_task_t *task, isc_event_t **event) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
isc_result_t res;
MCTXLOCK(ctx, &ctx->lock);
@@ -1083,16 +1264,16 @@ isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
return (res);
}
-
-void *
-isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
+ISC_MEMFUNC_SCOPE void *
+isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
void *ptr;
isc_boolean_t call_water = ISC_FALSE;
REQUIRE(VALID_CONTEXT(ctx));
if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)
- return (isc__mem_allocate(ctx, size FLARG_PASS));
+ return (isc__mem_allocate(ctx0, size FLARG_PASS));
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(ctx, &ctx->lock);
@@ -1128,9 +1309,9 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
return (ptr);
}
-void
-isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
-{
+ISC_MEMFUNC_SCOPE void
+isc___mem_put(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
isc_boolean_t call_water = ISC_FALSE;
size_info *si;
size_t oldsize;
@@ -1146,7 +1327,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
oldsize -= ALIGNMENT_SIZE;
INSIST(oldsize == size);
}
- isc__mem_free(ctx, ptr FLARG_PASS);
+ isc_mem_free((isc_mem_t *)ctx, ptr);
return;
}
@@ -1181,8 +1362,10 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
}
-void
-isc_mem_waterack(isc_mem_t *ctx, int flag) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_waterack(isc_mem_t *ctx0, int flag) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
@@ -1195,7 +1378,7 @@ isc_mem_waterack(isc_mem_t *ctx, int flag) {
#if ISC_MEM_TRACKLINES
static void
-print_active(isc_mem_t *mctx, FILE *out) {
+print_active(isc__mem_t *mctx, FILE *out) {
if (mctx->debuglist != NULL) {
debuglink_t *dl;
unsigned int i, j;
@@ -1237,11 +1420,12 @@ print_active(isc_mem_t *mctx, FILE *out) {
/*
* Print the stats[] on the stream "out" with suitable formatting.
*/
-void
-isc_mem_stats(isc_mem_t *ctx, FILE *out) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_stats(isc_mem_t *ctx0, FILE *out) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
size_t i;
const struct stats *s;
- const isc_mempool_t *pool;
+ const isc__mempool_t *pool;
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
@@ -1314,7 +1498,8 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
*/
static void *
-isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
+isc__mem_allocateunlocked(isc_mem_t *ctx0, size_t size) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
size_info *si;
size += ALIGNMENT_SIZE;
@@ -1336,8 +1521,9 @@ isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
return (&si[1]);
}
-void *
-isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
+ISC_MEMFUNC_SCOPE void *
+isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
size_info *si;
isc_boolean_t call_water = ISC_FALSE;
@@ -1345,9 +1531,9 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
MCTXLOCK(ctx, &ctx->lock);
- si = isc__mem_allocateunlocked(ctx, size);
+ si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size);
} else {
- si = isc__mem_allocateunlocked(ctx, size);
+ si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size);
MCTXLOCK(ctx, &ctx->lock);
if (si != NULL)
mem_getstats(ctx, si[-1].u.size);
@@ -1381,8 +1567,9 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
return (si);
}
-void *
-isc__mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG) {
+ISC_MEMFUNC_SCOPE void *
+isc___mem_reallocate(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
void *new_ptr = NULL;
size_t oldsize, copysize;
@@ -1400,23 +1587,24 @@ isc__mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG) {
* NULL if allocation fails or doesn't happen.
*/
if (size > 0U) {
- new_ptr = isc__mem_allocate(ctx, size FLARG_PASS);
+ new_ptr = isc__mem_allocate(ctx0, size FLARG_PASS);
if (new_ptr != NULL && ptr != NULL) {
oldsize = (((size_info *)ptr)[-1]).u.size;
INSIST(oldsize >= ALIGNMENT_SIZE);
oldsize -= ALIGNMENT_SIZE;
copysize = oldsize > size ? size : oldsize;
memcpy(new_ptr, ptr, copysize);
- isc__mem_free(ctx, ptr FLARG_PASS);
+ isc__mem_free(ctx0, ptr FLARG_PASS);
}
} else if (ptr != NULL)
- isc__mem_free(ctx, ptr FLARG_PASS);
+ isc__mem_free(ctx0, ptr FLARG_PASS);
return (new_ptr);
}
-void
-isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
+ISC_MEMFUNC_SCOPE void
+isc___mem_free(isc_mem_t *ctx0, void *ptr FLARG) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
size_info *si;
size_t size;
isc_boolean_t call_water= ISC_FALSE;
@@ -1472,8 +1660,9 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
* Other useful things.
*/
-char *
-isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
+ISC_MEMFUNC_SCOPE char *
+isc___mem_strdup(isc_mem_t *mctx0, const char *s FLARG) {
+ isc__mem_t *mctx = (isc__mem_t *)mctx0;
size_t len;
char *ns;
@@ -1482,7 +1671,7 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
len = strlen(s);
- ns = isc__mem_allocate(mctx, len + 1 FLARG_PASS);
+ ns = isc___mem_allocate((isc_mem_t *)mctx, len + 1 FLARG_PASS);
if (ns != NULL)
strncpy(ns, s, len + 1);
@@ -1490,8 +1679,10 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
return (ns);
}
-void
-isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_setdestroycheck(isc_mem_t *ctx0, isc_boolean_t flag) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
@@ -1504,8 +1695,10 @@ isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
* Quotas
*/
-void
-isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_setquota(isc_mem_t *ctx0, size_t quota) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
@@ -1514,8 +1707,9 @@ isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
MCTXUNLOCK(ctx, &ctx->lock);
}
-size_t
-isc_mem_getquota(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_getquota(isc_mem_t *ctx0) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
size_t quota;
REQUIRE(VALID_CONTEXT(ctx));
@@ -1528,8 +1722,9 @@ isc_mem_getquota(isc_mem_t *ctx) {
return (quota);
}
-size_t
-isc_mem_inuse(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_inuse(isc_mem_t *ctx0) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
size_t inuse;
REQUIRE(VALID_CONTEXT(ctx));
@@ -1542,10 +1737,11 @@ isc_mem_inuse(isc_mem_t *ctx) {
return (inuse);
}
-void
-isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+ISC_MEMFUNC_SCOPE void
+isc__mem_setwater(isc_mem_t *ctx0, isc_mem_water_t water, void *water_arg,
size_t hiwater, size_t lowater)
{
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
isc_boolean_t callwater = ISC_FALSE;
isc_mem_water_t oldwater;
void *oldwater_arg;
@@ -1580,8 +1776,10 @@ isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
(oldwater)(oldwater_arg, ISC_MEM_LOWATER);
}
-isc_boolean_t
-isc_mem_isovermem(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE isc_boolean_t
+isc__mem_isovermem(isc_mem_t *ctx0) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
REQUIRE(VALID_CONTEXT(ctx));
/*
@@ -1592,8 +1790,10 @@ isc_mem_isovermem(isc_mem_t *ctx) {
return (ctx->is_overmem);
}
-void
-isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_setname(isc_mem_t *ctx0, const char *name, void *tag) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
REQUIRE(VALID_CONTEXT(ctx));
LOCK(&ctx->lock);
@@ -1603,15 +1803,19 @@ isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) {
UNLOCK(&ctx->lock);
}
-const char *
-isc_mem_getname(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE const char *
+isc__mem_getname(isc_mem_t *ctx0) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
REQUIRE(VALID_CONTEXT(ctx));
return (ctx->name);
}
-void *
-isc_mem_gettag(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE void *
+isc__mem_gettag(isc_mem_t *ctx0) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
REQUIRE(VALID_CONTEXT(ctx));
return (ctx->tag);
@@ -1621,9 +1825,10 @@ isc_mem_gettag(isc_mem_t *ctx) {
* Memory pool stuff
*/
-isc_result_t
-isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
- isc_mempool_t *mpctx;
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) {
+ isc__mem_t *mctx = (isc__mem_t *)mctx0;
+ isc__mempool_t *mpctx;
REQUIRE(VALID_CONTEXT(mctx));
REQUIRE(size > 0U);
@@ -1633,11 +1838,13 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
* Allocate space for this pool, initialize values, and if all works
* well, attach to the memory context.
*/
- mpctx = isc_mem_get(mctx, sizeof(isc_mempool_t));
+ mpctx = isc_mem_get((isc_mem_t *)mctx, sizeof(isc__mempool_t));
if (mpctx == NULL)
return (ISC_R_NOMEMORY);
- mpctx->magic = MEMPOOL_MAGIC;
+ mpctx->common.methods = (isc_mempoolmethods_t *)&mempoolmethods;
+ mpctx->common.impmagic = MEMPOOL_MAGIC;
+ mpctx->common.magic = ISCAPI_MPOOL_MAGIC;
mpctx->lock = NULL;
mpctx->mctx = mctx;
mpctx->size = size;
@@ -1652,7 +1859,7 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
#endif
mpctx->items = NULL;
- *mpctxp = mpctx;
+ *mpctxp = (isc_mempool_t *)mpctx;
MCTXLOCK(mctx, &mctx->lock);
ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
@@ -1662,9 +1869,12 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
return (ISC_R_SUCCESS);
}
-void
-isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setname(isc_mempool_t *mpctx0, const char *name) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
REQUIRE(name != NULL);
+ REQUIRE(VALID_MEMPOOL(mpctx));
#if ISC_MEMPOOL_NAMES
if (mpctx->lock != NULL)
@@ -1681,20 +1891,20 @@ isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
#endif
}
-void
-isc_mempool_destroy(isc_mempool_t **mpctxp) {
- isc_mempool_t *mpctx;
- isc_mem_t *mctx;
+ISC_MEMFUNC_SCOPE void
+isc__mempool_destroy(isc_mempool_t **mpctxp) {
+ isc__mempool_t *mpctx;
+ isc__mem_t *mctx;
isc_mutex_t *lock;
element *item;
REQUIRE(mpctxp != NULL);
- mpctx = *mpctxp;
+ mpctx = (isc__mempool_t *)*mpctxp;
REQUIRE(VALID_MEMPOOL(mpctx));
#if ISC_MEMPOOL_NAMES
if (mpctx->allocated > 0)
UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_mempool_destroy(): mempool %s "
+ "isc__mempool_destroy(): mempool %s "
"leaked memory",
mpctx->name);
#endif
@@ -1734,9 +1944,10 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) {
mctx->poolcnt--;
MCTXUNLOCK(mctx, &mctx->lock);
- mpctx->magic = 0;
+ mpctx->common.impmagic = 0;
+ mpctx->common.magic = 0;
- isc_mem_put(mpctx->mctx, mpctx, sizeof(isc_mempool_t));
+ isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t));
if (lock != NULL)
UNLOCK(lock);
@@ -1744,8 +1955,10 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) {
*mpctxp = NULL;
}
-void
-isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_associatelock(isc_mempool_t *mpctx0, isc_mutex_t *lock) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
REQUIRE(VALID_MEMPOOL(mpctx));
REQUIRE(mpctx->lock == NULL);
REQUIRE(lock != NULL);
@@ -1753,10 +1966,11 @@ isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
mpctx->lock = lock;
}
-void *
-isc__mempool_get(isc_mempool_t *mpctx FLARG) {
+ISC_MEMFUNC_SCOPE void *
+isc___mempool_get(isc_mempool_t *mpctx0 FLARG) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
element *item;
- isc_mem_t *mctx;
+ isc__mem_t *mctx;
unsigned int i;
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1835,9 +2049,10 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) {
return (item);
}
-void
-isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
- isc_mem_t *mctx;
+ISC_MEMFUNC_SCOPE void
+isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+ isc__mem_t *mctx;
element *item;
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1892,8 +2107,10 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
* Quotas
*/
-void
-isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfreemax(isc_mempool_t *mpctx0, unsigned int limit) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
REQUIRE(VALID_MEMPOOL(mpctx));
if (mpctx->lock != NULL)
@@ -1905,8 +2122,9 @@ isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
UNLOCK(mpctx->lock);
}
-unsigned int
-isc_mempool_getfreemax(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreemax(isc_mempool_t *mpctx0) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
unsigned int freemax;
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1922,8 +2140,9 @@ isc_mempool_getfreemax(isc_mempool_t *mpctx) {
return (freemax);
}
-unsigned int
-isc_mempool_getfreecount(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreecount(isc_mempool_t *mpctx0) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
unsigned int freecount;
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1939,8 +2158,10 @@ isc_mempool_getfreecount(isc_mempool_t *mpctx) {
return (freecount);
}
-void
-isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setmaxalloc(isc_mempool_t *mpctx0, unsigned int limit) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
REQUIRE(limit > 0);
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1954,8 +2175,9 @@ isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
UNLOCK(mpctx->lock);
}
-unsigned int
-isc_mempool_getmaxalloc(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getmaxalloc(isc_mempool_t *mpctx0) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
unsigned int maxalloc;
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1971,8 +2193,9 @@ isc_mempool_getmaxalloc(isc_mempool_t *mpctx) {
return (maxalloc);
}
-unsigned int
-isc_mempool_getallocated(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getallocated(isc_mempool_t *mpctx0) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
unsigned int allocated;
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1988,8 +2211,10 @@ isc_mempool_getallocated(isc_mempool_t *mpctx) {
return (allocated);
}
-void
-isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfillcount(isc_mempool_t *mpctx0, unsigned int limit) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
REQUIRE(limit > 0);
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -2002,8 +2227,10 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
UNLOCK(mpctx->lock);
}
-unsigned int
-isc_mempool_getfillcount(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfillcount(isc_mempool_t *mpctx0) {
+ isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
unsigned int fillcount;
REQUIRE(VALID_MEMPOOL(mpctx));
@@ -2019,8 +2246,17 @@ isc_mempool_getfillcount(isc_mempool_t *mpctx) {
return (fillcount);
}
-void
-isc_mem_printactive(isc_mem_t *ctx, FILE *file) {
+#ifdef USE_MEMIMPREGISTER
+isc_result_t
+isc__mem_register() {
+ return (isc_mem_register(isc__mem_create2));
+}
+#endif
+
+#ifdef BIND9
+ISC_MEMFUNC_SCOPE void
+isc__mem_printactive(isc_mem_t *ctx0, FILE *file) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
REQUIRE(VALID_CONTEXT(ctx));
REQUIRE(file != NULL);
@@ -2033,12 +2269,12 @@ isc_mem_printactive(isc_mem_t *ctx, FILE *file) {
#endif
}
-void
-isc_mem_printallactive(FILE *file) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_printallactive(FILE *file) {
#if !ISC_MEM_TRACKLINES
UNUSED(file);
#else
- isc_mem_t *ctx;
+ isc__mem_t *ctx;
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
@@ -2053,15 +2289,15 @@ isc_mem_printallactive(FILE *file) {
#endif
}
-void
-isc_mem_checkdestroyed(FILE *file) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_checkdestroyed(FILE *file) {
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
LOCK(&lock);
if (!ISC_LIST_EMPTY(contexts)) {
#if ISC_MEM_TRACKLINES
- isc_mem_t *ctx;
+ isc__mem_t *ctx;
for (ctx = ISC_LIST_HEAD(contexts);
ctx != NULL;
@@ -2076,9 +2312,11 @@ isc_mem_checkdestroyed(FILE *file) {
UNLOCK(&lock);
}
-unsigned int
-isc_mem_references(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc_mem_references(isc_mem_t *ctx0) {
+ isc__mem_t *ctx = (isc__mem_t *)ctx0;
unsigned int references;
+
REQUIRE(VALID_CONTEXT(ctx));
MCTXLOCK(ctx, &ctx->lock);
@@ -2098,7 +2336,7 @@ typedef struct summarystat {
} summarystat_t;
static void
-renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
+renderctx(isc__mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
REQUIRE(VALID_CONTEXT(ctx));
xmlTextWriterStartElement(writer, ISC_XMLCHAR "context");
@@ -2184,7 +2422,7 @@ renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
void
isc_mem_renderxml(xmlTextWriterPtr writer) {
- isc_mem_t *ctx;
+ isc__mem_t *ctx;
summarystat_t summary;
isc_uint64_t lost;
@@ -2236,3 +2474,4 @@ isc_mem_renderxml(xmlTextWriterPtr writer) {
}
#endif /* HAVE_LIBXML2 */
+#endif /* BIND9 */
diff --git a/contrib/bind9/lib/isc/mem_api.c b/contrib/bind9/lib/isc/mem_api.c
new file mode 100644
index 0000000..638efcd
--- /dev/null
+++ b/contrib/bind9/lib/isc/mem_api.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2009, 2010 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: mem_api.c,v 1.8 2010-08-12 21:30:26 jinmei Exp $ */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/util.h>
+
+#if ISC_MEM_TRACKLINES
+#define FLARG_PASS , file, line
+#define FLARG , const char *file, unsigned int line
+#else
+#define FLARG_PASS
+#define FLARG
+#endif
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_memcreatefunc_t mem_createfunc = NULL;
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mem_register(isc_memcreatefunc_t createfunc) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+ LOCK(&createlock);
+ if (mem_createfunc == NULL)
+ mem_createfunc = createfunc;
+ else
+ result = ISC_R_EXISTS;
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+isc_result_t
+isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **mctxp) {
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(mem_createfunc != NULL);
+ result = (*mem_createfunc)(init_max_size, target_size, mctxp,
+ ISC_MEMFLAG_DEFAULT);
+
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+isc_result_t
+isc_mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp,
+ unsigned int flags)
+{
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(mem_createfunc != NULL);
+ result = (*mem_createfunc)(init_max_size, target_size, mctxp, flags);
+
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+void
+isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
+ REQUIRE(ISCAPI_MCTX_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ source->methods->attach(source, targetp);
+
+ ENSURE(*targetp == source);
+}
+
+void
+isc_mem_detach(isc_mem_t **mctxp) {
+ REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+ (*mctxp)->methods->detach(mctxp);
+
+ ENSURE(*mctxp == NULL);
+}
+
+void
+isc_mem_destroy(isc_mem_t **mctxp) {
+ REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+ (*mctxp)->methods->destroy(mctxp);
+
+ ENSURE(*mctxp == NULL);
+}
+
+void *
+isc__mem_get(isc_mem_t *mctx, size_t size FLARG) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return (mctx->methods->memget(mctx, size FLARG_PASS));
+}
+
+void
+isc__mem_put(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ mctx->methods->memput(mctx, ptr, size FLARG_PASS);
+}
+
+void
+isc__mem_putanddetach(isc_mem_t **mctxp, void *ptr, size_t size FLARG) {
+ REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+ (*mctxp)->methods->memputanddetach(mctxp, ptr, size FLARG_PASS);
+
+ /*
+ * XXX: We cannot always ensure *mctxp == NULL here
+ * (see lib/isc/mem.c).
+ */
+}
+
+void *
+isc__mem_allocate(isc_mem_t *mctx, size_t size FLARG) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return (mctx->methods->memallocate(mctx, size FLARG_PASS));
+}
+
+void *
+isc__mem_reallocate(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return (mctx->methods->memreallocate(mctx, ptr, size FLARG_PASS));
+}
+
+char *
+isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return (mctx->methods->memstrdup(mctx, s FLARG_PASS));
+}
+
+void
+isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ mctx->methods->memfree(mctx, ptr FLARG_PASS);
+}
+
+void
+isc_mem_setdestroycheck(isc_mem_t *mctx, isc_boolean_t flag) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ mctx->methods->setdestroycheck(mctx, flag);
+}
+
+void
+isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+ size_t hiwater, size_t lowater)
+{
+ REQUIRE(ISCAPI_MCTX_VALID(ctx));
+
+ ctx->methods->setwater(ctx, water, water_arg, hiwater, lowater);
+}
+
+void
+isc_mem_waterack(isc_mem_t *ctx, int flag) {
+ REQUIRE(ISCAPI_MCTX_VALID(ctx));
+
+ ctx->methods->waterack(ctx, flag);
+}
+
+size_t
+isc_mem_inuse(isc_mem_t *mctx) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return (mctx->methods->inuse(mctx));
+}
+
+isc_boolean_t
+isc_mem_isovermem(isc_mem_t *mctx) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return (mctx->methods->isovermem(mctx));
+}
+
+void
+isc_mem_setname(isc_mem_t *mctx, const char *name, void *tag) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ UNUSED(name);
+ UNUSED(tag);
+
+ return;
+}
+
+const char *
+isc_mem_getname(isc_mem_t *mctx) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return ("");
+}
+
+void *
+isc_mem_gettag(isc_mem_t *mctx) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return (NULL);
+}
+
+isc_result_t
+isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
+ REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+ return (mctx->methods->mpcreate(mctx, size, mpctxp));
+}
+
+void
+isc_mempool_destroy(isc_mempool_t **mpctxp) {
+ REQUIRE(mpctxp != NULL && ISCAPI_MPOOL_VALID(*mpctxp));
+
+ (*mpctxp)->methods->destroy(mpctxp);
+
+ ENSURE(*mpctxp == NULL);
+}
+
+void *
+isc__mempool_get(isc_mempool_t *mpctx FLARG) {
+ REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+ return (mpctx->methods->get(mpctx FLARG_PASS));
+}
+
+void
+isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
+ REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+ mpctx->methods->put(mpctx, mem FLARG_PASS);
+}
+
+unsigned int
+isc_mempool_getallocated(isc_mempool_t *mpctx) {
+ REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+ return (mpctx->methods->getallocated(mpctx));
+}
+
+void
+isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
+ REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+ mpctx->methods->setmaxalloc(mpctx, limit);
+}
+
+void
+isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
+ REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+ mpctx->methods->setfreemax(mpctx, limit);
+}
+
+void
+isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
+ REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+ mpctx->methods->setname(mpctx, name);
+}
+
+void
+isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
+ REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+ mpctx->methods->associatelock(mpctx, lock);
+}
+
+void
+isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
+ REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+ mpctx->methods->setfillcount(mpctx, limit);
+}
diff --git a/contrib/bind9/lib/isc/netaddr.c b/contrib/bind9/lib/isc/netaddr.c
index 92c4fe5..33dddb8 100644
--- a/contrib/bind9/lib/isc/netaddr.c
+++ b/contrib/bind9/lib/isc/netaddr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2010 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: netaddr.c,v 1.38 2007-06-18 23:47:44 tbox Exp $ */
+/* $Id: netaddr.c,v 1.41 2010-11-17 23:47:08 tbox Exp $ */
/*! \file */
@@ -303,18 +303,18 @@ isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
isc_result_t
isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
#ifdef ISC_PLATFORM_HAVESYSUNH
- if (strlen(path) > sizeof(netaddr->type.un) - 1)
- return (ISC_R_NOSPACE);
-
- memset(netaddr, 0, sizeof(*netaddr));
- netaddr->family = AF_UNIX;
- strcpy(netaddr->type.un, path);
- netaddr->zone = 0;
- return (ISC_R_SUCCESS);
-#else
+ if (strlen(path) > sizeof(netaddr->type.un) - 1)
+ return (ISC_R_NOSPACE);
+
+ memset(netaddr, 0, sizeof(*netaddr));
+ netaddr->family = AF_UNIX;
+ strcpy(netaddr->type.un, path);
+ netaddr->zone = 0;
+ return (ISC_R_SUCCESS);
+#else
UNUSED(netaddr);
UNUSED(path);
- return (ISC_R_NOTIMPLEMENTED);
+ return (ISC_R_NOTIMPLEMENTED);
#endif
}
diff --git a/contrib/bind9/lib/isc/nls/Makefile.in b/contrib/bind9/lib/isc/nls/Makefile.in
index c4ec7a1..bfd8dd0 100644
--- a/contrib/bind9/lib/isc/nls/Makefile.in
+++ b/contrib/bind9/lib/isc/nls/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007 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/or distribute this software for any
@@ -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.14 2007-06-19 23:47:18 tbox Exp $
+# $Id: Makefile.in,v 1.17 2009-12-05 23:31:41 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
diff --git a/contrib/bind9/lib/isc/nothreads/Makefile.in b/contrib/bind9/lib/isc/nothreads/Makefile.in
index 042cfce..29bacd6 100644
--- a/contrib/bind9/lib/isc/nothreads/Makefile.in
+++ b/contrib/bind9/lib/isc/nothreads/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007, 2010 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2000, 2001 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -13,11 +13,11 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.7.332.2 2010-06-09 23:48:16 tbox Exp $
+# $Id: Makefile.in,v 1.12 2010-06-09 23:50:58 tbox Exp $
-srcdir = @srcdir@
-VPATH = @srcdir@
top_srcdir = @top_srcdir@
+srcdir = @top_srcdir@/lib/isc/nothreads
+VPATH = @top_srcdir@/lib/isc/nothreads
CINCLUDES = -I${srcdir}/include \
-I${srcdir}/../unix/include \
diff --git a/contrib/bind9/lib/isc/powerpc/include/isc/atomic.h b/contrib/bind9/lib/isc/powerpc/include/isc/atomic.h
index 074fea1..2e11e39 100644
--- a/contrib/bind9/lib/isc/powerpc/include/isc/atomic.h
+++ b/contrib/bind9/lib/isc/powerpc/include/isc/atomic.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: atomic.h,v 1.6.332.2 2009-10-14 23:47:14 tbox Exp $ */
+/* $Id: atomic.h,v 1.8 2009-10-14 23:47:51 tbox Exp $ */
#ifndef ISC_ATOMIC_H
#define ISC_ATOMIC_H 1
diff --git a/contrib/bind9/lib/isc/print.c b/contrib/bind9/lib/isc/print.c
index 5d800f3..bd7b580 100644
--- a/contrib/bind9/lib/isc/print.c
+++ b/contrib/bind9/lib/isc/print.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: print.c,v 1.35.130.2 2010-10-18 23:46:17 tbox Exp $ */
+/* $Id: print.c,v 1.37 2010-10-18 23:47:08 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isc/pthreads/Makefile.in b/contrib/bind9/lib/isc/pthreads/Makefile.in
index 572d76c..7aae93d 100644
--- a/contrib/bind9/lib/isc/pthreads/Makefile.in
+++ b/contrib/bind9/lib/isc/pthreads/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2001 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -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.19 2007-06-19 23:47:18 tbox Exp $
+# $Id: Makefile.in,v 1.22 2009-12-05 23:31:41 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
diff --git a/contrib/bind9/lib/isc/pthreads/mutex.c b/contrib/bind9/lib/isc/pthreads/mutex.c
index efe38db..fa5a701 100644
--- a/contrib/bind9/lib/isc/pthreads/mutex.c
+++ b/contrib/bind9/lib/isc/pthreads/mutex.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mutex.c,v 1.16.112.2 2011-01-04 23:45:43 tbox Exp $ */
+/* $Id: mutex.c,v 1.18 2011-01-04 23:47:14 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isc/radix.c b/contrib/bind9/lib/isc/radix.c
index d72ed33..be2e841 100644
--- a/contrib/bind9/lib/isc/radix.c
+++ b/contrib/bind9/lib/isc/radix.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: radix.c,v 1.20.36.3 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: radix.c,v 1.23 2009-01-18 23:48:14 tbox Exp $ */
/*
* This source was adapted from MRT's RCS Ids:
diff --git a/contrib/bind9/lib/isc/random.c b/contrib/bind9/lib/isc/random.c
index 09145f4..f082fe6 100644
--- a/contrib/bind9/lib/isc/random.c
+++ b/contrib/bind9/lib/isc/random.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: random.c,v 1.25.332.2 2009-07-16 23:47:17 tbox Exp $ */
+/* $Id: random.c,v 1.28 2009-07-16 05:52:46 marka Exp $ */
/*! \file */
@@ -103,7 +103,7 @@ isc_uint32_t
isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) {
isc_uint32_t rnd;
- REQUIRE(jitter < max);
+ REQUIRE(jitter < max || (jitter == 0 && max == 0));
if (jitter == 0)
return (max);
diff --git a/contrib/bind9/lib/isc/rwlock.c b/contrib/bind9/lib/isc/rwlock.c
index 39b90d7..fce7516 100644
--- a/contrib/bind9/lib/isc/rwlock.c
+++ b/contrib/bind9/lib/isc/rwlock.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rwlock.c,v 1.44.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: rwlock.c,v 1.46 2009-01-18 23:48:14 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isc/sha1.c b/contrib/bind9/lib/isc/sha1.c
index 20ee28d..d72eb9c 100644
--- a/contrib/bind9/lib/isc/sha1.c
+++ b/contrib/bind9/lib/isc/sha1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 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: sha1.c,v 1.18 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: sha1.c,v 1.20 2009-02-06 23:47:42 tbox Exp $ */
/* $NetBSD: sha1.c,v 1.5 2000/01/22 22:19:14 mycroft Exp $ */
/* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */
@@ -38,11 +38,47 @@
#include "config.h"
#include <isc/assertions.h>
+#include <isc/platform.h>
#include <isc/sha1.h>
#include <isc/string.h>
#include <isc/types.h>
#include <isc/util.h>
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_sha1_init(isc_sha1_t *context)
+{
+ INSIST(context != NULL);
+
+ EVP_DigestInit(context, EVP_sha1());
+}
+
+void
+isc_sha1_invalidate(isc_sha1_t *context) {
+ EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha1_update(isc_sha1_t *context, const unsigned char *data,
+ unsigned int len)
+{
+ INSIST(context != 0);
+ INSIST(data != 0);
+
+ EVP_DigestUpdate(context, (const void *) data, (size_t) len);
+}
+
+void
+isc_sha1_final(isc_sha1_t *context, unsigned char *digest) {
+ INSIST(digest != 0);
+ INSIST(context != 0);
+
+ EVP_DigestFinal(context, digest, NULL);
+}
+
+#else
+
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/*@{*/
@@ -313,3 +349,4 @@ isc_sha1_final(isc_sha1_t *context, unsigned char *digest) {
memset(context, 0, sizeof(isc_sha1_t));
}
+#endif
diff --git a/contrib/bind9/lib/isc/sha2.c b/contrib/bind9/lib/isc/sha2.c
index 22f1d47..1dc05a70 100644
--- a/contrib/bind9/lib/isc/sha2.c
+++ b/contrib/bind9/lib/isc/sha2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-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
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sha2.c,v 1.13.332.4 2010-01-15 23:47:34 tbox Exp $ */
+/* $Id: sha2.c,v 1.18 2009-10-22 02:21:31 each Exp $ */
/* $FreeBSD$ */
/* $KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $ */
@@ -58,10 +58,169 @@
#include <config.h>
#include <isc/assertions.h>
+#include <isc/platform.h>
#include <isc/sha2.h>
#include <isc/string.h>
#include <isc/util.h>
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_sha224_init(isc_sha224_t *context) {
+ if (context == (isc_sha224_t *)0) {
+ return;
+ }
+ EVP_DigestInit(context, EVP_sha224());
+}
+
+void
+isc_sha224_invalidate(isc_sha224_t *context) {
+ EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
+ if (len == 0U) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha224_t *)0 && data != (isc_uint8_t*)0);
+
+ EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha224_t *)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (isc_uint8_t*)0) {
+ EVP_DigestFinal(context, digest, NULL);
+ } else {
+ EVP_MD_CTX_cleanup(context);
+ }
+}
+
+void
+isc_sha256_init(isc_sha256_t *context) {
+ if (context == (isc_sha256_t *)0) {
+ return;
+ }
+ EVP_DigestInit(context, EVP_sha256());
+}
+
+void
+isc_sha256_invalidate(isc_sha256_t *context) {
+ EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
+ if (len == 0U) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0);
+
+ EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha256_t *)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (isc_uint8_t*)0) {
+ EVP_DigestFinal(context, digest, NULL);
+ } else {
+ EVP_MD_CTX_cleanup(context);
+ }
+}
+
+void
+isc_sha512_init(isc_sha512_t *context) {
+ if (context == (isc_sha512_t *)0) {
+ return;
+ }
+ EVP_DigestInit(context, EVP_sha512());
+}
+
+void
+isc_sha512_invalidate(isc_sha512_t *context) {
+ EVP_MD_CTX_cleanup(context);
+}
+
+void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
+ if (len == 0U) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
+
+ EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha512_t *)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (isc_uint8_t*)0) {
+ EVP_DigestFinal(context, digest, NULL);
+ } else {
+ EVP_MD_CTX_cleanup(context);
+ }
+}
+
+void
+isc_sha384_init(isc_sha384_t *context) {
+ if (context == (isc_sha384_t *)0) {
+ return;
+ }
+ EVP_DigestInit(context, EVP_sha384());
+}
+
+void
+isc_sha384_invalidate(isc_sha384_t *context) {
+ EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
+ if (len == 0U) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
+
+ EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha384_t *)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (isc_uint8_t*)0) {
+ EVP_DigestFinal(context, digest, NULL);
+ } else {
+ EVP_MD_CTX_cleanup(context);
+ }
+}
+
+#else
+
/*
* UNROLLED TRANSFORM LOOP NOTE:
* You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
@@ -394,13 +553,6 @@ static const isc_uint64_t sha512_initial_hash_value[8] = {
};
#endif
-/*
- * Constant used by SHA256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char *sha2_hex_digits = "0123456789abcdef";
-
-
/*** SHA-224: *********************************************************/
void
@@ -432,41 +584,6 @@ isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
memset(sha256_digest, 0, ISC_SHA256_DIGESTLENGTH);
}
-char *
-isc_sha224_end(isc_sha224_t *context, char buffer[]) {
- isc_uint8_t digest[ISC_SHA224_DIGESTLENGTH], *d = digest;
- unsigned int i;
-
- /* Sanity check: */
- REQUIRE(context != (isc_sha224_t *)0);
-
- if (buffer != (char*)0) {
- isc_sha224_final(digest, context);
-
- for (i = 0; i < ISC_SHA224_DIGESTLENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- memset(context, 0, sizeof(context));
- }
- memset(digest, 0, ISC_SHA224_DIGESTLENGTH);
- return buffer;
-}
-
-char*
-isc_sha224_data(const isc_uint8_t *data, size_t len,
- char digest[ISC_SHA224_DIGESTSTRINGLENGTH])
-{
- isc_sha224_t context;
-
- isc_sha224_init(&context);
- isc_sha224_update(&context, data, len);
- return (isc_sha224_end(&context, digest));
-}
-
/*** SHA-256: *********************************************************/
void
isc_sha256_init(isc_sha256_t *context) {
@@ -479,6 +596,11 @@ isc_sha256_init(isc_sha256_t *context) {
context->bitcount = 0;
}
+void
+isc_sha256_invalidate(isc_sha256_t *context) {
+ memset(context, 0, sizeof(isc_sha256_t));
+}
+
#ifdef ISC_SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-256 round macros: */
@@ -656,11 +778,6 @@ isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
#endif /* ISC_SHA2_UNROLL_TRANSFORM */
void
-isc_sha256_invalidate(isc_sha256_t *context) {
- memset(context, 0, sizeof(isc_sha256_t));
-}
-
-void
isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
unsigned int freespace, usedspace;
@@ -782,42 +899,6 @@ isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
usedspace = 0;
}
-char *
-isc_sha256_end(isc_sha256_t *context, char buffer[]) {
- isc_uint8_t digest[ISC_SHA256_DIGESTLENGTH], *d = digest;
- unsigned int i;
-
- /* Sanity check: */
- REQUIRE(context != (isc_sha256_t *)0);
-
- if (buffer != (char*)0) {
- isc_sha256_final(digest, context);
-
- for (i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- memset(context, 0, sizeof(context));
- }
- memset(digest, 0, ISC_SHA256_DIGESTLENGTH);
- return buffer;
-}
-
-char *
-isc_sha256_data(const isc_uint8_t* data, size_t len,
- char digest[ISC_SHA256_DIGESTSTRINGLENGTH])
-{
- isc_sha256_t context;
-
- isc_sha256_init(&context);
- isc_sha256_update(&context, data, len);
- return (isc_sha256_end(&context, digest));
-}
-
-
/*** SHA-512: *********************************************************/
void
isc_sha512_init(isc_sha512_t *context) {
@@ -830,6 +911,11 @@ isc_sha512_init(isc_sha512_t *context) {
context->bitcount[0] = context->bitcount[1] = 0;
}
+void
+isc_sha512_invalidate(isc_sha512_t *context) {
+ memset(context, 0, sizeof(isc_sha512_t));
+}
+
#ifdef ISC_SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-512 round macros: */
@@ -1000,13 +1086,7 @@ isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
#endif /* ISC_SHA2_UNROLL_TRANSFORM */
-void
-isc_sha512_invalidate(isc_sha512_t *context) {
- memset(context, 0, sizeof(isc_sha512_t));
-}
-
-void
-isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
+void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
unsigned int freespace, usedspace;
if (len == 0U) {
@@ -1131,41 +1211,6 @@ void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
memset(context, 0, sizeof(context));
}
-char *
-isc_sha512_end(isc_sha512_t *context, char buffer[]) {
- isc_uint8_t digest[ISC_SHA512_DIGESTLENGTH], *d = digest;
- unsigned int i;
-
- /* Sanity check: */
- REQUIRE(context != (isc_sha512_t *)0);
-
- if (buffer != (char*)0) {
- isc_sha512_final(digest, context);
-
- for (i = 0; i < ISC_SHA512_DIGESTLENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char)0;
- } else {
- memset(context, 0, sizeof(context));
- }
- memset(digest, 0, ISC_SHA512_DIGESTLENGTH);
- return buffer;
-}
-
-char *
-isc_sha512_data(const isc_uint8_t *data, size_t len,
- char digest[ISC_SHA512_DIGESTSTRINGLENGTH])
-{
- isc_sha512_t context;
-
- isc_sha512_init(&context);
- isc_sha512_update(&context, data, len);
- return (isc_sha512_end(&context, digest));
-}
-
/*** SHA-384: *********************************************************/
void
@@ -1218,6 +1263,130 @@ isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
/* Zero out state data */
memset(context, 0, sizeof(context));
}
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+char *
+isc_sha224_end(isc_sha224_t *context, char buffer[]) {
+ isc_uint8_t digest[ISC_SHA224_DIGESTLENGTH], *d = digest;
+ unsigned int i;
+
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha224_t *)0);
+
+ if (buffer != (char*)0) {
+ isc_sha224_final(digest, context);
+
+ for (i = 0; i < ISC_SHA224_DIGESTLENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+ EVP_MD_CTX_cleanup(context);
+#else
+ memset(context, 0, sizeof(context));
+#endif
+ }
+ memset(digest, 0, ISC_SHA224_DIGESTLENGTH);
+ return buffer;
+}
+
+char *
+isc_sha224_data(const isc_uint8_t *data, size_t len,
+ char digest[ISC_SHA224_DIGESTSTRINGLENGTH])
+{
+ isc_sha224_t context;
+
+ isc_sha224_init(&context);
+ isc_sha224_update(&context, data, len);
+ return (isc_sha224_end(&context, digest));
+}
+
+char *
+isc_sha256_end(isc_sha256_t *context, char buffer[]) {
+ isc_uint8_t digest[ISC_SHA256_DIGESTLENGTH], *d = digest;
+ unsigned int i;
+
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha256_t *)0);
+
+ if (buffer != (char*)0) {
+ isc_sha256_final(digest, context);
+
+ for (i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+ EVP_MD_CTX_cleanup(context);
+#else
+ memset(context, 0, sizeof(context));
+#endif
+ }
+ memset(digest, 0, ISC_SHA256_DIGESTLENGTH);
+ return buffer;
+}
+
+char *
+isc_sha256_data(const isc_uint8_t* data, size_t len,
+ char digest[ISC_SHA256_DIGESTSTRINGLENGTH])
+{
+ isc_sha256_t context;
+
+ isc_sha256_init(&context);
+ isc_sha256_update(&context, data, len);
+ return (isc_sha256_end(&context, digest));
+}
+
+char *
+isc_sha512_end(isc_sha512_t *context, char buffer[]) {
+ isc_uint8_t digest[ISC_SHA512_DIGESTLENGTH], *d = digest;
+ unsigned int i;
+
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha512_t *)0);
+
+ if (buffer != (char*)0) {
+ isc_sha512_final(digest, context);
+
+ for (i = 0; i < ISC_SHA512_DIGESTLENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+ EVP_MD_CTX_cleanup(context);
+#else
+ memset(context, 0, sizeof(context));
+#endif
+ }
+ memset(digest, 0, ISC_SHA512_DIGESTLENGTH);
+ return buffer;
+}
+
+char *
+isc_sha512_data(const isc_uint8_t *data, size_t len,
+ char digest[ISC_SHA512_DIGESTSTRINGLENGTH])
+{
+ isc_sha512_t context;
+
+ isc_sha512_init(&context);
+ isc_sha512_update(&context, data, len);
+ return (isc_sha512_end(&context, digest));
+}
char *
isc_sha384_end(isc_sha384_t *context, char buffer[]) {
@@ -1237,13 +1406,17 @@ isc_sha384_end(isc_sha384_t *context, char buffer[]) {
}
*buffer = (char)0;
} else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+ EVP_MD_CTX_cleanup(context);
+#else
memset(context, 0, sizeof(context));
+#endif
}
memset(digest, 0, ISC_SHA384_DIGESTLENGTH);
return buffer;
}
-char*
+char *
isc_sha384_data(const isc_uint8_t *data, size_t len,
char digest[ISC_SHA384_DIGESTSTRINGLENGTH])
{
diff --git a/contrib/bind9/lib/isc/sockaddr.c b/contrib/bind9/lib/isc/sockaddr.c
index 19833e4..9661ee4 100644
--- a/contrib/bind9/lib/isc/sockaddr.c
+++ b/contrib/bind9/lib/isc/sockaddr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010 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: sockaddr.c,v 1.70 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: sockaddr.c,v 1.73 2010-11-17 23:47:09 tbox Exp $ */
/*! \file */
@@ -390,8 +390,8 @@ isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
#endif
sockaddr->type.sin6.sin6_port = htons(port);
break;
- default:
- INSIST(0);
+ default:
+ INSIST(0);
}
ISC_LINK_INIT(sockaddr, link);
}
diff --git a/contrib/bind9/lib/isc/socket_api.c b/contrib/bind9/lib/isc/socket_api.c
new file mode 100644
index 0000000..c1e5fd4
--- /dev/null
+++ b/contrib/bind9/lib/isc/socket_api.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 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: socket_api.c,v 1.5 2009-10-01 01:30:01 sar Exp $ */
+
+#include <config.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/socket.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_socketmgrcreatefunc_t socketmgr_createfunc = NULL;
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_register(isc_socketmgrcreatefunc_t createfunc) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+ LOCK(&createlock);
+ if (socketmgr_createfunc == NULL)
+ socketmgr_createfunc = createfunc;
+ else
+ result = ISC_R_EXISTS;
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+isc_result_t
+isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+ isc_socketmgr_t **managerp)
+{
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(socketmgr_createfunc != NULL);
+ result = (*socketmgr_createfunc)(mctx, managerp);
+
+ UNLOCK(&createlock);
+
+ if (result == ISC_R_SUCCESS)
+ isc_appctx_setsocketmgr(actx, *managerp);
+
+ return (result);
+}
+
+isc_result_t
+isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(socketmgr_createfunc != NULL);
+ result = (*socketmgr_createfunc)(mctx, managerp);
+
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+void
+isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
+ REQUIRE(managerp != NULL && ISCAPI_SOCKETMGR_VALID(*managerp));
+
+ (*managerp)->methods->destroy(managerp);
+
+ ENSURE(*managerp == NULL);
+}
+
+isc_result_t
+isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp)
+{
+ REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
+
+ return (manager->methods->socketcreate(manager, pf, type, socketp));
+}
+
+void
+isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ sock->methods->attach(sock, socketp);
+
+ ENSURE(*socketp == sock);
+}
+
+void
+isc_socket_detach(isc_socket_t **socketp) {
+ REQUIRE(socketp != NULL && ISCAPI_SOCKET_VALID(*socketp));
+
+ (*socketp)->methods->detach(socketp);
+
+ ENSURE(*socketp == NULL);
+}
+
+isc_result_t
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+ unsigned int options)
+{
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return (sock->methods->bind(sock, sockaddr, options));
+}
+
+isc_result_t
+isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
+ isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return (sock->methods->sendto(sock, region, task, action, arg, address,
+ pktinfo));
+}
+
+isc_result_t
+isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task,
+ isc_taskaction_t action, const void *arg)
+{
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return (sock->methods->connect(sock, addr, task, action, arg));
+}
+
+isc_result_t
+isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return (sock->methods->recv(sock, region, minimum, task, action, arg));
+}
+
+void
+isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ sock->methods->cancel(sock, task, how);
+}
+
+isc_result_t
+isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return (sock->methods->getsockname(sock, addressp));
+}
+
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ sock->methods->ipv6only(sock, yes);
+}
+
+isc_sockettype_t
+isc_socket_gettype(isc_socket_t *sock) {
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return (sock->methods->gettype(sock));
+}
+
+void
+isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+ REQUIRE(ISCAPI_SOCKET_VALID(socket));
+
+ UNUSED(socket); /* in case REQUIRE() is empty */
+ UNUSED(name);
+ UNUSED(tag);
+}
+
+isc_result_t
+isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
+ isc_sockfdwatch_t callback, void *cbarg,
+ isc_task_t *task, isc_socket_t **socketp)
+{
+ REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
+
+ return (manager->methods->fdwatchcreate(manager, fd, flags,
+ callback, cbarg, task,
+ socketp));
+}
+
+isc_result_t
+isc_socket_fdwatchpoke(isc_socket_t *sock, int flags)
+{
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return(sock->methods->fdwatchpoke(sock, flags));
+}
diff --git a/contrib/bind9/lib/isc/stats.c b/contrib/bind9/lib/isc/stats.c
index ac66bcf..e72fb54 100644
--- a/contrib/bind9/lib/isc/stats.c
+++ b/contrib/bind9/lib/isc/stats.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: stats.c,v 1.3.6.2 2009-01-29 23:47:44 tbox Exp $ */
+/* $Id: stats.c,v 1.3 2009-01-27 23:47:54 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isc/task.c b/contrib/bind9/lib/isc/task.c
index 5d87f21..a9dfd1f 100644
--- a/contrib/bind9/lib/isc/task.c
+++ b/contrib/bind9/lib/isc/task.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: task.c,v 1.107.120.2 2010-12-03 23:45:47 tbox Exp $ */
+/* $Id: task.c,v 1.115.14.1.2.1 2011-06-02 23:47:36 tbox Exp $ */
/*! \file
* \author Principal Author: Bob Halley
@@ -40,9 +40,33 @@
#include <isc/util.h>
#include <isc/xml.h>
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef OPENSSL_LEAKS
+#include <openssl/err.h>
+#endif
+
+/*%
+ * For BIND9 internal applications:
+ * when built with threads we use multiple worker threads shared by the whole
+ * application.
+ * when built without threads we share a single global task manager and use
+ * an integrated event loop for socket, timer, and other generic task events.
+ * For generic library:
+ * we don't use either of them: an application can have multiple task managers
+ * whether or not it's threaded, and if the application is threaded each thread
+ * is expected to have a separate manager; no "worker threads" are shared by
+ * the application threads.
+ */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_WORKER_THREADS
+#else
+#define USE_SHARED_MANAGER
+#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* BIND9 */
+
+#ifndef USE_WORKER_THREADS
#include "task_p.h"
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
#ifdef ISC_TASK_TRACE
#define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
@@ -66,7 +90,7 @@ typedef enum {
task_state_done
} task_state_t;
-#ifdef HAVE_LIBXML2
+#if defined(HAVE_LIBXML2) && defined(BIND9)
static const char *statenames[] = {
"idle", "ready", "running", "done",
};
@@ -75,10 +99,13 @@ static const char *statenames[] = {
#define TASK_MAGIC ISC_MAGIC('T', 'A', 'S', 'K')
#define VALID_TASK(t) ISC_MAGIC_VALID(t, TASK_MAGIC)
-struct isc_task {
+typedef struct isc__task isc__task_t;
+typedef struct isc__taskmgr isc__taskmgr_t;
+
+struct isc__task {
/* Not locked. */
- unsigned int magic;
- isc_taskmgr_t * manager;
+ isc_task_t common;
+ isc__taskmgr_t * manager;
isc_mutex_t lock;
/* Locked by task lock. */
task_state_t state;
@@ -91,8 +118,8 @@ struct isc_task {
char name[16];
void * tag;
/* Locked by task manager lock. */
- LINK(isc_task_t) link;
- LINK(isc_task_t) ready_link;
+ LINK(isc__task_t) link;
+ LINK(isc__task_t) ready_link;
};
#define TASK_F_SHUTTINGDOWN 0x01
@@ -103,9 +130,11 @@ struct isc_task {
#define TASK_MANAGER_MAGIC ISC_MAGIC('T', 'S', 'K', 'M')
#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TASK_MANAGER_MAGIC)
-struct isc_taskmgr {
+typedef ISC_LIST(isc__task_t) isc__tasklist_t;
+
+struct isc__taskmgr {
/* Not locked. */
- unsigned int magic;
+ isc_taskmgr_t common;
isc_mem_t * mctx;
isc_mutex_t lock;
#ifdef ISC_PLATFORM_USETHREADS
@@ -114,8 +143,8 @@ struct isc_taskmgr {
#endif /* ISC_PLATFORM_USETHREADS */
/* Locked by task manager lock. */
unsigned int default_quantum;
- LIST(isc_task_t) tasks;
- isc_tasklist_t ready_tasks;
+ LIST(isc__task_t) tasks;
+ isc__tasklist_t ready_tasks;
#ifdef ISC_PLATFORM_USETHREADS
isc_condition_t work_available;
isc_condition_t exclusive_granted;
@@ -123,7 +152,7 @@ struct isc_taskmgr {
unsigned int tasks_running;
isc_boolean_t exclusive_requested;
isc_boolean_t exiting;
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
unsigned int refs;
#endif /* ISC_PLATFORM_USETHREADS */
};
@@ -132,17 +161,116 @@ struct isc_taskmgr {
#define DEFAULT_DEFAULT_QUANTUM 5
#define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks))
-#ifndef ISC_PLATFORM_USETHREADS
-static isc_taskmgr_t *taskmgr = NULL;
-#endif /* ISC_PLATFORM_USETHREADS */
+#ifdef USE_SHARED_MANAGER
+static isc__taskmgr_t *taskmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_TASKFUNC_SCOPE
+#else
+#define ISC_TASKFUNC_SCOPE static
+#endif
+
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
+ isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_attach(isc_task_t *source0, isc_task_t **targetp);
+ISC_TASKFUNC_SCOPE void
+isc__task_detach(isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_send(isc_task_t *task0, isc_event_t **eventp);
+ISC_TASKFUNC_SCOPE void
+isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first,
+ isc_eventtype_t last, void *tag);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
+ void *tag);
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_purgeevent(isc_task_t *task0, isc_event_t *event);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
+ isc_eventtype_t last, void *tag,
+ isc_eventlist_t *events);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+ void *tag, isc_eventlist_t *events);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action,
+ const void *arg);
+ISC_TASKFUNC_SCOPE void
+isc__task_shutdown(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__task_destroy(isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_setname(isc_task_t *task0, const char *name, void *tag);
+ISC_TASKFUNC_SCOPE const char *
+isc__task_getname(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void *
+isc__task_gettag(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+ unsigned int default_quantum, isc_taskmgr_t **managerp);
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_destroy(isc_taskmgr_t **managerp);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_beginexclusive(isc_task_t *task);
+ISC_TASKFUNC_SCOPE void
+isc__task_endexclusive(isc_task_t *task0);
+
+static struct isc__taskmethods {
+ isc_taskmethods_t methods;
+
+ /*%
+ * The following are defined just for avoiding unused static functions.
+ */
+#ifndef BIND9
+ void *purgeevent, *unsendrange, *getname, *gettag, *getcurrenttime;
+#endif
+} taskmethods = {
+ {
+ isc__task_attach,
+ isc__task_detach,
+ isc__task_destroy,
+ isc__task_send,
+ isc__task_sendanddetach,
+ isc__task_unsend,
+ isc__task_onshutdown,
+ isc__task_shutdown,
+ isc__task_setname,
+ isc__task_purge,
+ isc__task_purgerange,
+ isc__task_beginexclusive,
+ isc__task_endexclusive
+ }
+#ifndef BIND9
+ ,
+ (void *)isc__task_purgeevent, (void *)isc__task_unsendrange,
+ (void *)isc__task_getname, (void *)isc__task_gettag,
+ (void *)isc__task_getcurrenttime
+#endif
+};
+
+static isc_taskmgrmethods_t taskmgrmethods = {
+ isc__taskmgr_destroy,
+ isc__task_create
+};
/***
*** Tasks.
***/
static void
-task_finished(isc_task_t *task) {
- isc_taskmgr_t *manager = task->manager;
+task_finished(isc__task_t *task) {
+ isc__taskmgr_t *manager = task->manager;
REQUIRE(EMPTY(task->events));
REQUIRE(EMPTY(task->on_shutdown));
@@ -153,7 +281,7 @@ task_finished(isc_task_t *task) {
LOCK(&manager->lock);
UNLINK(manager->tasks, task, link);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
if (FINISHED(manager)) {
/*
* All tasks have completed and the
@@ -163,19 +291,21 @@ task_finished(isc_task_t *task) {
*/
BROADCAST(&manager->work_available);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
UNLOCK(&manager->lock);
DESTROYLOCK(&task->lock);
- task->magic = 0;
+ task->common.impmagic = 0;
+ task->common.magic = 0;
isc_mem_put(manager->mctx, task, sizeof(*task));
}
-isc_result_t
-isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
- isc_task_t **taskp)
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
+ isc_task_t **taskp)
{
- isc_task_t *task;
+ isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+ isc__task_t *task;
isc_boolean_t exiting;
isc_result_t result;
@@ -220,14 +350,17 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
return (ISC_R_SHUTTINGDOWN);
}
- task->magic = TASK_MAGIC;
- *taskp = task;
+ task->common.methods = (isc_taskmethods_t *)&taskmethods;
+ task->common.magic = ISCAPI_TASK_MAGIC;
+ task->common.impmagic = TASK_MAGIC;
+ *taskp = (isc_task_t *)task;
return (ISC_R_SUCCESS);
}
-void
-isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
+ISC_TASKFUNC_SCOPE void
+isc__task_attach(isc_task_t *source0, isc_task_t **targetp) {
+ isc__task_t *source = (isc__task_t *)source0;
/*
* Attach *targetp to source.
@@ -242,11 +375,11 @@ isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
source->references++;
UNLOCK(&source->lock);
- *targetp = source;
+ *targetp = (isc_task_t *)source;
}
static inline isc_boolean_t
-task_shutdown(isc_task_t *task) {
+task_shutdown(isc__task_t *task) {
isc_boolean_t was_idle = ISC_FALSE;
isc_event_t *event, *prev;
@@ -283,8 +416,8 @@ task_shutdown(isc_task_t *task) {
}
static inline void
-task_ready(isc_task_t *task) {
- isc_taskmgr_t *manager = task->manager;
+task_ready(isc__task_t *task) {
+ isc__taskmgr_t *manager = task->manager;
REQUIRE(VALID_MANAGER(manager));
REQUIRE(task->state == task_state_ready);
@@ -294,15 +427,15 @@ task_ready(isc_task_t *task) {
LOCK(&manager->lock);
ENQUEUE(manager->ready_tasks, task, ready_link);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
SIGNAL(&manager->work_available);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
UNLOCK(&manager->lock);
}
static inline isc_boolean_t
-task_detach(isc_task_t *task) {
+task_detach(isc__task_t *task) {
/*
* Caller must be holding the task lock.
@@ -330,9 +463,9 @@ task_detach(isc_task_t *task) {
return (ISC_FALSE);
}
-void
-isc_task_detach(isc_task_t **taskp) {
- isc_task_t *task;
+ISC_TASKFUNC_SCOPE void
+isc__task_detach(isc_task_t **taskp) {
+ isc__task_t *task;
isc_boolean_t was_idle;
/*
@@ -340,7 +473,7 @@ isc_task_detach(isc_task_t **taskp) {
*/
REQUIRE(taskp != NULL);
- task = *taskp;
+ task = (isc__task_t *)*taskp;
REQUIRE(VALID_TASK(task));
XTRACE("isc_task_detach");
@@ -356,7 +489,7 @@ isc_task_detach(isc_task_t **taskp) {
}
static inline isc_boolean_t
-task_send(isc_task_t *task, isc_event_t **eventp) {
+task_send(isc__task_t *task, isc_event_t **eventp) {
isc_boolean_t was_idle = ISC_FALSE;
isc_event_t *event;
@@ -385,8 +518,9 @@ task_send(isc_task_t *task, isc_event_t **eventp) {
return (was_idle);
}
-void
-isc_task_send(isc_task_t *task, isc_event_t **eventp) {
+ISC_TASKFUNC_SCOPE void
+isc__task_send(isc_task_t *task0, isc_event_t **eventp) {
+ isc__task_t *task = (isc__task_t *)task0;
isc_boolean_t was_idle;
/*
@@ -426,10 +560,10 @@ isc_task_send(isc_task_t *task, isc_event_t **eventp) {
}
}
-void
-isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
+ISC_TASKFUNC_SCOPE void
+isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
isc_boolean_t idle1, idle2;
- isc_task_t *task;
+ isc__task_t *task;
/*
* Send '*event' to '*taskp' and then detach '*taskp' from its
@@ -437,7 +571,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
*/
REQUIRE(taskp != NULL);
- task = *taskp;
+ task = (isc__task_t *)*taskp;
REQUIRE(VALID_TASK(task));
XTRACE("isc_task_sendanddetach");
@@ -463,7 +597,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
#define PURGE_OK(event) (((event)->ev_attributes & ISC_EVENTATTR_NOPURGE) == 0)
static unsigned int
-dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first,
+dequeue_events(isc__task_t *task, void *sender, isc_eventtype_t first,
isc_eventtype_t last, void *tag,
isc_eventlist_t *events, isc_boolean_t purging)
{
@@ -502,10 +636,11 @@ dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first,
return (count);
}
-unsigned int
-isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
- isc_eventtype_t last, void *tag)
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first,
+ isc_eventtype_t last, void *tag)
{
+ isc__task_t *task = (isc__task_t *)task0;
unsigned int count;
isc_eventlist_t events;
isc_event_t *event, *next_event;
@@ -533,9 +668,9 @@ isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
return (count);
}
-unsigned int
-isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
- void *tag)
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
+ void *tag)
{
/*
* Purge events from a task's event queue.
@@ -543,11 +678,12 @@ isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
XTRACE("isc_task_purge");
- return (isc_task_purgerange(task, sender, type, type, tag));
+ return (isc__task_purgerange(task, sender, type, type, tag));
}
-isc_boolean_t
-isc_task_purgeevent(isc_task_t *task, isc_event_t *event) {
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_purgeevent(isc_task_t *task0, isc_event_t *event) {
+ isc__task_t *task = (isc__task_t *)task0;
isc_event_t *curr_event, *next_event;
/*
@@ -588,10 +724,10 @@ isc_task_purgeevent(isc_task_t *task, isc_event_t *event) {
return (ISC_TRUE);
}
-unsigned int
-isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
- isc_eventtype_t last, void *tag,
- isc_eventlist_t *events)
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
+ isc_eventtype_t last, void *tag,
+ isc_eventlist_t *events)
{
/*
* Remove events from a task's event queue.
@@ -599,13 +735,13 @@ isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
XTRACE("isc_task_unsendrange");
- return (dequeue_events(task, sender, first, last, tag, events,
- ISC_FALSE));
+ return (dequeue_events((isc__task_t *)task, sender, first,
+ last, tag, events, ISC_FALSE));
}
-unsigned int
-isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
- void *tag, isc_eventlist_t *events)
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+ void *tag, isc_eventlist_t *events)
{
/*
* Remove events from a task's event queue.
@@ -613,13 +749,15 @@ isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
XTRACE("isc_task_unsend");
- return (dequeue_events(task, sender, type, type, tag, events,
- ISC_FALSE));
+ return (dequeue_events((isc__task_t *)task, sender, type,
+ type, tag, events, ISC_FALSE));
}
-isc_result_t
-isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action,
+ const void *arg)
{
+ isc__task_t *task = (isc__task_t *)task0;
isc_boolean_t disallowed = ISC_FALSE;
isc_result_t result = ISC_R_SUCCESS;
isc_event_t *event;
@@ -655,8 +793,9 @@ isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
return (result);
}
-void
-isc_task_shutdown(isc_task_t *task) {
+ISC_TASKFUNC_SCOPE void
+isc__task_shutdown(isc_task_t *task0) {
+ isc__task_t *task = (isc__task_t *)task0;
isc_boolean_t was_idle;
/*
@@ -673,8 +812,8 @@ isc_task_shutdown(isc_task_t *task) {
task_ready(task);
}
-void
-isc_task_destroy(isc_task_t **taskp) {
+ISC_TASKFUNC_SCOPE void
+isc__task_destroy(isc_task_t **taskp) {
/*
* Destroy '*taskp'.
@@ -686,8 +825,9 @@ isc_task_destroy(isc_task_t **taskp) {
isc_task_detach(taskp);
}
-void
-isc_task_setname(isc_task_t *task, const char *name, void *tag) {
+ISC_TASKFUNC_SCOPE void
+isc__task_setname(isc_task_t *task0, const char *name, void *tag) {
+ isc__task_t *task = (isc__task_t *)task0;
/*
* Name 'task'.
@@ -702,18 +842,28 @@ isc_task_setname(isc_task_t *task, const char *name, void *tag) {
UNLOCK(&task->lock);
}
-const char *
-isc_task_getname(isc_task_t *task) {
+ISC_TASKFUNC_SCOPE const char *
+isc__task_getname(isc_task_t *task0) {
+ isc__task_t *task = (isc__task_t *)task0;
+
+ REQUIRE(VALID_TASK(task));
+
return (task->name);
}
-void *
-isc_task_gettag(isc_task_t *task) {
+ISC_TASKFUNC_SCOPE void *
+isc__task_gettag(isc_task_t *task0) {
+ isc__task_t *task = (isc__task_t *)task0;
+
+ REQUIRE(VALID_TASK(task));
+
return (task->tag);
}
-void
-isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) {
+ISC_TASKFUNC_SCOPE void
+isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t) {
+ isc__task_t *task = (isc__task_t *)task0;
+
REQUIRE(VALID_TASK(task));
REQUIRE(t != NULL);
@@ -728,12 +878,12 @@ isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) {
*** Task Manager.
***/
static void
-dispatch(isc_taskmgr_t *manager) {
- isc_task_t *task;
-#ifndef ISC_PLATFORM_USETHREADS
+dispatch(isc__taskmgr_t *manager) {
+ isc__task_t *task;
+#ifndef USE_WORKER_THREADS
unsigned int total_dispatch_count = 0;
- isc_tasklist_t ready_tasks;
-#endif /* ISC_PLATFORM_USETHREADS */
+ isc__tasklist_t ready_tasks;
+#endif /* USE_WORKER_THREADS */
REQUIRE(VALID_MANAGER(manager));
@@ -787,12 +937,12 @@ dispatch(isc_taskmgr_t *manager) {
* unlocks. The while expression is always protected by the lock.
*/
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
ISC_LIST_INIT(ready_tasks);
#endif
LOCK(&manager->lock);
while (!FINISHED(manager)) {
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
/*
* For reasons similar to those given in the comment in
* isc_task_send() above, it is safe for us to dequeue
@@ -812,11 +962,11 @@ dispatch(isc_taskmgr_t *manager) {
ISC_MSGSET_TASK,
ISC_MSG_AWAKE, "awake"));
}
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WORKER_THREADS */
if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM ||
EMPTY(manager->ready_tasks))
break;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
ISC_MSG_WORKING, "working"));
@@ -859,13 +1009,15 @@ dispatch(isc_taskmgr_t *manager) {
"execute action"));
if (event->ev_action != NULL) {
UNLOCK(&task->lock);
- (event->ev_action)(task,event);
+ (event->ev_action)(
+ (isc_task_t *)task,
+ event);
LOCK(&task->lock);
}
dispatch_count++;
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
total_dispatch_count++;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
}
if (task->references == 0 &&
@@ -950,12 +1102,12 @@ dispatch(isc_taskmgr_t *manager) {
LOCK(&manager->lock);
manager->tasks_running--;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
if (manager->exclusive_requested &&
manager->tasks_running == 1) {
SIGNAL(&manager->exclusive_granted);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
if (requeue) {
/*
* We know we're awake, so we don't have
@@ -976,7 +1128,7 @@ dispatch(isc_taskmgr_t *manager) {
* were usually nonempty, the 'optimization'
* might even hurt rather than help.
*/
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
ENQUEUE(manager->ready_tasks, task,
ready_link);
#else
@@ -985,19 +1137,19 @@ dispatch(isc_taskmgr_t *manager) {
}
}
}
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link);
#endif
UNLOCK(&manager->lock);
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
static isc_threadresult_t
#ifdef _WIN32
WINAPI
#endif
run(void *uap) {
- isc_taskmgr_t *manager = uap;
+ isc__taskmgr_t *manager = uap;
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_STARTING, "starting"));
@@ -1007,33 +1159,42 @@ run(void *uap) {
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_EXITING, "exiting"));
+#ifdef OPENSSL_LEAKS
+ ERR_remove_state(0);
+#endif
+
return ((isc_threadresult_t)0);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
static void
-manager_free(isc_taskmgr_t *manager) {
+manager_free(isc__taskmgr_t *manager) {
isc_mem_t *mctx;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
(void)isc_condition_destroy(&manager->exclusive_granted);
(void)isc_condition_destroy(&manager->work_available);
isc_mem_free(manager->mctx, manager->threads);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
DESTROYLOCK(&manager->lock);
- manager->magic = 0;
+ manager->common.impmagic = 0;
+ manager->common.magic = 0;
mctx = manager->mctx;
isc_mem_put(mctx, manager, sizeof(*manager));
isc_mem_detach(&mctx);
+
+#ifdef USE_SHARED_MANAGER
+ taskmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
}
-isc_result_t
-isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
- unsigned int default_quantum, isc_taskmgr_t **managerp)
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+ unsigned int default_quantum, isc_taskmgr_t **managerp)
{
isc_result_t result;
unsigned int i, started = 0;
- isc_taskmgr_t *manager;
+ isc__taskmgr_t *manager;
/*
* Create a new task manager.
@@ -1042,28 +1203,33 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
REQUIRE(workers > 0);
REQUIRE(managerp != NULL && *managerp == NULL);
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
UNUSED(i);
UNUSED(started);
- UNUSED(workers);
+#endif
+#ifdef USE_SHARED_MANAGER
if (taskmgr != NULL) {
+ if (taskmgr->refs == 0)
+ return (ISC_R_SHUTTINGDOWN);
taskmgr->refs++;
- *managerp = taskmgr;
+ *managerp = (isc_taskmgr_t *)taskmgr;
return (ISC_R_SUCCESS);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
manager = isc_mem_get(mctx, sizeof(*manager));
if (manager == NULL)
return (ISC_R_NOMEMORY);
- manager->magic = TASK_MANAGER_MAGIC;
+ manager->common.methods = &taskmgrmethods;
+ manager->common.impmagic = TASK_MANAGER_MAGIC;
+ manager->common.magic = ISCAPI_TASKMGR_MAGIC;
manager->mctx = NULL;
result = isc_mutex_init(&manager->lock);
if (result != ISC_R_SUCCESS)
goto cleanup_mgr;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
manager->workers = 0;
manager->threads = isc_mem_allocate(mctx,
workers * sizeof(isc_thread_t));
@@ -1087,7 +1253,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
result = ISC_R_UNEXPECTED;
goto cleanup_workavailable;
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
if (default_quantum == 0)
default_quantum = DEFAULT_DEFAULT_QUANTUM;
manager->default_quantum = default_quantum;
@@ -1099,7 +1265,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
isc_mem_attach(mctx, &manager->mctx);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
LOCK(&manager->lock);
/*
* Start workers.
@@ -1119,16 +1285,17 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
return (ISC_R_NOTHREADS);
}
isc_thread_setconcurrency(workers);
-#else /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
+#ifdef USE_SHARED_MANAGER
manager->refs = 1;
taskmgr = manager;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
- *managerp = manager;
+ *managerp = (isc_taskmgr_t *)manager;
return (ISC_R_SUCCESS);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
cleanup_workavailable:
(void)isc_condition_destroy(&manager->work_available);
cleanup_threads:
@@ -1141,10 +1308,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
return (result);
}
-void
-isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
- isc_taskmgr_t *manager;
- isc_task_t *task;
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
+ isc__taskmgr_t *manager;
+ isc__task_t *task;
unsigned int i;
/*
@@ -1152,18 +1319,20 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
*/
REQUIRE(managerp != NULL);
- manager = *managerp;
+ manager = (isc__taskmgr_t *)*managerp;
REQUIRE(VALID_MANAGER(manager));
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
UNUSED(i);
+#endif /* USE_WORKER_THREADS */
- if (manager->refs > 1) {
- manager->refs--;
+#ifdef USE_SHARED_MANAGER
+ manager->refs--;
+ if (manager->refs > 0) {
*managerp = NULL;
return;
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif
XTHREADTRACE("isc_taskmgr_destroy");
/*
@@ -1203,7 +1372,7 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
ENQUEUE(manager->ready_tasks, task, ready_link);
UNLOCK(&task->lock);
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
/*
* Wake up any sleeping workers. This ensures we get work done if
* there's work left to do, and if there are already no tasks left
@@ -1217,36 +1386,51 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
*/
for (i = 0; i < manager->workers; i++)
(void)isc_thread_join(manager->threads[i], NULL);
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WORKER_THREADS */
/*
* Dispatch the shutdown events.
*/
UNLOCK(&manager->lock);
- while (isc__taskmgr_ready())
- (void)isc__taskmgr_dispatch();
+ while (isc__taskmgr_ready((isc_taskmgr_t *)manager))
+ (void)isc__taskmgr_dispatch((isc_taskmgr_t *)manager);
+#ifdef BIND9
if (!ISC_LIST_EMPTY(manager->tasks))
isc_mem_printallactive(stderr);
+#endif
INSIST(ISC_LIST_EMPTY(manager->tasks));
-#endif /* ISC_PLATFORM_USETHREADS */
+#ifdef USE_SHARED_MANAGER
+ taskmgr = NULL;
+#endif
+#endif /* USE_WORKER_THREADS */
manager_free(manager);
*managerp = NULL;
}
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
isc_boolean_t
-isc__taskmgr_ready(void) {
- if (taskmgr == NULL)
+isc__taskmgr_ready(isc_taskmgr_t *manager0) {
+ isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+
+#ifdef USE_SHARED_MANAGER
+ if (manager == NULL)
+ manager = taskmgr;
+#endif
+ if (manager == NULL)
return (ISC_FALSE);
- return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks)));
+ return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks)));
}
isc_result_t
-isc__taskmgr_dispatch(void) {
- isc_taskmgr_t *manager = taskmgr;
+isc__taskmgr_dispatch(isc_taskmgr_t *manager0) {
+ isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
- if (taskmgr == NULL)
+#ifdef USE_SHARED_MANAGER
+ if (manager == NULL)
+ manager = taskmgr;
+#endif
+ if (manager == NULL)
return (ISC_R_NOTFOUND);
dispatch(manager);
@@ -1254,12 +1438,13 @@ isc__taskmgr_dispatch(void) {
return (ISC_R_SUCCESS);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
-isc_result_t
-isc_task_beginexclusive(isc_task_t *task) {
-#ifdef ISC_PLATFORM_USETHREADS
- isc_taskmgr_t *manager = task->manager;
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_beginexclusive(isc_task_t *task0) {
+#ifdef USE_WORKER_THREADS
+ isc__task_t *task = (isc__task_t *)task0;
+ isc__taskmgr_t *manager = task->manager;
REQUIRE(task->state == task_state_running);
LOCK(&manager->lock);
if (manager->exclusive_requested) {
@@ -1272,15 +1457,17 @@ isc_task_beginexclusive(isc_task_t *task) {
}
UNLOCK(&manager->lock);
#else
- UNUSED(task);
+ UNUSED(task0);
#endif
return (ISC_R_SUCCESS);
}
-void
-isc_task_endexclusive(isc_task_t *task) {
-#ifdef ISC_PLATFORM_USETHREADS
- isc_taskmgr_t *manager = task->manager;
+ISC_TASKFUNC_SCOPE void
+isc__task_endexclusive(isc_task_t *task0) {
+#ifdef USE_WORKER_THREADS
+ isc__task_t *task = (isc__task_t *)task0;
+ isc__taskmgr_t *manager = task->manager;
+
REQUIRE(task->state == task_state_running);
LOCK(&manager->lock);
REQUIRE(manager->exclusive_requested);
@@ -1288,23 +1475,31 @@ isc_task_endexclusive(isc_task_t *task) {
BROADCAST(&manager->work_available);
UNLOCK(&manager->lock);
#else
- UNUSED(task);
+ UNUSED(task0);
#endif
}
+#ifdef USE_SOCKETIMPREGISTER
+isc_result_t
+isc__task_register() {
+ return (isc_task_register(isc__taskmgr_create));
+}
+#endif
+
isc_boolean_t
isc_task_exiting(isc_task_t *t) {
- isc_task_t *task = (isc_task_t *)t;
+ isc__task_t *task = (isc__task_t *)t;
REQUIRE(VALID_TASK(task));
return (TASK_SHUTTINGDOWN(task));
}
-#ifdef HAVE_LIBXML2
+
+#if defined(HAVE_LIBXML2) && defined(BIND9)
void
-isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer)
-{
- isc_task_t *task;
+isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, xmlTextWriterPtr writer) {
+ isc__taskmgr_t *mgr = (isc__taskmgr_t *)mgr0;
+ isc__task_t *task;
LOCK(&mgr->lock);
@@ -1380,4 +1575,4 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer)
UNLOCK(&mgr->lock);
}
-#endif /* HAVE_LIBXML2 */
+#endif /* HAVE_LIBXML2 && BIND9 */
diff --git a/contrib/bind9/lib/isc/task_api.c b/contrib/bind9/lib/isc/task_api.c
new file mode 100644
index 0000000..4e03db2
--- /dev/null
+++ b/contrib/bind9/lib/isc/task_api.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2009, 2010 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: task_api.c,v 1.7 2010-12-22 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_taskmgrcreatefunc_t taskmgr_createfunc = NULL;
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_task_register(isc_taskmgrcreatefunc_t createfunc) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+ LOCK(&createlock);
+ if (taskmgr_createfunc == NULL)
+ taskmgr_createfunc = createfunc;
+ else
+ result = ISC_R_EXISTS;
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+isc_result_t
+isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+ unsigned int workers, unsigned int default_quantum,
+ isc_taskmgr_t **managerp)
+{
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(taskmgr_createfunc != NULL);
+ result = (*taskmgr_createfunc)(mctx, workers, default_quantum,
+ managerp);
+
+ UNLOCK(&createlock);
+
+ if (result == ISC_R_SUCCESS)
+ isc_appctx_settaskmgr(actx, *managerp);
+
+ return (result);
+}
+
+isc_result_t
+isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+ unsigned int default_quantum, isc_taskmgr_t **managerp)
+{
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(taskmgr_createfunc != NULL);
+ result = (*taskmgr_createfunc)(mctx, workers, default_quantum,
+ managerp);
+
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+void
+isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
+ REQUIRE(managerp != NULL && ISCAPI_TASKMGR_VALID(*managerp));
+
+ (*managerp)->methods->destroy(managerp);
+
+ ENSURE(*managerp == NULL);
+}
+
+isc_result_t
+isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
+ isc_task_t **taskp)
+{
+ REQUIRE(ISCAPI_TASKMGR_VALID(manager));
+ REQUIRE(taskp != NULL && *taskp == NULL);
+
+ return (manager->methods->taskcreate(manager, quantum, taskp));
+}
+
+void
+isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
+ REQUIRE(ISCAPI_TASK_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ source->methods->attach(source, targetp);
+
+ ENSURE(*targetp == source);
+}
+
+void
+isc_task_detach(isc_task_t **taskp) {
+ REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp));
+
+ (*taskp)->methods->detach(taskp);
+
+ ENSURE(*taskp == NULL);
+}
+
+void
+isc_task_send(isc_task_t *task, isc_event_t **eventp) {
+ REQUIRE(ISCAPI_TASK_VALID(task));
+ REQUIRE(eventp != NULL && *eventp != NULL);
+
+ task->methods->send(task, eventp);
+
+ ENSURE(*eventp == NULL);
+}
+
+void
+isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
+ REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp));
+ REQUIRE(eventp != NULL && *eventp != NULL);
+
+ (*taskp)->methods->sendanddetach(taskp, eventp);
+
+ ENSURE(*taskp == NULL && *eventp == NULL);
+}
+
+unsigned int
+isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+ void *tag, isc_eventlist_t *events)
+{
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ return (task->methods->unsend(task, sender, type, tag, events));
+}
+
+isc_result_t
+isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ return (task->methods->onshutdown(task, action, arg));
+}
+
+void
+isc_task_shutdown(isc_task_t *task) {
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ task->methods->shutdown(task);
+}
+
+void
+isc_task_setname(isc_task_t *task, const char *name, void *tag) {
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ task->methods->setname(task, name, tag);
+}
+
+unsigned int
+isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag)
+{
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ return (task->methods->purgeevents(task, sender, type, tag));
+}
+
+isc_result_t
+isc_task_beginexclusive(isc_task_t *task) {
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ return (task->methods->beginexclusive(task));
+}
+
+void
+isc_task_endexclusive(isc_task_t *task) {
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ task->methods->endexclusive(task);
+}
+
+
+/*%
+ * This is necessary for libisc's internal timer implementation. Other
+ * implementation might skip implementing this.
+ */
+unsigned int
+isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
+ isc_eventtype_t last, void *tag)
+{
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ return (task->methods->purgerange(task, sender, first, last, tag));
+}
diff --git a/contrib/bind9/lib/isc/task_p.h b/contrib/bind9/lib/isc/task_p.h
index 7bf208a..1bcdca6 100644
--- a/contrib/bind9/lib/isc/task_p.h
+++ b/contrib/bind9/lib/isc/task_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: task_p.h,v 1.11 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: task_p.h,v 1.13 2009-09-02 23:48:02 tbox Exp $ */
#ifndef ISC_TASK_P_H
#define ISC_TASK_P_H
@@ -23,9 +23,9 @@
/*! \file */
isc_boolean_t
-isc__taskmgr_ready(void);
+isc__taskmgr_ready(isc_taskmgr_t *taskmgr);
isc_result_t
-isc__taskmgr_dispatch(void);
+isc__taskmgr_dispatch(isc_taskmgr_t *taskmgr);
#endif /* ISC_TASK_P_H */
diff --git a/contrib/bind9/lib/isc/timer.c b/contrib/bind9/lib/isc/timer.c
index 6342688..ab89cdd 100644
--- a/contrib/bind9/lib/isc/timer.c
+++ b/contrib/bind9/lib/isc/timer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009, 2011 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: timer.c,v 1.84.58.4 2009-01-23 23:47:21 tbox Exp $ */
+/* $Id: timer.c,v 1.95.302.1.2.1 2011-06-02 23:47:36 tbox Exp $ */
/*! \file */
@@ -34,9 +34,22 @@
#include <isc/timer.h>
#include <isc/util.h>
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef OPENSSL_LEAKS
+#include <openssl/err.h>
+#endif
+
+/* See task.c about the following definition: */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_TIMER_THREAD
+#else
+#define USE_SHARED_MANAGER
+#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* BIND9 */
+
+#ifndef USE_TIMER_THREAD
#include "timer_p.h"
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
#ifdef ISC_TIMER_TRACE
#define XTRACE(s) fprintf(stderr, "%s\n", (s))
@@ -58,10 +71,13 @@
#define TIMER_MAGIC ISC_MAGIC('T', 'I', 'M', 'R')
#define VALID_TIMER(t) ISC_MAGIC_VALID(t, TIMER_MAGIC)
-struct isc_timer {
+typedef struct isc__timer isc__timer_t;
+typedef struct isc__timermgr isc__timermgr_t;
+
+struct isc__timer {
/*! Not locked. */
- unsigned int magic;
- isc_timermgr_t * manager;
+ isc_timer_t common;
+ isc__timermgr_t * manager;
isc_mutex_t lock;
/*! Locked by timer lock. */
unsigned int references;
@@ -75,45 +91,119 @@ struct isc_timer {
void * arg;
unsigned int index;
isc_time_t due;
- LINK(isc_timer_t) link;
+ LINK(isc__timer_t) link;
};
#define TIMER_MANAGER_MAGIC ISC_MAGIC('T', 'I', 'M', 'M')
#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TIMER_MANAGER_MAGIC)
-struct isc_timermgr {
+struct isc__timermgr {
/* Not locked. */
- unsigned int magic;
+ isc_timermgr_t common;
isc_mem_t * mctx;
isc_mutex_t lock;
/* Locked by manager lock. */
isc_boolean_t done;
- LIST(isc_timer_t) timers;
+ LIST(isc__timer_t) timers;
unsigned int nscheduled;
isc_time_t due;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
isc_condition_t wakeup;
isc_thread_t thread;
-#else /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
+#ifdef USE_SHARED_MANAGER
unsigned int refs;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
isc_heap_t * heap;
};
-#ifndef ISC_PLATFORM_USETHREADS
+/*%
+ * The followings can be either static or public, depending on build
+ * environment.
+ */
+
+#ifdef BIND9
+#define ISC_TIMERFUNC_SCOPE
+#else
+#define ISC_TIMERFUNC_SCOPE static
+#endif
+
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_create(isc_timermgr_t *manager, isc_timertype_t type,
+ isc_time_t *expires, isc_interval_t *interval,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_reset(isc_timer_t *timer, isc_timertype_t type,
+ isc_time_t *expires, isc_interval_t *interval,
+ isc_boolean_t purge);
+ISC_TIMERFUNC_SCOPE isc_timertype_t
+isc__timer_gettype(isc_timer_t *timer);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_touch(isc_timer_t *timer);
+ISC_TIMERFUNC_SCOPE void
+isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE void
+isc__timer_detach(isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_poke(isc_timermgr_t *manager0);
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_destroy(isc_timermgr_t **managerp);
+
+static struct isc__timermethods {
+ isc_timermethods_t methods;
+
+ /*%
+ * The following are defined just for avoiding unused static functions.
+ */
+#ifndef BIND9
+ void *gettype;
+#endif
+} timermethods = {
+ {
+ isc__timer_attach,
+ isc__timer_detach,
+ isc__timer_reset,
+ isc__timer_touch
+ }
+#ifndef BIND9
+ ,
+ (void *)isc__timer_gettype
+#endif
+};
+
+static struct isc__timermgrmethods {
+ isc_timermgrmethods_t methods;
+#ifndef BIND9
+ void *poke; /* see above */
+#endif
+} timermgrmethods = {
+ {
+ isc__timermgr_destroy,
+ isc__timer_create
+ }
+#ifndef BIND9
+ ,
+ (void *)isc__timermgr_poke
+#endif
+};
+
+#ifdef USE_SHARED_MANAGER
/*!
- * If threads are not in use, there can be only one.
+ * If the manager is supposed to be shared, there can be only one.
*/
-static isc_timermgr_t *timermgr = NULL;
-#endif /* ISC_PLATFORM_USETHREADS */
+static isc__timermgr_t *timermgr = NULL;
+#endif /* USE_SHARED_MANAGER */
static inline isc_result_t
-schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
+schedule(isc__timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
isc_result_t result;
- isc_timermgr_t *manager;
+ isc__timermgr_t *manager;
isc_time_t due;
int cmp;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
isc_boolean_t timedwait;
#endif
@@ -123,13 +213,13 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
REQUIRE(timer->type != isc_timertype_inactive);
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_TIMER_THREAD
UNUSED(signal_ok);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
manager = timer->manager;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
/*!
* If the manager was timed wait, we may need to signal the
* manager to force a wakeup.
@@ -199,7 +289,7 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
* the current "next" timer. We do this either by waking up the
* run thread, or explicitly setting the value in the manager.
*/
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
/*
* This is a temporary (probably) hack to fix a bug on tru64 5.1
@@ -232,19 +322,19 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
"signal (schedule)"));
SIGNAL(&manager->wakeup);
}
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_TIMER_THREAD */
if (timer->index == 1 &&
isc_time_compare(&timer->due, &manager->due) < 0)
manager->due = timer->due;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
return (ISC_R_SUCCESS);
}
static inline void
-deschedule(isc_timer_t *timer) {
+deschedule(isc__timer_t *timer) {
isc_boolean_t need_wakeup = ISC_FALSE;
- isc_timermgr_t *manager;
+ isc__timermgr_t *manager;
/*
* The caller must ensure locking.
@@ -258,20 +348,20 @@ deschedule(isc_timer_t *timer) {
timer->index = 0;
INSIST(manager->nscheduled > 0);
manager->nscheduled--;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
if (need_wakeup) {
XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
ISC_MSG_SIGNALDESCHED,
"signal (deschedule)"));
SIGNAL(&manager->wakeup);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
}
}
static void
-destroy(isc_timer_t *timer) {
- isc_timermgr_t *manager = timer->manager;
+destroy(isc__timer_t *timer) {
+ isc__timermgr_t *manager = timer->manager;
/*
* The caller must ensure it is safe to destroy the timer.
@@ -291,17 +381,19 @@ destroy(isc_timer_t *timer) {
isc_task_detach(&timer->task);
DESTROYLOCK(&timer->lock);
- timer->magic = 0;
+ timer->common.impmagic = 0;
+ timer->common.magic = 0;
isc_mem_put(manager->mctx, timer, sizeof(*timer));
}
-isc_result_t
-isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
- isc_time_t *expires, isc_interval_t *interval,
- isc_task_t *task, isc_taskaction_t action, const void *arg,
- isc_timer_t **timerp)
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type,
+ isc_time_t *expires, isc_interval_t *interval,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_timer_t **timerp)
{
- isc_timer_t *timer;
+ isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+ isc__timer_t *timer;
isc_result_t result;
isc_time_t now;
@@ -382,7 +474,9 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
return (result);
}
ISC_LINK_INIT(timer, link);
- timer->magic = TIMER_MAGIC;
+ timer->common.impmagic = TIMER_MAGIC;
+ timer->common.magic = ISCAPI_TIMER_MAGIC;
+ timer->common.methods = (isc_timermethods_t *)&timermethods;
LOCK(&manager->lock);
@@ -401,25 +495,27 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
UNLOCK(&manager->lock);
if (result != ISC_R_SUCCESS) {
- timer->magic = 0;
+ timer->common.impmagic = 0;
+ timer->common.magic = 0;
DESTROYLOCK(&timer->lock);
isc_task_detach(&timer->task);
isc_mem_put(manager->mctx, timer, sizeof(*timer));
return (result);
}
- *timerp = timer;
+ *timerp = (isc_timer_t *)timer;
return (ISC_R_SUCCESS);
}
-isc_result_t
-isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
- isc_time_t *expires, isc_interval_t *interval,
- isc_boolean_t purge)
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_reset(isc_timer_t *timer0, isc_timertype_t type,
+ isc_time_t *expires, isc_interval_t *interval,
+ isc_boolean_t purge)
{
+ isc__timer_t *timer = (isc__timer_t *)timer0;
isc_time_t now;
- isc_timermgr_t *manager;
+ isc__timermgr_t *manager;
isc_result_t result;
/*
@@ -489,8 +585,9 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
return (result);
}
-isc_timertype_t
-isc_timer_gettype(isc_timer_t *timer) {
+ISC_TIMERFUNC_SCOPE isc_timertype_t
+isc__timer_gettype(isc_timer_t *timer0) {
+ isc__timer_t *timer = (isc__timer_t *)timer0;
isc_timertype_t t;
REQUIRE(VALID_TIMER(timer));
@@ -502,8 +599,9 @@ isc_timer_gettype(isc_timer_t *timer) {
return (t);
}
-isc_result_t
-isc_timer_touch(isc_timer_t *timer) {
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_touch(isc_timer_t *timer0) {
+ isc__timer_t *timer = (isc__timer_t *)timer0;
isc_result_t result;
isc_time_t now;
@@ -532,8 +630,10 @@ isc_timer_touch(isc_timer_t *timer) {
return (result);
}
-void
-isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
+ISC_TIMERFUNC_SCOPE void
+isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) {
+ isc__timer_t *timer = (isc__timer_t *)timer0;
+
/*
* Attach *timerp to timer.
*/
@@ -545,12 +645,12 @@ isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
timer->references++;
UNLOCK(&timer->lock);
- *timerp = timer;
+ *timerp = (isc_timer_t *)timer;
}
-void
-isc_timer_detach(isc_timer_t **timerp) {
- isc_timer_t *timer;
+ISC_TIMERFUNC_SCOPE void
+isc__timer_detach(isc_timer_t **timerp) {
+ isc__timer_t *timer;
isc_boolean_t free_timer = ISC_FALSE;
/*
@@ -558,7 +658,7 @@ isc_timer_detach(isc_timer_t **timerp) {
*/
REQUIRE(timerp != NULL);
- timer = *timerp;
+ timer = (isc__timer_t *)*timerp;
REQUIRE(VALID_TIMER(timer));
LOCK(&timer->lock);
@@ -575,11 +675,11 @@ isc_timer_detach(isc_timer_t **timerp) {
}
static void
-dispatch(isc_timermgr_t *manager, isc_time_t *now) {
+dispatch(isc__timermgr_t *manager, isc_time_t *now) {
isc_boolean_t done = ISC_FALSE, post_event, need_schedule;
isc_timerevent_t *event;
isc_eventtype_t type = 0;
- isc_timer_t *timer;
+ isc__timer_t *timer;
isc_result_t result;
isc_boolean_t idle;
@@ -693,13 +793,13 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) {
}
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
static isc_threadresult_t
#ifdef _WIN32 /* XXXDCL */
WINAPI
#endif
run(void *uap) {
- isc_timermgr_t *manager = uap;
+ isc__timermgr_t *manager = uap;
isc_time_t now;
isc_result_t result;
@@ -732,13 +832,17 @@ run(void *uap) {
}
UNLOCK(&manager->lock);
+#ifdef OPENSSL_LEAKS
+ ERR_remove_state(0);
+#endif
+
return ((isc_threadresult_t)0);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
static isc_boolean_t
sooner(void *v1, void *v2) {
- isc_timer_t *t1, *t2;
+ isc__timer_t *t1, *t2;
t1 = v1;
t2 = v2;
@@ -752,7 +856,7 @@ sooner(void *v1, void *v2) {
static void
set_index(void *what, unsigned int index) {
- isc_timer_t *timer;
+ isc__timer_t *timer;
timer = what;
REQUIRE(VALID_TIMER(timer));
@@ -760,9 +864,9 @@ set_index(void *what, unsigned int index) {
timer->index = index;
}
-isc_result_t
-isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
- isc_timermgr_t *manager;
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
+ isc__timermgr_t *manager;
isc_result_t result;
/*
@@ -771,19 +875,21 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
REQUIRE(managerp != NULL && *managerp == NULL);
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
if (timermgr != NULL) {
timermgr->refs++;
- *managerp = timermgr;
+ *managerp = (isc_timermgr_t *)timermgr;
return (ISC_R_SUCCESS);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
manager = isc_mem_get(mctx, sizeof(*manager));
if (manager == NULL)
return (ISC_R_NOMEMORY);
- manager->magic = TIMER_MANAGER_MAGIC;
+ manager->common.impmagic = TIMER_MANAGER_MAGIC;
+ manager->common.magic = ISCAPI_TIMERMGR_MAGIC;
+ manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods;
manager->mctx = NULL;
manager->done = ISC_FALSE;
INIT_LIST(manager->timers);
@@ -803,7 +909,7 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
return (result);
}
isc_mem_attach(mctx, &manager->mctx);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) {
isc_mem_detach(&manager->mctx);
DESTROYLOCK(&manager->lock);
@@ -828,30 +934,33 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
ISC_MSG_FAILED, "failed"));
return (ISC_R_UNEXPECTED);
}
-#else /* ISC_PLATFORM_USETHREADS */
+#endif
+#ifdef USE_SHARED_MANAGER
manager->refs = 1;
timermgr = manager;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
- *managerp = manager;
+ *managerp = (isc_timermgr_t *)manager;
return (ISC_R_SUCCESS);
}
-void
-isc_timermgr_poke(isc_timermgr_t *manager) {
-#ifdef ISC_PLATFORM_USETHREADS
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_poke(isc_timermgr_t *manager0) {
+#ifdef USE_TIMER_THREAD
+ isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+
REQUIRE(VALID_MANAGER(manager));
SIGNAL(&manager->wakeup);
#else
- UNUSED(manager);
+ UNUSED(manager0);
#endif
}
-void
-isc_timermgr_destroy(isc_timermgr_t **managerp) {
- isc_timermgr_t *manager;
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_destroy(isc_timermgr_t **managerp) {
+ isc__timermgr_t *manager;
isc_mem_t *mctx;
/*
@@ -859,34 +968,37 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) {
*/
REQUIRE(managerp != NULL);
- manager = *managerp;
+ manager = (isc__timermgr_t *)*managerp;
REQUIRE(VALID_MANAGER(manager));
LOCK(&manager->lock);
-#ifndef ISC_PLATFORM_USETHREADS
- if (manager->refs > 1) {
- manager->refs--;
+#ifdef USE_SHARED_MANAGER
+ manager->refs--;
+ if (manager->refs > 0) {
UNLOCK(&manager->lock);
*managerp = NULL;
return;
}
+ timermgr = NULL;
+#endif /* USE_SHARED_MANAGER */
- isc__timermgr_dispatch();
-#endif /* ISC_PLATFORM_USETHREADS */
+#ifndef USE_TIMER_THREAD
+ isc__timermgr_dispatch((isc_timermgr_t *)manager);
+#endif
REQUIRE(EMPTY(manager->timers));
manager->done = ISC_TRUE;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
ISC_MSG_SIGNALDESTROY, "signal (destroy)"));
SIGNAL(&manager->wakeup);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
UNLOCK(&manager->lock);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
/*
* Wait for thread to exit.
*/
@@ -895,39 +1007,63 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) {
"isc_thread_join() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"));
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
/*
* Clean up.
*/
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
(void)isc_condition_destroy(&manager->wakeup);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
DESTROYLOCK(&manager->lock);
isc_heap_destroy(&manager->heap);
- manager->magic = 0;
+ manager->common.impmagic = 0;
+ manager->common.magic = 0;
mctx = manager->mctx;
isc_mem_put(mctx, manager, sizeof(*manager));
isc_mem_detach(&mctx);
*managerp = NULL;
+
+#ifdef USE_SHARED_MANAGER
+ timermgr = NULL;
+#endif
}
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_TIMER_THREAD
isc_result_t
-isc__timermgr_nextevent(isc_time_t *when) {
- if (timermgr == NULL || timermgr->nscheduled == 0)
+isc__timermgr_nextevent(isc_timermgr_t *manager0, isc_time_t *when) {
+ isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+
+#ifdef USE_SHARED_MANAGER
+ if (manager == NULL)
+ manager = timermgr;
+#endif
+ if (manager == NULL || manager->nscheduled == 0)
return (ISC_R_NOTFOUND);
- *when = timermgr->due;
+ *when = manager->due;
return (ISC_R_SUCCESS);
}
void
-isc__timermgr_dispatch(void) {
+isc__timermgr_dispatch(isc_timermgr_t *manager0) {
+ isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
isc_time_t now;
- if (timermgr == NULL)
+
+#ifdef USE_SHARED_MANAGER
+ if (manager == NULL)
+ manager = timermgr;
+#endif
+ if (manager == NULL)
return;
TIME_NOW(&now);
- dispatch(timermgr, &now);
+ dispatch(manager, &now);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
+
+#ifdef USE_TIMERIMPREGISTER
+isc_result_t
+isc__timer_register() {
+ return (isc_timer_register(isc__timermgr_create));
+}
+#endif
diff --git a/contrib/bind9/lib/isc/timer_api.c b/contrib/bind9/lib/isc/timer_api.c
new file mode 100644
index 0000000..5a9bf9d
--- /dev/null
+++ b/contrib/bind9/lib/isc/timer_api.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 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: timer_api.c,v 1.4 2009-09-02 23:48:02 tbox Exp $ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_timermgrcreatefunc_t timermgr_createfunc = NULL;
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_timer_register(isc_timermgrcreatefunc_t createfunc) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+ LOCK(&createlock);
+ if (timermgr_createfunc == NULL)
+ timermgr_createfunc = createfunc;
+ else
+ result = ISC_R_EXISTS;
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+isc_result_t
+isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+ isc_timermgr_t **managerp)
+{
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(timermgr_createfunc != NULL);
+ result = (*timermgr_createfunc)(mctx, managerp);
+
+ UNLOCK(&createlock);
+
+ if (result == ISC_R_SUCCESS)
+ isc_appctx_settimermgr(actx, *managerp);
+
+ return (result);
+}
+
+isc_result_t
+isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
+ isc_result_t result;
+
+ LOCK(&createlock);
+
+ REQUIRE(timermgr_createfunc != NULL);
+ result = (*timermgr_createfunc)(mctx, managerp);
+
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+void
+isc_timermgr_destroy(isc_timermgr_t **managerp) {
+ REQUIRE(*managerp != NULL && ISCAPI_TIMERMGR_VALID(*managerp));
+
+ (*managerp)->methods->destroy(managerp);
+
+ ENSURE(*managerp == NULL);
+}
+
+isc_result_t
+isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
+ isc_time_t *expires, isc_interval_t *interval,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_timer_t **timerp)
+{
+ REQUIRE(ISCAPI_TIMERMGR_VALID(manager));
+
+ return (manager->methods->timercreate(manager, type, expires,
+ interval, task, action, arg,
+ timerp));
+}
+
+void
+isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
+ REQUIRE(ISCAPI_TIMER_VALID(timer));
+ REQUIRE(timerp != NULL && *timerp == NULL);
+
+ timer->methods->attach(timer, timerp);
+
+ ENSURE(*timerp == timer);
+}
+
+void
+isc_timer_detach(isc_timer_t **timerp) {
+ REQUIRE(timerp != NULL && ISCAPI_TIMER_VALID(*timerp));
+
+ (*timerp)->methods->detach(timerp);
+
+ ENSURE(*timerp == NULL);
+}
+
+isc_result_t
+isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
+ isc_time_t *expires, isc_interval_t *interval,
+ isc_boolean_t purge)
+{
+ REQUIRE(ISCAPI_TIMER_VALID(timer));
+
+ return (timer->methods->reset(timer, type, expires, interval, purge));
+}
+
+isc_result_t
+isc_timer_touch(isc_timer_t *timer) {
+ REQUIRE(ISCAPI_TIMER_VALID(timer));
+
+ return (timer->methods->touch(timer));
+}
diff --git a/contrib/bind9/lib/isc/timer_p.h b/contrib/bind9/lib/isc/timer_p.h
index b41f922..657b695 100644
--- a/contrib/bind9/lib/isc/timer_p.h
+++ b/contrib/bind9/lib/isc/timer_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: timer_p.h,v 1.10 2007-06-19 23:47:17 tbox Exp $ */
+/* $Id: timer_p.h,v 1.12 2009-09-02 23:48:02 tbox Exp $ */
#ifndef ISC_TIMER_P_H
#define ISC_TIMER_P_H
@@ -23,9 +23,9 @@
/*! \file */
isc_result_t
-isc__timermgr_nextevent(isc_time_t *when);
+isc__timermgr_nextevent(isc_timermgr_t *timermgr, isc_time_t *when);
void
-isc__timermgr_dispatch(void);
+isc__timermgr_dispatch(isc_timermgr_t *timermgr);
#endif /* ISC_TIMER_P_H */
diff --git a/contrib/bind9/lib/isc/unix/Makefile.in b/contrib/bind9/lib/isc/unix/Makefile.in
index 7d23b96..2c91756 100644
--- a/contrib/bind9/lib/isc/unix/Makefile.in
+++ b/contrib/bind9/lib/isc/unix/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2001 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -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.41 2007-06-19 23:47:18 tbox Exp $
+# $Id: Makefile.in,v 1.44 2009-12-05 23:31:41 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
diff --git a/contrib/bind9/lib/isc/unix/app.c b/contrib/bind9/lib/isc/unix/app.c
index 6bd1660..4dc5130 100644
--- a/contrib/bind9/lib/isc/unix/app.c
+++ b/contrib/bind9/lib/isc/unix/app.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-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: app.c,v 1.60 2008-10-15 03:41:17 marka Exp $ */
+/* $Id: app.c,v 1.64 2009-11-04 05:58:46 marka Exp $ */
/*! \file */
@@ -37,6 +37,7 @@
#include <isc/app.h>
#include <isc/boolean.h>
#include <isc/condition.h>
+#include <isc/mem.h>
#include <isc/msgs.h>
#include <isc/mutex.h>
#include <isc/event.h>
@@ -47,31 +48,129 @@
#include <isc/time.h>
#include <isc/util.h>
+/*%
+ * For BIND9 internal applications built with threads, we use a single app
+ * context and let multiple worker, I/O, timer threads do actual jobs.
+ * For other cases (including BIND9 built without threads) an app context acts
+ * as an event loop dispatching various events.
+ */
+#if defined(ISC_PLATFORM_USETHREADS) && defined(BIND9)
+#define USE_THREADS_SINGLECTX
+#endif
+
#ifdef ISC_PLATFORM_USETHREADS
#include <pthread.h>
-#else /* ISC_PLATFORM_USETHREADS */
+#endif
+
+#ifndef USE_THREADS_SINGLECTX
#include "../timer_p.h"
#include "../task_p.h"
#include "socket_p.h"
+#endif /* USE_THREADS_SINGLECTX */
+
+#ifdef ISC_PLATFORM_USETHREADS
+static pthread_t blockedthread;
#endif /* ISC_PLATFORM_USETHREADS */
-static isc_eventlist_t on_run;
-static isc_mutex_t lock;
-static isc_boolean_t shutdown_requested = ISC_FALSE;
-static isc_boolean_t running = ISC_FALSE;
-/*!
- * We assume that 'want_shutdown' can be read and written atomically.
+/*%
+ * The following can be either static or public, depending on build environment.
*/
-static volatile isc_boolean_t want_shutdown = ISC_FALSE;
+
+#ifdef BIND9
+#define ISC_APPFUNC_SCOPE
+#else
+#define ISC_APPFUNC_SCOPE static
+#endif
+
+ISC_APPFUNC_SCOPE isc_result_t isc__app_start(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxstart(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_onrun(isc_mem_t *mctx,
+ isc_task_t *task,
+ isc_taskaction_t action,
+ void *arg);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxrun(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_run(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_shutdown(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_reload(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE void isc__app_ctxfinish(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE void isc__app_finish(void);
+ISC_APPFUNC_SCOPE void isc__app_block(void);
+ISC_APPFUNC_SCOPE void isc__app_unblock(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__appctx_create(isc_mem_t *mctx,
+ isc_appctx_t **ctxp);
+ISC_APPFUNC_SCOPE void isc__appctx_destroy(isc_appctx_t **ctxp);
+ISC_APPFUNC_SCOPE void isc__appctx_settaskmgr(isc_appctx_t *ctx,
+ isc_taskmgr_t *taskmgr);
+ISC_APPFUNC_SCOPE void isc__appctx_setsocketmgr(isc_appctx_t *ctx,
+ isc_socketmgr_t *socketmgr);
+ISC_APPFUNC_SCOPE void isc__appctx_settimermgr(isc_appctx_t *ctx,
+ isc_timermgr_t *timermgr);
+
/*
- * We assume that 'want_reload' can be read and written atomically.
+ * The application context of this module. This implementation actually
+ * doesn't use it. (This may change in the future).
*/
-static volatile isc_boolean_t want_reload = ISC_FALSE;
+#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x')
+#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC)
+
+typedef struct isc__appctx {
+ isc_appctx_t common;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ isc_eventlist_t on_run;
+ isc_boolean_t shutdown_requested;
+ isc_boolean_t running;
+
+ /*!
+ * We assume that 'want_shutdown' can be read and written atomically.
+ */
+ isc_boolean_t want_shutdown;
+ /*
+ * We assume that 'want_reload' can be read and written atomically.
+ */
+ isc_boolean_t want_reload;
-static isc_boolean_t blocked = ISC_FALSE;
-#ifdef ISC_PLATFORM_USETHREADS
-static pthread_t blockedthread;
-#endif /* ISC_PLATFORM_USETHREADS */
+ isc_boolean_t blocked;
+
+ isc_taskmgr_t *taskmgr;
+ isc_socketmgr_t *socketmgr;
+ isc_timermgr_t *timermgr;
+} isc__appctx_t;
+
+static isc__appctx_t isc_g_appctx;
+
+static struct {
+ isc_appmethods_t methods;
+
+ /*%
+ * The following are defined just for avoiding unused static functions.
+ */
+#ifndef BIND9
+ void *run, *shutdown, *start, *onrun, *reload, *finish,
+ *block, *unblock;
+#endif
+} appmethods = {
+ {
+ isc__appctx_destroy,
+ isc__app_ctxstart,
+ isc__app_ctxrun,
+ isc__app_ctxsuspend,
+ isc__app_ctxshutdown,
+ isc__app_ctxfinish,
+ isc__appctx_settaskmgr,
+ isc__appctx_setsocketmgr,
+ isc__appctx_settimermgr
+ }
+#ifndef BIND9
+ ,
+ (void *)isc__app_run, (void *)isc__app_shutdown,
+ (void *)isc__app_start, (void *)isc__app_onrun, (void *)isc__app_reload,
+ (void *)isc__app_finish, (void *)isc__app_block,
+ (void *)isc__app_unblock
+#endif
+};
#ifdef HAVE_LINUXTHREADS
/*!
@@ -91,13 +190,13 @@ static pthread_t main_thread;
static void
exit_action(int arg) {
UNUSED(arg);
- want_shutdown = ISC_TRUE;
+ isc_g_appctx.want_shutdown = ISC_TRUE;
}
static void
reload_action(int arg) {
UNUSED(arg);
- want_reload = ISC_TRUE;
+ isc_g_appctx.want_reload = ISC_TRUE;
}
#endif
@@ -123,12 +222,12 @@ handle_signal(int sig, void (*handler)(int)) {
return (ISC_R_SUCCESS);
}
-isc_result_t
-isc_app_start(void) {
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxstart(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
isc_result_t result;
- int presult;
- sigset_t sset;
- char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_APPCTX(ctx));
/*
* Start an ISC library application.
@@ -151,7 +250,35 @@ isc_app_start(void) {
main_thread = pthread_self();
#endif
- result = isc_mutex_init(&lock);
+ result = isc_mutex_init(&ctx->lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ ISC_LIST_INIT(ctx->on_run);
+
+ ctx->shutdown_requested = ISC_FALSE;
+ ctx->running = ISC_FALSE;
+ ctx->want_shutdown = ISC_FALSE;
+ ctx->want_reload = ISC_FALSE;
+ ctx->blocked = ISC_FALSE;
+
+ return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_start(void) {
+ isc_result_t result;
+ int presult;
+ sigset_t sset;
+ char strbuf[ISC_STRERRORSIZE];
+
+ isc_g_appctx.common.impmagic = APPCTX_MAGIC;
+ isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC;
+ isc_g_appctx.common.methods = &appmethods.methods;
+ isc_g_appctx.mctx = NULL;
+ /* The remaining members will be initialized in ctxstart() */
+
+ result = isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx);
if (result != ISC_R_SUCCESS)
return (result);
@@ -253,22 +380,20 @@ isc_app_start(void) {
}
#endif /* ISC_PLATFORM_USETHREADS */
- ISC_LIST_INIT(on_run);
-
return (ISC_R_SUCCESS);
}
-isc_result_t
-isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
void *arg)
{
isc_event_t *event;
isc_task_t *cloned_task = NULL;
isc_result_t result;
- LOCK(&lock);
+ LOCK(&isc_g_appctx.lock);
- if (running) {
+ if (isc_g_appctx.running) {
result = ISC_R_ALREADYRUNNING;
goto unlock;
}
@@ -285,24 +410,25 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
goto unlock;
}
- ISC_LIST_APPEND(on_run, event, ev_link);
+ ISC_LIST_APPEND(isc_g_appctx.on_run, event, ev_link);
result = ISC_R_SUCCESS;
unlock:
- UNLOCK(&lock);
+ UNLOCK(&isc_g_appctx.lock);
return (result);
}
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_THREADS_SINGLECTX
/*!
* Event loop for nonthreaded programs.
*/
static isc_result_t
-evloop(void) {
+evloop(isc__appctx_t *ctx) {
isc_result_t result;
- while (!want_shutdown) {
+
+ while (!ctx->want_shutdown) {
int n;
isc_time_t when, now;
struct timeval tv, *tvp;
@@ -310,14 +436,27 @@ evloop(void) {
isc_boolean_t readytasks;
isc_boolean_t call_timer_dispatch = ISC_FALSE;
- readytasks = isc__taskmgr_ready();
+ /*
+ * Check the reload (or suspend) case first for exiting the
+ * loop as fast as possible in case:
+ * - the direct call to isc__taskmgr_dispatch() in
+ * isc__app_ctxrun() completes all the tasks so far,
+ * - there is thus currently no active task, and
+ * - there is a timer event
+ */
+ if (ctx->want_reload) {
+ ctx->want_reload = ISC_FALSE;
+ return (ISC_R_RELOAD);
+ }
+
+ readytasks = isc__taskmgr_ready(ctx->taskmgr);
if (readytasks) {
tv.tv_sec = 0;
tv.tv_usec = 0;
tvp = &tv;
call_timer_dispatch = ISC_TRUE;
} else {
- result = isc__timermgr_nextevent(&when);
+ result = isc__timermgr_nextevent(ctx->timermgr, &when);
if (result != ISC_R_SUCCESS)
tvp = NULL;
else {
@@ -334,7 +473,7 @@ evloop(void) {
}
swait = NULL;
- n = isc__socketmgr_waitevents(tvp, &swait);
+ n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait);
if (n == 0 || call_timer_dispatch) {
/*
@@ -351,20 +490,17 @@ evloop(void) {
* call, since this loop only runs in the non-thread
* mode.
*/
- isc__timermgr_dispatch();
+ isc__timermgr_dispatch(ctx->timermgr);
}
if (n > 0)
- (void)isc__socketmgr_dispatch(swait);
- (void)isc__taskmgr_dispatch();
-
- if (want_reload) {
- want_reload = ISC_FALSE;
- return (ISC_R_RELOAD);
- }
+ (void)isc__socketmgr_dispatch(ctx->socketmgr, swait);
+ (void)isc__taskmgr_dispatch(ctx->taskmgr);
}
return (ISC_R_SUCCESS);
}
+#endif /* USE_THREADS_SINGLECTX */
+#ifndef ISC_PLATFORM_USETHREADS
/*
* This is a gross hack to support waiting for condition
* variables in nonthreaded programs in a limited way;
@@ -400,11 +536,11 @@ isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) {
INSIST(*mp == 1); /* Mutex must be locked on entry. */
--*mp;
- result = evloop();
+ result = evloop(&isc_g_appctx);
if (result == ISC_R_RELOAD)
- want_reload = ISC_TRUE;
+ isc_g_appctx.want_reload = ISC_TRUE;
if (signalled) {
- want_shutdown = ISC_FALSE;
+ isc_g_appctx.want_shutdown = ISC_FALSE;
signalled = ISC_FALSE;
}
@@ -420,43 +556,46 @@ isc__nothread_signal_hack(isc_condition_t *cp) {
INSIST(in_recursive_evloop);
- want_shutdown = ISC_TRUE;
+ isc_g_appctx.want_shutdown = ISC_TRUE;
signalled = ISC_TRUE;
return (ISC_R_SUCCESS);
}
#endif /* ISC_PLATFORM_USETHREADS */
-isc_result_t
-isc_app_run(void) {
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxrun(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
int result;
isc_event_t *event, *next_event;
isc_task_t *task;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_THREADS_SINGLECTX
sigset_t sset;
char strbuf[ISC_STRERRORSIZE];
#ifdef HAVE_SIGWAIT
int sig;
#endif
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_THREADS_SINGLECTX */
+
+ REQUIRE(VALID_APPCTX(ctx));
#ifdef HAVE_LINUXTHREADS
REQUIRE(main_thread == pthread_self());
#endif
- LOCK(&lock);
+ LOCK(&ctx->lock);
- if (!running) {
- running = ISC_TRUE;
+ if (!ctx->running) {
+ ctx->running = ISC_TRUE;
/*
* Post any on-run events (in FIFO order).
*/
- for (event = ISC_LIST_HEAD(on_run);
+ for (event = ISC_LIST_HEAD(ctx->on_run);
event != NULL;
event = next_event) {
next_event = ISC_LIST_NEXT(event, ev_link);
- ISC_LIST_UNLINK(on_run, event, ev_link);
+ ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
task = event->ev_sender;
event->ev_sender = NULL;
isc_task_sendanddetach(&task, &event);
@@ -464,7 +603,7 @@ isc_app_run(void) {
}
- UNLOCK(&lock);
+ UNLOCK(&ctx->lock);
#ifndef HAVE_SIGWAIT
/*
@@ -473,19 +612,27 @@ isc_app_run(void) {
* We do this here to ensure that the signal handler is installed
* (i.e. that it wasn't a "one-shot" handler).
*/
- result = handle_signal(SIGHUP, reload_action);
- if (result != ISC_R_SUCCESS)
- return (ISC_R_SUCCESS);
+ if (ctx == &isc_g_appctx) {
+ result = handle_signal(SIGHUP, reload_action);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+ }
#endif
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_THREADS_SINGLECTX
+ /*
+ * When we are using multiple contexts, we don't rely on signals.
+ */
+ if (ctx != &isc_g_appctx)
+ return (ISC_R_SUCCESS);
+
/*
* There is no danger if isc_app_shutdown() is called before we wait
* for signals. Signals are blocked, so any such signal will simply
* be made pending and we will get it when we call sigwait().
*/
- while (!want_shutdown) {
+ while (!ctx->want_shutdown) {
#ifdef HAVE_SIGWAIT
/*
* Wait for SIGHUP, SIGINT, or SIGTERM.
@@ -503,21 +650,19 @@ isc_app_run(void) {
#ifndef HAVE_UNIXWARE_SIGWAIT
result = sigwait(&sset, &sig);
if (result == 0) {
- if (sig == SIGINT ||
- sig == SIGTERM)
- want_shutdown = ISC_TRUE;
+ if (sig == SIGINT || sig == SIGTERM)
+ ctx->want_shutdown = ISC_TRUE;
else if (sig == SIGHUP)
- want_reload = ISC_TRUE;
+ ctx->want_reload = ISC_TRUE;
}
#else /* Using UnixWare sigwait semantics. */
sig = sigwait(&sset);
if (sig >= 0) {
- if (sig == SIGINT ||
- sig == SIGTERM)
- want_shutdown = ISC_TRUE;
+ if (sig == SIGINT || sig == SIGTERM)
+ ctx->want_shutdown = ISC_TRUE;
else if (sig == SIGHUP)
- want_reload = ISC_TRUE;
+ ctx->want_reload = ISC_TRUE;
}
#endif /* HAVE_UNIXWARE_SIGWAIT */
@@ -528,131 +673,174 @@ isc_app_run(void) {
if (sigemptyset(&sset) != 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_app_run() sigsetops: %s", strbuf);
+ "isc_app_run() sigsetops: %s",
+ strbuf);
return (ISC_R_UNEXPECTED);
}
result = sigsuspend(&sset);
#endif /* HAVE_SIGWAIT */
- if (want_reload) {
- want_reload = ISC_FALSE;
+ if (ctx->want_reload) {
+ ctx->want_reload = ISC_FALSE;
return (ISC_R_RELOAD);
}
- if (want_shutdown && blocked)
+ if (ctx->want_shutdown && ctx->blocked)
exit(1);
}
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_THREADS_SINGLECTX */
- (void)isc__taskmgr_dispatch();
+ (void)isc__taskmgr_dispatch(ctx->taskmgr);
- result = evloop();
+ result = evloop(ctx);
if (result != ISC_R_SUCCESS)
return (result);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_THREADS_SINGLECTX */
return (ISC_R_SUCCESS);
}
-isc_result_t
-isc_app_shutdown(void) {
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_run() {
+ return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxshutdown(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
isc_boolean_t want_kill = ISC_TRUE;
char strbuf[ISC_STRERRORSIZE];
- LOCK(&lock);
+ REQUIRE(VALID_APPCTX(ctx));
- REQUIRE(running);
+ LOCK(&ctx->lock);
- if (shutdown_requested)
+ REQUIRE(ctx->running);
+
+ if (ctx->shutdown_requested)
want_kill = ISC_FALSE;
else
- shutdown_requested = ISC_TRUE;
+ ctx->shutdown_requested = ISC_TRUE;
- UNLOCK(&lock);
+ UNLOCK(&ctx->lock);
if (want_kill) {
+ if (ctx != &isc_g_appctx)
+ ctx->want_shutdown = ISC_TRUE;
+ else {
#ifdef HAVE_LINUXTHREADS
- int result;
-
- result = pthread_kill(main_thread, SIGTERM);
- if (result != 0) {
- isc__strerror(result, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_app_shutdown() pthread_kill: %s",
- strbuf);
- return (ISC_R_UNEXPECTED);
- }
+ int result;
+
+ result = pthread_kill(main_thread, SIGTERM);
+ if (result != 0) {
+ isc__strerror(result, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_shutdown() "
+ "pthread_kill: %s",
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
#else
- if (kill(getpid(), SIGTERM) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_app_shutdown() kill: %s", strbuf);
- return (ISC_R_UNEXPECTED);
+ if (kill(getpid(), SIGTERM) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_shutdown() "
+ "kill: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+#endif /* HAVE_LINUXTHREADS */
}
-#endif
}
return (ISC_R_SUCCESS);
}
-isc_result_t
-isc_app_reload(void) {
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_shutdown() {
+ return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxsuspend(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
isc_boolean_t want_kill = ISC_TRUE;
char strbuf[ISC_STRERRORSIZE];
- LOCK(&lock);
+ REQUIRE(VALID_APPCTX(ctx));
+
+ LOCK(&ctx->lock);
- REQUIRE(running);
+ REQUIRE(ctx->running);
/*
* Don't send the reload signal if we're shutting down.
*/
- if (shutdown_requested)
+ if (ctx->shutdown_requested)
want_kill = ISC_FALSE;
- UNLOCK(&lock);
+ UNLOCK(&ctx->lock);
if (want_kill) {
+ if (ctx != &isc_g_appctx)
+ ctx->want_reload = ISC_TRUE;
+ else {
#ifdef HAVE_LINUXTHREADS
- int result;
-
- result = pthread_kill(main_thread, SIGHUP);
- if (result != 0) {
- isc__strerror(result, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_app_reload() pthread_kill: %s",
- strbuf);
- return (ISC_R_UNEXPECTED);
- }
+ int result;
+
+ result = pthread_kill(main_thread, SIGHUP);
+ if (result != 0) {
+ isc__strerror(result, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_reload() "
+ "pthread_kill: %s",
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
#else
- if (kill(getpid(), SIGHUP) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_app_reload() kill: %s", strbuf);
- return (ISC_R_UNEXPECTED);
- }
+ if (kill(getpid(), SIGHUP) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_reload() "
+ "kill: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
#endif
+ }
}
return (ISC_R_SUCCESS);
}
-void
-isc_app_finish(void) {
- DESTROYLOCK(&lock);
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_reload(void) {
+ return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE void
+isc__app_ctxfinish(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ DESTROYLOCK(&ctx->lock);
+}
+
+ISC_APPFUNC_SCOPE void
+isc__app_finish(void) {
+ isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx);
}
-void
-isc_app_block(void) {
+ISC_APPFUNC_SCOPE void
+isc__app_block(void) {
#ifdef ISC_PLATFORM_USETHREADS
sigset_t sset;
#endif /* ISC_PLATFORM_USETHREADS */
- REQUIRE(running);
- REQUIRE(!blocked);
+ REQUIRE(isc_g_appctx.running);
+ REQUIRE(!isc_g_appctx.blocked);
- blocked = ISC_TRUE;
+ isc_g_appctx.blocked = ISC_TRUE;
#ifdef ISC_PLATFORM_USETHREADS
blockedthread = pthread_self();
RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
@@ -662,16 +850,16 @@ isc_app_block(void) {
#endif /* ISC_PLATFORM_USETHREADS */
}
-void
-isc_app_unblock(void) {
+ISC_APPFUNC_SCOPE void
+isc__app_unblock(void) {
#ifdef ISC_PLATFORM_USETHREADS
sigset_t sset;
#endif /* ISC_PLATFORM_USETHREADS */
- REQUIRE(running);
- REQUIRE(blocked);
+ REQUIRE(isc_g_appctx.running);
+ REQUIRE(isc_g_appctx.blocked);
- blocked = ISC_FALSE;
+ isc_g_appctx.blocked = ISC_FALSE;
#ifdef ISC_PLATFORM_USETHREADS
REQUIRE(blockedthread == pthread_self());
@@ -682,3 +870,77 @@ isc_app_unblock(void) {
RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
#endif /* ISC_PLATFORM_USETHREADS */
}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
+ isc__appctx_t *ctx;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(ctxp != NULL && *ctxp == NULL);
+
+ ctx = isc_mem_get(mctx, sizeof(*ctx));
+ if (ctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ctx->common.impmagic = APPCTX_MAGIC;
+ ctx->common.magic = ISCAPI_APPCTX_MAGIC;
+ ctx->common.methods = &appmethods.methods;
+
+ ctx->mctx = NULL;
+ isc_mem_attach(mctx, &ctx->mctx);
+
+ ctx->taskmgr = NULL;
+ ctx->socketmgr = NULL;
+ ctx->timermgr = NULL;
+
+ *ctxp = (isc_appctx_t *)ctx;
+
+ return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_destroy(isc_appctx_t **ctxp) {
+ isc__appctx_t *ctx;
+
+ REQUIRE(ctxp != NULL);
+ ctx = (isc__appctx_t *)*ctxp;
+ REQUIRE(VALID_APPCTX(ctx));
+
+ isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
+
+ *ctxp = NULL;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ ctx->taskmgr = taskmgr;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ ctx->socketmgr = socketmgr;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ ctx->timermgr = timermgr;
+}
+
+#ifdef USE_APPIMPREGISTER
+isc_result_t
+isc__app_register() {
+ return (isc_app_register(isc__appctx_create));
+}
+#endif
diff --git a/contrib/bind9/lib/isc/unix/dir.c b/contrib/bind9/lib/isc/unix/dir.c
index 8053c42..0caf882 100644
--- a/contrib/bind9/lib/isc/unix/dir.c
+++ b/contrib/bind9/lib/isc/unix/dir.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dir.c,v 1.25.332.3 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: dir.c,v 1.29 2009-02-16 23:48:04 tbox Exp $ */
/*! \file
* \author Principal Authors: DCL */
diff --git a/contrib/bind9/lib/isc/unix/entropy.c b/contrib/bind9/lib/isc/unix/entropy.c
index bdff8d9..9044632 100644
--- a/contrib/bind9/lib/isc/unix/entropy.c
+++ b/contrib/bind9/lib/isc/unix/entropy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 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: entropy.c,v 1.80.332.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: entropy.c,v 1.82 2008-12-01 23:47:45 tbox Exp $ */
/* \file unix/entropy.c
* \brief
diff --git a/contrib/bind9/lib/isc/unix/file.c b/contrib/bind9/lib/isc/unix/file.c
index ae737b8..25d856c 100644
--- a/contrib/bind9/lib/isc/unix/file.c
+++ b/contrib/bind9/lib/isc/unix/file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -48,7 +48,7 @@
* SUCH DAMAGE.
*/
-/* $Id: file.c,v 1.51.332.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: file.c,v 1.57 2011-01-11 23:47:14 tbox Exp $ */
/*! \file */
@@ -68,6 +68,7 @@
#include <isc/dir.h>
#include <isc/file.h>
#include <isc/log.h>
+#include <isc/mem.h>
#include <isc/random.h>
#include <isc/string.h>
#include <isc/time.h>
@@ -242,16 +243,26 @@ isc_file_renameunique(const char *file, char *templet) {
return (ISC_R_SUCCESS);
}
-
isc_result_t
isc_file_openunique(char *templet, FILE **fp) {
+ int mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+ return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp) {
+ int mode = S_IWUSR|S_IRUSR;
+ return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
int fd;
FILE *f;
isc_result_t result = ISC_R_SUCCESS;
char *x;
char *cp;
isc_uint32_t which;
- int mode;
REQUIRE(templet != NULL);
REQUIRE(fp != NULL && *fp == NULL);
@@ -269,7 +280,6 @@ isc_file_openunique(char *templet, FILE **fp) {
x = cp--;
}
- mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) {
if (errno != EEXIST)
@@ -442,3 +452,73 @@ isc_file_truncate(const char *filename, isc_offset_t size) {
result = isc__errno2result(errno);
return (result);
}
+
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp) {
+ isc_result_t result;
+ int flags;
+ struct stat sb;
+ FILE *f;
+ int fd;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(fp != NULL && *fp == NULL);
+
+ result = file_stats(filename, &sb);
+ if (result == ISC_R_SUCCESS) {
+ if ((sb.st_mode & S_IFREG) == 0)
+ return (ISC_R_INVALIDFILE);
+ flags = O_WRONLY | O_TRUNC;
+ } else if (result == ISC_R_FILENOTFOUND) {
+ flags = O_WRONLY | O_CREAT | O_EXCL;
+ } else
+ return (result);
+
+ fd = open(filename, flags, S_IRUSR | S_IWUSR);
+ if (fd == -1)
+ return (isc__errno2result(errno));
+
+ f = fdopen(fd, "w");
+ if (f == NULL) {
+ result = isc__errno2result(errno);
+ close(fd);
+ return (result);
+ }
+
+ *fp = f;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename)
+{
+ char *dir, *file, *slash;
+
+ slash = strrchr(path, '/');
+
+ if (slash == path) {
+ file = ++slash;
+ dir = isc_mem_strdup(mctx, "/");
+ } else if (slash != NULL) {
+ file = ++slash;
+ dir = isc_mem_allocate(mctx, slash - path);
+ if (dir != NULL)
+ strlcpy(dir, path, slash - path);
+ } else {
+ file = path;
+ dir = isc_mem_strdup(mctx, ".");
+ }
+
+ if (dir == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (*file == '\0') {
+ isc_mem_free(mctx, dir);
+ return (ISC_R_INVALIDFILE);
+ }
+
+ *dirname = dir;
+ *basename = file;
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c b/contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c
index 1e9c814..90a3faf 100644
--- a/contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c
+++ b/contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ifiter_getifaddrs.c,v 1.11.120.2 2009-09-24 23:47:34 tbox Exp $ */
+/* $Id: ifiter_getifaddrs.c,v 1.13 2009-09-24 23:48:13 tbox Exp $ */
/*! \file
* \brief
diff --git a/contrib/bind9/lib/isc/unix/ifiter_ioctl.c b/contrib/bind9/lib/isc/unix/ifiter_ioctl.c
index c004f61..010b365 100644
--- a/contrib/bind9/lib/isc/unix/ifiter_ioctl.c
+++ b/contrib/bind9/lib/isc/unix/ifiter_ioctl.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ifiter_ioctl.c,v 1.60.120.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: ifiter_ioctl.c,v 1.62 2009-01-18 23:48:14 tbox Exp $ */
/*! \file
* \brief
diff --git a/contrib/bind9/lib/isc/unix/include/isc/net.h b/contrib/bind9/lib/isc/unix/include/isc/net.h
index 5fad793..112f1d7 100644
--- a/contrib/bind9/lib/isc/unix/include/isc/net.h
+++ b/contrib/bind9/lib/isc/unix/include/isc/net.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007-2009 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.h,v 1.48.84.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: net.h,v 1.50 2008-12-01 04:14:54 marka Exp $ */
#ifndef ISC_NET_H
#define ISC_NET_H 1
diff --git a/contrib/bind9/lib/isc/unix/include/isc/offset.h b/contrib/bind9/lib/isc/unix/include/isc/offset.h
index 91f43c37..2920899 100644
--- a/contrib/bind9/lib/isc/unix/include/isc/offset.h
+++ b/contrib/bind9/lib/isc/unix/include/isc/offset.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: offset.h,v 1.15.332.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: offset.h,v 1.17 2008-12-01 23:47:45 tbox Exp $ */
#ifndef ISC_OFFSET_H
#define ISC_OFFSET_H 1
diff --git a/contrib/bind9/lib/isc/unix/include/isc/strerror.h b/contrib/bind9/lib/isc/unix/include/isc/strerror.h
index e094e96..ac8d496 100644
--- a/contrib/bind9/lib/isc/unix/include/isc/strerror.h
+++ b/contrib/bind9/lib/isc/unix/include/isc/strerror.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: strerror.h,v 1.8.332.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: strerror.h,v 1.10 2008-12-01 23:47:45 tbox Exp $ */
#ifndef ISC_STRERROR_H
#define ISC_STRERROR_H
diff --git a/contrib/bind9/lib/isc/unix/include/isc/time.h b/contrib/bind9/lib/isc/unix/include/isc/time.h
index 2149011..19f0810 100644
--- a/contrib/bind9/lib/isc/unix/include/isc/time.h
+++ b/contrib/bind9/lib/isc/unix/include/isc/time.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: time.h,v 1.38.56.2 2009-01-05 23:47:23 tbox Exp $ */
+/* $Id: time.h,v 1.40 2009-01-05 23:47:54 tbox Exp $ */
#ifndef ISC_TIME_H
#define ISC_TIME_H 1
diff --git a/contrib/bind9/lib/isc/unix/interfaceiter.c b/contrib/bind9/lib/isc/unix/interfaceiter.c
index 2d60a33..37fc3b1 100644
--- a/contrib/bind9/lib/isc/unix/interfaceiter.c
+++ b/contrib/bind9/lib/isc/unix/interfaceiter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007-2009 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/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: interfaceiter.c,v 1.44.120.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: interfaceiter.c,v 1.45 2008-12-01 03:51:47 marka Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isc/unix/resource.c b/contrib/bind9/lib/isc/unix/resource.c
index 1061282..99a4b8c 100644
--- a/contrib/bind9/lib/isc/unix/resource.c
+++ b/contrib/bind9/lib/isc/unix/resource.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resource.c,v 1.21.66.2 2009-02-13 23:47:39 tbox Exp $ */
+/* $Id: resource.c,v 1.23 2009-02-13 23:48:14 tbox Exp $ */
#include <config.h>
diff --git a/contrib/bind9/lib/isc/unix/socket.c b/contrib/bind9/lib/isc/unix/socket.c
index 055e883..ec7487e 100644
--- a/contrib/bind9/lib/isc/unix/socket.c
+++ b/contrib/bind9/lib/isc/unix/socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: socket.c,v 1.308.12.17 2010-12-22 03:28:13 marka Exp $ */
+/* $Id: socket.c,v 1.333.14.2.2.1 2011-06-02 23:47:36 tbox Exp $ */
/*! \file */
@@ -76,9 +76,19 @@
#include "errno2result.h"
-#ifndef ISC_PLATFORM_USETHREADS
+/* See task.c about the following definition: */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_WATCHER_THREAD
+#else
+#define USE_SHARED_MANAGER
+#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* BIND9 */
+
+#ifndef USE_WATCHER_THREAD
#include "socket_p.h"
-#endif /* ISC_PLATFORM_USETHREADS */
+#include "../task_p.h"
+#endif /* USE_WATCHER_THREAD */
#if defined(SO_BSDCOMPAT) && defined(__linux__)
#include <sys/utsname.h>
@@ -101,7 +111,7 @@ typedef struct {
#define USE_SELECT
#endif /* ISC_PLATFORM_HAVEKQUEUE */
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WATCHER_THREAD
#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
struct isc_socketwait {
int nevents;
@@ -114,7 +124,7 @@ struct isc_socketwait {
int maxfd;
};
#endif /* USE_KQUEUE */
-#endif /* !ISC_PLATFORM_USETHREADS */
+#endif /* !USE_WATCHER_THREAD */
/*%
* Maximum number of allowable open sockets. This is also the maximum
@@ -248,7 +258,7 @@ typedef enum { poll_idle, poll_active, poll_checking } pollstate_t;
typedef isc_event_t intev_t;
#define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o')
-#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC)
+#define VALID_SOCKET(s) ISC_MAGIC_VALID(s, SOCKET_MAGIC)
/*!
* IPv6 control information. If the socket is an IPv6 socket we want
@@ -282,16 +292,21 @@ typedef isc_event_t intev_t;
*/
#define NRETRIES 10
-struct isc_socket {
+typedef struct isc__socket isc__socket_t;
+typedef struct isc__socketmgr isc__socketmgr_t;
+
+#define NEWCONNSOCK(ev) ((isc__socket_t *)(ev)->newsocket)
+
+struct isc__socket {
/* Not locked. */
- unsigned int magic;
- isc_socketmgr_t *manager;
+ isc_socket_t common;
+ isc__socketmgr_t *manager;
isc_mutex_t lock;
isc_sockettype_t type;
const isc_statscounter_t *statsindex;
/* Locked by socket lock. */
- ISC_LINK(isc_socket_t) link;
+ ISC_LINK(isc__socket_t) link;
unsigned int references;
int fd;
int pf;
@@ -339,9 +354,9 @@ struct isc_socket {
#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
-struct isc_socketmgr {
+struct isc__socketmgr {
/* Not locked. */
- unsigned int magic;
+ isc_socketmgr_t common;
isc_mem_t *mctx;
isc_mutex_t lock;
isc_mutex_t *fdlock;
@@ -370,14 +385,14 @@ struct isc_socketmgr {
#endif
/* Locked by fdlock. */
- isc_socket_t **fds;
+ isc__socket_t **fds;
int *fdstate;
#ifdef USE_DEVPOLL
pollinfo_t *fdpollinfo;
#endif
/* Locked by manager lock. */
- ISC_LIST(isc_socket_t) socklist;
+ ISC_LIST(isc__socket_t) socklist;
#ifdef USE_SELECT
fd_set *read_fds;
fd_set *read_fds_copy;
@@ -386,17 +401,18 @@ struct isc_socketmgr {
int maxfd;
#endif /* USE_SELECT */
int reserved; /* unlocked */
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
isc_thread_t watcher;
isc_condition_t shutdown_ok;
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WATCHER_THREAD */
unsigned int refs;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
+ int maxudp;
};
-#ifndef ISC_PLATFORM_USETHREADS
-static isc_socketmgr_t *socketmgr = NULL;
-#endif /* ISC_PLATFORM_USETHREADS */
+#ifdef USE_SHARED_MANAGER
+static isc__socketmgr_t *socketmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
#define CLOSED 0 /* this one must be zero */
#define MANAGED 1
@@ -412,26 +428,165 @@ static isc_socketmgr_t *socketmgr = NULL;
# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
#endif
-static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **);
-static void send_senddone_event(isc_socket_t *, isc_socketevent_t **);
-static void free_socket(isc_socket_t **);
-static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t,
- isc_socket_t **);
-static void destroy(isc_socket_t **);
+static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **);
+static void send_senddone_event(isc__socket_t *, isc_socketevent_t **);
+static void free_socket(isc__socket_t **);
+static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t,
+ isc__socket_t **);
+static void destroy(isc__socket_t **);
static void internal_accept(isc_task_t *, isc_event_t *);
static void internal_connect(isc_task_t *, isc_event_t *);
static void internal_recv(isc_task_t *, isc_event_t *);
static void internal_send(isc_task_t *, isc_event_t *);
static void internal_fdwatch_write(isc_task_t *, isc_event_t *);
static void internal_fdwatch_read(isc_task_t *, isc_event_t *);
-static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *);
-static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
+static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *);
+static void build_msghdr_send(isc__socket_t *, isc_socketevent_t *,
struct msghdr *, struct iovec *, size_t *);
-static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
+static void build_msghdr_recv(isc__socket_t *, isc_socketevent_t *,
struct msghdr *, struct iovec *, size_t *);
-#ifdef ISC_PLATFORM_USETHREADS
-static isc_boolean_t process_ctlfd(isc_socketmgr_t *manager);
+#ifdef USE_WATCHER_THREAD
+static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager);
+#endif
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_SOCKETFUNC_SCOPE
+#else
+#define ISC_SOCKETFUNC_SCOPE static
+#endif
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_detach(isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+ unsigned int maxsocks);
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_destroy(isc_socketmgr_t **managerp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ unsigned int minimum, isc_task_t *task,
+ isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv(isc_socket_t *sock, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv2(isc_socket_t *sock, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_socketevent_t *event, unsigned int flags);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ isc_socketevent_t *event, unsigned int flags);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
+ isc_uint32_t owner, isc_uint32_t group);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+ unsigned int options);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_filter(isc_socket_t *sock, const char *filter);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_listen(isc_socket_t *sock, unsigned int backlog);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_accept(isc_socket_t *sock,
+ isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+ isc_task_t *task, isc_taskaction_t action,
+ const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how);
+ISC_SOCKETFUNC_SCOPE isc_sockettype_t
+isc__socket_gettype(isc_socket_t *sock);
+ISC_SOCKETFUNC_SCOPE isc_boolean_t
+isc__socket_isbound(isc_socket_t *sock);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes);
+#if defined(HAVE_LIBXML2) && defined(BIND9)
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer);
+#endif
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
+ isc_sockfdwatch_t callback, void *cbarg,
+ isc_task_t *task, isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchpoke(isc_socket_t *sock, int flags);
+
+static struct {
+ isc_socketmethods_t methods;
+
+ /*%
+ * The following are defined just for avoiding unused static functions.
+ */
+#ifndef BIND9
+ void *recvv, *send, *sendv, *sendto2, *cleanunix, *permunix, *filter,
+ *listen, *accept, *getpeername, *isbound;
+#endif
+} socketmethods = {
+ {
+ isc__socket_attach,
+ isc__socket_detach,
+ isc__socket_bind,
+ isc__socket_sendto,
+ isc__socket_connect,
+ isc__socket_recv,
+ isc__socket_cancel,
+ isc__socket_getsockname,
+ isc__socket_gettype,
+ isc__socket_ipv6only,
+ isc__socket_fdwatchpoke
+ }
+#ifndef BIND9
+ ,
+ (void *)isc__socket_recvv, (void *)isc__socket_send,
+ (void *)isc__socket_sendv, (void *)isc__socket_sendto2,
+ (void *)isc__socket_cleanunix, (void *)isc__socket_permunix,
+ (void *)isc__socket_filter, (void *)isc__socket_listen,
+ (void *)isc__socket_accept, (void *)isc__socket_getpeername,
+ (void *)isc__socket_isbound
#endif
+};
+
+static isc_socketmgrmethods_t socketmgrmethods = {
+ isc__socketmgr_destroy,
+ isc__socket_create,
+ isc__socket_fdwatchcreate
+};
#define SELECT_POKE_SHUTDOWN (-1)
#define SELECT_POKE_NOTHING (-2)
@@ -531,12 +686,14 @@ static const isc_statscounter_t fdwatchstatsindex[] = {
isc_sockstatscounter_fdwatchrecvfail
};
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) || \
+ defined(USE_WATCHER_THREAD)
static void
-manager_log(isc_socketmgr_t *sockmgr,
+manager_log(isc__socketmgr_t *sockmgr,
isc_logcategory_t *category, isc_logmodule_t *module, int level,
const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
static void
-manager_log(isc_socketmgr_t *sockmgr,
+manager_log(isc__socketmgr_t *sockmgr,
isc_logcategory_t *category, isc_logmodule_t *module, int level,
const char *fmt, ...)
{
@@ -553,14 +710,15 @@ manager_log(isc_socketmgr_t *sockmgr,
isc_log_write(isc_lctx, category, module, level,
"sockmgr %p: %s", sockmgr, msgbuf);
}
+#endif
static void
-socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
+socket_log(isc__socket_t *sock, isc_sockaddr_t *address,
isc_logcategory_t *category, isc_logmodule_t *module, int level,
isc_msgcat_t *msgcat, int msgset, int message,
const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10);
static void
-socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
+socket_log(isc__socket_t *sock, isc_sockaddr_t *address,
isc_logcategory_t *category, isc_logmodule_t *module, int level,
isc_msgcat_t *msgcat, int msgset, int message,
const char *fmt, ...)
@@ -595,7 +753,7 @@ socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
* setting IPV6_V6ONLY.
*/
static void
-FIX_IPV6_RECVPKTINFO(isc_socket_t *sock)
+FIX_IPV6_RECVPKTINFO(isc__socket_t *sock)
{
char strbuf[ISC_STRERRORSIZE];
int on = 1;
@@ -632,7 +790,7 @@ inc_stats(isc_stats_t *stats, isc_statscounter_t counterid) {
}
static inline isc_result_t
-watch_fd(isc_socketmgr_t *manager, int fd, int msg) {
+watch_fd(isc__socketmgr_t *manager, int fd, int msg) {
isc_result_t result = ISC_R_SUCCESS;
#ifdef USE_KQUEUE
@@ -700,7 +858,7 @@ watch_fd(isc_socketmgr_t *manager, int fd, int msg) {
}
static inline isc_result_t
-unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) {
+unwatch_fd(isc__socketmgr_t *manager, int fd, int msg) {
isc_result_t result = ISC_R_SUCCESS;
#ifdef USE_KQUEUE
@@ -787,7 +945,7 @@ unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) {
}
static void
-wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
+wakeup_socket(isc__socketmgr_t *manager, int fd, int msg) {
isc_result_t result;
int lockid = FDLOCK_ID(fd);
@@ -848,14 +1006,14 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
}
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
/*
* Poke the select loop when there is something for us to do.
* The write is required (by POSIX) to complete. That is, we
* will not get partial writes.
*/
static void
-select_poke(isc_socketmgr_t *mgr, int fd, int msg) {
+select_poke(isc__socketmgr_t *mgr, int fd, int msg) {
int cc;
int buf[2];
char strbuf[ISC_STRERRORSIZE];
@@ -894,7 +1052,7 @@ select_poke(isc_socketmgr_t *mgr, int fd, int msg) {
* Read a message on the internal fd.
*/
static void
-select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
+select_readmsg(isc__socketmgr_t *mgr, int *fd, int *msg) {
int buf[2];
int cc;
char strbuf[ISC_STRERRORSIZE];
@@ -921,19 +1079,19 @@ select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
*fd = buf[0];
*msg = buf[1];
}
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WATCHER_THREAD */
/*
* Update the state of the socketmgr when something changes.
*/
static void
-select_poke(isc_socketmgr_t *manager, int fd, int msg) {
+select_poke(isc__socketmgr_t *manager, int fd, int msg) {
if (msg == SELECT_POKE_SHUTDOWN)
return;
else if (fd >= 0)
wakeup_socket(manager, fd, msg);
return;
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
/*
* Make a fd non-blocking.
@@ -1026,7 +1184,7 @@ cmsg_space(ISC_SOCKADDR_LEN_T len) {
* Process control messages received on a socket.
*/
static void
-process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
+process_cmsg(isc__socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
#ifdef USE_CMSG
struct cmsghdr *cmsgp;
#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
@@ -1129,7 +1287,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
* this transaction can send.
*/
static void
-build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
+build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
struct msghdr *msg, struct iovec *iov, size_t *write_countp)
{
unsigned int iovcount;
@@ -1248,7 +1406,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
* this transaction can receive.
*/
static void
-build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
+build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev,
struct msghdr *msg, struct iovec *iov, size_t *read_countp)
{
unsigned int iovcount;
@@ -1369,7 +1527,7 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
}
static void
-set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
+set_dev_address(isc_sockaddr_t *address, isc__socket_t *sock,
isc_socketevent_t *dev)
{
if (sock->type == isc_sockettype_udp) {
@@ -1393,7 +1551,7 @@ destroy_socketevent(isc_event_t *event) {
}
static isc_socketevent_t *
-allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
+allocate_socketevent(isc__socket_t *sock, isc_eventtype_t eventtype,
isc_taskaction_t action, const void *arg)
{
isc_socketevent_t *ev;
@@ -1446,7 +1604,7 @@ dump_msg(struct msghdr *msg) {
#define DOIO_EOF 3 /* EOF, no event sent */
static int
-doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
+doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) {
int cc;
struct iovec iov[MAXSCATTERGATHER_RECV];
size_t read_count;
@@ -1554,6 +1712,12 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
}
return (DOIO_SOFT);
}
+ /*
+ * Simulate a firewall blocking UDP responses bigger than
+ * 512 bytes.
+ */
+ if (sock->manager->maxudp != 0 && cc > sock->manager->maxudp)
+ return (DOIO_SOFT);
}
socket_log(sock, &dev->address, IOEVENT,
@@ -1630,7 +1794,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
* No other return values are possible.
*/
static int
-doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
+doio_send(isc__socket_t *sock, isc_socketevent_t *dev) {
int cc;
struct iovec iov[MAXSCATTERGATHER_SEND];
size_t write_count;
@@ -1741,7 +1905,7 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
* references exist.
*/
static void
-closesocket(isc_socketmgr_t *manager, isc_socket_t *sock, int fd) {
+closesocket(isc__socketmgr_t *manager, isc__socket_t *sock, int fd) {
isc_sockettype_t type = sock->type;
int lockid = FDLOCK_ID(fd);
@@ -1804,10 +1968,10 @@ closesocket(isc_socketmgr_t *manager, isc_socket_t *sock, int fd) {
}
static void
-destroy(isc_socket_t **sockp) {
+destroy(isc__socket_t **sockp) {
int fd;
- isc_socket_t *sock = *sockp;
- isc_socketmgr_t *manager = sock->manager;
+ isc__socket_t *sock = *sockp;
+ isc__socketmgr_t *manager = sock->manager;
socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_DESTROYING, "destroying");
@@ -1828,10 +1992,10 @@ destroy(isc_socket_t **sockp) {
ISC_LIST_UNLINK(manager->socklist, sock, link);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (ISC_LIST_EMPTY(manager->socklist))
SIGNAL(&manager->shutdown_ok);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
UNLOCK(&manager->lock);
@@ -1839,10 +2003,10 @@ destroy(isc_socket_t **sockp) {
}
static isc_result_t
-allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
- isc_socket_t **socketp)
+allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
+ isc__socket_t **socketp)
{
- isc_socket_t *sock;
+ isc__socket_t *sock;
isc_result_t result;
ISC_SOCKADDR_LEN_T cmsgbuflen;
@@ -1853,7 +2017,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
result = ISC_R_UNEXPECTED;
- sock->magic = 0;
+ sock->common.magic = 0;
+ sock->common.impmagic = 0;
sock->references = 0;
sock->manager = manager;
@@ -1917,7 +2082,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
*/
result = isc_mutex_init(&sock->lock);
if (result != ISC_R_SUCCESS) {
- sock->magic = 0;
+ sock->common.magic = 0;
+ sock->common.impmagic = 0;
goto error;
}
@@ -1931,7 +2097,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW,
NULL, sock, sock, NULL, NULL);
- sock->magic = SOCKET_MAGIC;
+ sock->common.magic = ISCAPI_SOCKET_MAGIC;
+ sock->common.impmagic = SOCKET_MAGIC;
*socketp = sock;
return (ISC_R_SUCCESS);
@@ -1956,8 +2123,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
* also close the socket.
*/
static void
-free_socket(isc_socket_t **socketp) {
- isc_socket_t *sock = *socketp;
+free_socket(isc__socket_t **socketp) {
+ isc__socket_t *sock = *socketp;
INSIST(sock->references == 0);
INSIST(VALID_SOCKET(sock));
@@ -1977,7 +2144,8 @@ free_socket(isc_socket_t **socketp) {
isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,
sock->sendcmsgbuflen);
- sock->magic = 0;
+ sock->common.magic = 0;
+ sock->common.impmagic = 0;
DESTROYLOCK(&sock->lock);
@@ -2025,7 +2193,7 @@ clear_bsdcompat(void) {
#endif
static isc_result_t
-opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
+opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
char strbuf[ISC_STRERRORSIZE];
const char *err = "socket";
int tries = 0;
@@ -2316,11 +2484,12 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
* called with 'arg' as the arg value. The new socket is returned
* in 'socketp'.
*/
-isc_result_t
-isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
- isc_socket_t **socketp)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp)
{
- isc_socket_t *sock = NULL;
+ isc__socket_t *sock = NULL;
+ isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
isc_result_t result;
int lockid;
@@ -2356,8 +2525,9 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
return (result);
}
+ sock->common.methods = (isc_socketmethods_t *)&socketmethods;
sock->references = 1;
- *socketp = sock;
+ *socketp = (isc_socket_t *)sock;
/*
* Note we don't have to lock the socket like we normally would because
@@ -2388,9 +2558,11 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
return (ISC_R_SUCCESS);
}
-isc_result_t
-isc_socket_open(isc_socket_t *sock) {
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_open(isc_socket_t *sock0) {
isc_result_t result;
+ isc__socket_t *sock = (isc__socket_t *)sock0;
REQUIRE(VALID_SOCKET(sock));
@@ -2430,6 +2602,7 @@ isc_socket_open(isc_socket_t *sock) {
return (result);
}
+#endif /* BIND9 */
/*
* Create a new 'type' socket managed by 'manager'. Events
@@ -2437,12 +2610,13 @@ isc_socket_open(isc_socket_t *sock) {
* called with 'arg' as the arg value. The new socket is returned
* in 'socketp'.
*/
-isc_result_t
-isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
- isc_sockfdwatch_t callback, void *cbarg,
- isc_task_t *task, isc_socket_t **socketp)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags,
+ isc_sockfdwatch_t callback, void *cbarg,
+ isc_task_t *task, isc_socket_t **socketp)
{
- isc_socket_t *sock = NULL;
+ isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+ isc__socket_t *sock = NULL;
isc_result_t result;
int lockid;
@@ -2460,8 +2634,9 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
sock->fdwatchtask = task;
sock->statsindex = fdwatchstatsindex;
+ sock->common.methods = (isc_socketmethods_t *)&socketmethods;
sock->references = 1;
- *socketp = sock;
+ *socketp = (isc_socket_t *)sock;
/*
* Note we don't have to lock the socket like we normally would because
@@ -2494,10 +2669,50 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
}
/*
+ * Indicate to the manager that it should watch the socket again.
+ * This can be used to restart watching if the previous event handler
+ * didn't indicate there was more data to be processed. Primarily
+ * it is for writing but could be used for reading if desired
+ */
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchpoke(isc_socket_t *sock0, int flags)
+{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ /*
+ * We check both flags first to allow us to get the lock
+ * once but only if we need it.
+ */
+
+ if ((flags & (ISC_SOCKFDWATCH_READ | ISC_SOCKFDWATCH_WRITE)) != 0) {
+ LOCK(&sock->lock);
+ if (((flags & ISC_SOCKFDWATCH_READ) != 0) &&
+ !sock->pending_recv)
+ select_poke(sock->manager, sock->fd,
+ SELECT_POKE_READ);
+ if (((flags & ISC_SOCKFDWATCH_WRITE) != 0) &&
+ !sock->pending_send)
+ select_poke(sock->manager, sock->fd,
+ SELECT_POKE_WRITE);
+ UNLOCK(&sock->lock);
+ }
+
+ socket_log(sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_POKED, "fdwatch-poked flags: %d", flags);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
* Attach to a socket. Caller must explicitly detach when it is done.
*/
-void
-isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_attach(isc_socket_t *sock0, isc_socket_t **socketp) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
+
REQUIRE(VALID_SOCKET(sock));
REQUIRE(socketp != NULL && *socketp == NULL);
@@ -2505,20 +2720,20 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
sock->references++;
UNLOCK(&sock->lock);
- *socketp = sock;
+ *socketp = (isc_socket_t *)sock;
}
/*
* Dereference a socket. If this is the last reference to it, clean things
* up by destroying the socket.
*/
-void
-isc_socket_detach(isc_socket_t **socketp) {
- isc_socket_t *sock;
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_detach(isc_socket_t **socketp) {
+ isc__socket_t *sock;
isc_boolean_t kill_socket = ISC_FALSE;
REQUIRE(socketp != NULL);
- sock = *socketp;
+ sock = (isc__socket_t *)*socketp;
REQUIRE(VALID_SOCKET(sock));
LOCK(&sock->lock);
@@ -2534,10 +2749,12 @@ isc_socket_detach(isc_socket_t **socketp) {
*socketp = NULL;
}
-isc_result_t
-isc_socket_close(isc_socket_t *sock) {
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_close(isc_socket_t *sock0) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
int fd;
- isc_socketmgr_t *manager;
+ isc__socketmgr_t *manager;
isc_sockettype_t type;
REQUIRE(VALID_SOCKET(sock));
@@ -2575,6 +2792,7 @@ isc_socket_close(isc_socket_t *sock) {
return (ISC_R_SUCCESS);
}
+#endif /* BIND9 */
/*
* I/O is possible on a given socket. Schedule an event to this task that
@@ -2585,7 +2803,7 @@ isc_socket_close(isc_socket_t *sock) {
* The socket and manager must be locked before calling this function.
*/
static void
-dispatch_recv(isc_socket_t *sock) {
+dispatch_recv(isc__socket_t *sock) {
intev_t *iev;
isc_socketevent_t *ev;
isc_task_t *sender;
@@ -2619,7 +2837,7 @@ dispatch_recv(isc_socket_t *sock) {
}
static void
-dispatch_send(isc_socket_t *sock) {
+dispatch_send(isc__socket_t *sock) {
intev_t *iev;
isc_socketevent_t *ev;
isc_task_t *sender;
@@ -2656,7 +2874,7 @@ dispatch_send(isc_socket_t *sock) {
* Dispatch an internal accept event.
*/
static void
-dispatch_accept(isc_socket_t *sock) {
+dispatch_accept(isc__socket_t *sock) {
intev_t *iev;
isc_socket_newconnev_t *ev;
@@ -2682,7 +2900,7 @@ dispatch_accept(isc_socket_t *sock) {
}
static void
-dispatch_connect(isc_socket_t *sock) {
+dispatch_connect(isc__socket_t *sock) {
intev_t *iev;
isc_socket_connev_t *ev;
@@ -2712,7 +2930,7 @@ dispatch_connect(isc_socket_t *sock) {
* Caller must have the socket locked if the event is attached to the socket.
*/
static void
-send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+send_recvdone_event(isc__socket_t *sock, isc_socketevent_t **dev) {
isc_task_t *task;
task = (*dev)->ev_sender;
@@ -2735,7 +2953,7 @@ send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
* Caller must have the socket locked if the event is attached to the socket.
*/
static void
-send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+send_senddone_event(isc__socket_t *sock, isc_socketevent_t **dev) {
isc_task_t *task;
INSIST(dev != NULL && *dev != NULL);
@@ -2766,8 +2984,8 @@ send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
*/
static void
internal_accept(isc_task_t *me, isc_event_t *ev) {
- isc_socket_t *sock;
- isc_socketmgr_t *manager;
+ isc__socket_t *sock;
+ isc__socketmgr_t *manager;
isc_socket_newconnev_t *dev;
isc_task_t *task;
ISC_SOCKADDR_LEN_T addrlen;
@@ -2822,9 +3040,9 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
* daemons such as BIND 8 and Apache.
*/
- addrlen = sizeof(dev->newsocket->peer_address.type);
- memset(&dev->newsocket->peer_address.type, 0, addrlen);
- fd = accept(sock->fd, &dev->newsocket->peer_address.type.sa,
+ addrlen = sizeof(NEWCONNSOCK(dev)->peer_address.type);
+ memset(&NEWCONNSOCK(dev)->peer_address.type, 0, addrlen);
+ fd = accept(sock->fd, &NEWCONNSOCK(dev)->peer_address.type.sa,
(void *)&addrlen);
#ifdef F_DUPFD
@@ -2894,14 +3112,14 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
(void)close(fd);
goto soft_error;
- } else if (dev->newsocket->peer_address.type.sa.sa_family !=
+ } else if (NEWCONNSOCK(dev)->peer_address.type.sa.sa_family !=
sock->pf)
{
UNEXPECTED_ERROR(__FILE__, __LINE__,
"internal_accept(): "
"accept() returned peer address "
"family %u (expected %u)",
- dev->newsocket->peer_address.
+ NEWCONNSOCK(dev)->peer_address.
type.sa.sa_family,
sock->pf);
(void)close(fd);
@@ -2920,8 +3138,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
}
if (fd != -1) {
- dev->newsocket->peer_address.length = addrlen;
- dev->newsocket->pf = sock->pf;
+ NEWCONNSOCK(dev)->peer_address.length = addrlen;
+ NEWCONNSOCK(dev)->pf = sock->pf;
}
/*
@@ -2950,28 +3168,28 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
int lockid = FDLOCK_ID(fd);
LOCK(&manager->fdlock[lockid]);
- manager->fds[fd] = dev->newsocket;
+ manager->fds[fd] = NEWCONNSOCK(dev);
manager->fdstate[fd] = MANAGED;
UNLOCK(&manager->fdlock[lockid]);
LOCK(&manager->lock);
- ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);
+ ISC_LIST_APPEND(manager->socklist, NEWCONNSOCK(dev), link);
- dev->newsocket->fd = fd;
- dev->newsocket->bound = 1;
- dev->newsocket->connected = 1;
+ NEWCONNSOCK(dev)->fd = fd;
+ NEWCONNSOCK(dev)->bound = 1;
+ NEWCONNSOCK(dev)->connected = 1;
/*
* Save away the remote address
*/
- dev->address = dev->newsocket->peer_address;
+ dev->address = NEWCONNSOCK(dev)->peer_address;
#ifdef USE_SELECT
if (manager->maxfd < fd)
manager->maxfd = fd;
#endif
- socket_log(sock, &dev->newsocket->peer_address, CREATION,
+ socket_log(sock, &NEWCONNSOCK(dev)->peer_address, CREATION,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
"accepted connection, new socket %p",
dev->newsocket);
@@ -2981,8 +3199,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
inc_stats(manager->stats, sock->statsindex[STATID_ACCEPT]);
} else {
inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]);
- dev->newsocket->references--;
- free_socket(&dev->newsocket);
+ NEWCONNSOCK(dev)->references--;
+ free_socket((isc__socket_t **)&dev->newsocket);
}
/*
@@ -3006,7 +3224,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
static void
internal_recv(isc_task_t *me, isc_event_t *ev) {
isc_socketevent_t *dev;
- isc_socket_t *sock;
+ isc__socket_t *sock;
INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);
@@ -3071,14 +3289,14 @@ internal_recv(isc_task_t *me, isc_event_t *ev) {
static void
internal_send(isc_task_t *me, isc_event_t *ev) {
isc_socketevent_t *dev;
- isc_socket_t *sock;
+ isc__socket_t *sock;
INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
/*
* Find out what socket this is and lock it.
*/
- sock = (isc_socket_t *)ev->ev_sender;
+ sock = (isc__socket_t *)ev->ev_sender;
INSIST(VALID_SOCKET(sock));
LOCK(&sock->lock);
@@ -3125,7 +3343,7 @@ internal_send(isc_task_t *me, isc_event_t *ev) {
static void
internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
- isc_socket_t *sock;
+ isc__socket_t *sock;
int more_data;
INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
@@ -3133,7 +3351,7 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
/*
* Find out what socket this is and lock it.
*/
- sock = (isc_socket_t *)ev->ev_sender;
+ sock = (isc__socket_t *)ev->ev_sender;
INSIST(VALID_SOCKET(sock));
LOCK(&sock->lock);
@@ -3144,7 +3362,8 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
INSIST(sock->pending_send == 1);
UNLOCK(&sock->lock);
- more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg);
+ more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock,
+ sock->fdwatcharg, ISC_SOCKFDWATCH_WRITE);
LOCK(&sock->lock);
sock->pending_send = 0;
@@ -3165,7 +3384,7 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
static void
internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
- isc_socket_t *sock;
+ isc__socket_t *sock;
int more_data;
INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);
@@ -3173,7 +3392,7 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
/*
* Find out what socket this is and lock it.
*/
- sock = (isc_socket_t *)ev->ev_sender;
+ sock = (isc__socket_t *)ev->ev_sender;
INSIST(VALID_SOCKET(sock));
LOCK(&sock->lock);
@@ -3184,7 +3403,8 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
INSIST(sock->pending_recv == 1);
UNLOCK(&sock->lock);
- more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg);
+ more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock,
+ sock->fdwatcharg, ISC_SOCKFDWATCH_READ);
LOCK(&sock->lock);
sock->pending_recv = 0;
@@ -3208,10 +3428,10 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
* and unlocking twice if both reads and writes are possible.
*/
static void
-process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable,
+process_fd(isc__socketmgr_t *manager, int fd, isc_boolean_t readable,
isc_boolean_t writeable)
{
- isc_socket_t *sock;
+ isc__socket_t *sock;
isc_boolean_t unlock_sock;
isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE;
int lockid = FDLOCK_ID(fd);
@@ -3277,11 +3497,11 @@ check_write:
#ifdef USE_KQUEUE
static isc_boolean_t
-process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
+process_fds(isc__socketmgr_t *manager, struct kevent *events, int nevents) {
int i;
isc_boolean_t readable, writable;
isc_boolean_t done = ISC_FALSE;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
isc_boolean_t have_ctlevent = ISC_FALSE;
#endif
@@ -3299,7 +3519,7 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
for (i = 0; i < nevents; i++) {
REQUIRE(events[i].ident < manager->maxsocks);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) {
have_ctlevent = ISC_TRUE;
continue;
@@ -3310,7 +3530,7 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
process_fd(manager, events[i].ident, readable, writable);
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (have_ctlevent)
done = process_ctlfd(manager);
#endif
@@ -3319,10 +3539,11 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
}
#elif defined(USE_EPOLL)
static isc_boolean_t
-process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
+process_fds(isc__socketmgr_t *manager, struct epoll_event *events, int nevents)
+{
int i;
isc_boolean_t done = ISC_FALSE;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
isc_boolean_t have_ctlevent = ISC_FALSE;
#endif
@@ -3335,7 +3556,7 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
for (i = 0; i < nevents; i++) {
REQUIRE(events[i].data.fd < (int)manager->maxsocks);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (events[i].data.fd == manager->pipe_fds[0]) {
have_ctlevent = ISC_TRUE;
continue;
@@ -3357,7 +3578,7 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
(events[i].events & EPOLLOUT) != 0);
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (have_ctlevent)
done = process_ctlfd(manager);
#endif
@@ -3366,10 +3587,10 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
}
#elif defined(USE_DEVPOLL)
static isc_boolean_t
-process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
+process_fds(isc__socketmgr_t *manager, struct pollfd *events, int nevents) {
int i;
isc_boolean_t done = ISC_FALSE;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
isc_boolean_t have_ctlevent = ISC_FALSE;
#endif
@@ -3382,7 +3603,7 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
for (i = 0; i < nevents; i++) {
REQUIRE(events[i].fd < (int)manager->maxsocks);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (events[i].fd == manager->pipe_fds[0]) {
have_ctlevent = ISC_TRUE;
continue;
@@ -3393,7 +3614,7 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
(events[i].events & POLLOUT) != 0);
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (have_ctlevent)
done = process_ctlfd(manager);
#endif
@@ -3402,27 +3623,27 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
}
#elif defined(USE_SELECT)
static void
-process_fds(isc_socketmgr_t *manager, int maxfd,
- fd_set *readfds, fd_set *writefds)
+process_fds(isc__socketmgr_t *manager, int maxfd, fd_set *readfds,
+ fd_set *writefds)
{
int i;
REQUIRE(maxfd <= (int)manager->maxsocks);
for (i = 0; i < maxfd; i++) {
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1])
continue;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
process_fd(manager, i, FD_ISSET(i, readfds),
FD_ISSET(i, writefds));
}
}
#endif
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
static isc_boolean_t
-process_ctlfd(isc_socketmgr_t *manager) {
+process_ctlfd(isc__socketmgr_t *manager) {
int msg, fd;
for (;;) {
@@ -3470,7 +3691,7 @@ process_ctlfd(isc_socketmgr_t *manager) {
*/
static isc_threadresult_t
watcher(void *uap) {
- isc_socketmgr_t *manager = uap;
+ isc__socketmgr_t *manager = uap;
isc_boolean_t done;
int ctlfd;
int cc;
@@ -3585,22 +3806,34 @@ watcher(void *uap) {
return ((isc_threadresult_t)0);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
-void
-isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager0, isc_uint32_t reserved) {
+ isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
REQUIRE(VALID_MANAGER(manager));
manager->reserved = reserved;
}
+ISC_SOCKETFUNC_SCOPE void
+isc___socketmgr_maxudp(isc_socketmgr_t *manager0, int maxudp) {
+ isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+ REQUIRE(VALID_MANAGER(manager));
+
+ manager->maxudp = maxudp;
+}
+#endif /* BIND9 */
+
/*
* Create a new socket manager.
*/
static isc_result_t
-setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
+setup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) {
isc_result_t result;
#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
char strbuf[ISC_STRERRORSIZE];
@@ -3626,7 +3859,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
return (result);
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
if (result != ISC_R_SUCCESS) {
close(manager->kqueue_fd);
@@ -3634,7 +3867,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
sizeof(struct kevent) * manager->nevents);
return (result);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
#elif defined(USE_EPOLL)
manager->nevents = ISC_SOCKET_MAXEVENTS;
manager->events = isc_mem_get(mctx, sizeof(struct epoll_event) *
@@ -3654,7 +3887,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
sizeof(struct epoll_event) * manager->nevents);
return (result);
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
if (result != ISC_R_SUCCESS) {
close(manager->epoll_fd);
@@ -3662,7 +3895,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
sizeof(struct epoll_event) * manager->nevents);
return (result);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
#elif defined(USE_DEVPOLL)
/*
* XXXJT: /dev/poll seems to reject large numbers of events,
@@ -3700,7 +3933,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
sizeof(pollinfo_t) * manager->maxsocks);
return (result);
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
if (result != ISC_R_SUCCESS) {
close(manager->devpoll_fd);
@@ -3710,7 +3943,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
sizeof(pollinfo_t) * manager->maxsocks);
return (result);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
#elif defined(USE_SELECT)
UNUSED(result);
@@ -3758,20 +3991,20 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
memset(manager->read_fds, 0, manager->fd_bufsize);
memset(manager->write_fds, 0, manager->fd_bufsize);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
(void)watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
manager->maxfd = manager->pipe_fds[0];
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WATCHER_THREAD */
manager->maxfd = 0;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
#endif /* USE_KQUEUE */
return (ISC_R_SUCCESS);
}
static void
-cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
-#ifdef ISC_PLATFORM_USETHREADS
+cleanup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) {
+#ifdef USE_WATCHER_THREAD
isc_result_t result;
result = unwatch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
@@ -3781,7 +4014,7 @@ cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"));
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
#ifdef USE_KQUEUE
close(manager->kqueue_fd);
@@ -3809,35 +4042,35 @@ cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
#endif /* USE_KQUEUE */
}
-isc_result_t
-isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
- return (isc_socketmgr_create2(mctx, managerp, 0));
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+ return (isc__socketmgr_create2(mctx, managerp, 0));
}
-isc_result_t
-isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
- unsigned int maxsocks)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+ unsigned int maxsocks)
{
int i;
- isc_socketmgr_t *manager;
-#ifdef ISC_PLATFORM_USETHREADS
+ isc__socketmgr_t *manager;
+#ifdef USE_WATCHER_THREAD
char strbuf[ISC_STRERRORSIZE];
#endif
isc_result_t result;
REQUIRE(managerp != NULL && *managerp == NULL);
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
if (socketmgr != NULL) {
/* Don't allow maxsocks to be updated */
if (maxsocks > 0 && socketmgr->maxsocks != maxsocks)
return (ISC_R_EXISTS);
socketmgr->refs++;
- *managerp = socketmgr;
+ *managerp = (isc_socketmgr_t *)socketmgr;
return (ISC_R_SUCCESS);
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
if (maxsocks == 0)
maxsocks = ISC_SOCKET_MAXSOCKETS;
@@ -3850,8 +4083,9 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
memset(manager, 0, sizeof(*manager));
manager->maxsocks = maxsocks;
manager->reserved = 0;
+ manager->maxudp = 0;
manager->fds = isc_mem_get(mctx,
- manager->maxsocks * sizeof(isc_socket_t *));
+ manager->maxsocks * sizeof(isc__socket_t *));
if (manager->fds == NULL) {
result = ISC_R_NOMEMORY;
goto free_manager;
@@ -3863,7 +4097,9 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
}
manager->stats = NULL;
- manager->magic = SOCKET_MANAGER_MAGIC;
+ manager->common.methods = &socketmgrmethods;
+ manager->common.magic = ISCAPI_SOCKETMGR_MAGIC;
+ manager->common.impmagic = SOCKET_MANAGER_MAGIC;
manager->mctx = NULL;
memset(manager->fds, 0, manager->maxsocks * sizeof(isc_socket_t *));
ISC_LIST_INIT(manager->socklist);
@@ -3887,7 +4123,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
}
}
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_condition_init() %s",
@@ -3916,9 +4152,11 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
#if 0
RUNTIME_CHECK(make_nonblock(manager->pipe_fds[1]) == ISC_R_SUCCESS);
#endif
-#else /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
+
+#ifdef USE_SHARED_MANAGER
manager->refs = 1;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
/*
* Set up initial state for the select loop
@@ -3927,7 +4165,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
if (result != ISC_R_SUCCESS)
goto cleanup;
memset(manager->fdstate, 0, manager->maxsocks * sizeof(int));
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
/*
* Start up the select/poll thread.
*/
@@ -3941,26 +4179,26 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
result = ISC_R_UNEXPECTED;
goto cleanup;
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
isc_mem_attach(mctx, &manager->mctx);
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
socketmgr = manager;
-#endif /* ISC_PLATFORM_USETHREADS */
- *managerp = manager;
+#endif /* USE_SHARED_MANAGER */
+ *managerp = (isc_socketmgr_t *)manager;
return (ISC_R_SUCCESS);
cleanup:
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
(void)close(manager->pipe_fds[0]);
(void)close(manager->pipe_fds[1]);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
cleanup_condition:
(void)isc_condition_destroy(&manager->shutdown_ok);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
cleanup_lock:
@@ -3988,8 +4226,10 @@ free_manager:
return (result);
}
+#ifdef BIND9
isc_result_t
-isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager0, unsigned int *nsockp) {
+ isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
REQUIRE(VALID_MANAGER(manager));
REQUIRE(nsockp != NULL);
@@ -3999,7 +4239,9 @@ isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
}
void
-isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
+isc__socketmgr_setstats(isc_socketmgr_t *manager0, isc_stats_t *stats) {
+ isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
REQUIRE(VALID_MANAGER(manager));
REQUIRE(ISC_LIST_EMPTY(manager->socklist));
REQUIRE(manager->stats == NULL);
@@ -4007,10 +4249,11 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
isc_stats_attach(stats, &manager->stats);
}
+#endif
-void
-isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
- isc_socketmgr_t *manager;
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
+ isc__socketmgr_t *manager;
int i;
isc_mem_t *mctx;
@@ -4019,42 +4262,36 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
*/
REQUIRE(managerp != NULL);
- manager = *managerp;
+ manager = (isc__socketmgr_t *)*managerp;
REQUIRE(VALID_MANAGER(manager));
-#ifndef ISC_PLATFORM_USETHREADS
- if (manager->refs > 1) {
- manager->refs--;
+#ifdef USE_SHARED_MANAGER
+ manager->refs--;
+ if (manager->refs > 0) {
*managerp = NULL;
return;
}
-#endif /* ISC_PLATFORM_USETHREADS */
+ socketmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
LOCK(&manager->lock);
-#ifdef ISC_PLATFORM_USETHREADS
/*
* Wait for all sockets to be destroyed.
*/
while (!ISC_LIST_EMPTY(manager->socklist)) {
+#ifdef USE_WATCHER_THREAD
manager_log(manager, CREATION, "%s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_SOCKETSREMAIN,
"sockets exist"));
WAIT(&manager->shutdown_ok, &manager->lock);
+#else /* USE_WATCHER_THREAD */
+ UNLOCK(&manager->lock);
+ isc__taskmgr_dispatch(NULL);
+ LOCK(&manager->lock);
+#endif /* USE_WATCHER_THREAD */
}
-#else /* ISC_PLATFORM_USETHREADS */
- /*
- * Hope all sockets have been destroyed.
- */
- if (!ISC_LIST_EMPTY(manager->socklist)) {
- manager_log(manager, CREATION, "%s",
- isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
- ISC_MSG_SOCKETSREMAIN,
- "sockets exist"));
- INSIST(0);
- }
-#endif /* ISC_PLATFORM_USETHREADS */
UNLOCK(&manager->lock);
@@ -4065,7 +4302,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
*/
select_poke(manager, 0, SELECT_POKE_SHUTDOWN);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
/*
* Wait for thread to exit.
*/
@@ -4074,25 +4311,25 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
"isc_thread_join() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"));
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
/*
* Clean up.
*/
cleanup_watcher(manager->mctx, manager);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
(void)close(manager->pipe_fds[0]);
(void)close(manager->pipe_fds[1]);
(void)isc_condition_destroy(&manager->shutdown_ok);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
for (i = 0; i < (int)manager->maxsocks; i++)
if (manager->fdstate[i] == CLOSE_PENDING) /* no need to lock */
(void)close(i);
isc_mem_put(manager->mctx, manager->fds,
- manager->maxsocks * sizeof(isc_socket_t *));
+ manager->maxsocks * sizeof(isc__socket_t *));
isc_mem_put(manager->mctx, manager->fdstate,
manager->maxsocks * sizeof(int));
@@ -4106,17 +4343,22 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
FDLOCK_COUNT * sizeof(isc_mutex_t));
}
DESTROYLOCK(&manager->lock);
- manager->magic = 0;
+ manager->common.magic = 0;
+ manager->common.impmagic = 0;
mctx= manager->mctx;
isc_mem_put(mctx, manager, sizeof(*manager));
isc_mem_detach(&mctx);
*managerp = NULL;
+
+#ifdef USE_SHARED_MANAGER
+ socketmgr = NULL;
+#endif
}
static isc_result_t
-socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+socket_recv(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
unsigned int flags)
{
int io_state;
@@ -4187,13 +4429,14 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
return (result);
}
-isc_result_t
-isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
- unsigned int minimum, isc_task_t *task,
- isc_taskaction_t action, const void *arg)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recvv(isc_socket_t *sock0, isc_bufferlist_t *buflist,
+ unsigned int minimum, isc_task_t *task,
+ isc_taskaction_t action, const void *arg)
{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
isc_socketevent_t *dev;
- isc_socketmgr_t *manager;
+ isc__socketmgr_t *manager;
unsigned int iocount;
isc_buffer_t *buffer;
@@ -4241,12 +4484,14 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
return (socket_recv(sock, dev, task, 0));
}
-isc_result_t
-isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
- isc_task_t *task, isc_taskaction_t action, const void *arg)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv(isc_socket_t *sock0, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_taskaction_t action, const void *arg)
{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
isc_socketevent_t *dev;
- isc_socketmgr_t *manager;
+ isc__socketmgr_t *manager;
REQUIRE(VALID_SOCKET(sock));
REQUIRE(action != NULL);
@@ -4260,14 +4505,16 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
if (dev == NULL)
return (ISC_R_NOMEMORY);
- return (isc_socket_recv2(sock, region, minimum, task, dev, 0));
+ return (isc__socket_recv2(sock0, region, minimum, task, dev, 0));
}
-isc_result_t
-isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
- unsigned int minimum, isc_task_t *task,
- isc_socketevent_t *event, unsigned int flags)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv2(isc_socket_t *sock0, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_socketevent_t *event, unsigned int flags)
{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
+
event->ev_sender = sock;
event->result = ISC_R_UNEXPECTED;
ISC_LIST_INIT(event->bufferlist);
@@ -4292,7 +4539,7 @@ isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
}
static isc_result_t
-socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
unsigned int flags)
{
@@ -4383,24 +4630,25 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
return (result);
}
-isc_result_t
-isc_socket_send(isc_socket_t *sock, isc_region_t *region,
- isc_task_t *task, isc_taskaction_t action, const void *arg)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
{
/*
* REQUIRE() checking is performed in isc_socket_sendto().
*/
- return (isc_socket_sendto(sock, region, task, action, arg, NULL,
- NULL));
+ return (isc__socket_sendto(sock, region, task, action, arg, NULL,
+ NULL));
}
-isc_result_t
-isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
- isc_task_t *task, isc_taskaction_t action, const void *arg,
- isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
isc_socketevent_t *dev;
- isc_socketmgr_t *manager;
+ isc__socketmgr_t *manager;
REQUIRE(VALID_SOCKET(sock));
REQUIRE(region != NULL);
@@ -4422,21 +4670,22 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
return (socket_send(sock, dev, task, address, pktinfo, 0));
}
-isc_result_t
-isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
- isc_task_t *task, isc_taskaction_t action, const void *arg)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
{
- return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL,
- NULL));
+ return (isc__socket_sendtov(sock, buflist, task, action, arg, NULL,
+ NULL));
}
-isc_result_t
-isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
- isc_task_t *task, isc_taskaction_t action, const void *arg,
- isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
isc_socketevent_t *dev;
- isc_socketmgr_t *manager;
+ isc__socketmgr_t *manager;
unsigned int iocount;
isc_buffer_t *buffer;
@@ -4470,12 +4719,15 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
return (socket_send(sock, dev, task, address, pktinfo, 0));
}
-isc_result_t
-isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
- isc_task_t *task,
- isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
- isc_socketevent_t *event, unsigned int flags)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto2(isc_socket_t *sock0, isc_region_t *region,
+ isc_task_t *task,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ isc_socketevent_t *event, unsigned int flags)
{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
+
+ REQUIRE(VALID_SOCKET(sock));
REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
REQUIRE(sock->type == isc_sockettype_udp);
@@ -4490,8 +4742,8 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
return (socket_send(sock, event, task, address, pktinfo, flags));
}
-void
-isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) {
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) {
#ifdef ISC_PLATFORM_HAVESYSUNH
int s;
struct stat sb;
@@ -4620,8 +4872,8 @@ isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) {
#endif
}
-isc_result_t
-isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
isc_uint32_t owner, isc_uint32_t group)
{
#ifdef ISC_PLATFORM_HAVESYSUNH
@@ -4674,12 +4926,15 @@ isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
#endif
}
-isc_result_t
-isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
- unsigned int options) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr,
+ unsigned int options) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
char strbuf[ISC_STRERRORSIZE];
int on = 1;
+ REQUIRE(VALID_SOCKET(sock));
+
LOCK(&sock->lock);
INSIST(!sock->bound);
@@ -4745,8 +5000,9 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
*/
#undef ENABLE_ACCEPTFILTER
-isc_result_t
-isc_socket_filter(isc_socket_t *sock, const char *filter) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_filter(isc_socket_t *sock0, const char *filter) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
#if defined(SO_ACCEPTFILTER) && defined(ENABLE_ACCEPTFILTER)
char strbuf[ISC_STRERRORSIZE];
struct accept_filter_arg afa;
@@ -4784,8 +5040,9 @@ isc_socket_filter(isc_socket_t *sock, const char *filter) {
* is a new connection we'll have to allocate a new one anyway, so we might
* as well keep things simple rather than having to track them.
*/
-isc_result_t
-isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_listen(isc_socket_t *sock0, unsigned int backlog) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
char strbuf[ISC_STRERRORSIZE];
REQUIRE(VALID_SOCKET(sock));
@@ -4818,14 +5075,15 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
/*
* This should try to do aggressive accept() XXXMLG
*/
-isc_result_t
-isc_socket_accept(isc_socket_t *sock,
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_accept(isc_socket_t *sock0,
isc_task_t *task, isc_taskaction_t action, const void *arg)
{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
isc_socket_newconnev_t *dev;
- isc_socketmgr_t *manager;
+ isc__socketmgr_t *manager;
isc_task_t *ntask = NULL;
- isc_socket_t *nsock;
+ isc__socket_t *nsock;
isc_result_t result;
isc_boolean_t do_poke = ISC_FALSE;
@@ -4872,7 +5130,7 @@ isc_socket_accept(isc_socket_t *sock,
nsock->statsindex = sock->statsindex;
dev->ev_sender = ntask;
- dev->newsocket = nsock;
+ dev->newsocket = (isc_socket_t *)nsock;
/*
* Poke watcher here. We still have the socket locked, so there
@@ -4891,13 +5149,14 @@ isc_socket_accept(isc_socket_t *sock,
return (ISC_R_SUCCESS);
}
-isc_result_t
-isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr,
isc_task_t *task, isc_taskaction_t action, const void *arg)
{
+ isc__socket_t *sock = (isc__socket_t *)sock0;
isc_socket_connev_t *dev;
isc_task_t *ntask = NULL;
- isc_socketmgr_t *manager;
+ isc__socketmgr_t *manager;
int cc;
char strbuf[ISC_STRERRORSIZE];
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
@@ -5037,7 +5296,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
*/
static void
internal_connect(isc_task_t *me, isc_event_t *ev) {
- isc_socket_t *sock;
+ isc__socket_t *sock;
isc_socket_connev_t *dev;
isc_task_t *task;
int cc;
@@ -5151,8 +5410,9 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
}
-isc_result_t
-isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getpeername(isc_socket_t *sock0, isc_sockaddr_t *addressp) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
isc_result_t result;
REQUIRE(VALID_SOCKET(sock));
@@ -5172,8 +5432,9 @@ isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
return (result);
}
-isc_result_t
-isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getsockname(isc_socket_t *sock0, isc_sockaddr_t *addressp) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
ISC_SOCKADDR_LEN_T len;
isc_result_t result;
char strbuf[ISC_STRERRORSIZE];
@@ -5210,8 +5471,9 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
* Run through the list of events on this socket, and cancel the ones
* queued for task "task" of type "how". "how" is a bitmask.
*/
-void
-isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cancel(isc_socket_t *sock0, isc_task_t *task, unsigned int how) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
REQUIRE(VALID_SOCKET(sock));
@@ -5290,8 +5552,8 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
ISC_LIST_UNLINK(sock->accept_list, dev,
ev_link);
- dev->newsocket->references--;
- free_socket(&dev->newsocket);
+ NEWCONNSOCK(dev)->references--;
+ free_socket((isc__socket_t **)&dev->newsocket);
dev->result = ISC_R_CANCELED;
dev->ev_sender = sock;
@@ -5330,17 +5592,22 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
UNLOCK(&sock->lock);
}
-isc_sockettype_t
-isc_socket_gettype(isc_socket_t *sock) {
+ISC_SOCKETFUNC_SCOPE isc_sockettype_t
+isc__socket_gettype(isc_socket_t *sock0) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
+
REQUIRE(VALID_SOCKET(sock));
return (sock->type);
}
-isc_boolean_t
-isc_socket_isbound(isc_socket_t *sock) {
+ISC_SOCKETFUNC_SCOPE isc_boolean_t
+isc__socket_isbound(isc_socket_t *sock0) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
isc_boolean_t val;
+ REQUIRE(VALID_SOCKET(sock));
+
LOCK(&sock->lock);
val = ((sock->bound) ? ISC_TRUE : ISC_FALSE);
UNLOCK(&sock->lock);
@@ -5348,8 +5615,9 @@ isc_socket_isbound(isc_socket_t *sock) {
return (val);
}
-void
-isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
#if defined(IPV6_V6ONLY)
int onoff = yes ? 1 : 0;
#else
@@ -5379,12 +5647,21 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
#endif
}
-#ifndef ISC_PLATFORM_USETHREADS
-/* In our assumed scenario, we can simply use a single static object. */
+#ifndef USE_WATCHER_THREAD
+/*
+ * In our assumed scenario, we can simply use a single static object.
+ * XXX: this is not true if the application uses multiple threads with
+ * 'multi-context' mode. Fixing this is a future TODO item.
+ */
static isc_socketwait_t swait_private;
int
-isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
+isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp,
+ isc_socketwait_t **swaitp)
+{
+ isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+
int n;
#ifdef USE_KQUEUE
struct timespec ts, *tsp;
@@ -5398,7 +5675,11 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
REQUIRE(swaitp != NULL && *swaitp == NULL);
- if (socketmgr == NULL)
+#ifdef USE_SHARED_MANAGER
+ if (manager == NULL)
+ manager = socketmgr;
+#endif
+ if (manager == NULL)
return (0);
#ifdef USE_KQUEUE
@@ -5408,8 +5689,8 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
tsp = &ts;
} else
tsp = NULL;
- swait_private.nevents = kevent(socketmgr->kqueue_fd, NULL, 0,
- socketmgr->events, socketmgr->nevents,
+ swait_private.nevents = kevent(manager->kqueue_fd, NULL, 0,
+ manager->events, manager->nevents,
tsp);
n = swait_private.nevents;
#elif defined(USE_EPOLL)
@@ -5417,29 +5698,28 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000;
else
timeout = -1;
- swait_private.nevents = epoll_wait(socketmgr->epoll_fd,
- socketmgr->events,
- socketmgr->nevents, timeout);
+ swait_private.nevents = epoll_wait(manager->epoll_fd,
+ manager->events,
+ manager->nevents, timeout);
n = swait_private.nevents;
#elif defined(USE_DEVPOLL)
- dvp.dp_fds = socketmgr->events;
- dvp.dp_nfds = socketmgr->nevents;
+ dvp.dp_fds = manager->events;
+ dvp.dp_nfds = manager->nevents;
if (tvp != NULL) {
dvp.dp_timeout = tvp->tv_sec * 1000 +
(tvp->tv_usec + 999) / 1000;
} else
dvp.dp_timeout = -1;
- swait_private.nevents = ioctl(socketmgr->devpoll_fd, DP_POLL, &dvp);
+ swait_private.nevents = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
n = swait_private.nevents;
#elif defined(USE_SELECT)
- memcpy(socketmgr->read_fds_copy, socketmgr->read_fds,
- socketmgr->fd_bufsize);
- memcpy(socketmgr->write_fds_copy, socketmgr->write_fds,
- socketmgr->fd_bufsize);
+ memcpy(manager->read_fds_copy, manager->read_fds, manager->fd_bufsize);
+ memcpy(manager->write_fds_copy, manager->write_fds,
+ manager->fd_bufsize);
- swait_private.readset = socketmgr->read_fds_copy;
- swait_private.writeset = socketmgr->write_fds_copy;
- swait_private.maxfd = socketmgr->maxfd + 1;
+ swait_private.readset = manager->read_fds_copy;
+ swait_private.writeset = manager->write_fds_copy;
+ swait_private.maxfd = manager->maxfd + 1;
n = select(swait_private.maxfd, swait_private.readset,
swait_private.writeset, NULL, tvp);
@@ -5450,24 +5730,32 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
}
isc_result_t
-isc__socketmgr_dispatch(isc_socketwait_t *swait) {
+isc__socketmgr_dispatch(isc_socketmgr_t *manager0, isc_socketwait_t *swait) {
+ isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
REQUIRE(swait == &swait_private);
- if (socketmgr == NULL)
+#ifdef USE_SHARED_MANAGER
+ if (manager == NULL)
+ manager = socketmgr;
+#endif
+ if (manager == NULL)
return (ISC_R_NOTFOUND);
#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
- (void)process_fds(socketmgr, socketmgr->events, swait->nevents);
+ (void)process_fds(manager, manager->events, swait->nevents);
return (ISC_R_SUCCESS);
#elif defined(USE_SELECT)
- process_fds(socketmgr, swait->maxfd, swait->readset, swait->writeset);
+ process_fds(manager, swait->maxfd, swait->readset, swait->writeset);
return (ISC_R_SUCCESS);
#endif
}
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
+#ifdef BIND9
void
-isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+isc__socket_setname(isc_socket_t *socket0, const char *name, void *tag) {
+ isc__socket_t *socket = (isc__socket_t *)socket0;
/*
* Name 'socket'.
@@ -5482,17 +5770,29 @@ isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
UNLOCK(&socket->lock);
}
-const char *
-isc_socket_getname(isc_socket_t *socket) {
+ISC_SOCKETFUNC_SCOPE const char *
+isc__socket_getname(isc_socket_t *socket0) {
+ isc__socket_t *socket = (isc__socket_t *)socket0;
+
return (socket->name);
}
void *
-isc_socket_gettag(isc_socket_t *socket) {
+isc__socket_gettag(isc_socket_t *socket0) {
+ isc__socket_t *socket = (isc__socket_t *)socket0;
+
return (socket->tag);
}
+#endif /* BIND9 */
-#ifdef HAVE_LIBXML2
+#ifdef USE_SOCKETIMPREGISTER
+isc_result_t
+isc__socket_register() {
+ return (isc_socket_register(isc__socketmgr_create));
+}
+#endif
+
+#if defined(HAVE_LIBXML2) && defined(BIND9)
static const char *
_socktype(isc_sockettype_t type)
@@ -5509,21 +5809,21 @@ _socktype(isc_sockettype_t type)
return ("not-initialized");
}
-void
-isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer)
-{
- isc_socket_t *sock;
+ISC_SOCKETFUNC_SCOPE void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer) {
+ isc__socketmgr_t *mgr = (isc__socketmgr_t *)mgr0;
+ isc__socket_t *sock;
char peerbuf[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_t addr;
ISC_SOCKADDR_LEN_T len;
LOCK(&mgr->lock);
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
xmlTextWriterEndElement(writer);
-#endif
+#endif /* USE_SHARED_MANAGER */
xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets");
sock = ISC_LIST_HEAD(mgr->socklist);
diff --git a/contrib/bind9/lib/isc/unix/socket_p.h b/contrib/bind9/lib/isc/unix/socket_p.h
index b9a2347..b6c4b6a 100644
--- a/contrib/bind9/lib/isc/unix/socket_p.h
+++ b/contrib/bind9/lib/isc/unix/socket_p.h
@@ -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) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: socket_p.h,v 1.13 2008-06-23 23:47:11 tbox Exp $ */
+/* $Id: socket_p.h,v 1.15 2009-09-02 23:48:03 tbox Exp $ */
#ifndef ISC_SOCKET_P_H
#define ISC_SOCKET_P_H
@@ -27,6 +27,7 @@
#endif
typedef struct isc_socketwait isc_socketwait_t;
-int isc__socketmgr_waitevents(struct timeval *, isc_socketwait_t **);
-isc_result_t isc__socketmgr_dispatch(isc_socketwait_t *);
+int isc__socketmgr_waitevents(isc_socketmgr_t *, struct timeval *,
+ isc_socketwait_t **);
+isc_result_t isc__socketmgr_dispatch(isc_socketmgr_t *, isc_socketwait_t *);
#endif /* ISC_SOCKET_P_H */
diff --git a/contrib/bind9/lib/isc/unix/strerror.c b/contrib/bind9/lib/isc/unix/strerror.c
index 08ea52d..4a61a97 100644
--- a/contrib/bind9/lib/isc/unix/strerror.c
+++ b/contrib/bind9/lib/isc/unix/strerror.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: strerror.c,v 1.8.332.2 2009-02-16 23:47:15 tbox Exp $ */
+/* $Id: strerror.c,v 1.10 2009-02-16 23:48:04 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/isccc/Makefile.in b/contrib/bind9/lib/isccc/Makefile.in
index fb08fcd..1417172 100644
--- a/contrib/bind9/lib/isccc/Makefile.in
+++ b/contrib/bind9/lib/isccc/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001, 2003 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -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.9 2007-06-19 23:47:21 tbox Exp $
+# $Id: Makefile.in,v 1.12.244.1.2.1 2011-06-02 23:47:37 tbox Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -71,7 +71,7 @@ libisccc.la: ${OBJS}
${LIBTOOL_MODE_LINK} \
${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccc.la -rpath ${libdir} \
-version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
- ${OBJS} ${LIBS} ${ISCLIBS}
+ ${OBJS} ${ISCLIBS} ${LIBS}
timestamp: libisccc.@A@
touch timestamp
diff --git a/contrib/bind9/lib/isccc/api b/contrib/bind9/lib/isccc/api
index 2240cdd..94575eb 100644
--- a/contrib/bind9/lib/isccc/api
+++ b/contrib/bind9/lib/isccc/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 50
-LIBREVISION = 1
+LIBINTERFACE = 80
+LIBREVISION = 0
LIBAGE = 0
diff --git a/contrib/bind9/lib/isccfg/Makefile.in b/contrib/bind9/lib/isccfg/Makefile.in
index 4c55a16..37b0a26 100644
--- a/contrib/bind9/lib/isccfg/Makefile.in
+++ b/contrib/bind9/lib/isccfg/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2005, 2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001-2003 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -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.18 2007-06-19 23:47:22 tbox Exp $
+# $Id: Makefile.in,v 1.21.244.1.2.1 2011-06-02 23:47:37 tbox Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -27,7 +27,7 @@ top_srcdir = @top_srcdir@
CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES}
-CDEFINES = @USE_DLZ@
+CDEFINES = @USE_DLZ@
CWARNINGS =
ISCLIBS = ../../lib/isc/libisc.@A@
@@ -68,7 +68,7 @@ libisccfg.la: ${OBJS}
${LIBTOOL_MODE_LINK} \
${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccfg.la -rpath ${libdir} \
-version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
- ${OBJS} ${LIBS} ${DNSLIBS} ${ISCCCLIBS} ${ISCLIBS}
+ ${OBJS} ${DNSLIBS} ${ISCCCLIBS} ${ISCLIBS} ${LIBS}
timestamp: libisccfg.@A@
touch timestamp
diff --git a/contrib/bind9/lib/isccfg/aclconf.c b/contrib/bind9/lib/isccfg/aclconf.c
index 6bf0ad8..44d436a4 100644
--- a/contrib/bind9/lib/isccfg/aclconf.c
+++ b/contrib/bind9/lib/isccfg/aclconf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 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: aclconf.c,v 1.22.34.4 2009-10-01 23:47:17 tbox Exp $ */
+/* $Id: aclconf.c,v 1.29 2010-08-13 23:47:03 tbox Exp $ */
#include <config.h>
@@ -39,7 +39,7 @@ cfg_aclconfctx_init(cfg_aclconfctx_t *ctx) {
}
void
-cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) {
+cfg_aclconfctx_clear(cfg_aclconfctx_t *ctx) {
dns_acl_t *dacl, *next;
for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
@@ -51,6 +51,23 @@ cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) {
}
}
+void
+cfg_aclconfctx_clone(cfg_aclconfctx_t *src, cfg_aclconfctx_t *dest) {
+ dns_acl_t *dacl, *next;
+ REQUIRE(src != NULL && dest != NULL);
+
+ cfg_aclconfctx_init(dest);
+ for (dacl = ISC_LIST_HEAD(src->named_acl_cache);
+ dacl != NULL;
+ dacl = next)
+ {
+ dns_acl_t *copy;
+ next = ISC_LIST_NEXT(dacl, nextincache);
+ dns_acl_attach(dacl, &copy);
+ ISC_LIST_APPEND(dest->named_acl_cache, copy, nextincache);
+ }
+}
+
/*
* Find the definition of the named acl whose name is "name".
*/
@@ -150,7 +167,7 @@ convert_keyname(const cfg_obj_t *keyobj, isc_log_t *lctx, isc_mem_t *mctx,
isc_buffer_add(&buf, keylen);
dns_fixedname_init(&fixname);
result = dns_name_fromtext(dns_fixedname_name(&fixname), &buf,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(keyobj, lctx, ISC_LOG_WARNING,
"key name '%s' is not a valid domain name",
diff --git a/contrib/bind9/lib/isccfg/api b/contrib/bind9/lib/isccfg/api
index fbbf923..7821c32 100644
--- a/contrib/bind9/lib/isccfg/api
+++ b/contrib/bind9/lib/isccfg/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 50
-LIBREVISION = 3
-LIBAGE = 0
+LIBINTERFACE = 81
+LIBREVISION = 1
+LIBAGE = 1
diff --git a/contrib/bind9/lib/isccfg/dnsconf.c b/contrib/bind9/lib/isccfg/dnsconf.c
new file mode 100644
index 0000000..7091d63
--- /dev/null
+++ b/contrib/bind9/lib/isccfg/dnsconf.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 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: dnsconf.c,v 1.4 2009-09-02 23:48:03 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
+
+/*%
+ * A trusted key, as used in the "trusted-keys" statement.
+ */
+static cfg_tuplefielddef_t trustedkey_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "flags", &cfg_type_uint32, 0 },
+ { "protocol", &cfg_type_uint32, 0 },
+ { "algorithm", &cfg_type_uint32, 0 },
+ { "key", &cfg_type_qstring, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_trustedkey = {
+ "trustedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, trustedkey_fields
+};
+
+static cfg_type_t cfg_type_trustedkeys = {
+ "trusted-keys", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+ cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_trustedkey
+};
+
+/*%
+ * Clauses that can be found within the top level of the dns.conf
+ * file only.
+ */
+static cfg_clausedef_t
+dnsconf_clauses[] = {
+ { "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI },
+ { NULL, NULL, 0 }
+};
+
+/*% The top-level dns.conf syntax. */
+
+static cfg_clausedef_t *
+dnsconf_clausesets[] = {
+ dnsconf_clauses,
+ NULL
+};
+
+LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_dnsconf = {
+ "dnsconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
+ &cfg_rep_map, dnsconf_clausesets
+};
diff --git a/contrib/bind9/lib/isccfg/include/isccfg/aclconf.h b/contrib/bind9/lib/isccfg/include/isccfg/aclconf.h
index f2ab70f..49aef03 100644
--- a/contrib/bind9/lib/isccfg/include/isccfg/aclconf.h
+++ b/contrib/bind9/lib/isccfg/include/isccfg/aclconf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: aclconf.h,v 1.10 2007-10-12 04:17:18 each Exp $ */
+/* $Id: aclconf.h,v 1.12 2010-08-13 23:47:04 tbox Exp $ */
#ifndef ISCCFG_ACLCONF_H
#define ISCCFG_ACLCONF_H 1
@@ -44,9 +44,15 @@ cfg_aclconfctx_init(cfg_aclconfctx_t *ctx);
*/
void
-cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx);
+cfg_aclconfctx_clone(cfg_aclconfctx_t *src, cfg_aclconfctx_t *dest);
/*
- * Destroy an ACL configuration context.
+ * Copy the contents of one ACL configuration context into another.
+ */
+
+void
+cfg_aclconfctx_clear(cfg_aclconfctx_t *ctx);
+/*
+ * Clear the contents of an ACL configuration context.
*/
isc_result_t
diff --git a/contrib/bind9/lib/isccfg/include/isccfg/cfg.h b/contrib/bind9/lib/isccfg/include/isccfg/cfg.h
index 06efa35..82900d6 100644
--- a/contrib/bind9/lib/isccfg/include/isccfg/cfg.h
+++ b/contrib/bind9/lib/isccfg/include/isccfg/cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010 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: cfg.h,v 1.44 2007-10-12 04:17:18 each Exp $ */
+/* $Id: cfg.h,v 1.46 2010-08-13 23:47:04 tbox Exp $ */
#ifndef ISCCFG_CFG_H
#define ISCCFG_CFG_H 1
@@ -35,6 +35,7 @@
#include <isc/formatcheck.h>
#include <isc/lang.h>
+#include <isc/refcount.h>
#include <isc/types.h>
#include <isc/list.h>
@@ -70,7 +71,7 @@ typedef struct cfg_obj cfg_obj_t;
typedef struct cfg_listelt cfg_listelt_t;
/*%
- * A callback function to be called when parsing an option
+ * A callback function to be called when parsing an option
* that needs to be interpreted at parsing time, like
* "directory".
*/
@@ -83,6 +84,12 @@ typedef isc_result_t
ISC_LANG_BEGINDECLS
+void
+cfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest);
+/*%<
+ * Reference a parser object.
+ */
+
isc_result_t
cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret);
/*%<
@@ -123,7 +130,7 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
* (isc_parse_buffer()).
*
* Returns an error if the file does not parse correctly.
- *
+ *
* Requires:
*\li "filename" is valid.
*\li "mem" is valid.
@@ -140,13 +147,14 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
void
cfg_parser_destroy(cfg_parser_t **pctxp);
/*%<
- * Destroy a configuration parser.
+ * Remove a reference to a configuration parser; destroy it if there are no
+ * more references.
*/
isc_boolean_t
cfg_obj_isvoid(const cfg_obj_t *obj);
/*%<
- * Return true iff 'obj' is of void type (e.g., an optional
+ * Return true iff 'obj' is of void type (e.g., an optional
* value not specified).
*/
@@ -355,7 +363,7 @@ cfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse);
* all contained lists.
*/
-const cfg_obj_t *
+cfg_obj_t *
cfg_listelt_value(const cfg_listelt_t *elt);
/*%<
* Returns the configuration object associated with cfg_listelt_t.
@@ -389,17 +397,25 @@ cfg_print_grammar(const cfg_type_t *type,
isc_boolean_t
cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type);
/*%<
- * Return true iff 'obj' is of type 'type'.
+ * Return true iff 'obj' is of type 'type'.
*/
-void cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **obj);
+void
+cfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest);
+/*%<
+ * Reference a configuration object.
+ */
+
+void
+cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **obj);
/*%<
- * Destroy a configuration object.
+ * Delete a reference to a configuration object; destroy the object if
+ * there are no more references.
*/
void
cfg_obj_log(const cfg_obj_t *obj, isc_log_t *lctx, int level,
- const char *fmt, ...)
+ const char *fmt, ...)
ISC_FORMAT_PRINTF(4, 5);
/*%<
* Log a message concerning configuration object 'obj' to the logging
diff --git a/contrib/bind9/lib/isccfg/include/isccfg/dnsconf.h b/contrib/bind9/lib/isccfg/include/isccfg/dnsconf.h
new file mode 100644
index 0000000..bb71338
--- /dev/null
+++ b/contrib/bind9/lib/isccfg/include/isccfg/dnsconf.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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: dnsconf.h,v 1.3 2009-09-02 23:48:03 tbox Exp $ */
+
+#ifndef ISCCFG_NAMEDCONF_H
+#define ISCCFG_NAMEDCONF_H 1
+
+/*! \file
+ * \brief
+ * This module defines the named.conf, rndc.conf, and rndc.key grammars.
+ */
+
+#include <isccfg/cfg.h>
+
+/*
+ * Configuration object types.
+ */
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_dnsconf;
+/*%< A complete dns.conf file. */
+
+#endif /* ISCCFG_CFG_H */
diff --git a/contrib/bind9/lib/isccfg/include/isccfg/grammar.h b/contrib/bind9/lib/isccfg/include/isccfg/grammar.h
index b8b845b..afc95bc 100644
--- a/contrib/bind9/lib/isccfg/include/isccfg/grammar.h
+++ b/contrib/bind9/lib/isccfg/include/isccfg/grammar.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002, 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: grammar.h,v 1.17 2008-09-25 04:02:39 tbox Exp $ */
+/* $Id: grammar.h,v 1.24 2011-01-04 23:47:14 tbox Exp $ */
#ifndef ISCCFG_GRAMMAR_H
#define ISCCFG_GRAMMAR_H 1
@@ -53,6 +53,8 @@
#define CFG_CLAUSEFLAG_CALLBACK 0x00000020
/*% A option that is only used in testing. */
#define CFG_CLAUSEFLAG_TESTONLY 0x00000040
+/*% A configuration option that was not configured at compile time. */
+#define CFG_CLAUSEFLAG_NOTCONFIGURED 0x00000080
typedef struct cfg_clausedef cfg_clausedef_t;
typedef struct cfg_tuplefielddef cfg_tuplefielddef_t;
@@ -157,6 +159,7 @@ struct cfg_obj {
isc_sockaddr_t sockaddr;
cfg_netprefix_t netprefix;
} value;
+ isc_refcount_t references; /*%< reference counter */
const char * file;
unsigned int line;
};
@@ -210,10 +213,21 @@ struct cfg_parser {
*/
unsigned int line;
+ /*%
+ * Parser context flags, used for maintaining state
+ * from one token to the next.
+ */
+ unsigned int flags;
+
+ /*%< Reference counter */
+ isc_refcount_t references;
+
cfg_parsecallback_t callback;
void *callbackarg;
};
+/* Parser context flags */
+#define CFG_PCTX_SKIP 0x1
/*@{*/
/*%
@@ -314,10 +328,16 @@ cfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port);
isc_result_t
cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+isc_result_t
+cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
void
cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj);
void
+cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+void
cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type);
isc_result_t
diff --git a/contrib/bind9/lib/isccfg/include/isccfg/log.h b/contrib/bind9/lib/isccfg/include/isccfg/log.h
index f45e4c2..2c9dc12 100644
--- a/contrib/bind9/lib/isccfg/include/isccfg/log.h
+++ b/contrib/bind9/lib/isccfg/include/isccfg/log.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.h,v 1.12.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: log.h,v 1.14 2009-01-18 23:48:14 tbox Exp $ */
#ifndef ISCCFG_LOG_H
#define ISCCFG_LOG_H 1
diff --git a/contrib/bind9/lib/isccfg/include/isccfg/namedconf.h b/contrib/bind9/lib/isccfg/include/isccfg/namedconf.h
index 34aa3e8..9242cf3 100644
--- a/contrib/bind9/lib/isccfg/include/isccfg/namedconf.h
+++ b/contrib/bind9/lib/isccfg/include/isccfg/namedconf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010 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: namedconf.h,v 1.9.332.2 2009-06-25 23:47:28 tbox Exp $ */
+/* $Id: namedconf.h,v 1.18 2010-08-11 18:14:20 each Exp $ */
#ifndef ISCCFG_NAMEDCONF_H
#define ISCCFG_NAMEDCONF_H 1
@@ -33,12 +33,24 @@
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_namedconf;
/*%< A complete named.conf file. */
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bindkeys;
+/*%< A bind.keys file. */
+
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_newzones;
+/*%< A new-zones file (for zones added by 'rndc addzone'). */
+
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_addzoneconf;
+/*%< A single zone passed via the addzone rndc command. */
+
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_rndcconf;
/*%< A complete rndc.conf file. */
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_rndckey;
/*%< A complete rndc.key file. */
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sessionkey;
+/*%< A complete session.key file. */
+
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_keyref;
/*%< A key reference, used as an ACL element */
diff --git a/contrib/bind9/lib/isccfg/namedconf.c b/contrib/bind9/lib/isccfg/namedconf.c
index f291507..f80d34b 100644
--- a/contrib/bind9/lib/isccfg/namedconf.c
+++ b/contrib/bind9/lib/isccfg/namedconf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002, 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: namedconf.c,v 1.92.44.2 2010-05-13 23:47:49 tbox Exp $ */
+/* $Id: namedconf.c,v 1.131.8.1 2011-02-03 05:50:08 marka Exp $ */
/*! \file */
@@ -24,6 +24,7 @@
#include <string.h>
#include <isc/lex.h>
+#include <isc/mem.h>
#include <isc/result.h>
#include <isc/string.h>
#include <isc/util.h>
@@ -35,9 +36,9 @@
#define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
/*% Check a return value. */
-#define CHECK(op) \
- do { result = (op); \
- if (result != ISC_R_SUCCESS) goto cleanup; \
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto cleanup; \
} while (0)
/*% Clean up a configuration object if non-NULL. */
@@ -57,7 +58,17 @@ static isc_result_t
parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
static isc_result_t
-parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret);
+
+static isc_result_t
+parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret);
+static void
+print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+static void
+doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type);
static void
print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj);
@@ -111,6 +122,7 @@ static cfg_type_t cfg_type_zone;
static cfg_type_t cfg_type_zoneopts;
static cfg_type_t cfg_type_dynamically_loadable_zones;
static cfg_type_t cfg_type_dynamically_loadable_zones_opts;
+static cfg_type_t cfg_type_v4_aaaa;
/*
* Clauses that can be found in a 'dynamically loadable zones' statement
@@ -241,30 +253,76 @@ static cfg_tuplefielddef_t pubkey_fields[] = {
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_pubkey = {
- "pubkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, pubkey_fields };
+ "pubkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, pubkey_fields };
/*%
* A list of RR types, used in grant statements.
* Note that the old parser allows quotes around the RR type names.
*/
static cfg_type_t cfg_type_rrtypelist = {
- "rrtypelist", cfg_parse_spacelist, cfg_print_spacelist, cfg_doc_terminal,
- &cfg_rep_list, &cfg_type_astring
+ "rrtypelist", cfg_parse_spacelist, cfg_print_spacelist,
+ cfg_doc_terminal, &cfg_rep_list, &cfg_type_astring
};
static const char *mode_enums[] = { "grant", "deny", NULL };
static cfg_type_t cfg_type_mode = {
- "mode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
- &mode_enums
+ "mode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+ &cfg_rep_string, &mode_enums
};
+static isc_result_t
+parse_matchtype(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret) {
+ isc_result_t result;
+
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), "zonesub") == 0) {
+ pctx->flags |= CFG_PCTX_SKIP;
+ }
+ return (cfg_parse_enum(pctx, type, ret));
+
+ cleanup:
+ return (result);
+}
+
+static isc_result_t
+parse_matchname(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+
+ if ((pctx->flags & CFG_PCTX_SKIP) != 0) {
+ pctx->flags &= ~CFG_PCTX_SKIP;
+ CHECK(cfg_parse_void(pctx, NULL, &obj));
+ } else
+ result = cfg_parse_astring(pctx, type, &obj);
+
+ *ret = obj;
+ cleanup:
+ return (result);
+}
+
+static void
+doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_print_chars(pctx, "[ ", 2);
+ cfg_doc_obj(pctx, type->of);
+ cfg_print_chars(pctx, " ]", 2);
+}
+
static const char *matchtype_enums[] = {
"name", "subdomain", "wildcard", "self", "selfsub", "selfwild",
"krb5-self", "ms-self", "krb5-subdomain", "ms-subdomain",
- "tcp-self", "6to4-self", NULL };
+ "tcp-self", "6to4-self", "zonesub", "external", NULL };
+
static cfg_type_t cfg_type_matchtype = {
- "matchtype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
- &matchtype_enums
+ "matchtype", parse_matchtype, cfg_print_ustring,
+ cfg_doc_enum, &cfg_rep_string, &matchtype_enums
+};
+
+static cfg_type_t cfg_type_matchname = {
+ "optional_matchname", parse_matchname, cfg_print_ustring,
+ &doc_matchname, &cfg_rep_tuple, &cfg_type_ustring
};
/*%
@@ -274,18 +332,70 @@ static cfg_tuplefielddef_t grant_fields[] = {
{ "mode", &cfg_type_mode, 0 },
{ "identity", &cfg_type_astring, 0 }, /* domain name */
{ "matchtype", &cfg_type_matchtype, 0 },
- { "name", &cfg_type_astring, 0 }, /* domain name */
+ { "name", &cfg_type_matchname, 0 }, /* domain name */
{ "types", &cfg_type_rrtypelist, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_grant = {
- "grant", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, grant_fields };
+ "grant", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, grant_fields
+};
static cfg_type_t cfg_type_updatepolicy = {
- "update_policy", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
- &cfg_rep_list, &cfg_type_grant
+ "update_policy", parse_updatepolicy, print_updatepolicy,
+ doc_updatepolicy, &cfg_rep_list, &cfg_type_grant
};
+static isc_result_t
+parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret) {
+ isc_result_t result;
+ CHECK(cfg_gettoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special &&
+ pctx->token.value.as_char == '{') {
+ cfg_ungettoken(pctx);
+ return (cfg_parse_bracketed_list(pctx, type, ret));
+ }
+
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), "local") == 0) {
+ cfg_obj_t *obj = NULL;
+ CHECK(cfg_create_obj(pctx, &cfg_type_ustring, &obj));
+ obj->value.string.length = strlen("local");
+ obj->value.string.base = isc_mem_get(pctx->mctx,
+ obj->value.string.length + 1);
+ if (obj->value.string.base == NULL) {
+ isc_mem_put(pctx->mctx, obj, sizeof(*obj));
+ return (ISC_R_NOMEMORY);
+ }
+ memcpy(obj->value.string.base, "local", 5);
+ obj->value.string.base[5] = '\0';
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+ }
+
+ cfg_ungettoken(pctx);
+ return (ISC_R_UNEXPECTEDTOKEN);
+
+ cleanup:
+ return (result);
+}
+
+static void
+print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ if (cfg_obj_isstring(obj))
+ cfg_print_ustring(pctx, obj);
+ else
+ cfg_print_bracketed_list(pctx, obj);
+}
+
+static void
+doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_print_cstr(pctx, "( local | { ");
+ cfg_doc_obj(pctx, type->of);
+ cfg_print_cstr(pctx, "; ... }");
+}
+
/*%
* A view statement.
*/
@@ -296,7 +406,9 @@ static cfg_tuplefielddef_t view_fields[] = {
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_view = {
- "view", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, view_fields };
+ "view", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, view_fields
+};
/*%
* A zone statement.
@@ -308,7 +420,9 @@ static cfg_tuplefielddef_t zone_fields[] = {
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_zone = {
- "zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, zone_fields };
+ "zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, zone_fields
+};
/*%
* A "category" clause in the "logging" statement.
@@ -319,13 +433,15 @@ static cfg_tuplefielddef_t category_fields[] = {
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_category = {
- "category", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, category_fields };
+ "category", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, category_fields
+};
/*%
- * A trusted key, as used in the "trusted-keys" statement.
+ * A dnssec key, as used in the "trusted-keys" statement.
*/
-static cfg_tuplefielddef_t trustedkey_fields[] = {
+static cfg_tuplefielddef_t dnsseckey_fields[] = {
{ "name", &cfg_type_astring, 0 },
{ "flags", &cfg_type_uint32, 0 },
{ "protocol", &cfg_type_uint32, 0 },
@@ -333,9 +449,27 @@ static cfg_tuplefielddef_t trustedkey_fields[] = {
{ "key", &cfg_type_qstring, 0 },
{ NULL, NULL, 0 }
};
-static cfg_type_t cfg_type_trustedkey = {
- "trustedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
- trustedkey_fields
+static cfg_type_t cfg_type_dnsseckey = {
+ "dnsseckey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, dnsseckey_fields
+};
+
+/*%
+ * A managed key initialization specifier, as used in the
+ * "managed-keys" statement.
+ */
+static cfg_tuplefielddef_t managedkey_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "init", &cfg_type_ustring, 0 }, /* must be literal "initial-key" */
+ { "flags", &cfg_type_uint32, 0 },
+ { "protocol", &cfg_type_uint32, 0 },
+ { "algorithm", &cfg_type_uint32, 0 },
+ { "key", &cfg_type_qstring, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_managedkey = {
+ "managedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, managedkey_fields
};
static keyword_type_t wild_class_kw = { "class", &cfg_type_ustring };
@@ -397,6 +531,7 @@ static cfg_tuplefielddef_t checknames_fields[] = {
{ "mode", &cfg_type_checkmode, 0 },
{ NULL, NULL, 0 }
};
+
static cfg_type_t cfg_type_checknames = {
"checknames", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
checknames_fields
@@ -407,6 +542,13 @@ static cfg_type_t cfg_type_bracketed_sockaddrlist = {
&cfg_rep_list, &cfg_type_sockaddr
};
+static const char *autodnssec_enums[] = { "allow", "maintain", "create",
+ "off", NULL };
+static cfg_type_t cfg_type_autodnssec = {
+ "autodnssec", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+ &cfg_rep_string, &autodnssec_enums
+};
+
static cfg_type_t cfg_type_rrsetorder = {
"rrsetorder", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
&cfg_rep_list, &cfg_type_rrsetorderingelement
@@ -421,13 +563,27 @@ static cfg_type_t cfg_type_optional_port = {
/*% A list of keys, as in the "key" clause of the controls statement. */
static cfg_type_t cfg_type_keylist = {
- "keylist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
- &cfg_type_astring
+ "keylist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+ cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring
+};
+
+/*% A list of dnssec keys, as in "trusted-keys" */
+static cfg_type_t cfg_type_dnsseckeys = {
+ "dnsseckeys", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+ cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_dnsseckey
};
-static cfg_type_t cfg_type_trustedkeys = {
- "trusted-keys", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
- &cfg_type_trustedkey
+/*%
+ * A list of managed key entries, as in "trusted-keys". Currently
+ * (9.7.0) this has a format similar to dnssec keys, except the keyname
+ * is followed by the keyword "initial-key". In future releases, this
+ * keyword may take other values indicating different methods for the
+ * key to be initialized.
+ */
+
+static cfg_type_t cfg_type_managedkeys = {
+ "managedkeys", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+ cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_managedkey
};
static const char *forwardtype_enums[] = { "first", "only", NULL };
@@ -437,7 +593,8 @@ static cfg_type_t cfg_type_forwardtype = {
};
static const char *zonetype_enums[] = {
- "master", "slave", "stub", "hint", "forward", "delegation-only", NULL };
+ "master", "slave", "stub", "static-stub", "hint", "forward",
+ "delegation-only", NULL };
static cfg_type_t cfg_type_zonetype = {
"zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
&cfg_rep_string, &zonetype_enums
@@ -479,6 +636,7 @@ parse_qstringornone(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
isc_result_t result;
+
CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
if (pctx->token.type == isc_tokentype_string &&
strcasecmp(TOKEN_STRING(pctx), "none") == 0)
@@ -496,13 +654,65 @@ doc_qstringornone(cfg_printer_t *pctx, const cfg_type_t *type) {
}
static cfg_type_t cfg_type_qstringornone = {
- "qstringornone", parse_qstringornone, NULL, doc_qstringornone, NULL, NULL };
+ "qstringornone", parse_qstringornone, NULL, doc_qstringornone,
+ NULL, NULL
+};
/*%
- * keyword hostname
+ * A boolean ("yes" or "no"), or the special keyword "auto".
+ * Used in the dnssec-validation option.
*/
+static void
+print_auto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ UNUSED(obj);
+ cfg_print_cstr(pctx, "auto");
+}
+
+static cfg_type_t cfg_type_auto = {
+ "auto", NULL, print_auto, NULL, &cfg_rep_void, NULL
+};
+
+static isc_result_t
+parse_boolorauto(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+
+ CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), "auto") == 0)
+ return (cfg_create_obj(pctx, &cfg_type_auto, ret));
+ cfg_ungettoken(pctx);
+ return (cfg_parse_boolean(pctx, type, ret));
+ cleanup:
+ return (result);
+}
static void
+print_boolorauto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ if (obj->type->rep == &cfg_rep_void)
+ cfg_print_chars(pctx, "auto", 4);
+ else if (obj->value.boolean)
+ cfg_print_chars(pctx, "yes", 3);
+ else
+ cfg_print_chars(pctx, "no", 2);
+}
+
+static void
+doc_boolorauto(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_cstr(pctx, "( yes | no | auto )");
+}
+
+static cfg_type_t cfg_type_boolorauto = {
+ "boolorauto", parse_boolorauto, print_boolorauto,
+ doc_boolorauto, NULL, NULL
+};
+
+/*%
+ * keyword hostname
+ */
+static void
print_hostname(cfg_printer_t *pctx, const cfg_obj_t *obj) {
UNUSED(obj);
cfg_print_cstr(pctx, "hostname");
@@ -652,7 +862,18 @@ namedconf_or_view_clauses[] = {
/* only 1 DLZ per view allowed */
{ "dlz", &cfg_type_dynamically_loadable_zones, 0 },
{ "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
- { "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI },
+ { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
+ { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI },
+ { NULL, NULL, 0 }
+};
+
+/*%
+ * Clauses that can occur in the bind.keys file.
+ */
+static cfg_clausedef_t
+bindkeys_clauses[] = {
+ { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
+ { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI },
{ NULL, NULL, 0 }
};
@@ -661,18 +882,21 @@ namedconf_or_view_clauses[] = {
*/
static cfg_clausedef_t
options_clauses[] = {
- { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
- { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
{ "avoid-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
{ "avoid-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
+ { "bindkeys-file", &cfg_type_qstring, 0 },
{ "blackhole", &cfg_type_bracketed_aml, 0 },
{ "coresize", &cfg_type_size, 0 },
{ "datasize", &cfg_type_size, 0 },
+ { "session-keyfile", &cfg_type_qstringornone, 0 },
+ { "session-keyname", &cfg_type_astring, 0 },
+ { "session-keyalg", &cfg_type_astring, 0 },
{ "deallocate-on-exit", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
{ "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK },
{ "dump-file", &cfg_type_qstring, 0 },
{ "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
{ "files", &cfg_type_size, 0 },
+ { "flush-zones-on-shutdown", &cfg_type_boolean, 0 },
{ "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
{ "heartbeat-interval", &cfg_type_uint32, 0 },
{ "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP },
@@ -681,6 +905,7 @@ options_clauses[] = {
{ "interface-interval", &cfg_type_uint32, 0 },
{ "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
{ "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
+ { "managed-keys-directory", &cfg_type_qstring, 0 },
{ "match-mapped-addresses", &cfg_type_boolean, 0 },
{ "memstatistics-file", &cfg_type_qstring, 0 },
{ "memstatistics", &cfg_type_boolean, 0 },
@@ -693,6 +918,7 @@ options_clauses[] = {
{ "random-device", &cfg_type_qstring, 0 },
{ "recursive-clients", &cfg_type_uint32, 0 },
{ "reserved-sockets", &cfg_type_uint32, 0 },
+ { "secroots-file", &cfg_type_qstring, 0 },
{ "serial-queries", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
{ "serial-query-rate", &cfg_type_uint32, 0 },
{ "server-id", &cfg_type_serverid, 0 },
@@ -703,6 +929,7 @@ options_clauses[] = {
{ "tcp-listen-queue", &cfg_type_uint32, 0 },
{ "tkey-dhkey", &cfg_type_tkey_dhkey, 0 },
{ "tkey-gssapi-credential", &cfg_type_qstring, 0 },
+ { "tkey-gssapi-keytab", &cfg_type_qstring, 0 },
{ "tkey-domain", &cfg_type_qstring, 0 },
{ "transfers-per-ns", &cfg_type_uint32, 0 },
{ "transfers-in", &cfg_type_uint32, 0 },
@@ -710,12 +937,12 @@ options_clauses[] = {
{ "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
{ "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
{ "use-ixfr", &cfg_type_boolean, 0 },
+ { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
+ { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
{ "version", &cfg_type_qstringornone, 0 },
- { "flush-zones-on-shutdown", &cfg_type_boolean, 0 },
{ NULL, NULL, 0 }
};
-
static cfg_type_t cfg_type_namelist = {
"namelist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_qstring };
@@ -726,6 +953,34 @@ static cfg_type_t cfg_type_optional_exclude = {
"optional_exclude", parse_optional_keyvalue, print_keyvalue,
doc_optional_keyvalue, &cfg_rep_list, &exclude_kw };
+static keyword_type_t exceptionnames_kw = { "except-from", &cfg_type_namelist };
+
+static cfg_type_t cfg_type_optional_exceptionnames = {
+ "optional_allow", parse_optional_keyvalue, print_keyvalue,
+ doc_optional_keyvalue, &cfg_rep_list, &exceptionnames_kw };
+
+static cfg_tuplefielddef_t denyaddresses_fields[] = {
+ { "acl", &cfg_type_bracketed_aml, 0 },
+ { "except-from", &cfg_type_optional_exceptionnames, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_denyaddresses = {
+ "denyaddresses", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, denyaddresses_fields
+};
+
+static cfg_tuplefielddef_t denyaliases_fields[] = {
+ { "name", &cfg_type_namelist, 0 },
+ { "except-from", &cfg_type_optional_exceptionnames, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_denyaliases = {
+ "denyaliases", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, denyaliases_fields
+};
+
static cfg_type_t cfg_type_algorithmlist = {
"algorithmlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring };
@@ -758,20 +1013,134 @@ static cfg_type_t cfg_type_masterformat = {
&cfg_rep_string, &masterformat_enums
};
+
+
+/*
+ * response-policy {
+ * zone <string> [ policy (given|no-op|nxdomain|nodata|cname <domain> ) ];
+ * };
+ *
+ * this is a chimera of doc_optional_keyvalue() and cfg_doc_enum()
+ */
+static void
+doc_rpz_policies(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const keyword_type_t *kw;
+ const char * const *p;
+
+ kw = type->of;
+ cfg_print_chars(pctx, "[ ", 2);
+ cfg_print_cstr(pctx, kw->name);
+ cfg_print_chars(pctx, " ", 1);
+
+ cfg_print_chars(pctx, "( ", 2);
+ for (p = kw->type->of; *p != NULL; p++) {
+ cfg_print_cstr(pctx, *p);
+ if (p[1] != NULL)
+ cfg_print_chars(pctx, " | ", 3);
+ }
+}
+
+/*
+ * print_qstring() from parser.c
+ */
+static void
+print_rpz_cname(cfg_printer_t *pctx, const cfg_obj_t *obj)
+{
+ cfg_print_chars(pctx, "\"", 1);
+ cfg_print_ustring(pctx, obj);
+ cfg_print_chars(pctx, "\"", 1);
+}
+
+static void
+doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_doc_terminal(pctx, type);
+ cfg_print_chars(pctx, " ) ]", 4);
+}
+
+static isc_result_t
+parse_rpz(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ const cfg_tuplefielddef_t *fields = type->of;
+
+ CHECK(cfg_create_tuple(pctx, type, &obj));
+ CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
+ CHECK(cfg_parse_obj(pctx, fields[1].type, &obj->value.tuple[1]));
+ /*
+ * parse cname domain only after "policy cname"
+ */
+ if (cfg_obj_isvoid(obj->value.tuple[1]) ||
+ strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[1]))) {
+ CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
+ } else {
+ CHECK(cfg_parse_obj(pctx, fields[2].type, &obj->value.tuple[2]));
+ }
+
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static const char *rpz_policies[] = {
+ "given", "no-op", "nxdomain", "nodata", "cname", NULL
+};
+static cfg_type_t cfg_type_rpz_policylist = {
+ "policies", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+ &cfg_rep_string, &rpz_policies
+};
+static keyword_type_t rpz_policies_kw = {
+ "policy", &cfg_type_rpz_policylist
+};
+static cfg_type_t cfg_type_rpz_policy = {
+ "optional_policy", parse_optional_keyvalue, print_keyvalue,
+ doc_rpz_policies, &cfg_rep_string, &rpz_policies_kw
+};
+static cfg_type_t cfg_type_cname = {
+ "domain", cfg_parse_astring, print_rpz_cname, doc_rpz_cname,
+ &cfg_rep_string, NULL
+};
+static cfg_tuplefielddef_t rpzone_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "policy", &cfg_type_rpz_policy, 0 },
+ { "cname", &cfg_type_cname, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_rpzone = {
+ "rpzone", parse_rpz, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, rpzone_fields
+};
+static cfg_clausedef_t rpz_clauses[] = {
+ { "zone", &cfg_type_rpzone, CFG_CLAUSEFLAG_MULTI },
+ { NULL, NULL, 0 }
+};
+static cfg_clausedef_t *rpz_clausesets[] = {
+ rpz_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_rpz = {
+ "rpz", cfg_parse_map, cfg_print_map, cfg_doc_map,
+ &cfg_rep_map, rpz_clausesets
+};
+
+
+
/*%
* dnssec-lookaside
*/
static keyword_type_t trustanchor_kw = { "trust-anchor", &cfg_type_astring };
-static cfg_type_t cfg_type_trustanchor = {
- "trust-anchor", parse_keyvalue, print_keyvalue, doc_keyvalue,
- &cfg_rep_string, &trustanchor_kw
+static cfg_type_t cfg_type_optional_trustanchor = {
+ "optional_trustanchor", parse_optional_keyvalue, print_keyvalue,
+ doc_keyvalue, &cfg_rep_string, &trustanchor_kw
};
static cfg_tuplefielddef_t lookaside_fields[] = {
{ "domain", &cfg_type_astring, 0 },
- { "trust-anchor", &cfg_type_trustanchor, 0 },
+ { "trust-anchor", &cfg_type_optional_trustanchor, 0 },
{ NULL, NULL, 0 }
};
@@ -780,6 +1149,31 @@ static cfg_type_t cfg_type_lookaside = {
&cfg_rep_tuple, lookaside_fields
};
+/*
+ * DNS64.
+ */
+static cfg_clausedef_t
+dns64_clauses[] = {
+ { "clients", &cfg_type_bracketed_aml, 0 },
+ { "mapped", &cfg_type_bracketed_aml, 0 },
+ { "exclude", &cfg_type_bracketed_aml, 0 },
+ { "suffix", &cfg_type_netaddr6, 0 },
+ { "recursive-only", &cfg_type_boolean, 0 },
+ { "break-dnssec", &cfg_type_boolean, 0 },
+ { NULL, NULL, 0 },
+};
+
+static cfg_clausedef_t *
+dns64_clausesets[] = {
+ dns64_clauses,
+ NULL
+};
+
+static cfg_type_t cfg_type_dns64 = {
+ "dns64", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map,
+ &cfg_rep_map, dns64_clausesets
+};
+
/*%
* Clauses that can be found within the 'view' statement,
* with defaults in the 'options' statement.
@@ -791,26 +1185,33 @@ view_clauses[] = {
{ "acache-enable", &cfg_type_boolean, 0 },
{ "additional-from-auth", &cfg_type_boolean, 0 },
{ "additional-from-cache", &cfg_type_boolean, 0 },
+ { "allow-new-zones", &cfg_type_boolean, 0 },
{ "allow-query-cache", &cfg_type_bracketed_aml, 0 },
{ "allow-query-cache-on", &cfg_type_bracketed_aml, 0 },
{ "allow-recursion", &cfg_type_bracketed_aml, 0 },
{ "allow-recursion-on", &cfg_type_bracketed_aml, 0 },
{ "allow-v6-synthesis", &cfg_type_bracketed_aml,
CFG_CLAUSEFLAG_OBSOLETE },
+ { "attach-cache", &cfg_type_astring, 0 },
{ "auth-nxdomain", &cfg_type_boolean, CFG_CLAUSEFLAG_NEWDEFAULT },
{ "cache-file", &cfg_type_qstring, 0 },
{ "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
{ "cleaning-interval", &cfg_type_uint32, 0 },
{ "clients-per-query", &cfg_type_uint32, 0 },
+ { "deny-answer-addresses", &cfg_type_denyaddresses, 0 },
+ { "deny-answer-aliases", &cfg_type_denyaliases, 0 },
{ "disable-algorithms", &cfg_type_disablealgorithm,
CFG_CLAUSEFLAG_MULTI },
{ "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
+ { "dns64", &cfg_type_dns64, CFG_CLAUSEFLAG_MULTI },
+ { "dns64-server", &cfg_type_astring, 0 },
+ { "dns64-contact", &cfg_type_astring, 0 },
{ "dnssec-accept-expired", &cfg_type_boolean, 0 },
{ "dnssec-enable", &cfg_type_boolean, 0 },
{ "dnssec-lookaside", &cfg_type_lookaside, CFG_CLAUSEFLAG_MULTI },
{ "dnssec-must-be-secure", &cfg_type_mustbesecure,
CFG_CLAUSEFLAG_MULTI },
- { "dnssec-validation", &cfg_type_boolean, 0 },
+ { "dnssec-validation", &cfg_type_boolorauto, 0 },
{ "dual-stack-servers", &cfg_type_nameportiplist, 0 },
{ "edns-udp-size", &cfg_type_uint32, 0 },
{ "empty-contact", &cfg_type_astring, 0 },
@@ -841,6 +1242,7 @@ view_clauses[] = {
{ "recursion", &cfg_type_boolean, 0 },
{ "request-ixfr", &cfg_type_boolean, 0 },
{ "request-nsid", &cfg_type_boolean, 0 },
+ { "resolver-query-timeout", &cfg_type_uint32, 0 },
{ "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
{ "root-delegation-only", &cfg_type_optional_exclude, 0 },
{ "rrset-order", &cfg_type_rrsetorder, 0 },
@@ -850,6 +1252,16 @@ view_clauses[] = {
{ "transfer-format", &cfg_type_transferformat, 0 },
{ "use-queryport-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
{ "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ { "filter-aaaa", &cfg_type_bracketed_aml, 0 },
+ { "filter-aaaa-on-v4", &cfg_type_v4_aaaa, 0 },
+#else
+ { "filter-aaaa", &cfg_type_bracketed_aml,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "filter-aaaa-on-v4", &cfg_type_v4_aaaa,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
+#endif
+ { "response-policy", &cfg_type_rpz, 0 },
{ NULL, NULL, 0 }
};
@@ -920,6 +1332,7 @@ zone_clauses[] = {
{ "also-notify", &cfg_type_portiplist, 0 },
{ "alt-transfer-source", &cfg_type_sockaddr4wild, 0 },
{ "alt-transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
+ { "check-dup-records", &cfg_type_checkmode, 0 },
{ "check-integrity", &cfg_type_boolean, 0 },
{ "check-mx", &cfg_type_checkmode, 0 },
{ "check-mx-cname", &cfg_type_checkmode, 0 },
@@ -927,6 +1340,8 @@ zone_clauses[] = {
{ "check-srv-cname", &cfg_type_checkmode, 0 },
{ "check-wildcard", &cfg_type_boolean, 0 },
{ "dialup", &cfg_type_dialuptype, 0 },
+ { "dnssec-dnskey-kskonly", &cfg_type_boolean, 0 },
+ { "dnssec-secure-to-insecure", &cfg_type_boolean, 0 },
{ "forward", &cfg_type_forwardtype, 0 },
{ "forwarders", &cfg_type_portiplist, 0 },
{ "key-directory", &cfg_type_qstring, 0 },
@@ -986,6 +1401,9 @@ zone_only_clauses[] = {
*/
{ "check-names", &cfg_type_checkmode, 0 },
{ "ixfr-from-differences", &cfg_type_boolean, 0 },
+ { "auto-dnssec", &cfg_type_autodnssec, 0 },
+ { "server-addresses", &cfg_type_bracketed_sockaddrlist, 0 },
+ { "server-names", &cfg_type_namelist, 0 },
{ NULL, NULL, 0 }
};
@@ -998,12 +1416,40 @@ namedconf_clausesets[] = {
namedconf_or_view_clauses,
NULL
};
-
LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_namedconf = {
"namedconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
&cfg_rep_map, namedconf_clausesets
};
+/*% The bind.keys syntax (trusted-keys/managed-keys only). */
+static cfg_clausedef_t *
+bindkeys_clausesets[] = {
+ bindkeys_clauses,
+ NULL
+};
+LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bindkeys = {
+ "bindkeys", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
+ &cfg_rep_map, bindkeys_clausesets
+};
+
+/*% The new-zone-file syntax (for zones added by 'rndc addzone') */
+static cfg_clausedef_t
+newzones_clauses[] = {
+ { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+newzones_clausesets[] = {
+ newzones_clauses,
+ NULL
+};
+
+LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_newzones = {
+ "newzones", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
+ &cfg_rep_map, newzones_clausesets
+};
+
/*% The "options" statement syntax. */
static cfg_clausedef_t *
@@ -1166,6 +1612,38 @@ static cfg_type_t cfg_type_logging = {
"logging", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, logging_clausesets };
+/*%
+ * For parsing an 'addzone' statement
+ */
+
+static cfg_tuplefielddef_t addzone_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "class", &cfg_type_optional_class, 0 },
+ { "view", &cfg_type_optional_class, 0 },
+ { "options", &cfg_type_zoneopts, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_addzone = {
+ "addzone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, addzone_fields };
+
+static cfg_clausedef_t
+addzoneconf_clauses[] = {
+ { "addzone", &cfg_type_addzone, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+addzoneconf_clausesets[] = {
+ addzoneconf_clauses,
+ NULL
+};
+
+LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_addzoneconf = {
+ "addzoneconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
+ &cfg_rep_map, addzoneconf_clausesets
+};
+
+
static isc_result_t
parse_unitstring(char *str, isc_resourcevalue_t *valuep) {
char *endp;
@@ -1385,6 +1863,17 @@ static cfg_type_t cfg_type_ixfrdifftype = {
&cfg_rep_string, ixfrdiff_enums,
};
+static const char *v4_aaaa_enums[] = { "break-dnssec", NULL };
+static isc_result_t
+parse_v4_aaaa(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret) {
+ return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
+}
+static cfg_type_t cfg_type_v4_aaaa = {
+ "v4_aaaa", parse_v4_aaaa, cfg_print_ustring,
+ doc_enum_or_other, &cfg_rep_string, v4_aaaa_enums,
+};
+
static keyword_type_t key_kw = { "key", &cfg_type_astring };
LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_keyref = {
@@ -2082,6 +2571,15 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndckey = {
&cfg_rep_map, rndckey_clausesets
};
+/*
+ * session.key has exactly the same syntax as rndc.key, but it's defined
+ * separately for clarity (and so we can extend it someday, if needed).
+ */
+LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_sessionkey = {
+ "sessionkey", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
+ &cfg_rep_map, rndckey_clausesets
+};
+
static cfg_tuplefielddef_t nameport_fields[] = {
{ "name", &cfg_type_astring, 0 },
{ "port", &cfg_type_optional_port, 0 },
diff --git a/contrib/bind9/lib/isccfg/parser.c b/contrib/bind9/lib/isccfg/parser.c
index 2f64a09..87ad391 100644
--- a/contrib/bind9/lib/isccfg/parser.c
+++ b/contrib/bind9/lib/isccfg/parser.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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: parser.c,v 1.129 2008-09-25 04:02:39 tbox Exp $ */
+/* $Id: parser.c,v 1.139 2011-01-04 23:47:14 tbox Exp $ */
/*! \file */
@@ -29,12 +29,12 @@
#include <isc/mem.h>
#include <isc/net.h>
#include <isc/netaddr.h>
+#include <isc/netscope.h>
#include <isc/print.h>
#include <isc/string.h>
#include <isc/sockaddr.h>
-#include <isc/netscope.h>
-#include <isc/util.h>
#include <isc/symtab.h>
+#include <isc/util.h>
#include <isccfg/cfg.h>
#include <isccfg/grammar.h>
@@ -387,6 +387,12 @@ cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) {
if (pctx == NULL)
return (ISC_R_NOMEMORY);
+ result = isc_refcount_init(&pctx->references, 1);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, pctx, sizeof(*pctx));
+ return (result);
+ }
+
pctx->mctx = mctx;
pctx->lctx = lctx;
pctx->lexer = NULL;
@@ -400,6 +406,7 @@ cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) {
pctx->callback = NULL;
pctx->callbackarg = NULL;
pctx->token.type = isc_tokentype_unknown;
+ pctx->flags = 0;
memset(specials, 0, sizeof(specials));
specials['{'] = 1;
@@ -526,17 +533,30 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
}
void
+cfg_parser_attach(cfg_parser_t *src, cfg_parser_t **dest) {
+ REQUIRE(src != NULL);
+ REQUIRE(dest != NULL && *dest == NULL);
+ isc_refcount_increment(&src->references, NULL);
+ *dest = src;
+}
+
+void
cfg_parser_destroy(cfg_parser_t **pctxp) {
cfg_parser_t *pctx = *pctxp;
- isc_lex_destroy(&pctx->lexer);
- /*
- * Cleaning up open_files does not
- * close the files; that was already done
- * by closing the lexer.
- */
- CLEANUP_OBJ(pctx->open_files);
- CLEANUP_OBJ(pctx->closed_files);
- isc_mem_put(pctx->mctx, pctx, sizeof(*pctx));
+ unsigned int refs;
+
+ isc_refcount_decrement(&pctx->references, &refs);
+ if (refs == 0) {
+ isc_lex_destroy(&pctx->lexer);
+ /*
+ * Cleaning up open_files does not
+ * close the files; that was already done
+ * by closing the lexer.
+ */
+ CLEANUP_OBJ(pctx->open_files);
+ CLEANUP_OBJ(pctx->closed_files);
+ isc_mem_put(pctx->mctx, pctx, sizeof(*pctx));
+ }
*pctxp = NULL;
}
@@ -848,8 +868,8 @@ cfg_obj_asboolean(const cfg_obj_t *obj) {
return (obj->value.boolean);
}
-static isc_result_t
-parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+isc_result_t
+cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
{
isc_result_t result;
isc_boolean_t value;
@@ -888,8 +908,8 @@ parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
return (result);
}
-static void
-print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+void
+cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) {
if (obj->value.boolean)
cfg_print_chars(pctx, "yes", 3);
else
@@ -897,7 +917,7 @@ print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) {
}
cfg_type_t cfg_type_boolean = {
- "boolean", parse_boolean, print_boolean, cfg_doc_terminal,
+ "boolean", cfg_parse_boolean, cfg_print_boolean, cfg_doc_terminal,
&cfg_rep_boolean, NULL
};
@@ -1132,7 +1152,7 @@ cfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse) {
return (count);
}
-const cfg_obj_t *
+cfg_obj_t *
cfg_listelt_value(const cfg_listelt_t *elt) {
REQUIRE(elt != NULL);
return (elt->obj);
@@ -1237,6 +1257,14 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
if ((clause->flags & CFG_CLAUSEFLAG_NYI) != 0)
cfg_parser_warning(pctx, 0, "option '%s' is "
"not implemented", clause->name);
+
+ if ((clause->flags & CFG_CLAUSEFLAG_NOTCONFIGURED) != 0) {
+ cfg_parser_warning(pctx, 0, "option '%s' is not "
+ "configured", clause->name);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
/*
* Don't log options with CFG_CLAUSEFLAG_NEWDEFAULT
* set here - we need to log the *lack* of such an option,
@@ -1478,6 +1506,7 @@ static struct flagtext {
{ CFG_CLAUSEFLAG_OBSOLETE, "obsolete" },
{ CFG_CLAUSEFLAG_NEWDEFAULT, "default changed" },
{ CFG_CLAUSEFLAG_TESTONLY, "test only" },
+ { CFG_CLAUSEFLAG_NOTCONFIGURED, "not configured" },
{ 0, NULL }
};
@@ -2305,6 +2334,7 @@ cfg_obj_line(const cfg_obj_t *obj) {
isc_result_t
cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
cfg_obj_t *obj;
obj = isc_mem_get(pctx->mctx, sizeof(cfg_obj_t));
@@ -2313,10 +2343,16 @@ cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
obj->type = type;
obj->file = current_file(pctx);
obj->line = pctx->line;
+ result = isc_refcount_init(&obj->references, 1);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t));
+ return (result);
+ }
*ret = obj;
return (ISC_R_SUCCESS);
}
+
static void
map_symtabitem_destroy(char *key, unsigned int type,
isc_symvalue_t symval, void *userarg)
@@ -2370,11 +2406,25 @@ cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type) {
void
cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **objp) {
cfg_obj_t *obj = *objp;
- obj->type->rep->free(pctx, obj);
- isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t));
+ unsigned int refs;
+
+ isc_refcount_decrement(&obj->references, &refs);
+ if (refs == 0) {
+ obj->type->rep->free(pctx, obj);
+ isc_refcount_destroy(&obj->references);
+ isc_mem_put(pctx->mctx, obj, sizeof(cfg_obj_t));
+ }
*objp = NULL;
}
+void
+cfg_obj_attach(cfg_obj_t *src, cfg_obj_t **dest) {
+ REQUIRE(src != NULL);
+ REQUIRE(dest != NULL && *dest == NULL);
+ isc_refcount_increment(&src->references, NULL);
+ *dest = src;
+}
+
static void
free_noop(cfg_parser_t *pctx, cfg_obj_t *obj) {
UNUSED(pctx);
diff --git a/contrib/bind9/lib/lwres/api b/contrib/bind9/lib/lwres/api
index fbbf923..94575eb 100644
--- a/contrib/bind9/lib/lwres/api
+++ b/contrib/bind9/lib/lwres/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 50
-LIBREVISION = 3
+LIBINTERFACE = 80
+LIBREVISION = 0
LIBAGE = 0
diff --git a/contrib/bind9/lib/lwres/context.c b/contrib/bind9/lib/lwres/context.c
index 1310022..e8f0eda 100644
--- a/contrib/bind9/lib/lwres/context.c
+++ b/contrib/bind9/lib/lwres/context.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: context.c,v 1.50.332.5 2009-09-01 23:47:05 tbox Exp $ */
+/* $Id: context.c,v 1.55 2009-09-02 23:48:03 tbox Exp $ */
/*! \file context.c
lwres_context_create() creates a #lwres_context_t structure for use in
diff --git a/contrib/bind9/lib/lwres/context_p.h b/contrib/bind9/lib/lwres/context_p.h
index 663b1da..0976951 100644
--- a/contrib/bind9/lib/lwres/context_p.h
+++ b/contrib/bind9/lib/lwres/context_p.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: context_p.h,v 1.17.332.2 2008-12-30 23:46:49 tbox Exp $ */
+/* $Id: context_p.h,v 1.19 2008-12-17 23:47:58 tbox Exp $ */
#ifndef LWRES_CONTEXT_P_H
#define LWRES_CONTEXT_P_H 1
diff --git a/contrib/bind9/lib/lwres/getaddrinfo.c b/contrib/bind9/lib/lwres/getaddrinfo.c
index 665205a..81534fc 100644
--- a/contrib/bind9/lib/lwres/getaddrinfo.c
+++ b/contrib/bind9/lib/lwres/getaddrinfo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* This code is derived from software contributed to ISC by
@@ -18,7 +18,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: getaddrinfo.c,v 1.52.254.2 2009-03-31 23:47:16 tbox Exp $ */
+/* $Id: getaddrinfo.c,v 1.54 2008-11-25 23:47:23 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/lwres/getipnode.c b/contrib/bind9/lib/lwres/getipnode.c
index b9eadee..bc90c74 100644
--- a/contrib/bind9/lib/lwres/getipnode.c
+++ b/contrib/bind9/lib/lwres/getipnode.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: getipnode.c,v 1.42.332.5 2009-09-01 23:47:05 tbox Exp $ */
+/* $Id: getipnode.c,v 1.47 2009-09-01 23:47:45 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/lwres/include/lwres/context.h b/contrib/bind9/lib/lwres/include/lwres/context.h
index 46be27a..2421b57 100644
--- a/contrib/bind9/lib/lwres/include/lwres/context.h
+++ b/contrib/bind9/lib/lwres/include/lwres/context.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: context.h,v 1.21.332.2 2008-12-30 23:46:49 tbox Exp $ */
+/* $Id: context.h,v 1.23 2008-12-17 23:47:58 tbox Exp $ */
#ifndef LWRES_CONTEXT_H
#define LWRES_CONTEXT_H 1
diff --git a/contrib/bind9/lib/lwres/include/lwres/netdb.h.in b/contrib/bind9/lib/lwres/include/lwres/netdb.h.in
index 7531ca3..8eedd27 100644
--- a/contrib/bind9/lib/lwres/include/lwres/netdb.h.in
+++ b/contrib/bind9/lib/lwres/include/lwres/netdb.h.in
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: netdb.h.in,v 1.39.332.2 2009-01-18 23:47:41 tbox Exp $ */
+/* $Id: netdb.h.in,v 1.41 2009-01-18 23:48:14 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/lwres/lwconfig.c b/contrib/bind9/lib/lwres/lwconfig.c
index 356c106..764ff2a 100644
--- a/contrib/bind9/lib/lwres/lwconfig.c
+++ b/contrib/bind9/lib/lwres/lwconfig.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lwconfig.c,v 1.46.332.2 2008-12-30 23:46:49 tbox Exp $ */
+/* $Id: lwconfig.c,v 1.48 2008-12-17 23:47:58 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/lib/lwres/man/lwres.3 b/contrib/bind9/lib/lwres/man/lwres.3
index 77f96b6..c2c0bb6 100644
--- a/contrib/bind9/lib/lwres/man/lwres.3
+++ b/contrib/bind9/lib/lwres/man/lwres.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres.3,v 1.29 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres.html b/contrib/bind9/lib/lwres/man/lwres.html
index 3844c01..6cfb750 100644
--- a/contrib/bind9/lib/lwres/man/lwres.html
+++ b/contrib/bind9/lib/lwres/man/lwres.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres.html,v 1.23.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres.html,v 1.24.484.1 2011-06-09 03:41:05 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres &#8212; introduction to the lightweight resolver library</p>
@@ -32,7 +32,7 @@
<div class="funcsynopsis"><pre class="funcsynopsisinfo">#include &lt;lwres/lwres.h&gt;</pre></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543348"></a><h2>DESCRIPTION</h2>
+<a name="id2543346"></a><h2>DESCRIPTION</h2>
<p>
The BIND 9 lightweight resolver library is a simple, name service
independent stub resolver library. It provides hostname-to-address
@@ -47,7 +47,7 @@
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543361"></a><h2>OVERVIEW</h2>
+<a name="id2543358"></a><h2>OVERVIEW</h2>
<p>
The lwresd library implements multiple name service APIs.
The standard
@@ -101,7 +101,7 @@
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543425"></a><h2>CLIENT-SIDE LOW-LEVEL API CALL FLOW</h2>
+<a name="id2543422"></a><h2>CLIENT-SIDE LOW-LEVEL API CALL FLOW</h2>
<p>
When a client program wishes to make an lwres request using the
native low-level API, it typically performs the following
@@ -149,7 +149,7 @@
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543573"></a><h2>SERVER-SIDE LOW-LEVEL API CALL FLOW</h2>
+<a name="id2543571"></a><h2>SERVER-SIDE LOW-LEVEL API CALL FLOW</h2>
<p>
When implementing the server side of the lightweight resolver
protocol using the lwres library, a sequence of actions like the
@@ -191,7 +191,7 @@
<p></p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543656"></a><h2>SEE ALSO</h2>
+<a name="id2543654"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">lwres_gethostent</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">lwres_getipnode</span>(3)</span>,
diff --git a/contrib/bind9/lib/lwres/man/lwres_buffer.3 b/contrib/bind9/lib/lwres/man/lwres_buffer.3
index 89b9b65..0fc5225 100644
--- a/contrib/bind9/lib/lwres/man/lwres_buffer.3
+++ b/contrib/bind9/lib/lwres/man/lwres_buffer.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_buffer.3,v 1.26.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_buffer.3,v 1.27 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_buffer.html b/contrib/bind9/lib/lwres/man/lwres_buffer.html
index 7f3934a..b7e034f 100644
--- a/contrib/bind9/lib/lwres/man/lwres_buffer.html
+++ b/contrib/bind9/lib/lwres/man/lwres_buffer.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_buffer.html,v 1.21.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_buffer.html,v 1.22.484.1 2011-06-09 03:41:05 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_buffer_init, lwres_buffer_invalidate, lwres_buffer_add, lwres_buffer_subtract, lwres_buffer_clear, lwres_buffer_first, lwres_buffer_forward, lwres_buffer_back, lwres_buffer_getuint8, lwres_buffer_putuint8, lwres_buffer_getuint16, lwres_buffer_putuint16, lwres_buffer_getuint32, lwres_buffer_putuint32, lwres_buffer_putmem, lwres_buffer_getmem &#8212; lightweight resolver buffer management</p>
@@ -262,7 +262,7 @@ void
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543892"></a><h2>DESCRIPTION</h2>
+<a name="id2543890"></a><h2>DESCRIPTION</h2>
<p>
These functions provide bounds checked access to a region of memory
where data is being read or written.
diff --git a/contrib/bind9/lib/lwres/man/lwres_config.3 b/contrib/bind9/lib/lwres/man/lwres_config.3
index 5b8a728..0ea1320 100644
--- a/contrib/bind9/lib/lwres/man/lwres_config.3
+++ b/contrib/bind9/lib/lwres/man/lwres_config.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_config.3,v 1.26.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_config.3,v 1.27 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_config.html b/contrib/bind9/lib/lwres/man/lwres_config.html
index 2cee5ef..8c330a3 100644
--- a/contrib/bind9/lib/lwres/man/lwres_config.html
+++ b/contrib/bind9/lib/lwres/man/lwres_config.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_config.html,v 1.22.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_config.html,v 1.23.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_conf_init, lwres_conf_clear, lwres_conf_parse, lwres_conf_print, lwres_conf_get &#8212; lightweight resolver configuration</p>
@@ -90,7 +90,7 @@ lwres_conf_t *
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543441"></a><h2>DESCRIPTION</h2>
+<a name="id2543438"></a><h2>DESCRIPTION</h2>
<p><code class="function">lwres_conf_init()</code>
creates an empty
<span class="type">lwres_conf_t</span>
@@ -123,7 +123,7 @@ lwres_conf_t *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543508"></a><h2>RETURN VALUES</h2>
+<a name="id2543506"></a><h2>RETURN VALUES</h2>
<p><code class="function">lwres_conf_parse()</code>
returns <span class="errorcode">LWRES_R_SUCCESS</span>
if it successfully read and parsed
@@ -142,13 +142,13 @@ lwres_conf_t *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543545"></a><h2>SEE ALSO</h2>
+<a name="id2543543"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">stdio</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">resolver</span>(5)</span>.
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543571"></a><h2>FILES</h2>
+<a name="id2543569"></a><h2>FILES</h2>
<p><code class="filename">/etc/resolv.conf</code>
</p>
</div>
diff --git a/contrib/bind9/lib/lwres/man/lwres_context.3 b/contrib/bind9/lib/lwres/man/lwres_context.3
index a96a075..fdcaf55 100644
--- a/contrib/bind9/lib/lwres/man/lwres_context.3
+++ b/contrib/bind9/lib/lwres/man/lwres_context.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_context.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_context.3,v 1.29 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_context.html b/contrib/bind9/lib/lwres/man/lwres_context.html
index d525a4b..50d5d9f 100644
--- a/contrib/bind9/lib/lwres/man/lwres_context.html
+++ b/contrib/bind9/lib/lwres/man/lwres_context.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_context.html,v 1.23.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_context.html,v 1.24.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_context_create, lwres_context_destroy, lwres_context_nextserial, lwres_context_initserial, lwres_context_freemem, lwres_context_allocmem, lwres_context_sendrecv &#8212; lightweight resolver context management</p>
@@ -172,7 +172,7 @@ void *
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543531"></a><h2>DESCRIPTION</h2>
+<a name="id2543529"></a><h2>DESCRIPTION</h2>
<p><code class="function">lwres_context_create()</code>
creates a <span class="type">lwres_context_t</span> structure for use in
lightweight resolver operations. It holds a socket and other
@@ -258,7 +258,7 @@ void *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543719"></a><h2>RETURN VALUES</h2>
+<a name="id2543717"></a><h2>RETURN VALUES</h2>
<p><code class="function">lwres_context_create()</code>
returns <span class="errorcode">LWRES_R_NOMEMORY</span> if memory for
the <span class="type">struct lwres_context</span> could not be allocated,
@@ -283,7 +283,7 @@ void *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543769"></a><h2>SEE ALSO</h2>
+<a name="id2543767"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">lwres_conf_init</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">malloc</span>(3)</span>,
diff --git a/contrib/bind9/lib/lwres/man/lwres_gabn.3 b/contrib/bind9/lib/lwres/man/lwres_gabn.3
index 28ea7e1..769c952 100644
--- a/contrib/bind9/lib/lwres/man/lwres_gabn.3
+++ b/contrib/bind9/lib/lwres/man/lwres_gabn.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_gabn.3,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_gabn.3,v 1.28 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_gabn.html b/contrib/bind9/lib/lwres/man/lwres_gabn.html
index b69f432..32b5f21 100644
--- a/contrib/bind9/lib/lwres/man/lwres_gabn.html
+++ b/contrib/bind9/lib/lwres/man/lwres_gabn.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_gabn.html,v 1.24.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_gabn.html,v 1.25.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_gabnrequest_render, lwres_gabnresponse_render, lwres_gabnrequest_parse, lwres_gabnresponse_parse, lwres_gabnresponse_free, lwres_gabnrequest_free &#8212; lightweight resolver getaddrbyname message handling</p>
@@ -178,7 +178,7 @@ void
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543522"></a><h2>DESCRIPTION</h2>
+<a name="id2543520"></a><h2>DESCRIPTION</h2>
<p>
These are low-level routines for creating and parsing
lightweight resolver name-to-address lookup request and
@@ -278,7 +278,7 @@ typedef struct {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543667"></a><h2>RETURN VALUES</h2>
+<a name="id2543665"></a><h2>RETURN VALUES</h2>
<p>
The getaddrbyname opcode functions
<code class="function">lwres_gabnrequest_render()</code>,
@@ -316,7 +316,7 @@ typedef struct {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543733"></a><h2>SEE ALSO</h2>
+<a name="id2543731"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">lwres_packet</span>(3)</span>
</p>
</div>
diff --git a/contrib/bind9/lib/lwres/man/lwres_gai_strerror.3 b/contrib/bind9/lib/lwres/man/lwres_gai_strerror.3
index 3d80727..2527896 100644
--- a/contrib/bind9/lib/lwres/man/lwres_gai_strerror.3
+++ b/contrib/bind9/lib/lwres/man/lwres_gai_strerror.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_gai_strerror.3,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_gai_strerror.3,v 1.28 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_gai_strerror.html b/contrib/bind9/lib/lwres/man/lwres_gai_strerror.html
index 616eebe..9ff330b 100644
--- a/contrib/bind9/lib/lwres/man/lwres_gai_strerror.html
+++ b/contrib/bind9/lib/lwres/man/lwres_gai_strerror.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_gai_strerror.html,v 1.24.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_gai_strerror.html,v 1.25.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_gai_strerror &#8212; print suitable error string</p>
@@ -42,7 +42,7 @@ char *
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543361"></a><h2>DESCRIPTION</h2>
+<a name="id2543358"></a><h2>DESCRIPTION</h2>
<p><code class="function">lwres_gai_strerror()</code>
returns an error message corresponding to an error code returned by
<code class="function">getaddrinfo()</code>.
@@ -110,7 +110,7 @@ char *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543576"></a><h2>SEE ALSO</h2>
+<a name="id2543574"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">strerror</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">lwres_getaddrinfo</span>(3)</span>,
diff --git a/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.3 b/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.3
index 2953f3b..cfc4aec 100644
--- a/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.3
+++ b/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_getaddrinfo.3,v 1.31.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_getaddrinfo.3,v 1.32 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html b/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html
index 013e878..d367f51 100644
--- a/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html
+++ b/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_getaddrinfo.html,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_getaddrinfo.html,v 1.28.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_getaddrinfo, lwres_freeaddrinfo &#8212; socket address structure to host and service name</p>
@@ -89,7 +89,7 @@ struct addrinfo {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543412"></a><h2>DESCRIPTION</h2>
+<a name="id2543410"></a><h2>DESCRIPTION</h2>
<p><code class="function">lwres_getaddrinfo()</code>
is used to get a list of IP addresses and port numbers for host
<em class="parameter"><code>hostname</code></em> and service
@@ -283,7 +283,7 @@ struct addrinfo {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543789"></a><h2>RETURN VALUES</h2>
+<a name="id2543787"></a><h2>RETURN VALUES</h2>
<p><code class="function">lwres_getaddrinfo()</code>
returns zero on success or one of the error codes listed in
<span class="citerefentry"><span class="refentrytitle">gai_strerror</span>(3)</span>
@@ -294,7 +294,7 @@ struct addrinfo {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543827"></a><h2>SEE ALSO</h2>
+<a name="id2542118"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">lwres_getaddrinfo</span>(3)</span>,
diff --git a/contrib/bind9/lib/lwres/man/lwres_gethostent.3 b/contrib/bind9/lib/lwres/man/lwres_gethostent.3
index 35ea1c2..7acc506 100644
--- a/contrib/bind9/lib/lwres/man/lwres_gethostent.3
+++ b/contrib/bind9/lib/lwres/man/lwres_gethostent.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_gethostent.3,v 1.29.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_gethostent.3,v 1.30 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_gethostent.html b/contrib/bind9/lib/lwres/man/lwres_gethostent.html
index fd27dcf..fdaa062 100644
--- a/contrib/bind9/lib/lwres/man/lwres_gethostent.html
+++ b/contrib/bind9/lib/lwres/man/lwres_gethostent.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_gethostent.html,v 1.24.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_gethostent.html,v 1.25.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_gethostbyname, lwres_gethostbyname2, lwres_gethostbyaddr, lwres_gethostent, lwres_sethostent, lwres_endhostent, lwres_gethostbyname_r, lwres_gethostbyaddr_r, lwres_gethostent_r, lwres_sethostent_r, lwres_endhostent_r &#8212; lightweight resolver get network host entry</p>
@@ -228,7 +228,7 @@ void
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543608"></a><h2>DESCRIPTION</h2>
+<a name="id2543606"></a><h2>DESCRIPTION</h2>
<p>
These functions provide hostname-to-address and
address-to-hostname lookups by means of the lightweight resolver.
@@ -366,7 +366,7 @@ struct hostent {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543959"></a><h2>RETURN VALUES</h2>
+<a name="id2543957"></a><h2>RETURN VALUES</h2>
<p>
The functions
<code class="function">lwres_gethostbyname()</code>,
@@ -430,7 +430,7 @@ struct hostent {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2544193"></a><h2>SEE ALSO</h2>
+<a name="id2544190"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">gethostent</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">lwres_getipnode</span>(3)</span>,
@@ -439,7 +439,7 @@ struct hostent {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2544227"></a><h2>BUGS</h2>
+<a name="id2544225"></a><h2>BUGS</h2>
<p><code class="function">lwres_gethostbyname()</code>,
<code class="function">lwres_gethostbyname2()</code>,
<code class="function">lwres_gethostbyaddr()</code>
diff --git a/contrib/bind9/lib/lwres/man/lwres_getipnode.3 b/contrib/bind9/lib/lwres/man/lwres_getipnode.3
index b46e78f..40ba59c 100644
--- a/contrib/bind9/lib/lwres/man/lwres_getipnode.3
+++ b/contrib/bind9/lib/lwres/man/lwres_getipnode.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_getipnode.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_getipnode.3,v 1.29 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_getipnode.html b/contrib/bind9/lib/lwres/man/lwres_getipnode.html
index 20c6d30..9f54cb6 100644
--- a/contrib/bind9/lib/lwres/man/lwres_getipnode.html
+++ b/contrib/bind9/lib/lwres/man/lwres_getipnode.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_getipnode.html,v 1.25.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_getipnode.html,v 1.26.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_getipnodebyname, lwres_getipnodebyaddr, lwres_freehostent &#8212; lightweight resolver nodename / address translation API</p>
@@ -98,7 +98,7 @@ void
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543431"></a><h2>DESCRIPTION</h2>
+<a name="id2543429"></a><h2>DESCRIPTION</h2>
<p>
These functions perform thread safe, protocol independent
nodename-to-address and address-to-nodename
@@ -217,7 +217,7 @@ struct hostent {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543689"></a><h2>RETURN VALUES</h2>
+<a name="id2543687"></a><h2>RETURN VALUES</h2>
<p>
If an error occurs,
<code class="function">lwres_getipnodebyname()</code>
@@ -261,7 +261,7 @@ struct hostent {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543786"></a><h2>SEE ALSO</h2>
+<a name="id2543784"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">RFC2553</span></span>,
<span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>,
diff --git a/contrib/bind9/lib/lwres/man/lwres_getnameinfo.3 b/contrib/bind9/lib/lwres/man/lwres_getnameinfo.3
index 3a75efb..5674fb2 100644
--- a/contrib/bind9/lib/lwres/man/lwres_getnameinfo.3
+++ b/contrib/bind9/lib/lwres/man/lwres_getnameinfo.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_getnameinfo.3,v 1.29.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_getnameinfo.3,v 1.30 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_getnameinfo.html b/contrib/bind9/lib/lwres/man/lwres_getnameinfo.html
index fb7837f..1048543 100644
--- a/contrib/bind9/lib/lwres/man/lwres_getnameinfo.html
+++ b/contrib/bind9/lib/lwres/man/lwres_getnameinfo.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_getnameinfo.html,v 1.23.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_getnameinfo.html,v 1.24.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_getnameinfo &#8212; lightweight resolver socket address structure to hostname and
@@ -82,7 +82,7 @@ int
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543393"></a><h2>DESCRIPTION</h2>
+<a name="id2543390"></a><h2>DESCRIPTION</h2>
<p>
This function is equivalent to the
<span class="citerefentry"><span class="refentrytitle">getnameinfo</span>(3)</span> function defined in RFC2133.
@@ -149,13 +149,13 @@ int
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543534"></a><h2>RETURN VALUES</h2>
+<a name="id2543532"></a><h2>RETURN VALUES</h2>
<p><code class="function">lwres_getnameinfo()</code>
returns 0 on success or a non-zero error code if an error occurs.
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543546"></a><h2>SEE ALSO</h2>
+<a name="id2543544"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">RFC2133</span></span>,
<span class="citerefentry"><span class="refentrytitle">getservbyport</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>,
@@ -165,7 +165,7 @@ int
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543604"></a><h2>BUGS</h2>
+<a name="id2543602"></a><h2>BUGS</h2>
<p>
RFC2133 fails to define what the nonzero return values of
<span class="citerefentry"><span class="refentrytitle">getnameinfo</span>(3)</span>
diff --git a/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.3 b/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.3
index c804e11..2aa1a9c 100644
--- a/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.3
+++ b/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_getrrsetbyname.3,v 1.25.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_getrrsetbyname.3,v 1.26 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html b/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html
index 9d9dc04..3a7fb9f 100644
--- a/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html
+++ b/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_getrrsetbyname.html,v 1.23.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_getrrsetbyname.html,v 1.24.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_getrrsetbyname, lwres_freerrset &#8212; retrieve DNS records</p>
@@ -102,7 +102,7 @@ struct rrsetinfo {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543414"></a><h2>DESCRIPTION</h2>
+<a name="id2543412"></a><h2>DESCRIPTION</h2>
<p><code class="function">lwres_getrrsetbyname()</code>
gets a set of resource records associated with a
<em class="parameter"><code>hostname</code></em>, <em class="parameter"><code>class</code></em>,
@@ -150,7 +150,7 @@ struct rrsetinfo {
<p></p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543526"></a><h2>RETURN VALUES</h2>
+<a name="id2543524"></a><h2>RETURN VALUES</h2>
<p><code class="function">lwres_getrrsetbyname()</code>
returns zero on success, and one of the following error codes if
an error occurred:
@@ -184,7 +184,7 @@ struct rrsetinfo {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543626"></a><h2>SEE ALSO</h2>
+<a name="id2543624"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>.
</p>
</div>
diff --git a/contrib/bind9/lib/lwres/man/lwres_gnba.3 b/contrib/bind9/lib/lwres/man/lwres_gnba.3
index b34fc05..ad9d627 100644
--- a/contrib/bind9/lib/lwres/man/lwres_gnba.3
+++ b/contrib/bind9/lib/lwres/man/lwres_gnba.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_gnba.3,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_gnba.3,v 1.28 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_gnba.html b/contrib/bind9/lib/lwres/man/lwres_gnba.html
index 158f4d0..8c7691e 100644
--- a/contrib/bind9/lib/lwres/man/lwres_gnba.html
+++ b/contrib/bind9/lib/lwres/man/lwres_gnba.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_gnba.html,v 1.24.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_gnba.html,v 1.25.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_gnbarequest_render, lwres_gnbaresponse_render, lwres_gnbarequest_parse, lwres_gnbaresponse_parse, lwres_gnbaresponse_free, lwres_gnbarequest_free &#8212; lightweight resolver getnamebyaddress message handling</p>
@@ -183,7 +183,7 @@ void
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543525"></a><h2>DESCRIPTION</h2>
+<a name="id2543523"></a><h2>DESCRIPTION</h2>
<p>
These are low-level routines for creating and parsing
lightweight resolver address-to-name lookup request and
@@ -270,7 +270,7 @@ typedef struct {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543665"></a><h2>RETURN VALUES</h2>
+<a name="id2543662"></a><h2>RETURN VALUES</h2>
<p>
The getnamebyaddr opcode functions
<code class="function">lwres_gnbarequest_render()</code>,
@@ -308,7 +308,7 @@ typedef struct {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543731"></a><h2>SEE ALSO</h2>
+<a name="id2543729"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">lwres_packet</span>(3)</span>.
</p>
</div>
diff --git a/contrib/bind9/lib/lwres/man/lwres_hstrerror.3 b/contrib/bind9/lib/lwres/man/lwres_hstrerror.3
index f65ba54..b9d5316 100644
--- a/contrib/bind9/lib/lwres/man/lwres_hstrerror.3
+++ b/contrib/bind9/lib/lwres/man/lwres_hstrerror.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_hstrerror.3,v 1.27.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_hstrerror.3,v 1.28 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_hstrerror.html b/contrib/bind9/lib/lwres/man/lwres_hstrerror.html
index d5d25ec..df1c425 100644
--- a/contrib/bind9/lib/lwres/man/lwres_hstrerror.html
+++ b/contrib/bind9/lib/lwres/man/lwres_hstrerror.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_hstrerror.html,v 1.23.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_hstrerror.html,v 1.24.484.1 2011-06-09 03:41:07 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_herror, lwres_hstrerror &#8212; lightweight resolver error message generation</p>
@@ -50,7 +50,7 @@ const char *
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543379"></a><h2>DESCRIPTION</h2>
+<a name="id2543377"></a><h2>DESCRIPTION</h2>
<p><code class="function">lwres_herror()</code>
prints the string <em class="parameter"><code>s</code></em> on
<span class="type">stderr</span> followed by the string generated by
@@ -84,7 +84,7 @@ const char *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543497"></a><h2>RETURN VALUES</h2>
+<a name="id2543495"></a><h2>RETURN VALUES</h2>
<p>
The string <span class="errorname">Unknown resolver error</span> is returned by
<code class="function">lwres_hstrerror()</code>
@@ -94,7 +94,7 @@ const char *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543517"></a><h2>SEE ALSO</h2>
+<a name="id2543515"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">herror</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">lwres_hstrerror</span>(3)</span>.
diff --git a/contrib/bind9/lib/lwres/man/lwres_inetntop.3 b/contrib/bind9/lib/lwres/man/lwres_inetntop.3
index 6bd063a..be85906 100644
--- a/contrib/bind9/lib/lwres/man/lwres_inetntop.3
+++ b/contrib/bind9/lib/lwres/man/lwres_inetntop.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_inetntop.3,v 1.26.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_inetntop.3,v 1.27 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_inetntop.html b/contrib/bind9/lib/lwres/man/lwres_inetntop.html
index 8467e4b..f0ea41a 100644
--- a/contrib/bind9/lib/lwres/man/lwres_inetntop.html
+++ b/contrib/bind9/lib/lwres/man/lwres_inetntop.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_inetntop.html,v 1.23.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_inetntop.html,v 1.24.484.1 2011-06-09 03:41:06 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_net_ntop &#8212; lightweight resolver IP address presentation</p>
@@ -62,7 +62,7 @@ const char *
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543379"></a><h2>DESCRIPTION</h2>
+<a name="id2543377"></a><h2>DESCRIPTION</h2>
<p><code class="function">lwres_net_ntop()</code>
converts an IP address of protocol family
<em class="parameter"><code>af</code></em> &#8212; IPv4 or IPv6 &#8212; at
@@ -80,7 +80,7 @@ const char *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543411"></a><h2>RETURN VALUES</h2>
+<a name="id2543409"></a><h2>RETURN VALUES</h2>
<p>
If successful, the function returns <em class="parameter"><code>dst</code></em>:
a pointer to a string containing the presentation format of the
@@ -93,7 +93,7 @@ const char *
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543444"></a><h2>SEE ALSO</h2>
+<a name="id2543442"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">RFC1884</span></span>,
<span class="citerefentry"><span class="refentrytitle">inet_ntop</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">errno</span>(3)</span>.
diff --git a/contrib/bind9/lib/lwres/man/lwres_noop.3 b/contrib/bind9/lib/lwres/man/lwres_noop.3
index fd05e7e..3be40b2 100644
--- a/contrib/bind9/lib/lwres/man/lwres_noop.3
+++ b/contrib/bind9/lib/lwres/man/lwres_noop.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_noop.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_noop.3,v 1.29 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_noop.html b/contrib/bind9/lib/lwres/man/lwres_noop.html
index 4a94836..8f9d402 100644
--- a/contrib/bind9/lib/lwres/man/lwres_noop.html
+++ b/contrib/bind9/lib/lwres/man/lwres_noop.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_noop.html,v 1.25.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_noop.html,v 1.26.484.1 2011-06-09 03:41:07 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_nooprequest_render, lwres_noopresponse_render, lwres_nooprequest_parse, lwres_noopresponse_parse, lwres_noopresponse_free, lwres_nooprequest_free &#8212; lightweight resolver no-op message handling</p>
@@ -179,7 +179,7 @@ void
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543522"></a><h2>DESCRIPTION</h2>
+<a name="id2543520"></a><h2>DESCRIPTION</h2>
<p>
These are low-level routines for creating and parsing
lightweight resolver no-op request and response messages.
@@ -270,7 +270,7 @@ typedef struct {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543672"></a><h2>RETURN VALUES</h2>
+<a name="id2543670"></a><h2>RETURN VALUES</h2>
<p>
The no-op opcode functions
<code class="function">lwres_nooprequest_render()</code>,
@@ -309,7 +309,7 @@ typedef struct {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543738"></a><h2>SEE ALSO</h2>
+<a name="id2543736"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">lwres_packet</span>(3)</span>
</p>
</div>
diff --git a/contrib/bind9/lib/lwres/man/lwres_packet.3 b/contrib/bind9/lib/lwres/man/lwres_packet.3
index 5c096b5..ad4a82c 100644
--- a/contrib/bind9/lib/lwres/man/lwres_packet.3
+++ b/contrib/bind9/lib/lwres/man/lwres_packet.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_packet.3,v 1.29.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_packet.3,v 1.30 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_packet.html b/contrib/bind9/lib/lwres/man/lwres_packet.html
index 096b4bb..84eafc1 100644
--- a/contrib/bind9/lib/lwres/man/lwres_packet.html
+++ b/contrib/bind9/lib/lwres/man/lwres_packet.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_packet.html,v 1.26.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_packet.html,v 1.27.484.1 2011-06-09 03:41:07 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_lwpacket_renderheader, lwres_lwpacket_parseheader &#8212; lightweight resolver packet handling functions</p>
@@ -66,7 +66,7 @@ lwres_result_t
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543389"></a><h2>DESCRIPTION</h2>
+<a name="id2543387"></a><h2>DESCRIPTION</h2>
<p>
These functions rely on a
<span class="type">struct lwres_lwpacket</span>
@@ -219,7 +219,7 @@ struct lwres_lwpacket {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543706"></a><h2>RETURN VALUES</h2>
+<a name="id2543704"></a><h2>RETURN VALUES</h2>
<p>
Successful calls to
<code class="function">lwres_lwpacket_renderheader()</code> and
diff --git a/contrib/bind9/lib/lwres/man/lwres_resutil.3 b/contrib/bind9/lib/lwres/man/lwres_resutil.3
index 6e17797..04cad4e 100644
--- a/contrib/bind9/lib/lwres/man/lwres_resutil.3
+++ b/contrib/bind9/lib/lwres/man/lwres_resutil.3
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwres_resutil.3,v 1.28.418.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwres_resutil.3,v 1.29 2009-07-11 01:12:46 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/lib/lwres/man/lwres_resutil.html b/contrib/bind9/lib/lwres/man/lwres_resutil.html
index 1d2aa76..b4de764 100644
--- a/contrib/bind9/lib/lwres/man/lwres_resutil.html
+++ b/contrib/bind9/lib/lwres/man/lwres_resutil.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwres_resutil.html,v 1.25.418.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwres_resutil.html,v 1.26.484.1 2011-06-09 03:41:07 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -22,7 +22,7 @@
<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
-<a name="id2476275"></a><div class="titlepage"></div>
+<a name="id2476267"></a><div class="titlepage"></div>
<div class="refnamediv">
<h2>Name</h2>
<p>lwres_string_parse, lwres_addr_parse, lwres_getaddrsbyname, lwres_getnamebyaddr &#8212; lightweight resolver utility functions</p>
@@ -134,7 +134,7 @@ lwres_result_t
</div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543466"></a><h2>DESCRIPTION</h2>
+<a name="id2543464"></a><h2>DESCRIPTION</h2>
<p><code class="function">lwres_string_parse()</code>
retrieves a DNS-encoded string starting the current pointer of
lightweight resolver buffer <em class="parameter"><code>b</code></em>: i.e.
@@ -210,7 +210,7 @@ typedef struct {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543605"></a><h2>RETURN VALUES</h2>
+<a name="id2543603"></a><h2>RETURN VALUES</h2>
<p>
Successful calls to
<code class="function">lwres_string_parse()</code>
@@ -248,7 +248,7 @@ typedef struct {
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543676"></a><h2>SEE ALSO</h2>
+<a name="id2543674"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">lwres_buffer</span>(3)</span>,
<span class="citerefentry"><span class="refentrytitle">lwres_gabn</span>(3)</span>.
diff --git a/contrib/bind9/lib/lwres/print_p.h b/contrib/bind9/lib/lwres/print_p.h
index e2f6ad6..ed71535 100644
--- a/contrib/bind9/lib/lwres/print_p.h
+++ b/contrib/bind9/lib/lwres/print_p.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: print_p.h,v 1.4.332.2 2010-08-16 23:45:48 tbox Exp $ */
+/* $Id: print_p.h,v 1.6 2010-08-16 23:46:52 tbox Exp $ */
#ifndef LWRES_PRINT_P_H
#define LWRES_PRINT_P_H 1
OpenPOWER on IntegriCloud