diff --git a/TODO b/TODO index 5d47378922..caf40853c8 100644 --- a/TODO +++ b/TODO @@ -1177,7 +1177,7 @@ o Network (net/, drivers/net) Title: MISSING netdb INTERFACES Description: There is no implementation for many netdb interfaces such as - getaddrinfo(), freeaddrinfo(), getnameinfo(), etc. + getnetbyname(), getprotobyname(), getnameinfo(), etc. Status: Open Priority: Low diff --git a/include/netdb.h b/include/netdb.h index 56b5fb35cd..580a0bbf0d 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/netdb.h * - * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Reference: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/netdb.h.html @@ -114,23 +114,14 @@ #define NI_NUMERICSCOPE (1 << 4) #define NI_DGRAM (1 << 5) -/* The header shall define the following macros for use as error - * values for gethostbyaddr() and gethostbyname() - */ - -#define HOST_NOT_FOUND 1 -#define NO_DATA 2 -#define NO_RECOVERY 3 -#define TRY_AGAIN 4 - /* Address Information Errors. The header shall define the * following macros for use as error values for getaddrinfo() and * getnameinfo(): * * EAI_AGAIN - The name could not be resolved at this time. Future * attempts may succeed. - * EAI_BADFLAGS - The flags had an invalid value.EAI_FAILA non- - * recoverable error occurred. + * EAI_BADFLAGS - The flags had an invalid value. + * EAI_FAIL - A non-recoverable error occurred. * EAI_FAMILY - The address family was not recognized or the address * length was invalid for the specified family. * EAI_MEMORY - There was a memory allocation failure. @@ -148,13 +139,14 @@ #define EAI_AGAIN 1 #define EAI_BADFLAGS 2 -#define EAI_FAMILY 3 -#define EAI_MEMORY 4 -#define EAI_NONAME 5 -#define EAI_SERVICE 6 -#define EAI_SOCKTYPE 7 -#define EAI_SYSTEM 8 -#define EAI_OVERFLOW 9 +#define EAI_FAIL 3 +#define EAI_FAMILY 4 +#define EAI_MEMORY 5 +#define EAI_NONAME 6 +#define EAI_SERVICE 7 +#define EAI_SOCKTYPE 8 +#define EAI_SYSTEM 9 +#define EAI_OVERFLOW 10 /* h_errno values that may be returned by gethosbyname(), gethostbyname_r(), * gethostbyaddr(), or gethostbyaddr_r() @@ -170,6 +162,9 @@ * * TRY_AGAIN - A temporary and possibly transient error occurred, such as * a failure of a server to respond. + * + * These are obsolete and were removed in the Open Group Base Specifications + * Issue 7, 2018 edition. */ #define HOST_NOT_FOUND 1 @@ -254,9 +249,13 @@ extern "C" /* When the header is included, h_errno shall be available as a * modifiable lvalue of type int. It is unspecified whether h_errno is a * macro or an identifier declared with external linkage. + * + * h_errno is obsolete and was removed in the Open Group Base Specifications + * Issue 7, 2018 edition. */ /* REVISIT: This should at least be per-task? */ + EXTERN int h_errno; /**************************************************************************** @@ -270,22 +269,25 @@ void endhostent(void); void endnetent(void); void endprotoent(void); void endservent(void); +#endif void freeaddrinfo(FAR struct addrinfo *); FAR const char *gai_strerror(int); int getaddrinfo(FAR const char *restrict, FAR const char *restrict, FAR const struct addrinfo *restrict, FAR struct addrinfo **restrict); -#endif FAR struct hostent *gethostbyaddr(FAR const void *addr, socklen_t len, int type); FAR struct hostent *gethostbyname(FAR const char *name); +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 *restrict, socklen_t, - FAR char *restrict, socklen_t, FAR char *restrict, +int getnameinfo(FAR const struct sockaddr *restrict, + socklen_t, FAR char *restrict, + socklen_t, FAR char *restrict, socklen_t, int); FAR struct netent *getnetbyaddr(uint32_t, int); FAR struct netent *getnetbyname(FAR const char *); @@ -293,7 +295,6 @@ FAR struct netent *getnetent(void); FAR struct protoent *getprotobyname(FAR const char *); FAR struct protoent *getprotobynumber(int); FAR struct protoent *getprotoent(void); -FAR struct servent *getservbyname(FAR const char *, FAR const char *); FAR struct servent *getservbyport(int, FAR const char *); FAR struct servent *getservent(void); void sethostent(int); @@ -310,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 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); #endif /* CONFIG_LIBC_NETDB */ diff --git a/libs/libc/netdb/Kconfig b/libs/libc/netdb/Kconfig index a841ce14b7..b54ff676a4 100644 --- a/libs/libc/netdb/Kconfig +++ b/libs/libc/netdb/Kconfig @@ -9,6 +9,15 @@ config LIBC_NETDB menu "NETDB Support" +config LIBC_GAISTRERROR + bool "Enable gai_strerror" + default n + ---help--- + The gai_strerror() function shall return a text string describing an error + value for the getaddrinfo() and getnameinfo(). But it can also require a lot + of memory. If this option is not selected, gai_strerror() will still exist in + the build but it will not decode error values. + menuconfig NETDB_HOSTFILE bool "Network host file support" default n diff --git a/libs/libc/netdb/Make.defs b/libs/libc/netdb/Make.defs index 49588637f2..e29aa1eac3 100644 --- a/libs/libc/netdb/Make.defs +++ b/libs/libc/netdb/Make.defs @@ -38,6 +38,8 @@ ifeq ($(CONFIG_LIBC_NETDB),y) # Add the netdb C files to the build CSRCS += lib_netdb.c lib_gethostbyname.c lib_gethostbynamer.c +CSRCS += lib_getservbyname.c lib_getservbynamer.c +CSRCS += lib_gaistrerror.c lib_freeaddrinfo.c lib_getaddrinfo.c # Add host file support @@ -56,7 +58,7 @@ CSRCS += lib_dnscache.c endif endif -# Add the net directory to the build +# Add the netdb directory to the build DEPPATH += --dep-path netdb VPATH += :netdb diff --git a/libs/libc/netdb/lib_dnsbind.c b/libs/libc/netdb/lib_dnsbind.c index f71e9af5e2..3c1645f7a1 100644 --- a/libs/libc/netdb/lib_dnsbind.c +++ b/libs/libc/netdb/lib_dnsbind.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/netdb/lib_dnsclien.c + * libs/libc/netdb/lib_dnsbind.c * * Copyright (C) 2007, 2009, 2012, 2014-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt diff --git a/libs/libc/netdb/lib_dnsinit.c b/libs/libc/netdb/lib_dnsinit.c index 0df7d3b58d..2b15ec15c2 100644 --- a/libs/libc/netdb/lib_dnsinit.c +++ b/libs/libc/netdb/lib_dnsinit.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/netdb/lib_dnscache.c + * libs/libc/netdb/lib_dnsinit.c * * Copyright (C) 2007, 2009, 2012, 2014-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt diff --git a/libs/libc/netdb/lib_freeaddrinfo.c b/libs/libc/netdb/lib_freeaddrinfo.c new file mode 100644 index 0000000000..a9a6cd0147 --- /dev/null +++ b/libs/libc/netdb/lib_freeaddrinfo.c @@ -0,0 +1,68 @@ +/**************************************************************************** + * libs/libc/netdb/lib_freeaddrinfo.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 "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: freeaddrinfo + ****************************************************************************/ + +void freeaddrinfo(FAR struct addrinfo *ai) +{ + FAR struct addrinfo *p; + + DEBUGASSERT(ai != NULL); + + do + { + p = ai; + ai = ai->ai_next; + lib_free(p); + } + while (ai != NULL); +} + diff --git a/libs/libc/netdb/lib_gaistrerror.c b/libs/libc/netdb/lib_gaistrerror.c new file mode 100644 index 0000000000..83a078fa50 --- /dev/null +++ b/libs/libc/netdb/lib_gaistrerror.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * libs/libc/netdb/lib_gaistrerror.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 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct errno_strmap_s +{ + uint8_t errnum; + const char *str; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_LIBC_GAISTRERROR + +/* This table maps all error numbers to descriptive strings. + * The only assumption that the code makes with regard to this + * this table is that it is ordered by error number. + * + * The size of this table is quite large. Its size can be + * reduced by eliminating some of the more obscure error + * strings. + * + * Only short names are currently supported. + */ + +static const struct errno_strmap_s g_gaierrnomap[] = +{ + { EAI_AGAIN, "EAI_AGAIN" }, + { EAI_BADFLAGS, "EAI_BADFLAGS" }, + { EAI_FAIL, "EAI_FAIL" }, + { EAI_FAMILY, "EAI_FAMILY" }, + { EAI_MEMORY, "EAI_MEMORY" }, + { EAI_NONAME, "EAI_NONAME" }, + { EAI_SERVICE, "EAI_SERVICE" }, + { EAI_SOCKTYPE, "EAI_SOCKTYPE" }, + { EAI_SYSTEM, "EAI_SYSTEM" }, + { EAI_OVERFLOW, "EAI_OVERFLOW" }, +}; + +#define NERRNO_STRS (sizeof(g_gaierrnomap) / sizeof(struct errno_strmap_s)) + +#endif /* CONFIG_LIBC_GAISTRERROR */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gai_strerror + ****************************************************************************/ + +FAR const char *gai_strerror(int errnum) +{ +#ifdef CONFIG_LIBC_GAISTRERROR + int ndxlow = 0; + int ndxhi = NERRNO_STRS - 1; + int ndxmid; + + do + { + ndxmid = (ndxlow + ndxhi) >> 1; + if (errnum > g_gaierrnomap[ndxmid].errnum) + { + ndxlow = ndxmid + 1; + } + else if (errnum < g_gaierrnomap[ndxmid].errnum) + { + ndxhi = ndxmid - 1; + } + else + { + return g_gaierrnomap[ndxmid].str; + } + } + while (ndxlow <= ndxhi); +#endif + return "Unknown error"; +} + diff --git a/libs/libc/netdb/lib_getaddrinfo.c b/libs/libc/netdb/lib_getaddrinfo.c new file mode 100644 index 0000000000..81af718967 --- /dev/null +++ b/libs/libc/netdb/lib_getaddrinfo.c @@ -0,0 +1,311 @@ +/**************************************************************************** + * libs/libc/netdb/lib_getaddrinfo.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 "libc.h" + +/**************************************************************************** + * Private Data Types + ****************************************************************************/ + +struct ai_s +{ + struct addrinfo ai; + union + { + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } sa; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +FAR static struct ai_s *alloc_ai(int family, int port, FAR void *addr) +{ + struct ai_s *ai; + socklen_t addrlen; + + addrlen = (family == AF_INET) ? sizeof(struct sockaddr_in) + : sizeof(struct sockaddr_in6); + + ai = lib_zalloc(sizeof(struct ai_s)); + if (ai == NULL) + { + return ai; + } + + ai->ai.ai_addr = (struct sockaddr *)&ai->sa; + ai->ai.ai_addrlen = addrlen; + ai->ai.ai_addr->sa_family = ai->ai.ai_family = family; + + switch (family) + { +#ifdef CONFIG_NET_IPv4 + case AF_INET: + ai->sa.sin.sin_family = AF_INET; + ai->sa.sin.sin_port = HTONS(port); + memcpy(&ai->sa.sin.sin_addr, addr, sizeof(ai->sa.sin.sin_addr)); + break; +#endif +#ifdef CONFIG_NET_IPv6 + case AF_INET6: + ai->sa.sin6.sin6_family = AF_INET6; + ai->sa.sin6.sin6_port = HTONS(port); + memcpy(&ai->sa.sin6.sin6_addr, addr, sizeof(ai->sa.sin6.sin6_addr)); + break; +#endif + } + + return ai; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getaddrinfo + ****************************************************************************/ + +int getaddrinfo(FAR const char *restrict hostname, + FAR const char *restrict servname, + FAR const struct addrinfo *restrict hint, + FAR struct addrinfo **restrict res) +{ + int family = AF_UNSPEC; + int port = 0; + int flags = 0; + int proto = 0; + int socktype = 0; + struct hostent *hp; + struct ai_s *ai; + struct ai_s *prev_ai = NULL; + const int valid_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | + AI_NUMERICSERV | AI_V4MAPPED | AI_ALL | + AI_ADDRCONFIG; + int i; + + if (hostname == NULL && servname == NULL) + { + return EAI_NONAME; + } + + if (hint) + { + family = hint->ai_family; + flags = hint->ai_flags; + proto = hint->ai_protocol; + socktype = hint->ai_socktype; + + if ((flags & valid_flags) != flags) + { + return EAI_BADFLAGS; + } + + if (family != AF_INET && + family != AF_INET6 && + family != AF_UNSPEC) + { + return EAI_FAMILY; + } + } + + if (servname) + { + char *endp; + struct servent *sp; + + port = strtol(servname, &endp, 10); + if (port > 0 && port <= 65535 && *endp == '\0') + { + port = HTONS(port); + } + else if (flags & AI_NUMERICSERV) + { + return EAI_NONAME; + } + else if ((sp = getservbyname(servname, NULL)) != NULL) + { + port = sp->s_port; + } + else + { + return EAI_SERVICE; + } + } + + if (flags & AI_PASSIVE) + { + in_addr_t addr; + + addr = hostname ? inet_addr(hostname) : HTONL(0x00000000); + + /* REVISIT: IPv6? */ + + ai = alloc_ai(AF_INET, port, &addr); + if (ai == NULL) + { + return EAI_MEMORY; + } + + *res = (struct addrinfo *)ai; + return OK; + } + + *res = NULL; + + if (!hostname) + { +#ifdef CONFIG_NET_LOOPBACK + /* Local service. */ + +#ifdef CONFIG_NET_IPv4 + if (family == AF_INET || family == AF_UNSPEC) + { + ai = alloc_ai(AF_INET, port, (void *)&g_lo_ipv4addr); + if (ai == NULL) + { + return EAI_MEMORY; + } + + *res = (struct addrinfo *)ai; + } +#endif +#ifdef CONFIG_NET_IPv6 + if (family == AF_INET6 || family == AF_UNSPEC) + { + ai = alloc_ai(AF_INET6, port, (void *)&g_lo_ipv6addr); + if (ai == NULL) + { + return (*res != NULL) ? OK : EAI_MEMORY; + } + + /* Can return both IPv4 and IPv6 loopback. */ + + if (*res != NULL) + { + (*res)->ai_next = (struct addrinfo *)ai; + } + else + { + *res = (struct addrinfo *)ai; + } + } +#endif + return (*res != NULL) ? OK : EAI_FAMILY; +#else + /* Local service, but no loopback so cannot succeed. */ + + return EAI_FAIL; +#endif /* CONFIG_NET_LOOPBACK */ + } + + /* REVISIT: no check for AI_NUMERICHOST flag. */ + + /* REVISIT: use gethostbyname_r with own buffer of refactor all + * public APIs to use internal lookup function. + */ + + hp = gethostbyname(hostname); + if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) + { + for (i = 0; hp->h_addr_list[i]; i++) + { + if (family != AF_UNSPEC && hp->h_addrtype != family) + { + /* Filter by protocol family. */ + + continue; + } + + /* REVISIT: filter by socktype and protocol not implemented. */ + + UNUSED(proto); + UNUSED(socktype); + + ai = alloc_ai(hp->h_addrtype, port, hp->h_addr_list[i]); + if (ai == NULL) + { + if (*res) + { + freeaddrinfo(*res); + } + + return EAI_MEMORY; + } + + /* REVISIT: grok canonical name. + * + * OpenGroup: "if the canonical name is not available, then ai_canonname shall + * refer to the hostname argument or a string with the same contents." + */ + + ai->ai.ai_canonname = (char *)hostname; + + /* Add result to linked list. + * TODO: RFC 3484/6724 destination address sort not implemented. + */ + + if (prev_ai) + { + prev_ai->ai.ai_next = (struct addrinfo *)ai; + } + else + { + *res = (struct addrinfo *)ai; + } + + prev_ai = ai; + } + + return OK; + } + + return EAI_AGAIN; +} + diff --git a/libs/libc/netdb/lib_gethostbyname.c b/libs/libc/netdb/lib_gethostbyname.c index 1ca9ff1079..f16fd3aceb 100644 --- a/libs/libc/netdb/lib_gethostbyname.c +++ b/libs/libc/netdb/lib_gethostbyname.c @@ -52,7 +52,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: gethostname + * Name: gethostbyname * * Description: * The gethostbyname() function returns a structure of type hostent for diff --git a/libs/libc/netdb/lib_gethostbynamer.c b/libs/libc/netdb/lib_gethostbynamer.c index 83a7817328..051d1e9739 100644 --- a/libs/libc/netdb/lib_gethostbynamer.c +++ b/libs/libc/netdb/lib_gethostbynamer.c @@ -697,7 +697,7 @@ errorout_with_herrnocode: ****************************************************************************/ /**************************************************************************** - * Name: gethostname_r + * Name: gethostbyname_r * * Description: * The gethostbyname_r() function returns a structure of type hostent for diff --git a/libs/libc/netdb/lib_getservbyname.c b/libs/libc/netdb/lib_getservbyname.c new file mode 100644 index 0000000000..3256eb3527 --- /dev/null +++ b/libs/libc/netdb/lib_getservbyname.c @@ -0,0 +1,66 @@ +/**************************************************************************** + * 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: getservbyname + ****************************************************************************/ + +FAR struct servent *getservbyname(FAR const char *name, FAR const char *proto) +{ + static struct servent ent; + static char *buf[2]; + struct servent *res; + int ret; + + ret = getservbyname_r(name, proto, &ent, (void *)buf, sizeof buf, &res); + return (ret != OK) ? NULL : res; +} + +#endif /* CONFIG_LIBC_NETDB */ + diff --git a/libs/libc/netdb/lib_getservbynamer.c b/libs/libc/netdb/lib_getservbynamer.c new file mode 100644 index 0000000000..acbefa30ca --- /dev/null +++ b/libs/libc/netdb/lib_getservbynamer.c @@ -0,0 +1,169 @@ +/**************************************************************************** + * 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 + +#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 + ****************************************************************************/ + +/* Declare your services here. TODO: read from /etc/services? + * REVISIT: This is just an example, lets not add full list here. + */ + +const static struct services_db_s g_services_db[] = +{ + { "ntp", 123, IP_PROTO_TCP }, + { "ntp", 123, IP_PROTO_UDP }, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getservbyname_r + ****************************************************************************/ + +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) +{ + char *end = ""; + int protocol; + int i; + + DEBUGASSERT(name != NULL && 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; + } + + /* Numeric port number strings are not service records. */ + + strtoul(name, &end, 10); + if (*end == '\0') + { + return ENOENT; + } + + 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; i < ARRAY_SIZE(g_services_db); i++) + { + if (strcmp(name, g_services_db[i].s_name) == 0 && + (protocol == 0 || protocol == g_services_db[i].s_protocol)) + { + result_buf->s_name = (char *)name; + result_buf->s_aliases = (void *)buf; + result_buf->s_aliases[0] = (char *)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/string/Kconfig b/libs/libc/string/Kconfig index 2ab3f3e557..3d8f967a4a 100644 --- a/libs/libc/string/Kconfig +++ b/libs/libc/string/Kconfig @@ -10,12 +10,12 @@ config LIBC_STRERROR default n ---help--- strerror() is useful because it decodes 'errno' values into a human readable - strings. But it can also require a lot of memory. If this option is selected, - strerror() will still exist in the build but it will not decode error values. - This option should be used by other logic to decide if it should use strerror() - or not. For example, the NSH application will not use strerror() if this - option is not selected; perror() will not use strerror() is this option is not - selected (see also NSH_STRERROR). + strings. But it can also require a lot of memory. If this option is not + selected, strerror() will still exist in the build but it will not decode error + values. This option should be used by other logic to decide if it should use + strerror() or not. For example, the NSH application will not use strerror() + if this option is not selected; perror() will not use strerror() is this option + is not selected (see also NSH_STRERROR). config LIBC_STRERROR_SHORT bool "Use short error descriptions in strerror()"