xref: /freebsd/contrib/ntp/libntp/socktoa.c (revision f5f40dd63bc7acbb5312b26ac1ea1103c12352a6)
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