libs/libc/netdb: Implemented the netdb functions getnameinfo(), getservbyport(), and getservbyport_r().

This commit is contained in:
Michael Jung 2019-06-30 15:12:34 -06:00 committed by Gregory Nutt
parent 53119cd476
commit b9d2e516ef
9 changed files with 475 additions and 44 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,220 @@
/****************************************************************************
* libc/netdb/lib_getnameinfo.c
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
* Author: Michael Jung <mijung@gmx.net>
*
* 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 <string.h>
#include <stdio.h>
#include <errno.h>
#include <arpa/inet.h>
#include <assert.h>
#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 */

View File

@ -47,27 +47,10 @@
#include <netdb.h>
#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 */

View File

@ -0,0 +1,69 @@
/****************************************************************************
* libs/libc/netdb/lib_getservbyport.c
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
* Author: Michael Jung <mijung@gmx.net>
*
* Based on 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: 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 */

View File

@ -0,0 +1,132 @@
/****************************************************************************
* libs/libc/netdb/lib_getservbyportr.c
*
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
* Author: Michael Jung <mijung@gmx.net>
*
* Based on 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>
#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 */

View File

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