diff options
Diffstat (limited to 'net-dns/c-ares')
-rw-r--r-- | net-dns/c-ares/Manifest | 3 | ||||
-rw-r--r-- | net-dns/c-ares/c-ares-1.22.0-r1.ebuild | 109 | ||||
-rw-r--r-- | net-dns/c-ares/files/c-ares-1.22.0-hosts-lookup-perf.patch | 403 | ||||
-rw-r--r-- | net-dns/c-ares/files/c-ares-1.22.0-hosts-lookup.patch | 109 |
4 files changed, 624 insertions, 0 deletions
diff --git a/net-dns/c-ares/Manifest b/net-dns/c-ares/Manifest index 2fddcda01e5c..8c73a94ca2ef 100644 --- a/net-dns/c-ares/Manifest +++ b/net-dns/c-ares/Manifest @@ -1,3 +1,5 @@ +AUX c-ares-1.22.0-hosts-lookup-perf.patch 12716 BLAKE2B cbe44158dde65ece531636d90279531311a0ea245fba0c69fa45eac022ae619370c2c34b575cf5bd00426f6035ad9884627f65e1abbbacdd91e8accb9ee31229 SHA512 197d978e99fc77bd99ada251751250fcf10d414a421aee99fbcdfd4cc971695ff41243de2455feebaf74cbfc26c953148d4ffcc1510a0c1b5d11a167b9bd9637 +AUX c-ares-1.22.0-hosts-lookup.patch 4165 BLAKE2B 226b019a5f20c6cb36af53699e5a110507a9a868d848f2096cb6938c934f5c50d57111b8f0465e9bded4e0e900fca4a5326bb184d09605241cbffb049bf72ba8 SHA512 fcd9ff94e13d6ad06a3e36085ec8bfffffa628a8563c8f6cc041e766f0dc313dc1d30fe8a96d1e0f4d42cef5a25fb8342cc7c619f90feb12bb520ebde32dd697 DIST c-ares-1.19.1.tar.gz 1579100 BLAKE2B 4b6c9593edb1a91ab76d54ddacb1cd5d67006d5e628ea1f3289f54e9360be32abeb5d8fc7d23e193feab3e7928e8efde82757eb12fe217dc92ed0d9132bedf5d SHA512 466a94efda626e815a6ef7a890637056339f883d549ea6055e289fd8cd2391130e5682c905c0fb3bd7e955af7f6deb793562c170eb0ee066a4a62085a82ba470 DIST c-ares-1.19.1.tar.gz.asc 488 BLAKE2B 9c47d7b3e67d9a2bd1e332912d21d20ca591fc34f81707c18a4615ea14ba2da00146d1998250a5f4dd2a0b1c04f9bd2013d4940ac734674c0bdff6815985e19d SHA512 1b204ab1a667af1326be4b7c62c0919aacd447a2e00efea4b8ef2ec9f2b13ffb236a836ff8953b0b3359727faf3fb8cfcd71d0b06a0e533a09f9e9ea66024f4e DIST c-ares-1.20.1.tar.gz 1599175 BLAKE2B 44d160e04dcbd78f0ad7c1f2eb3f34ff07017fd9b5c4bc12b81b123022297adccfff45f43630f8c73afdfd9424ff6ee9fb96c627405ec486c8d78bb0c7e518ca SHA512 83400fb276ebcf16dfe6f43d56ca87839d132b5a0544420eda9fa148eb85468b3f215593fcefc2a7a3a8ed8b0d4ef093ed99616a4e466b01f6913934240539e4 @@ -9,5 +11,6 @@ DIST c-ares-1.22.0.tar.gz.asc 488 BLAKE2B 93d378c92aef3ef1bfedc1d09ffb171c735c02 EBUILD c-ares-1.19.1.ebuild 1953 BLAKE2B 1ded6481a7ebecae276cf0be56591051b72ba20469590e1231b8c873cc9d3869fda7a36cc79f3cadf14f4fef27e05e68dadf683fe9a23b5884c6562f7f3db8c9 SHA512 cf383c805ba7f878afa5c1e75144fca115ee60f420fb257e42badd9d31eaefcb21e2ec9eccdce72d061287e67aa3fe38cfa4ad7168064b8e95318e041e651aa7 EBUILD c-ares-1.20.1.ebuild 2328 BLAKE2B e9bbfc9de5f1cb42435181fee98e9803c7e98282507484e96d31a7d02ec9032a378bf8e371da5f135d4e4592001c46bf5604bd94f1c3d671ea441dbffd4fff70 SHA512 e3e237c4194c9a6c831947c13167ad012f82cac3fe9c56aaad7df1951d30e1c829c12b13b151656ae76892eb3abb83e2fef18ee3113cfc25fe67af2004c58f94 EBUILD c-ares-1.21.0.ebuild 2320 BLAKE2B 0bf5577ca5af7eaaa7a0b1adb0acdc63b4a7c2a6be151c39742c6168ee8c44331f6918919d536967a34f527a3ee7b435979b5f4de27203b990a311d079731579 SHA512 fc5446f9b664a5fb93366877f86f029605842850a4aefc73d2c0138f7e5a4c7e61d2429e8c9be1256552805fce7220e26b3e9671dcaa1e561a465ddeceb96fdc +EBUILD c-ares-1.22.0-r1.ebuild 3100 BLAKE2B e17b04ae23041d39383cfdb423b88c6049710eb6ce8df54aa864d9abb905718acfcb97e416f64ef65bbd00fd6c52aef9e2ef3734ad7e67ca9f0681262a9897d8 SHA512 868365d27f7792aa00cee0839b7fd5cd489c2c12d5512ca6590b27c4dbec6b67f105028f266374dd99f990324d60c28f0266fe5a677a6ff0a66cb7f554c47790 EBUILD c-ares-1.22.0.ebuild 3004 BLAKE2B 54969e3ba5a0ae50507c72053c68e4cef46b5bcfb17a13a8da74787b7e9df95eb6991b72accc08e1cd668fb2f32a40b64531cb55599b017f8d9fe6e2410777ff SHA512 d887752df57e10a49959d18e1768cf0445771fbdc763c8867ec8dabf37e1baf0bddb1ec8676a5951ab408041fac5db34812165091d60e0c2740cec262466e9e3 MISC metadata.xml 402 BLAKE2B ab03bca92ec4073f5a877993558552136f0ae673f98619aa1f30eb94b6d8f2103b1cf77d23a9f2b3d56ee33af23d626ee230e480a3e3e0bc174df879082466bd SHA512 e02d13db5d10b1aaaae5680247a6b47610dda28a13b7754d2b97f08a760ce732957c96fb6e88ce7fd2076bfec275e72bfbb3dec802940f0159122364ab21acda diff --git a/net-dns/c-ares/c-ares-1.22.0-r1.ebuild b/net-dns/c-ares/c-ares-1.22.0-r1.ebuild new file mode 100644 index 000000000000..5356eceefd2a --- /dev/null +++ b/net-dns/c-ares/c-ares-1.22.0-r1.ebuild @@ -0,0 +1,109 @@ +# Copyright 1999-2023 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/danielstenberg.asc +inherit edo multilib-minimal verify-sig + +DESCRIPTION="C library that resolves names asynchronously" +HOMEPAGE="https://c-ares.org/" +SRC_URI=" + https://c-ares.org/download/${P}.tar.gz + verify-sig? ( https://c-ares.org/download/${P}.tar.gz.asc ) +" + +# ISC for lib/{bitncmp.c,inet_ntop.c,inet_net_pton.c} (bug #912405) +LICENSE="MIT ISC" +# Subslot = SONAME of libcares.so.2 +SLOT="0/2" +KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux ~arm64-macos ~ppc-macos ~x64-macos ~x64-solaris" +IUSE="static-libs test" +RESTRICT="!test? ( test )" + +BDEPEND="verify-sig? ( sec-keys/openpgp-keys-danielstenberg )" + +DOCS=( AUTHORS CHANGES NEWS README.md RELEASE-NOTES TODO ) + +PATCHES=( + "${FILESDIR}"/${P}-hosts-lookup.patch + "${FILESDIR}"/${P}-hosts-lookup-perf.patch +) + +MULTILIB_WRAPPED_HEADERS=( + /usr/include/ares_build.h +) + +QA_CONFIG_IMPL_DECL_SKIP=( + # Checking for obsolete headers + malloc + calloc + free + + # Non-existent on Linux + closesocket + CloseSocket + ioctlsocket + bitncmp +) + +multilib_src_configure() { + # These configure tests take a long time to run. The args one runs in O(n^4). + export ac_cv_func_getnameinfo='yes' + export ac_cv_func_recvfrom='yes' + export ac_cv_func_recv='yes' + export ac_cv_func_send='yes' + export curl_cv_func_getnameinfo_args='const struct sockaddr *,socklen_t,size_t,int' + export curl_cv_func_recv_args='int,void *,size_t,int,int' + export curl_cv_func_recvfrom_args='int,void *,size_t,int,struct sockaddr *,socklen_t *,int' + export curl_cv_func_send_args='int,const void *,size_t,int,int' + export curl_cv_getnameinfo='yes' + export curl_cv_recv='yes' + export curl_cv_recvfrom='yes' + export curl_cv_send='yes' + + local myeconfargs=( + --cache-file="${BUILD_DIR}"/config.cache + + --enable-nonblocking + --enable-symbol-hiding + $(use_enable static-libs static) + $(use_enable test tests) + ) + + # Needed for running unit tests only + # Violates sandbox and tests pass fine without + export ax_cv_uts_namespace=no + export ax_cv_user_namespace=no + ECONF_SOURCE="${S}" econf "${myeconfargs[@]}" +} + +multilib_src_test() { + cd "${BUILD_DIR}"/test || die + + # We're skipping the "real" network tests with the filter + # see https://github.com/c-ares/c-ares/tree/main/test + local network_tests=( + # Most live tests have Live in the name + *Live* + # These don't but are still in ares-test-live.cc => live + *GetTCPSock* + *TimeoutValue* + *GetSock* + *GetSock_virtualized* + *VerifySocketFunctionCallback* + # Seems flaky, even run manually + # https://github.com/c-ares/c-ares/commit/9e542a8839f81c990bb0dff14beeaf9aa6bcc18d + *MockUDPMaxQueriesTest.GetHostByNameParallelLookups* + ) + + # The format for disabling test1, test2, and test3 looks like: + # -test1:test2:test3 + edo ./arestest --gtest_filter=-$(echo $(IFS=:; echo "${network_tests[*]}")) +} + +multilib_src_install_all() { + einstalldocs + + find "${ED}" -name "*.la" -delete || die +} diff --git a/net-dns/c-ares/files/c-ares-1.22.0-hosts-lookup-perf.patch b/net-dns/c-ares/files/c-ares-1.22.0-hosts-lookup-perf.patch new file mode 100644 index 000000000000..4830c9cb97e9 --- /dev/null +++ b/net-dns/c-ares/files/c-ares-1.22.0-hosts-lookup-perf.patch @@ -0,0 +1,403 @@ +https://github.com/c-ares/c-ares/commit/2724f0e26c8875ce194d68dc15840e9435a1c805 + +From 2724f0e26c8875ce194d68dc15840e9435a1c805 Mon Sep 17 00:00:00 2001 +From: Brad House <brad@brad-house.com> +Date: Thu, 16 Nov 2023 15:20:48 -0500 +Subject: [PATCH] optimize: large /etc/hosts files reading + +profiling found some hot paths that could be optimized to reduce +insert times into the cache. + +Fix By: Brad House (@bradh352) +--- a/src/lib/ares__hosts_file.c ++++ b/src/lib/ares__hosts_file.c +@@ -313,81 +313,51 @@ static ares_hosts_file_t *ares__hosts_file_create(const char *filename) + return NULL; + } + +-static ares_bool_t ares__hosts_entry_ipaddr_exists(ares_hosts_entry_t *entry, +- const char *ipaddr) +-{ +- ares__llist_node_t *node; +- +- for (node = ares__llist_node_first(entry->ips); node != NULL; +- node = ares__llist_node_next(node)) { +- const char *myaddr = ares__llist_node_val(node); +- if (strcmp(myaddr, ipaddr) == 0) { +- return ARES_TRUE; +- } +- } +- +- return ARES_FALSE; +-} +- +-static ares_bool_t ares__hosts_entry_host_exists(ares_hosts_entry_t *entry, +- const char *host) +-{ +- ares__llist_node_t *node; +- +- for (node = ares__llist_node_first(entry->ips); node != NULL; +- node = ares__llist_node_next(node)) { +- const char *myhost = ares__llist_node_val(node); +- if (strcasecmp(myhost, host) == 0) { +- return ARES_TRUE; +- } +- } +- +- return ARES_FALSE; +-} ++typedef enum { ++ ARES_MATCH_NONE = 0, ++ ARES_MATCH_IPADDR = 1, ++ ARES_MATCH_HOST = 2 ++} ares_hosts_file_match_t; + +-static ares_status_t ares__hosts_file_merge_entry(ares_hosts_entry_t *existing, +- ares_hosts_entry_t *entry) ++static ares_status_t ares__hosts_file_merge_entry(ares_hosts_file_t *hf, ++ ares_hosts_entry_t *existing, ++ ares_hosts_entry_t *entry, ++ ares_hosts_file_match_t matchtype) + { + ares__llist_node_t *node; + +- while ((node = ares__llist_node_first(entry->ips)) != NULL) { +- char *ipaddr = ares__llist_node_claim(node); ++ /* If we matched on IP address, we know there can only be 1, so there's no ++ * reason to do anything */ ++ if (matchtype != ARES_MATCH_IPADDR) { ++ while ((node = ares__llist_node_first(entry->ips)) != NULL) { ++ const char *ipaddr = ares__llist_node_val(node); + +- if (ares__hosts_entry_ipaddr_exists(existing, ipaddr)) { +- ares_free(ipaddr); +- continue; +- } ++ if (ares__htable_strvp_get_direct(hf->iphash, ipaddr) != NULL) { ++ ares__llist_node_destroy(node); ++ continue; ++ } + +- if (ares__llist_insert_last(existing->ips, ipaddr) == NULL) { +- ares_free(ipaddr); +- return ARES_ENOMEM; ++ ares__llist_node_move_parent_last(node, existing->ips); + } + } + + + while ((node = ares__llist_node_first(entry->hosts)) != NULL) { +- char *hostname = ares__llist_node_claim(node); ++ const char *hostname = ares__llist_node_val(node); + +- if (ares__hosts_entry_host_exists(existing, hostname)) { +- ares_free(hostname); ++ if (ares__htable_strvp_get_direct(hf->hosthash, hostname) != NULL) { ++ ares__llist_node_destroy(node); + continue; + } + +- if (ares__llist_insert_last(existing->hosts, hostname) == NULL) { +- ares_free(hostname); +- return ARES_ENOMEM; +- } ++ ares__llist_node_move_parent_last(node, existing->hosts); + } + + ares__hosts_entry_destroy(entry); + return ARES_SUCCESS; + } + +-typedef enum { +- ARES_MATCH_NONE = 0, +- ARES_MATCH_IPADDR = 1, +- ARES_MATCH_HOST = 2 +-} ares_hosts_file_match_t; ++ + + static ares_hosts_file_match_t + ares__hosts_file_match(const ares_hosts_file_t *hf, ares_hosts_entry_t *entry, +@@ -435,7 +405,7 @@ static ares_status_t ares__hosts_file_add(ares_hosts_file_t *hosts, + matchtype = ares__hosts_file_match(hosts, entry, &match); + + if (matchtype != ARES_MATCH_NONE) { +- status = ares__hosts_file_merge_entry(match, entry); ++ status = ares__hosts_file_merge_entry(hosts, match, entry, matchtype); + if (status != ARES_SUCCESS) { + ares__hosts_entry_destroy(entry); + return status; +@@ -481,6 +451,22 @@ static ares_status_t ares__hosts_file_add(ares_hosts_file_t *hosts, + return ARES_SUCCESS; + } + ++static ares_bool_t ares__hosts_entry_isdup(ares_hosts_entry_t *entry, ++ const char *host) ++{ ++ ares__llist_node_t *node; ++ ++ for (node = ares__llist_node_first(entry->ips); node != NULL; ++ node = ares__llist_node_next(node)) { ++ const char *myhost = ares__llist_node_val(node); ++ if (strcasecmp(myhost, host) == 0) { ++ return ARES_TRUE; ++ } ++ } ++ ++ return ARES_FALSE; ++} ++ + static ares_status_t ares__parse_hosts_hostnames(ares__buf_t *buf, + ares_hosts_entry_t *entry) + { +@@ -531,7 +517,7 @@ static ares_status_t ares__parse_hosts_hostnames(ares__buf_t *buf, + } + + /* Don't add a duplicate to the same entry */ +- if (ares__hosts_entry_host_exists(entry, hostname)) { ++ if (ares__hosts_entry_isdup(entry, hostname)) { + continue; + } + +--- a/src/lib/ares__htable.c ++++ b/src/lib/ares__htable.c +@@ -66,7 +66,7 @@ static unsigned int ares__htable_generate_seed(ares__htable_t *htable) + + static void ares__htable_buckets_destroy(ares__llist_t **buckets, + unsigned int size, +- unsigned char destroy_vals) ++ ares_bool_t destroy_vals) + { + unsigned int i; + +@@ -94,7 +94,7 @@ void ares__htable_destroy(ares__htable_t *htable) + if (htable == NULL) { + return; + } +- ares__htable_buckets_destroy(htable->buckets, htable->size, 1); ++ ares__htable_buckets_destroy(htable->buckets, htable->size, ARES_TRUE); + ares_free(htable); + } + +@@ -180,11 +180,40 @@ static ares_bool_t ares__htable_expand(ares__htable_t *htable) + + for (i = 0; i < old_size; i++) { + ares__llist_node_t *node; +- for (node = ares__llist_node_first(htable->buckets[i]); node != NULL; +- node = ares__llist_node_next(node)) { ++ ++ /* Nothing in this bucket */ ++ if (htable->buckets[i] == NULL) ++ continue; ++ ++ /* Fast past optimization (most likely case), there is likely only a single ++ * entry in both the source and destination, check for this to confirm and ++ * if so, just move the bucket over */ ++ if (ares__llist_len(htable->buckets[i]) == 1) { ++ void *val = ares__llist_first_val(htable->buckets[i]); ++ size_t idx = HASH_IDX(htable, htable->bucket_key(val)); ++ ++ if (buckets[idx] == NULL) { ++ /* Swap! */ ++ buckets[idx] = htable->buckets[i]; ++ htable->buckets[i] = NULL; ++ continue; ++ } ++ } ++ ++ /* Slow path, collisions */ ++ while ((node = ares__llist_node_first(htable->buckets[i])) != NULL) { + void *val = ares__llist_node_val(node); + size_t idx = HASH_IDX(htable, htable->bucket_key(val)); + ++ /* Try fast path again as maybe we popped one collision off and the ++ * next we can reuse the llist parent */ ++ if (buckets[idx] == NULL && ares__llist_len(htable->buckets[i]) == 1) { ++ /* Swap! */ ++ buckets[idx] = htable->buckets[i]; ++ htable->buckets[i] = NULL; ++ break; ++ } ++ + if (buckets[idx] == NULL) { + buckets[idx] = ares__llist_create(htable->bucket_free); + } +@@ -192,19 +221,17 @@ static ares_bool_t ares__htable_expand(ares__htable_t *htable) + goto fail; + } + +- if (ares__llist_insert_first(buckets[idx], val) == NULL) { +- goto fail; +- } ++ ares__llist_node_move_parent_first(node, buckets[idx]); + } + } + + /* Swap out buckets */ +- ares__htable_buckets_destroy(htable->buckets, old_size, 0); ++ ares__htable_buckets_destroy(htable->buckets, old_size, ARES_FALSE); + htable->buckets = buckets; + return ARES_TRUE; + + fail: +- ares__htable_buckets_destroy(buckets, htable->size, 0); ++ ares__htable_buckets_destroy(buckets, htable->size, ARES_FALSE); + htable->size = old_size; + + return ARES_FALSE; +--- a/src/lib/ares__llist.c ++++ b/src/lib/ares__llist.c +@@ -71,24 +71,14 @@ typedef enum { + ARES__LLIST_INSERT_BEFORE + } ares__llist_insert_type_t; + +-static ares__llist_node_t *ares__llist_insert_at(ares__llist_t *list, +- ares__llist_insert_type_t type, +- ares__llist_node_t *at, +- void *val) ++static void ares__llist_attach_at(ares__llist_t *list, ++ ares__llist_insert_type_t type, ++ ares__llist_node_t *at, ++ ares__llist_node_t *node) + { +- ares__llist_node_t *node = NULL; +- +- if (list == NULL || val == NULL) { +- return NULL; +- } +- +- node = ares_malloc_zero(sizeof(*node)); +- +- if (node == NULL) { +- return NULL; +- } ++ if (list == NULL || node == NULL) ++ return; + +- node->data = val; + node->parent = list; + + if (type == ARES__LLIST_INSERT_BEFORE && (at == list->head || at == NULL)) { +@@ -126,6 +116,27 @@ static ares__llist_node_t *ares__llist_insert_at(ares__llist_t *list, + } + + list->cnt++; ++} ++ ++static ares__llist_node_t *ares__llist_insert_at(ares__llist_t *list, ++ ares__llist_insert_type_t type, ++ ares__llist_node_t *at, ++ void *val) ++{ ++ ares__llist_node_t *node = NULL; ++ ++ if (list == NULL || val == NULL) { ++ return NULL; ++ } ++ ++ node = ares_malloc_zero(sizeof(*node)); ++ ++ if (node == NULL) { ++ return NULL; ++ } ++ ++ node->data = val; ++ ares__llist_attach_at(list, type, at, node); + + return node; + } +@@ -233,17 +244,14 @@ void *ares__llist_last_val(ares__llist_t *list) + return ares__llist_node_val(ares__llist_node_last(list)); + } + +-void *ares__llist_node_claim(ares__llist_node_t *node) ++static void ares__llist_node_detach(ares__llist_node_t *node) + { +- void *val; + ares__llist_t *list; + +- if (node == NULL) { +- return NULL; +- } ++ if (node == NULL) ++ return; + + list = node->parent; +- val = node->data; + + if (node->prev) { + node->prev->next = node->next; +@@ -260,9 +268,22 @@ void *ares__llist_node_claim(ares__llist_node_t *node) + if (node == list->tail) { + list->tail = node->prev; + } +- ares_free(node); + ++ node->parent = NULL; + list->cnt--; ++} ++ ++void *ares__llist_node_claim(ares__llist_node_t *node) ++{ ++ void *val; ++ ++ if (node == NULL) { ++ return NULL; ++ } ++ ++ val = node->data; ++ ares__llist_node_detach(node); ++ ares_free(node); + + return val; + } +@@ -313,3 +334,23 @@ void ares__llist_destroy(ares__llist_t *list) + } + ares_free(list); + } ++ ++void ares__llist_node_move_parent_last(ares__llist_node_t *node, ++ ares__llist_t *new_parent) ++{ ++ if (node == NULL || new_parent == NULL) ++ return; ++ ++ ares__llist_node_detach(node); ++ ares__llist_attach_at(new_parent, ARES__LLIST_INSERT_TAIL, NULL, node); ++} ++ ++void ares__llist_node_move_parent_first(ares__llist_node_t *node, ++ ares__llist_t *new_parent) ++{ ++ if (node == NULL || new_parent == NULL) ++ return; ++ ++ ares__llist_node_detach(node); ++ ares__llist_attach_at(new_parent, ARES__LLIST_INSERT_HEAD, NULL, node); ++} +--- a/src/lib/ares__llist.h ++++ b/src/lib/ares__llist.h +@@ -198,6 +198,23 @@ void ares__llist_node_destroy(ares__llist_node_t *node); + */ + void ares__llist_destroy(ares__llist_t *list); + ++/*! Detach node from the current list and re-attach it to the new list as the ++ * last entry. ++ * ++ * \param[in] node node to move ++ * \param[in] parent new list ++ */ ++void ares__llist_node_move_parent_last(ares__llist_node_t *node, ++ ares__llist_t *new_parent); ++ ++/*! Detach node from the current list and re-attach it to the new list as the ++ * first entry. ++ * ++ * \param[in] node node to move ++ * \param[in] parent new list ++ */ ++void ares__llist_node_move_parent_first(ares__llist_node_t *node, ++ ares__llist_t *new_parent); + /*! @} */ + + #endif /* __ARES__LLIST_H */ + diff --git a/net-dns/c-ares/files/c-ares-1.22.0-hosts-lookup.patch b/net-dns/c-ares/files/c-ares-1.22.0-hosts-lookup.patch new file mode 100644 index 000000000000..c0e76ca7e83c --- /dev/null +++ b/net-dns/c-ares/files/c-ares-1.22.0-hosts-lookup.patch @@ -0,0 +1,109 @@ +https://github.com/c-ares/c-ares/commit/a3631763ca30804c3095d99474e05625f0c9b0fa + +From a3631763ca30804c3095d99474e05625f0c9b0fa Mon Sep 17 00:00:00 2001 +From: Brad House <brad@brad-house.com> +Date: Thu, 16 Nov 2023 12:19:39 -0500 +Subject: [PATCH] Fix /etc/hosts processing performance with all entries using + same IP address + +Some users use blacklist files like https://github.com/StevenBlack/hosts which +can contain 200k+ host entries all pointing to 0.0.0.0. Due to the merge +logic in the new hosts processor, all those entries will be associated as +aliases for the same ip address. + +The first issue is that it attempts to check the status of all the hosts for +the merged entry, when it should only be checking the new hosts added to the +merged entry, so this caused exponential time as the entries got longer. + +The next issue is if searching for one of those hosts, it would append all +the matches as cnames/aliases, but there is zero use for 200k aliases +being appended to a lookup, so we are artificially capping this to 100. + +Bug report reference: https://bugs.gentoo.org/917400 + +Fix By: Brad House (@bradh352) +--- a/src/lib/ares__hosts_file.c ++++ b/src/lib/ares__hosts_file.c +@@ -422,9 +422,15 @@ static ares_status_t ares__hosts_file_add(ares_hosts_file_t *hosts, + ares_hosts_entry_t *entry) + { + ares_hosts_entry_t *match = NULL; +- ares_status_t status = ARES_SUCCESS; ++ ares_status_t status = ARES_SUCCESS; + ares__llist_node_t *node; + ares_hosts_file_match_t matchtype; ++ size_t num_hostnames; ++ ++ /* Record the number of hostnames in this entry file. If we merge into an ++ * existing record, these will be *appended* to the entry, so we'll count ++ * backwards when adding to the hosts hashtable */ ++ num_hostnames = ares__llist_len(entry->hosts); + + matchtype = ares__hosts_file_match(hosts, entry, &match); + +@@ -450,10 +456,17 @@ static ares_status_t ares__hosts_file_add(ares_hosts_file_t *hosts, + } + } + +- for (node = ares__llist_node_first(entry->hosts); node != NULL; +- node = ares__llist_node_next(node)) { ++ /* Go backwards, on a merge, hostnames are appended. Breakout once we've ++ * consumed all the hosts that we appended */ ++ for (node = ares__llist_node_last(entry->hosts); node != NULL; ++ node = ares__llist_node_prev(node)) { + const char *val = ares__llist_node_val(node); + ++ if (num_hostnames == 0) ++ break; ++ ++ num_hostnames--; ++ + /* first hostname match wins. If we detect a duplicate hostname for another + * ip it will automatically be added to the same entry */ + if (ares__htable_strvp_get(hosts->hosthash, val, NULL)) { +@@ -950,6 +963,12 @@ ares_status_t ares__hosts_entry_to_hostent(const ares_hosts_entry_t *entry, + + /* Copy aliases */ + naliases = ares__llist_len(entry->hosts) - 1; ++ ++ /* Cap at 100, some people use https://github.com/StevenBlack/hosts and we ++ * don't need 200k+ aliases */ ++ if (naliases > 100) ++ naliases = 100; ++ + (*hostent)->h_aliases = + ares_malloc_zero((naliases + 1) * sizeof(*(*hostent)->h_aliases)); + if ((*hostent)->h_aliases == NULL) { +@@ -968,6 +987,10 @@ ares_status_t ares__hosts_entry_to_hostent(const ares_hosts_entry_t *entry, + goto fail; + } + idx++; ++ ++ /* Break out if artificially capped */ ++ if (idx == naliases) ++ break; + node = ares__llist_node_next(node); + } + +@@ -988,6 +1011,7 @@ static ares_status_t + const char *primaryhost; + ares__llist_node_t *node; + ares_status_t status; ++ size_t cnt = 0; + + node = ares__llist_node_first(entry->hosts); + primaryhost = ares__llist_node_val(node); +@@ -997,6 +1021,12 @@ static ares_status_t + while (node != NULL) { + const char *host = ares__llist_node_val(node); + ++ /* Cap at 100 entries. , some people use https://github.com/StevenBlack/hosts ++ * and we don't need 200k+ aliases */ ++ cnt++; ++ if (cnt > 100) ++ break; ++ + cname = ares__append_addrinfo_cname(&cnames); + if (cname == NULL) { + status = ARES_ENOMEM; + |