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