diff options
Diffstat (limited to 'libntp/socktoa.c')
-rw-r--r-- | libntp/socktoa.c | 142 |
1 files changed, 125 insertions, 17 deletions
diff --git a/libntp/socktoa.c b/libntp/socktoa.c index 62e4537266f0..98abe7c42036 100644 --- a/libntp/socktoa.c +++ b/libntp/socktoa.c @@ -1,5 +1,5 @@ /* - * socktoa - return a numeric host name from a sockaddr_storage structure + * socktoa.c socktoa(), sockporttoa(), and sock_hash() */ #ifdef HAVE_CONFIG_H @@ -14,49 +14,157 @@ #include <netinet/in.h> #endif -#include <arpa/inet.h> - -#ifdef ISC_PLATFORM_NEEDNTOP -#include <isc/net.h> -#endif - #include <stdio.h> +#include <arpa/inet.h> +#include <isc/result.h> +#include <isc/netaddr.h> +#include <isc/sockaddr.h> #include "ntp_fp.h" #include "lib_strbuf.h" #include "ntp_stdlib.h" #include "ntp.h" -char * +/* + * socktoa - return a numeric host name from a sockaddr_storage structure + */ +const char * socktoa( const sockaddr_u *sock ) { - register char *buffer; + int saved_errno; + char * res; + char * addr; + u_long scope; - LIB_GETBUF(buffer); + saved_errno = socket_errno(); + LIB_GETBUF(res); - if (NULL == sock) - strncpy(buffer, "(null)", LIB_BUFLENGTH); - else { + if (NULL == sock) { + strlcpy(res, "(null)", LIB_BUFLENGTH); + } else { switch(AF(sock)) { case AF_INET: case AF_UNSPEC: - inet_ntop(AF_INET, PSOCK_ADDR4(sock), buffer, + inet_ntop(AF_INET, PSOCK_ADDR4(sock), res, LIB_BUFLENGTH); break; case AF_INET6: - inet_ntop(AF_INET6, PSOCK_ADDR6(sock), buffer, + inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res, LIB_BUFLENGTH); + scope = SCOPE_VAR(sock); + if (0 != scope && !strchr(res, '%')) { + addr = res; + LIB_GETBUF(res); + snprintf(res, LIB_BUFLENGTH, "%s%%%lu", + addr, scope); + res[LIB_BUFLENGTH - 1] = '\0'; + } break; default: - snprintf(buffer, LIB_BUFLENGTH, + snprintf(res, LIB_BUFLENGTH, "(socktoa unknown family %d)", AF(sock)); } } - return buffer; + errno = saved_errno; + + return res; +} + + +const char * +sockporttoa( + const sockaddr_u *sock + ) +{ + int saved_errno; + const char * atext; + char * buf; + + saved_errno = socket_errno(); + atext = socktoa(sock); + LIB_GETBUF(buf); + snprintf(buf, LIB_BUFLENGTH, + (IS_IPV6(sock)) + ? "[%s]:%hu" + : "%s:%hu", + atext, SRCPORT(sock)); + errno = saved_errno; + + return buf; +} + + +/* + * sock_hash - hash a sockaddr_u structure + */ +u_short +sock_hash( + const sockaddr_u *addr + ) +{ + u_int hashVal; + u_int j; + size_t len; + const u_char *pch; + + hashVal = 0; + len = 0; + + /* + * We can't just hash the whole thing because there are hidden + * fields in sockaddr_in6 that might be filled in by recvfrom(), + * so just use the family, port and address. + */ + pch = (const void *)&AF(addr); + hashVal = 37 * hashVal + *pch; + if (sizeof(AF(addr)) > 1) { + pch++; + hashVal = 37 * hashVal + *pch; + } + switch(AF(addr)) { + case AF_INET: + pch = (const void *)&SOCK_ADDR4(addr); + len = sizeof(SOCK_ADDR4(addr)); + break; + + case AF_INET6: + pch = (const void *)&SOCK_ADDR6(addr); + len = sizeof(SOCK_ADDR6(addr)); + break; + } + + for (j = 0; j < len ; j++) + hashVal = 37 * hashVal + pch[j]; + + return (u_short)(hashVal & USHRT_MAX); +} + + +int +sockaddr_masktoprefixlen( + const sockaddr_u * psa + ) +{ + isc_netaddr_t isc_na; + isc_sockaddr_t isc_sa; + u_int pfxlen; + isc_result_t result; + int rc; + + ZERO(isc_sa); + memcpy(&isc_sa.type, psa, + min(sizeof(isc_sa.type), sizeof(*psa))); + isc_netaddr_fromsockaddr(&isc_na, &isc_sa); + result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen); + rc = (ISC_R_SUCCESS == result) + ? (int)pfxlen + : -1; + + return rc; } |