1132451Sroberto/*
2280849Scy * socktoa.c	socktoa(), sockporttoa(), and sock_hash()
3132451Sroberto */
4132451Sroberto
5280849Scy#ifdef HAVE_CONFIG_H
6132451Sroberto#include <config.h>
7280849Scy#endif
8132451Sroberto
9132451Sroberto#include <sys/types.h>
10280849Scy#ifdef HAVE_SYS_SOCKET_H
11132451Sroberto#include <sys/socket.h>
12280849Scy#endif
13280849Scy#ifdef HAVE_NETINET_IN_H
14132451Sroberto#include <netinet/in.h>
15132451Sroberto#endif
16132451Sroberto
17132451Sroberto#include <stdio.h>
18280849Scy#include <arpa/inet.h>
19280849Scy#include <isc/result.h>
20280849Scy#include <isc/netaddr.h>
21280849Scy#include <isc/sockaddr.h>
22132451Sroberto
23132451Sroberto#include "ntp_fp.h"
24132451Sroberto#include "lib_strbuf.h"
25132451Sroberto#include "ntp_stdlib.h"
26132451Sroberto#include "ntp.h"
27132451Sroberto
28280849Scy/*
29280849Scy * socktoa - return a numeric host name from a sockaddr_storage structure
30280849Scy */
31280849Scyconst char *
32132451Srobertosocktoa(
33280849Scy	const sockaddr_u *sock
34132451Sroberto	)
35132451Sroberto{
36280849Scy	int		saved_errno;
37280849Scy	char *		res;
38280849Scy	char *		addr;
39280849Scy	u_long		scope;
40132451Sroberto
41280849Scy	saved_errno = socket_errno();
42280849Scy	LIB_GETBUF(res);
43132451Sroberto
44280849Scy	if (NULL == sock) {
45280849Scy		strlcpy(res, "(null)", LIB_BUFLENGTH);
46280849Scy	} else {
47280849Scy		switch(AF(sock)) {
48132451Sroberto
49280849Scy		case AF_INET:
50280849Scy		case AF_UNSPEC:
51280849Scy			inet_ntop(AF_INET, PSOCK_ADDR4(sock), res,
52280849Scy				  LIB_BUFLENGTH);
53280849Scy			break;
54132451Sroberto
55280849Scy		case AF_INET6:
56280849Scy			inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res,
57280849Scy				  LIB_BUFLENGTH);
58280849Scy			scope = SCOPE_VAR(sock);
59280849Scy			if (0 != scope && !strchr(res, '%')) {
60280849Scy				addr = res;
61280849Scy				LIB_GETBUF(res);
62280849Scy				snprintf(res, LIB_BUFLENGTH, "%s%%%lu",
63280849Scy					 addr, scope);
64280849Scy				res[LIB_BUFLENGTH - 1] = '\0';
65280849Scy			}
66132451Sroberto			break;
67132451Sroberto
68182007Sroberto		default:
69280849Scy			snprintf(res, LIB_BUFLENGTH,
70280849Scy				 "(socktoa unknown family %d)",
71280849Scy				 AF(sock));
72182007Sroberto		}
73132451Sroberto	}
74280849Scy	errno = saved_errno;
75280849Scy
76280849Scy	return res;
77132451Sroberto}
78280849Scy
79280849Scy
80280849Scyconst char *
81280849Scysockporttoa(
82280849Scy	const sockaddr_u *sock
83280849Scy	)
84280849Scy{
85280849Scy	int		saved_errno;
86280849Scy	const char *	atext;
87280849Scy	char *		buf;
88280849Scy
89280849Scy	saved_errno = socket_errno();
90280849Scy	atext = socktoa(sock);
91280849Scy	LIB_GETBUF(buf);
92280849Scy	snprintf(buf, LIB_BUFLENGTH,
93280849Scy		 (IS_IPV6(sock))
94280849Scy		     ? "[%s]:%hu"
95280849Scy		     : "%s:%hu",
96280849Scy		 atext, SRCPORT(sock));
97280849Scy	errno = saved_errno;
98280849Scy
99280849Scy	return buf;
100280849Scy}
101280849Scy
102280849Scy
103280849Scy/*
104280849Scy * sock_hash - hash a sockaddr_u structure
105280849Scy */
106280849Scyu_short
107280849Scysock_hash(
108280849Scy	const sockaddr_u *addr
109280849Scy	)
110280849Scy{
111280849Scy	u_int hashVal;
112280849Scy	u_int j;
113280849Scy	size_t len;
114280849Scy	const u_char *pch;
115280849Scy
116280849Scy	hashVal = 0;
117280849Scy	len = 0;
118280849Scy
119280849Scy	/*
120280849Scy	 * We can't just hash the whole thing because there are hidden
121280849Scy	 * fields in sockaddr_in6 that might be filled in by recvfrom(),
122280849Scy	 * so just use the family, port and address.
123280849Scy	 */
124280849Scy	pch = (const void *)&AF(addr);
125280849Scy	hashVal = 37 * hashVal + *pch;
126280849Scy	if (sizeof(AF(addr)) > 1) {
127280849Scy		pch++;
128280849Scy		hashVal = 37 * hashVal + *pch;
129280849Scy	}
130280849Scy	switch(AF(addr)) {
131280849Scy	case AF_INET:
132280849Scy		pch = (const void *)&SOCK_ADDR4(addr);
133280849Scy		len = sizeof(SOCK_ADDR4(addr));
134280849Scy		break;
135280849Scy
136280849Scy	case AF_INET6:
137280849Scy		pch = (const void *)&SOCK_ADDR6(addr);
138280849Scy		len = sizeof(SOCK_ADDR6(addr));
139280849Scy		break;
140280849Scy	}
141280849Scy
142280849Scy	for (j = 0; j < len ; j++)
143280849Scy		hashVal = 37 * hashVal + pch[j];
144280849Scy
145280849Scy	return (u_short)(hashVal & USHRT_MAX);
146280849Scy}
147280849Scy
148280849Scy
149280849Scyint
150280849Scysockaddr_masktoprefixlen(
151280849Scy	const sockaddr_u *	psa
152280849Scy	)
153280849Scy{
154280849Scy	isc_netaddr_t	isc_na;
155280849Scy	isc_sockaddr_t	isc_sa;
156280849Scy	u_int		pfxlen;
157280849Scy	isc_result_t	result;
158280849Scy	int		rc;
159280849Scy
160280849Scy	ZERO(isc_sa);
161280849Scy	memcpy(&isc_sa.type, psa,
162280849Scy	       min(sizeof(isc_sa.type), sizeof(*psa)));
163280849Scy	isc_netaddr_fromsockaddr(&isc_na, &isc_sa);
164280849Scy	result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen);
165280849Scy	rc = (ISC_R_SUCCESS == result)
166280849Scy		 ? (int)pfxlen
167280849Scy		 : -1;
168280849Scy
169280849Scy	return rc;
170280849Scy}
171