1*eabc0478Schristos /* $NetBSD: socktoa.c,v 1.7 2024/08/18 20:47:13 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 48585484eSchristos * socktoa.c socktoa(), sockporttoa(), and sock_hash() 5abb0f93cSkardel */ 6abb0f93cSkardel 7abb0f93cSkardel #ifdef HAVE_CONFIG_H 8abb0f93cSkardel #include <config.h> 9abb0f93cSkardel #endif 10abb0f93cSkardel 11abb0f93cSkardel #include <sys/types.h> 12abb0f93cSkardel #ifdef HAVE_SYS_SOCKET_H 13abb0f93cSkardel #include <sys/socket.h> 14abb0f93cSkardel #endif 15abb0f93cSkardel #ifdef HAVE_NETINET_IN_H 16abb0f93cSkardel #include <netinet/in.h> 17abb0f93cSkardel #endif 18abb0f93cSkardel 19abb0f93cSkardel #include <stdio.h> 208585484eSchristos #include <arpa/inet.h> 218585484eSchristos #include <isc/result.h> 228585484eSchristos #include <isc/netaddr.h> 238585484eSchristos #include <isc/sockaddr.h> 24abb0f93cSkardel 25abb0f93cSkardel #include "ntp_fp.h" 26abb0f93cSkardel #include "ntp_stdlib.h" 27abb0f93cSkardel #include "ntp.h" 28abb0f93cSkardel 298585484eSchristos /* 308585484eSchristos * socktoa - return a numeric host name from a sockaddr_storage structure 318585484eSchristos */ 328585484eSchristos const char * 33abb0f93cSkardel socktoa( 34f003fb54Skardel const sockaddr_u *sock 35abb0f93cSkardel ) 36abb0f93cSkardel { 378585484eSchristos int saved_errno; 388585484eSchristos char * res; 398585484eSchristos char * addr; 408585484eSchristos u_long scope; 41abb0f93cSkardel 428585484eSchristos saved_errno = socket_errno(); 438585484eSchristos LIB_GETBUF(res); 44abb0f93cSkardel 458585484eSchristos if (NULL == sock) { 468585484eSchristos strlcpy(res, "(null)", LIB_BUFLENGTH); 478585484eSchristos } else { 48abb0f93cSkardel switch(AF(sock)) { 49abb0f93cSkardel 50abb0f93cSkardel case AF_INET: 51abb0f93cSkardel case AF_UNSPEC: 528585484eSchristos inet_ntop(AF_INET, PSOCK_ADDR4(sock), res, 53abb0f93cSkardel LIB_BUFLENGTH); 54abb0f93cSkardel break; 55abb0f93cSkardel 56abb0f93cSkardel case AF_INET6: 578585484eSchristos inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res, 58abb0f93cSkardel LIB_BUFLENGTH); 598585484eSchristos scope = SCOPE_VAR(sock); 608585484eSchristos if (0 != scope && !strchr(res, '%')) { 618585484eSchristos addr = res; 628585484eSchristos LIB_GETBUF(res); 638585484eSchristos snprintf(res, LIB_BUFLENGTH, "%s%%%lu", 648585484eSchristos addr, scope); 658585484eSchristos res[LIB_BUFLENGTH - 1] = '\0'; 668585484eSchristos } 67abb0f93cSkardel break; 68abb0f93cSkardel 69abb0f93cSkardel default: 708585484eSchristos snprintf(res, LIB_BUFLENGTH, 71abb0f93cSkardel "(socktoa unknown family %d)", 72abb0f93cSkardel AF(sock)); 73abb0f93cSkardel } 74abb0f93cSkardel } 758585484eSchristos errno = saved_errno; 768585484eSchristos 778585484eSchristos return res; 788585484eSchristos } 798585484eSchristos 808585484eSchristos 818585484eSchristos const char * 828585484eSchristos sockporttoa( 838585484eSchristos const sockaddr_u *sock 848585484eSchristos ) 858585484eSchristos { 868585484eSchristos int saved_errno; 878585484eSchristos const char * atext; 888585484eSchristos char * buf; 898585484eSchristos 908585484eSchristos saved_errno = socket_errno(); 918585484eSchristos atext = socktoa(sock); 928585484eSchristos LIB_GETBUF(buf); 938585484eSchristos snprintf(buf, LIB_BUFLENGTH, 948585484eSchristos (IS_IPV6(sock)) 95ba1a5140Sjoerg ? "[%s]:%u" 96ba1a5140Sjoerg : "%s:%u", 978585484eSchristos atext, SRCPORT(sock)); 988585484eSchristos errno = saved_errno; 998585484eSchristos 1008585484eSchristos return buf; 1018585484eSchristos } 1028585484eSchristos 1038585484eSchristos 1048585484eSchristos /* 1058585484eSchristos * sock_hash - hash a sockaddr_u structure 1068585484eSchristos */ 1078585484eSchristos u_short 1088585484eSchristos sock_hash( 1098585484eSchristos const sockaddr_u *addr 1108585484eSchristos ) 1118585484eSchristos { 1128585484eSchristos u_int hashVal; 1138585484eSchristos u_int j; 1148585484eSchristos size_t len; 1158585484eSchristos const u_char *pch; 1168585484eSchristos 1178585484eSchristos hashVal = 0; 1188585484eSchristos len = 0; 1198585484eSchristos 1208585484eSchristos /* 1218585484eSchristos * We can't just hash the whole thing because there are hidden 1228585484eSchristos * fields in sockaddr_in6 that might be filled in by recvfrom(), 123*eabc0478Schristos * so just use the family and address. 1248585484eSchristos */ 1258585484eSchristos pch = (const void *)&AF(addr); 1268585484eSchristos hashVal = 37 * hashVal + *pch; 1278585484eSchristos if (sizeof(AF(addr)) > 1) { 1288585484eSchristos pch++; 1298585484eSchristos hashVal = 37 * hashVal + *pch; 1308585484eSchristos } 1318585484eSchristos switch(AF(addr)) { 1328585484eSchristos case AF_INET: 1338585484eSchristos pch = (const void *)&SOCK_ADDR4(addr); 1348585484eSchristos len = sizeof(SOCK_ADDR4(addr)); 1358585484eSchristos break; 1368585484eSchristos 1378585484eSchristos case AF_INET6: 1388585484eSchristos pch = (const void *)&SOCK_ADDR6(addr); 1398585484eSchristos len = sizeof(SOCK_ADDR6(addr)); 1408585484eSchristos break; 1418585484eSchristos } 1428585484eSchristos 1438585484eSchristos for (j = 0; j < len ; j++) 1448585484eSchristos hashVal = 37 * hashVal + pch[j]; 1458585484eSchristos 1468585484eSchristos return (u_short)(hashVal & USHRT_MAX); 1478585484eSchristos } 1488585484eSchristos 1498585484eSchristos 1508585484eSchristos int 1518585484eSchristos sockaddr_masktoprefixlen( 1528585484eSchristos const sockaddr_u * psa 1538585484eSchristos ) 1548585484eSchristos { 1558585484eSchristos isc_netaddr_t isc_na; 1568585484eSchristos isc_sockaddr_t isc_sa; 1578585484eSchristos u_int pfxlen; 1588585484eSchristos isc_result_t result; 1598585484eSchristos int rc; 1608585484eSchristos 1618585484eSchristos ZERO(isc_sa); 1628585484eSchristos memcpy(&isc_sa.type, psa, 1638585484eSchristos min(sizeof(isc_sa.type), sizeof(*psa))); 1648585484eSchristos isc_netaddr_fromsockaddr(&isc_na, &isc_sa); 1658585484eSchristos result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen); 1668585484eSchristos rc = (ISC_R_SUCCESS == result) 1678585484eSchristos ? (int)pfxlen 1688585484eSchristos : -1; 1698585484eSchristos 1708585484eSchristos return rc; 171abb0f93cSkardel } 172