xref: /freebsd/contrib/ntp/libntp/socktohost.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
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 
24 const char *
25 socktohost(
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 
40 	/* reverse the address to purported DNS name */
41 	LIB_GETBUF(pbuf);
42 	gni_flags = NI_DGRAM | NI_NAMEREQD;
43 	if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
44 			NULL, 0, gni_flags))
45 		return stoa(sock);	/* use address */
46 
47 	TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
48 
49 	/*
50 	 * Resolve the reversed name and make sure the reversed address
51 	 * is among the results.
52 	 */
53 	ZERO(hints);
54 	hints.ai_family = AF(sock);
55 	hints.ai_protocol = IPPROTO_UDP;
56 	hints.ai_socktype = SOCK_DGRAM;
57 	hints.ai_flags = 0;
58 	alist = NULL;
59 
60 	a_info = getaddrinfo(pbuf, svc, &hints, &alist);
61 	if (a_info == EAI_NONAME
62 #ifdef EAI_NODATA
63 	    || a_info == EAI_NODATA
64 #endif
65 	   ) {
66 		hints.ai_flags = AI_CANONNAME;
67 #ifdef AI_ADDRCONFIG
68 		hints.ai_flags |= AI_ADDRCONFIG;
69 #endif
70 		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
71 	}
72 #ifdef AI_ADDRCONFIG
73 	/* Some older implementations don't like AI_ADDRCONFIG. */
74 	if (a_info == EAI_BADFLAGS) {
75 		hints.ai_flags &= ~AI_ADDRCONFIG;
76 		a_info = getaddrinfo(pbuf, svc, &hints, &alist);
77 	}
78 #endif
79 	if (a_info)
80 		goto forward_fail;
81 
82 	INSIST(alist != NULL);
83 
84 	for (ai = alist; ai != NULL; ai = ai->ai_next) {
85 		/*
86 		 * Make a convenience sockaddr_u copy from ai->ai_addr
87 		 * because casting from sockaddr * to sockaddr_u * is
88 		 * risking alignment problems on platforms where
89 		 * sockaddr_u has stricter alignment than sockaddr,
90 		 * such as sparc.
91 		 */
92 		ZERO_SOCK(&addr);
93 		octets = min(sizeof(addr), ai->ai_addrlen);
94 		memcpy(&addr, ai->ai_addr, octets);
95 		if (SOCK_EQ(sock, &addr))
96 			break;
97 	}
98 	freeaddrinfo(alist);
99 
100 	if (ai != NULL)
101 		return pbuf;	/* forward check passed */
102 
103     forward_fail:
104 	TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
105 		  gai_strerror(a_info)));
106 	LIB_GETBUF(pliar);
107 	snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
108 
109 	return pliar;
110 }
111