00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <stdio.h>
00025
00026 #include <isc/buffer.h>
00027 #include <isc/hash.h>
00028 #include <isc/msgs.h>
00029 #include <isc/netaddr.h>
00030 #include <isc/print.h>
00031 #include <isc/region.h>
00032 #include <isc/sockaddr.h>
00033 #include <isc/string.h>
00034 #include <isc/util.h>
00035
00036 isc_boolean_t
00037 isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
00038 return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
00039 ISC_SOCKADDR_CMPPORT|
00040 ISC_SOCKADDR_CMPSCOPE));
00041 }
00042
00043 isc_boolean_t
00044 isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
00045 return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
00046 ISC_SOCKADDR_CMPSCOPE));
00047 }
00048
00049 isc_boolean_t
00050 isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
00051 unsigned int flags)
00052 {
00053 REQUIRE(a != NULL && b != NULL);
00054
00055 if (a->length != b->length)
00056 return (ISC_FALSE);
00057
00058
00059
00060
00061
00062
00063 if (a->type.sa.sa_family != b->type.sa.sa_family)
00064 return (ISC_FALSE);
00065 switch (a->type.sa.sa_family) {
00066 case AF_INET:
00067 if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
00068 memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
00069 sizeof(a->type.sin.sin_addr)) != 0)
00070 return (ISC_FALSE);
00071 if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
00072 a->type.sin.sin_port != b->type.sin.sin_port)
00073 return (ISC_FALSE);
00074 break;
00075 case AF_INET6:
00076 if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
00077 memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
00078 sizeof(a->type.sin6.sin6_addr)) != 0)
00079 return (ISC_FALSE);
00080 #ifdef ISC_PLATFORM_HAVESCOPEID
00081
00082
00083
00084
00085 if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 &&
00086 a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id &&
00087 ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 ||
00088 (a->type.sin6.sin6_scope_id != 0 &&
00089 b->type.sin6.sin6_scope_id != 0)))
00090 return (ISC_FALSE);
00091 #endif
00092 if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
00093 a->type.sin6.sin6_port != b->type.sin6.sin6_port)
00094 return (ISC_FALSE);
00095 break;
00096 default:
00097 if (memcmp(&a->type, &b->type, a->length) != 0)
00098 return (ISC_FALSE);
00099 }
00100 return (ISC_TRUE);
00101 }
00102
00103 isc_boolean_t
00104 isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
00105 unsigned int prefixlen)
00106 {
00107 isc_netaddr_t na, nb;
00108 isc_netaddr_fromsockaddr(&na, a);
00109 isc_netaddr_fromsockaddr(&nb, b);
00110 return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
00111 }
00112
00113 isc_result_t
00114 isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
00115 isc_result_t result;
00116 isc_netaddr_t netaddr;
00117 char pbuf[sizeof("65000")];
00118 unsigned int plen;
00119 isc_region_t avail;
00120
00121 REQUIRE(sockaddr != NULL);
00122
00123
00124
00125
00126
00127
00128 switch (sockaddr->type.sa.sa_family) {
00129 case AF_INET:
00130 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
00131 break;
00132 case AF_INET6:
00133 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
00134 break;
00135 #ifdef ISC_PLAFORM_HAVESYSUNH
00136 case AF_UNIX:
00137 plen = strlen(sockaddr->type.sunix.sun_path);
00138 if (plen >= isc_buffer_availablelength(target))
00139 return (ISC_R_NOSPACE);
00140
00141 isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen);
00142
00143
00144
00145
00146 isc_buffer_availableregion(target, &avail);
00147 INSIST(avail.length >= 1);
00148 avail.base[0] = '\0';
00149
00150 return (ISC_R_SUCCESS);
00151 #endif
00152 default:
00153 return (ISC_R_FAILURE);
00154 }
00155
00156 plen = strlen(pbuf);
00157 INSIST(plen < sizeof(pbuf));
00158
00159 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
00160 result = isc_netaddr_totext(&netaddr, target);
00161 if (result != ISC_R_SUCCESS)
00162 return (result);
00163
00164 if (1 + plen + 1 > isc_buffer_availablelength(target))
00165 return (ISC_R_NOSPACE);
00166
00167 isc_buffer_putmem(target, (const unsigned char *)"#", 1);
00168 isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
00169
00170
00171
00172
00173 isc_buffer_availableregion(target, &avail);
00174 INSIST(avail.length >= 1);
00175 avail.base[0] = '\0';
00176
00177 return (ISC_R_SUCCESS);
00178 }
00179
00180 void
00181 isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
00182 isc_result_t result;
00183 isc_buffer_t buf;
00184
00185 if (size == 0U)
00186 return;
00187
00188 isc_buffer_init(&buf, array, size);
00189 result = isc_sockaddr_totext(sa, &buf);
00190 if (result != ISC_R_SUCCESS) {
00191
00192
00193
00194 snprintf(array, size,
00195 isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
00196 ISC_MSG_UNKNOWNADDR,
00197 "<unknown address, family %u>"),
00198 sa->type.sa.sa_family);
00199 array[size - 1] = '\0';
00200 }
00201 }
00202
00203 unsigned int
00204 isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
00205 unsigned int length = 0;
00206 const unsigned char *s = NULL;
00207 unsigned int h = 0;
00208 unsigned int g;
00209 unsigned int p = 0;
00210 const struct in6_addr *in6;
00211
00212 REQUIRE(sockaddr != NULL);
00213
00214 switch (sockaddr->type.sa.sa_family) {
00215 case AF_INET:
00216 s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
00217 p = ntohs(sockaddr->type.sin.sin_port);
00218 length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
00219 break;
00220 case AF_INET6:
00221 in6 = &sockaddr->type.sin6.sin6_addr;
00222 s = (const unsigned char *)in6;
00223 if (IN6_IS_ADDR_V4MAPPED(in6)) {
00224 s += 12;
00225 length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
00226 } else
00227 length = sizeof(sockaddr->type.sin6.sin6_addr);
00228 p = ntohs(sockaddr->type.sin6.sin6_port);
00229 break;
00230 default:
00231 UNEXPECTED_ERROR(__FILE__, __LINE__,
00232 isc_msgcat_get(isc_msgcat,
00233 ISC_MSGSET_SOCKADDR,
00234 ISC_MSG_UNKNOWNFAMILY,
00235 "unknown address family: %d"),
00236 (int)sockaddr->type.sa.sa_family);
00237 s = (const unsigned char *)&sockaddr->type;
00238 length = sockaddr->length;
00239 p = 0;
00240 }
00241
00242 h = isc_hash_calc(s, length, ISC_TRUE);
00243 if (!address_only) {
00244 g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
00245 ISC_TRUE);
00246 h = h ^ g;
00247 }
00248
00249 return (h);
00250 }
00251
00252 void
00253 isc_sockaddr_any(isc_sockaddr_t *sockaddr)
00254 {
00255 memset(sockaddr, 0, sizeof(*sockaddr));
00256 sockaddr->type.sin.sin_family = AF_INET;
00257 #ifdef ISC_PLATFORM_HAVESALEN
00258 sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
00259 #endif
00260 sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
00261 sockaddr->type.sin.sin_port = 0;
00262 sockaddr->length = sizeof(sockaddr->type.sin);
00263 ISC_LINK_INIT(sockaddr, link);
00264 }
00265
00266 void
00267 isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
00268 {
00269 memset(sockaddr, 0, sizeof(*sockaddr));
00270 sockaddr->type.sin6.sin6_family = AF_INET6;
00271 #ifdef ISC_PLATFORM_HAVESALEN
00272 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
00273 #endif
00274 sockaddr->type.sin6.sin6_addr = in6addr_any;
00275 sockaddr->type.sin6.sin6_port = 0;
00276 sockaddr->length = sizeof(sockaddr->type.sin6);
00277 ISC_LINK_INIT(sockaddr, link);
00278 }
00279
00280 void
00281 isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
00282 in_port_t port)
00283 {
00284 memset(sockaddr, 0, sizeof(*sockaddr));
00285 sockaddr->type.sin.sin_family = AF_INET;
00286 #ifdef ISC_PLATFORM_HAVESALEN
00287 sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
00288 #endif
00289 sockaddr->type.sin.sin_addr = *ina;
00290 sockaddr->type.sin.sin_port = htons(port);
00291 sockaddr->length = sizeof(sockaddr->type.sin);
00292 ISC_LINK_INIT(sockaddr, link);
00293 }
00294
00295 void
00296 isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
00297 switch (pf) {
00298 case AF_INET:
00299 isc_sockaddr_any(sockaddr);
00300 break;
00301 case AF_INET6:
00302 isc_sockaddr_any6(sockaddr);
00303 break;
00304 default:
00305 INSIST(0);
00306 }
00307 }
00308
00309 void
00310 isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
00311 in_port_t port)
00312 {
00313 memset(sockaddr, 0, sizeof(*sockaddr));
00314 sockaddr->type.sin6.sin6_family = AF_INET6;
00315 #ifdef ISC_PLATFORM_HAVESALEN
00316 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
00317 #endif
00318 sockaddr->type.sin6.sin6_addr = *ina6;
00319 sockaddr->type.sin6.sin6_port = htons(port);
00320 sockaddr->length = sizeof(sockaddr->type.sin6);
00321 ISC_LINK_INIT(sockaddr, link);
00322 }
00323
00324 void
00325 isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
00326 in_port_t port)
00327 {
00328 memset(sockaddr, 0, sizeof(*sockaddr));
00329 sockaddr->type.sin6.sin6_family = AF_INET6;
00330 #ifdef ISC_PLATFORM_HAVESALEN
00331 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
00332 #endif
00333 sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
00334 sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
00335 memmove(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
00336 sockaddr->type.sin6.sin6_port = htons(port);
00337 sockaddr->length = sizeof(sockaddr->type.sin6);
00338 ISC_LINK_INIT(sockaddr, link);
00339 }
00340
00341 int
00342 isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
00343
00344
00345
00346
00347
00348 #if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
00349
00350
00351
00352 return (sockaddr->type.sa.sa_family);
00353 #else
00354 switch (sockaddr->type.sa.sa_family) {
00355 case AF_INET:
00356 return (PF_INET);
00357 case AF_INET6:
00358 return (PF_INET6);
00359 default:
00360 FATAL_ERROR(__FILE__, __LINE__,
00361 isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
00362 ISC_MSG_UNKNOWNFAMILY,
00363 "unknown address family: %d"),
00364 (int)sockaddr->type.sa.sa_family);
00365 }
00366 #endif
00367 }
00368
00369 void
00370 isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
00371 in_port_t port)
00372 {
00373 memset(sockaddr, 0, sizeof(*sockaddr));
00374 sockaddr->type.sin.sin_family = na->family;
00375 switch (na->family) {
00376 case AF_INET:
00377 sockaddr->length = sizeof(sockaddr->type.sin);
00378 #ifdef ISC_PLATFORM_HAVESALEN
00379 sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
00380 #endif
00381 sockaddr->type.sin.sin_addr = na->type.in;
00382 sockaddr->type.sin.sin_port = htons(port);
00383 break;
00384 case AF_INET6:
00385 sockaddr->length = sizeof(sockaddr->type.sin6);
00386 #ifdef ISC_PLATFORM_HAVESALEN
00387 sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
00388 #endif
00389 memmove(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
00390 #ifdef ISC_PLATFORM_HAVESCOPEID
00391 sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
00392 #endif
00393 sockaddr->type.sin6.sin6_port = htons(port);
00394 break;
00395 default:
00396 INSIST(0);
00397 }
00398 ISC_LINK_INIT(sockaddr, link);
00399 }
00400
00401 void
00402 isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
00403 switch (sockaddr->type.sa.sa_family) {
00404 case AF_INET:
00405 sockaddr->type.sin.sin_port = htons(port);
00406 break;
00407 case AF_INET6:
00408 sockaddr->type.sin6.sin6_port = htons(port);
00409 break;
00410 default:
00411 FATAL_ERROR(__FILE__, __LINE__,
00412 isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
00413 ISC_MSG_UNKNOWNFAMILY,
00414 "unknown address family: %d"),
00415 (int)sockaddr->type.sa.sa_family);
00416 }
00417 }
00418
00419 in_port_t
00420 isc_sockaddr_getport(const isc_sockaddr_t *sockaddr) {
00421 in_port_t port = 0;
00422
00423 switch (sockaddr->type.sa.sa_family) {
00424 case AF_INET:
00425 port = ntohs(sockaddr->type.sin.sin_port);
00426 break;
00427 case AF_INET6:
00428 port = ntohs(sockaddr->type.sin6.sin6_port);
00429 break;
00430 default:
00431 FATAL_ERROR(__FILE__, __LINE__,
00432 isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
00433 ISC_MSG_UNKNOWNFAMILY,
00434 "unknown address family: %d"),
00435 (int)sockaddr->type.sa.sa_family);
00436 }
00437
00438 return (port);
00439 }
00440
00441 isc_boolean_t
00442 isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) {
00443 isc_netaddr_t netaddr;
00444
00445 if (sockaddr->type.sa.sa_family == AF_INET ||
00446 sockaddr->type.sa.sa_family == AF_INET6) {
00447 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
00448 return (isc_netaddr_ismulticast(&netaddr));
00449 }
00450 return (ISC_FALSE);
00451 }
00452
00453 isc_boolean_t
00454 isc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) {
00455 isc_netaddr_t netaddr;
00456
00457 if (sockaddr->type.sa.sa_family == AF_INET) {
00458 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
00459 return (isc_netaddr_isexperimental(&netaddr));
00460 }
00461 return (ISC_FALSE);
00462 }
00463
00464 isc_boolean_t
00465 isc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) {
00466 isc_netaddr_t netaddr;
00467
00468 if (sockaddr->type.sa.sa_family == AF_INET6) {
00469 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
00470 return (isc_netaddr_issitelocal(&netaddr));
00471 }
00472 return (ISC_FALSE);
00473 }
00474
00475 isc_boolean_t
00476 isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) {
00477 isc_netaddr_t netaddr;
00478
00479 if (sockaddr->type.sa.sa_family == AF_INET6) {
00480 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
00481 return (isc_netaddr_islinklocal(&netaddr));
00482 }
00483 return (ISC_FALSE);
00484 }
00485
00486 isc_result_t
00487 isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) {
00488 #ifdef ISC_PLATFORM_HAVESYSUNH
00489 if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path))
00490 return (ISC_R_NOSPACE);
00491 memset(sockaddr, 0, sizeof(*sockaddr));
00492 sockaddr->length = sizeof(sockaddr->type.sunix);
00493 sockaddr->type.sunix.sun_family = AF_UNIX;
00494 #ifdef ISC_PLATFORM_HAVESALEN
00495 sockaddr->type.sunix.sun_len =
00496 (unsigned char)sizeof(sockaddr->type.sunix);
00497 #endif
00498 strcpy(sockaddr->type.sunix.sun_path, path);
00499 return (ISC_R_SUCCESS);
00500 #else
00501 UNUSED(sockaddr);
00502 UNUSED(path);
00503 return (ISC_R_NOTIMPLEMENTED);
00504 #endif
00505 }