From da0eafcdee52147e72d407cc3b9f179378ee1d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 30 May 2023 08:46:17 +0200 Subject: [PATCH 01/12] Improve RBT overmem cache cleaning When cache memory usage is over the configured cache size (overmem) and we are cleaning unused entries, it might not be enough to clean just two entries if the entries to be expired are smaller than the newly added rdata. This could be abused by an attacker to cause a remote Denial of Service by possibly running out of the operating system memory. Currently, the addrdataset() tries to do a single TTL-based cleaning considering the serve-stale TTL and then optionally moves to overmem cleaning if we are in that condition. Then the overmem_purge() tries to do another single TTL based cleaning from the TTL heap and then continue with LRU-based cleaning up to 2 entries cleaned. Squash the TTL-cleaning mechanism into single call from addrdataset(), but ignore the serve-stale TTL if we are currently overmem. Then instead of having a fixed number of entries to clean, pass the size of newly added rdatasetheader to the overmem_purge() function and cleanup at least the size of the newly added data. This prevents the cache going over the configured memory limit (`max-cache-size`). Additionally, refactor the overmem_purge() function to reduce for-loop nesting for readability. --- lib/dns/rbtdb.c | 117 +++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 47 deletions(-) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 2bc92f3835..6887b9fcc4 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -622,7 +622,7 @@ expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, isc_rwlocktype_t *nlocktypep, isc_rwlocktype_t *tlocktypep, expire_t reason DNS__DB_FLARG); static void -overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now, +overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, size_t purgesize, isc_rwlocktype_t *tlocktypep DNS__DB_FLARG); static void resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader); @@ -6878,6 +6878,16 @@ cleanup: static dns_dbmethods_t zone_methods; +static size_t +rdataset_size(rdatasetheader_t *header) { + if (!NONEXISTENT(header)) { + return (dns_rdataslab_size((unsigned char *)header, + sizeof(*header))); + } + + return (sizeof(*header)); +} + static isc_result_t addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, @@ -7042,7 +7052,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } if (cache_is_overmem) { - overmem_purge(rbtdb, rbtnode->locknum, now, + overmem_purge(rbtdb, rbtnode->locknum, rdataset_size(newheader), &tlocktype DNS__DB_FLARG_PASS); } @@ -7062,12 +7072,19 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1); - if (header != NULL && - header->rdh_ttl + STALE_TTL(header, rbtdb) < - now - RBTDB_VIRTUAL) - { - expire_header(rbtdb, header, &nlocktype, &tlocktype, - expire_ttl DNS__DB_FLARG_PASS); + if (header != NULL) { + dns_ttl_t rdh_ttl = header->rdh_ttl; + + /* Only account for stale TTL if cache is not overmem */ + if (!cache_is_overmem) { + rdh_ttl += STALE_TTL(header, rbtdb); + } + + if (rdh_ttl < now - RBTDB_VIRTUAL) { + expire_header(rbtdb, header, &nlocktype, + &tlocktype, + expire_ttl DNS__DB_FLARG_PASS); + } } /* @@ -9971,54 +9988,61 @@ update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, isc_stdtime_t now) { ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum], header, link); } +static size_t +expire_lru_headers(dns_rbtdb_t *rbtdb, unsigned int locknum, + isc_rwlocktype_t *nlocktypep, isc_rwlocktype_t *tlocktypep, + size_t purgesize DNS__DB_FLARG) { + rdatasetheader_t *header, *header_prev; + size_t purged = 0; + + for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]); + header != NULL && purged <= purgesize; header = header_prev) + { + header_prev = ISC_LIST_PREV(header, link); + /* + * Unlink the entry at this point to avoid checking it + * again even if it's currently used someone else and + * cannot be purged at this moment. This entry won't be + * referenced any more (so unlinking is safe) since the + * TTL was reset to 0. + */ + ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header, link); + size_t header_size = rdataset_size(header); + expire_header(rbtdb, header, nlocktypep, tlocktypep, + expire_lru DNS__DB_FLARG_PASS); + purged += header_size; + } + + return (purged); +} + /*% - * Purge some expired and/or stale (i.e. unused for some period) cache entries - * under an overmem condition. To recover from this condition quickly, up to - * 2 entries will be purged. This process is triggered while adding a new - * entry, and we specifically avoid purging entries in the same LRU bucket as - * the one to which the new entry will belong. Otherwise, we might purge - * entries of the same name of different RR types while adding RRsets from a - * single response (consider the case where we're adding A and AAAA glue records - * of the same NS name). + * Purge some stale (i.e. unused for some period - LRU based cleaning) cache + * entries under the overmem condition. To recover from this condition quickly, + * we cleanup entries up to the size of newly added rdata (passed as purgesize). + * + * This process is triggered while adding a new entry, and we specifically avoid + * purging entries in the same LRU bucket as the one to which the new entry will + * belong. Otherwise, we might purge entries of the same name of different RR + * types while adding RRsets from a single response (consider the case where + * we're adding A and AAAA glue records of the same NS name). */ static void -overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now, +overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, size_t purgesize, isc_rwlocktype_t *tlocktypep DNS__DB_FLARG) { - rdatasetheader_t *header, *header_prev; unsigned int locknum; - int purgecount = 2; + size_t purged = 0; for (locknum = (locknum_start + 1) % rbtdb->node_lock_count; - locknum != locknum_start && purgecount > 0; + locknum != locknum_start && purged <= purgesize; locknum = (locknum + 1) % rbtdb->node_lock_count) { isc_rwlocktype_t nlocktype = isc_rwlocktype_none; NODE_WRLOCK(&rbtdb->node_locks[locknum].lock, &nlocktype); - header = isc_heap_element(rbtdb->heaps[locknum], 1); - if (header && header->rdh_ttl < now - RBTDB_VIRTUAL) { - expire_header(rbtdb, header, &nlocktype, tlocktypep, - expire_ttl DNS__DB_FLARG_PASS); - purgecount--; - } - - for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]); - header != NULL && purgecount > 0; header = header_prev) - { - header_prev = ISC_LIST_PREV(header, link); - /* - * Unlink the entry at this point to avoid checking it - * again even if it's currently used someone else and - * cannot be purged at this moment. This entry won't be - * referenced any more (so unlinking is safe) since the - * TTL was reset to 0. - */ - ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header, - link); - expire_header(rbtdb, header, &nlocktype, tlocktypep, - expire_lru DNS__DB_FLARG_PASS); - purgecount--; - } + purged += expire_lru_headers( + rbtdb, locknum, &nlocktype, tlocktypep, + purgesize - purged DNS__DB_FLARG_PASS); NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, &nlocktype); } @@ -10037,15 +10061,14 @@ expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, INSIST(*nlocktypep == isc_rwlocktype_write); if (isc_refcount_current(&header->node->references) == 0) { - isc_rwlocktype_t nlocktype = isc_rwlocktype_write; /* * If no one else is using the node, we can clean it up now. * We first need to gain a new reference to the node to meet a * requirement of decrement_reference(). */ new_reference(rbtdb, header->node, - nlocktype DNS__DB_FLARG_PASS); - decrement_reference(rbtdb, header->node, 0, &nlocktype, + *nlocktypep DNS__DB_FLARG_PASS); + decrement_reference(rbtdb, header->node, 0, nlocktypep, tlocktypep, true, false DNS__DB_FLARG_PASS); if (rbtdb->cachestats == NULL) { From 616bd7a96ee17ac99a81e11141e2c8c89a884eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Thu, 1 Jun 2023 15:46:23 +0200 Subject: [PATCH 02/12] Add CHANGES and release note for [GL #4055] --- CHANGES | 4 +++- doc/notes/notes-current.rst | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 98d1e3d11f..c02537d86d 100644 --- a/CHANGES +++ b/CHANGES @@ -2,7 +2,9 @@ 6191. [placeholder] -6190. [placeholder] +6190. [security] Improve the overmem cleaning process to prevent the + cache going over the configured limit. (CVE-2023-2828) + [GL #4055] 6189. [bug] Fix an extra dns_validator deatch when encountering deadling which would lead to assertion failure. diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index a3bce92751..cfb62bd023 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -15,7 +15,14 @@ Notes for BIND 9.19.14 Security Fixes ~~~~~~~~~~~~~~ -- None. +- The overmem cleaning process has been improved, to prevent the cache from + significantly exceeding the configured :any:`max-cache-size` limit. + (CVE-2023-2828) + + ISC would like to thank Shoham Danino from Reichman University, Anat + Bremler-Barr from Tel-Aviv University, Yehuda Afek from Tel-Aviv University, + and Yuval Shavitt from Tel-Aviv University for bringing this vulnerability to + our attention. :gl:`#4055` New Features ~~~~~~~~~~~~ From 1afde574e9e16f15986e991fd17b570d8ecaf8ba Mon Sep 17 00:00:00 2001 From: Michal Nowak Date: Wed, 7 Jun 2023 14:03:01 +0200 Subject: [PATCH 03/12] Set max-cache-size expectations for low values --- doc/arm/reference.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 7aea96ea13..2aab7a6a9d 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -3772,6 +3772,11 @@ system. default value of that option (90% of physical memory for each individual cache) may lead to memory exhaustion over time. + .. note:: + + :any:`max-cache-size` does not work reliably for the maximum + amount of memory of 100 MB or lower. + Upon startup and reconfiguration, caches with a limited size preallocate a small amount of memory (less than 1% of :any:`max-cache-size` for a given view). This preallocation serves as an From f251588176f5716eb5a21de2cd7f0994f56fcc7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Fri, 2 Jun 2023 12:17:16 +0200 Subject: [PATCH 04/12] Add a missing word to the release note for #4004 --- doc/notes/notes-9.19.13.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/notes/notes-9.19.13.rst b/doc/notes/notes-9.19.13.rst index a88b3179c3..6438bc4e9a 100644 --- a/doc/notes/notes-9.19.13.rst +++ b/doc/notes/notes-9.19.13.rst @@ -29,11 +29,11 @@ Bug Fixes Furthermore, NOTIFY failures are now logged at the INFO level. :gl:`#4001` :gl:`#4002` -- The :any:`max-transfer-time-in` and :any:`max-transfer-idle-in` have - not had any effect since the BIND 9 networking stack was refactored in - version 9.16. The missing functionality has been re-implemented and - incoming zone transfers now time out properly when not progressing. - :gl:`#4004` +- The :any:`max-transfer-time-in` and :any:`max-transfer-idle-in` + statements have not had any effect since the BIND 9 networking stack + was refactored in version 9.16. The missing functionality has been + re-implemented and incoming zone transfers now time out properly when + not progressing. :gl:`#4004` - The read timeout in :iscman:`rndc` is now 60 seconds, matching the behavior in BIND 9.16 and earlier. It had previously been lowered to From eb88490e91688181b9793282f1ee1398848a29e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Fri, 2 Jun 2023 12:17:16 +0200 Subject: [PATCH 05/12] Re-add a code comment to the "hooks" system test Commit 5a84c7a09bccf124b9f10a2bc25bb635d822eec2 removed a useful code comment from the "hooks" system test. Add it back to prevent confusion. --- bin/tests/system/hooks/tests_async_plugin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/tests/system/hooks/tests_async_plugin.py b/bin/tests/system/hooks/tests_async_plugin.py index 48f9feefbd..2f42e27379 100644 --- a/bin/tests/system/hooks/tests_async_plugin.py +++ b/bin/tests/system/hooks/tests_async_plugin.py @@ -23,4 +23,5 @@ def test_async_hook(named_port): "A", ) ans = dns.query.udp(msg, "10.53.0.1", timeout=10, port=named_port) + # the test-async plugin changes the status of any positive answer to NOTIMP assert ans.rcode() == dns.rcode.NOTIMP From 350613af9d58398762e2a39d1d8b0acc7f74ef06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Fri, 2 Jun 2023 12:17:16 +0200 Subject: [PATCH 06/12] Drop "Known Issues" entry for #4006 as it is fixed --- doc/notes/notes-known-issues.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/notes/notes-known-issues.rst b/doc/notes/notes-known-issues.rst index d71ff3341c..e6622d56be 100644 --- a/doc/notes/notes-known-issues.rst +++ b/doc/notes/notes-known-issues.rst @@ -38,9 +38,3 @@ Known Issues have ``subjectAltName`` set. In such cases, the ``Subject`` field is ignored. Only old platforms are affected by this, e.g. those supplied with OpenSSL versions older than 1.1.1. :gl:`#3163` - -- Loading a large number of zones is significantly slower in BIND - 9.19.12 than in the previous development releases due to a new data - structure being used for storing information about the zones to serve. - This slowdown is considered to be a bug and will be addressed in a - future BIND 9.19.x development release. :gl:`#4006` From 1f48e1c998ffa2340e0e3a3d9ed64c59e560e5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Fri, 2 Jun 2023 12:24:48 +0200 Subject: [PATCH 07/12] Prepare release notes for BIND 9.19.14 --- doc/arm/notes.rst | 2 +- doc/notes/{notes-current.rst => notes-9.19.14.rst} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename doc/notes/{notes-current.rst => notes-9.19.14.rst} (100%) diff --git a/doc/arm/notes.rst b/doc/arm/notes.rst index 8b8d64d332..0a75a013ad 100644 --- a/doc/arm/notes.rst +++ b/doc/arm/notes.rst @@ -38,7 +38,7 @@ information about each release, and source code. .. include:: ../notes/notes-known-issues.rst -.. include:: ../notes/notes-current.rst +.. include:: ../notes/notes-9.19.14.rst .. include:: ../notes/notes-9.19.13.rst .. include:: ../notes/notes-9.19.12.rst .. include:: ../notes/notes-9.19.11.rst diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-9.19.14.rst similarity index 100% rename from doc/notes/notes-current.rst rename to doc/notes/notes-9.19.14.rst From 76877a83be202712ba7041895361bcf8993f8d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Fri, 2 Jun 2023 12:28:23 +0200 Subject: [PATCH 08/12] Tweak and reword release notes --- doc/notes/notes-9.19.14.rst | 45 +++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/doc/notes/notes-9.19.14.rst b/doc/notes/notes-9.19.14.rst index cfb62bd023..362913b6e5 100644 --- a/doc/notes/notes-9.19.14.rst +++ b/doc/notes/notes-9.19.14.rst @@ -27,16 +27,16 @@ Security Fixes New Features ~~~~~~~~~~~~ -- Add support for multi-signer model 2 (RFC 8901) when using - ``inline-signing``. :gl:`#2710` +- Support for multi-signer model 2 (:rfc:`8901`) when using + :any:`inline-signing` was added. :gl:`#2710` -- A new option to :any:`dnssec-policy` has been added, :any:`cdnskey`, that - allows you to enable or disable the publication of CDNSKEY records. - :gl:`#4050` +- A new option to :any:`dnssec-policy` has been added, :any:`cdnskey`, + that allows users to enable or disable the publication of CDNSKEY + records. :gl:`#4050` -- The read timeout in ``rndc`` can now be specified on the command line - using the ``-t`` option, allowing commands that take a long time to - complete sufficient time to do so. :gl:`#4046` +- The read timeout in :iscman:`rndc` can now be specified on the command + line using the :option:`-t ` option, allowing commands that + take a long time to complete sufficient time to do so. :gl:`#4046` - The system test suite can now be executed with pytest (along with pytest-xdist for parallel execution). :gl:`#3978` @@ -46,30 +46,31 @@ Removed Features - Special-case code that was originally added to allow GSS-TSIG to work around bugs in the Windows 2000 version of Active Directory has now - been removed since Windows 2000 is long past end-of-life. - The ``nsupdate -o`` option and the ``oldgsstsig`` command to ``nsupdate`` - have been deprecated, and are now treated as synonyms for ``nsupdate -g`` - and ``gsstsig`` respectively. :gl:`#4012` + been removed, since Windows 2000 is long past end-of-life. The + :option:`-o ` option and the ``oldgsstsig`` command to + :iscman:`nsupdate` have been deprecated, and are now treated as + synonyms for :option:`-g ` and ``gsstsig`` respectively. + :gl:`#4012` Feature Changes ~~~~~~~~~~~~~~~ -- Improve the responsiveness of the ``named`` serving as an authoritative DNS - server for a delegation-heavy zone(s) shortly after loading such zone(s). - :gl:`#4045` +- The responsiveness of :iscman:`named` was improved, when serving as an + authoritative DNS server for a delegation-heavy zone(s) shortly after + loading such zone(s). :gl:`#4045` Bug Fixes ~~~~~~~~~ - When the :any:`stale-answer-enable` option was enabled and the - :any:`stale-answer-client-timeout` option was enabled and larger than 0, - ``named`` was taking two places from the :any:`clients-per-query` limit for - each client and was failing to gradually auto-tune its value, as configured. - This has been fixed. :gl:`#4074` + :any:`stale-answer-client-timeout` option was enabled and larger than + 0, :iscman:`named` previously allocated two slots from the + :any:`clients-per-query` limit for each client and failed to gradually + auto-tune its value, as configured. This has been fixed. :gl:`#4074` -- It could happen that after the :any:`stale-answer-client-timeout` duration, - a delegation from cache was returned to the client. This has now been fixed. - :gl:`#3950` +- Previously, it was possible for a delegation from cache to be returned + to the client after the :any:`stale-answer-client-timeout` duration. + This has been fixed. :gl:`#3950` - BIND could allocate too big buffers when sending data via stream-based DNS transports, leading to increased memory usage. From f933f1856bdbfcd03aba18452ec42cd36b49eef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Fri, 2 Jun 2023 12:29:53 +0200 Subject: [PATCH 09/12] Reorder release notes --- doc/notes/notes-9.19.14.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/notes/notes-9.19.14.rst b/doc/notes/notes-9.19.14.rst index 362913b6e5..dbfebe43b9 100644 --- a/doc/notes/notes-9.19.14.rst +++ b/doc/notes/notes-9.19.14.rst @@ -27,6 +27,10 @@ Security Fixes New Features ~~~~~~~~~~~~ +- The read timeout in :iscman:`rndc` can now be specified on the command + line using the :option:`-t ` option, allowing commands that + take a long time to complete sufficient time to do so. :gl:`#4046` + - Support for multi-signer model 2 (:rfc:`8901`) when using :any:`inline-signing` was added. :gl:`#2710` @@ -34,10 +38,6 @@ New Features that allows users to enable or disable the publication of CDNSKEY records. :gl:`#4050` -- The read timeout in :iscman:`rndc` can now be specified on the command - line using the :option:`-t ` option, allowing commands that - take a long time to complete sufficient time to do so. :gl:`#4046` - - The system test suite can now be executed with pytest (along with pytest-xdist for parallel execution). :gl:`#3978` From 466530c73bc3bd17bc2f7bdc640c24f65a277923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Fri, 2 Jun 2023 12:17:16 +0200 Subject: [PATCH 10/12] Add release note for #4049 --- doc/notes/notes-9.19.14.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/notes/notes-9.19.14.rst b/doc/notes/notes-9.19.14.rst index dbfebe43b9..3a270e5d79 100644 --- a/doc/notes/notes-9.19.14.rst +++ b/doc/notes/notes-9.19.14.rst @@ -55,6 +55,11 @@ Removed Features Feature Changes ~~~~~~~~~~~~~~~ +- If a response from an authoritative server has its RCODE set to + FORMERR and contains an echoed EDNS COOKIE option that was present in + the query, :iscman:`named` now retries sending the query to the + same server without an EDNS COOKIE option. :gl:`#4049` + - The responsiveness of :iscman:`named` was improved, when serving as an authoritative DNS server for a delegation-heavy zone(s) shortly after loading such zone(s). :gl:`#4045` From 3b1149694172d9b52604e6059e87d6a9be05531f Mon Sep 17 00:00:00 2001 From: Michal Nowak Date: Fri, 9 Jun 2023 12:16:22 +0200 Subject: [PATCH 11/12] Add a CHANGES marker --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index c02537d86d..93722a30f2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ + --- 9.19.14 released --- + 6192. [placeholder] 6191. [placeholder] From fce968989356a7ae22036f4776072db6bb9c72b5 Mon Sep 17 00:00:00 2001 From: Michal Nowak Date: Fri, 9 Jun 2023 12:17:36 +0200 Subject: [PATCH 12/12] Update BIND version for release --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2d9d30eda1..3f79919a44 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ m4_define([bind_VERSION_MAJOR], 9)dnl m4_define([bind_VERSION_MINOR], 19)dnl m4_define([bind_VERSION_PATCH], 14)dnl -m4_define([bind_VERSION_EXTRA], -dev)dnl +m4_define([bind_VERSION_EXTRA], )dnl m4_define([bind_DESCRIPTION], [(Development Release)])dnl m4_define([bind_SRCID], [m4_esyscmd_s([git rev-parse --short HEAD | cut -b1-7])])dnl m4_define([bind_PKG_VERSION], [[bind_VERSION_MAJOR.bind_VERSION_MINOR.bind_VERSION_PATCH]bind_VERSION_EXTRA])dnl