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 } 119