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