freebsd-dev/libntp/socktohost.c
2016-01-08 08:06:14 +00:00

119 lines
2.5 KiB
C

/*
* socktoa - return a numeric host name from a sockaddr_storage structure
*/
#include <config.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <arpa/inet.h>
#include <stdio.h>
#include "ntp_fp.h"
#include "lib_strbuf.h"
#include "ntp_stdlib.h"
#include "ntp.h"
#include "ntp_debug.h"
const char *
socktohost(
const sockaddr_u *sock
)
{
const char svc[] = "ntp";
char * pbuf;
char * pliar;
int gni_flags;
struct addrinfo hints;
struct addrinfo * alist;
struct addrinfo * ai;
sockaddr_u addr;
size_t octets;
int a_info;
int saved_errno;
saved_errno = socket_errno();
/* reverse the address to purported DNS name */
LIB_GETBUF(pbuf);
gni_flags = NI_DGRAM | NI_NAMEREQD;
if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
NULL, 0, gni_flags)) {
errno = saved_errno;
return stoa(sock); /* use address */
}
TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
/*
* Resolve the reversed name and make sure the reversed address
* is among the results.
*/
ZERO(hints);
hints.ai_family = AF(sock);
hints.ai_protocol = IPPROTO_UDP;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
alist = NULL;
a_info = getaddrinfo(pbuf, svc, &hints, &alist);
if (a_info == EAI_NONAME
#ifdef EAI_NODATA
|| a_info == EAI_NODATA
#endif
) {
hints.ai_flags = AI_CANONNAME;
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif
a_info = getaddrinfo(pbuf, svc, &hints, &alist);
}
#ifdef AI_ADDRCONFIG
/* Some older implementations don't like AI_ADDRCONFIG. */
if (a_info == EAI_BADFLAGS) {
hints.ai_flags &= ~AI_ADDRCONFIG;
a_info = getaddrinfo(pbuf, svc, &hints, &alist);
}
#endif
if (a_info)
goto forward_fail;
INSIST(alist != NULL);
for (ai = alist; ai != NULL; ai = ai->ai_next) {
/*
* Make a convenience sockaddr_u copy from ai->ai_addr
* because casting from sockaddr * to sockaddr_u * is
* risking alignment problems on platforms where
* sockaddr_u has stricter alignment than sockaddr,
* such as sparc.
*/
ZERO_SOCK(&addr);
octets = min(sizeof(addr), ai->ai_addrlen);
memcpy(&addr, ai->ai_addr, octets);
if (SOCK_EQ(sock, &addr))
break;
}
freeaddrinfo(alist);
if (ai != NULL) {
errno = saved_errno;
return pbuf; /* forward check passed */
}
forward_fail:
TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
gai_strerror(a_info)));
LIB_GETBUF(pliar);
snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
errno = saved_errno;
return pliar;
}