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