1258945Sroberto/* 2280849Scy * Copyright (C) 2004-2007, 2010-2012 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 1999-2003 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18280849Scy/* $Id$ */ 19258945Sroberto 20258945Sroberto/*! \file */ 21258945Sroberto 22258945Sroberto#include <config.h> 23258945Sroberto 24258945Sroberto#include <stdio.h> 25258945Sroberto 26258945Sroberto#include <isc/buffer.h> 27258945Sroberto#include <isc/hash.h> 28258945Sroberto#include <isc/msgs.h> 29258945Sroberto#include <isc/netaddr.h> 30258945Sroberto#include <isc/print.h> 31258945Sroberto#include <isc/region.h> 32258945Sroberto#include <isc/sockaddr.h> 33258945Sroberto#include <isc/string.h> 34258945Sroberto#include <isc/util.h> 35258945Sroberto 36258945Srobertoisc_boolean_t 37258945Srobertoisc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { 38258945Sroberto return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR| 39258945Sroberto ISC_SOCKADDR_CMPPORT| 40258945Sroberto ISC_SOCKADDR_CMPSCOPE)); 41258945Sroberto} 42258945Sroberto 43258945Srobertoisc_boolean_t 44258945Srobertoisc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { 45258945Sroberto return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR| 46258945Sroberto ISC_SOCKADDR_CMPSCOPE)); 47258945Sroberto} 48258945Sroberto 49258945Srobertoisc_boolean_t 50258945Srobertoisc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b, 51258945Sroberto unsigned int flags) 52258945Sroberto{ 53258945Sroberto REQUIRE(a != NULL && b != NULL); 54258945Sroberto 55258945Sroberto if (a->length != b->length) 56258945Sroberto return (ISC_FALSE); 57258945Sroberto 58258945Sroberto /* 59258945Sroberto * We don't just memcmp because the sin_zero field isn't always 60258945Sroberto * zero. 61258945Sroberto */ 62258945Sroberto 63258945Sroberto if (a->type.sa.sa_family != b->type.sa.sa_family) 64258945Sroberto return (ISC_FALSE); 65258945Sroberto switch (a->type.sa.sa_family) { 66258945Sroberto case AF_INET: 67258945Sroberto if ((flags & ISC_SOCKADDR_CMPADDR) != 0 && 68258945Sroberto memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr, 69258945Sroberto sizeof(a->type.sin.sin_addr)) != 0) 70258945Sroberto return (ISC_FALSE); 71258945Sroberto if ((flags & ISC_SOCKADDR_CMPPORT) != 0 && 72258945Sroberto a->type.sin.sin_port != b->type.sin.sin_port) 73258945Sroberto return (ISC_FALSE); 74258945Sroberto break; 75258945Sroberto case AF_INET6: 76258945Sroberto if ((flags & ISC_SOCKADDR_CMPADDR) != 0 && 77258945Sroberto memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, 78258945Sroberto sizeof(a->type.sin6.sin6_addr)) != 0) 79258945Sroberto return (ISC_FALSE); 80258945Sroberto#ifdef ISC_PLATFORM_HAVESCOPEID 81258945Sroberto /* 82258945Sroberto * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return 83258945Sroberto * ISC_FALSE if one of the scopes in zero. 84258945Sroberto */ 85258945Sroberto if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 && 86258945Sroberto a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id && 87258945Sroberto ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 || 88258945Sroberto (a->type.sin6.sin6_scope_id != 0 && 89258945Sroberto b->type.sin6.sin6_scope_id != 0))) 90258945Sroberto return (ISC_FALSE); 91258945Sroberto#endif 92258945Sroberto if ((flags & ISC_SOCKADDR_CMPPORT) != 0 && 93258945Sroberto a->type.sin6.sin6_port != b->type.sin6.sin6_port) 94258945Sroberto return (ISC_FALSE); 95258945Sroberto break; 96258945Sroberto default: 97258945Sroberto if (memcmp(&a->type, &b->type, a->length) != 0) 98258945Sroberto return (ISC_FALSE); 99258945Sroberto } 100258945Sroberto return (ISC_TRUE); 101258945Sroberto} 102258945Sroberto 103258945Srobertoisc_boolean_t 104258945Srobertoisc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b, 105258945Sroberto unsigned int prefixlen) 106258945Sroberto{ 107258945Sroberto isc_netaddr_t na, nb; 108258945Sroberto isc_netaddr_fromsockaddr(&na, a); 109258945Sroberto isc_netaddr_fromsockaddr(&nb, b); 110258945Sroberto return (isc_netaddr_eqprefix(&na, &nb, prefixlen)); 111258945Sroberto} 112258945Sroberto 113258945Srobertoisc_result_t 114258945Srobertoisc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) { 115258945Sroberto isc_result_t result; 116258945Sroberto isc_netaddr_t netaddr; 117258945Sroberto char pbuf[sizeof("65000")]; 118258945Sroberto unsigned int plen; 119258945Sroberto isc_region_t avail; 120258945Sroberto 121258945Sroberto REQUIRE(sockaddr != NULL); 122258945Sroberto 123258945Sroberto /* 124258945Sroberto * Do the port first, giving us the opportunity to check for 125258945Sroberto * unsupported address families before calling 126258945Sroberto * isc_netaddr_fromsockaddr(). 127258945Sroberto */ 128258945Sroberto switch (sockaddr->type.sa.sa_family) { 129258945Sroberto case AF_INET: 130258945Sroberto snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port)); 131258945Sroberto break; 132258945Sroberto case AF_INET6: 133258945Sroberto snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port)); 134258945Sroberto break; 135258945Sroberto#ifdef ISC_PLAFORM_HAVESYSUNH 136258945Sroberto case AF_UNIX: 137293894Sglebius plen = (unsigned int)strlen(sockaddr->type.sunix.sun_path); 138258945Sroberto if (plen >= isc_buffer_availablelength(target)) 139258945Sroberto return (ISC_R_NOSPACE); 140258945Sroberto 141258945Sroberto isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen); 142258945Sroberto 143258945Sroberto /* 144258945Sroberto * Null terminate after used region. 145258945Sroberto */ 146258945Sroberto isc_buffer_availableregion(target, &avail); 147258945Sroberto INSIST(avail.length >= 1); 148258945Sroberto avail.base[0] = '\0'; 149258945Sroberto 150258945Sroberto return (ISC_R_SUCCESS); 151258945Sroberto#endif 152258945Sroberto default: 153258945Sroberto return (ISC_R_FAILURE); 154258945Sroberto } 155258945Sroberto 156293894Sglebius plen = (unsigned int)strlen(pbuf); 157258945Sroberto INSIST(plen < sizeof(pbuf)); 158258945Sroberto 159258945Sroberto isc_netaddr_fromsockaddr(&netaddr, sockaddr); 160258945Sroberto result = isc_netaddr_totext(&netaddr, target); 161258945Sroberto if (result != ISC_R_SUCCESS) 162258945Sroberto return (result); 163258945Sroberto 164258945Sroberto if (1 + plen + 1 > isc_buffer_availablelength(target)) 165258945Sroberto return (ISC_R_NOSPACE); 166258945Sroberto 167258945Sroberto isc_buffer_putmem(target, (const unsigned char *)"#", 1); 168258945Sroberto isc_buffer_putmem(target, (const unsigned char *)pbuf, plen); 169258945Sroberto 170258945Sroberto /* 171258945Sroberto * Null terminate after used region. 172258945Sroberto */ 173258945Sroberto isc_buffer_availableregion(target, &avail); 174258945Sroberto INSIST(avail.length >= 1); 175258945Sroberto avail.base[0] = '\0'; 176258945Sroberto 177258945Sroberto return (ISC_R_SUCCESS); 178258945Sroberto} 179258945Sroberto 180258945Srobertovoid 181258945Srobertoisc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) { 182258945Sroberto isc_result_t result; 183258945Sroberto isc_buffer_t buf; 184258945Sroberto 185280849Scy if (size == 0U) 186280849Scy return; 187280849Scy 188258945Sroberto isc_buffer_init(&buf, array, size); 189258945Sroberto result = isc_sockaddr_totext(sa, &buf); 190258945Sroberto if (result != ISC_R_SUCCESS) { 191258945Sroberto /* 192258945Sroberto * The message is the same as in netaddr.c. 193258945Sroberto */ 194258945Sroberto snprintf(array, size, 195280849Scy "<%s %u>", 196258945Sroberto isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR, 197258945Sroberto ISC_MSG_UNKNOWNADDR, 198280849Scy "unknown address, family"), 199258945Sroberto sa->type.sa.sa_family); 200258945Sroberto array[size - 1] = '\0'; 201258945Sroberto } 202258945Sroberto} 203258945Sroberto 204258945Srobertounsigned int 205258945Srobertoisc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { 206258945Sroberto unsigned int length = 0; 207258945Sroberto const unsigned char *s = NULL; 208258945Sroberto unsigned int h = 0; 209258945Sroberto unsigned int g; 210258945Sroberto unsigned int p = 0; 211258945Sroberto const struct in6_addr *in6; 212258945Sroberto 213258945Sroberto REQUIRE(sockaddr != NULL); 214258945Sroberto 215258945Sroberto switch (sockaddr->type.sa.sa_family) { 216258945Sroberto case AF_INET: 217258945Sroberto s = (const unsigned char *)&sockaddr->type.sin.sin_addr; 218258945Sroberto p = ntohs(sockaddr->type.sin.sin_port); 219258945Sroberto length = sizeof(sockaddr->type.sin.sin_addr.s_addr); 220258945Sroberto break; 221258945Sroberto case AF_INET6: 222258945Sroberto in6 = &sockaddr->type.sin6.sin6_addr; 223258945Sroberto if (IN6_IS_ADDR_V4MAPPED(in6)) { 224280849Scy s = (const unsigned char *)&in6 + 12; 225258945Sroberto length = sizeof(sockaddr->type.sin.sin_addr.s_addr); 226258945Sroberto } else { 227258945Sroberto s = (const unsigned char *)in6; 228258945Sroberto length = sizeof(sockaddr->type.sin6.sin6_addr); 229258945Sroberto } 230258945Sroberto p = ntohs(sockaddr->type.sin6.sin6_port); 231258945Sroberto break; 232258945Sroberto default: 233258945Sroberto UNEXPECTED_ERROR(__FILE__, __LINE__, 234280849Scy "%s: %d", 235258945Sroberto isc_msgcat_get(isc_msgcat, 236258945Sroberto ISC_MSGSET_SOCKADDR, 237258945Sroberto ISC_MSG_UNKNOWNFAMILY, 238280849Scy "unknown address family"), 239258945Sroberto (int)sockaddr->type.sa.sa_family); 240258945Sroberto s = (const unsigned char *)&sockaddr->type; 241258945Sroberto length = sockaddr->length; 242258945Sroberto p = 0; 243258945Sroberto } 244258945Sroberto 245258945Sroberto h = isc_hash_calc(s, length, ISC_TRUE); 246258945Sroberto if (!address_only) { 247258945Sroberto g = isc_hash_calc((const unsigned char *)&p, sizeof(p), 248258945Sroberto ISC_TRUE); 249258945Sroberto h = h ^ g; /* XXX: we should concatenate h and p first */ 250258945Sroberto } 251258945Sroberto 252258945Sroberto return (h); 253258945Sroberto} 254258945Sroberto 255258945Srobertovoid 256258945Srobertoisc_sockaddr_any(isc_sockaddr_t *sockaddr) 257258945Sroberto{ 258258945Sroberto memset(sockaddr, 0, sizeof(*sockaddr)); 259258945Sroberto sockaddr->type.sin.sin_family = AF_INET; 260258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 261258945Sroberto sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 262258945Sroberto#endif 263258945Sroberto sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY; 264258945Sroberto sockaddr->type.sin.sin_port = 0; 265258945Sroberto sockaddr->length = sizeof(sockaddr->type.sin); 266258945Sroberto ISC_LINK_INIT(sockaddr, link); 267258945Sroberto} 268258945Sroberto 269258945Srobertovoid 270258945Srobertoisc_sockaddr_any6(isc_sockaddr_t *sockaddr) 271258945Sroberto{ 272258945Sroberto memset(sockaddr, 0, sizeof(*sockaddr)); 273258945Sroberto sockaddr->type.sin6.sin6_family = AF_INET6; 274258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 275258945Sroberto sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 276258945Sroberto#endif 277258945Sroberto sockaddr->type.sin6.sin6_addr = in6addr_any; 278258945Sroberto sockaddr->type.sin6.sin6_port = 0; 279258945Sroberto sockaddr->length = sizeof(sockaddr->type.sin6); 280258945Sroberto ISC_LINK_INIT(sockaddr, link); 281258945Sroberto} 282258945Sroberto 283258945Srobertovoid 284258945Srobertoisc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, 285258945Sroberto in_port_t port) 286258945Sroberto{ 287258945Sroberto memset(sockaddr, 0, sizeof(*sockaddr)); 288258945Sroberto sockaddr->type.sin.sin_family = AF_INET; 289258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 290258945Sroberto sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 291258945Sroberto#endif 292258945Sroberto sockaddr->type.sin.sin_addr = *ina; 293258945Sroberto sockaddr->type.sin.sin_port = htons(port); 294258945Sroberto sockaddr->length = sizeof(sockaddr->type.sin); 295258945Sroberto ISC_LINK_INIT(sockaddr, link); 296258945Sroberto} 297258945Sroberto 298258945Srobertovoid 299258945Srobertoisc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) { 300258945Sroberto switch (pf) { 301258945Sroberto case AF_INET: 302258945Sroberto isc_sockaddr_any(sockaddr); 303258945Sroberto break; 304258945Sroberto case AF_INET6: 305258945Sroberto isc_sockaddr_any6(sockaddr); 306258945Sroberto break; 307258945Sroberto default: 308258945Sroberto INSIST(0); 309258945Sroberto } 310258945Sroberto} 311258945Sroberto 312258945Srobertovoid 313258945Srobertoisc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6, 314258945Sroberto in_port_t port) 315258945Sroberto{ 316258945Sroberto memset(sockaddr, 0, sizeof(*sockaddr)); 317258945Sroberto sockaddr->type.sin6.sin6_family = AF_INET6; 318258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 319258945Sroberto sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 320258945Sroberto#endif 321258945Sroberto sockaddr->type.sin6.sin6_addr = *ina6; 322258945Sroberto sockaddr->type.sin6.sin6_port = htons(port); 323258945Sroberto sockaddr->length = sizeof(sockaddr->type.sin6); 324258945Sroberto ISC_LINK_INIT(sockaddr, link); 325258945Sroberto} 326258945Sroberto 327258945Srobertovoid 328258945Srobertoisc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, 329258945Sroberto in_port_t port) 330258945Sroberto{ 331258945Sroberto memset(sockaddr, 0, sizeof(*sockaddr)); 332258945Sroberto sockaddr->type.sin6.sin6_family = AF_INET6; 333258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 334258945Sroberto sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 335258945Sroberto#endif 336258945Sroberto sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff; 337258945Sroberto sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff; 338258945Sroberto memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4); 339258945Sroberto sockaddr->type.sin6.sin6_port = htons(port); 340258945Sroberto sockaddr->length = sizeof(sockaddr->type.sin6); 341258945Sroberto ISC_LINK_INIT(sockaddr, link); 342258945Sroberto} 343258945Sroberto 344258945Srobertoint 345258945Srobertoisc_sockaddr_pf(const isc_sockaddr_t *sockaddr) { 346258945Sroberto 347258945Sroberto /* 348258945Sroberto * Get the protocol family of 'sockaddr'. 349258945Sroberto */ 350258945Sroberto 351258945Sroberto#if (AF_INET == PF_INET && AF_INET6 == PF_INET6) 352258945Sroberto /* 353258945Sroberto * Assume that PF_xxx == AF_xxx for all AF and PF. 354258945Sroberto */ 355258945Sroberto return (sockaddr->type.sa.sa_family); 356258945Sroberto#else 357258945Sroberto switch (sockaddr->type.sa.sa_family) { 358258945Sroberto case AF_INET: 359258945Sroberto return (PF_INET); 360258945Sroberto case AF_INET6: 361258945Sroberto return (PF_INET6); 362258945Sroberto default: 363258945Sroberto FATAL_ERROR(__FILE__, __LINE__, 364258945Sroberto isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 365258945Sroberto ISC_MSG_UNKNOWNFAMILY, 366258945Sroberto "unknown address family: %d"), 367258945Sroberto (int)sockaddr->type.sa.sa_family); 368258945Sroberto } 369258945Sroberto#endif 370258945Sroberto} 371258945Sroberto 372258945Srobertovoid 373258945Srobertoisc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na, 374258945Sroberto in_port_t port) 375258945Sroberto{ 376258945Sroberto memset(sockaddr, 0, sizeof(*sockaddr)); 377258945Sroberto sockaddr->type.sin.sin_family = (short)na->family; 378258945Sroberto switch (na->family) { 379258945Sroberto case AF_INET: 380258945Sroberto sockaddr->length = sizeof(sockaddr->type.sin); 381258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 382258945Sroberto sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 383258945Sroberto#endif 384258945Sroberto sockaddr->type.sin.sin_addr = na->type.in; 385258945Sroberto sockaddr->type.sin.sin_port = htons(port); 386258945Sroberto break; 387258945Sroberto case AF_INET6: 388258945Sroberto sockaddr->length = sizeof(sockaddr->type.sin6); 389258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 390258945Sroberto sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 391258945Sroberto#endif 392258945Sroberto memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16); 393258945Sroberto#ifdef ISC_PLATFORM_HAVESCOPEID 394258945Sroberto sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na); 395258945Sroberto#endif 396258945Sroberto sockaddr->type.sin6.sin6_port = htons(port); 397258945Sroberto break; 398280849Scy default: 399280849Scy INSIST(0); 400258945Sroberto } 401258945Sroberto ISC_LINK_INIT(sockaddr, link); 402258945Sroberto} 403258945Sroberto 404258945Srobertovoid 405258945Srobertoisc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) { 406258945Sroberto switch (sockaddr->type.sa.sa_family) { 407258945Sroberto case AF_INET: 408258945Sroberto sockaddr->type.sin.sin_port = htons(port); 409258945Sroberto break; 410258945Sroberto case AF_INET6: 411258945Sroberto sockaddr->type.sin6.sin6_port = htons(port); 412258945Sroberto break; 413258945Sroberto default: 414258945Sroberto FATAL_ERROR(__FILE__, __LINE__, 415280849Scy "%s: %d", 416258945Sroberto isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 417258945Sroberto ISC_MSG_UNKNOWNFAMILY, 418280849Scy "unknown address family"), 419258945Sroberto (int)sockaddr->type.sa.sa_family); 420258945Sroberto } 421258945Sroberto} 422258945Sroberto 423258945Srobertoin_port_t 424258945Srobertoisc_sockaddr_getport(const isc_sockaddr_t *sockaddr) { 425258945Sroberto in_port_t port = 0; 426258945Sroberto 427258945Sroberto switch (sockaddr->type.sa.sa_family) { 428258945Sroberto case AF_INET: 429258945Sroberto port = ntohs(sockaddr->type.sin.sin_port); 430258945Sroberto break; 431258945Sroberto case AF_INET6: 432258945Sroberto port = ntohs(sockaddr->type.sin6.sin6_port); 433258945Sroberto break; 434258945Sroberto default: 435258945Sroberto FATAL_ERROR(__FILE__, __LINE__, 436280849Scy "%s: %d", 437258945Sroberto isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 438258945Sroberto ISC_MSG_UNKNOWNFAMILY, 439280849Scy "unknown address family"), 440258945Sroberto (int)sockaddr->type.sa.sa_family); 441258945Sroberto } 442258945Sroberto 443258945Sroberto return (port); 444258945Sroberto} 445258945Sroberto 446258945Srobertoisc_boolean_t 447258945Srobertoisc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) { 448258945Sroberto isc_netaddr_t netaddr; 449258945Sroberto 450258945Sroberto if (sockaddr->type.sa.sa_family == AF_INET || 451258945Sroberto sockaddr->type.sa.sa_family == AF_INET6) { 452258945Sroberto isc_netaddr_fromsockaddr(&netaddr, sockaddr); 453258945Sroberto return (isc_netaddr_ismulticast(&netaddr)); 454258945Sroberto } 455258945Sroberto return (ISC_FALSE); 456258945Sroberto} 457258945Sroberto 458258945Srobertoisc_boolean_t 459258945Srobertoisc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) { 460258945Sroberto isc_netaddr_t netaddr; 461258945Sroberto 462258945Sroberto if (sockaddr->type.sa.sa_family == AF_INET) { 463258945Sroberto isc_netaddr_fromsockaddr(&netaddr, sockaddr); 464258945Sroberto return (isc_netaddr_isexperimental(&netaddr)); 465258945Sroberto } 466258945Sroberto return (ISC_FALSE); 467258945Sroberto} 468258945Sroberto 469258945Srobertoisc_boolean_t 470258945Srobertoisc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) { 471258945Sroberto isc_netaddr_t netaddr; 472258945Sroberto 473258945Sroberto if (sockaddr->type.sa.sa_family == AF_INET6) { 474258945Sroberto isc_netaddr_fromsockaddr(&netaddr, sockaddr); 475258945Sroberto return (isc_netaddr_issitelocal(&netaddr)); 476258945Sroberto } 477258945Sroberto return (ISC_FALSE); 478258945Sroberto} 479258945Sroberto 480258945Srobertoisc_boolean_t 481258945Srobertoisc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) { 482258945Sroberto isc_netaddr_t netaddr; 483258945Sroberto 484258945Sroberto if (sockaddr->type.sa.sa_family == AF_INET6) { 485258945Sroberto isc_netaddr_fromsockaddr(&netaddr, sockaddr); 486258945Sroberto return (isc_netaddr_islinklocal(&netaddr)); 487258945Sroberto } 488258945Sroberto return (ISC_FALSE); 489258945Sroberto} 490258945Sroberto 491258945Srobertoisc_result_t 492258945Srobertoisc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) { 493258945Sroberto#ifdef ISC_PLATFORM_HAVESYSUNH 494258945Sroberto if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path)) 495258945Sroberto return (ISC_R_NOSPACE); 496258945Sroberto memset(sockaddr, 0, sizeof(*sockaddr)); 497258945Sroberto sockaddr->length = sizeof(sockaddr->type.sunix); 498258945Sroberto sockaddr->type.sunix.sun_family = AF_UNIX; 499258945Sroberto#ifdef ISC_PLATFORM_HAVESALEN 500258945Sroberto sockaddr->type.sunix.sun_len = 501258945Sroberto (unsigned char)sizeof(sockaddr->type.sunix); 502258945Sroberto#endif 503258945Sroberto strcpy(sockaddr->type.sunix.sun_path, path); 504258945Sroberto return (ISC_R_SUCCESS); 505258945Sroberto#else 506258945Sroberto UNUSED(sockaddr); 507258945Sroberto UNUSED(path); 508258945Sroberto return (ISC_R_NOTIMPLEMENTED); 509258945Sroberto#endif 510258945Sroberto} 511