libs/libc/netdb: Add getaddrinfo() and friends.

This commit is contained in:
Juha Niskanen 2018-06-08 07:07:21 -06:00 committed by Gregory Nutt
parent 5c8a975d79
commit 1f4a1eab6d
14 changed files with 789 additions and 35 deletions

2
TODO
View File

@ -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

View File

@ -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 <gnutt@nuttx.org>
*
* 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 <netdb.h> 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 <netdb.h> 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 <netdb.h> 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 */

View File

@ -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

View File

@ -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

View File

@ -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 <gnutt@nuttx.org>

View File

@ -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 <gnutt@nuttx.org>

View File

@ -0,0 +1,68 @@
/****************************************************************************
* libs/libc/netdb/lib_freeaddrinfo.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Juha Niskanen <juha.niskanen@haltian.com>
*
* 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 <nuttx/config.h>
#include <netdb.h>
#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);
}

View File

@ -0,0 +1,125 @@
/****************************************************************************
* libs/libc/netdb/lib_gaistrerror.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Juha Niskanen <juha.niskanen@haltian.com>
*
* 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 <nuttx/config.h>
#include <stdint.h>
#include <netdb.h>
/****************************************************************************
* 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";
}

View File

@ -0,0 +1,311 @@
/****************************************************************************
* libs/libc/netdb/lib_getaddrinfo.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Juha Niskanen <juha.niskanen@haltian.com>
*
* 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 <nuttx/config.h>
#include <string.h>
#include <arpa/inet.h>
#include <nuttx/net/loopback.h>
#include <netdb.h>
#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;
}

View File

@ -52,7 +52,7 @@
****************************************************************************/
/****************************************************************************
* Name: gethostname
* Name: gethostbyname
*
* Description:
* The gethostbyname() function returns a structure of type hostent for

View File

@ -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

View File

@ -0,0 +1,66 @@
/****************************************************************************
* libs/libc/netdb/lib_getservbyname.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Juha Niskanen <juha.niskanen@haltian.com>
*
* 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 <nuttx/config.h>
#include <netdb.h>
#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 */

View File

@ -0,0 +1,169 @@
/****************************************************************************
* libs/libc/netdb/lib_getservbynamer.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Juha Niskanen <juha.niskanen@haltian.com>
*
* 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 <nuttx/config.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/net/ip.h>
#include <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
****************************************************************************/
/* 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 */

View File

@ -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()"