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