1/*
2 * socktoa - return a numeric host name from a sockaddr_storage structure
3 */
4#include <config.h>
5#include <sys/types.h>
6#ifdef HAVE_SYS_SOCKET_H
7#include <sys/socket.h>
8#endif
9#ifdef HAVE_NETINET_IN_H
10#include <netinet/in.h>
11#endif
12
13#include <arpa/inet.h>
14
15#include <stdio.h>
16
17#include "ntp_fp.h"
18#include "lib_strbuf.h"
19#include "ntp_stdlib.h"
20#include "ntp.h"
21#include "ntp_debug.h"
22
23
24const char *
25socktohost(
26	const sockaddr_u *sock
27	)
28{
29	const char		svc[] = "ntp";
30	char *			pbuf;
31	char *			pliar;
32	int			gni_flags;
33	struct addrinfo		hints;
34	struct addrinfo *	alist;
35	struct addrinfo *	ai;
36	sockaddr_u		addr;
37	size_t			octets;
38	int			a_info;
39	int			saved_errno;
40
41	saved_errno = socket_errno();
42
43	/* reverse the address to purported DNS name */
44	LIB_GETBUF(pbuf);
45	gni_flags = NI_DGRAM | NI_NAMEREQD;
46	if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
47			NULL, 0, gni_flags)) {
48		errno = saved_errno;
49		return stoa(sock);	/* use address */
50	}
51
52	TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
53
54	/*
55	 * Resolve the reversed name and make sure the reversed address
56	 * is among the results.
57	 */
58	ZERO(hints);
59	hints.ai_family = AF(sock);
60	hints.ai_protocol = IPPROTO_UDP;
61	hints.ai_socktype = SOCK_DGRAM;
62	hints.ai_flags = 0;
63	alist = NULL;
64
65	a_info = getaddrinfo(pbuf, svc, &hints, &alist);
66	if (a_info == EAI_NONAME
67#ifdef EAI_NODATA
68	    || a_info == EAI_NODATA
69#endif
70	   ) {
71		hints.ai_flags = AI_CANONNAME;
72#ifdef AI_ADDRCONFIG
73		hints.ai_flags |= AI_ADDRCONFIG;
74#endif
75		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
76	}
77#ifdef AI_ADDRCONFIG
78	/* Some older implementations don't like AI_ADDRCONFIG. */
79	if (a_info == EAI_BADFLAGS) {
80		hints.ai_flags &= ~AI_ADDRCONFIG;
81		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
82	}
83#endif
84	if (a_info)
85		goto forward_fail;
86
87	INSIST(alist != NULL);
88
89	for (ai = alist; ai != NULL; ai = ai->ai_next) {
90		/*
91		 * Make a convenience sockaddr_u copy from ai->ai_addr
92		 * because casting from sockaddr * to sockaddr_u * is
93		 * risking alignment problems on platforms where
94		 * sockaddr_u has stricter alignment than sockaddr,
95		 * such as sparc.
96		 */
97		ZERO_SOCK(&addr);
98		octets = min(sizeof(addr), ai->ai_addrlen);
99		memcpy(&addr, ai->ai_addr, octets);
100		if (SOCK_EQ(sock, &addr))
101			break;
102	}
103	freeaddrinfo(alist);
104
105	if (ai != NULL) {
106		errno = saved_errno;
107		return pbuf;	/* forward check passed */
108	}
109
110    forward_fail:
111	TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
112		  gai_strerror(a_info)));
113	LIB_GETBUF(pliar);
114	snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
115
116	errno = saved_errno;
117	return pliar;
118}
119