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