You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
7.1 KiB
248 lines
7.1 KiB
commit b195fd86c616b147dad3a63498b79e0dedb4662b |
|
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
|
Date: Mon Mar 7 22:17:36 2022 +0530 |
|
|
|
gaih_inet: Simplify canon name resolution |
|
|
|
Simplify logic for allocation of canon to remove the canonbuf variable; |
|
canon now always points to an allocated block. Also pull the canon name |
|
set into a separate function. |
|
|
|
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
|
Reviewed-by: DJ Delorie <dj@redhat.com> |
|
(cherry picked from commit d01411f6bc61429fc027c38827bf3103b48eef2e) |
|
|
|
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c |
|
index 702d8a50e0c218d2..5c0d873e1d766099 100644 |
|
--- a/sysdeps/posix/getaddrinfo.c |
|
+++ b/sysdeps/posix/getaddrinfo.c |
|
@@ -285,7 +285,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, |
|
\ |
|
if (localcanon != NULL && canon == NULL) \ |
|
{ \ |
|
- canonbuf = __strdup (localcanon); \ |
|
+ char *canonbuf = __strdup (localcanon); \ |
|
if (canonbuf == NULL) \ |
|
{ \ |
|
__resolv_context_put (res_ctx); \ |
|
@@ -323,6 +323,41 @@ getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name) |
|
return __strdup (name); |
|
} |
|
|
|
+/* Process looked up canonical name and if necessary, decode to IDNA. Result |
|
+ is a new string written to CANONP and the earlier string is freed. */ |
|
+ |
|
+static int |
|
+process_canonname (const struct addrinfo *req, const char *orig_name, |
|
+ char **canonp) |
|
+{ |
|
+ char *canon = *canonp; |
|
+ |
|
+ if ((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 ?: orig_name, &out); |
|
+ if (rc == 0) |
|
+ { |
|
+ free (canon); |
|
+ canon = out; |
|
+ } |
|
+ else if (rc == EAI_IDN_ENCODE) |
|
+ /* Use the punycode name as a fallback. */ |
|
+ do_idn = false; |
|
+ else |
|
+ return -rc; |
|
+ } |
|
+ if (!do_idn && canon == NULL && (canon = __strdup (orig_name)) == NULL) |
|
+ return -EAI_MEMORY; |
|
+ } |
|
+ |
|
+ *canonp = canon; |
|
+ return 0; |
|
+} |
|
+ |
|
static int |
|
gaih_inet (const char *name, const struct gaih_service *service, |
|
const struct addrinfo *req, struct addrinfo **pai, |
|
@@ -332,7 +367,7 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv; |
|
struct gaih_addrtuple *at = NULL; |
|
bool got_ipv6 = false; |
|
- const char *canon = NULL; |
|
+ char *canon = NULL; |
|
const char *orig_name = name; |
|
|
|
/* Reserve stack memory for the scratch buffer in the getaddrinfo |
|
@@ -453,7 +488,6 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
|
|
bool malloc_name = false; |
|
struct gaih_addrtuple *addrmem = NULL; |
|
- char *canonbuf = NULL; |
|
int result = 0; |
|
|
|
if (name != NULL) |
|
@@ -495,7 +529,15 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
} |
|
|
|
if (req->ai_flags & AI_CANONNAME) |
|
- canon = name; |
|
+ { |
|
+ char *canonbuf = __strdup (name); |
|
+ if (canonbuf == NULL) |
|
+ { |
|
+ result = -EAI_MEMORY; |
|
+ goto free_and_return; |
|
+ } |
|
+ canon = canonbuf; |
|
+ } |
|
|
|
goto process_list; |
|
} |
|
@@ -545,7 +587,15 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
} |
|
|
|
if (req->ai_flags & AI_CANONNAME) |
|
- canon = name; |
|
+ { |
|
+ char *canonbuf = __strdup (name); |
|
+ if (canonbuf == NULL) |
|
+ { |
|
+ result = -EAI_MEMORY; |
|
+ goto free_and_return; |
|
+ } |
|
+ canon = canonbuf; |
|
+ } |
|
|
|
goto process_list; |
|
} |
|
@@ -676,9 +726,9 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
(*pat)->next = NULL; |
|
if (added_canon || air->canon == NULL) |
|
(*pat)->name = NULL; |
|
- else if (canonbuf == NULL) |
|
+ else if (canon == NULL) |
|
{ |
|
- canonbuf = __strdup (air->canon); |
|
+ char *canonbuf = __strdup (air->canon); |
|
if (canonbuf == NULL) |
|
{ |
|
result = -EAI_MEMORY; |
|
@@ -748,9 +798,9 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
/* Always start afresh; continue should discard previous results |
|
and the hosts database does not support merge. */ |
|
at = NULL; |
|
- free (canonbuf); |
|
+ free (canon); |
|
free (addrmem); |
|
- canon = canonbuf = NULL; |
|
+ canon = NULL; |
|
addrmem = NULL; |
|
got_ipv6 = false; |
|
|
|
@@ -805,7 +855,16 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
no_data = 1; |
|
|
|
if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL) |
|
- canon = at->name; |
|
+ { |
|
+ char *canonbuf = __strdup (at->name); |
|
+ if (canonbuf == NULL) |
|
+ { |
|
+ __resolv_context_put (res_ctx); |
|
+ result = -EAI_MEMORY; |
|
+ goto free_and_return; |
|
+ } |
|
+ canon = canonbuf; |
|
+ } |
|
|
|
struct gaih_addrtuple **pat = &at; |
|
|
|
@@ -893,7 +952,7 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
if ((req->ai_flags & AI_CANONNAME) != 0 |
|
&& canon == NULL) |
|
{ |
|
- canonbuf = getcanonname (nip, at, name); |
|
+ char *canonbuf = getcanonname (nip, at, name); |
|
if (canonbuf == NULL) |
|
{ |
|
__resolv_context_put (res_ctx); |
|
@@ -1004,6 +1063,10 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
} |
|
|
|
{ |
|
+ /* Set up the canonical name if we need it. */ |
|
+ if ((result = process_canonname (req, orig_name, &canon)) != 0) |
|
+ goto free_and_return; |
|
+ |
|
struct gaih_servtuple *st2; |
|
struct gaih_addrtuple *at2 = at; |
|
size_t socklen; |
|
@@ -1014,48 +1077,6 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
*/ |
|
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) |
|
{ |
|
@@ -1078,7 +1099,6 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
ai = *pai = malloc (sizeof (struct addrinfo) + socklen); |
|
if (ai == NULL) |
|
{ |
|
- free ((char *) canon); |
|
result = -EAI_MEMORY; |
|
goto free_and_return; |
|
} |
|
@@ -1138,7 +1158,7 @@ gaih_inet (const char *name, const struct gaih_service *service, |
|
if (malloc_name) |
|
free ((char *) name); |
|
free (addrmem); |
|
- free (canonbuf); |
|
+ free (canon); |
|
|
|
return result; |
|
}
|
|
|