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