1132451Sroberto/* 2285612Sdelphij * socktoa.c socktoa(), sockporttoa(), and sock_hash() 3132451Sroberto */ 4132451Sroberto 5285612Sdelphij#ifdef HAVE_CONFIG_H 6132451Sroberto#include <config.h> 7285612Sdelphij#endif 8132451Sroberto 9132451Sroberto#include <sys/types.h> 10285612Sdelphij#ifdef HAVE_SYS_SOCKET_H 11132451Sroberto#include <sys/socket.h> 12285612Sdelphij#endif 13285612Sdelphij#ifdef HAVE_NETINET_IN_H 14132451Sroberto#include <netinet/in.h> 15132451Sroberto#endif 16132451Sroberto 17132451Sroberto#include <stdio.h> 18285612Sdelphij#include <arpa/inet.h> 19285612Sdelphij#include <isc/result.h> 20285612Sdelphij#include <isc/netaddr.h> 21285612Sdelphij#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 28285612Sdelphij/* 29285612Sdelphij * socktoa - return a numeric host name from a sockaddr_storage structure 30285612Sdelphij */ 31285612Sdelphijconst char * 32132451Srobertosocktoa( 33285612Sdelphij const sockaddr_u *sock 34132451Sroberto ) 35132451Sroberto{ 36285612Sdelphij int saved_errno; 37285612Sdelphij char * res; 38285612Sdelphij char * addr; 39285612Sdelphij u_long scope; 40132451Sroberto 41285612Sdelphij saved_errno = socket_errno(); 42285612Sdelphij LIB_GETBUF(res); 43132451Sroberto 44285612Sdelphij if (NULL == sock) { 45285612Sdelphij strlcpy(res, "(null)", LIB_BUFLENGTH); 46285612Sdelphij } else { 47285612Sdelphij switch(AF(sock)) { 48132451Sroberto 49285612Sdelphij case AF_INET: 50285612Sdelphij case AF_UNSPEC: 51285612Sdelphij inet_ntop(AF_INET, PSOCK_ADDR4(sock), res, 52285612Sdelphij LIB_BUFLENGTH); 53285612Sdelphij break; 54132451Sroberto 55285612Sdelphij case AF_INET6: 56285612Sdelphij inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res, 57285612Sdelphij LIB_BUFLENGTH); 58285612Sdelphij scope = SCOPE_VAR(sock); 59285612Sdelphij if (0 != scope && !strchr(res, '%')) { 60285612Sdelphij addr = res; 61285612Sdelphij LIB_GETBUF(res); 62285612Sdelphij snprintf(res, LIB_BUFLENGTH, "%s%%%lu", 63285612Sdelphij addr, scope); 64285612Sdelphij res[LIB_BUFLENGTH - 1] = '\0'; 65285612Sdelphij } 66132451Sroberto break; 67132451Sroberto 68182007Sroberto default: 69285612Sdelphij snprintf(res, LIB_BUFLENGTH, 70285612Sdelphij "(socktoa unknown family %d)", 71285612Sdelphij AF(sock)); 72182007Sroberto } 73132451Sroberto } 74285612Sdelphij errno = saved_errno; 75285612Sdelphij 76285612Sdelphij return res; 77132451Sroberto} 78285612Sdelphij 79285612Sdelphij 80285612Sdelphijconst char * 81285612Sdelphijsockporttoa( 82285612Sdelphij const sockaddr_u *sock 83285612Sdelphij ) 84285612Sdelphij{ 85285612Sdelphij int saved_errno; 86285612Sdelphij const char * atext; 87285612Sdelphij char * buf; 88285612Sdelphij 89285612Sdelphij saved_errno = socket_errno(); 90285612Sdelphij atext = socktoa(sock); 91285612Sdelphij LIB_GETBUF(buf); 92285612Sdelphij snprintf(buf, LIB_BUFLENGTH, 93285612Sdelphij (IS_IPV6(sock)) 94285612Sdelphij ? "[%s]:%hu" 95285612Sdelphij : "%s:%hu", 96285612Sdelphij atext, SRCPORT(sock)); 97285612Sdelphij errno = saved_errno; 98285612Sdelphij 99285612Sdelphij return buf; 100285612Sdelphij} 101285612Sdelphij 102285612Sdelphij 103285612Sdelphij/* 104285612Sdelphij * sock_hash - hash a sockaddr_u structure 105285612Sdelphij */ 106285612Sdelphiju_short 107285612Sdelphijsock_hash( 108285612Sdelphij const sockaddr_u *addr 109285612Sdelphij ) 110285612Sdelphij{ 111285612Sdelphij u_int hashVal; 112285612Sdelphij u_int j; 113285612Sdelphij size_t len; 114285612Sdelphij const u_char *pch; 115285612Sdelphij 116285612Sdelphij hashVal = 0; 117285612Sdelphij len = 0; 118285612Sdelphij 119285612Sdelphij /* 120285612Sdelphij * We can't just hash the whole thing because there are hidden 121285612Sdelphij * fields in sockaddr_in6 that might be filled in by recvfrom(), 122285612Sdelphij * so just use the family, port and address. 123285612Sdelphij */ 124285612Sdelphij pch = (const void *)&AF(addr); 125285612Sdelphij hashVal = 37 * hashVal + *pch; 126285612Sdelphij if (sizeof(AF(addr)) > 1) { 127285612Sdelphij pch++; 128285612Sdelphij hashVal = 37 * hashVal + *pch; 129285612Sdelphij } 130285612Sdelphij switch(AF(addr)) { 131285612Sdelphij case AF_INET: 132285612Sdelphij pch = (const void *)&SOCK_ADDR4(addr); 133285612Sdelphij len = sizeof(SOCK_ADDR4(addr)); 134285612Sdelphij break; 135285612Sdelphij 136285612Sdelphij case AF_INET6: 137285612Sdelphij pch = (const void *)&SOCK_ADDR6(addr); 138285612Sdelphij len = sizeof(SOCK_ADDR6(addr)); 139285612Sdelphij break; 140285612Sdelphij } 141285612Sdelphij 142285612Sdelphij for (j = 0; j < len ; j++) 143285612Sdelphij hashVal = 37 * hashVal + pch[j]; 144285612Sdelphij 145285612Sdelphij return (u_short)(hashVal & USHRT_MAX); 146285612Sdelphij} 147285612Sdelphij 148285612Sdelphij 149285612Sdelphijint 150285612Sdelphijsockaddr_masktoprefixlen( 151285612Sdelphij const sockaddr_u * psa 152285612Sdelphij ) 153285612Sdelphij{ 154285612Sdelphij isc_netaddr_t isc_na; 155285612Sdelphij isc_sockaddr_t isc_sa; 156285612Sdelphij u_int pfxlen; 157285612Sdelphij isc_result_t result; 158285612Sdelphij int rc; 159285612Sdelphij 160285612Sdelphij ZERO(isc_sa); 161285612Sdelphij memcpy(&isc_sa.type, psa, 162285612Sdelphij min(sizeof(isc_sa.type), sizeof(*psa))); 163285612Sdelphij isc_netaddr_fromsockaddr(&isc_na, &isc_sa); 164285612Sdelphij result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen); 165285612Sdelphij rc = (ISC_R_SUCCESS == result) 166285612Sdelphij ? (int)pfxlen 167285612Sdelphij : -1; 168285612Sdelphij 169285612Sdelphij return rc; 170285612Sdelphij} 171