Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / bind-9.3 / lib / isc / sockaddr.c
1 /*
2  * Copyright (C) 2004, 2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-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.1.2.12 2006/03/02 00:37:20 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 #ifdef ISC_PLATFORM_HAVESCOPEID
61                 if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id)
62                         return (ISC_FALSE);
63 #endif
64                 if (a->type.sin6.sin6_port != b->type.sin6.sin6_port)
65                         return (ISC_FALSE);
66                 break;
67         default:
68                 if (memcmp(&a->type, &b->type, a->length) != 0)
69                         return (ISC_FALSE);
70         }
71         return (ISC_TRUE);
72 }
73
74 isc_boolean_t
75 isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
76         REQUIRE(a != NULL && b != NULL);
77
78         if (a->length != b->length)
79                 return (ISC_FALSE);
80
81         if (a->type.sa.sa_family != b->type.sa.sa_family)
82                 return (ISC_FALSE);
83         switch (a->type.sa.sa_family) {
84         case AF_INET:
85                 if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
86                            sizeof(a->type.sin.sin_addr)) != 0)
87                         return (ISC_FALSE);
88                 break;
89         case AF_INET6:
90                 if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
91                            sizeof(a->type.sin6.sin6_addr)) != 0)
92                         return (ISC_FALSE);
93 #ifdef ISC_PLATFORM_HAVESCOPEID
94                 if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id)
95                         return (ISC_FALSE);
96 #endif
97                 break;
98         default:
99                 if (memcmp(&a->type, &b->type, a->length) != 0)
100                         return (ISC_FALSE);
101         }
102         return (ISC_TRUE);
103 }
104
105 isc_boolean_t
106 isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
107                           unsigned int prefixlen)
108 {
109         isc_netaddr_t na, nb;
110         isc_netaddr_fromsockaddr(&na, a);
111         isc_netaddr_fromsockaddr(&nb, b);
112         return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
113 }
114
115 isc_result_t
116 isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
117         isc_result_t result;
118         isc_netaddr_t netaddr;
119         char pbuf[sizeof("65000")];
120         unsigned int plen;
121         isc_region_t avail;
122
123         REQUIRE(sockaddr != NULL);
124
125         /*
126          * Do the port first, giving us the opportunity to check for
127          * unsupported address families before calling
128          * isc_netaddr_fromsockaddr().
129          */
130         switch (sockaddr->type.sa.sa_family) {
131         case AF_INET:
132                 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
133                 break;
134         case AF_INET6:
135                 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
136                 break;
137         default:
138                 return (ISC_R_FAILURE);
139         }
140
141         plen = strlen(pbuf);
142         INSIST(plen < sizeof(pbuf));
143
144         isc_netaddr_fromsockaddr(&netaddr, sockaddr);
145         result = isc_netaddr_totext(&netaddr, target);
146         if (result != ISC_R_SUCCESS)
147                 return (result);
148
149         if (1 + plen + 1 > isc_buffer_availablelength(target))
150                 return (ISC_R_NOSPACE);
151
152         isc_buffer_putmem(target, (const unsigned char *)"#", 1);
153         isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
154
155         /*
156          * Null terminate after used region.
157          */
158         isc_buffer_availableregion(target, &avail);
159         INSIST(avail.length >= 1);
160         avail.base[0] = '\0';
161
162         return (ISC_R_SUCCESS);
163 }
164
165 void
166 isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
167         isc_result_t result;
168         isc_buffer_t buf;
169
170         isc_buffer_init(&buf, array, size);
171         result = isc_sockaddr_totext(sa, &buf);
172         if (result != ISC_R_SUCCESS) {
173                 /*
174                  * The message is the same as in netaddr.c.
175                  */
176                 snprintf(array, size,
177                          isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
178                                         ISC_MSG_UNKNOWNADDR,
179                                         "<unknown address, family %u>"),
180                          sa->type.sa.sa_family);
181                 array[size - 1] = '\0';
182         }
183 }
184
185 unsigned int
186 isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
187         unsigned int length = 0;
188         const unsigned char *s = NULL;
189         unsigned int h = 0;
190         unsigned int g;
191         unsigned int p = 0;
192         const struct in6_addr *in6;
193
194         REQUIRE(sockaddr != NULL);
195
196         switch (sockaddr->type.sa.sa_family) {
197         case AF_INET:
198                 s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
199                 p = ntohs(sockaddr->type.sin.sin_port);
200                 length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
201                 break;
202         case AF_INET6:
203                 in6 = &sockaddr->type.sin6.sin6_addr;
204                 if (IN6_IS_ADDR_V4MAPPED(in6)) {
205                         s = (const unsigned char *)&in6[12];
206                         length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
207                 } else {
208                         s = (const unsigned char *)in6;
209                         length = sizeof(sockaddr->type.sin6.sin6_addr);
210                 }
211                 p = ntohs(sockaddr->type.sin6.sin6_port);
212                 break;
213         default:
214                 UNEXPECTED_ERROR(__FILE__, __LINE__,
215                                  isc_msgcat_get(isc_msgcat,
216                                                 ISC_MSGSET_SOCKADDR,
217                                                 ISC_MSG_UNKNOWNFAMILY,
218                                                 "unknown address family: %d"),
219                                              (int)sockaddr->type.sa.sa_family);
220                 s = (const unsigned char *)&sockaddr->type;
221                 length = sockaddr->length;
222                 p = 0;
223         }
224
225         h = isc_hash_calc(s, length, ISC_TRUE);
226         if (!address_only) {
227                 g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
228                                   ISC_TRUE);
229                 h = h ^ g; /* XXX: we should concatenate h and p first */
230         }
231
232         return (h);
233 }
234
235 void
236 isc_sockaddr_any(isc_sockaddr_t *sockaddr)
237 {
238         memset(sockaddr, 0, sizeof(*sockaddr));
239         sockaddr->type.sin.sin_family = AF_INET;
240 #ifdef ISC_PLATFORM_HAVESALEN
241         sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
242 #endif
243         sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
244         sockaddr->type.sin.sin_port = 0;
245         sockaddr->length = sizeof(sockaddr->type.sin);
246         ISC_LINK_INIT(sockaddr, link);
247 }
248
249 void
250 isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
251 {
252         memset(sockaddr, 0, sizeof(*sockaddr));
253         sockaddr->type.sin6.sin6_family = AF_INET6;
254 #ifdef ISC_PLATFORM_HAVESALEN
255         sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
256 #endif
257         sockaddr->type.sin6.sin6_addr = in6addr_any;
258         sockaddr->type.sin6.sin6_port = 0;
259         sockaddr->length = sizeof(sockaddr->type.sin6);
260         ISC_LINK_INIT(sockaddr, link);
261 }
262
263 void
264 isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
265                     in_port_t port)
266 {
267         memset(sockaddr, 0, sizeof(*sockaddr));
268         sockaddr->type.sin.sin_family = AF_INET;
269 #ifdef ISC_PLATFORM_HAVESALEN
270         sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
271 #endif
272         sockaddr->type.sin.sin_addr = *ina;
273         sockaddr->type.sin.sin_port = htons(port);
274         sockaddr->length = sizeof(sockaddr->type.sin);
275         ISC_LINK_INIT(sockaddr, link);
276 }
277
278 void
279 isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
280      switch (pf) {
281      case AF_INET:
282              isc_sockaddr_any(sockaddr);
283              break;
284      case AF_INET6:
285              isc_sockaddr_any6(sockaddr);
286              break;
287      default:
288              INSIST(0);
289      }
290 }
291
292 void
293 isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
294                      in_port_t port)
295 {
296         memset(sockaddr, 0, sizeof(*sockaddr));
297         sockaddr->type.sin6.sin6_family = AF_INET6;
298 #ifdef ISC_PLATFORM_HAVESALEN
299         sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
300 #endif
301         sockaddr->type.sin6.sin6_addr = *ina6;
302         sockaddr->type.sin6.sin6_port = htons(port);
303         sockaddr->length = sizeof(sockaddr->type.sin6);
304         ISC_LINK_INIT(sockaddr, link);
305 }
306
307 void
308 isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
309                       in_port_t port)
310 {
311         memset(sockaddr, 0, sizeof(*sockaddr));
312         sockaddr->type.sin6.sin6_family = AF_INET6;
313 #ifdef ISC_PLATFORM_HAVESALEN
314         sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
315 #endif
316         sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
317         sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
318         memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
319         sockaddr->type.sin6.sin6_port = htons(port);
320         sockaddr->length = sizeof(sockaddr->type.sin6);
321         ISC_LINK_INIT(sockaddr, link);
322 }
323
324 int
325 isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
326
327         /*
328          * Get the protocol family of 'sockaddr'.
329          */
330
331 #if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
332         /*
333          * Assume that PF_xxx == AF_xxx for all AF and PF.
334          */
335         return (sockaddr->type.sa.sa_family);
336 #else
337         switch (sockaddr->type.sa.sa_family) {
338         case AF_INET:
339                 return (PF_INET);
340         case AF_INET6:
341                 return (PF_INET6);
342         default:
343                 FATAL_ERROR(__FILE__, __LINE__,
344                             isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
345                                            ISC_MSG_UNKNOWNFAMILY,
346                                            "unknown address family: %d"),
347                             (int)sockaddr->type.sa.sa_family);
348         }
349 #endif
350 }
351
352 void
353 isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
354                     in_port_t port)
355 {
356         memset(sockaddr, 0, sizeof(*sockaddr));
357         sockaddr->type.sin.sin_family = na->family;
358         switch (na->family) {
359         case AF_INET:
360                 sockaddr->length = sizeof(sockaddr->type.sin);
361 #ifdef ISC_PLATFORM_HAVESALEN
362                 sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
363 #endif
364                 sockaddr->type.sin.sin_addr = na->type.in;
365                 sockaddr->type.sin.sin_port = htons(port);
366                 break;
367         case AF_INET6:
368                 sockaddr->length = sizeof(sockaddr->type.sin6);
369 #ifdef ISC_PLATFORM_HAVESALEN
370                 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
371 #endif
372                 memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
373 #ifdef ISC_PLATFORM_HAVESCOPEID
374                 sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
375 #endif
376                 sockaddr->type.sin6.sin6_port = htons(port);
377                 break;
378         default:
379                 INSIST(0);
380         }
381         ISC_LINK_INIT(sockaddr, link);
382 }
383
384 void
385 isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
386         switch (sockaddr->type.sa.sa_family) {
387         case AF_INET:
388                 sockaddr->type.sin.sin_port = htons(port);
389                 break;
390         case AF_INET6:
391                 sockaddr->type.sin6.sin6_port = htons(port);
392                 break;
393         default:
394                 FATAL_ERROR(__FILE__, __LINE__,
395                             isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
396                                            ISC_MSG_UNKNOWNFAMILY,
397                                            "unknown address family: %d"),
398                             (int)sockaddr->type.sa.sa_family);
399         }
400 }
401
402 in_port_t
403 isc_sockaddr_getport(const isc_sockaddr_t *sockaddr) {
404         in_port_t port = 0;
405
406         switch (sockaddr->type.sa.sa_family) {
407         case AF_INET:
408                 port = ntohs(sockaddr->type.sin.sin_port);
409                 break;
410         case AF_INET6:
411                 port = ntohs(sockaddr->type.sin6.sin6_port);
412                 break;
413         default:
414                 FATAL_ERROR(__FILE__, __LINE__,
415                             isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
416                                            ISC_MSG_UNKNOWNFAMILY,
417                                            "unknown address family: %d"),
418                             (int)sockaddr->type.sa.sa_family);
419         }
420
421         return (port);
422 }
423
424 isc_boolean_t
425 isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) {
426         isc_netaddr_t netaddr;
427
428         isc_netaddr_fromsockaddr(&netaddr, sockaddr);
429         return (isc_netaddr_ismulticast(&netaddr));
430 }
431
432 isc_boolean_t
433 isc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) {
434         isc_netaddr_t netaddr;
435
436         if (sockaddr->type.sa.sa_family == AF_INET) {
437                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
438                 return (isc_netaddr_isexperimental(&netaddr));
439         }
440         return (ISC_FALSE);
441 }
442
443 isc_boolean_t
444 isc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) {
445         isc_netaddr_t netaddr;
446
447         if (sockaddr->type.sa.sa_family == AF_INET6) {
448                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
449                 return (isc_netaddr_issitelocal(&netaddr));
450         }
451         return (ISC_FALSE);
452 }
453
454 isc_boolean_t
455 isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) {
456         isc_netaddr_t netaddr;
457
458         if (sockaddr->type.sa.sa_family == AF_INET6) {
459                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
460                 return (isc_netaddr_islinklocal(&netaddr));
461         }
462         return (ISC_FALSE);
463 }