Skip to content

Commit

Permalink
libs/libc/netdb: Implemented the netdb functions getnameinfo(), getse…
Browse files Browse the repository at this point in the history
…rvbyport(), and getservbyport_r().
  • Loading branch information
michi-jung authored and gregory-nutt committed Jun 30, 2019
1 parent 53119cd commit b9d2e51
Show file tree
Hide file tree
Showing 9 changed files with 475 additions and 44 deletions.
14 changes: 8 additions & 6 deletions include/netdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions libs/libc/netdb/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions libs/libc/netdb/lib_dns.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
31 changes: 21 additions & 10 deletions libs/libc/netdb/lib_gethostbyaddrr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
****************************************************************************/
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -356,8 +371,8 @@ int lib_hostfile_lookup(FAR const void *addr, socklen_t len, int type,
* 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.
Expand All @@ -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);

Expand Down
220 changes: 220 additions & 0 deletions libs/libc/netdb/lib_getnameinfo.c
Original file line number Diff line number Diff line change
@@ -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 */
Loading

0 comments on commit b9d2e51

Please sign in to comment.