diff options
Diffstat (limited to 'contrib/ntp/libntp/socktohost.c')
-rw-r--r-- | contrib/ntp/libntp/socktohost.c | 95 |
1 files changed, 87 insertions, 8 deletions
diff --git a/contrib/ntp/libntp/socktohost.c b/contrib/ntp/libntp/socktohost.c index 7aafdc7..c61e571 100644 --- a/contrib/ntp/libntp/socktohost.c +++ b/contrib/ntp/libntp/socktohost.c @@ -1,9 +1,14 @@ /* * 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> @@ -13,19 +18,93 @@ #include "lib_strbuf.h" #include "ntp_stdlib.h" #include "ntp.h" +#include "ntp_debug.h" -char * +const char * socktohost( - struct sockaddr_storage* sock + const sockaddr_u *sock ) { - register char *buffer; + 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; - LIB_GETBUF(buffer); - if (getnameinfo((struct sockaddr *)sock, SOCKLEN(sock), buffer, - LIB_BUFLENGTH /* NI_MAXHOST*/, NULL, 0, 0)) - return stoa(sock); + /* 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)) + return stoa(sock); /* use address */ - return buffer; + 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; + + NTP_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) + 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); + + return pliar; } |