Merge from vendor branch NTPD:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isc / sockaddr.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: sockaddr.c,v 1.48.2.5 2004/03/09 06:11:51 marka Exp $ */
19
20 #include <config.h>
21
22 #include <stdio.h>
23
24 #include <isc/buffer.h>
25 #include <isc/hash.h>
26 #include <isc/msgs.h>
27 #include <isc/netaddr.h>
28 #include <isc/print.h>
29 #include <isc/region.h>
30 #include <isc/sockaddr.h>
31 #include <isc/string.h>
32 #include <isc/util.h>
33
34 isc_boolean_t
35 isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
36         REQUIRE(a != NULL && b != NULL);
37
38         if (a->length != b->length)
39                 return (ISC_FALSE);
40
41         /*
42          * We don't just memcmp because the sin_zero field isn't always
43          * zero.
44          */
45
46         if (a->type.sa.sa_family != b->type.sa.sa_family)
47                 return (ISC_FALSE);
48         switch (a->type.sa.sa_family) {
49         case AF_INET:
50                 if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
51                            sizeof(a->type.sin.sin_addr)) != 0)
52                         return (ISC_FALSE);
53                 if (a->type.sin.sin_port != b->type.sin.sin_port)
54                         return (ISC_FALSE);
55                 break;
56         case AF_INET6:
57                 if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
58                            sizeof(a->type.sin6.sin6_addr)) != 0)
59                         return (ISC_FALSE);
60                 if (a->type.sin6.sin6_port != b->type.sin6.sin6_port)
61                         return (ISC_FALSE);
62                 break;
63         default:
64                 if (memcmp(&a->type, &b->type, a->length) != 0)
65                         return (ISC_FALSE);
66         }
67         return (ISC_TRUE);
68 }
69
70 isc_boolean_t
71 isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
72         REQUIRE(a != NULL && b != NULL);
73
74         if (a->length != b->length)
75                 return (ISC_FALSE);
76
77         if (a->type.sa.sa_family != b->type.sa.sa_family)
78                 return (ISC_FALSE);
79         switch (a->type.sa.sa_family) {
80         case AF_INET:
81                 if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
82                            sizeof(a->type.sin.sin_addr)) != 0)
83                         return (ISC_FALSE);
84                 break;
85         case AF_INET6:
86                 if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
87                            sizeof(a->type.sin6.sin6_addr)) != 0)
88                         return (ISC_FALSE);
89                 break;
90         default:
91                 if (memcmp(&a->type, &b->type, a->length) != 0)
92                         return (ISC_FALSE);
93         }
94         return (ISC_TRUE);
95 }
96
97 isc_boolean_t
98 isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
99                           unsigned int prefixlen)
100 {
101         isc_netaddr_t na, nb;
102         isc_netaddr_fromsockaddr(&na, a);
103         isc_netaddr_fromsockaddr(&nb, b);
104         return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
105 }
106
107 isc_result_t
108 isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
109         isc_result_t result;
110         isc_netaddr_t netaddr;
111         char pbuf[sizeof("65000")];
112         unsigned int plen;
113         isc_region_t avail;
114
115         REQUIRE(sockaddr != NULL);
116
117         /*
118          * Do the port first, giving us the opportunity to check for
119          * unsupported address families before calling
120          * isc_netaddr_fromsockaddr().
121          */
122         switch (sockaddr->type.sa.sa_family) {
123         case AF_INET:
124                 sprintf(pbuf, "%u", ntohs(sockaddr->type.sin.sin_port));
125                 break;
126         case AF_INET6:
127                 sprintf(pbuf, "%u", ntohs(sockaddr->type.sin6.sin6_port));
128                 break;
129         default:
130                 return (ISC_R_FAILURE);
131         }
132
133         plen = strlen(pbuf);
134         INSIST(plen < sizeof(pbuf));
135
136         isc_netaddr_fromsockaddr(&netaddr, sockaddr);
137         result = isc_netaddr_totext(&netaddr, target);
138         if (result != ISC_R_SUCCESS)
139                 return (result);
140
141         if (1 + plen + 1 > isc_buffer_availablelength(target))
142                 return (ISC_R_NOSPACE);
143
144         isc_buffer_putmem(target, (const unsigned char *)"#", 1);
145         isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
146
147         /*
148          * Null terminate after used region.
149          */
150         isc_buffer_availableregion(target, &avail);
151         INSIST(avail.length >= 1);
152         avail.base[0] = '\0';
153
154         return (ISC_R_SUCCESS);
155 }
156
157 void
158 isc_sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size) {
159         isc_result_t result;
160         isc_buffer_t buf;
161
162         isc_buffer_init(&buf, array, size);
163         result = isc_sockaddr_totext(sa, &buf);
164         if (result != ISC_R_SUCCESS) {
165                 /*
166                  * The message is the same as in netaddr.c.
167                  */
168                 snprintf(array, size,
169                          isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
170                                         ISC_MSG_UNKNOWNADDR,
171                                         "<unknown address, family %u>"),
172                          sa->type.sa.sa_family);
173                 array[size - 1] = '\0';
174         }
175 }
176
177 unsigned int
178 isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
179         unsigned int length = 0;
180         const unsigned char *s = NULL;
181         unsigned int h = 0;
182         unsigned int g;
183         unsigned int p = 0;
184         const struct in6_addr *in6;
185
186         REQUIRE(sockaddr != NULL);
187         switch (sockaddr->type.sa.sa_family) {
188         case AF_INET:
189                 s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
190                 p = ntohs(sockaddr->type.sin.sin_port);
191                 length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
192                 break;
193         case AF_INET6:
194                 in6 = &sockaddr->type.sin6.sin6_addr;
195                 if (IN6_IS_ADDR_V4MAPPED(in6)) {
196                         s = (const unsigned char *)&in6[12];
197                         length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
198                 } else {
199                         s = (const unsigned char *)in6;
200                         length = sizeof(sockaddr->type.sin6.sin6_addr);
201                 }
202                 p = ntohs(sockaddr->type.sin6.sin6_port);
203                 break;
204         default:
205                 UNEXPECTED_ERROR(__FILE__, __LINE__,
206                                  isc_msgcat_get(isc_msgcat,
207                                                 ISC_MSGSET_SOCKADDR,
208                                                 ISC_MSG_UNKNOWNFAMILY,
209                                                 "unknown address family: %d"),
210                                              (int)sockaddr->type.sa.sa_family);
211                 s = (const unsigned char *)&sockaddr->type;
212                 length = sockaddr->length;
213                 p = 0;
214         }
215
216         h = isc_hash_calc(s, length, ISC_TRUE);
217         if (!address_only) {
218                 g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
219                                   ISC_TRUE);
220                 h = h ^ g; /* XXX: we should concatenate h and p first */
221         }
222
223         return (h);
224 }
225
226 void
227 isc_sockaddr_any(isc_sockaddr_t *sockaddr)
228 {
229         memset(sockaddr, 0, sizeof(*sockaddr));
230         sockaddr->type.sin.sin_family = AF_INET;
231 #ifdef ISC_PLATFORM_HAVESALEN
232         sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
233 #endif
234         sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
235         sockaddr->type.sin.sin_port = 0;
236         sockaddr->length = sizeof(sockaddr->type.sin);
237         ISC_LINK_INIT(sockaddr, link);
238 }
239
240 void
241 isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
242 {
243         memset(sockaddr, 0, sizeof(*sockaddr));
244         sockaddr->type.sin6.sin6_family = AF_INET6;
245 #ifdef ISC_PLATFORM_HAVESALEN
246         sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
247 #endif
248         sockaddr->type.sin6.sin6_addr = in6addr_any;
249         sockaddr->type.sin6.sin6_port = 0;
250         sockaddr->length = sizeof(sockaddr->type.sin6);
251         ISC_LINK_INIT(sockaddr, link);
252 }
253
254 void
255 isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
256                     in_port_t port)
257 {
258         memset(sockaddr, 0, sizeof(*sockaddr));
259         sockaddr->type.sin.sin_family = AF_INET;
260 #ifdef ISC_PLATFORM_HAVESALEN
261         sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
262 #endif
263         sockaddr->type.sin.sin_addr = *ina;
264         sockaddr->type.sin.sin_port = htons(port);
265         sockaddr->length = sizeof(sockaddr->type.sin);
266         ISC_LINK_INIT(sockaddr, link);
267 }
268
269 void
270 isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
271      switch (pf) {
272      case AF_INET:
273              isc_sockaddr_any(sockaddr);
274              break;
275      case AF_INET6:
276              isc_sockaddr_any6(sockaddr);
277              break;
278      default:
279              INSIST(0);
280      }
281 }
282
283 void
284 isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
285                      in_port_t port)
286 {
287         memset(sockaddr, 0, sizeof(*sockaddr));
288         sockaddr->type.sin6.sin6_family = AF_INET6;
289 #ifdef ISC_PLATFORM_HAVESALEN
290         sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
291 #endif
292         sockaddr->type.sin6.sin6_addr = *ina6;
293         sockaddr->type.sin6.sin6_port = htons(port);
294         sockaddr->length = sizeof(sockaddr->type.sin6);
295         ISC_LINK_INIT(sockaddr, link);
296 }
297
298 void
299 isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
300                       in_port_t port)
301 {
302         memset(sockaddr, 0, sizeof(*sockaddr));
303         sockaddr->type.sin6.sin6_family = AF_INET6;
304 #ifdef ISC_PLATFORM_HAVESALEN
305         sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
306 #endif
307         sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
308         sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
309         memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
310         sockaddr->type.sin6.sin6_port = htons(port);
311         sockaddr->length = sizeof(sockaddr->type.sin6);
312         ISC_LINK_INIT(sockaddr, link);
313 }
314
315 int
316 isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
317
318         /*
319          * Get the protocol family of 'sockaddr'.
320          */
321
322 #if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
323         /*
324          * Assume that PF_xxx == AF_xxx for all AF and PF.
325          */
326         return (sockaddr->type.sa.sa_family);
327 #else
328         switch (sockaddr->type.sa.sa_family) {
329         case AF_INET:
330                 return (PF_INET);
331         case AF_INET6:
332                 return (PF_INET6);
333         default:
334                 FATAL_ERROR(__FILE__, __LINE__,
335                             isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
336                                            ISC_MSG_UNKNOWNFAMILY,
337                                            "unknown address family: %d"),
338                             (int)sockaddr->type.sa.sa_family);
339         }
340 #endif
341 }
342
343 void
344 isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
345                     in_port_t port)
346 {
347         memset(sockaddr, 0, sizeof(*sockaddr));
348         sockaddr->type.sin.sin_family = na->family;
349         switch (na->family) {
350         case AF_INET:
351                 sockaddr->length = sizeof(sockaddr->type.sin);
352 #ifdef ISC_PLATFORM_HAVESALEN
353                 sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
354 #endif
355                 sockaddr->type.sin.sin_addr = na->type.in;
356                 sockaddr->type.sin.sin_port = htons(port);
357                 break;
358         case AF_INET6:
359                 sockaddr->length = sizeof(sockaddr->type.sin6);
360 #ifdef ISC_PLATFORM_HAVESALEN
361                 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
362 #endif
363                 memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
364                 sockaddr->type.sin6.sin6_port = htons(port);
365                 break;
366         default:
367                 INSIST(0);
368         }
369         ISC_LINK_INIT(sockaddr, link);
370 }
371
372 void
373 isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
374         switch (sockaddr->type.sa.sa_family) {
375         case AF_INET:
376                 sockaddr->type.sin.sin_port = htons(port);
377                 break;
378         case AF_INET6:
379                 sockaddr->type.sin6.sin6_port = htons(port);
380                 break;
381         default:
382                 FATAL_ERROR(__FILE__, __LINE__,
383                             isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
384                                            ISC_MSG_UNKNOWNFAMILY,
385                                            "unknown address family: %d"),
386                             (int)sockaddr->type.sa.sa_family);
387         }
388 }
389
390 in_port_t
391 isc_sockaddr_getport(isc_sockaddr_t *sockaddr) {
392         in_port_t port = 0;
393
394         switch (sockaddr->type.sa.sa_family) {
395         case AF_INET:
396                 port = ntohs(sockaddr->type.sin.sin_port);
397                 break;
398         case AF_INET6:
399                 port = ntohs(sockaddr->type.sin6.sin6_port);
400                 break;
401         default:
402                 FATAL_ERROR(__FILE__, __LINE__,
403                             isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
404                                            ISC_MSG_UNKNOWNFAMILY,
405                                            "unknown address family: %d"),
406                             (int)sockaddr->type.sa.sa_family);
407         }
408
409         return (port);
410 }
411
412 isc_boolean_t
413 isc_sockaddr_ismulticast(isc_sockaddr_t *sockaddr) {
414         isc_netaddr_t netaddr;
415
416         isc_netaddr_fromsockaddr(&netaddr, sockaddr);
417         return (isc_netaddr_ismulticast(&netaddr));
418 }
419
420 isc_boolean_t
421 isc_sockaddr_isexperimental(isc_sockaddr_t *sockaddr) {
422         isc_netaddr_t netaddr;
423
424         if (sockaddr->type.sa.sa_family == AF_INET) {
425                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
426                 return (isc_netaddr_isexperimental(&netaddr));
427         }
428         return (ISC_FALSE);
429 }