From 8d66a316dae815eb22e50948b7e0d3d84bc4cbb4 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Mon, 30 Mar 2020 15:45:08 +0800 Subject: [PATCH] libc/netdb: Support save the mix of IPv4/IPv6 address into hostent Signed-off-by: Xiang Xiao Change-Id: I704d38afde14b6d90a7726096fd1f483f96ba237 --- include/netdb.h | 7 +- libs/libc/netdb/lib_getaddrinfo.c | 4 +- libs/libc/netdb/lib_gethostbyaddrr.c | 62 +++++++-------- libs/libc/netdb/lib_gethostbynamer.c | 109 ++++++++++++++------------- libs/libc/netdb/lib_parsehostfile.c | 17 +++-- 5 files changed, 101 insertions(+), 98 deletions(-) diff --git a/include/netdb.h b/include/netdb.h index 6bb15ba4a5..5374fe8dfe 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -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 { diff --git a/libs/libc/netdb/lib_getaddrinfo.c b/libs/libc/netdb/lib_getaddrinfo.c index cc0009966c..797006617f 100644 --- a/libs/libc/netdb/lib_getaddrinfo.c +++ b/libs/libc/netdb/lib_getaddrinfo.c @@ -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) { diff --git a/libs/libc/netdb/lib_gethostbyaddrr.c b/libs/libc/netdb/lib_gethostbyaddrr.c index 0199bd0c86..b9115d745d 100644 --- a/libs/libc/netdb/lib_gethostbyaddrr.c +++ b/libs/libc/netdb/lib_gethostbyaddrr.c @@ -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 */ diff --git a/libs/libc/netdb/lib_gethostbynamer.c b/libs/libc/netdb/lib_gethostbynamer.c index fc4cf82ca3..b8846556b3 100644 --- a/libs/libc/netdb/lib_gethostbynamer.c +++ b/libs/libc/netdb/lib_gethostbynamer.c @@ -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); diff --git a/libs/libc/netdb/lib_parsehostfile.c b/libs/libc/netdb/lib_parsehostfile.c index 156b81a0ea..d48f9a92dd 100644 --- a/libs/libc/netdb/lib_parsehostfile.c +++ b/libs/libc/netdb/lib_parsehostfile.c @@ -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 */