diff options
author | Alexander Smirnov <alex@ydb.tech> | 2024-10-19 17:59:18 +0000 |
---|---|---|
committer | Alexander Smirnov <alex@ydb.tech> | 2024-10-19 17:59:18 +0000 |
commit | ceddbfe68f6ec7949a4062716c8f9840a59c6888 (patch) | |
tree | abfecadbb9c1e5aea40701dd20d902cb7bccd962 /contrib/libs/c-ares/src/lib/ares_addrinfo2hostent.c | |
parent | 07f2e60d02d95eab14a86a4b9469db1af7795001 (diff) | |
parent | d920c750e476fa2dc80c45f990d9456b1afeadd1 (diff) | |
download | ydb-ceddbfe68f6ec7949a4062716c8f9840a59c6888.tar.gz |
Merge branch 'rightlib' into mergelibs-241019-1758
Diffstat (limited to 'contrib/libs/c-ares/src/lib/ares_addrinfo2hostent.c')
-rw-r--r-- | contrib/libs/c-ares/src/lib/ares_addrinfo2hostent.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/contrib/libs/c-ares/src/lib/ares_addrinfo2hostent.c b/contrib/libs/c-ares/src/lib/ares_addrinfo2hostent.c new file mode 100644 index 0000000000..2bbc791157 --- /dev/null +++ b/contrib/libs/c-ares/src/lib/ares_addrinfo2hostent.c @@ -0,0 +1,274 @@ +/* MIT License + * + * Copyright (c) 1998 Massachusetts Institute of Technology + * Copyright (c) 2005 Dominick Meglio + * Copyright (c) 2019 Andrew Selivanov + * Copyright (c) 2021 Brad House + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * SPDX-License-Identifier: MIT + */ + +#include "ares_private.h" + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +# include <arpa/inet.h> +#endif + +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + + +ares_status_t ares_addrinfo2hostent(const struct ares_addrinfo *ai, int family, + struct hostent **host) +{ + struct ares_addrinfo_node *next; + struct ares_addrinfo_cname *next_cname; + char **aliases = NULL; + char *addrs = NULL; + size_t naliases = 0; + size_t naddrs = 0; + size_t alias = 0; + size_t i; + + if (ai == NULL || host == NULL) { + return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */ + } + + /* Use the first node of the response as the family, since hostent can only + * represent one family. We assume getaddrinfo() returned a sorted list if + * the user requested AF_UNSPEC. */ + if (family == AF_UNSPEC && ai->nodes) { + family = ai->nodes->ai_family; + } + + if (family != AF_INET && family != AF_INET6) { + return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */ + } + + *host = ares_malloc(sizeof(**host)); + if (!(*host)) { + goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */ + } + memset(*host, 0, sizeof(**host)); + + next = ai->nodes; + while (next) { + if (next->ai_family == family) { + ++naddrs; + } + next = next->ai_next; + } + + next_cname = ai->cnames; + while (next_cname) { + if (next_cname->alias) { + ++naliases; + } + next_cname = next_cname->next; + } + + aliases = ares_malloc((naliases + 1) * sizeof(char *)); + if (!aliases) { + goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */ + } + (*host)->h_aliases = aliases; + memset(aliases, 0, (naliases + 1) * sizeof(char *)); + + if (naliases) { + for (next_cname = ai->cnames; next_cname != NULL; + next_cname = next_cname->next) { + if (next_cname->alias == NULL) { + continue; + } + aliases[alias] = ares_strdup(next_cname->alias); + if (!aliases[alias]) { + goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */ + } + alias++; + } + } + + + (*host)->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *)); + if (!(*host)->h_addr_list) { + goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */ + } + + memset((*host)->h_addr_list, 0, (naddrs + 1) * sizeof(char *)); + + if (ai->cnames) { + (*host)->h_name = ares_strdup(ai->cnames->name); + if ((*host)->h_name == NULL && ai->cnames->name) { + goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */ + } + } else { + (*host)->h_name = ares_strdup(ai->name); + if ((*host)->h_name == NULL && ai->name) { + goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */ + } + } + + (*host)->h_addrtype = (HOSTENT_ADDRTYPE_TYPE)family; + + if (family == AF_INET) { + (*host)->h_length = sizeof(struct in_addr); + } + + if (family == AF_INET6) { + (*host)->h_length = sizeof(struct ares_in6_addr); + } + + if (naddrs) { + addrs = ares_malloc(naddrs * (size_t)(*host)->h_length); + if (!addrs) { + goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */ + } + + i = 0; + for (next = ai->nodes; next != NULL; next = next->ai_next) { + if (next->ai_family != family) { + continue; + } + (*host)->h_addr_list[i] = addrs + (i * (size_t)(*host)->h_length); + if (family == AF_INET6) { + memcpy((*host)->h_addr_list[i], + &(CARES_INADDR_CAST(const struct sockaddr_in6 *, next->ai_addr) + ->sin6_addr), + (size_t)(*host)->h_length); + } + if (family == AF_INET) { + memcpy((*host)->h_addr_list[i], + &(CARES_INADDR_CAST(const struct sockaddr_in *, next->ai_addr) + ->sin_addr), + (size_t)(*host)->h_length); + } + ++i; + } + + if (i == 0) { + ares_free(addrs); + } + } + + if (naddrs == 0 && naliases == 0) { + ares_free_hostent(*host); + *host = NULL; + return ARES_ENODATA; + } + + return ARES_SUCCESS; + +/* LCOV_EXCL_START: OutOfMemory */ +enomem: + ares_free_hostent(*host); + *host = NULL; + return ARES_ENOMEM; + /* LCOV_EXCL_STOP */ +} + +ares_status_t ares_addrinfo2addrttl(const struct ares_addrinfo *ai, int family, + size_t req_naddrttls, + struct ares_addrttl *addrttls, + struct ares_addr6ttl *addr6ttls, + size_t *naddrttls) +{ + struct ares_addrinfo_node *next; + struct ares_addrinfo_cname *next_cname; + int cname_ttl = INT_MAX; + + if (family != AF_INET && family != AF_INET6) { + return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */ + } + + if (ai == NULL || naddrttls == NULL) { + return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */ + } + + if (family == AF_INET && addrttls == NULL) { + return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */ + } + + if (family == AF_INET6 && addr6ttls == NULL) { + return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */ + } + + if (req_naddrttls == 0) { + return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */ + } + + *naddrttls = 0; + + next_cname = ai->cnames; + while (next_cname) { + if (next_cname->ttl < cname_ttl) { + cname_ttl = next_cname->ttl; + } + next_cname = next_cname->next; + } + + for (next = ai->nodes; next != NULL; next = next->ai_next) { + if (next->ai_family != family) { + continue; + } + + if (*naddrttls >= req_naddrttls) { + break; + } + + if (family == AF_INET6) { + if (next->ai_ttl > cname_ttl) { + addr6ttls[*naddrttls].ttl = cname_ttl; + } else { + addr6ttls[*naddrttls].ttl = next->ai_ttl; + } + + memcpy(&addr6ttls[*naddrttls].ip6addr, + &(CARES_INADDR_CAST(const struct sockaddr_in6 *, next->ai_addr) + ->sin6_addr), + sizeof(struct ares_in6_addr)); + } else { + if (next->ai_ttl > cname_ttl) { + addrttls[*naddrttls].ttl = cname_ttl; + } else { + addrttls[*naddrttls].ttl = next->ai_ttl; + } + memcpy(&addrttls[*naddrttls].ipaddr, + &(CARES_INADDR_CAST(const struct sockaddr_in *, next->ai_addr) + ->sin_addr), + sizeof(struct in_addr)); + } + (*naddrttls)++; + } + + return ARES_SUCCESS; +} |