1132451Sroberto/*
2132451Sroberto * socktoa - return a numeric host name from a sockaddr_storage structure
3132451Sroberto */
4285612Sdelphij#include <config.h>
5132451Sroberto#include <sys/types.h>
6285612Sdelphij#ifdef HAVE_SYS_SOCKET_H
7132451Sroberto#include <sys/socket.h>
8285612Sdelphij#endif
9285612Sdelphij#ifdef HAVE_NETINET_IN_H
10132451Sroberto#include <netinet/in.h>
11285612Sdelphij#endif
12132451Sroberto
13132451Sroberto#include <arpa/inet.h>
14132451Sroberto
15132451Sroberto#include <stdio.h>
16132451Sroberto
17132451Sroberto#include "ntp_fp.h"
18132451Sroberto#include "lib_strbuf.h"
19132451Sroberto#include "ntp_stdlib.h"
20132451Sroberto#include "ntp.h"
21285612Sdelphij#include "ntp_debug.h"
22132451Sroberto
23132451Sroberto
24285612Sdelphijconst char *
25132451Srobertosocktohost(
26285612Sdelphij	const sockaddr_u *sock
27132451Sroberto	)
28132451Sroberto{
29285612Sdelphij	const char		svc[] = "ntp";
30285612Sdelphij	char *			pbuf;
31285612Sdelphij	char *			pliar;
32285612Sdelphij	int			gni_flags;
33285612Sdelphij	struct addrinfo		hints;
34285612Sdelphij	struct addrinfo *	alist;
35285612Sdelphij	struct addrinfo *	ai;
36285612Sdelphij	sockaddr_u		addr;
37285612Sdelphij	size_t			octets;
38285612Sdelphij	int			a_info;
39293650Sglebius	int			saved_errno;
40132451Sroberto
41293650Sglebius	saved_errno = socket_errno();
42293650Sglebius
43285612Sdelphij	/* reverse the address to purported DNS name */
44285612Sdelphij	LIB_GETBUF(pbuf);
45285612Sdelphij	gni_flags = NI_DGRAM | NI_NAMEREQD;
46285612Sdelphij	if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
47293650Sglebius			NULL, 0, gni_flags)) {
48293650Sglebius		errno = saved_errno;
49285612Sdelphij		return stoa(sock);	/* use address */
50293650Sglebius	}
51132451Sroberto
52285612Sdelphij	TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
53285612Sdelphij
54285612Sdelphij	/*
55285612Sdelphij	 * Resolve the reversed name and make sure the reversed address
56285612Sdelphij	 * is among the results.
57285612Sdelphij	 */
58285612Sdelphij	ZERO(hints);
59285612Sdelphij	hints.ai_family = AF(sock);
60285612Sdelphij	hints.ai_protocol = IPPROTO_UDP;
61285612Sdelphij	hints.ai_socktype = SOCK_DGRAM;
62285612Sdelphij	hints.ai_flags = 0;
63285612Sdelphij	alist = NULL;
64285612Sdelphij
65285612Sdelphij	a_info = getaddrinfo(pbuf, svc, &hints, &alist);
66285612Sdelphij	if (a_info == EAI_NONAME
67285612Sdelphij#ifdef EAI_NODATA
68285612Sdelphij	    || a_info == EAI_NODATA
69285612Sdelphij#endif
70285612Sdelphij	   ) {
71285612Sdelphij		hints.ai_flags = AI_CANONNAME;
72285612Sdelphij#ifdef AI_ADDRCONFIG
73285612Sdelphij		hints.ai_flags |= AI_ADDRCONFIG;
74285612Sdelphij#endif
75285612Sdelphij		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
76285612Sdelphij	}
77285612Sdelphij#ifdef AI_ADDRCONFIG
78285612Sdelphij	/* Some older implementations don't like AI_ADDRCONFIG. */
79285612Sdelphij	if (a_info == EAI_BADFLAGS) {
80285612Sdelphij		hints.ai_flags &= ~AI_ADDRCONFIG;
81285612Sdelphij		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
82285612Sdelphij	}
83285612Sdelphij#endif
84285612Sdelphij	if (a_info)
85285612Sdelphij		goto forward_fail;
86285612Sdelphij
87289997Sglebius	INSIST(alist != NULL);
88285612Sdelphij
89285612Sdelphij	for (ai = alist; ai != NULL; ai = ai->ai_next) {
90285612Sdelphij		/*
91285612Sdelphij		 * Make a convenience sockaddr_u copy from ai->ai_addr
92285612Sdelphij		 * because casting from sockaddr * to sockaddr_u * is
93285612Sdelphij		 * risking alignment problems on platforms where
94285612Sdelphij		 * sockaddr_u has stricter alignment than sockaddr,
95285612Sdelphij		 * such as sparc.
96285612Sdelphij		 */
97285612Sdelphij		ZERO_SOCK(&addr);
98285612Sdelphij		octets = min(sizeof(addr), ai->ai_addrlen);
99285612Sdelphij		memcpy(&addr, ai->ai_addr, octets);
100285612Sdelphij		if (SOCK_EQ(sock, &addr))
101285612Sdelphij			break;
102285612Sdelphij	}
103285612Sdelphij	freeaddrinfo(alist);
104285612Sdelphij
105293650Sglebius	if (ai != NULL) {
106293650Sglebius		errno = saved_errno;
107285612Sdelphij		return pbuf;	/* forward check passed */
108293650Sglebius	}
109285612Sdelphij
110285612Sdelphij    forward_fail:
111285612Sdelphij	TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
112285612Sdelphij		  gai_strerror(a_info)));
113285612Sdelphij	LIB_GETBUF(pliar);
114285612Sdelphij	snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
115285612Sdelphij
116293650Sglebius	errno = saved_errno;
117285612Sdelphij	return pliar;
118132451Sroberto}
119