xref: /netbsd-src/external/bsd/ntp/dist/libntp/socktoa.c (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
1 /*	$NetBSD: socktoa.c,v 1.7 2024/08/18 20:47:13 christos Exp $	*/
2 
3 /*
4  * socktoa.c	socktoa(), sockporttoa(), and sock_hash()
5  */
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <sys/types.h>
12 #ifdef HAVE_SYS_SOCKET_H
13 #include <sys/socket.h>
14 #endif
15 #ifdef HAVE_NETINET_IN_H
16 #include <netinet/in.h>
17 #endif
18 
19 #include <stdio.h>
20 #include <arpa/inet.h>
21 #include <isc/result.h>
22 #include <isc/netaddr.h>
23 #include <isc/sockaddr.h>
24 
25 #include "ntp_fp.h"
26 #include "ntp_stdlib.h"
27 #include "ntp.h"
28 
29 /*
30  * socktoa - return a numeric host name from a sockaddr_storage structure
31  */
32 const char *
33 socktoa(
34 	const sockaddr_u *sock
35 	)
36 {
37 	int		saved_errno;
38 	char *		res;
39 	char *		addr;
40 	u_long		scope;
41 
42 	saved_errno = socket_errno();
43 	LIB_GETBUF(res);
44 
45 	if (NULL == sock) {
46 		strlcpy(res, "(null)", LIB_BUFLENGTH);
47 	} else {
48 		switch(AF(sock)) {
49 
50 		case AF_INET:
51 		case AF_UNSPEC:
52 			inet_ntop(AF_INET, PSOCK_ADDR4(sock), res,
53 				  LIB_BUFLENGTH);
54 			break;
55 
56 		case AF_INET6:
57 			inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res,
58 				  LIB_BUFLENGTH);
59 			scope = SCOPE_VAR(sock);
60 			if (0 != scope && !strchr(res, '%')) {
61 				addr = res;
62 				LIB_GETBUF(res);
63 				snprintf(res, LIB_BUFLENGTH, "%s%%%lu",
64 					 addr, scope);
65 				res[LIB_BUFLENGTH - 1] = '\0';
66 			}
67 			break;
68 
69 		default:
70 			snprintf(res, LIB_BUFLENGTH,
71 				 "(socktoa unknown family %d)",
72 				 AF(sock));
73 		}
74 	}
75 	errno = saved_errno;
76 
77 	return res;
78 }
79 
80 
81 const char *
82 sockporttoa(
83 	const sockaddr_u *sock
84 	)
85 {
86 	int		saved_errno;
87 	const char *	atext;
88 	char *		buf;
89 
90 	saved_errno = socket_errno();
91 	atext = socktoa(sock);
92 	LIB_GETBUF(buf);
93 	snprintf(buf, LIB_BUFLENGTH,
94 		 (IS_IPV6(sock))
95 		     ? "[%s]:%u"
96 		     : "%s:%u",
97 		 atext, SRCPORT(sock));
98 	errno = saved_errno;
99 
100 	return buf;
101 }
102 
103 
104 /*
105  * sock_hash - hash a sockaddr_u structure
106  */
107 u_short
108 sock_hash(
109 	const sockaddr_u *addr
110 	)
111 {
112 	u_int hashVal;
113 	u_int j;
114 	size_t len;
115 	const u_char *pch;
116 
117 	hashVal = 0;
118 	len = 0;
119 
120 	/*
121 	 * We can't just hash the whole thing because there are hidden
122 	 * fields in sockaddr_in6 that might be filled in by recvfrom(),
123 	 * so just use the family and address.
124 	 */
125 	pch = (const void *)&AF(addr);
126 	hashVal = 37 * hashVal + *pch;
127 	if (sizeof(AF(addr)) > 1) {
128 		pch++;
129 		hashVal = 37 * hashVal + *pch;
130 	}
131 	switch(AF(addr)) {
132 	case AF_INET:
133 		pch = (const void *)&SOCK_ADDR4(addr);
134 		len = sizeof(SOCK_ADDR4(addr));
135 		break;
136 
137 	case AF_INET6:
138 		pch = (const void *)&SOCK_ADDR6(addr);
139 		len = sizeof(SOCK_ADDR6(addr));
140 		break;
141 	}
142 
143 	for (j = 0; j < len ; j++)
144 		hashVal = 37 * hashVal + pch[j];
145 
146 	return (u_short)(hashVal & USHRT_MAX);
147 }
148 
149 
150 int
151 sockaddr_masktoprefixlen(
152 	const sockaddr_u *	psa
153 	)
154 {
155 	isc_netaddr_t	isc_na;
156 	isc_sockaddr_t	isc_sa;
157 	u_int		pfxlen;
158 	isc_result_t	result;
159 	int		rc;
160 
161 	ZERO(isc_sa);
162 	memcpy(&isc_sa.type, psa,
163 	       min(sizeof(isc_sa.type), sizeof(*psa)));
164 	isc_netaddr_fromsockaddr(&isc_na, &isc_sa);
165 	result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen);
166 	rc = (ISC_R_SUCCESS == result)
167 		 ? (int)pfxlen
168 		 : -1;
169 
170 	return rc;
171 }
172