diff --git a/include/netdb.h b/include/netdb.h index aac1a60733..8fc99a4af9 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -277,32 +277,31 @@ int getaddrinfo(FAR const char *nodename, FAR const char *servname, FAR const struct addrinfo *hints, FAR struct addrinfo **res); +int getnameinfo(FAR const struct sockaddr *sa, + socklen_t salen, FAR char *node, + socklen_t nodelen, FAR char *service, + socklen_t servicelen, int flags); FAR struct hostent *gethostbyaddr(FAR const void *addr, socklen_t len, int type); FAR struct hostent *gethostbyname(FAR const char *name); +FAR struct servent *getservbyport(int port, FAR const char *proto); FAR struct servent *getservbyname(FAR const char *name, FAR const char *proto); #if 0 /* None of these are yet supported */ FAR struct hostent *gethostent(void); -int getnameinfo(FAR const struct sockaddr *sa, - socklen_t salen, FAR char *node, - socklen_t nodelen, FAR char *service, - socklen_t servicelen, int flags); FAR struct netent *getnetbyaddr(uint32_t net, int type); FAR struct netent *getnetbyname(FAR const char *name); FAR struct netent *getnetent(void); FAR struct protoent *getprotobyname(FAR const char *name); FAR struct protoent *getprotobynumber(int proto); FAR struct protoent *getprotoent(void); -FAR struct servent *getservbyport(int port, FAR const char *proto); FAR struct servent *getservent(void); void sethostent(int); void setnetent(int stayopen); void setprotoent(int stayopen); void setservent(int); - #endif /* None of these are yet supported */ /* Non-standard interfaces similar to Glibc 2 interfaces */ @@ -312,6 +311,9 @@ int gethostbyaddr_r(FAR const void *addr, socklen_t len, int type, size_t buflen, int *h_errnop); int gethostbyname_r(FAR const char *name, FAR struct hostent *host, FAR char *buf, size_t buflen, int *h_errnop); +int getservbyport_r(int port, FAR const char *proto, + FAR struct servent *result_buf, FAR char *buf, + size_t buflen, FAR struct servent **result); int getservbyname_r(FAR const char *name, FAR const char *proto, FAR struct servent *result_buf, FAR char *buf, size_t buflen, FAR struct servent **result); diff --git a/libs/libc/netdb/Make.defs b/libs/libc/netdb/Make.defs index 268596d1f6..dc601c28a8 100644 --- a/libs/libc/netdb/Make.defs +++ b/libs/libc/netdb/Make.defs @@ -39,7 +39,9 @@ ifeq ($(CONFIG_LIBC_NETDB),y) CSRCS += lib_netdb.c lib_gethostbyname.c lib_gethostbynamer.c CSRCS += lib_getservbyname.c lib_getservbynamer.c +CSRCS += lib_getservbyport.c lib_getservbyportr.c CSRCS += lib_gaistrerror.c lib_freeaddrinfo.c lib_getaddrinfo.c +CSRCS += lib_getnameinfo.c # Add host file support diff --git a/libs/libc/netdb/lib_dns.h b/libs/libc/netdb/lib_dns.h index 58e9ddf165..3caba91519 100644 --- a/libs/libc/netdb/lib_dns.h +++ b/libs/libc/netdb/lib_dns.h @@ -36,8 +36,8 @@ * ****************************************************************************/ -#ifndef __LIBC_NETDB_LIB_DNS_H -#define __LIBC_NETDB_LIB_DNS_H +#ifndef __LIBS_LIBC_NETDB_LIB_DNS_H +#define __LIBS_LIBC_NETDB_LIB_DNS_H /**************************************************************************** * Included Files @@ -259,4 +259,4 @@ void dns_notify_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen); } #endif -#endif /* __LIBC_NETDB_LIB_DNS_H */ +#endif /* __LIBS_LIBC_NETDB_LIB_DNS_H */ diff --git a/libs/libc/netdb/lib_gethostbyaddrr.c b/libs/libc/netdb/lib_gethostbyaddrr.c index cae3968400..e4ff8abb88 100644 --- a/libs/libc/netdb/lib_gethostbyaddrr.c +++ b/libs/libc/netdb/lib_gethostbyaddrr.c @@ -53,6 +53,18 @@ #ifdef CONFIG_NETDB_HOSTFILE +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/* This is the layout of the caller provided memory area */ + +struct hostent_info_s +{ + FAR char *hi_addrlist[CONFIG_NETDB_DNSCLIENT_MAXIP + 1]; + char hi_data[1]; +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -113,7 +125,7 @@ static bool lib_lo_ipv6match(FAR const void *addr, socklen_t len, int type) { FAR struct in_addr6 *ipv6addr; - if (type == AF_INE6T && len >= sizeof(struct in_addr6)) + if (type == AF_INET6 && len >= sizeof(struct in_addr6)) { ipv6addr = (FAR struct in_addr6 *)addr; return net_ipv6addr_cmp(ipv6addr->sin6_addr.s6_addr16, g_lo_ipv6addr); @@ -159,6 +171,9 @@ static int lib_localhost(FAR const void *addr, socklen_t len, int type, int herrnocode; int namelen; + memset(host, 0, sizeof(struct hostent)); + memset(buf, 0, buflen); + if (lib_lo_ipv4match(addr, len, type)) { /* Setup to transfer the IPv4 address */ @@ -197,8 +212,6 @@ static int lib_localhost(FAR const void *addr, socklen_t len, int type, 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; @@ -218,6 +231,8 @@ static int lib_localhost(FAR const void *addr, socklen_t len, int type, } strncpy(dest, g_lo_hostname, buflen); + host->h_name = dest; + return 0; errorout_with_herrnocode: @@ -314,7 +329,7 @@ int lib_hostfile_lookup(FAR const void *addr, socklen_t len, int type, ninfo("Comparing addresses...\n"); if (memcmp(addr, hostaddr, len) == 0) { - /* We have a match */ + /* We have a match */ fclose(stream); return OK; @@ -356,8 +371,8 @@ errorout_with_herrnocode: * pointer to a struct of a type depending on the address type, for example * a struct in_addr * for address type AF_INET. * - * gethostbyaddr_r() is *not* POSIX but is similar to a Glibc extension and is - * used internally by NuttX to implement the POSIX gethostbyaddr(). + * gethostbyaddr_r() is *not* POSIX but is similar to a Glibc extension and + * is used internally by NuttX to implement the POSIX gethostbyaddr(). * * Input Parameters: * addr - The address of the host to find. @@ -379,10 +394,6 @@ int gethostbyaddr_r(FAR const void *addr, socklen_t len, int type, FAR struct hostent *host, FAR char *buf, size_t buflen, int *h_errnop) { - FAR FILE *stream; - int herrnocode; - int nread; - DEBUGASSERT(addr != NULL && host != NULL && buf != NULL); DEBUGASSERT(type == AF_INET || type == AF_INET6); diff --git a/libs/libc/netdb/lib_getnameinfo.c b/libs/libc/netdb/lib_getnameinfo.c new file mode 100644 index 0000000000..c867b1cde8 --- /dev/null +++ b/libs/libc/netdb/lib_getnameinfo.c @@ -0,0 +1,220 @@ +/**************************************************************************** + * libc/netdb/lib_getnameinfo.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Michael Jung + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include "libc.h" +#include "netdb/lib_netdb.h" + +#ifdef CONFIG_LIBC_NETDB + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getnameinfo + ****************************************************************************/ + +int getnameinfo(FAR const struct sockaddr *addr, socklen_t addrlen, + FAR char *host, socklen_t hostlen, + FAR char *serv, socklen_t servlen, int flags) +{ + FAR const void *saddr; + socklen_t saddr_len; + int port; + int ret; + + if (addr->sa_family == AF_INET && + addrlen == sizeof(struct sockaddr_in)) + { + const struct sockaddr_in *sa_in = (const struct sockaddr_in *)addr; + + port = ntohs(sa_in->sin_port); + saddr = &sa_in->sin_addr; + saddr_len = sizeof(sa_in->sin_addr); + } +#ifdef CONFIG_NET_IPv6 + else if (addr->sa_family == AF_INET6 && + addrlen == sizeof(struct sockaddr_in6)) + { + const struct sockaddr_in6 *sa_in6 = (const struct sockaddr_in6 *)addr; + + port = ntohs(sa_in6->sin6_port); + saddr = &sa_in6->sin6_addr; + saddr_len = sizeof(sa_in6->sin6_addr); + } +#endif + else + { + return EAI_FAMILY; + } + + if (!(flags & NI_NUMERICHOST)) + { +#ifndef CONFIG_NETDB_HOSTFILE + /* Fall-back to numeric for the host name. */ + + flags |= NI_NUMERICHOST; + (void)saddr_len; +#else + struct hostent hostent; + int h_errno; + + ret = gethostbyaddr_r(saddr, saddr_len, addr->sa_family, &hostent, host, + hostlen, &h_errno); + + if (ret == OK) + { + size_t sz = strlen(hostent.h_name) + 1; + + if (sz <= hostlen) + { + memmove(host, hostent.h_name, sz); + } + else + { + memmove(host, hostent.h_name, hostlen); + host[hostlen - 1] = '\0'; + } + } + else + { + switch (h_errno) + { + case HOST_NOT_FOUND: + { + if (flags & NI_NAMEREQD) + { + return EAI_NONAME; + } + } + break; + + case NO_RECOVERY: + { + if (flags & NI_NAMEREQD) + { + return EAI_FAIL; + } + } + break; + + case NO_DATA: + case TRY_AGAIN: + { + if (flags & NI_NAMEREQD) + { + return EAI_AGAIN; + } + } + break; + + default: + DEBUGASSERT(0); + } + + /* Fall-back to numeric for the host name. */ + + flags |= NI_NUMERICHOST; + } +#endif /* CONFIG_NETDB_HOSTFILE */ + } + + if (flags & NI_NUMERICHOST) + { + if (!inet_ntop(addr->sa_family, saddr, host, hostlen)) + { + switch (errno) + { + case ENOSPC: + return EAI_OVERFLOW; + + default: + DEBUGASSERT(0); + } + } + } + + if (!(flags & NI_NUMERICSERV)) + { + struct servent servent; + struct servent *result; + + ret = getservbyport_r(port, flags & NI_DGRAM ? "udp" : NULL, &servent, + serv, servlen, &result); + + if (ret == OK) + { + size_t sz = strlen(servent.s_name) + 1; + + if (sz <= servlen) + { + memmove(serv, servent.s_name, sz); + } + else + { + memmove(serv, servent.s_name, servlen); + serv[servlen - 1] = '\0'; + } + } + else + { + /* Fall-back to numeric for the host name. */ + + flags |= NI_NUMERICSERV; + } + } + + if (flags & NI_NUMERICSERV) + { + snprintf(serv, servlen, "%d", port); + } + + return OK; +} + +#endif /* CONFIG_LIBC_NETDB */ diff --git a/libs/libc/netdb/lib_getservbynamer.c b/libs/libc/netdb/lib_getservbynamer.c index acbefa30ca..56540cd219 100644 --- a/libs/libc/netdb/lib_getservbynamer.c +++ b/libs/libc/netdb/lib_getservbynamer.c @@ -47,27 +47,10 @@ #include +#include "lib_netdb.h" + #ifdef CONFIG_LIBC_NETDB -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif - -/**************************************************************************** - * Private Data Types - ****************************************************************************/ - -struct services_db_s -{ - const char *s_name; - int s_port; - int s_protocol; -}; - /**************************************************************************** * Private Data ****************************************************************************/ @@ -76,10 +59,11 @@ struct services_db_s * REVISIT: This is just an example, lets not add full list here. */ -const static struct services_db_s g_services_db[] = +const struct services_db_s g_services_db[] = { { "ntp", 123, IP_PROTO_TCP }, { "ntp", 123, IP_PROTO_UDP }, + { NULL, 0, 0 } }; /**************************************************************************** @@ -137,7 +121,7 @@ int getservbyname_r(FAR const char *name, FAR const char *proto, return EINVAL; } - for (i = 0; i < ARRAY_SIZE(g_services_db); i++) + for (i = 0; g_services_db[i].s_name; i++) { if (strcmp(name, g_services_db[i].s_name) == 0 && (protocol == 0 || protocol == g_services_db[i].s_protocol)) @@ -166,4 +150,3 @@ int getservbyname_r(FAR const char *name, FAR const char *proto, } #endif /* CONFIG_LIBC_NETDB */ - diff --git a/libs/libc/netdb/lib_getservbyport.c b/libs/libc/netdb/lib_getservbyport.c new file mode 100644 index 0000000000..59c4e4a96e --- /dev/null +++ b/libs/libc/netdb/lib_getservbyport.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * libs/libc/netdb/lib_getservbyport.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Michael Jung + * + * Based on libs/libc/netdb/lib_getservbyname.c + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Juha Niskanen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#ifdef CONFIG_LIBC_NETDB + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getservbyport + ****************************************************************************/ + +FAR struct servent *getservbyport(int port, FAR const char *proto) +{ + static struct servent ent; + static FAR char *buf[2]; + struct servent *res; + int ret; + + ret = getservbyport_r(port, proto, &ent, (FAR void *)buf, sizeof buf, &res); + return (ret != OK) ? NULL : res; +} + +#endif /* CONFIG_LIBC_NETDB */ diff --git a/libs/libc/netdb/lib_getservbyportr.c b/libs/libc/netdb/lib_getservbyportr.c new file mode 100644 index 0000000000..233254c9f3 --- /dev/null +++ b/libs/libc/netdb/lib_getservbyportr.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * libs/libc/netdb/lib_getservbyportr.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Michael Jung + * + * Based on libs/libc/netdb/lib_getservbynamer.c + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Juha Niskanen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "lib_netdb.h" + +#ifdef CONFIG_LIBC_NETDB + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getservbyport_r + ****************************************************************************/ + +int getservbyport_r(int port, FAR const char *proto, + FAR struct servent *result_buf, FAR char *buf, + size_t buflen, FAR struct servent **result) +{ + int protocol; + int i; + + DEBUGASSERT(buf != NULL); + DEBUGASSERT(result_buf != NULL && result != NULL); + + /* Linux man page says result must be NULL in case of failure. */ + + *result = NULL; + + /* We need space for two pointers for hostalias strings. */ + + if (buflen < 2 * sizeof(char *)) + { + return ERANGE; + } + + if (proto == NULL) + { + protocol = 0; + } + else if (strcmp(proto, "tcp") == 0) + { + protocol = IPPROTO_TCP; + } + else if (strcmp(proto, "udp") == 0) + { + protocol = IPPROTO_UDP; + } + else + { + return EINVAL; + } + + for (i = 0; g_services_db[i].s_name; i++) + { + if (port == g_services_db[i].s_port && + (protocol == 0 || protocol == g_services_db[i].s_protocol)) + { + result_buf->s_name = (char *)g_services_db[i].s_name; + result_buf->s_aliases = (void *)buf; + result_buf->s_aliases[0] = (char *)g_services_db[i].s_name; + result_buf->s_aliases[1] = NULL; + result_buf->s_port = HTONS(g_services_db[i].s_port); + + if (g_services_db[i].s_protocol == IPPROTO_TCP) + { + result_buf->s_proto = "tcp"; + } + else + { + result_buf->s_proto = "udp"; + } + + *result = result_buf; + return 0; + } + } + + return ENOENT; +} + +#endif /* CONFIG_LIBC_NETDB */ diff --git a/libs/libc/netdb/lib_netdb.h b/libs/libc/netdb/lib_netdb.h index b3b8bea935..41d2285b43 100644 --- a/libs/libc/netdb/lib_netdb.h +++ b/libs/libc/netdb/lib_netdb.h @@ -33,8 +33,8 @@ * ****************************************************************************/ -#ifndef __LIBC_NETDB_LIB_NETDB_H -#define __LIBC_NETDB_LIB_NETDB_H +#ifndef __LIBS_LIBC_NETDB_LIB_NETDB_H +#define __LIBS_LIBC_NETDB_LIB_NETDB_H /**************************************************************************** * Included Files @@ -70,6 +70,17 @@ # define CONFIG_NETDB_BUFSIZE 128 #endif +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct services_db_s +{ + FAR const char *s_name; + int s_port; + int s_protocol; +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -84,6 +95,7 @@ extern "C" EXTERN struct hostent g_hostent; EXTERN char g_hostbuffer[CONFIG_NETDB_BUFSIZE]; +EXTERN const struct services_db_s g_services_db[]; /**************************************************************************** * Public Function Prototypes @@ -95,4 +107,4 @@ EXTERN char g_hostbuffer[CONFIG_NETDB_BUFSIZE]; #endif #endif /* CONFIG_LIBC_NETDB */ -#endif /* __LIBC_NETDB_LIB_NETDB_H */ +#endif /* __LIBS_LIBC_NETDB_LIB_NETDB_H */