libc/netdb: Support save the mix of IPv4/IPv6 address into hostent

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Change-Id: I704d38afde14b6d90a7726096fd1f483f96ba237
This commit is contained in:
Xiang Xiao 2020-03-30 15:45:08 +08:00 committed by patacongo
parent 7f2810f73a
commit 8d66a316da
5 changed files with 101 additions and 98 deletions

View File

@ -184,14 +184,17 @@ struct hostent
FAR char **h_aliases; /* A pointer to an array of pointers to the
* alternative host names, terminated by a
* null pointer. */
int h_addrtype; /* Address type. */
int h_length; /* The length, in bytes, of the address. */
FAR int *h_addrtypes; /* A pointer to an array of address type. */
FAR int *h_lengths; /* A pointer to an array of the length, in bytes,
* of the address. */
FAR char **h_addr_list; /* A pointer to an array of pointers to network
* addresses (in network byte order) for the host,
* terminated by a null pointer. */
};
#define h_addr h_addr_list[0] /* For backward compatibility */
#define h_length h_lengths[0]
#define h_addrtype h_addrtypes[0]
struct netent
{

View File

@ -287,7 +287,7 @@ int getaddrinfo(FAR const char *hostname, FAR const char *servname,
{
for (i = 0; hp->h_addr_list[i]; i++)
{
if (family != AF_UNSPEC && hp->h_addrtype != family)
if (family != AF_UNSPEC && hp->h_addrtypes[i] != family)
{
/* Filter by protocol family. */
@ -296,7 +296,7 @@ int getaddrinfo(FAR const char *hostname, FAR const char *servname,
/* REVISIT: filter by socktype and protocol not implemented. */
ai = alloc_ai(hp->h_addrtype, socktype, proto, port,
ai = alloc_ai(hp->h_addrtypes[i], socktype, proto, port,
hp->h_addr_list[i]);
if (ai == NULL)
{

View File

@ -61,8 +61,10 @@
struct hostent_info_s
{
int hi_addrtypes[CONFIG_NETDB_MAX_IPADDR + 1];
int hi_lengths[CONFIG_NETDB_MAX_IPADDR + 1];
FAR char *hi_addrlist[CONFIG_NETDB_MAX_IPADDR + 1];
char hi_data[1];
char hi_data[1];
};
/****************************************************************************
@ -164,34 +166,48 @@ static int lib_localhost(FAR const void *addr, socklen_t len, int type,
size_t buflen)
{
FAR struct hostent_info_s *info;
socklen_t addrlen;
FAR const uint8_t *src;
FAR char *dest;
int namelen;
/* Make sure that space remains to hold the hostent structure */
if (buflen <= sizeof(struct hostent_info_s))
{
return -ERANGE;
}
info = (FAR struct hostent_info_s *)buf;
dest = info->hi_data;
buflen -= (sizeof(struct hostent_info_s) - 1);
memset(host, 0, sizeof(struct hostent));
memset(info, 0, sizeof(struct hostent_info_s));
host->h_addrtypes = info->hi_addrtypes;
host->h_lengths = info->hi_lengths;
host->h_addr_list = info->hi_addrlist;
#ifdef CONFIG_NET_IPv4
if (lib_lo_ipv4match(addr, len, type))
{
/* Setup to transfer the IPv4 address */
/* Save the IPv4 address */
addrlen = sizeof(struct in_addr);
src = (FAR uint8_t *)&g_lo_ipv4addr;
host->h_length = sizeof(struct in_addr);
host->h_addr = (FAR char *)&g_lo_ipv4addr;
host->h_addrtype = AF_INET;
goto out_copy;
goto out_copyname;
}
#endif
#ifdef CONFIG_NET_IPv6
if (lib_lo_ipv6match(addr, len, type))
{
/* Setup to transfer the IPv6 address */
/* Save the IPv6 address */
addrlen = sizeof(struct in6_addr);
src = (FAR uint8_t *)&g_lo_ipv6addr;
host->h_length = sizeof(struct in6_addr);
host->h_addr = (FAR char *)&g_lo_ipv6addr;
host->h_addrtype = AF_INET6;
goto out_copy;
goto out_copyname;
}
#endif
@ -199,29 +215,7 @@ static int lib_localhost(FAR const void *addr, socklen_t len, int type,
return 1;
out_copy:
/* Make sure that space remains to hold the hostent structure and
* the IP address.
*/
if (buflen <= (sizeof(struct hostent_info_s) + addrlen))
{
return -ERANGE;
}
info = (FAR struct hostent_info_s *)buf;
dest = info->hi_data;
buflen -= (sizeof(struct hostent_info_s) - 1);
memset(info, 0, sizeof(struct hostent_info_s));
memcpy(dest, src, addrlen);
info->hi_addrlist[0] = dest;
host->h_addr_list = info->hi_addrlist;
host->h_length = addrlen;
dest += addrlen;
buflen -= addrlen;
out_copyname:
/* And copy localhost host name */

View File

@ -66,8 +66,10 @@
struct hostent_info_s
{
int hi_addrtypes[CONFIG_NETDB_MAX_IPADDR + 1];
int hi_lengths[CONFIG_NETDB_MAX_IPADDR + 1];
FAR char *hi_addrlist[CONFIG_NETDB_MAX_IPADDR + 1];
char hi_data[1];
char hi_data[1];
};
/****************************************************************************
@ -120,6 +122,10 @@ static int lib_numeric_address(FAR const char *name,
memset(host, 0, sizeof(struct hostent));
memset(info, 0, sizeof(struct hostent_info_s));
host->h_addrtypes = info->hi_addrtypes;
host->h_lengths = info->hi_lengths;
host->h_addr_list = info->hi_addrlist;
/* If the address contains a colon, then it might be a numeric IPv6
* address
*/
@ -189,12 +195,11 @@ static int lib_numeric_address(FAR const char *name,
return 1;
}
info->hi_addrlist[0] = ptr;
host->h_addr_list = info->hi_addrlist;
host->h_length = addrlen;
host->h_addr = ptr;
host->h_length = addrlen;
ptr += addrlen;
buflen -= addrlen;
ptr += addrlen;
buflen -= addrlen;
/* And copy name */
@ -235,53 +240,49 @@ static int lib_localhost(FAR const char *name, FAR struct hostent *host,
FAR char *buf, size_t buflen)
{
FAR struct hostent_info_s *info;
socklen_t addrlen;
FAR const char *src;
FAR char *dest;
int namelen;
int i = 0;
if (strcmp(name, g_lo_hostname) == 0)
{
/* Yes.. it is the localhost */
#ifdef CONFIG_NET_IPv4
/* Setup to transfer the IPv4 address */
/* Make sure that space remains to hold the hostent structure */
addrlen = sizeof(struct in_addr);
src = (FAR const char *)&g_lo_ipv4addr;
host->h_addrtype = AF_INET;
#else /* CONFIG_NET_IPv6 */
/* Setup to transfer the IPv6 address */
addrlen = sizeof(struct in6_addr);
src = (FAR const char *)&g_lo_ipv6addr;
host->h_addrtype = AF_INET6;
#endif
/* Make sure that space remains to hold the hostent structure and
* the IP address.
*/
if (buflen <= (sizeof(struct hostent_info_s) + addrlen))
if (buflen <= sizeof(struct hostent_info_s))
{
return -ERANGE;
}
info = (FAR struct hostent_info_s *)buf;
dest = info->hi_data;
buflen -= (sizeof(struct hostent_info_s) - 1);
info = (FAR struct hostent_info_s *)buf;
dest = info->hi_data;
buflen -= (sizeof(struct hostent_info_s) - 1);
memset(host, 0, sizeof(struct hostent));
memset(info, 0, sizeof(struct hostent_info_s));
memcpy(dest, src, addrlen);
info->hi_addrlist[0] = dest;
host->h_addr_list = info->hi_addrlist;
host->h_length = addrlen;
host->h_addrtypes = info->hi_addrtypes;
host->h_lengths = info->hi_lengths;
host->h_addr_list = info->hi_addrlist;
dest += addrlen;
buflen -= addrlen;
#ifdef CONFIG_NET_IPv4
/* Save the IPv4 address */
info->hi_addrtypes[i] = AF_INET;
info->hi_lengths[i] = sizeof(struct in_addr);
info->hi_addrlist[i] = (FAR char *)&g_lo_ipv4addr;
i++;
#endif
#ifdef CONFIG_NET_IPv6
/* Save the IPv6 address */
info->hi_addrtypes[i] = AF_INET6;
info->hi_lengths[i] = sizeof(struct in6_addr);
info->hi_addrlist[i] = (FAR char *)&g_lo_ipv6addr;
i++;
#endif
/* And copy name */
@ -362,6 +363,10 @@ static int lib_find_answer(FAR const char *name, FAR struct hostent *host,
memset(host, 0, sizeof(struct hostent));
memset(info, 0, sizeof(struct hostent_info_s));
host->h_addrtypes = info->hi_addrtypes;
host->h_lengths = info->hi_lengths;
host->h_addr_list = info->hi_addrlist;
/* Try to get the host address using the DNS name server */
naddr = buflen / sizeof(union dns_addr_u);
@ -401,18 +406,14 @@ static int lib_find_answer(FAR const char *name, FAR struct hostent *host,
}
#endif
/* REVISIT: This assumes addresses are all either IPv4 or IPv6. */
info->hi_addrtypes[i] = addrtype;
info->hi_lengths[i] = addrlen;
info->hi_addrlist[i] = addrdata;
info->hi_addrlist[i] = addrdata;
host->h_addrtype = addrtype;
host->h_length = addrlen;
ptr += sizeof(union dns_addr_u);
buflen -= sizeof(union dns_addr_u);
ptr += sizeof(union dns_addr_u);
buflen -= sizeof(union dns_addr_u);
}
host->h_addr_list = info->hi_addrlist;
/* And copy name */
namelen = strlen(name);
@ -524,6 +525,10 @@ static int lib_dns_lookup(FAR const char *name, FAR struct hostent *host,
memset(host, 0, sizeof(struct hostent));
memset(info, 0, sizeof(struct hostent_info_s));
host->h_addrtypes = info->hi_addrtypes;
host->h_lengths = info->hi_lengths;
host->h_addr_list = info->hi_addrlist;
/* Try to get the host address using the DNS name server */
naddr = buflen / sizeof(union dns_addr_u);
@ -561,18 +566,14 @@ static int lib_dns_lookup(FAR const char *name, FAR struct hostent *host,
}
#endif
/* REVISIT: This assumes addresses are all either IPv4 or IPv6. */
info->hi_addrtypes[i] = addrtype;
info->hi_lengths[i] = addrlen;
info->hi_addrlist[i] = addrdata;
info->hi_addrlist[i] = addrdata;
host->h_addrtype = addrtype;
host->h_length = addrlen;
ptr += sizeof(union dns_addr_u);
buflen -= sizeof(union dns_addr_u);
ptr += sizeof(union dns_addr_u);
buflen -= sizeof(union dns_addr_u);
}
host->h_addr_list = info->hi_addrlist;
/* And copy name */
namelen = strlen(name);

View File

@ -72,8 +72,10 @@
struct hostent_info_s
{
FAR char *hi_aliases[CONFIG_NETDB_MAX_ALTNAMES + 1];
int hi_addrtypes[2];
int hi_lengths[2];
FAR char *hi_addrlist[2];
char hi_data[1];
char hi_data[1];
};
/****************************************************************************
@ -292,6 +294,10 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host,
memset(host, 0, sizeof(struct hostent));
memset(info, 0, sizeof(struct hostent_info_s));
host->h_addrtypes = info->hi_addrtypes;
host->h_lengths = info->hi_lengths;
host->h_addr_list = info->hi_addrlist;
/* Skip over any leading spaces */
do
@ -379,12 +385,11 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host,
host->h_addrtype = AF_INET;
}
info->hi_addrlist[0] = ptr;
host->h_addr_list = info->hi_addrlist;
host->h_length = addrlen;
host->h_addr = ptr;
host->h_length = addrlen;
ptr += addrlen;
buflen -= addrlen;
ptr += addrlen;
buflen -= addrlen;
/* Skip over any additional whitespace */