mirror of git://sourceware.org/git/glibc.git
gaih_inet: Split simple gethostbyname into its own function
Add a free_at flag in gaih_result to indicate if res.at needs to be freed by the caller. Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> Reviewed-by: DJ Delorie <dj@redhat.com>
This commit is contained in:
parent
26dea46119
commit
b44389cb7f
|
@ -120,6 +120,7 @@ struct gaih_result
|
||||||
{
|
{
|
||||||
struct gaih_addrtuple *at;
|
struct gaih_addrtuple *at;
|
||||||
char *canon;
|
char *canon;
|
||||||
|
bool free_at;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Values for `protoflag'. */
|
/* Values for `protoflag'. */
|
||||||
|
@ -565,6 +566,62 @@ out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If possible, call the simple, old functions, which do not support IPv6 scope
|
||||||
|
ids, nor retrieving the canonical name. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
try_simple_gethostbyname (const char *name, const struct addrinfo *req,
|
||||||
|
struct scratch_buffer *tmpbuf,
|
||||||
|
struct gaih_result *res)
|
||||||
|
{
|
||||||
|
res->at = NULL;
|
||||||
|
|
||||||
|
if (req->ai_family != AF_INET || (req->ai_flags & AI_CANONNAME) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int rc;
|
||||||
|
struct hostent th;
|
||||||
|
struct hostent *h;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf->data,
|
||||||
|
tmpbuf->length, &h, &h_errno);
|
||||||
|
if (rc != ERANGE || h_errno != NETDB_INTERNAL)
|
||||||
|
break;
|
||||||
|
if (!scratch_buffer_grow (tmpbuf))
|
||||||
|
return -EAI_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == 0)
|
||||||
|
{
|
||||||
|
if (h != NULL)
|
||||||
|
{
|
||||||
|
/* We found data, convert it. RES->AT from the conversion will
|
||||||
|
either be an allocated block or NULL, both of which are safe to
|
||||||
|
pass to free (). */
|
||||||
|
if (!convert_hostent_to_gaih_addrtuple (req, AF_INET, h, &res->at))
|
||||||
|
return -EAI_MEMORY;
|
||||||
|
|
||||||
|
res->free_at = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (h_errno == NO_DATA)
|
||||||
|
return -EAI_NODATA;
|
||||||
|
|
||||||
|
return -EAI_NONAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h_errno == NETDB_INTERNAL)
|
||||||
|
return -EAI_SYSTEM;
|
||||||
|
if (h_errno == TRY_AGAIN)
|
||||||
|
return -EAI_AGAIN;
|
||||||
|
|
||||||
|
/* We made requests but they turned out no data.
|
||||||
|
The name is known, though. */
|
||||||
|
return -EAI_NODATA;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gaih_inet (const char *name, const struct gaih_service *service,
|
gaih_inet (const char *name, const struct gaih_service *service,
|
||||||
const struct addrinfo *req, struct addrinfo **pai,
|
const struct addrinfo *req, struct addrinfo **pai,
|
||||||
|
@ -610,6 +667,11 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||||
else if (res.at != NULL)
|
else if (res.at != NULL)
|
||||||
goto process_list;
|
goto process_list;
|
||||||
|
|
||||||
|
if ((result = try_simple_gethostbyname (name, req, tmpbuf, &res)) != 0)
|
||||||
|
goto free_and_return;
|
||||||
|
else if (res.at != NULL)
|
||||||
|
goto process_list;
|
||||||
|
|
||||||
int no_data = 0;
|
int no_data = 0;
|
||||||
int no_inet6_data = 0;
|
int no_inet6_data = 0;
|
||||||
nss_action_list nip;
|
nss_action_list nip;
|
||||||
|
@ -619,69 +681,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||||
struct resolv_context *res_ctx = NULL;
|
struct resolv_context *res_ctx = NULL;
|
||||||
bool do_merge = false;
|
bool do_merge = false;
|
||||||
|
|
||||||
/* If we do not have to look for IPv6 addresses or the canonical
|
|
||||||
name, use the simple, old functions, which do not support
|
|
||||||
IPv6 scope ids, nor retrieving the canonical name. */
|
|
||||||
if (req->ai_family == AF_INET
|
|
||||||
&& (req->ai_flags & AI_CANONNAME) == 0)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
struct hostent th;
|
|
||||||
struct hostent *h;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
rc = __gethostbyname2_r (name, AF_INET, &th,
|
|
||||||
tmpbuf->data, tmpbuf->length,
|
|
||||||
&h, &h_errno);
|
|
||||||
if (rc != ERANGE || h_errno != NETDB_INTERNAL)
|
|
||||||
break;
|
|
||||||
if (!scratch_buffer_grow (tmpbuf))
|
|
||||||
{
|
|
||||||
result = -EAI_MEMORY;
|
|
||||||
goto free_and_return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == 0)
|
|
||||||
{
|
|
||||||
if (h != NULL)
|
|
||||||
{
|
|
||||||
/* We found data, convert it. */
|
|
||||||
if (!convert_hostent_to_gaih_addrtuple
|
|
||||||
(req, AF_INET, h, &addrmem))
|
|
||||||
{
|
|
||||||
result = -EAI_MEMORY;
|
|
||||||
goto free_and_return;
|
|
||||||
}
|
|
||||||
res.at = addrmem;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (h_errno == NO_DATA)
|
|
||||||
result = -EAI_NODATA;
|
|
||||||
else
|
|
||||||
result = -EAI_NONAME;
|
|
||||||
goto free_and_return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (h_errno == NETDB_INTERNAL)
|
|
||||||
result = -EAI_SYSTEM;
|
|
||||||
else if (h_errno == TRY_AGAIN)
|
|
||||||
result = -EAI_AGAIN;
|
|
||||||
else
|
|
||||||
/* We made requests but they turned out no data.
|
|
||||||
The name is known, though. */
|
|
||||||
result = -EAI_NODATA;
|
|
||||||
|
|
||||||
goto free_and_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto process_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_NSCD
|
#ifdef USE_NSCD
|
||||||
if (__nss_not_use_nscd_hosts > 0
|
if (__nss_not_use_nscd_hosts > 0
|
||||||
&& ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
|
&& ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
|
||||||
|
@ -1165,6 +1164,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||||
if (malloc_name)
|
if (malloc_name)
|
||||||
free ((char *) name);
|
free ((char *) name);
|
||||||
free (addrmem);
|
free (addrmem);
|
||||||
|
if (res.free_at)
|
||||||
|
free (res.at);
|
||||||
free (res.canon);
|
free (res.canon);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in New Issue