From: Siddhesh Poyarekar via Libc-alpha <libc-alpha@sourceware.org>
To: libc-alpha@sourceware.org
Subject: [PATCH 5/5] gaih_inet: Make process_list label into a function
Date: Wed, 4 Aug 2021 02:59:19 +0530 [thread overview]
Message-ID: <20210803212919.3059194-6-siddhesh@sourceware.org> (raw)
In-Reply-To: <20210803212919.3059194-1-siddhesh@sourceware.org>
process_list is the final operation in gaih_inet where the result is
written out. Factor it out into a separate function and call it at
the end if there have been no errors. Rename the free_and_return
label to done and use it to jump to the end of gaih_inet, where
process_list is called if return is non-zero.
This change makes the code more linear and slightly clearer to follow.
This needs still more rework to make the function simpler to
understand.
---
sysdeps/posix/getaddrinfo.c | 311 +++++++++++++++++-------------------
1 file changed, 149 insertions(+), 162 deletions(-)
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 220cd41cde..3afac87fa2 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -256,7 +256,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
{ \
__resolv_context_put (res_ctx); \
result = -EAI_MEMORY; \
- goto free_and_return; \
+ goto done; \
} \
} \
if (status == NSS_STATUS_NOTFOUND \
@@ -266,7 +266,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
{ \
__resolv_context_put (res_ctx); \
result = -EAI_SYSTEM; \
- goto free_and_return; \
+ goto done; \
} \
if (h_errno == TRY_AGAIN) \
no_data = EAI_AGAIN; \
@@ -279,7 +279,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
{ \
__resolv_context_put (res_ctx); \
result = -EAI_SYSTEM; \
- goto free_and_return; \
+ goto done; \
} \
*pat = addrmem; \
\
@@ -290,7 +290,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
{ \
__resolv_context_put (res_ctx); \
result = -EAI_SYSTEM; \
- goto free_and_return; \
+ goto done; \
} \
canon = canonbuf; \
} \
@@ -323,6 +323,123 @@ getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name)
return __strdup (name);
}
+static int
+process_list (const struct addrinfo *req, struct gaih_addrtuple *at,
+ struct gaih_servtuple *st, const char *canon, bool canon_alloc,
+ bool got_ipv6, struct addrinfo **pai, unsigned int *naddrs)
+{
+ struct gaih_servtuple *st2;
+ struct gaih_addrtuple *at2 = at;
+ size_t socklen;
+ sa_family_t family;
+
+ /*
+ buffer is the size of an unformatted IPv6 address in printable format.
+ */
+ for (at2 = at; at2 != NULL; at2 = at2->next)
+ {
+ /* Only the first entry gets the canonical name. */
+ if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
+ {
+ bool do_idn = req->ai_flags & AI_CANONIDN;
+ if (do_idn)
+ {
+ char *out;
+ int rc = __idna_from_dns_encoding (canon, &out);
+ if (rc == 0)
+ canon = out;
+ else if (rc == EAI_IDN_ENCODE)
+ /* Use the punycode name as a fallback. */
+ do_idn = false;
+ else
+ return -rc;
+ }
+ if (!do_idn)
+ {
+ if (!canon_alloc)
+ {
+ canon = __strdup (canon);
+ if (canon == NULL)
+ return -EAI_MEMORY;
+ }
+ }
+ }
+
+ family = at2->family;
+ if (family == AF_INET6)
+ {
+ socklen = sizeof (struct sockaddr_in6);
+
+ /* If we looked up IPv4 mapped address discard them here if
+ the caller isn't interested in all address and we have
+ found at least one IPv6 address. */
+ if (got_ipv6
+ && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
+ && IN6_IS_ADDR_V4MAPPED (at2->addr))
+ continue;
+ }
+ else
+ socklen = sizeof (struct sockaddr_in);
+
+ for (st2 = st; st2 != NULL; st2 = st2->next)
+ {
+ struct addrinfo *ai;
+ ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
+ if (ai == NULL)
+ {
+ free ((char *) canon);
+ return -EAI_MEMORY;
+ }
+
+ ai->ai_flags = req->ai_flags;
+ ai->ai_family = family;
+ ai->ai_socktype = st2->socktype;
+ ai->ai_protocol = st2->protocol;
+ ai->ai_addrlen = socklen;
+ ai->ai_addr = (void *) (ai + 1);
+
+ /* We only add the canonical name once. */
+ ai->ai_canonname = (char *) canon;
+ canon = NULL;
+
+#ifdef _HAVE_SA_LEN
+ ai->ai_addr->sa_len = socklen;
+#endif /* _HAVE_SA_LEN */
+ ai->ai_addr->sa_family = family;
+
+ /* In case of an allocation error the list must be NULL
+ terminated. */
+ ai->ai_next = NULL;
+
+ if (family == AF_INET6)
+ {
+ struct sockaddr_in6 *sin6p =
+ (struct sockaddr_in6 *) ai->ai_addr;
+
+ sin6p->sin6_port = st2->port;
+ sin6p->sin6_flowinfo = 0;
+ memcpy (&sin6p->sin6_addr,
+ at2->addr, sizeof (struct in6_addr));
+ sin6p->sin6_scope_id = at2->scopeid;
+ }
+ else
+ {
+ struct sockaddr_in *sinp =
+ (struct sockaddr_in *) ai->ai_addr;
+ sinp->sin_port = st2->port;
+ memcpy (&sinp->sin_addr,
+ at2->addr, sizeof (struct in_addr));
+ memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
+ }
+
+ pai = &(ai->ai_next);
+ }
+
+ ++*naddrs;
+ }
+ return 0;
+}
+
static int
gaih_inet (const char *name, const struct gaih_service *service,
const struct addrinfo *req, struct addrinfo **pai,
@@ -479,7 +596,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
else
{
result = -EAI_ADDRFAMILY;
- goto free_and_return;
+ goto done;
}
if (req->ai_flags & AI_CANONNAME)
@@ -507,7 +624,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
else
{
result = -EAI_ADDRFAMILY;
- goto free_and_return;
+ goto done;
}
if (scope_delim != NULL
@@ -516,7 +633,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
&at->scopeid) != 0)
{
result = -EAI_NONAME;
- goto free_and_return;
+ goto done;
}
if (req->ai_flags & AI_CANONNAME)
@@ -555,7 +672,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (!scratch_buffer_grow (tmpbuf))
{
result = -EAI_MEMORY;
- goto free_and_return;
+ goto done;
}
}
@@ -568,7 +685,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
(req, AF_INET, h, &addrmem))
{
result = -EAI_MEMORY;
- goto free_and_return;
+ goto done;
}
*pat = addrmem;
}
@@ -578,7 +695,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
result = -EAI_NODATA;
else
result = -EAI_NONAME;
- goto free_and_return;
+ goto done;
}
}
else
@@ -592,10 +709,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
The name is known, though. */
result = -EAI_NODATA;
- goto free_and_return;
+ goto done;
}
- goto process_list;
+ if (at->family == AF_UNSPEC)
+ result = -EAI_NONAME;
+
+ goto done;
}
#ifdef USE_NSCD
@@ -619,7 +739,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (addrmem == NULL)
{
result = -EAI_MEMORY;
- goto free_and_return;
+ goto done;
}
struct gaih_addrtuple *addrfree = addrmem;
@@ -654,7 +774,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (canonbuf == NULL)
{
result = -EAI_MEMORY;
- goto free_and_return;
+ goto done;
}
canon = (*pat)->name = canonbuf;
}
@@ -687,16 +807,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
free (air);
if (at->family == AF_UNSPEC)
- {
- result = -EAI_NONAME;
- goto free_and_return;
- }
+ result = -EAI_NONAME;
- goto process_list;
+ goto done;
}
else if (err == 0)
/* The database contains a negative entry. */
- goto free_and_return;
+ goto done;
else if (__nss_not_use_nscd_hosts == 0)
{
if (h_errno == NETDB_INTERNAL && errno == ENOMEM)
@@ -706,7 +823,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
else
result = -EAI_SYSTEM;
- goto free_and_return;
+ goto done;
}
}
#endif
@@ -755,7 +872,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
{
__resolv_context_put (res_ctx);
result = -EAI_MEMORY;
- goto free_and_return;
+ goto done;
}
}
@@ -854,7 +971,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
{
__resolv_context_put (res_ctx);
result = -EAI_MEMORY;
- goto free_and_return;
+ goto done;
}
canon = canonbuf;
}
@@ -903,7 +1020,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
&& h_errno == NETDB_INTERNAL)
{
result = -EAI_SYSTEM;
- goto free_and_return;
+ goto done;
}
if (no_data != 0 && no_inet6_data != 0)
@@ -916,16 +1033,12 @@ gaih_inet (const char *name, const struct gaih_service *service,
is known, though. */
result = -EAI_NODATA;
- goto free_and_return;
+ goto done;
}
}
- process_list:
if (at->family == AF_UNSPEC)
- {
- result = -EAI_NONAME;
- goto free_and_return;
- }
+ result = -EAI_NONAME;
}
else
{
@@ -955,142 +1068,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
}
}
- {
- struct gaih_servtuple *st2;
- struct gaih_addrtuple *at2 = at;
- size_t socklen;
- sa_family_t family;
-
- /*
- buffer is the size of an unformatted IPv6 address in printable format.
- */
- while (at2 != NULL)
- {
- /* Only the first entry gets the canonical name. */
- if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
- {
- if (canon == NULL)
- /* If the canonical name cannot be determined, use
- the passed in string. */
- canon = orig_name;
-
- bool do_idn = req->ai_flags & AI_CANONIDN;
- if (do_idn)
- {
- char *out;
- int rc = __idna_from_dns_encoding (canon, &out);
- if (rc == 0)
- canon = out;
- else if (rc == EAI_IDN_ENCODE)
- /* Use the punycode name as a fallback. */
- do_idn = false;
- else
- {
- result = -rc;
- goto free_and_return;
- }
- }
- if (!do_idn)
- {
- if (canonbuf != NULL)
- /* We already allocated the string using malloc, but
- the buffer is now owned by canon. */
- canonbuf = NULL;
- else
- {
- canon = __strdup (canon);
- if (canon == NULL)
- {
- result = -EAI_MEMORY;
- goto free_and_return;
- }
- }
- }
- }
-
- family = at2->family;
- if (family == AF_INET6)
- {
- socklen = sizeof (struct sockaddr_in6);
-
- /* If we looked up IPv4 mapped address discard them here if
- the caller isn't interested in all address and we have
- found at least one IPv6 address. */
- if (got_ipv6
- && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
- && IN6_IS_ADDR_V4MAPPED (at2->addr))
- goto ignore;
- }
- else
- socklen = sizeof (struct sockaddr_in);
-
- for (st2 = st; st2 != NULL; st2 = st2->next)
- {
- struct addrinfo *ai;
- ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
- if (ai == NULL)
- {
- free ((char *) canon);
- result = -EAI_MEMORY;
- goto free_and_return;
- }
-
- ai->ai_flags = req->ai_flags;
- ai->ai_family = family;
- ai->ai_socktype = st2->socktype;
- ai->ai_protocol = st2->protocol;
- ai->ai_addrlen = socklen;
- ai->ai_addr = (void *) (ai + 1);
-
- /* We only add the canonical name once. */
- ai->ai_canonname = (char *) canon;
- canon = NULL;
-
-#ifdef _HAVE_SA_LEN
- ai->ai_addr->sa_len = socklen;
-#endif /* _HAVE_SA_LEN */
- ai->ai_addr->sa_family = family;
-
- /* In case of an allocation error the list must be NULL
- terminated. */
- ai->ai_next = NULL;
-
- if (family == AF_INET6)
- {
- struct sockaddr_in6 *sin6p =
- (struct sockaddr_in6 *) ai->ai_addr;
-
- sin6p->sin6_port = st2->port;
- sin6p->sin6_flowinfo = 0;
- memcpy (&sin6p->sin6_addr,
- at2->addr, sizeof (struct in6_addr));
- sin6p->sin6_scope_id = at2->scopeid;
- }
- else
- {
- struct sockaddr_in *sinp =
- (struct sockaddr_in *) ai->ai_addr;
- sinp->sin_port = st2->port;
- memcpy (&sinp->sin_addr,
- at2->addr, sizeof (struct in_addr));
- memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
- }
-
- pai = &(ai->ai_next);
- }
-
- ++*naddrs;
-
- ignore:
- at2 = at2->next;
- }
- }
+done:
+ if (result == 0)
+ result = process_list (req, at, st, canon ?: orig_name, canonbuf != NULL,
+ got_ipv6, pai, naddrs);
- free_and_return:
if (malloc_name)
free ((char *) name);
free (addrmem);
- free (canonbuf);
+ if (result != 0)
+ free (canonbuf);
return result;
}
--
2.31.1
prev parent reply other threads:[~2021-08-03 21:33 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-03 21:29 [PATCH 0/5] getaddrinfo spaghetti cleanups Siddhesh Poyarekar via Libc-alpha
2021-08-03 21:29 ` [PATCH 1/5] gaiconf_init: Refactor some bits for readability Siddhesh Poyarekar via Libc-alpha
2021-08-03 21:29 ` [PATCH 2/5] gai_init: Avoid jumping from if condition to its else counterpart Siddhesh Poyarekar via Libc-alpha
2021-08-03 21:29 ` [PATCH 3/5] getaddrinfo: Refactor code for readability Siddhesh Poyarekar via Libc-alpha
2021-08-03 21:29 ` [PATCH 4/5] gaih_inet: Consolidate got_port code Siddhesh Poyarekar via Libc-alpha
2021-08-03 21:29 ` Siddhesh Poyarekar via Libc-alpha [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/libc/involved.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210803212919.3059194-6-siddhesh@sourceware.org \
--to=libc-alpha@sourceware.org \
--cc=siddhesh@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).