1132451Sroberto/* 2290001Sglebius * socktoa.c socktoa(), sockporttoa(), and sock_hash() 3132451Sroberto */ 4132451Sroberto 5290001Sglebius#ifdef HAVE_CONFIG_H 6132451Sroberto#include <config.h> 7290001Sglebius#endif 8132451Sroberto 9132451Sroberto#include <sys/types.h> 10290001Sglebius#ifdef HAVE_SYS_SOCKET_H 11132451Sroberto#include <sys/socket.h> 12290001Sglebius#endif 13290001Sglebius#ifdef HAVE_NETINET_IN_H 14132451Sroberto#include <netinet/in.h> 15132451Sroberto#endif 16132451Sroberto 17132451Sroberto#include <stdio.h> 18290001Sglebius#include <arpa/inet.h> 19290001Sglebius#include <isc/result.h> 20290001Sglebius#include <isc/netaddr.h> 21290001Sglebius#include <isc/sockaddr.h> 22132451Sroberto 23132451Sroberto#include "ntp_fp.h" 24132451Sroberto#include "lib_strbuf.h" 25132451Sroberto#include "ntp_stdlib.h" 26132451Sroberto#include "ntp.h" 27132451Sroberto 28290001Sglebius/* 29290001Sglebius * socktoa - return a numeric host name from a sockaddr_storage structure 30290001Sglebius */ 31290001Sglebiusconst char * 32132451Srobertosocktoa( 33290001Sglebius const sockaddr_u *sock 34132451Sroberto ) 35132451Sroberto{ 36290001Sglebius int saved_errno; 37290001Sglebius char * res; 38290001Sglebius char * addr; 39290001Sglebius u_long scope; 40132451Sroberto 41290001Sglebius saved_errno = socket_errno(); 42290001Sglebius LIB_GETBUF(res); 43132451Sroberto 44290001Sglebius if (NULL == sock) { 45290001Sglebius strlcpy(res, "(null)", LIB_BUFLENGTH); 46290001Sglebius } else { 47290001Sglebius switch(AF(sock)) { 48132451Sroberto 49290001Sglebius case AF_INET: 50290001Sglebius case AF_UNSPEC: 51290001Sglebius inet_ntop(AF_INET, PSOCK_ADDR4(sock), res, 52290001Sglebius LIB_BUFLENGTH); 53290001Sglebius break; 54132451Sroberto 55290001Sglebius case AF_INET6: 56290001Sglebius inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res, 57290001Sglebius LIB_BUFLENGTH); 58290001Sglebius scope = SCOPE_VAR(sock); 59290001Sglebius if (0 != scope && !strchr(res, '%')) { 60290001Sglebius addr = res; 61290001Sglebius LIB_GETBUF(res); 62290001Sglebius snprintf(res, LIB_BUFLENGTH, "%s%%%lu", 63290001Sglebius addr, scope); 64290001Sglebius res[LIB_BUFLENGTH - 1] = '\0'; 65290001Sglebius } 66132451Sroberto break; 67132451Sroberto 68182007Sroberto default: 69290001Sglebius snprintf(res, LIB_BUFLENGTH, 70290001Sglebius "(socktoa unknown family %d)", 71290001Sglebius AF(sock)); 72182007Sroberto } 73132451Sroberto } 74290001Sglebius errno = saved_errno; 75290001Sglebius 76290001Sglebius return res; 77132451Sroberto} 78290001Sglebius 79290001Sglebius 80290001Sglebiusconst char * 81290001Sglebiussockporttoa( 82290001Sglebius const sockaddr_u *sock 83290001Sglebius ) 84290001Sglebius{ 85290001Sglebius int saved_errno; 86290001Sglebius const char * atext; 87290001Sglebius char * buf; 88290001Sglebius 89290001Sglebius saved_errno = socket_errno(); 90290001Sglebius atext = socktoa(sock); 91290001Sglebius LIB_GETBUF(buf); 92290001Sglebius snprintf(buf, LIB_BUFLENGTH, 93290001Sglebius (IS_IPV6(sock)) 94290001Sglebius ? "[%s]:%hu" 95290001Sglebius : "%s:%hu", 96290001Sglebius atext, SRCPORT(sock)); 97290001Sglebius errno = saved_errno; 98290001Sglebius 99290001Sglebius return buf; 100290001Sglebius} 101290001Sglebius 102290001Sglebius 103290001Sglebius/* 104290001Sglebius * sock_hash - hash a sockaddr_u structure 105290001Sglebius */ 106290001Sglebiusu_short 107290001Sglebiussock_hash( 108290001Sglebius const sockaddr_u *addr 109290001Sglebius ) 110290001Sglebius{ 111290001Sglebius u_int hashVal; 112290001Sglebius u_int j; 113290001Sglebius size_t len; 114290001Sglebius const u_char *pch; 115290001Sglebius 116290001Sglebius hashVal = 0; 117290001Sglebius len = 0; 118290001Sglebius 119290001Sglebius /* 120290001Sglebius * We can't just hash the whole thing because there are hidden 121290001Sglebius * fields in sockaddr_in6 that might be filled in by recvfrom(), 122290001Sglebius * so just use the family, port and address. 123290001Sglebius */ 124290001Sglebius pch = (const void *)&AF(addr); 125290001Sglebius hashVal = 37 * hashVal + *pch; 126290001Sglebius if (sizeof(AF(addr)) > 1) { 127290001Sglebius pch++; 128290001Sglebius hashVal = 37 * hashVal + *pch; 129290001Sglebius } 130290001Sglebius switch(AF(addr)) { 131290001Sglebius case AF_INET: 132290001Sglebius pch = (const void *)&SOCK_ADDR4(addr); 133290001Sglebius len = sizeof(SOCK_ADDR4(addr)); 134290001Sglebius break; 135290001Sglebius 136290001Sglebius case AF_INET6: 137290001Sglebius pch = (const void *)&SOCK_ADDR6(addr); 138290001Sglebius len = sizeof(SOCK_ADDR6(addr)); 139290001Sglebius break; 140290001Sglebius } 141290001Sglebius 142290001Sglebius for (j = 0; j < len ; j++) 143290001Sglebius hashVal = 37 * hashVal + pch[j]; 144290001Sglebius 145290001Sglebius return (u_short)(hashVal & USHRT_MAX); 146290001Sglebius} 147290001Sglebius 148290001Sglebius 149290001Sglebiusint 150290001Sglebiussockaddr_masktoprefixlen( 151290001Sglebius const sockaddr_u * psa 152290001Sglebius ) 153290001Sglebius{ 154290001Sglebius isc_netaddr_t isc_na; 155290001Sglebius isc_sockaddr_t isc_sa; 156290001Sglebius u_int pfxlen; 157290001Sglebius isc_result_t result; 158290001Sglebius int rc; 159290001Sglebius 160290001Sglebius ZERO(isc_sa); 161290001Sglebius memcpy(&isc_sa.type, psa, 162290001Sglebius min(sizeof(isc_sa.type), sizeof(*psa))); 163290001Sglebius isc_netaddr_fromsockaddr(&isc_na, &isc_sa); 164290001Sglebius result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen); 165290001Sglebius rc = (ISC_R_SUCCESS == result) 166290001Sglebius ? (int)pfxlen 167290001Sglebius : -1; 168290001Sglebius 169290001Sglebius return rc; 170290001Sglebius} 171