19c2daa00SOllivier Robert /* 22b15cb3dSCy Schubert * socktoa.c socktoa(), sockporttoa(), and sock_hash() 39c2daa00SOllivier Robert */ 49c2daa00SOllivier Robert 52b15cb3dSCy Schubert #ifdef HAVE_CONFIG_H 69c2daa00SOllivier Robert #include <config.h> 72b15cb3dSCy Schubert #endif 89c2daa00SOllivier Robert 99c2daa00SOllivier Robert #include <sys/types.h> 102b15cb3dSCy Schubert #ifdef HAVE_SYS_SOCKET_H 119c2daa00SOllivier Robert #include <sys/socket.h> 122b15cb3dSCy Schubert #endif 132b15cb3dSCy Schubert #ifdef HAVE_NETINET_IN_H 149c2daa00SOllivier Robert #include <netinet/in.h> 159c2daa00SOllivier Robert #endif 169c2daa00SOllivier Robert 179c2daa00SOllivier Robert #include <stdio.h> 182b15cb3dSCy Schubert #include <arpa/inet.h> 192b15cb3dSCy Schubert #include <isc/result.h> 202b15cb3dSCy Schubert #include <isc/netaddr.h> 212b15cb3dSCy Schubert #include <isc/sockaddr.h> 229c2daa00SOllivier Robert 239c2daa00SOllivier Robert #include "ntp_fp.h" 249c2daa00SOllivier Robert #include "ntp_stdlib.h" 259c2daa00SOllivier Robert #include "ntp.h" 269c2daa00SOllivier Robert 272b15cb3dSCy Schubert /* 282b15cb3dSCy Schubert * socktoa - return a numeric host name from a sockaddr_storage structure 292b15cb3dSCy Schubert */ 302b15cb3dSCy Schubert const char * 319c2daa00SOllivier Robert socktoa( 322b15cb3dSCy Schubert const sockaddr_u *sock 339c2daa00SOllivier Robert ) 349c2daa00SOllivier Robert { 352b15cb3dSCy Schubert int saved_errno; 362b15cb3dSCy Schubert char * res; 372b15cb3dSCy Schubert char * addr; 382b15cb3dSCy Schubert u_long scope; 399c2daa00SOllivier Robert 402b15cb3dSCy Schubert saved_errno = socket_errno(); 412b15cb3dSCy Schubert LIB_GETBUF(res); 429c2daa00SOllivier Robert 432b15cb3dSCy Schubert if (NULL == sock) { 442b15cb3dSCy Schubert strlcpy(res, "(null)", LIB_BUFLENGTH); 452b15cb3dSCy Schubert } else { 462b15cb3dSCy Schubert switch(AF(sock)) { 479c2daa00SOllivier Robert 489c2daa00SOllivier Robert case AF_INET: 492b15cb3dSCy Schubert case AF_UNSPEC: 502b15cb3dSCy Schubert inet_ntop(AF_INET, PSOCK_ADDR4(sock), res, 519c2daa00SOllivier Robert LIB_BUFLENGTH); 529c2daa00SOllivier Robert break; 539c2daa00SOllivier Robert 549c2daa00SOllivier Robert case AF_INET6: 552b15cb3dSCy Schubert inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res, 569c2daa00SOllivier Robert LIB_BUFLENGTH); 572b15cb3dSCy Schubert scope = SCOPE_VAR(sock); 582b15cb3dSCy Schubert if (0 != scope && !strchr(res, '%')) { 592b15cb3dSCy Schubert addr = res; 602b15cb3dSCy Schubert LIB_GETBUF(res); 612b15cb3dSCy Schubert snprintf(res, LIB_BUFLENGTH, "%s%%%lu", 622b15cb3dSCy Schubert addr, scope); 632b15cb3dSCy Schubert res[LIB_BUFLENGTH - 1] = '\0'; 642b15cb3dSCy Schubert } 652b15cb3dSCy Schubert break; 662b15cb3dSCy Schubert 67ea906c41SOllivier Robert default: 682b15cb3dSCy Schubert snprintf(res, LIB_BUFLENGTH, 692b15cb3dSCy Schubert "(socktoa unknown family %d)", 702b15cb3dSCy Schubert AF(sock)); 71ea906c41SOllivier Robert } 729c2daa00SOllivier Robert } 732b15cb3dSCy Schubert errno = saved_errno; 742b15cb3dSCy Schubert 752b15cb3dSCy Schubert return res; 762b15cb3dSCy Schubert } 772b15cb3dSCy Schubert 782b15cb3dSCy Schubert 792b15cb3dSCy Schubert const char * 802b15cb3dSCy Schubert sockporttoa( 812b15cb3dSCy Schubert const sockaddr_u *sock 822b15cb3dSCy Schubert ) 832b15cb3dSCy Schubert { 842b15cb3dSCy Schubert int saved_errno; 852b15cb3dSCy Schubert const char * atext; 862b15cb3dSCy Schubert char * buf; 872b15cb3dSCy Schubert 882b15cb3dSCy Schubert saved_errno = socket_errno(); 892b15cb3dSCy Schubert atext = socktoa(sock); 902b15cb3dSCy Schubert LIB_GETBUF(buf); 912b15cb3dSCy Schubert snprintf(buf, LIB_BUFLENGTH, 922b15cb3dSCy Schubert (IS_IPV6(sock)) 932b15cb3dSCy Schubert ? "[%s]:%hu" 942b15cb3dSCy Schubert : "%s:%hu", 952b15cb3dSCy Schubert atext, SRCPORT(sock)); 962b15cb3dSCy Schubert errno = saved_errno; 972b15cb3dSCy Schubert 982b15cb3dSCy Schubert return buf; 992b15cb3dSCy Schubert } 1002b15cb3dSCy Schubert 1012b15cb3dSCy Schubert 1022b15cb3dSCy Schubert /* 1032b15cb3dSCy Schubert * sock_hash - hash a sockaddr_u structure 1042b15cb3dSCy Schubert */ 1052b15cb3dSCy Schubert u_short 1062b15cb3dSCy Schubert sock_hash( 1072b15cb3dSCy Schubert const sockaddr_u *addr 1082b15cb3dSCy Schubert ) 1092b15cb3dSCy Schubert { 1102b15cb3dSCy Schubert u_int hashVal; 1112b15cb3dSCy Schubert u_int j; 1122b15cb3dSCy Schubert size_t len; 1132b15cb3dSCy Schubert const u_char *pch; 1142b15cb3dSCy Schubert 1152b15cb3dSCy Schubert hashVal = 0; 1162b15cb3dSCy Schubert len = 0; 1172b15cb3dSCy Schubert 1182b15cb3dSCy Schubert /* 1192b15cb3dSCy Schubert * We can't just hash the whole thing because there are hidden 1202b15cb3dSCy Schubert * fields in sockaddr_in6 that might be filled in by recvfrom(), 121*a466cc55SCy Schubert * so just use the family and address. 1222b15cb3dSCy Schubert */ 1232b15cb3dSCy Schubert pch = (const void *)&AF(addr); 1242b15cb3dSCy Schubert hashVal = 37 * hashVal + *pch; 1252b15cb3dSCy Schubert if (sizeof(AF(addr)) > 1) { 1262b15cb3dSCy Schubert pch++; 1272b15cb3dSCy Schubert hashVal = 37 * hashVal + *pch; 1282b15cb3dSCy Schubert } 1292b15cb3dSCy Schubert switch(AF(addr)) { 1302b15cb3dSCy Schubert case AF_INET: 1312b15cb3dSCy Schubert pch = (const void *)&SOCK_ADDR4(addr); 1322b15cb3dSCy Schubert len = sizeof(SOCK_ADDR4(addr)); 1332b15cb3dSCy Schubert break; 1342b15cb3dSCy Schubert 1352b15cb3dSCy Schubert case AF_INET6: 1362b15cb3dSCy Schubert pch = (const void *)&SOCK_ADDR6(addr); 1372b15cb3dSCy Schubert len = sizeof(SOCK_ADDR6(addr)); 1382b15cb3dSCy Schubert break; 1392b15cb3dSCy Schubert } 1402b15cb3dSCy Schubert 1412b15cb3dSCy Schubert for (j = 0; j < len ; j++) 1422b15cb3dSCy Schubert hashVal = 37 * hashVal + pch[j]; 1432b15cb3dSCy Schubert 1442b15cb3dSCy Schubert return (u_short)(hashVal & USHRT_MAX); 1452b15cb3dSCy Schubert } 1462b15cb3dSCy Schubert 1472b15cb3dSCy Schubert 1482b15cb3dSCy Schubert int 1492b15cb3dSCy Schubert sockaddr_masktoprefixlen( 1502b15cb3dSCy Schubert const sockaddr_u * psa 1512b15cb3dSCy Schubert ) 1522b15cb3dSCy Schubert { 1532b15cb3dSCy Schubert isc_netaddr_t isc_na; 1542b15cb3dSCy Schubert isc_sockaddr_t isc_sa; 1552b15cb3dSCy Schubert u_int pfxlen; 1562b15cb3dSCy Schubert isc_result_t result; 1572b15cb3dSCy Schubert int rc; 1582b15cb3dSCy Schubert 1592b15cb3dSCy Schubert ZERO(isc_sa); 1602b15cb3dSCy Schubert memcpy(&isc_sa.type, psa, 1612b15cb3dSCy Schubert min(sizeof(isc_sa.type), sizeof(*psa))); 1622b15cb3dSCy Schubert isc_netaddr_fromsockaddr(&isc_na, &isc_sa); 1632b15cb3dSCy Schubert result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen); 1642b15cb3dSCy Schubert rc = (ISC_R_SUCCESS == result) 1652b15cb3dSCy Schubert ? (int)pfxlen 1662b15cb3dSCy Schubert : -1; 1672b15cb3dSCy Schubert 1682b15cb3dSCy Schubert return rc; 1699c2daa00SOllivier Robert } 170