xref: /netbsd-src/external/bsd/ntp/dist/libntp/socktoa.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: socktoa.c,v 1.7 2024/08/18 20:47:13 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
48585484eSchristos  * socktoa.c	socktoa(), sockporttoa(), and sock_hash()
5abb0f93cSkardel  */
6abb0f93cSkardel 
7abb0f93cSkardel #ifdef HAVE_CONFIG_H
8abb0f93cSkardel #include <config.h>
9abb0f93cSkardel #endif
10abb0f93cSkardel 
11abb0f93cSkardel #include <sys/types.h>
12abb0f93cSkardel #ifdef HAVE_SYS_SOCKET_H
13abb0f93cSkardel #include <sys/socket.h>
14abb0f93cSkardel #endif
15abb0f93cSkardel #ifdef HAVE_NETINET_IN_H
16abb0f93cSkardel #include <netinet/in.h>
17abb0f93cSkardel #endif
18abb0f93cSkardel 
19abb0f93cSkardel #include <stdio.h>
208585484eSchristos #include <arpa/inet.h>
218585484eSchristos #include <isc/result.h>
228585484eSchristos #include <isc/netaddr.h>
238585484eSchristos #include <isc/sockaddr.h>
24abb0f93cSkardel 
25abb0f93cSkardel #include "ntp_fp.h"
26abb0f93cSkardel #include "ntp_stdlib.h"
27abb0f93cSkardel #include "ntp.h"
28abb0f93cSkardel 
298585484eSchristos /*
308585484eSchristos  * socktoa - return a numeric host name from a sockaddr_storage structure
318585484eSchristos  */
328585484eSchristos const char *
33abb0f93cSkardel socktoa(
34f003fb54Skardel 	const sockaddr_u *sock
35abb0f93cSkardel 	)
36abb0f93cSkardel {
378585484eSchristos 	int		saved_errno;
388585484eSchristos 	char *		res;
398585484eSchristos 	char *		addr;
408585484eSchristos 	u_long		scope;
41abb0f93cSkardel 
428585484eSchristos 	saved_errno = socket_errno();
438585484eSchristos 	LIB_GETBUF(res);
44abb0f93cSkardel 
458585484eSchristos 	if (NULL == sock) {
468585484eSchristos 		strlcpy(res, "(null)", LIB_BUFLENGTH);
478585484eSchristos 	} else {
48abb0f93cSkardel 		switch(AF(sock)) {
49abb0f93cSkardel 
50abb0f93cSkardel 		case AF_INET:
51abb0f93cSkardel 		case AF_UNSPEC:
528585484eSchristos 			inet_ntop(AF_INET, PSOCK_ADDR4(sock), res,
53abb0f93cSkardel 				  LIB_BUFLENGTH);
54abb0f93cSkardel 			break;
55abb0f93cSkardel 
56abb0f93cSkardel 		case AF_INET6:
578585484eSchristos 			inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res,
58abb0f93cSkardel 				  LIB_BUFLENGTH);
598585484eSchristos 			scope = SCOPE_VAR(sock);
608585484eSchristos 			if (0 != scope && !strchr(res, '%')) {
618585484eSchristos 				addr = res;
628585484eSchristos 				LIB_GETBUF(res);
638585484eSchristos 				snprintf(res, LIB_BUFLENGTH, "%s%%%lu",
648585484eSchristos 					 addr, scope);
658585484eSchristos 				res[LIB_BUFLENGTH - 1] = '\0';
668585484eSchristos 			}
67abb0f93cSkardel 			break;
68abb0f93cSkardel 
69abb0f93cSkardel 		default:
708585484eSchristos 			snprintf(res, LIB_BUFLENGTH,
71abb0f93cSkardel 				 "(socktoa unknown family %d)",
72abb0f93cSkardel 				 AF(sock));
73abb0f93cSkardel 		}
74abb0f93cSkardel 	}
758585484eSchristos 	errno = saved_errno;
768585484eSchristos 
778585484eSchristos 	return res;
788585484eSchristos }
798585484eSchristos 
808585484eSchristos 
818585484eSchristos const char *
828585484eSchristos sockporttoa(
838585484eSchristos 	const sockaddr_u *sock
848585484eSchristos 	)
858585484eSchristos {
868585484eSchristos 	int		saved_errno;
878585484eSchristos 	const char *	atext;
888585484eSchristos 	char *		buf;
898585484eSchristos 
908585484eSchristos 	saved_errno = socket_errno();
918585484eSchristos 	atext = socktoa(sock);
928585484eSchristos 	LIB_GETBUF(buf);
938585484eSchristos 	snprintf(buf, LIB_BUFLENGTH,
948585484eSchristos 		 (IS_IPV6(sock))
95ba1a5140Sjoerg 		     ? "[%s]:%u"
96ba1a5140Sjoerg 		     : "%s:%u",
978585484eSchristos 		 atext, SRCPORT(sock));
988585484eSchristos 	errno = saved_errno;
998585484eSchristos 
1008585484eSchristos 	return buf;
1018585484eSchristos }
1028585484eSchristos 
1038585484eSchristos 
1048585484eSchristos /*
1058585484eSchristos  * sock_hash - hash a sockaddr_u structure
1068585484eSchristos  */
1078585484eSchristos u_short
1088585484eSchristos sock_hash(
1098585484eSchristos 	const sockaddr_u *addr
1108585484eSchristos 	)
1118585484eSchristos {
1128585484eSchristos 	u_int hashVal;
1138585484eSchristos 	u_int j;
1148585484eSchristos 	size_t len;
1158585484eSchristos 	const u_char *pch;
1168585484eSchristos 
1178585484eSchristos 	hashVal = 0;
1188585484eSchristos 	len = 0;
1198585484eSchristos 
1208585484eSchristos 	/*
1218585484eSchristos 	 * We can't just hash the whole thing because there are hidden
1228585484eSchristos 	 * fields in sockaddr_in6 that might be filled in by recvfrom(),
123*eabc0478Schristos 	 * so just use the family and address.
1248585484eSchristos 	 */
1258585484eSchristos 	pch = (const void *)&AF(addr);
1268585484eSchristos 	hashVal = 37 * hashVal + *pch;
1278585484eSchristos 	if (sizeof(AF(addr)) > 1) {
1288585484eSchristos 		pch++;
1298585484eSchristos 		hashVal = 37 * hashVal + *pch;
1308585484eSchristos 	}
1318585484eSchristos 	switch(AF(addr)) {
1328585484eSchristos 	case AF_INET:
1338585484eSchristos 		pch = (const void *)&SOCK_ADDR4(addr);
1348585484eSchristos 		len = sizeof(SOCK_ADDR4(addr));
1358585484eSchristos 		break;
1368585484eSchristos 
1378585484eSchristos 	case AF_INET6:
1388585484eSchristos 		pch = (const void *)&SOCK_ADDR6(addr);
1398585484eSchristos 		len = sizeof(SOCK_ADDR6(addr));
1408585484eSchristos 		break;
1418585484eSchristos 	}
1428585484eSchristos 
1438585484eSchristos 	for (j = 0; j < len ; j++)
1448585484eSchristos 		hashVal = 37 * hashVal + pch[j];
1458585484eSchristos 
1468585484eSchristos 	return (u_short)(hashVal & USHRT_MAX);
1478585484eSchristos }
1488585484eSchristos 
1498585484eSchristos 
1508585484eSchristos int
1518585484eSchristos sockaddr_masktoprefixlen(
1528585484eSchristos 	const sockaddr_u *	psa
1538585484eSchristos 	)
1548585484eSchristos {
1558585484eSchristos 	isc_netaddr_t	isc_na;
1568585484eSchristos 	isc_sockaddr_t	isc_sa;
1578585484eSchristos 	u_int		pfxlen;
1588585484eSchristos 	isc_result_t	result;
1598585484eSchristos 	int		rc;
1608585484eSchristos 
1618585484eSchristos 	ZERO(isc_sa);
1628585484eSchristos 	memcpy(&isc_sa.type, psa,
1638585484eSchristos 	       min(sizeof(isc_sa.type), sizeof(*psa)));
1648585484eSchristos 	isc_netaddr_fromsockaddr(&isc_na, &isc_sa);
1658585484eSchristos 	result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen);
1668585484eSchristos 	rc = (ISC_R_SUCCESS == result)
1678585484eSchristos 		 ? (int)pfxlen
1688585484eSchristos 		 : -1;
1698585484eSchristos 
1708585484eSchristos 	return rc;
171abb0f93cSkardel }
172