socktohost.c revision 293894
1130561Sobrien/*
2130561Sobrien * socktoa - return a numeric host name from a sockaddr_storage structure
3130561Sobrien */
4130561Sobrien#include <config.h>
5130561Sobrien#include <sys/types.h>
6130561Sobrien#ifdef HAVE_SYS_SOCKET_H
7130561Sobrien#include <sys/socket.h>
8130561Sobrien#endif
9130561Sobrien#ifdef HAVE_NETINET_IN_H
10130561Sobrien#include <netinet/in.h>
11130561Sobrien#endif
12130561Sobrien
13130561Sobrien#include <arpa/inet.h>
14130561Sobrien
15130561Sobrien#include <stdio.h>
16130561Sobrien
17130561Sobrien#include "ntp_fp.h"
18218822Sdim#include "lib_strbuf.h"
19130561Sobrien#include "ntp_stdlib.h"
20130561Sobrien#include "ntp.h"
21130561Sobrien#include "ntp_debug.h"
22130561Sobrien
23130561Sobrien
24130561Sobrienconst char *
25130561Sobriensocktohost(
26130561Sobrien	const sockaddr_u *sock
27130561Sobrien	)
28130561Sobrien{
29130561Sobrien	const char		svc[] = "ntp";
30130561Sobrien	char *			pbuf;
31130561Sobrien	char *			pliar;
32130561Sobrien	int			gni_flags;
33130561Sobrien	struct addrinfo		hints;
34130561Sobrien	struct addrinfo *	alist;
35130561Sobrien	struct addrinfo *	ai;
36130561Sobrien	sockaddr_u		addr;
37130561Sobrien	size_t			octets;
38130561Sobrien	int			a_info;
39130561Sobrien	int			saved_errno;
40130561Sobrien
41130561Sobrien	saved_errno = socket_errno();
42130561Sobrien
43130561Sobrien	/* reverse the address to purported DNS name */
44130561Sobrien	LIB_GETBUF(pbuf);
45130561Sobrien	gni_flags = NI_DGRAM | NI_NAMEREQD;
46130561Sobrien	if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
47130561Sobrien			NULL, 0, gni_flags)) {
48130561Sobrien		errno = saved_errno;
49130561Sobrien		return stoa(sock);	/* use address */
50130561Sobrien	}
51130561Sobrien
52130561Sobrien	TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
53130561Sobrien
54130561Sobrien	/*
55130561Sobrien	 * Resolve the reversed name and make sure the reversed address
56130561Sobrien	 * is among the results.
57130561Sobrien	 */
58130561Sobrien	ZERO(hints);
59130561Sobrien	hints.ai_family = AF(sock);
60130561Sobrien	hints.ai_protocol = IPPROTO_UDP;
61130561Sobrien	hints.ai_socktype = SOCK_DGRAM;
62130561Sobrien	hints.ai_flags = 0;
63130561Sobrien	alist = NULL;
64130561Sobrien
65130561Sobrien	a_info = getaddrinfo(pbuf, svc, &hints, &alist);
66130561Sobrien	if (a_info == EAI_NONAME
67130561Sobrien#ifdef EAI_NODATA
68130561Sobrien	    || a_info == EAI_NODATA
69130561Sobrien#endif
70130561Sobrien	   ) {
71130561Sobrien		hints.ai_flags = AI_CANONNAME;
72130561Sobrien#ifdef AI_ADDRCONFIG
73130561Sobrien		hints.ai_flags |= AI_ADDRCONFIG;
74130561Sobrien#endif
75130561Sobrien		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
76130561Sobrien	}
77130561Sobrien#ifdef AI_ADDRCONFIG
78130561Sobrien	/* Some older implementations don't like AI_ADDRCONFIG. */
79130561Sobrien	if (a_info == EAI_BADFLAGS) {
80130561Sobrien		hints.ai_flags &= ~AI_ADDRCONFIG;
81130561Sobrien		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
82130561Sobrien	}
83130561Sobrien#endif
84130561Sobrien	if (a_info)
85130561Sobrien		goto forward_fail;
86130561Sobrien
87130561Sobrien	INSIST(alist != NULL);
88130561Sobrien
89130561Sobrien	for (ai = alist; ai != NULL; ai = ai->ai_next) {
90130561Sobrien		/*
91130561Sobrien		 * Make a convenience sockaddr_u copy from ai->ai_addr
92130561Sobrien		 * because casting from sockaddr * to sockaddr_u * is
93130561Sobrien		 * risking alignment problems on platforms where
94130561Sobrien		 * sockaddr_u has stricter alignment than sockaddr,
95130561Sobrien		 * such as sparc.
96130561Sobrien		 */
97130561Sobrien		ZERO_SOCK(&addr);
98130561Sobrien		octets = min(sizeof(addr), ai->ai_addrlen);
99130561Sobrien		memcpy(&addr, ai->ai_addr, octets);
100130561Sobrien		if (SOCK_EQ(sock, &addr))
101130561Sobrien			break;
102130561Sobrien	}
103130561Sobrien	freeaddrinfo(alist);
104130561Sobrien
105130561Sobrien	if (ai != NULL) {
106130561Sobrien		errno = saved_errno;
107130561Sobrien		return pbuf;	/* forward check passed */
108130561Sobrien	}
109130561Sobrien
110130561Sobrien    forward_fail:
111130561Sobrien	TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
112130561Sobrien		  gai_strerror(a_info)));
113130561Sobrien	LIB_GETBUF(pliar);
114130561Sobrien	snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
115130561Sobrien
116130561Sobrien	errno = saved_errno;
117130561Sobrien	return pliar;
118130561Sobrien}
119130561Sobrien