1154133Sharti/*	$NetBSD: socktoa.c,v 1.6 2020/05/25 20:47:24 christos Exp $	*/
2154133Sharti
3154133Sharti/*
4154133Sharti * socktoa.c	socktoa(), sockporttoa(), and sock_hash()
5154133Sharti */
6154133Sharti
7154133Sharti#ifdef HAVE_CONFIG_H
8154133Sharti#include <config.h>
9154133Sharti#endif
10154133Sharti
11154133Sharti#include <sys/types.h>
12154133Sharti#ifdef HAVE_SYS_SOCKET_H
13154133Sharti#include <sys/socket.h>
14154133Sharti#endif
15154133Sharti#ifdef HAVE_NETINET_IN_H
16154133Sharti#include <netinet/in.h>
17154133Sharti#endif
18154133Sharti
19154133Sharti#include <stdio.h>
20154133Sharti#include <arpa/inet.h>
21154133Sharti#include <isc/result.h>
22154133Sharti#include <isc/netaddr.h>
23154133Sharti#include <isc/sockaddr.h>
24154133Sharti
25154133Sharti#include "ntp_fp.h"
26154133Sharti#include "lib_strbuf.h"
27154133Sharti#include "ntp_stdlib.h"
28154133Sharti#include "ntp.h"
29154133Sharti
30154133Sharti/*
31154133Sharti * socktoa - return a numeric host name from a sockaddr_storage structure
32154133Sharti */
33154133Sharticonst char *
34154133Shartisocktoa(
35154133Sharti	const sockaddr_u *sock
36154133Sharti	)
37154133Sharti{
38154133Sharti	int		saved_errno;
39154133Sharti	char *		res;
40154133Sharti	char *		addr;
41154133Sharti	u_long		scope;
42154133Sharti
43154133Sharti	saved_errno = socket_errno();
44154133Sharti	LIB_GETBUF(res);
45154133Sharti
46154133Sharti	if (NULL == sock) {
47154133Sharti		strlcpy(res, "(null)", LIB_BUFLENGTH);
48154133Sharti	} else {
49154133Sharti		switch(AF(sock)) {
50154133Sharti
51154133Sharti		case AF_INET:
52160341Sharti		case AF_UNSPEC:
53160341Sharti			inet_ntop(AF_INET, PSOCK_ADDR4(sock), res,
54154133Sharti				  LIB_BUFLENGTH);
55154133Sharti			break;
56154133Sharti
57154133Sharti		case AF_INET6:
58154133Sharti			inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res,
59160341Sharti				  LIB_BUFLENGTH);
60160341Sharti			scope = SCOPE_VAR(sock);
61160341Sharti			if (0 != scope && !strchr(res, '%')) {
62154133Sharti				addr = res;
63154133Sharti				LIB_GETBUF(res);
64154133Sharti				snprintf(res, LIB_BUFLENGTH, "%s%%%lu",
65154133Sharti					 addr, scope);
66154133Sharti				res[LIB_BUFLENGTH - 1] = '\0';
67154133Sharti			}
68160341Sharti			break;
69160341Sharti
70154133Sharti		default:
71154133Sharti			snprintf(res, LIB_BUFLENGTH,
72154133Sharti				 "(socktoa unknown family %d)",
73154133Sharti				 AF(sock));
74160341Sharti		}
75154133Sharti	}
76154133Sharti	errno = saved_errno;
77154133Sharti
78154133Sharti	return res;
79154133Sharti}
80154133Sharti
81154133Sharti
82154133Sharticonst char *
83154133Shartisockporttoa(
84154133Sharti	const sockaddr_u *sock
85154133Sharti	)
86154133Sharti{
87160341Sharti	int		saved_errno;
88154133Sharti	const char *	atext;
89160341Sharti	char *		buf;
90160341Sharti
91154133Sharti	saved_errno = socket_errno();
92154133Sharti	atext = socktoa(sock);
93160341Sharti	LIB_GETBUF(buf);
94154133Sharti	snprintf(buf, LIB_BUFLENGTH,
95154133Sharti		 (IS_IPV6(sock))
96154133Sharti		     ? "[%s]:%u"
97154133Sharti		     : "%s:%u",
98154133Sharti		 atext, SRCPORT(sock));
99154133Sharti	errno = saved_errno;
100154133Sharti
101154133Sharti	return buf;
102154133Sharti}
103154133Sharti
104154133Sharti
105154133Sharti/*
106154133Sharti * sock_hash - hash a sockaddr_u structure
107154133Sharti */
108154133Shartiu_short
109154133Shartisock_hash(
110154133Sharti	const sockaddr_u *addr
111154133Sharti	)
112154133Sharti{
113154133Sharti	u_int hashVal;
114154133Sharti	u_int j;
115154133Sharti	size_t len;
116154133Sharti	const u_char *pch;
117154133Sharti
118154133Sharti	hashVal = 0;
119154133Sharti	len = 0;
120154133Sharti
121154133Sharti	/*
122154133Sharti	 * We can't just hash the whole thing because there are hidden
123154133Sharti	 * fields in sockaddr_in6 that might be filled in by recvfrom(),
124154133Sharti	 * so just use the family, port and address.
125154133Sharti	 */
126154133Sharti	pch = (const void *)&AF(addr);
127154133Sharti	hashVal = 37 * hashVal + *pch;
128154133Sharti	if (sizeof(AF(addr)) > 1) {
129154133Sharti		pch++;
130154133Sharti		hashVal = 37 * hashVal + *pch;
131154133Sharti	}
132154133Sharti	switch(AF(addr)) {
133154133Sharti	case AF_INET:
134154133Sharti		pch = (const void *)&SOCK_ADDR4(addr);
135154133Sharti		len = sizeof(SOCK_ADDR4(addr));
136228990Suqs		break;
137154133Sharti
138154133Sharti	case AF_INET6:
139154133Sharti		pch = (const void *)&SOCK_ADDR6(addr);
140154133Sharti		len = sizeof(SOCK_ADDR6(addr));
141154133Sharti		break;
142154133Sharti	}
143154133Sharti
144160341Sharti	for (j = 0; j < len ; j++)
145154133Sharti		hashVal = 37 * hashVal + pch[j];
146160341Sharti
147160341Sharti	return (u_short)(hashVal & USHRT_MAX);
148154133Sharti}
149154133Sharti
150160341Sharti
151154133Shartiint
152154133Shartisockaddr_masktoprefixlen(
153154133Sharti	const sockaddr_u *	psa
154154133Sharti	)
155154133Sharti{
156154133Sharti	isc_netaddr_t	isc_na;
157154133Sharti	isc_sockaddr_t	isc_sa;
158160341Sharti	u_int		pfxlen;
159154133Sharti	isc_result_t	result;
160154133Sharti	int		rc;
161154133Sharti
162154133Sharti	ZERO(isc_sa);
163154133Sharti	memcpy(&isc_sa.type, psa,
164154133Sharti	       min(sizeof(isc_sa.type), sizeof(*psa)));
165154133Sharti	isc_netaddr_fromsockaddr(&isc_na, &isc_sa);
166160341Sharti	result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen);
167160341Sharti	rc = (ISC_R_SUCCESS == result)
168160341Sharti		 ? (int)pfxlen
169154133Sharti		 : -1;
170160341Sharti
171160341Sharti	return rc;
172160341Sharti}
173160341Sharti