1 /* 2 * socktoa.c socktoa(), sockporttoa(), and sock_hash() 3 */ 4 5 #ifdef HAVE_CONFIG_H 6 #include <config.h> 7 #endif 8 9 #include <sys/types.h> 10 #ifdef HAVE_SYS_SOCKET_H 11 #include <sys/socket.h> 12 #endif 13 #ifdef HAVE_NETINET_IN_H 14 #include <netinet/in.h> 15 #endif 16 17 #include <stdio.h> 18 #include <arpa/inet.h> 19 #include <isc/result.h> 20 #include <isc/netaddr.h> 21 #include <isc/sockaddr.h> 22 23 #include "ntp_fp.h" 24 #include "lib_strbuf.h" 25 #include "ntp_stdlib.h" 26 #include "ntp.h" 27 28 /* 29 * socktoa - return a numeric host name from a sockaddr_storage structure 30 */ 31 const char * 32 socktoa( 33 const sockaddr_u *sock 34 ) 35 { 36 int saved_errno; 37 char * res; 38 char * addr; 39 u_long scope; 40 41 saved_errno = socket_errno(); 42 LIB_GETBUF(res); 43 44 if (NULL == sock) { 45 strlcpy(res, "(null)", LIB_BUFLENGTH); 46 } else { 47 switch(AF(sock)) { 48 49 case AF_INET: 50 case AF_UNSPEC: 51 inet_ntop(AF_INET, PSOCK_ADDR4(sock), res, 52 LIB_BUFLENGTH); 53 break; 54 55 case AF_INET6: 56 inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res, 57 LIB_BUFLENGTH); 58 scope = SCOPE_VAR(sock); 59 if (0 != scope && !strchr(res, '%')) { 60 addr = res; 61 LIB_GETBUF(res); 62 snprintf(res, LIB_BUFLENGTH, "%s%%%lu", 63 addr, scope); 64 res[LIB_BUFLENGTH - 1] = '\0'; 65 } 66 break; 67 68 default: 69 snprintf(res, LIB_BUFLENGTH, 70 "(socktoa unknown family %d)", 71 AF(sock)); 72 } 73 } 74 errno = saved_errno; 75 76 return res; 77 } 78 79 80 const char * 81 sockporttoa( 82 const sockaddr_u *sock 83 ) 84 { 85 int saved_errno; 86 const char * atext; 87 char * buf; 88 89 saved_errno = socket_errno(); 90 atext = socktoa(sock); 91 LIB_GETBUF(buf); 92 snprintf(buf, LIB_BUFLENGTH, 93 (IS_IPV6(sock)) 94 ? "[%s]:%hu" 95 : "%s:%hu", 96 atext, SRCPORT(sock)); 97 errno = saved_errno; 98 99 return buf; 100 } 101 102 103 /* 104 * sock_hash - hash a sockaddr_u structure 105 */ 106 u_short 107 sock_hash( 108 const sockaddr_u *addr 109 ) 110 { 111 u_int hashVal; 112 u_int j; 113 size_t len; 114 const u_char *pch; 115 116 hashVal = 0; 117 len = 0; 118 119 /* 120 * We can't just hash the whole thing because there are hidden 121 * fields in sockaddr_in6 that might be filled in by recvfrom(), 122 * so just use the family, port and address. 123 */ 124 pch = (const void *)&AF(addr); 125 hashVal = 37 * hashVal + *pch; 126 if (sizeof(AF(addr)) > 1) { 127 pch++; 128 hashVal = 37 * hashVal + *pch; 129 } 130 switch(AF(addr)) { 131 case AF_INET: 132 pch = (const void *)&SOCK_ADDR4(addr); 133 len = sizeof(SOCK_ADDR4(addr)); 134 break; 135 136 case AF_INET6: 137 pch = (const void *)&SOCK_ADDR6(addr); 138 len = sizeof(SOCK_ADDR6(addr)); 139 break; 140 } 141 142 for (j = 0; j < len ; j++) 143 hashVal = 37 * hashVal + pch[j]; 144 145 return (u_short)(hashVal & USHRT_MAX); 146 } 147 148 149 int 150 sockaddr_masktoprefixlen( 151 const sockaddr_u * psa 152 ) 153 { 154 isc_netaddr_t isc_na; 155 isc_sockaddr_t isc_sa; 156 u_int pfxlen; 157 isc_result_t result; 158 int rc; 159 160 ZERO(isc_sa); 161 memcpy(&isc_sa.type, psa, 162 min(sizeof(isc_sa.type), sizeof(*psa))); 163 isc_netaddr_fromsockaddr(&isc_na, &isc_sa); 164 result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen); 165 rc = (ISC_R_SUCCESS == result) 166 ? (int)pfxlen 167 : -1; 168 169 return rc; 170 } 171