1132451Sroberto/*
2132451Sroberto * socktoa - return a numeric host name from a sockaddr_storage structure
3132451Sroberto */
4290000Sglebius#include <config.h>
5132451Sroberto#include <sys/types.h>
6290000Sglebius#ifdef HAVE_SYS_SOCKET_H
7132451Sroberto#include <sys/socket.h>
8290000Sglebius#endif
9290000Sglebius#ifdef HAVE_NETINET_IN_H
10132451Sroberto#include <netinet/in.h>
11290000Sglebius#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"
21290000Sglebius#include "ntp_debug.h"
22132451Sroberto
23132451Sroberto
24290000Sglebiusconst char *
25132451Srobertosocktohost(
26290000Sglebius	const sockaddr_u *sock
27132451Sroberto	)
28132451Sroberto{
29290000Sglebius	const char		svc[] = "ntp";
30290000Sglebius	char *			pbuf;
31290000Sglebius	char *			pliar;
32290000Sglebius	int			gni_flags;
33290000Sglebius	struct addrinfo		hints;
34290000Sglebius	struct addrinfo *	alist;
35290000Sglebius	struct addrinfo *	ai;
36290000Sglebius	sockaddr_u		addr;
37290000Sglebius	size_t			octets;
38290000Sglebius	int			a_info;
39293894Sglebius	int			saved_errno;
40132451Sroberto
41293894Sglebius	saved_errno = socket_errno();
42293894Sglebius
43290000Sglebius	/* reverse the address to purported DNS name */
44290000Sglebius	LIB_GETBUF(pbuf);
45290000Sglebius	gni_flags = NI_DGRAM | NI_NAMEREQD;
46290000Sglebius	if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
47293894Sglebius			NULL, 0, gni_flags)) {
48293894Sglebius		errno = saved_errno;
49290000Sglebius		return stoa(sock);	/* use address */
50293894Sglebius	}
51132451Sroberto
52290000Sglebius	TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
53290000Sglebius
54290000Sglebius	/*
55290000Sglebius	 * Resolve the reversed name and make sure the reversed address
56290000Sglebius	 * is among the results.
57290000Sglebius	 */
58290000Sglebius	ZERO(hints);
59290000Sglebius	hints.ai_family = AF(sock);
60290000Sglebius	hints.ai_protocol = IPPROTO_UDP;
61290000Sglebius	hints.ai_socktype = SOCK_DGRAM;
62290000Sglebius	hints.ai_flags = 0;
63290000Sglebius	alist = NULL;
64290000Sglebius
65290000Sglebius	a_info = getaddrinfo(pbuf, svc, &hints, &alist);
66290000Sglebius	if (a_info == EAI_NONAME
67290000Sglebius#ifdef EAI_NODATA
68290000Sglebius	    || a_info == EAI_NODATA
69290000Sglebius#endif
70290000Sglebius	   ) {
71290000Sglebius		hints.ai_flags = AI_CANONNAME;
72290000Sglebius#ifdef AI_ADDRCONFIG
73290000Sglebius		hints.ai_flags |= AI_ADDRCONFIG;
74290000Sglebius#endif
75290000Sglebius		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
76290000Sglebius	}
77290000Sglebius#ifdef AI_ADDRCONFIG
78290000Sglebius	/* Some older implementations don't like AI_ADDRCONFIG. */
79290000Sglebius	if (a_info == EAI_BADFLAGS) {
80290000Sglebius		hints.ai_flags &= ~AI_ADDRCONFIG;
81290000Sglebius		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
82290000Sglebius	}
83290000Sglebius#endif
84290000Sglebius	if (a_info)
85290000Sglebius		goto forward_fail;
86290000Sglebius
87290000Sglebius	INSIST(alist != NULL);
88290000Sglebius
89290000Sglebius	for (ai = alist; ai != NULL; ai = ai->ai_next) {
90290000Sglebius		/*
91290000Sglebius		 * Make a convenience sockaddr_u copy from ai->ai_addr
92290000Sglebius		 * because casting from sockaddr * to sockaddr_u * is
93290000Sglebius		 * risking alignment problems on platforms where
94290000Sglebius		 * sockaddr_u has stricter alignment than sockaddr,
95290000Sglebius		 * such as sparc.
96290000Sglebius		 */
97290000Sglebius		ZERO_SOCK(&addr);
98290000Sglebius		octets = min(sizeof(addr), ai->ai_addrlen);
99290000Sglebius		memcpy(&addr, ai->ai_addr, octets);
100290000Sglebius		if (SOCK_EQ(sock, &addr))
101290000Sglebius			break;
102290000Sglebius	}
103290000Sglebius	freeaddrinfo(alist);
104290000Sglebius
105293894Sglebius	if (ai != NULL) {
106293894Sglebius		errno = saved_errno;
107290000Sglebius		return pbuf;	/* forward check passed */
108293894Sglebius	}
109290000Sglebius
110290000Sglebius    forward_fail:
111290000Sglebius	TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
112290000Sglebius		  gai_strerror(a_info)));
113290000Sglebius	LIB_GETBUF(pliar);
114290000Sglebius	snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
115290000Sglebius
116293894Sglebius	errno = saved_errno;
117290000Sglebius	return pliar;
118132451Sroberto}
119