1132451Sroberto/*
2132451Sroberto * socktoa - return a numeric host name from a sockaddr_storage structure
3132451Sroberto */
4290001Sglebius#include <config.h>
5132451Sroberto#include <sys/types.h>
6290001Sglebius#ifdef HAVE_SYS_SOCKET_H
7132451Sroberto#include <sys/socket.h>
8290001Sglebius#endif
9290001Sglebius#ifdef HAVE_NETINET_IN_H
10132451Sroberto#include <netinet/in.h>
11290001Sglebius#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"
21290001Sglebius#include "ntp_debug.h"
22132451Sroberto
23132451Sroberto
24290001Sglebiusconst char *
25132451Srobertosocktohost(
26290001Sglebius	const sockaddr_u *sock
27132451Sroberto	)
28132451Sroberto{
29290001Sglebius	const char		svc[] = "ntp";
30290001Sglebius	char *			pbuf;
31290001Sglebius	char *			pliar;
32290001Sglebius	int			gni_flags;
33290001Sglebius	struct addrinfo		hints;
34290001Sglebius	struct addrinfo *	alist;
35290001Sglebius	struct addrinfo *	ai;
36290001Sglebius	sockaddr_u		addr;
37290001Sglebius	size_t			octets;
38290001Sglebius	int			a_info;
39293896Sglebius	int			saved_errno;
40132451Sroberto
41293896Sglebius	saved_errno = socket_errno();
42293896Sglebius
43290001Sglebius	/* reverse the address to purported DNS name */
44290001Sglebius	LIB_GETBUF(pbuf);
45290001Sglebius	gni_flags = NI_DGRAM | NI_NAMEREQD;
46290001Sglebius	if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
47293896Sglebius			NULL, 0, gni_flags)) {
48293896Sglebius		errno = saved_errno;
49290001Sglebius		return stoa(sock);	/* use address */
50293896Sglebius	}
51132451Sroberto
52290001Sglebius	TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
53290001Sglebius
54290001Sglebius	/*
55290001Sglebius	 * Resolve the reversed name and make sure the reversed address
56290001Sglebius	 * is among the results.
57290001Sglebius	 */
58290001Sglebius	ZERO(hints);
59290001Sglebius	hints.ai_family = AF(sock);
60290001Sglebius	hints.ai_protocol = IPPROTO_UDP;
61290001Sglebius	hints.ai_socktype = SOCK_DGRAM;
62290001Sglebius	hints.ai_flags = 0;
63290001Sglebius	alist = NULL;
64290001Sglebius
65290001Sglebius	a_info = getaddrinfo(pbuf, svc, &hints, &alist);
66290001Sglebius	if (a_info == EAI_NONAME
67290001Sglebius#ifdef EAI_NODATA
68290001Sglebius	    || a_info == EAI_NODATA
69290001Sglebius#endif
70290001Sglebius	   ) {
71290001Sglebius		hints.ai_flags = AI_CANONNAME;
72290001Sglebius#ifdef AI_ADDRCONFIG
73290001Sglebius		hints.ai_flags |= AI_ADDRCONFIG;
74290001Sglebius#endif
75290001Sglebius		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
76290001Sglebius	}
77290001Sglebius#ifdef AI_ADDRCONFIG
78290001Sglebius	/* Some older implementations don't like AI_ADDRCONFIG. */
79290001Sglebius	if (a_info == EAI_BADFLAGS) {
80290001Sglebius		hints.ai_flags &= ~AI_ADDRCONFIG;
81290001Sglebius		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
82290001Sglebius	}
83290001Sglebius#endif
84290001Sglebius	if (a_info)
85290001Sglebius		goto forward_fail;
86290001Sglebius
87290001Sglebius	INSIST(alist != NULL);
88290001Sglebius
89290001Sglebius	for (ai = alist; ai != NULL; ai = ai->ai_next) {
90290001Sglebius		/*
91290001Sglebius		 * Make a convenience sockaddr_u copy from ai->ai_addr
92290001Sglebius		 * because casting from sockaddr * to sockaddr_u * is
93290001Sglebius		 * risking alignment problems on platforms where
94290001Sglebius		 * sockaddr_u has stricter alignment than sockaddr,
95290001Sglebius		 * such as sparc.
96290001Sglebius		 */
97290001Sglebius		ZERO_SOCK(&addr);
98290001Sglebius		octets = min(sizeof(addr), ai->ai_addrlen);
99290001Sglebius		memcpy(&addr, ai->ai_addr, octets);
100290001Sglebius		if (SOCK_EQ(sock, &addr))
101290001Sglebius			break;
102290001Sglebius	}
103290001Sglebius	freeaddrinfo(alist);
104290001Sglebius
105293896Sglebius	if (ai != NULL) {
106293896Sglebius		errno = saved_errno;
107290001Sglebius		return pbuf;	/* forward check passed */
108293896Sglebius	}
109290001Sglebius
110290001Sglebius    forward_fail:
111290001Sglebius	TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
112290001Sglebius		  gai_strerror(a_info)));
113290001Sglebius	LIB_GETBUF(pliar);
114290001Sglebius	snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
115290001Sglebius
116293896Sglebius	errno = saved_errno;
117290001Sglebius	return pliar;
118132451Sroberto}
119