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 * 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