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