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