1135446Strhodes/* 2262706Serwin * Copyright (C) 2004-2007, 2010-2012, 2014 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-2003 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18234010Sdougb/* $Id$ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24135446Strhodes#include <stdio.h> 25135446Strhodes 26135446Strhodes#include <isc/buffer.h> 27135446Strhodes#include <isc/hash.h> 28135446Strhodes#include <isc/msgs.h> 29135446Strhodes#include <isc/netaddr.h> 30135446Strhodes#include <isc/print.h> 31135446Strhodes#include <isc/region.h> 32135446Strhodes#include <isc/sockaddr.h> 33135446Strhodes#include <isc/string.h> 34135446Strhodes#include <isc/util.h> 35135446Strhodes 36135446Strhodesisc_boolean_t 37135446Strhodesisc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { 38170222Sdougb return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR| 39170222Sdougb ISC_SOCKADDR_CMPPORT| 40170222Sdougb ISC_SOCKADDR_CMPSCOPE)); 41170222Sdougb} 42170222Sdougb 43170222Sdougbisc_boolean_t 44170222Sdougbisc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { 45170222Sdougb return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR| 46170222Sdougb ISC_SOCKADDR_CMPSCOPE)); 47170222Sdougb} 48170222Sdougb 49170222Sdougbisc_boolean_t 50170222Sdougbisc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b, 51170222Sdougb unsigned int flags) 52170222Sdougb{ 53135446Strhodes REQUIRE(a != NULL && b != NULL); 54135446Strhodes 55135446Strhodes if (a->length != b->length) 56135446Strhodes return (ISC_FALSE); 57135446Strhodes 58135446Strhodes /* 59135446Strhodes * We don't just memcmp because the sin_zero field isn't always 60135446Strhodes * zero. 61135446Strhodes */ 62135446Strhodes 63135446Strhodes if (a->type.sa.sa_family != b->type.sa.sa_family) 64135446Strhodes return (ISC_FALSE); 65135446Strhodes switch (a->type.sa.sa_family) { 66135446Strhodes case AF_INET: 67170222Sdougb if ((flags & ISC_SOCKADDR_CMPADDR) != 0 && 68170222Sdougb memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr, 69135446Strhodes sizeof(a->type.sin.sin_addr)) != 0) 70135446Strhodes return (ISC_FALSE); 71170222Sdougb if ((flags & ISC_SOCKADDR_CMPPORT) != 0 && 72170222Sdougb a->type.sin.sin_port != b->type.sin.sin_port) 73135446Strhodes return (ISC_FALSE); 74135446Strhodes break; 75135446Strhodes case AF_INET6: 76170222Sdougb if ((flags & ISC_SOCKADDR_CMPADDR) != 0 && 77170222Sdougb memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, 78135446Strhodes sizeof(a->type.sin6.sin6_addr)) != 0) 79135446Strhodes return (ISC_FALSE); 80135446Strhodes#ifdef ISC_PLATFORM_HAVESCOPEID 81170222Sdougb /* 82170222Sdougb * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return 83170222Sdougb * ISC_FALSE if one of the scopes in zero. 84170222Sdougb */ 85170222Sdougb if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 && 86170222Sdougb a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id && 87170222Sdougb ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 || 88170222Sdougb (a->type.sin6.sin6_scope_id != 0 && 89170222Sdougb b->type.sin6.sin6_scope_id != 0))) 90135446Strhodes return (ISC_FALSE); 91135446Strhodes#endif 92170222Sdougb if ((flags & ISC_SOCKADDR_CMPPORT) != 0 && 93170222Sdougb a->type.sin6.sin6_port != b->type.sin6.sin6_port) 94135446Strhodes return (ISC_FALSE); 95135446Strhodes break; 96135446Strhodes default: 97135446Strhodes if (memcmp(&a->type, &b->type, a->length) != 0) 98135446Strhodes return (ISC_FALSE); 99135446Strhodes } 100135446Strhodes return (ISC_TRUE); 101135446Strhodes} 102135446Strhodes 103135446Strhodesisc_boolean_t 104135446Strhodesisc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b, 105135446Strhodes unsigned int prefixlen) 106135446Strhodes{ 107135446Strhodes isc_netaddr_t na, nb; 108135446Strhodes isc_netaddr_fromsockaddr(&na, a); 109135446Strhodes isc_netaddr_fromsockaddr(&nb, b); 110135446Strhodes return (isc_netaddr_eqprefix(&na, &nb, prefixlen)); 111135446Strhodes} 112135446Strhodes 113135446Strhodesisc_result_t 114135446Strhodesisc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) { 115135446Strhodes isc_result_t result; 116135446Strhodes isc_netaddr_t netaddr; 117135446Strhodes char pbuf[sizeof("65000")]; 118135446Strhodes unsigned int plen; 119135446Strhodes isc_region_t avail; 120135446Strhodes 121135446Strhodes REQUIRE(sockaddr != NULL); 122135446Strhodes 123135446Strhodes /* 124135446Strhodes * Do the port first, giving us the opportunity to check for 125135446Strhodes * unsupported address families before calling 126135446Strhodes * isc_netaddr_fromsockaddr(). 127135446Strhodes */ 128135446Strhodes switch (sockaddr->type.sa.sa_family) { 129135446Strhodes case AF_INET: 130135446Strhodes snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port)); 131135446Strhodes break; 132135446Strhodes case AF_INET6: 133135446Strhodes snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port)); 134135446Strhodes break; 135170222Sdougb#ifdef ISC_PLAFORM_HAVESYSUNH 136170222Sdougb case AF_UNIX: 137170222Sdougb plen = strlen(sockaddr->type.sunix.sun_path); 138170222Sdougb if (plen >= isc_buffer_availablelength(target)) 139170222Sdougb return (ISC_R_NOSPACE); 140170222Sdougb 141170222Sdougb isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen); 142170222Sdougb 143170222Sdougb /* 144170222Sdougb * Null terminate after used region. 145170222Sdougb */ 146170222Sdougb isc_buffer_availableregion(target, &avail); 147170222Sdougb INSIST(avail.length >= 1); 148170222Sdougb avail.base[0] = '\0'; 149170222Sdougb 150170222Sdougb return (ISC_R_SUCCESS); 151170222Sdougb#endif 152135446Strhodes default: 153135446Strhodes return (ISC_R_FAILURE); 154135446Strhodes } 155135446Strhodes 156135446Strhodes plen = strlen(pbuf); 157135446Strhodes INSIST(plen < sizeof(pbuf)); 158135446Strhodes 159135446Strhodes isc_netaddr_fromsockaddr(&netaddr, sockaddr); 160135446Strhodes result = isc_netaddr_totext(&netaddr, target); 161135446Strhodes if (result != ISC_R_SUCCESS) 162135446Strhodes return (result); 163135446Strhodes 164135446Strhodes if (1 + plen + 1 > isc_buffer_availablelength(target)) 165135446Strhodes return (ISC_R_NOSPACE); 166135446Strhodes 167135446Strhodes isc_buffer_putmem(target, (const unsigned char *)"#", 1); 168135446Strhodes isc_buffer_putmem(target, (const unsigned char *)pbuf, plen); 169135446Strhodes 170135446Strhodes /* 171135446Strhodes * Null terminate after used region. 172135446Strhodes */ 173135446Strhodes isc_buffer_availableregion(target, &avail); 174135446Strhodes INSIST(avail.length >= 1); 175135446Strhodes avail.base[0] = '\0'; 176135446Strhodes 177135446Strhodes return (ISC_R_SUCCESS); 178135446Strhodes} 179135446Strhodes 180135446Strhodesvoid 181135446Strhodesisc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) { 182135446Strhodes isc_result_t result; 183135446Strhodes isc_buffer_t buf; 184135446Strhodes 185225361Sdougb if (size == 0U) 186225361Sdougb return; 187225361Sdougb 188135446Strhodes isc_buffer_init(&buf, array, size); 189135446Strhodes result = isc_sockaddr_totext(sa, &buf); 190135446Strhodes if (result != ISC_R_SUCCESS) { 191135446Strhodes /* 192135446Strhodes * The message is the same as in netaddr.c. 193135446Strhodes */ 194135446Strhodes snprintf(array, size, 195135446Strhodes isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR, 196135446Strhodes ISC_MSG_UNKNOWNADDR, 197135446Strhodes "<unknown address, family %u>"), 198135446Strhodes sa->type.sa.sa_family); 199135446Strhodes array[size - 1] = '\0'; 200135446Strhodes } 201135446Strhodes} 202135446Strhodes 203135446Strhodesunsigned int 204135446Strhodesisc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { 205135446Strhodes unsigned int length = 0; 206135446Strhodes const unsigned char *s = NULL; 207135446Strhodes unsigned int h = 0; 208135446Strhodes unsigned int g; 209135446Strhodes unsigned int p = 0; 210135446Strhodes const struct in6_addr *in6; 211135446Strhodes 212135446Strhodes REQUIRE(sockaddr != NULL); 213135446Strhodes 214135446Strhodes switch (sockaddr->type.sa.sa_family) { 215135446Strhodes case AF_INET: 216135446Strhodes s = (const unsigned char *)&sockaddr->type.sin.sin_addr; 217135446Strhodes p = ntohs(sockaddr->type.sin.sin_port); 218135446Strhodes length = sizeof(sockaddr->type.sin.sin_addr.s_addr); 219135446Strhodes break; 220135446Strhodes case AF_INET6: 221135446Strhodes in6 = &sockaddr->type.sin6.sin6_addr; 222254402Serwin s = (const unsigned char *)in6; 223135446Strhodes if (IN6_IS_ADDR_V4MAPPED(in6)) { 224254402Serwin s += 12; 225135446Strhodes length = sizeof(sockaddr->type.sin.sin_addr.s_addr); 226254402Serwin } else 227135446Strhodes length = sizeof(sockaddr->type.sin6.sin6_addr); 228135446Strhodes p = ntohs(sockaddr->type.sin6.sin6_port); 229135446Strhodes break; 230135446Strhodes default: 231135446Strhodes UNEXPECTED_ERROR(__FILE__, __LINE__, 232135446Strhodes isc_msgcat_get(isc_msgcat, 233135446Strhodes ISC_MSGSET_SOCKADDR, 234135446Strhodes ISC_MSG_UNKNOWNFAMILY, 235135446Strhodes "unknown address family: %d"), 236135446Strhodes (int)sockaddr->type.sa.sa_family); 237135446Strhodes s = (const unsigned char *)&sockaddr->type; 238135446Strhodes length = sockaddr->length; 239135446Strhodes p = 0; 240135446Strhodes } 241135446Strhodes 242135446Strhodes h = isc_hash_calc(s, length, ISC_TRUE); 243135446Strhodes if (!address_only) { 244135446Strhodes g = isc_hash_calc((const unsigned char *)&p, sizeof(p), 245135446Strhodes ISC_TRUE); 246135446Strhodes h = h ^ g; /* XXX: we should concatenate h and p first */ 247135446Strhodes } 248135446Strhodes 249135446Strhodes return (h); 250135446Strhodes} 251135446Strhodes 252135446Strhodesvoid 253135446Strhodesisc_sockaddr_any(isc_sockaddr_t *sockaddr) 254135446Strhodes{ 255135446Strhodes memset(sockaddr, 0, sizeof(*sockaddr)); 256135446Strhodes sockaddr->type.sin.sin_family = AF_INET; 257135446Strhodes#ifdef ISC_PLATFORM_HAVESALEN 258135446Strhodes sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 259135446Strhodes#endif 260135446Strhodes sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY; 261135446Strhodes sockaddr->type.sin.sin_port = 0; 262135446Strhodes sockaddr->length = sizeof(sockaddr->type.sin); 263135446Strhodes ISC_LINK_INIT(sockaddr, link); 264135446Strhodes} 265135446Strhodes 266135446Strhodesvoid 267135446Strhodesisc_sockaddr_any6(isc_sockaddr_t *sockaddr) 268135446Strhodes{ 269135446Strhodes memset(sockaddr, 0, sizeof(*sockaddr)); 270135446Strhodes sockaddr->type.sin6.sin6_family = AF_INET6; 271135446Strhodes#ifdef ISC_PLATFORM_HAVESALEN 272135446Strhodes sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 273135446Strhodes#endif 274135446Strhodes sockaddr->type.sin6.sin6_addr = in6addr_any; 275135446Strhodes sockaddr->type.sin6.sin6_port = 0; 276135446Strhodes sockaddr->length = sizeof(sockaddr->type.sin6); 277135446Strhodes ISC_LINK_INIT(sockaddr, link); 278135446Strhodes} 279135446Strhodes 280135446Strhodesvoid 281135446Strhodesisc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, 282135446Strhodes in_port_t port) 283135446Strhodes{ 284135446Strhodes memset(sockaddr, 0, sizeof(*sockaddr)); 285135446Strhodes sockaddr->type.sin.sin_family = AF_INET; 286135446Strhodes#ifdef ISC_PLATFORM_HAVESALEN 287135446Strhodes sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 288135446Strhodes#endif 289135446Strhodes sockaddr->type.sin.sin_addr = *ina; 290135446Strhodes sockaddr->type.sin.sin_port = htons(port); 291135446Strhodes sockaddr->length = sizeof(sockaddr->type.sin); 292135446Strhodes ISC_LINK_INIT(sockaddr, link); 293135446Strhodes} 294135446Strhodes 295135446Strhodesvoid 296135446Strhodesisc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) { 297135446Strhodes switch (pf) { 298135446Strhodes case AF_INET: 299135446Strhodes isc_sockaddr_any(sockaddr); 300135446Strhodes break; 301135446Strhodes case AF_INET6: 302135446Strhodes isc_sockaddr_any6(sockaddr); 303135446Strhodes break; 304135446Strhodes default: 305135446Strhodes INSIST(0); 306135446Strhodes } 307135446Strhodes} 308135446Strhodes 309135446Strhodesvoid 310135446Strhodesisc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6, 311135446Strhodes in_port_t port) 312135446Strhodes{ 313135446Strhodes memset(sockaddr, 0, sizeof(*sockaddr)); 314135446Strhodes sockaddr->type.sin6.sin6_family = AF_INET6; 315135446Strhodes#ifdef ISC_PLATFORM_HAVESALEN 316135446Strhodes sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 317135446Strhodes#endif 318135446Strhodes sockaddr->type.sin6.sin6_addr = *ina6; 319135446Strhodes sockaddr->type.sin6.sin6_port = htons(port); 320135446Strhodes sockaddr->length = sizeof(sockaddr->type.sin6); 321135446Strhodes ISC_LINK_INIT(sockaddr, link); 322135446Strhodes} 323135446Strhodes 324135446Strhodesvoid 325135446Strhodesisc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, 326135446Strhodes in_port_t port) 327135446Strhodes{ 328135446Strhodes memset(sockaddr, 0, sizeof(*sockaddr)); 329135446Strhodes sockaddr->type.sin6.sin6_family = AF_INET6; 330135446Strhodes#ifdef ISC_PLATFORM_HAVESALEN 331135446Strhodes sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 332135446Strhodes#endif 333135446Strhodes sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff; 334135446Strhodes sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff; 335262706Serwin memmove(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4); 336135446Strhodes sockaddr->type.sin6.sin6_port = htons(port); 337135446Strhodes sockaddr->length = sizeof(sockaddr->type.sin6); 338135446Strhodes ISC_LINK_INIT(sockaddr, link); 339135446Strhodes} 340135446Strhodes 341135446Strhodesint 342135446Strhodesisc_sockaddr_pf(const isc_sockaddr_t *sockaddr) { 343135446Strhodes 344135446Strhodes /* 345135446Strhodes * Get the protocol family of 'sockaddr'. 346135446Strhodes */ 347135446Strhodes 348135446Strhodes#if (AF_INET == PF_INET && AF_INET6 == PF_INET6) 349135446Strhodes /* 350135446Strhodes * Assume that PF_xxx == AF_xxx for all AF and PF. 351135446Strhodes */ 352135446Strhodes return (sockaddr->type.sa.sa_family); 353135446Strhodes#else 354135446Strhodes switch (sockaddr->type.sa.sa_family) { 355135446Strhodes case AF_INET: 356135446Strhodes return (PF_INET); 357135446Strhodes case AF_INET6: 358135446Strhodes return (PF_INET6); 359135446Strhodes default: 360135446Strhodes FATAL_ERROR(__FILE__, __LINE__, 361135446Strhodes isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 362135446Strhodes ISC_MSG_UNKNOWNFAMILY, 363135446Strhodes "unknown address family: %d"), 364135446Strhodes (int)sockaddr->type.sa.sa_family); 365135446Strhodes } 366135446Strhodes#endif 367135446Strhodes} 368135446Strhodes 369135446Strhodesvoid 370135446Strhodesisc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na, 371135446Strhodes in_port_t port) 372135446Strhodes{ 373135446Strhodes memset(sockaddr, 0, sizeof(*sockaddr)); 374135446Strhodes sockaddr->type.sin.sin_family = na->family; 375135446Strhodes switch (na->family) { 376135446Strhodes case AF_INET: 377135446Strhodes sockaddr->length = sizeof(sockaddr->type.sin); 378135446Strhodes#ifdef ISC_PLATFORM_HAVESALEN 379135446Strhodes sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 380135446Strhodes#endif 381135446Strhodes sockaddr->type.sin.sin_addr = na->type.in; 382135446Strhodes sockaddr->type.sin.sin_port = htons(port); 383135446Strhodes break; 384135446Strhodes case AF_INET6: 385135446Strhodes sockaddr->length = sizeof(sockaddr->type.sin6); 386135446Strhodes#ifdef ISC_PLATFORM_HAVESALEN 387135446Strhodes sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 388135446Strhodes#endif 389262706Serwin memmove(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16); 390135446Strhodes#ifdef ISC_PLATFORM_HAVESCOPEID 391135446Strhodes sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na); 392135446Strhodes#endif 393135446Strhodes sockaddr->type.sin6.sin6_port = htons(port); 394135446Strhodes break; 395224092Sdougb default: 396224092Sdougb INSIST(0); 397135446Strhodes } 398135446Strhodes ISC_LINK_INIT(sockaddr, link); 399135446Strhodes} 400135446Strhodes 401135446Strhodesvoid 402135446Strhodesisc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) { 403135446Strhodes switch (sockaddr->type.sa.sa_family) { 404135446Strhodes case AF_INET: 405135446Strhodes sockaddr->type.sin.sin_port = htons(port); 406135446Strhodes break; 407135446Strhodes case AF_INET6: 408135446Strhodes sockaddr->type.sin6.sin6_port = htons(port); 409135446Strhodes break; 410135446Strhodes default: 411135446Strhodes FATAL_ERROR(__FILE__, __LINE__, 412135446Strhodes isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 413135446Strhodes ISC_MSG_UNKNOWNFAMILY, 414135446Strhodes "unknown address family: %d"), 415135446Strhodes (int)sockaddr->type.sa.sa_family); 416135446Strhodes } 417135446Strhodes} 418135446Strhodes 419135446Strhodesin_port_t 420165071Sdougbisc_sockaddr_getport(const isc_sockaddr_t *sockaddr) { 421135446Strhodes in_port_t port = 0; 422135446Strhodes 423135446Strhodes switch (sockaddr->type.sa.sa_family) { 424135446Strhodes case AF_INET: 425135446Strhodes port = ntohs(sockaddr->type.sin.sin_port); 426135446Strhodes break; 427135446Strhodes case AF_INET6: 428135446Strhodes port = ntohs(sockaddr->type.sin6.sin6_port); 429135446Strhodes break; 430135446Strhodes default: 431135446Strhodes FATAL_ERROR(__FILE__, __LINE__, 432135446Strhodes isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 433135446Strhodes ISC_MSG_UNKNOWNFAMILY, 434135446Strhodes "unknown address family: %d"), 435135446Strhodes (int)sockaddr->type.sa.sa_family); 436135446Strhodes } 437135446Strhodes 438135446Strhodes return (port); 439135446Strhodes} 440135446Strhodes 441135446Strhodesisc_boolean_t 442165071Sdougbisc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) { 443135446Strhodes isc_netaddr_t netaddr; 444135446Strhodes 445170222Sdougb if (sockaddr->type.sa.sa_family == AF_INET || 446170222Sdougb sockaddr->type.sa.sa_family == AF_INET6) { 447170222Sdougb isc_netaddr_fromsockaddr(&netaddr, sockaddr); 448170222Sdougb return (isc_netaddr_ismulticast(&netaddr)); 449170222Sdougb } 450170222Sdougb return (ISC_FALSE); 451135446Strhodes} 452135446Strhodes 453135446Strhodesisc_boolean_t 454165071Sdougbisc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) { 455135446Strhodes isc_netaddr_t netaddr; 456135446Strhodes 457135446Strhodes if (sockaddr->type.sa.sa_family == AF_INET) { 458135446Strhodes isc_netaddr_fromsockaddr(&netaddr, sockaddr); 459135446Strhodes return (isc_netaddr_isexperimental(&netaddr)); 460135446Strhodes } 461135446Strhodes return (ISC_FALSE); 462135446Strhodes} 463135446Strhodes 464135446Strhodesisc_boolean_t 465165071Sdougbisc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) { 466135446Strhodes isc_netaddr_t netaddr; 467135446Strhodes 468135446Strhodes if (sockaddr->type.sa.sa_family == AF_INET6) { 469135446Strhodes isc_netaddr_fromsockaddr(&netaddr, sockaddr); 470135446Strhodes return (isc_netaddr_issitelocal(&netaddr)); 471135446Strhodes } 472135446Strhodes return (ISC_FALSE); 473135446Strhodes} 474135446Strhodes 475135446Strhodesisc_boolean_t 476165071Sdougbisc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) { 477135446Strhodes isc_netaddr_t netaddr; 478135446Strhodes 479135446Strhodes if (sockaddr->type.sa.sa_family == AF_INET6) { 480135446Strhodes isc_netaddr_fromsockaddr(&netaddr, sockaddr); 481135446Strhodes return (isc_netaddr_islinklocal(&netaddr)); 482135446Strhodes } 483135446Strhodes return (ISC_FALSE); 484135446Strhodes} 485170222Sdougb 486170222Sdougbisc_result_t 487170222Sdougbisc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) { 488170222Sdougb#ifdef ISC_PLATFORM_HAVESYSUNH 489170222Sdougb if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path)) 490170222Sdougb return (ISC_R_NOSPACE); 491170222Sdougb memset(sockaddr, 0, sizeof(*sockaddr)); 492170222Sdougb sockaddr->length = sizeof(sockaddr->type.sunix); 493170222Sdougb sockaddr->type.sunix.sun_family = AF_UNIX; 494170222Sdougb#ifdef ISC_PLATFORM_HAVESALEN 495170222Sdougb sockaddr->type.sunix.sun_len = 496170222Sdougb (unsigned char)sizeof(sockaddr->type.sunix); 497170222Sdougb#endif 498170222Sdougb strcpy(sockaddr->type.sunix.sun_path, path); 499170222Sdougb return (ISC_R_SUCCESS); 500170222Sdougb#else 501170222Sdougb UNUSED(sockaddr); 502170222Sdougb UNUSED(path); 503170222Sdougb return (ISC_R_NOTIMPLEMENTED); 504170222Sdougb#endif 505170222Sdougb} 506