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