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