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