Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / libisc / sockaddr.c
blob20a0e73ce345b0b5ed5a128c550aec7b577e0cd2
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: sockaddr.c,v 1.48.2.1.2.10 2004/05/15 03:46:12 jinmei Exp */
22 #include <config.h>
24 #define ISC_ONLY_IPV6
26 #include <stdio.h>
28 #include <isc/buffer.h>
30 * We currently don't need hashing here
32 #if 0
33 #include <isc/hash.h>
34 #endif
36 #include <isc/msgs.h>
37 #include <isc/netaddr.h>
38 #include <isc/print.h>
39 #include <isc/region.h>
40 #include <isc/sockaddr.h>
41 #include <isc/string.h>
42 #include <isc/util.h>
44 isc_boolean_t
45 isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
46 REQUIRE(a != NULL && b != NULL);
48 if (a->length != b->length)
49 return (ISC_FALSE);
52 * We don't just memcmp because the sin_zero field isn't always
53 * zero.
56 if (a->type.sa.sa_family != b->type.sa.sa_family)
57 return (ISC_FALSE);
58 switch (a->type.sa.sa_family) {
59 case AF_INET:
60 if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
61 sizeof(a->type.sin.sin_addr)) != 0)
62 return (ISC_FALSE);
63 if (a->type.sin.sin_port != b->type.sin.sin_port)
64 return (ISC_FALSE);
65 break;
66 case AF_INET6:
67 if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
68 sizeof(a->type.sin6.sin6_addr)) != 0)
69 return (ISC_FALSE);
70 #ifdef ISC_PLATFORM_HAVESCOPEID
71 if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id)
72 return (ISC_FALSE);
73 #endif
74 if (a->type.sin6.sin6_port != b->type.sin6.sin6_port)
75 return (ISC_FALSE);
76 break;
77 default:
78 if (memcmp(&a->type, &b->type, a->length) != 0)
79 return (ISC_FALSE);
81 return (ISC_TRUE);
84 isc_boolean_t
85 isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
86 REQUIRE(a != NULL && b != NULL);
88 if (a->length != b->length)
89 return (ISC_FALSE);
91 if (a->type.sa.sa_family != b->type.sa.sa_family)
92 return (ISC_FALSE);
93 switch (a->type.sa.sa_family) {
94 case AF_INET:
95 if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
96 sizeof(a->type.sin.sin_addr)) != 0)
97 return (ISC_FALSE);
98 break;
99 case AF_INET6:
100 if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
101 sizeof(a->type.sin6.sin6_addr)) != 0)
102 return (ISC_FALSE);
103 #ifdef ISC_PLATFORM_HAVESCOPEID
104 if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id)
105 return (ISC_FALSE);
106 #endif
107 break;
108 default:
109 if (memcmp(&a->type, &b->type, a->length) != 0)
110 return (ISC_FALSE);
112 return (ISC_TRUE);
115 isc_boolean_t
116 isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
117 unsigned int prefixlen)
119 isc_netaddr_t na, nb;
120 isc_netaddr_fromsockaddr(&na, a);
121 isc_netaddr_fromsockaddr(&nb, b);
122 return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
125 isc_result_t
126 isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
127 isc_result_t result;
128 isc_netaddr_t netaddr;
129 char pbuf[sizeof("65000")];
130 unsigned int plen;
131 isc_region_t avail;
133 REQUIRE(sockaddr != NULL);
136 * Do the port first, giving us the opportunity to check for
137 * unsupported address families before calling
138 * isc_netaddr_fromsockaddr().
140 switch (sockaddr->type.sa.sa_family) {
141 case AF_INET:
142 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
143 break;
144 case AF_INET6:
145 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
146 break;
147 default:
148 return (ISC_R_FAILURE);
151 plen = strlen(pbuf);
152 INSIST(plen < sizeof(pbuf));
154 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
155 result = isc_netaddr_totext(&netaddr, target);
156 if (result != ISC_R_SUCCESS)
157 return (result);
159 if (1 + plen + 1 > isc_buffer_availablelength(target))
160 return (ISC_R_NOSPACE);
162 isc_buffer_putmem(target, (const unsigned char *)"#", 1);
163 isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
166 * Null terminate after used region.
168 isc_buffer_availableregion(target, &avail);
169 INSIST(avail.length >= 1);
170 avail.base[0] = '\0';
172 return (ISC_R_SUCCESS);
175 void
176 isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
177 isc_result_t result;
178 isc_buffer_t buf;
180 isc_buffer_init(&buf, array, size);
181 result = isc_sockaddr_totext(sa, &buf);
182 if (result != ISC_R_SUCCESS) {
184 * The message is the same as in netaddr.c.
186 snprintf(array, size,
187 isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
188 ISC_MSG_UNKNOWNADDR,
189 "<unknown address, family %u>"),
190 sa->type.sa.sa_family);
191 array[size - 1] = '\0';
195 #if 0
197 * We currently don't need hashing here
199 unsigned int
200 isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
201 unsigned int length = 0;
202 const unsigned char *s = NULL;
203 unsigned int h = 0;
204 unsigned int g;
205 unsigned int p = 0;
206 const struct in6_addr *in6;
208 REQUIRE(sockaddr != NULL);
210 switch (sockaddr->type.sa.sa_family) {
211 case AF_INET:
212 s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
213 p = ntohs(sockaddr->type.sin.sin_port);
214 length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
215 break;
216 #if ISC_PLATFORM_HAVEIPV6
217 case AF_INET6:
218 in6 = &sockaddr->type.sin6.sin6_addr;
219 if (IN6_IS_ADDR_V4MAPPED(in6)) {
220 s = (const unsigned char *)&in6[12];
221 length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
222 } else {
223 s = (const unsigned char *)in6;
224 length = sizeof(sockaddr->type.sin6.sin6_addr);
226 p = ntohs(sockaddr->type.sin6.sin6_port);
227 break;
228 #endif
229 default:
230 UNEXPECTED_ERROR(__FILE__, __LINE__,
231 isc_msgcat_get(isc_msgcat,
232 ISC_MSGSET_SOCKADDR,
233 ISC_MSG_UNKNOWNFAMILY,
234 "unknown address family: %d"),
235 (int)sockaddr->type.sa.sa_family);
236 s = (const unsigned char *)&sockaddr->type;
237 length = sockaddr->length;
238 p = 0;
241 h = isc_hash_calc(s, length, ISC_TRUE);
242 if (!address_only) {
243 g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
244 ISC_TRUE);
245 h = h ^ g; /* XXX: we should concatenate h and p first */
248 return (h);
250 #endif
252 void
253 isc_sockaddr_any(isc_sockaddr_t *sockaddr)
255 memset(sockaddr, 0, sizeof(*sockaddr));
256 sockaddr->type.sin.sin_family = AF_INET;
257 #ifdef ISC_PLATFORM_HAVESALEN
258 sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
259 #endif
260 sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
261 sockaddr->type.sin.sin_port = 0;
262 sockaddr->length = sizeof(sockaddr->type.sin);
263 ISC_LINK_INIT(sockaddr, link);
266 void
267 isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
269 #ifdef ISC_PLATFORM_HAVEIPV6
270 memset(sockaddr, 0, sizeof(*sockaddr));
271 sockaddr->type.sin6.sin6_family = AF_INET6;
272 #ifdef ISC_PLATFORM_HAVESALEN
273 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
274 #endif
275 sockaddr->type.sin6.sin6_addr = in6addr_any;
276 sockaddr->type.sin6.sin6_port = 0;
277 sockaddr->length = sizeof(sockaddr->type.sin6);
278 ISC_LINK_INIT(sockaddr, link);
279 #endif
282 void
283 isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
284 in_port_t port)
286 memset(sockaddr, 0, sizeof(*sockaddr));
287 sockaddr->type.sin.sin_family = AF_INET;
288 #ifdef ISC_PLATFORM_HAVESALEN
289 sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
290 #endif
291 sockaddr->type.sin.sin_addr = *ina;
292 sockaddr->type.sin.sin_port = htons(port);
293 sockaddr->length = sizeof(sockaddr->type.sin);
294 ISC_LINK_INIT(sockaddr, link);
297 void
298 isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
299 switch (pf) {
300 case AF_INET:
301 isc_sockaddr_any(sockaddr);
302 break;
303 case AF_INET6:
304 isc_sockaddr_any6(sockaddr);
305 break;
306 default:
307 INSIST(0);
311 void
312 isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
313 in_port_t port)
315 memset(sockaddr, 0, sizeof(*sockaddr));
316 sockaddr->type.sin6.sin6_family = AF_INET6;
317 #ifdef ISC_PLATFORM_HAVESALEN
318 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
319 #endif
320 sockaddr->type.sin6.sin6_addr = *ina6;
321 sockaddr->type.sin6.sin6_port = htons(port);
322 sockaddr->length = sizeof(sockaddr->type.sin6);
323 ISC_LINK_INIT(sockaddr, link);
326 void
327 isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
328 in_port_t port)
330 memset(sockaddr, 0, sizeof(*sockaddr));
331 sockaddr->type.sin6.sin6_family = AF_INET6;
332 #ifdef ISC_PLATFORM_HAVESALEN
333 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
334 #endif
335 sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
336 sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
337 memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
338 sockaddr->type.sin6.sin6_port = htons(port);
339 sockaddr->length = sizeof(sockaddr->type.sin6);
340 ISC_LINK_INIT(sockaddr, link);
344 isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
347 * Get the protocol family of 'sockaddr'.
350 #if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
352 * Assume that PF_xxx == AF_xxx for all AF and PF.
354 return (sockaddr->type.sa.sa_family);
355 #else
356 switch (sockaddr->type.sa.sa_family) {
357 case AF_INET:
358 return (PF_INET);
359 case AF_INET6:
360 return (PF_INET6);
361 default:
362 FATAL_ERROR(__FILE__, __LINE__,
363 isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
364 ISC_MSG_UNKNOWNFAMILY,
365 "unknown address family: %d"),
366 (int)sockaddr->type.sa.sa_family);
368 #endif
371 void
372 isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
373 in_port_t port)
375 memset(sockaddr, 0, sizeof(*sockaddr));
376 sockaddr->type.sin.sin_family = na->family;
377 switch (na->family) {
378 case AF_INET:
379 sockaddr->length = sizeof(sockaddr->type.sin);
380 #ifdef ISC_PLATFORM_HAVESALEN
381 sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
382 #endif
383 sockaddr->type.sin.sin_addr = na->type.in;
384 sockaddr->type.sin.sin_port = htons(port);
385 break;
386 case AF_INET6:
387 sockaddr->length = sizeof(sockaddr->type.sin6);
388 #ifdef ISC_PLATFORM_HAVESALEN
389 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
390 #endif
391 memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
392 #ifdef ISC_PLATFORM_HAVESCOPEID
393 sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
394 #endif
395 sockaddr->type.sin6.sin6_port = htons(port);
396 break;
397 default:
398 INSIST(0);
400 ISC_LINK_INIT(sockaddr, link);
403 void
404 isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
405 switch (sockaddr->type.sa.sa_family) {
406 case AF_INET:
407 sockaddr->type.sin.sin_port = htons(port);
408 break;
409 case AF_INET6:
410 sockaddr->type.sin6.sin6_port = htons(port);
411 break;
412 default:
413 FATAL_ERROR(__FILE__, __LINE__,
414 isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
415 ISC_MSG_UNKNOWNFAMILY,
416 "unknown address family: %d"),
417 (int)sockaddr->type.sa.sa_family);
421 in_port_t
422 isc_sockaddr_getport(isc_sockaddr_t *sockaddr) {
423 in_port_t port = 0;
425 switch (sockaddr->type.sa.sa_family) {
426 case AF_INET:
427 port = ntohs(sockaddr->type.sin.sin_port);
428 break;
429 case AF_INET6:
430 port = ntohs(sockaddr->type.sin6.sin6_port);
431 break;
432 default:
433 FATAL_ERROR(__FILE__, __LINE__,
434 isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
435 ISC_MSG_UNKNOWNFAMILY,
436 "unknown address family: %d"),
437 (int)sockaddr->type.sa.sa_family);
440 return (port);
443 isc_boolean_t
444 isc_sockaddr_ismulticast(isc_sockaddr_t *sockaddr) {
445 isc_netaddr_t netaddr;
447 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
448 return (isc_netaddr_ismulticast(&netaddr));
451 isc_boolean_t
452 isc_sockaddr_isexperimental(isc_sockaddr_t *sockaddr) {
453 isc_netaddr_t netaddr;
455 if (sockaddr->type.sa.sa_family == AF_INET) {
456 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
457 return (isc_netaddr_isexperimental(&netaddr));
459 return (ISC_FALSE);
462 isc_boolean_t
463 isc_sockaddr_issitelocal(isc_sockaddr_t *sockaddr) {
464 isc_netaddr_t netaddr;
466 if (sockaddr->type.sa.sa_family == AF_INET6) {
467 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
468 return (isc_netaddr_issitelocal(&netaddr));
470 return (ISC_FALSE);
473 isc_boolean_t
474 isc_sockaddr_islinklocal(isc_sockaddr_t *sockaddr) {
475 isc_netaddr_t netaddr;
477 if (sockaddr->type.sa.sa_family == AF_INET6) {
478 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
479 return (isc_netaddr_islinklocal(&netaddr));
481 return (ISC_FALSE);