pkgsrc-Changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
CVS commit: [pkgsrc-2021Q3] pkgsrc/net/bind916
Module Name: pkgsrc
Committed By: tm
Date: Mon Nov 1 22:24:57 UTC 2021
Modified Files:
pkgsrc/net/bind916 [pkgsrc-2021Q3]: Makefile distinfo
pkgsrc/net/bind916/patches [pkgsrc-2021Q3]:
patch-lib_dns_include_dns_zone.h patch-lib_dns_rbt.c
patch-lib_dns_zone.c patch-lib_isc_netmgr_netmgr.c
patch-lib_isc_unix_socket.c patch-lib_ns_Makefile.in
patch-lib_ns_client.c
Added Files:
pkgsrc/net/bind916/patches [pkgsrc-2021Q3]: patch-bin_named_unix_os.c
patch-lib_dns_client.c patch-lib_dns_include_dns_client.h
patch-lib_dns_rdata.c patch-lib_isc_app.c
patch-lib_isc_netmgr_netmgr-int.h patch-lib_isc_siphash.c
patch-lib_isc_timer.c patch-lib_isc_unix_include_isc_stdatomic.h
Removed Files:
pkgsrc/net/bind916/patches [pkgsrc-2021Q3]: patch-bin_tools_arpaname.c
patch-contrib_dlz_modules_wildcard_dlz__wildcard__dynamic.c
patch-lib_dns_dnsrps.c patch-lib_dns_peer.c
patch-lib_isc_unix_include_isc_align.h patch-lib_ns_interfacemgr.c
Log Message:
Pullup ticket #6525 - requested by taca
net/bind916: security fix
Revisions pulled up:
- net/bind916/Makefile 1.28-1.29
- net/bind916/distinfo 1.24,1.26
- net/bind916/patches/patch-bin_named_unix_os.c 1.1
- net/bind916/patches/patch-bin_tools_arpaname.c deleted
- net/bind916/patches/patch-contrib_dlz_modules_wildcard_dlz__wildcard__dynamic.c deleted
- net/bind916/patches/patch-lib_dns_client.c 1.1
- net/bind916/patches/patch-lib_dns_dnsrps.c deleted
- net/bind916/patches/patch-lib_dns_include_dns_client.h 1.1
- net/bind916/patches/patch-lib_dns_include_dns_zone.h 1.3
- net/bind916/patches/patch-lib_dns_peer.c deleted
- net/bind916/patches/patch-lib_dns_rbt.c 1.3
- net/bind916/patches/patch-lib_dns_rdata.c 1.1
- net/bind916/patches/patch-lib_dns_zone.c 1.5
- net/bind916/patches/patch-lib_isc_app.c 1.1
- net/bind916/patches/patch-lib_isc_netmgr_netmgr-int.h 1.1
- net/bind916/patches/patch-lib_isc_netmgr_netmgr.c 1.2
- net/bind916/patches/patch-lib_isc_siphash.c 1.3
- net/bind916/patches/patch-lib_isc_timer.c 1.1
- net/bind916/patches/patch-lib_isc_unix_include_isc_align.h deleted
- net/bind916/patches/patch-lib_isc_unix_include_isc_stdatomic.h 1.1
- net/bind916/patches/patch-lib_isc_unix_socket.c 1.6
- net/bind916/patches/patch-lib_ns_Makefile.in 1.3
- net/bind916/patches/patch-lib_ns_client.c 1.5
- net/bind916/patches/patch-lib_ns_interfacemgr.c deleted
---
Module Name: pkgsrc
Committed By: taca
Date: Sun Oct 24 06:40:28 UTC 2021
Modified Files:
pkgsrc/net/bind916: Makefile distinfo
pkgsrc/net/bind916/patches: patch-lib_dns_include_dns_zone.h
patch-lib_dns_rbt.c patch-lib_dns_zone.c
patch-lib_isc_netmgr_netmgr.c patch-lib_isc_unix_socket.c
patch-lib_ns_Makefile.in patch-lib_ns_client.c
Added Files:
pkgsrc/net/bind916/patches: patch-bin_named_unix_os.c
patch-lib_dns_client.c patch-lib_dns_include_dns_client.h
patch-lib_dns_rdata.c patch-lib_isc_app.c
patch-lib_isc_netmgr_netmgr-int.h patch-lib_isc_siphash.c
patch-lib_isc_timer.c patch-lib_isc_unix_include_isc_stdatomic.h
Removed Files:
pkgsrc/net/bind916/patches: patch-bin_tools_arpaname.c
patch-contrib_dlz_modules_wildcard_dlz__wildcard__dynamic.c
patch-lib_dns_dnsrps.c patch-lib_dns_peer.c
patch-lib_isc_unix_include_isc_align.h patch-lib_ns_interfacemgr.c
Log Message:
net/bind916: update pkgsrc changes from NetBSD
Catch up changes from NetBSD; update them for BIND 9.16.
Bump PKGREVISION.
---
Module Name: pkgsrc
Committed By: taca
Date: Fri Oct 29 06:01:19 UTC 2021
Modified Files:
pkgsrc/net/bind916: Makefile distinfo
Log Message:
net/bind916: update to 9.16.22
This release contains security fix.
--- 9.16.22 released ---
5736. [security] The "lame-ttl" option is now forcibly set to 0. This
effectively disables the lame server cache, as it could
previously be abused by an attacker to significantly
degrade resolver performance. (CVE-2021-25219)
[GL #2899]
5724. [bug] Address a potential deadlock when checking zone content
consistency. [GL #2908]
5723. [bug] Change 5709 broke backward compatibility for the
"check-names master ..." and "check-names slave ..."
options. This has been fixed. [GL #2911]
5720. [contrib] Old-style DLZ drivers that had to be enabled at
build-time have been marked as deprecated. [GL #2814]
5719. [func] The "map" zone file format has been marked as
deprecated. [GL #2882]
5717. [func] The "cache-file" option, which was documented as "for
testing purposes only" and not to be used, has been
removed. [GL #2903]
5716. [bug] Multiple library names were mistakenly passed to the
krb5-config utility when ./configure was invoked with
the --with-gssapi=[/path/to/]krb5-config option. This
has been fixed by invoking krb5-config separately for
each required library. [GL #2866]
5715. [func] Add a check for ports specified in "*-source(-v6)"
options clashing with a global listening port. Such a
configuration was already unsupported, but it failed
silently; it is now treated as an error. [GL #2888]
5714. [bug] Remove the "adjust interface" mechanism which was
responsible for setting up listeners on interfaces when
the "*-source(-v6)" address and port were the same as
the "listen-on(-v6)" address and port. Such a
configuration is no longer supported; under certain
timing conditions, that mechanism could prevent named
from listening on some TCP ports. This has been fixed.
[GL #2852]
5712. [doc] Add deprecation notice about removing native PKCS#11
support in the next major BIND 9 release. [GL #2691]
To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.26.2.1 pkgsrc/net/bind916/Makefile
cvs rdiff -u -r1.22 -r1.22.2.1 pkgsrc/net/bind916/distinfo
cvs rdiff -u -r0 -r1.1.2.2 \
pkgsrc/net/bind916/patches/patch-bin_named_unix_os.c \
pkgsrc/net/bind916/patches/patch-lib_dns_client.c \
pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_client.h \
pkgsrc/net/bind916/patches/patch-lib_dns_rdata.c \
pkgsrc/net/bind916/patches/patch-lib_isc_app.c \
pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr-int.h \
pkgsrc/net/bind916/patches/patch-lib_isc_timer.c \
pkgsrc/net/bind916/patches/patch-lib_isc_unix_include_isc_stdatomic.h
cvs rdiff -u -r1.1 -r0 pkgsrc/net/bind916/patches/patch-bin_tools_arpaname.c \
pkgsrc/net/bind916/patches/patch-contrib_dlz_modules_wildcard_dlz__wildcard__dynamic.c \
pkgsrc/net/bind916/patches/patch-lib_dns_dnsrps.c \
pkgsrc/net/bind916/patches/patch-lib_dns_peer.c \
pkgsrc/net/bind916/patches/patch-lib_isc_unix_include_isc_align.h \
pkgsrc/net/bind916/patches/patch-lib_ns_interfacemgr.c
cvs rdiff -u -r1.2 -r1.2.2.1 \
pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_zone.h
cvs rdiff -u -r1.2 -r1.2.8.1 pkgsrc/net/bind916/patches/patch-lib_dns_rbt.c \
pkgsrc/net/bind916/patches/patch-lib_ns_Makefile.in
cvs rdiff -u -r1.4 -r1.4.2.1 pkgsrc/net/bind916/patches/patch-lib_dns_zone.c
cvs rdiff -u -r1.1 -r1.1.10.1 \
pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr.c
cvs rdiff -u -r0 -r1.3.2.2 pkgsrc/net/bind916/patches/patch-lib_isc_siphash.c
cvs rdiff -u -r1.5 -r1.5.4.1 \
pkgsrc/net/bind916/patches/patch-lib_isc_unix_socket.c
cvs rdiff -u -r1.4 -r1.4.4.1 pkgsrc/net/bind916/patches/patch-lib_ns_client.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: pkgsrc/net/bind916/Makefile
diff -u pkgsrc/net/bind916/Makefile:1.26 pkgsrc/net/bind916/Makefile:1.26.2.1
--- pkgsrc/net/bind916/Makefile:1.26 Sun Sep 19 16:26:51 2021
+++ pkgsrc/net/bind916/Makefile Mon Nov 1 22:24:56 2021
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.26 2021/09/19 16:26:51 taca Exp $
+# $NetBSD: Makefile,v 1.26.2.1 2021/11/01 22:24:56 tm Exp $
DISTNAME= bind-${BIND_VERSION}
PKGNAME= ${DISTNAME:S/-P/pl/}
@@ -15,7 +15,7 @@ CONFLICTS+= host-[0-9]*
MAKE_JOBS_SAFE= no
-BIND_VERSION= 9.16.21
+BIND_VERSION= 9.16.22
BUILD_DEFS+= BIND_DIR VARBASE
Index: pkgsrc/net/bind916/distinfo
diff -u pkgsrc/net/bind916/distinfo:1.22 pkgsrc/net/bind916/distinfo:1.22.2.1
--- pkgsrc/net/bind916/distinfo:1.22 Sun Sep 19 16:26:51 2021
+++ pkgsrc/net/bind916/distinfo Mon Nov 1 22:24:56 2021
@@ -1,17 +1,17 @@
-$NetBSD: distinfo,v 1.22 2021/09/19 16:26:51 taca Exp $
+$NetBSD: distinfo,v 1.22.2.1 2021/11/01 22:24:56 tm Exp $
-SHA1 (bind-9.16.21.tar.xz) = 9dd0b19f2fd05c88569faad3519787ed629b4934
-RMD160 (bind-9.16.21.tar.xz) = 57f41616424441caa6cd83e407f8a5043bd70e50
-SHA512 (bind-9.16.21.tar.xz) = 2cb71e50600fd7409ca7b7e2e9cf4ef6668b07faad7980ac8060e6a76f30a315182d75534ad1dcfb740c225cdf727b2bd6aa9ceb24ab77ffff09b7b5d6eaca2d
-Size (bind-9.16.21.tar.xz) = 5057816 bytes
+SHA1 (bind-9.16.22.tar.xz) = 0d56f6a88532363757534566598c48a9f7072bfa
+RMD160 (bind-9.16.22.tar.xz) = 73822462c0d47d919de54a5f7ce1ff7e20bb1452
+SHA512 (bind-9.16.22.tar.xz) = 586fb4d5a656d6539033dcdfdd230b36465a2d2e6ada651c1f1548d062a9050e7a962af87e2a56931fe24c65586d29012d4a041dcddbb28f42b4d01fe291d9d1
+Size (bind-9.16.22.tar.xz) = 5059000 bytes
SHA1 (patch-bin_dig_dighost.c) = b1073911d80ecd519af98b6678968296ff8c0c98
SHA1 (patch-bin_dig_include_dig_dig.h) = 10166f5bb98b208c7b10d63eb31e8253f704acc8
SHA1 (patch-bin_named_Makefile.in) = f1367da6a226ba44d0ee13acf00b8abeb5b1b7eb
SHA1 (patch-bin_named_main.c) = f00842529ec2015e0969d0dba58a1e13a510f9eb
SHA1 (patch-bin_named_server.c) = 6e59d3f637ebb829eec2f76ba7c350fb5cf9be6d
+SHA1 (patch-bin_named_unix_os.c) = fe9cde1240107151c5b10ba325c8f994ef76852d
SHA1 (patch-bin_nsupdate_nsupdate.c) = 4ccd0e503a972cf16905e999bcc574f8ee0dd85d
SHA1 (patch-bin_pkcs11_pkcs11-keygen.c) = d953bf48aadcdf7e95975d335167cc50f54ef91e
-SHA1 (patch-bin_tools_arpaname.c) = 868da4454d06dc823680cf06a764fa40b8474708
SHA1 (patch-bin_tools_nsec3hash.c) = 87c3891db62c45cd8ed2b484b17f7bf2e319bef3
SHA1 (patch-config.guess) = f44c6344a297e7c623dcbf75b308eb35f797a537
SHA1 (patch-config.h.in) = fb0396429bd68bb3bf478cb1da67736592208702
@@ -19,39 +19,42 @@ SHA1 (patch-config.sub) = 7389c0f2500f2a
SHA1 (patch-config.threads.in) = fc5cc7097d87523a34c0e630cb8dd1d081d859e5
SHA1 (patch-configure.ac) = 3dd8c49eb6bc475c20c88edc20bd8457698ad500
SHA1 (patch-contrib_dlz_config.dlz.in) = 6c53d61aaaf1a952a867e4c4da0194db94f511d7
-SHA1 (patch-contrib_dlz_modules_wildcard_dlz__wildcard__dynamic.c) = 37ba5f06f4970abaae6d98c4305f6372537a313f
SHA1 (patch-lib_dns_byaddr.c) = 647ddaaaf040233e18d1a87d83bc2bd63d2a20e3
-SHA1 (patch-lib_dns_dnsrps.c) = b4c66a808eeb1e859801028afacd7237cd89903a
+SHA1 (patch-lib_dns_client.c) = 94909ebeaded676cca502d83bf8071ae651e1928
SHA1 (patch-lib_dns_gssapi__link.c) = acd5f3c975d4edf391e77fd39cfa91810ad17ba2
-SHA1 (patch-lib_dns_include_dns_zone.h) = aafd99bf0b0c84aa69b444106608c6cff61938f1
+SHA1 (patch-lib_dns_include_dns_client.h) = 5e3c6baebe136b026f30552dbbff632a2b535301
+SHA1 (patch-lib_dns_include_dns_zone.h) = e6dfcd43430538ac2a39b217fcae0d81e4c4d163
SHA1 (patch-lib_dns_lookup.c) = 6c7463aca16abf6bd578aba1733a3217608a39d3
-SHA1 (patch-lib_dns_peer.c) = 16cc26fd4e792a23caef6e091f94f974041179e7
SHA1 (patch-lib_dns_pkcs11ecdsa__link.c) = 99f386b056c5a6471f69841c41a2698d36b6b275
SHA1 (patch-lib_dns_pkcs11eddsa__link.c) = bd887a6c8960da3a8663cdf5e955e045f16dee3f
-SHA1 (patch-lib_dns_rbt.c) = a9ef153a0548eb432567f1e3347c27ce5775a041
+SHA1 (patch-lib_dns_rbt.c) = c14eff9a609e4b49aa9db18f395461cd7c8944be
SHA1 (patch-lib_dns_rbtdb.c) = bb3f829cbed23bce624462766aa6d039a0153afe
+SHA1 (patch-lib_dns_rdata.c) = fb12d214a86d71d62e200e6bc09b7c8b7187b911
SHA1 (patch-lib_dns_request.c) = 82560e819cba0259883da8d47618ffabead22c55
SHA1 (patch-lib_dns_sdb.c) = ed447ec7a134e620765b25ee36124a19dfd9fab0
SHA1 (patch-lib_dns_sdlz.c) = 4fc15a577c64501c10c144eab147e54686e80309
SHA1 (patch-lib_dns_validator.c) = 03dd60d4c38be7248d1e07f2c29ddd543b5f7454
SHA1 (patch-lib_dns_view.c) = 5b092f0344b92d003f1fe1f28e4cc4c76b2505cf
-SHA1 (patch-lib_dns_zone.c) = 04a224863c8860c5f1b5bf4291b1af920c57fcd2
+SHA1 (patch-lib_dns_zone.c) = cd7bc1e76caf1d664393efa318786c2b33c000de
+SHA1 (patch-lib_isc_app.c) = 1c75ba0db1e7978b37e22742bf69a216ca9a23ef
SHA1 (patch-lib_isc_backtrace.c) = 1b6bca9b3de7f7298882c6c88274b0baf1dad507
SHA1 (patch-lib_isc_include_isc_netmgr.h) = 48ac44c6a9b81e6b442deba6c075653d3691464b
SHA1 (patch-lib_isc_include_isc_socket.h) = dc6376cd9e8391fa96efd805faee1a5d0647a142
SHA1 (patch-lib_isc_include_isc_types.h) = e5fcf15ee03d1d032a67f2e6d23b2e409042ab64
-SHA1 (patch-lib_isc_netmgr_netmgr.c) = 63168c8901646e7b2079e1dc3324087508bb1e62
+SHA1 (patch-lib_isc_netmgr_netmgr-int.h) = 9f493b33e00f09f45c78b6a66ebf7bfd52083792
+SHA1 (patch-lib_isc_netmgr_netmgr.c) = 3df1d37061f6ceb37e309a0dc4f782fc35863146
SHA1 (patch-lib_isc_rwlock.c) = 1d114248ddee20db7a7429afab446f8b2f0dca82
+SHA1 (patch-lib_isc_siphash.c) = 8999deb002e4fdb6b13e6f297298ef73c97042c3
SHA1 (patch-lib_isc_stats.c) = 8d962fa360740770588fccf1d303d7fe22ae724b
-SHA1 (patch-lib_isc_unix_include_isc_align.h) = 1bbd78f1617a40079d1044175cfe037bbd1d95b2
+SHA1 (patch-lib_isc_timer.c) = aea2019bbf3d84cad77af432a2bbdf0da8f2f893
+SHA1 (patch-lib_isc_unix_include_isc_stdatomic.h) = b73b0224be47c1733f6346fce9243e97f54e1865
SHA1 (patch-lib_isc_unix_net.c) = c654f60a1feefdba9bf980dcfa46ce37f46918aa
-SHA1 (patch-lib_isc_unix_socket.c) = ed1816b50698107cb2034e0e3c61406ee458e697
+SHA1 (patch-lib_isc_unix_socket.c) = 7d5b61124187009ce03f4fc963f8ad3c44d267d0
SHA1 (patch-lib_isc_unix_time.c) = fac9e66754e099f53ba8c499f5f179825a0b0fbd
-SHA1 (patch-lib_ns_Makefile.in) = 5d3ecf4d6673cf227635c03779e9969e6eeb8227
-SHA1 (patch-lib_ns_client.c) = db2ee0cc915f20ae09beb2c8a917e0b3e60dfedc
+SHA1 (patch-lib_ns_Makefile.in) = 7375d0cb44c891492594dc7540f78826c141106a
+SHA1 (patch-lib_ns_client.c) = 099ca607278d064081a0cfc92d96f0b31d95a944
SHA1 (patch-lib_ns_include_ns_client.h) = 3ccd630aee77ea638fb3b954b85bad9c74b0c86e
SHA1 (patch-lib_ns_include_ns_pfilter.h) = cc86752971b4f9f7492283c4ad3ff29bc1bae237
-SHA1 (patch-lib_ns_interfacemgr.c) = fc31720734b02155acd7fa9b370a6ebb82022532
SHA1 (patch-lib_ns_pfilter.c) = 8f4a3b3a729360a131eb1962c42a9f9f985c7e7b
SHA1 (patch-lib_ns_query.c) = 0c3c4a20aa4b40c144c4f986599cda67db3e2491
SHA1 (patch-lib_ns_update.c) = 2fb3457da333143508d28420490cbc1cb69ddb19
Index: pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_zone.h
diff -u pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_zone.h:1.2 pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_zone.h:1.2.2.1
--- pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_zone.h:1.2 Tue Jul 20 06:39:45 2021
+++ pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_zone.h Mon Nov 1 22:24:56 2021
@@ -1,10 +1,10 @@
-$NetBSD: patch-lib_dns_include_dns_zone.h,v 1.2 2021/07/20 06:39:45 rin Exp $
+$NetBSD: patch-lib_dns_include_dns_zone.h,v 1.2.2.1 2021/11/01 22:24:56 tm Exp $
No need to use atomic 64-bit integers for flags fit within 32-bit width.
---- lib/dns/include/dns/zone.h.orig 2020-05-06 09:59:35.000000000 +0000
+--- lib/dns/include/dns/zone.h.orig 2021-09-07 09:37:05.000000000 +0000
+++ lib/dns/include/dns/zone.h
-@@ -87,7 +87,9 @@ typedef enum {
+@@ -96,7 +96,9 @@ typedef enum {
DNS_ZONEOPT_CHECKSPF = 1 << 27, /*%< check SPF records */
DNS_ZONEOPT_CHECKTTL = 1 << 28, /*%< check max-zone-ttl */
DNS_ZONEOPT_AUTOEMPTY = 1 << 29, /*%< automatic empty zone */
@@ -14,7 +14,7 @@ No need to use atomic 64-bit integers fo
} dns_zoneopt_t;
/*
-@@ -99,7 +101,9 @@ typedef enum {
+@@ -108,7 +110,9 @@ typedef enum {
DNS_ZONEKEY_CREATE = 0x00000004U, /*%< make keys when needed */
DNS_ZONEKEY_FULLSIGN = 0x00000008U, /*%< roll to new keys immediately */
DNS_ZONEKEY_NORESIGN = 0x00000010U, /*%< no automatic resigning */
Index: pkgsrc/net/bind916/patches/patch-lib_dns_rbt.c
diff -u pkgsrc/net/bind916/patches/patch-lib_dns_rbt.c:1.2 pkgsrc/net/bind916/patches/patch-lib_dns_rbt.c:1.2.8.1
--- pkgsrc/net/bind916/patches/patch-lib_dns_rbt.c:1.2 Thu Nov 26 13:21:51 2020
+++ pkgsrc/net/bind916/patches/patch-lib_dns_rbt.c Mon Nov 1 22:24:56 2021
@@ -1,9 +1,9 @@
-$NetBSD: patch-lib_dns_rbt.c,v 1.2 2020/11/26 13:21:51 taca Exp $
+$NetBSD: patch-lib_dns_rbt.c,v 1.2.8.1 2021/11/01 22:24:56 tm Exp $
* Take from NetBSD base.
* Disable inline on powerpc.
---- lib/dns/rbt.c.orig 2020-11-16 14:44:37.000000000 +0000
+--- lib/dns/rbt.c.orig 2021-09-07 09:37:05.000000000 +0000
+++ lib/dns/rbt.c
@@ -319,12 +319,13 @@ Name(dns_rbtnode_t *node) {
}
@@ -45,11 +45,11 @@ $NetBSD: patch-lib_dns_rbt.c,v 1.2 2020/
goto cleanup; \
} \
- } while (0);
-+ } while(/*CONSTCOND*/0)
++ } while(0)
static isc_result_t
treefix(dns_rbt_t *rbt, void *base, size_t filesize, dns_rbtnode_t *n,
-@@ -879,7 +884,7 @@ treefix(dns_rbt_t *rbt, void *base, size
+@@ -880,7 +885,7 @@ treefix(dns_rbt_t *rbt, void *base, size
fprintf(stderr, "deserialize ");
dns_name_print(&nodename, stderr);
fprintf(stderr, "\n");
@@ -58,7 +58,7 @@ $NetBSD: patch-lib_dns_rbt.c,v 1.2 2020/
hexdump("node data", node_data, datasize);
#endif /* ifdef DEBUG */
isc_crc64_update(crc, (const uint8_t *)&header, sizeof(dns_rbtnode_t));
-@@ -955,7 +960,7 @@ dns_rbt_deserialize_tree(void *base_addr
+@@ -956,7 +961,7 @@ dns_rbt_deserialize_tree(void *base_addr
isc_crc64_final(&crc);
#ifdef DEBUG
Index: pkgsrc/net/bind916/patches/patch-lib_ns_Makefile.in
diff -u pkgsrc/net/bind916/patches/patch-lib_ns_Makefile.in:1.2 pkgsrc/net/bind916/patches/patch-lib_ns_Makefile.in:1.2.8.1
--- pkgsrc/net/bind916/patches/patch-lib_ns_Makefile.in:1.2 Sat Dec 19 16:41:36 2020
+++ pkgsrc/net/bind916/patches/patch-lib_ns_Makefile.in Mon Nov 1 22:24:57 2021
@@ -1,21 +1,20 @@
-$NetBSD: patch-lib_ns_Makefile.in,v 1.2 2020/12/19 16:41:36 taca Exp $
+$NetBSD: patch-lib_ns_Makefile.in,v 1.2.8.1 2021/11/01 22:24:57 tm Exp $
* Based on NetBSD, add support for blocklist(blacklist).
---- lib/ns/Makefile.in.orig 2020-12-07 08:16:53.000000000 +0000
+--- lib/ns/Makefile.in.orig 2021-09-07 09:37:05.000000000 +0000
+++ lib/ns/Makefile.in
-@@ -41,12 +41,12 @@ LIBS = @LIBS@
-
- # Alphabetically
+@@ -39,11 +39,11 @@ LIBS = @LIBS@
OBJS = client.@O@ hooks.@O@ interfacemgr.@O@ lib.@O@ \
-- listenlist.@O@ log.@O@ notify.@O@ query.@O@ \
-+ listenlist.@O@ log.@O@ notify.@O@ pfilter.@O@ query.@O@ \
+ listenlist.@O@ log.@O@ notify.@O@ query.@O@ \
server.@O@ sortlist.@O@ stats.@O@ update.@O@ \
- version.@O@ xfrout.@O@
+- version.@O@ xfrout.@O@
++ version.@O@ xfrout.@O@ pfilter.@O@
SRCS = client.c hooks.c interfacemgr.c lib.c listenlist.c \
-- log.c notify.c query.c server.c sortlist.c stats.c \
-+ log.c notify.c pfilter.c query.c server.c sortlist.c stats.c \
- update.c version.c xfrout.c
+ log.c notify.c query.c server.c sortlist.c stats.c \
+- update.c version.c xfrout.c
++ update.c version.c xfrout.c pfilter.c
SUBDIRS = include
+ TESTDIRS = @UNITTESTS@
Index: pkgsrc/net/bind916/patches/patch-lib_dns_zone.c
diff -u pkgsrc/net/bind916/patches/patch-lib_dns_zone.c:1.4 pkgsrc/net/bind916/patches/patch-lib_dns_zone.c:1.4.2.1
--- pkgsrc/net/bind916/patches/patch-lib_dns_zone.c:1.4 Tue Jul 20 07:23:04 2021
+++ pkgsrc/net/bind916/patches/patch-lib_dns_zone.c Mon Nov 1 22:24:56 2021
@@ -1,10 +1,10 @@
-$NetBSD: patch-lib_dns_zone.c,v 1.4 2021/07/20 07:23:04 rin Exp $
+$NetBSD: patch-lib_dns_zone.c,v 1.4.2.1 2021/11/01 22:24:56 tm Exp $
No need to use atomic 64-bit integers for flags fit within 32-bit width.
---- lib/dns/zone.c.orig 2021-06-18 19:08:07.000000000 +0900
-+++ lib/dns/zone.c 2021-07-19 08:46:21.613595923 +0900
-@@ -241,8 +241,13 @@ struct dns_zone {
+--- lib/dns/zone.c.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/dns/zone.c
+@@ -246,8 +246,13 @@ struct dns_zone {
int32_t journalsize;
dns_rdataclass_t rdclass;
dns_zonetype_t type;
@@ -18,7 +18,7 @@ No need to use atomic 64-bit integers fo
unsigned int db_argc;
char **db_argv;
isc_time_t expiretime;
-@@ -387,7 +392,11 @@ struct dns_zone {
+@@ -405,7 +410,11 @@ struct dns_zone {
/*%
* Autosigning/key-maintenance options
*/
@@ -30,11 +30,16 @@ No need to use atomic 64-bit integers fo
/*%
* True if added by "rndc addzone"
-@@ -524,7 +533,9 @@ typedef enum {
+@@ -537,12 +546,14 @@ typedef enum {
+ * notify due to the zone
+ * just being loaded for
+ * the first time. */
++#if 0
+ /*
+ * DO NOT add any new zone flags here until all platforms
* support 64-bit enum values. Currently they fail on
* Windows.
*/
-+#if 0
DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
+#endif
} dns_zoneflg_t;
Index: pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr.c
diff -u pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr.c:1.1 pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr.c:1.1.10.1
--- pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr.c:1.1 Sun Aug 9 15:20:22 2020
+++ pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr.c Mon Nov 1 22:24:56 2021
@@ -1,10 +1,19 @@
-$NetBSD: patch-lib_isc_netmgr_netmgr.c,v 1.1 2020/08/09 15:20:22 taca Exp $
+$NetBSD: patch-lib_isc_netmgr_netmgr.c,v 1.1.10.1 2021/11/01 22:24:56 tm Exp $
* Take from NetBSD base.
---- lib/isc/netmgr/netmgr.c.orig 2020-05-06 09:59:35.000000000 +0000
+--- lib/isc/netmgr/netmgr.c.orig 2021-09-07 09:37:05.000000000 +0000
+++ lib/isc/netmgr/netmgr.c
-@@ -1197,6 +1197,13 @@ isc_nmhandle_getdata(isc_nmhandle_t *han
+@@ -373,7 +373,7 @@ isc__netmgr_create(isc_mem_t *mctx, uint
+ mgr->workers_running++;
+ isc_thread_create(nm_thread, &mgr->workers[i], &worker->thread);
+
+- snprintf(name, sizeof(name), "isc-net-%04zu", i);
++ snprintf(name, sizeof(name), "net-%04zu", i);
+ isc_thread_setname(worker->thread, name);
+ }
+
+@@ -1828,6 +1828,13 @@ isc_nmhandle_getdata(isc_nmhandle_t *han
return (handle->opaque);
}
Index: pkgsrc/net/bind916/patches/patch-lib_isc_unix_socket.c
diff -u pkgsrc/net/bind916/patches/patch-lib_isc_unix_socket.c:1.5 pkgsrc/net/bind916/patches/patch-lib_isc_unix_socket.c:1.5.4.1
--- pkgsrc/net/bind916/patches/patch-lib_isc_unix_socket.c:1.5 Wed Jun 2 15:37:06 2021
+++ pkgsrc/net/bind916/patches/patch-lib_isc_unix_socket.c Mon Nov 1 22:24:57 2021
@@ -1,41 +1,23 @@
-$NetBSD: patch-lib_isc_unix_socket.c,v 1.5 2021/06/02 15:37:06 taca Exp $
+$NetBSD: patch-lib_isc_unix_socket.c,v 1.5.4.1 2021/11/01 22:24:57 tm Exp $
* Apply fixes from NetBSD base system.
* Fix build on SmartOS. In this special case, _XOPEN_SOURCE has to be only
defined on SmartOS.
---- lib/isc/unix/socket.c.orig 2021-05-12 09:53:16.000000000 +0000
+--- lib/isc/unix/socket.c.orig 2021-09-07 09:37:05.000000000 +0000
+++ lib/isc/unix/socket.c
-@@ -11,6 +11,15 @@
-
- /*! \file */
-
-+/* needed for CMSG_DATA */
-+#if defined(__sun)
-+#if (__STDC_VERSION__ - 0 < 199901L)
-+#define _XOPEN_SOURCE 500
-+#else
-+#define _XOPEN_SOURCE 600
-+#endif
-+#endif
-+
- #include <inttypes.h>
- #include <stdbool.h>
- #include <sys/param.h>
-@@ -360,7 +369,11 @@ struct isc_socket {
+@@ -360,6 +360,10 @@ struct isc_socket {
unsigned char overflow; /* used for MSG_TRUNC fake */
#endif /* ifdef ISC_PLATFORM_RECVOVERFLOW */
-- unsigned int dscp;
+ void *fdwatcharg;
+ isc_sockfdwatch_t fdwatchcb;
+ int fdwatchflags;
+ isc_task_t *fdwatchtask;
-+ unsigned int dscp;
+ unsigned int dscp;
};
- #define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
-@@ -469,6 +482,14 @@ static bool
+@@ -469,6 +473,14 @@ static bool
process_ctlfd(isc__socketthread_t *thread);
static void
setdscp(isc_socket_t *sock, isc_dscp_t dscp);
@@ -50,7 +32,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
#define SELECT_POKE_SHUTDOWN (-1)
#define SELECT_POKE_NOTHING (-2)
-@@ -1573,6 +1594,7 @@ doio_recv(isc_socket_t *sock, isc_socket
+@@ -1573,6 +1585,7 @@ doio_recv(isc_socket_t *sock, isc_socket
case isc_sockettype_udp:
case isc_sockettype_raw:
break;
@@ -58,15 +40,14 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
default:
INSIST(0);
ISC_UNREACHABLE();
-@@ -1781,9 +1803,26 @@ socketclose(isc__socketthread_t *thread,
+@@ -1781,9 +1794,26 @@ socketclose(isc__socketthread_t *thread,
*/
LOCK(&thread->fdlock[lockid]);
thread->fds[fd] = NULL;
-- thread->fdstate[fd] = CLOSE_PENDING;
+ if (sock->type == isc_sockettype_fdwatch)
+ thread->fdstate[fd] = CLOSED;
+ else
-+ thread->fdstate[fd] = CLOSE_PENDING;
+ thread->fdstate[fd] = CLOSE_PENDING;
UNLOCK(&thread->fdlock[lockid]);
- select_poke(thread->manager, thread->threadid, fd, SELECT_POKE_CLOSE);
+ if (sock->type == isc_sockettype_fdwatch) {
@@ -87,7 +68,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
inc_stats(thread->manager->stats, sock->statsindex[STATID_CLOSE]);
-@@ -2164,6 +2203,13 @@ again:
+@@ -2190,6 +2220,13 @@ again:
}
#endif /* if defined(PF_ROUTE) */
break;
@@ -101,7 +82,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
}
} else {
sock->fd = dup(dup_socket->fd);
-@@ -2456,6 +2502,7 @@ socket_create(isc_socketmgr_t *manager,
+@@ -2439,6 +2476,7 @@ socket_create(isc_socketmgr_t *manager,
REQUIRE(VALID_MANAGER(manager));
REQUIRE(socketp != NULL && *socketp == NULL);
@@ -109,7 +90,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
result = allocate_socket(manager, type, &sock);
if (result != ISC_R_SUCCESS) {
-@@ -2570,6 +2617,7 @@ isc_socket_open(isc_socket_t *sock) {
+@@ -2553,6 +2591,7 @@ isc_socket_open(isc_socket_t *sock) {
REQUIRE(isc_refcount_current(&sock->references) >= 1);
REQUIRE(sock->fd == -1);
REQUIRE(sock->threadid == -1);
@@ -117,7 +98,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
result = opensocket(sock->manager, sock, NULL);
-@@ -2648,6 +2696,7 @@ isc_socket_close(isc_socket_t *sock) {
+@@ -2631,6 +2670,7 @@ isc_socket_close(isc_socket_t *sock) {
LOCK(&sock->lock);
@@ -125,7 +106,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks);
INSIST(!sock->connecting);
-@@ -2678,6 +2727,24 @@ isc_socket_close(isc_socket_t *sock) {
+@@ -2661,6 +2701,24 @@ isc_socket_close(isc_socket_t *sock) {
return (ISC_R_SUCCESS);
}
@@ -150,7 +131,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
/*
* Dequeue an item off the given socket's read queue, set the result code
* in the done event to the one provided, and send it to the task it was
-@@ -3118,6 +3185,64 @@ finish:
+@@ -3101,6 +3159,58 @@ finish:
}
}
@@ -161,7 +142,6 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
+
+ INSIST(VALID_SOCKET(sock));
+
-+ LOCK(&sock->lock);
+ isc_refcount_increment(&sock->references);
+ UNLOCK(&sock->lock);
+
@@ -179,8 +159,6 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
+ if (more_data)
+ select_poke(sock->manager, sock->threadid, sock->fd,
+ SELECT_POKE_WRITE);
-+
-+ UNLOCK(&sock->lock);
+}
+
+static void
@@ -190,7 +168,6 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
+
+ INSIST(VALID_SOCKET(sock));
+
-+ LOCK(&sock->lock);
+ isc_refcount_increment(&sock->references);
+ UNLOCK(&sock->lock);
+
@@ -208,14 +185,12 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
+ if (more_data)
+ select_poke(sock->manager, sock->threadid, sock->fd,
+ SELECT_POKE_READ);
-+
-+ UNLOCK(&sock->lock);
+}
+
/*
* Process read/writes on each fd here. Avoid locking
* and unlocking twice if both reads and writes are possible.
-@@ -3165,7 +3290,7 @@ process_fd(isc__socketthread_t *thread,
+@@ -3148,7 +3258,7 @@ process_fd(isc__socketthread_t *thread,
if (sock->connecting) {
internal_connect(sock);
} else {
@@ -224,7 +199,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
}
}
-@@ -3173,7 +3298,7 @@ process_fd(isc__socketthread_t *thread,
+@@ -3156,7 +3266,7 @@ process_fd(isc__socketthread_t *thread,
if (sock->listener) {
internal_accept(sock); /* unlocks sock */
} else {
@@ -233,7 +208,16 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
UNLOCK(&sock->lock);
}
} else {
-@@ -5238,7 +5363,7 @@ static isc_once_t hasreuseport_once = IS
+@@ -3797,7 +3907,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, i
+ isc_thread_create(netthread, &manager->threads[i],
+ &manager->threads[i].thread);
+ char tname[1024];
+- sprintf(tname, "isc-socket-%d", i);
++ sprintf(tname, "socket-%d", i);
+ isc_thread_setname(manager->threads[i].thread, tname);
+ }
+
+@@ -5218,7 +5328,7 @@ static isc_once_t hasreuseport_once = IS
static bool hasreuseport = false;
static void
@@ -242,7 +226,7 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
/*
* SO_REUSEPORT works very differently on *BSD and on Linux (because why not).
* We only want to use it on Linux, if it's available. On BSD we want to dup()
-@@ -5292,6 +5417,8 @@ _socktype(isc_sockettype_t type) {
+@@ -5272,6 +5382,8 @@ _socktype(isc_sockettype_t type) {
return ("tcp");
case isc_sockettype_unix:
return ("unix");
@@ -251,28 +235,10 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
default:
return ("not-initialized");
}
-@@ -5304,7 +5431,7 @@ _socktype(isc_sockettype_t type) {
- xmlrc = (a); \
- if (xmlrc < 0) \
- goto error; \
-- } while (0)
-+ } while (/*CONSTCOND*/0)
- int
- isc_socketmgr_renderxml(isc_socketmgr_t *mgr, void *writer0) {
- isc_socket_t *sock = NULL;
-@@ -5410,7 +5537,7 @@ error:
- result = ISC_R_NOMEMORY; \
- goto error; \
- } \
-- } while (0)
-+ } while (/*CONSTCOND*/0)
-
- isc_result_t
- isc_socketmgr_renderjson(isc_socketmgr_t *mgr, void *stats0) {
-@@ -5521,4 +5648,113 @@ error:
-
+@@ -5502,3 +5614,113 @@ error:
return (result);
}
+ #endif /* HAVE_JSON_C */
+
+/*
+ * Create a new 'type' socket managed by 'manager'. Events
@@ -281,11 +247,10 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
+ * in 'socketp'.
+ */
+isc_result_t
-+isc_socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags,
++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__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+ isc_socket_t *sock = NULL;
+ isc__socketthread_t *thread;
+ isc_result_t result;
@@ -323,15 +288,19 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
+ thread->fdstate[sock->fd] = MANAGED;
+
+#if defined(USE_EPOLL)
-+ thread->epoll_events[sock->fd] = 0;
++ manager->epoll_events[sock->fd] = 0;
+#endif
++#ifdef USE_DEVPOLL
++ INSIST(thread->fdpollinfo[sock->fd].want_read == 0 &&
++ thread->fdpollinfo[sock->fd].want_write == 0);
++#endif /* ifdef USE_DEVPOLL */
+ UNLOCK(&thread->fdlock[lockid]);
+
+ LOCK(&manager->lock);
+ ISC_LIST_APPEND(manager->socklist, sock, link);
+#ifdef USE_SELECT
-+ if (manager->maxfd < sock->fd)
-+ manager->maxfd = sock->fd;
++ if (thread->maxfd < sock->fd)
++ thread->maxfd = sock->fd;
+#endif
+ UNLOCK(&manager->lock);
+
@@ -356,10 +325,8 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
+ */
+
+isc_result_t
-+isc_socket_fdwatchpoke(isc_socket_t *sock0, int flags)
++isc_socket_fdwatchpoke(isc_socket_t *sock, int flags)
+{
-+ isc_socket_t *sock = (isc_socket_t *)sock0;
-+
+ REQUIRE(VALID_SOCKET(sock));
+
+ /*
@@ -382,4 +349,3 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1
+
+ return (ISC_R_SUCCESS);
+}
- #endif /* HAVE_JSON_C */
Index: pkgsrc/net/bind916/patches/patch-lib_ns_client.c
diff -u pkgsrc/net/bind916/patches/patch-lib_ns_client.c:1.4 pkgsrc/net/bind916/patches/patch-lib_ns_client.c:1.4.4.1
--- pkgsrc/net/bind916/patches/patch-lib_ns_client.c:1.4 Tue Jul 20 06:39:45 2021
+++ pkgsrc/net/bind916/patches/patch-lib_ns_client.c Mon Nov 1 22:24:57 2021
@@ -1,9 +1,20 @@
-$NetBSD: patch-lib_ns_client.c,v 1.4 2021/07/20 06:39:45 rin Exp $
+$NetBSD: patch-lib_ns_client.c,v 1.4.4.1 2021/11/01 22:24:57 tm Exp $
Use 32-bit atomic integers for !_LP64 platforms.
---- lib/ns/client.c.orig 2021-07-19 08:32:57.384417149 +0900
-+++ lib/ns/client.c 2021-07-19 08:33:25.780329755 +0900
+--- lib/ns/client.c.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/ns/client.c
+@@ -87,8 +87,8 @@
+ isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, \
+ ISC_LOG_DEBUG(3), "clientmgr @%p: %s", manager, (m))
+ #else /* ifdef NS_CLIENT_TRACE */
+-#define CTRACE(m) ((void)(m))
+-#define MTRACE(m) ((void)(m))
++#define CTRACE(m) ((void)/*LINTED*/(m))
++#define MTRACE(m) ((void)/*LINTED*/(m))
+ #endif /* ifdef NS_CLIENT_TRACE */
+
+ #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
@@ -126,7 +126,7 @@
* Number of tasks to be used by clients - those are used only when recursing
*/
Added files:
Index: pkgsrc/net/bind916/patches/patch-bin_named_unix_os.c
diff -u /dev/null pkgsrc/net/bind916/patches/patch-bin_named_unix_os.c:1.1.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-bin_named_unix_os.c Mon Nov 1 22:24:56 2021
@@ -0,0 +1,20 @@
+$NetBSD: patch-bin_named_unix_os.c,v 1.1.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- bin/named/unix/os.c.orig 2021-09-07 09:37:05.000000000 +0000
++++ bin/named/unix/os.c
+@@ -125,11 +125,10 @@ linux_setcaps(cap_t caps) {
+ } \
+ } while (0)
+ #define FREE_CAP \
+- { \
++ do { \
+ cap_free(caps); \
+ cap_free(curcaps); \
+- } \
+- while (0)
++ } while (0)
+
+ static void
+ linux_initialprivs(void) {
Index: pkgsrc/net/bind916/patches/patch-lib_dns_client.c
diff -u /dev/null pkgsrc/net/bind916/patches/patch-lib_dns_client.c:1.1.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-lib_dns_client.c Mon Nov 1 22:24:56 2021
@@ -0,0 +1,1871 @@
+$NetBSD: patch-lib_dns_client.c,v 1.1.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- lib/dns/client.c.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/dns/client.c
+@@ -56,6 +56,9 @@
+ #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)
+
+@@ -92,6 +95,9 @@ struct dns_client {
+ 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;
+
+@@ -100,11 +106,23 @@ struct dns_client {
+ /* Locked */
+ 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
++
+ /*%
+ * Internal state for a single name resolution procedure
+ */
+@@ -151,8 +169,98 @@ typedef struct resarg {
+ bool 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;
++ bool 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;
++ bool 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;
++ bool 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;
++ bool want_tcp;
++
++ /* Locked */
++ dns_request_t *updatereq;
++ dns_request_t *soareq;
++ dns_clientrestrans_t *restrans;
++ dns_clientrestrans_t *restrans2;
++ bool 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);
+
+ /*
+ * Try honoring the operating system's preferred ephemeral port range.
+@@ -307,7 +415,7 @@ dns_client_create(isc_mem_t *mctx, isc_a
+ const isc_sockaddr_t *localaddr4,
+ const isc_sockaddr_t *localaddr6) {
+ isc_result_t result;
+- dns_client_t *client = NULL;
++ dns_client_t *client;
+ dns_dispatchmgr_t *dispatchmgr = NULL;
+ dns_dispatch_t *dispatchv4 = NULL;
+ dns_dispatch_t *dispatchv6 = NULL;
+@@ -385,10 +493,15 @@ dns_client_create(isc_mem_t *mctx, isc_a
+ 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->attributes = 0;
+@@ -440,8 +553,6 @@ destroyclient(dns_client_t *client) {
+ dns_dispatchmgr_destroy(&client->dispatchmgr);
+
+ isc_task_detach(&client->task);
+-
+- isc_mutex_destroy(&client->lock);
+ client->magic = 0;
+
+ isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
+@@ -1036,23 +1147,35 @@ dns_client_resolve(dns_client_t *client,
+ 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(client->actx != NULL);
+ REQUIRE(namelist != NULL && ISC_LIST_EMPTY(*namelist));
+
+- resarg = isc_mem_get(client->mctx, sizeof(*resarg));
++ 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 = (resarg_t){
+- .actx = client->actx,
+- .client = client,
+- .result = DNS_R_SERVFAIL,
+- .namelist = namelist,
+- };
++ resarg = isc_mem_get(client->mctx, sizeof(*resarg));
+
+ isc_mutex_init(&resarg->lock);
+
++ resarg->actx = actx;
++ resarg->client = client;
++ resarg->result = DNS_R_SERVFAIL;
++ resarg->namelist = namelist;
++ resarg->trans = NULL;
++ resarg->canceled = false;
+ result = dns_client_startresolve(client, name, rdclass, type, options,
+ client->task, resolve_done, resarg,
+ &resarg->trans);
+@@ -1066,7 +1189,7 @@ dns_client_resolve(dns_client_t *client,
+ * Start internal event loop. It blocks until the entire process
+ * is completed.
+ */
+- result = isc_app_ctxrun(client->actx);
++ result = isc_app_ctxrun(actx);
+
+ LOCK(&resarg->lock);
+ if (result == ISC_R_SUCCESS || result == ISC_R_SUSPEND) {
+@@ -1348,3 +1471,1634 @@ cleanup:
+ }
+ 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);
++ isc_mutex_destroy(&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, const 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));
++
++ isc_mutex_init(&reqarg->lock);
++
++ reqarg->actx = actx;
++ reqarg->client = client;
++ reqarg->trans = NULL;
++ reqarg->canceled = 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) {
++ isc_mutex_destroy(&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 = true;
++ dns_client_cancelresolve(reqarg->trans);
++
++ UNLOCK(&reqarg->lock);
++
++ /* reqarg will be freed in the event handler. */
++ } else {
++ UNLOCK(&reqarg->lock);
++
++ isc_mutex_destroy(&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, const 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 *tclone = NULL;
++ dns_clientreqevent_t *event = NULL;
++ reqctx_t *ctx = NULL;
++ dns_tsectype_t tsectype = dns_tsectype_none;
++ unsigned int reqoptions;
++
++ 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);
++ }
++
++ reqoptions = 0;
++ if ((options & DNS_CLIENTREQOPT_TCP) != 0) {
++ reqoptions |= DNS_REQUESTOPT_TCP;
++ }
++
++ tclone = NULL;
++ isc_task_attach(task, &tclone);
++ event = (dns_clientreqevent_t *)isc_event_allocate(
++ client->mctx, tclone, DNS_EVENT_CLIENTREQDONE, action, arg,
++ sizeof(*event));
++
++ ctx = isc_mem_get(client->mctx, sizeof(*ctx));
++ isc_mutex_init(&ctx->lock);
++
++ ctx->client = client;
++ ISC_LINK_INIT(ctx, link);
++ ctx->parseoptions = parseoptions;
++ ctx->canceled = 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);
++ isc_refcount_increment(&client->references);
++ UNLOCK(&client->lock);
++
++ ctx->request = NULL;
++ result = dns_request_createvia(view->requestmgr, qmessage, NULL, server,
++ -1, reqoptions, 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);
++ }
++
++ isc_refcount_decrement1(&client->references);
++
++ LOCK(&client->lock);
++ ISC_LIST_UNLINK(client->reqctxs, ctx, link);
++ UNLOCK(&client->lock);
++ isc_mutex_destroy(&ctx->lock);
++ isc_mem_put(client->mctx, ctx, sizeof(*ctx));
++
++ isc_event_free(ISC_EVENT_PTR(&event));
++ isc_task_detach(&tclone);
++ 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 = 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;
++
++ REQUIRE(transp != NULL);
++ ctx = (reqctx_t *)*transp;
++ *transp = NULL;
++ 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);
++
++ UNLOCK(&client->lock);
++
++ isc_mutex_destroy(&ctx->lock);
++ ctx->magic = 0;
++
++ isc_mem_put(mctx, ctx, sizeof(*ctx));
++
++ dns_client_destroy(&client);
++}
++
++/*%
++ * 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_detach(&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, reqoptions;
++
++ 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;
++ }
++
++ dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE, &answer);
++ 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_detach(&answer);
++ }
++ isc_event_free(&event);
++
++ LOCK(&uctx->lock);
++ uctx->currentserver = ISC_LIST_NEXT(uctx->currentserver, link);
++ dns_request_destroy(&uctx->updatereq);
++ /*
++ * Moving on to the next server shouldn't change the result
++ * for NXDOMAIN, YXDOMAIN, NXRRSET and YXRRSET as they
++ * indicate a prerequisite failure. REFUSED should also
++ * be consistent across all servers but often isn't as that
++ * is policy rather that zone content driven (slaves that
++ * aren't willing to forward should return NOTIMPL). NOTZONE
++ * indicates that we stuffed up the request construction so
++ * don't retry.
++ */
++ if (result != ISC_R_SUCCESS && result != DNS_R_NXDOMAIN &&
++ result != DNS_R_YXDOMAIN && result != DNS_R_YXRRSET &&
++ result != DNS_R_NXRRSET && result != DNS_R_NOTZONE &&
++ !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;
++ }
++ reqoptions = 0;
++ if (uctx->want_tcp) {
++ reqoptions |= DNS_REQUESTOPT_TCP;
++ }
++ result = dns_request_createvia(
++ uctx->view->requestmgr, uctx->updatemsg, NULL,
++ uctx->currentserver, -1, reqoptions, 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, reqoptions;
++
++ 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;
++ }
++ reqoptions = 0;
++ if (uctx->want_tcp) {
++ reqoptions |= DNS_REQUESTOPT_TCP;
++ }
++ result = dns_request_createvia(
++ uctx->view->requestmgr, uctx->updatemsg, NULL,
++ uctx->currentserver, -1, reqoptions, 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;
++ bool completed = 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));
++
++ dns_rdata_init(&rdata);
++ switch (family) {
++ case AF_INET:
++ dns_rdataset_current(rdataset, &rdata);
++ result = dns_rdata_tostruct(
++ &rdata, &rdata_a, NULL);
++ RUNTIME_CHECK(result == ISC_R_SUCCESS);
++ isc_sockaddr_fromin(
++ sa, &rdata_a.in_addr, 53);
++ dns_rdata_freestruct(&rdata_a);
++ break;
++ case AF_INET6:
++ dns_rdataset_current(rdataset, &rdata);
++ result = dns_rdata_tostruct(
++ &rdata, &rdata_aaaa, NULL);
++ RUNTIME_CHECK(result == ISC_R_SUCCESS);
++ 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 = 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,
++ const dns_name_t *soaname) {
++ isc_result_t result;
++ dns_rdata_t soarr = DNS_RDATA_INIT;
++ dns_rdata_soa_t soa;
++ dns_name_t primary;
++ unsigned int resoptions;
++
++ 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);
++ dns_name_copynf(soaname, uctx->zonename);
++ }
++
++ 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;
++ resoptions = 0;
++ if (uctx->want_tcp) {
++ resoptions |= DNS_CLIENTRESOPT_TCP;
++ }
++ result = dns_client_startresolve(
++ uctx->client, &primary, uctx->rdclass, dns_rdatatype_a,
++ resoptions, 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, resoptions,
++ uctx->client->task, resolveaddr_done,
++ &uctx->bp6, &uctx->restrans2);
++ }
++ UNLOCK(&uctx->lock);
++ }
++
++ 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;
++ bool seencname = false;
++ bool droplabel = false;
++ dns_name_t tname;
++ unsigned int nlabels, reqoptions;
++
++ UNUSED(task);
++
++ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
++ reqev = (dns_requestevent_t *)event;
++ request = reqev->request;
++ result = eresult = reqev->result;
++ POST(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;
++ }
++
++ dns_message_create(uctx->client->mctx, DNS_MESSAGE_INTENTPARSE,
++ &rcvmsg);
++ 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_detach(&rcvmsg);
++ dns_message_renderreset(uctx->soaquery);
++ reqoptions = 0;
++ if (uctx->want_tcp) {
++ reqoptions |= DNS_REQUESTOPT_TCP;
++ }
++ result = dns_request_createvia(
++ uctx->view->requestmgr, uctx->soaquery, NULL, addr, -1,
++ reqoptions, 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;
++ POST(section);
++
++ 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 = 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 = true;
++ break;
++ }
++ }
++
++ result = dns_message_nextname(rcvmsg, section);
++ }
++
++ if (soaset == NULL && !seencname) {
++ pass++;
++ goto lookforsoa;
++ }
++
++ if (seencname) {
++ droplabel = 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);
++ reqoptions = 0;
++ if (uctx->want_tcp) {
++ reqoptions |= DNS_REQUESTOPT_TCP;
++ }
++ result = dns_request_createvia(
++ uctx->view->requestmgr, soaquery, NULL,
++ uctx->currentserver, -1, reqoptions,
++ 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_detach(&uctx->soaquery);
++ LOCK(&uctx->lock);
++ dns_request_destroy(&uctx->soareq);
++ UNLOCK(&uctx->lock);
++ }
++
++ if (rcvmsg != NULL) {
++ dns_message_detach(&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;
++ unsigned int reqoptions;
++
++ if (soaquery == NULL) {
++ dns_message_create(uctx->client->mctx, DNS_MESSAGE_INTENTRENDER,
++ &soaquery);
++ }
++ 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;
++ reqoptions = 0;
++ if (uctx->want_tcp) {
++ reqoptions |= DNS_REQUESTOPT_TCP;
++ }
++
++ result = dns_request_createvia(
++ uctx->view->requestmgr, soaquery, NULL, uctx->currentserver, -1,
++ reqoptions, 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_detach(&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, resoptions;
++
++ 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);
++ resoptions = 0;
++ if (uctx->want_tcp) {
++ resoptions |= DNS_CLIENTRESOPT_TCP;
++ }
++
++ result = dns_client_startresolve(
++ uctx->client, &uctx->soaqname, uctx->rdclass,
++ dns_rdatatype_soa, resoptions, 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, const 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);
++ }
++ isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
++ dns_name_init(newname, NULL);
++ dns_name_setbuffer(newname, namebuf);
++ dns_message_takebuffer(msg, &namebuf);
++ dns_name_copynf(name, newname);
++
++ 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;
++ isc_buffer_allocate(mctx, &rdatabuf, r.length);
++ 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_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);
++ isc_mutex_destroy(&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,
++ const 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_CLIENTUPDOPT_ALLOWRUN) == 0)
++ {
++ /*
++ * If the client is run under application's control, we need
++ * to create a new running (sub)environment for this
++ * particular update.
++ */
++ return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */
++ } else {
++ actx = client->actx;
++ }
++
++ uarg = isc_mem_get(client->mctx, sizeof(*uarg));
++
++ isc_mutex_init(&uarg->lock);
++
++ uarg->actx = actx;
++ uarg->client = client;
++ uarg->result = ISC_R_FAILURE;
++ uarg->trans = NULL;
++ uarg->canceled = 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) {
++ isc_mutex_destroy(&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 = true;
++ dns_client_cancelupdate(uarg->trans);
++
++ UNLOCK(&uarg->lock);
++
++ /* uarg will be freed in the event handler. */
++ } else {
++ UNLOCK(&uarg->lock);
++
++ isc_mutex_destroy(&uarg->lock);
++ isc_mem_put(client->mctx, uarg, sizeof(*uarg));
++ }
++
++ return (result);
++}
++
++static void
++startupdate(isc_task_t *task, isc_event_t *event) {
++ updatectx_t *uctx;
++ isc_result_t result;
++ unsigned int resoptions;
++
++ REQUIRE(event != NULL);
++
++ UNUSED(task);
++
++ uctx = event->ev_arg;
++
++ 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 {
++ resoptions = 0;
++ if (uctx->want_tcp) {
++ resoptions |= DNS_CLIENTRESOPT_TCP;
++ }
++ dns_name_clone(uctx->firstname, &uctx->soaqname);
++ result = dns_client_startresolve(
++ uctx->client, &uctx->soaqname, uctx->rdclass,
++ dns_rdatatype_soa, resoptions, uctx->client->task,
++ resolvesoa_done, uctx, &uctx->restrans);
++ if (result != ISC_R_SUCCESS) {
++ goto fail;
++ }
++ }
++
++ isc_event_free(&event);
++
++fail:
++ if (result != ISC_R_SUCCESS) {
++ update_sendevent(uctx, result);
++ }
++}
++
++isc_result_t
++dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass,
++ const 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 *tclone = NULL;
++ dns_section_t section = DNS_SECTION_UPDATE;
++ isc_sockaddr_t *server, *sa = NULL;
++ dns_tsectype_t tsectype = dns_tsectype_none;
++ bool want_tcp;
++
++ 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);
++ }
++
++ want_tcp = ((options & DNS_CLIENTUPDOPT_TCP) != 0);
++
++ /*
++ * Create a context and prepare some resources.
++ */
++
++ uctx = isc_mem_get(client->mctx, sizeof(*uctx));
++
++ isc_mutex_init(&uctx->lock);
++
++ tclone = NULL;
++ isc_task_attach(task, &tclone);
++ uctx->client = client;
++ ISC_LINK_INIT(uctx, link);
++ uctx->state = dns_clientupdatestate_prepare;
++ uctx->view = view;
++ uctx->rdclass = rdclass;
++ uctx->canceled = 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;
++ uctx->want_tcp = want_tcp;
++ 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, tclone, DNS_EVENT_UPDATEDONE, action, arg,
++ sizeof(*uctx->event));
++ if (zonename != NULL) {
++ uctx->zonename = dns_fixedname_name(&uctx->zonefname);
++ dns_name_copynf(zonename, uctx->zonename);
++ }
++ 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));
++ 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 */
++ dns_message_create(client->mctx, DNS_MESSAGE_INTENTRENDER,
++ &uctx->updatemsg);
++ 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);
++ isc_refcount_increment(&client->references);
++ UNLOCK(&client->lock);
++
++ *transp = (dns_clientupdatetrans_t *)uctx;
++ result = isc_app_ctxonrun(client->actx, client->mctx, client->task,
++ startupdate, uctx);
++ if (result == ISC_R_ALREADYRUNNING) {
++ isc_event_t *event;
++ event = isc_event_allocate(client->mctx, dns_client_startupdate,
++ DNS_EVENT_STARTUPDATE, startupdate,
++ uctx, sizeof(*event));
++ result = ISC_R_SUCCESS;
++ isc_task_send(task, &event);
++ }
++ if (result == ISC_R_SUCCESS) {
++ return (result);
++ }
++
++ isc_refcount_decrement1(&client->references);
++ *transp = NULL;
++
++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_detach(&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(&tclone);
++ isc_mutex_destroy(&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 = 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_sockaddr_t *sa;
++
++ REQUIRE(transp != NULL);
++ uctx = (updatectx_t *)*transp;
++ *transp = NULL;
++ 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);
++
++ UNLOCK(&client->lock);
++
++ isc_mutex_destroy(&uctx->lock);
++ uctx->magic = 0;
++
++ isc_mem_put(mctx, uctx, sizeof(*uctx));
++
++ dns_client_destroy(&client);
++}
++
++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, const 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);
++ 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,
++ (unsigned int)(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);
++ ISC_UNREACHABLE();
++ }
++
++ 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;
++ }
++}
Index: pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_client.h
diff -u /dev/null pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_client.h:1.1.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-lib_dns_include_dns_client.h Mon Nov 1 22:24:56 2021
@@ -0,0 +1,280 @@
+$NetBSD: patch-lib_dns_include_dns_client.h,v 1.1.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- lib/dns/include/dns/client.h.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/dns/include/dns/client.h
+@@ -73,7 +73,7 @@ ISC_LANG_BEGINDECLS
+ /*%< Do not return DNSSEC data (e.g. RRSIGS) with response. */
+ #define DNS_CLIENTRESOPT_NODNSSEC 0x01
+ /*%< Allow running external context. */
+-#define DNS_CLIENTRESOPT_RESERVED 0x02
++#define DNS_CLIENTRESOPT_ALLOWRUN 0x02
+ /*%< Don't validate responses. */
+ #define DNS_CLIENTRESOPT_NOVALIDATE 0x04
+ /*%< Don't set the CD flag on upstream queries. */
+@@ -85,7 +85,7 @@ ISC_LANG_BEGINDECLS
+ * Optional flags for dns_client_(start)request.
+ */
+ /*%< Allow running external context. */
+-#define DNS_CLIENTREQOPT_RESERVED 0x01
++#define DNS_CLIENTREQOPT_ALLOWRUN 0x01
+ /*%< Use TCP transport. */
+ #define DNS_CLIENTREQOPT_TCP 0x02
+
+@@ -93,7 +93,7 @@ ISC_LANG_BEGINDECLS
+ * Optional flags for dns_client_(start)update.
+ */
+ /*%< Allow running external context. */
+-#define DNS_CLIENTUPDOPT_RESERVED 0x01
++#define DNS_CLIENTUPDOPT_ALLOWRUN 0x01
+ /*%< Use TCP transport. */
+ #define DNS_CLIENTUPDOPT_TCP 0x02
+
+@@ -119,6 +119,15 @@ typedef struct dns_clientresevent {
+ } 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
+@@ -132,6 +141,21 @@ typedef struct dns_clientreqevent {
+ 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(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
+@@ -139,16 +163,25 @@ dns_client_create(isc_mem_t *mctx, isc_a
+ const isc_sockaddr_t *localaddr4,
+ const isc_sockaddr_t *localaddr6);
+ /*%<
+- * Create a DNS client object with minimal internal resources, such as
+- * a default view for the IN class and IPv4/IPv6 dispatches for the view.
++ * 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_create() takes 'manager' arguments so that the caller can
++ * dns_client_createx() takes 'manager' arguments so that the caller can
+ * control the behavior of the client through the underlying event framework.
+- * 'localaddr4' and 'localaddr6' specify the local addresses to use for
+- * each address family; if both are set to NULL, then wildcard addresses
+- * will be used for both families. If only one is NULL, then the other
+- * address will be used as the local address, and the NULL protocol family
+- * will not be used.
++ * 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.
++ *
++ * dns_client_createx2 takes two additional parameters, 'localaddr4' and
++ * 'localaddr6', to specify the local address to use for each family. If
++ * both are set to NULL, then wildcard addresses will be used for both
++ * families. If only one is NULL, then the other address will be used
++ * as the local address, and the other protocol family will not be used.
++ *
++ * If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options',
++ * dns_client_create(x) will create a cache database with the view.
+ *
+ * Requires:
+ *
+@@ -267,8 +300,11 @@ dns_client_startresolve(dns_client_t *cl
+ * error. Otherwise, it returns the result code of the entire resolution
+ * process, either success or failure.
+ *
+- * It is expected that the client object passed to dns_client_resolve() was
+- * created via dns_client_create() and has external managers and contexts.
++ * 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
+@@ -404,8 +440,11 @@ dns_client_startrequest(dns_client_t *cl
+ * 'rmessage' will contain the response message. The caller must provide a
+ * valid initialized message.
+ *
+- * It is expected that the client object passed to dns_client_request() was
+- * created via dns_client_create() and has external managers and contexts.
++ * 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
+@@ -469,6 +508,146 @@ dns_client_destroyreqtrans(dns_clientreq
+ *\li *transp == NULL.
+ */
+
++isc_result_t
++dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass,
++ const 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,
++ const 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.
++ *
++ * It is typically expected that the client object passed to
++ * dns_client_update() was created via dns_client_create() and has its own
++ * managers and contexts. However, if the DNS_CLIENTUPDOPT_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_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.
++ *
++ * DNS_CLIENTUPDOPT_TCP switches to the TCP (vs. UDP) transport.
++ *
++ * 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, const 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 */
Index: pkgsrc/net/bind916/patches/patch-lib_dns_rdata.c
diff -u /dev/null pkgsrc/net/bind916/patches/patch-lib_dns_rdata.c:1.1.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-lib_dns_rdata.c Mon Nov 1 22:24:56 2021
@@ -0,0 +1,17 @@
+$NetBSD: patch-lib_dns_rdata.c,v 1.1.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- lib/dns/rdata.c.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/dns/rdata.c
+@@ -1888,8 +1888,8 @@ inet_totext(int af, uint32_t flags, isc_
+ * parsing, so append 0 in that case.
+ */
+ if (af == AF_INET6 && (flags & DNS_STYLEFLAG_YAML) != 0) {
+- isc_textregion_t tr;
+- isc_buffer_usedregion(target, (isc_region_t *)&tr);
++ isc_region_t tr;
++ isc_buffer_usedregion(target, &tr);
+ if (tr.base[tr.length - 1] == ':') {
+ if (isc_buffer_availablelength(target) == 0) {
+ return (ISC_R_NOSPACE);
Index: pkgsrc/net/bind916/patches/patch-lib_isc_app.c
diff -u /dev/null pkgsrc/net/bind916/patches/patch-lib_isc_app.c:1.1.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-lib_isc_app.c Mon Nov 1 22:24:56 2021
@@ -0,0 +1,24 @@
+$NetBSD: patch-lib_isc_app.c,v 1.1.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- lib/isc/app.c.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/isc/app.c
+@@ -162,6 +162,8 @@ isc_app_ctxstart(isc_appctx_t *ctx) {
+ * blocked by default, ensuring that only the thread that calls
+ * sigwait() for them will get those signals.
+ */
++ if (isc_bind9) {
++
+ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 ||
+ sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0)
+ {
+@@ -176,6 +178,8 @@ isc_app_ctxstart(isc_appctx_t *ctx) {
+ "isc_app_start() pthread_sigmask: %s", strbuf);
+ }
+
++ }
++
+ #endif /* WIN32 */
+
+ return (ISC_R_SUCCESS);
Index: pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr-int.h
diff -u /dev/null pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr-int.h:1.1.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-lib_isc_netmgr_netmgr-int.h Mon Nov 1 22:24:56 2021
@@ -0,0 +1,102 @@
+$NetBSD: patch-lib_isc_netmgr_netmgr-int.h,v 1.1.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- lib/isc/netmgr/netmgr-int.h.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/isc/netmgr/netmgr-int.h
+@@ -377,13 +377,13 @@ typedef struct isc__netievent__socket {
+ } isc__netievent__socket_t;
+
+ #define NETIEVENT_SOCKET_TYPE(type) \
+- typedef isc__netievent__socket_t isc__netievent_##type##_t;
++ typedef isc__netievent__socket_t isc__netievent_##type##_t
+
+ #define NETIEVENT_SOCKET_DECL(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+ isc_nm_t *nm, isc_nmsocket_t *sock); \
+ void isc__nm_put_netievent_##type(isc_nm_t *nm, \
+- isc__netievent_##type##_t *ievent);
++ isc__netievent_##type##_t *ievent)
+
+ #define NETIEVENT_SOCKET_DEF(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+@@ -407,13 +407,13 @@ typedef struct isc__netievent__socket_re
+ } isc__netievent__socket_req_t;
+
+ #define NETIEVENT_SOCKET_REQ_TYPE(type) \
+- typedef isc__netievent__socket_req_t isc__netievent_##type##_t;
++ typedef isc__netievent__socket_req_t isc__netievent_##type##_t
+
+ #define NETIEVENT_SOCKET_REQ_DECL(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+ isc_nm_t *nm, isc_nmsocket_t *sock, isc__nm_uvreq_t *req); \
+ void isc__nm_put_netievent_##type(isc_nm_t *nm, \
+- isc__netievent_##type##_t *ievent);
++ isc__netievent_##type##_t *ievent)
+
+ #define NETIEVENT_SOCKET_REQ_DEF(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+@@ -440,14 +440,14 @@ typedef struct isc__netievent__socket_re
+ } isc__netievent__socket_req_result_t;
+
+ #define NETIEVENT_SOCKET_REQ_RESULT_TYPE(type) \
+- typedef isc__netievent__socket_req_result_t isc__netievent_##type##_t;
++ typedef isc__netievent__socket_req_result_t isc__netievent_##type##_t
+
+ #define NETIEVENT_SOCKET_REQ_RESULT_DECL(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+ isc_nm_t *nm, isc_nmsocket_t *sock, isc__nm_uvreq_t *req, \
+ isc_result_t result); \
+ void isc__nm_put_netievent_##type(isc_nm_t *nm, \
+- isc__netievent_##type##_t *ievent);
++ isc__netievent_##type##_t *ievent)
+
+ #define NETIEVENT_SOCKET_REQ_RESULT_DEF(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+@@ -474,13 +474,13 @@ typedef struct isc__netievent__socket_ha
+ } isc__netievent__socket_handle_t;
+
+ #define NETIEVENT_SOCKET_HANDLE_TYPE(type) \
+- typedef isc__netievent__socket_handle_t isc__netievent_##type##_t;
++ typedef isc__netievent__socket_handle_t isc__netievent_##type##_t
+
+ #define NETIEVENT_SOCKET_HANDLE_DECL(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+ isc_nm_t *nm, isc_nmsocket_t *sock, isc_nmhandle_t *handle); \
+ void isc__nm_put_netievent_##type(isc_nm_t *nm, \
+- isc__netievent_##type##_t *ievent);
++ isc__netievent_##type##_t *ievent)
+
+ #define NETIEVENT_SOCKET_HANDLE_DEF(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+@@ -506,13 +506,13 @@ typedef struct isc__netievent__socket_qu
+ } isc__netievent__socket_quota_t;
+
+ #define NETIEVENT_SOCKET_QUOTA_TYPE(type) \
+- typedef isc__netievent__socket_quota_t isc__netievent_##type##_t;
++ typedef isc__netievent__socket_quota_t isc__netievent_##type##_t
+
+ #define NETIEVENT_SOCKET_QUOTA_DECL(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+ isc_nm_t *nm, isc_nmsocket_t *sock, isc_quota_t *quota); \
+ void isc__nm_put_netievent_##type(isc_nm_t *nm, \
+- isc__netievent_##type##_t *ievent);
++ isc__netievent_##type##_t *ievent)
+
+ #define NETIEVENT_SOCKET_QUOTA_DEF(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+@@ -571,12 +571,12 @@ typedef struct isc__netievent {
+ isc__netievent_type type;
+ } isc__netievent_t;
+
+-#define NETIEVENT_TYPE(type) typedef isc__netievent_t isc__netievent_##type##_t;
++#define NETIEVENT_TYPE(type) typedef isc__netievent_t isc__netievent_##type##_t
+
+ #define NETIEVENT_DECL(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type(isc_nm_t *nm); \
+ void isc__nm_put_netievent_##type(isc_nm_t *nm, \
+- isc__netievent_##type##_t *ievent);
++ isc__netievent_##type##_t *ievent)
+
+ #define NETIEVENT_DEF(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
Index: pkgsrc/net/bind916/patches/patch-lib_isc_timer.c
diff -u /dev/null pkgsrc/net/bind916/patches/patch-lib_isc_timer.c:1.1.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-lib_isc_timer.c Mon Nov 1 22:24:56 2021
@@ -0,0 +1,15 @@
+$NetBSD: patch-lib_isc_timer.c,v 1.1.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- lib/isc/timer.c.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/isc/timer.c
+@@ -696,7 +696,7 @@ isc_timermgr_create(isc_mem_t *mctx, isc
+ isc_mem_attach(mctx, &manager->mctx);
+ isc_condition_init(&manager->wakeup);
+ isc_thread_create(run, manager, &manager->thread);
+- isc_thread_setname(manager->thread, "isc-timer");
++ isc_thread_setname(manager->thread, "timer");
+
+ *managerp = manager;
+
Index: pkgsrc/net/bind916/patches/patch-lib_isc_unix_include_isc_stdatomic.h
diff -u /dev/null pkgsrc/net/bind916/patches/patch-lib_isc_unix_include_isc_stdatomic.h:1.1.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-lib_isc_unix_include_isc_stdatomic.h Mon Nov 1 22:24:56 2021
@@ -0,0 +1,15 @@
+$NetBSD: patch-lib_isc_unix_include_isc_stdatomic.h,v 1.1.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- lib/isc/unix/include/isc/stdatomic.h.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/isc/unix/include/isc/stdatomic.h
+@@ -142,7 +142,7 @@ typedef uintmax_t atomic_uintmax_t;
+ __c11_atomic_compare_exchange_weak_explicit(obj, expected, desired, \
+ succ, fail)
+ #define atomic_exchange_explicit(obj, desired, order) \
+- __c11_atomic_exchange_explicit(obj, expected, order)
++ __c11_atomic_exchange_explicit(obj, desired, order)
+ #elif defined(__GNUC_ATOMICS) /* __atomic builtins */
+ #define atomic_init(obj, desired) (*obj = desired)
+ #define atomic_load_explicit(obj, order) __atomic_load_n(obj, order)
Index: pkgsrc/net/bind916/patches/patch-lib_isc_siphash.c
diff -u /dev/null pkgsrc/net/bind916/patches/patch-lib_isc_siphash.c:1.3.2.2
--- /dev/null Mon Nov 1 22:24:57 2021
+++ pkgsrc/net/bind916/patches/patch-lib_isc_siphash.c Mon Nov 1 22:24:56 2021
@@ -0,0 +1,23 @@
+$NetBSD: patch-lib_isc_siphash.c,v 1.3.2.2 2021/11/01 22:24:56 tm Exp $
+
+* Take from NetBSD base.
+
+--- lib/isc/siphash.c.orig 2021-09-07 09:37:05.000000000 +0000
++++ lib/isc/siphash.c
+@@ -90,8 +90,14 @@ isc_siphash24(const uint8_t *k, const ui
+ REQUIRE(k != NULL);
+ REQUIRE(out != NULL);
+
+- uint64_t k0 = U8TO64_LE(k);
+- uint64_t k1 = U8TO64_LE(k + 8);
++ uint64_t k0;
++ uint64_t k1;
++
++ memcpy(&k0, k, sizeof(k0));
++ memcpy(&k1, k + sizeof(k0), sizeof(k1));
++
++ k0 = le64toh(k0);
++ k1 = le64toh(k1);
+
+ uint64_t v0 = UINT64_C(0x736f6d6570736575) ^ k0;
+ uint64_t v1 = UINT64_C(0x646f72616e646f6d) ^ k1;
Home |
Main Index |
Thread Index |
Old Index