1*eabc0478Schristos /* $NetBSD: sockaddr.c,v 1.2 2024/08/18 20:47:14 christos Exp $ */ 2897be3a4Schristos 3897be3a4Schristos /* 4897be3a4Schristos * Copyright (C) 2004-2007, 2010-2012 Internet Systems Consortium, Inc. ("ISC") 5897be3a4Schristos * Copyright (C) 1999-2003 Internet Software Consortium. 6897be3a4Schristos * 7897be3a4Schristos * Permission to use, copy, modify, and/or distribute this software for any 8897be3a4Schristos * purpose with or without fee is hereby granted, provided that the above 9897be3a4Schristos * copyright notice and this permission notice appear in all copies. 10897be3a4Schristos * 11897be3a4Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12897be3a4Schristos * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13897be3a4Schristos * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14897be3a4Schristos * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15897be3a4Schristos * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16897be3a4Schristos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17897be3a4Schristos * PERFORMANCE OF THIS SOFTWARE. 18897be3a4Schristos */ 19897be3a4Schristos 20897be3a4Schristos /* Id */ 21897be3a4Schristos 22897be3a4Schristos /*! \file */ 23897be3a4Schristos 24897be3a4Schristos #include <config.h> 25897be3a4Schristos 26897be3a4Schristos #include <stdio.h> 27897be3a4Schristos 28897be3a4Schristos #include <isc/buffer.h> 29897be3a4Schristos #include <isc/hash.h> 30897be3a4Schristos #include <isc/msgs.h> 31897be3a4Schristos #include <isc/netaddr.h> 32897be3a4Schristos #include <isc/print.h> 33897be3a4Schristos #include <isc/region.h> 34897be3a4Schristos #include <isc/sockaddr.h> 35897be3a4Schristos #include <isc/string.h> 36897be3a4Schristos #include <isc/util.h> 37897be3a4Schristos 38897be3a4Schristos isc_boolean_t 39897be3a4Schristos isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { 40897be3a4Schristos return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR| 41897be3a4Schristos ISC_SOCKADDR_CMPPORT| 42897be3a4Schristos ISC_SOCKADDR_CMPSCOPE)); 43897be3a4Schristos } 44897be3a4Schristos 45897be3a4Schristos isc_boolean_t 46897be3a4Schristos isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { 47897be3a4Schristos return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR| 48897be3a4Schristos ISC_SOCKADDR_CMPSCOPE)); 49897be3a4Schristos } 50897be3a4Schristos 51897be3a4Schristos isc_boolean_t 52897be3a4Schristos isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b, 53897be3a4Schristos unsigned int flags) 54897be3a4Schristos { 55897be3a4Schristos REQUIRE(a != NULL && b != NULL); 56897be3a4Schristos 57897be3a4Schristos if (a->length != b->length) 58897be3a4Schristos return (ISC_FALSE); 59897be3a4Schristos 60897be3a4Schristos /* 61897be3a4Schristos * We don't just memcmp because the sin_zero field isn't always 62897be3a4Schristos * zero. 63897be3a4Schristos */ 64897be3a4Schristos 65897be3a4Schristos if (a->type.sa.sa_family != b->type.sa.sa_family) 66897be3a4Schristos return (ISC_FALSE); 67897be3a4Schristos switch (a->type.sa.sa_family) { 68897be3a4Schristos case AF_INET: 69897be3a4Schristos if ((flags & ISC_SOCKADDR_CMPADDR) != 0 && 70897be3a4Schristos memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr, 71897be3a4Schristos sizeof(a->type.sin.sin_addr)) != 0) 72897be3a4Schristos return (ISC_FALSE); 73897be3a4Schristos if ((flags & ISC_SOCKADDR_CMPPORT) != 0 && 74897be3a4Schristos a->type.sin.sin_port != b->type.sin.sin_port) 75897be3a4Schristos return (ISC_FALSE); 76897be3a4Schristos break; 77897be3a4Schristos case AF_INET6: 78897be3a4Schristos if ((flags & ISC_SOCKADDR_CMPADDR) != 0 && 79897be3a4Schristos memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, 80897be3a4Schristos sizeof(a->type.sin6.sin6_addr)) != 0) 81897be3a4Schristos return (ISC_FALSE); 82897be3a4Schristos #ifdef ISC_PLATFORM_HAVESCOPEID 83897be3a4Schristos /* 84897be3a4Schristos * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return 85897be3a4Schristos * ISC_FALSE if one of the scopes in zero. 86897be3a4Schristos */ 87897be3a4Schristos if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 && 88897be3a4Schristos a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id && 89897be3a4Schristos ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 || 90897be3a4Schristos (a->type.sin6.sin6_scope_id != 0 && 91897be3a4Schristos b->type.sin6.sin6_scope_id != 0))) 92897be3a4Schristos return (ISC_FALSE); 93897be3a4Schristos #endif 94897be3a4Schristos if ((flags & ISC_SOCKADDR_CMPPORT) != 0 && 95897be3a4Schristos a->type.sin6.sin6_port != b->type.sin6.sin6_port) 96897be3a4Schristos return (ISC_FALSE); 97897be3a4Schristos break; 98897be3a4Schristos default: 99897be3a4Schristos if (memcmp(&a->type, &b->type, a->length) != 0) 100897be3a4Schristos return (ISC_FALSE); 101897be3a4Schristos } 102897be3a4Schristos return (ISC_TRUE); 103897be3a4Schristos } 104897be3a4Schristos 105897be3a4Schristos isc_boolean_t 106897be3a4Schristos isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b, 107897be3a4Schristos unsigned int prefixlen) 108897be3a4Schristos { 109897be3a4Schristos isc_netaddr_t na, nb; 110897be3a4Schristos isc_netaddr_fromsockaddr(&na, a); 111897be3a4Schristos isc_netaddr_fromsockaddr(&nb, b); 112897be3a4Schristos return (isc_netaddr_eqprefix(&na, &nb, prefixlen)); 113897be3a4Schristos } 114897be3a4Schristos 115897be3a4Schristos isc_result_t 116897be3a4Schristos isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) { 117897be3a4Schristos isc_result_t result; 118897be3a4Schristos isc_netaddr_t netaddr; 119897be3a4Schristos char pbuf[sizeof("65000")]; 120897be3a4Schristos unsigned int plen; 121897be3a4Schristos isc_region_t avail; 122897be3a4Schristos 123897be3a4Schristos REQUIRE(sockaddr != NULL); 124897be3a4Schristos 125897be3a4Schristos /* 126897be3a4Schristos * Do the port first, giving us the opportunity to check for 127897be3a4Schristos * unsupported address families before calling 128897be3a4Schristos * isc_netaddr_fromsockaddr(). 129897be3a4Schristos */ 130897be3a4Schristos switch (sockaddr->type.sa.sa_family) { 131897be3a4Schristos case AF_INET: 132897be3a4Schristos snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port)); 133897be3a4Schristos break; 134897be3a4Schristos case AF_INET6: 135897be3a4Schristos snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port)); 136897be3a4Schristos break; 137897be3a4Schristos #ifdef ISC_PLAFORM_HAVESYSUNH 138897be3a4Schristos case AF_UNIX: 139897be3a4Schristos plen = (unsigned int)strlen(sockaddr->type.sunix.sun_path); 140897be3a4Schristos if (plen >= isc_buffer_availablelength(target)) 141897be3a4Schristos return (ISC_R_NOSPACE); 142897be3a4Schristos 143897be3a4Schristos isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen); 144897be3a4Schristos 145897be3a4Schristos /* 146897be3a4Schristos * Null terminate after used region. 147897be3a4Schristos */ 148897be3a4Schristos isc_buffer_availableregion(target, &avail); 149897be3a4Schristos INSIST(avail.length >= 1); 150897be3a4Schristos avail.base[0] = '\0'; 151897be3a4Schristos 152897be3a4Schristos return (ISC_R_SUCCESS); 153897be3a4Schristos #endif 154897be3a4Schristos default: 155897be3a4Schristos return (ISC_R_FAILURE); 156897be3a4Schristos } 157897be3a4Schristos 158897be3a4Schristos plen = (unsigned int)strlen(pbuf); 159897be3a4Schristos INSIST(plen < sizeof(pbuf)); 160897be3a4Schristos 161897be3a4Schristos isc_netaddr_fromsockaddr(&netaddr, sockaddr); 162897be3a4Schristos result = isc_netaddr_totext(&netaddr, target); 163897be3a4Schristos if (result != ISC_R_SUCCESS) 164897be3a4Schristos return (result); 165897be3a4Schristos 166897be3a4Schristos if (1 + plen + 1 > isc_buffer_availablelength(target)) 167897be3a4Schristos return (ISC_R_NOSPACE); 168897be3a4Schristos 169897be3a4Schristos isc_buffer_putmem(target, (const unsigned char *)"#", 1); 170897be3a4Schristos isc_buffer_putmem(target, (const unsigned char *)pbuf, plen); 171897be3a4Schristos 172897be3a4Schristos /* 173897be3a4Schristos * Null terminate after used region. 174897be3a4Schristos */ 175897be3a4Schristos isc_buffer_availableregion(target, &avail); 176897be3a4Schristos INSIST(avail.length >= 1); 177897be3a4Schristos avail.base[0] = '\0'; 178897be3a4Schristos 179897be3a4Schristos return (ISC_R_SUCCESS); 180897be3a4Schristos } 181897be3a4Schristos 182897be3a4Schristos void 183897be3a4Schristos isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) { 184897be3a4Schristos isc_result_t result; 185897be3a4Schristos isc_buffer_t buf; 186897be3a4Schristos 187897be3a4Schristos if (size == 0U) 188897be3a4Schristos return; 189897be3a4Schristos 190897be3a4Schristos isc_buffer_init(&buf, array, size); 191897be3a4Schristos result = isc_sockaddr_totext(sa, &buf); 192897be3a4Schristos if (result != ISC_R_SUCCESS) { 193897be3a4Schristos /* 194897be3a4Schristos * The message is the same as in netaddr.c. 195897be3a4Schristos */ 196897be3a4Schristos snprintf(array, size, 197897be3a4Schristos "<%s %u>", 198897be3a4Schristos isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR, 199897be3a4Schristos ISC_MSG_UNKNOWNADDR, 200897be3a4Schristos "unknown address, family"), 201897be3a4Schristos sa->type.sa.sa_family); 202897be3a4Schristos array[size - 1] = '\0'; 203897be3a4Schristos } 204897be3a4Schristos } 205897be3a4Schristos 206897be3a4Schristos unsigned int 207897be3a4Schristos isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { 208897be3a4Schristos unsigned int length = 0; 209897be3a4Schristos const unsigned char *s = NULL; 210897be3a4Schristos unsigned int h = 0; 211897be3a4Schristos unsigned int g; 212897be3a4Schristos unsigned int p = 0; 213897be3a4Schristos const struct in6_addr *in6; 214897be3a4Schristos 215897be3a4Schristos REQUIRE(sockaddr != NULL); 216897be3a4Schristos 217897be3a4Schristos switch (sockaddr->type.sa.sa_family) { 218897be3a4Schristos case AF_INET: 219897be3a4Schristos s = (const unsigned char *)&sockaddr->type.sin.sin_addr; 220897be3a4Schristos p = ntohs(sockaddr->type.sin.sin_port); 221897be3a4Schristos length = sizeof(sockaddr->type.sin.sin_addr.s_addr); 222897be3a4Schristos break; 223897be3a4Schristos case AF_INET6: 224897be3a4Schristos in6 = &sockaddr->type.sin6.sin6_addr; 225897be3a4Schristos if (IN6_IS_ADDR_V4MAPPED(in6)) { 226897be3a4Schristos s = (const unsigned char *)&in6 + 12; 227897be3a4Schristos length = sizeof(sockaddr->type.sin.sin_addr.s_addr); 228897be3a4Schristos } else { 229897be3a4Schristos s = (const unsigned char *)in6; 230897be3a4Schristos length = sizeof(sockaddr->type.sin6.sin6_addr); 231897be3a4Schristos } 232897be3a4Schristos p = ntohs(sockaddr->type.sin6.sin6_port); 233897be3a4Schristos break; 234897be3a4Schristos default: 235897be3a4Schristos UNEXPECTED_ERROR(__FILE__, __LINE__, 236897be3a4Schristos "%s: %d", 237897be3a4Schristos isc_msgcat_get(isc_msgcat, 238897be3a4Schristos ISC_MSGSET_SOCKADDR, 239897be3a4Schristos ISC_MSG_UNKNOWNFAMILY, 240897be3a4Schristos "unknown address family"), 241897be3a4Schristos (int)sockaddr->type.sa.sa_family); 242897be3a4Schristos s = (const unsigned char *)&sockaddr->type; 243897be3a4Schristos length = sockaddr->length; 244897be3a4Schristos p = 0; 245897be3a4Schristos } 246897be3a4Schristos 247897be3a4Schristos h = isc_hash_calc(s, length, ISC_TRUE); 248897be3a4Schristos if (!address_only) { 249897be3a4Schristos g = isc_hash_calc((const unsigned char *)&p, sizeof(p), 250897be3a4Schristos ISC_TRUE); 251897be3a4Schristos h = h ^ g; /* XXX: we should concatenate h and p first */ 252897be3a4Schristos } 253897be3a4Schristos 254897be3a4Schristos return (h); 255897be3a4Schristos } 256897be3a4Schristos 257897be3a4Schristos void 258897be3a4Schristos isc_sockaddr_any(isc_sockaddr_t *sockaddr) 259897be3a4Schristos { 260897be3a4Schristos memset(sockaddr, 0, sizeof(*sockaddr)); 261897be3a4Schristos sockaddr->type.sin.sin_family = AF_INET; 262897be3a4Schristos #ifdef ISC_PLATFORM_HAVESALEN 263897be3a4Schristos sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 264897be3a4Schristos #endif 265897be3a4Schristos sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY; 266897be3a4Schristos sockaddr->type.sin.sin_port = 0; 267897be3a4Schristos sockaddr->length = sizeof(sockaddr->type.sin); 268897be3a4Schristos ISC_LINK_INIT(sockaddr, link); 269897be3a4Schristos } 270897be3a4Schristos 271897be3a4Schristos void 272897be3a4Schristos isc_sockaddr_any6(isc_sockaddr_t *sockaddr) 273897be3a4Schristos { 274897be3a4Schristos memset(sockaddr, 0, sizeof(*sockaddr)); 275897be3a4Schristos sockaddr->type.sin6.sin6_family = AF_INET6; 276897be3a4Schristos #ifdef ISC_PLATFORM_HAVESALEN 277897be3a4Schristos sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 278897be3a4Schristos #endif 279897be3a4Schristos sockaddr->type.sin6.sin6_addr = in6addr_any; 280897be3a4Schristos sockaddr->type.sin6.sin6_port = 0; 281897be3a4Schristos sockaddr->length = sizeof(sockaddr->type.sin6); 282897be3a4Schristos ISC_LINK_INIT(sockaddr, link); 283897be3a4Schristos } 284897be3a4Schristos 285897be3a4Schristos void 286897be3a4Schristos isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, 287897be3a4Schristos in_port_t port) 288897be3a4Schristos { 289897be3a4Schristos memset(sockaddr, 0, sizeof(*sockaddr)); 290897be3a4Schristos sockaddr->type.sin.sin_family = AF_INET; 291897be3a4Schristos #ifdef ISC_PLATFORM_HAVESALEN 292897be3a4Schristos sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 293897be3a4Schristos #endif 294897be3a4Schristos sockaddr->type.sin.sin_addr = *ina; 295897be3a4Schristos sockaddr->type.sin.sin_port = htons(port); 296897be3a4Schristos sockaddr->length = sizeof(sockaddr->type.sin); 297897be3a4Schristos ISC_LINK_INIT(sockaddr, link); 298897be3a4Schristos } 299897be3a4Schristos 300897be3a4Schristos void 301897be3a4Schristos isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) { 302897be3a4Schristos switch (pf) { 303897be3a4Schristos case AF_INET: 304897be3a4Schristos isc_sockaddr_any(sockaddr); 305897be3a4Schristos break; 306897be3a4Schristos case AF_INET6: 307897be3a4Schristos isc_sockaddr_any6(sockaddr); 308897be3a4Schristos break; 309897be3a4Schristos default: 310897be3a4Schristos INSIST(0); 311897be3a4Schristos } 312897be3a4Schristos } 313897be3a4Schristos 314897be3a4Schristos void 315897be3a4Schristos isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6, 316897be3a4Schristos in_port_t port) 317897be3a4Schristos { 318897be3a4Schristos memset(sockaddr, 0, sizeof(*sockaddr)); 319897be3a4Schristos sockaddr->type.sin6.sin6_family = AF_INET6; 320897be3a4Schristos #ifdef ISC_PLATFORM_HAVESALEN 321897be3a4Schristos sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 322897be3a4Schristos #endif 323897be3a4Schristos sockaddr->type.sin6.sin6_addr = *ina6; 324897be3a4Schristos sockaddr->type.sin6.sin6_port = htons(port); 325897be3a4Schristos sockaddr->length = sizeof(sockaddr->type.sin6); 326897be3a4Schristos ISC_LINK_INIT(sockaddr, link); 327897be3a4Schristos } 328897be3a4Schristos 329897be3a4Schristos void 330897be3a4Schristos isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, 331897be3a4Schristos in_port_t port) 332897be3a4Schristos { 333897be3a4Schristos memset(sockaddr, 0, sizeof(*sockaddr)); 334897be3a4Schristos sockaddr->type.sin6.sin6_family = AF_INET6; 335897be3a4Schristos #ifdef ISC_PLATFORM_HAVESALEN 336897be3a4Schristos sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 337897be3a4Schristos #endif 338897be3a4Schristos sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff; 339897be3a4Schristos sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff; 340897be3a4Schristos memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4); 341897be3a4Schristos sockaddr->type.sin6.sin6_port = htons(port); 342897be3a4Schristos sockaddr->length = sizeof(sockaddr->type.sin6); 343897be3a4Schristos ISC_LINK_INIT(sockaddr, link); 344897be3a4Schristos } 345897be3a4Schristos 346897be3a4Schristos int 347897be3a4Schristos isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) { 348897be3a4Schristos 349897be3a4Schristos /* 350897be3a4Schristos * Get the protocol family of 'sockaddr'. 351897be3a4Schristos */ 352897be3a4Schristos 353897be3a4Schristos #if (AF_INET == PF_INET && AF_INET6 == PF_INET6) 354897be3a4Schristos /* 355897be3a4Schristos * Assume that PF_xxx == AF_xxx for all AF and PF. 356897be3a4Schristos */ 357897be3a4Schristos return (sockaddr->type.sa.sa_family); 358897be3a4Schristos #else 359897be3a4Schristos switch (sockaddr->type.sa.sa_family) { 360897be3a4Schristos case AF_INET: 361897be3a4Schristos return (PF_INET); 362897be3a4Schristos case AF_INET6: 363897be3a4Schristos return (PF_INET6); 364897be3a4Schristos default: 365897be3a4Schristos FATAL_ERROR(__FILE__, __LINE__, 366897be3a4Schristos isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 367897be3a4Schristos ISC_MSG_UNKNOWNFAMILY, 368897be3a4Schristos "unknown address family: %d"), 369897be3a4Schristos (int)sockaddr->type.sa.sa_family); 370897be3a4Schristos } 371897be3a4Schristos #endif 372897be3a4Schristos } 373897be3a4Schristos 374897be3a4Schristos void 375897be3a4Schristos isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na, 376897be3a4Schristos in_port_t port) 377897be3a4Schristos { 378897be3a4Schristos memset(sockaddr, 0, sizeof(*sockaddr)); 379897be3a4Schristos sockaddr->type.sin.sin_family = (short)na->family; 380897be3a4Schristos switch (na->family) { 381897be3a4Schristos case AF_INET: 382897be3a4Schristos sockaddr->length = sizeof(sockaddr->type.sin); 383897be3a4Schristos #ifdef ISC_PLATFORM_HAVESALEN 384897be3a4Schristos sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); 385897be3a4Schristos #endif 386897be3a4Schristos sockaddr->type.sin.sin_addr = na->type.in; 387897be3a4Schristos sockaddr->type.sin.sin_port = htons(port); 388897be3a4Schristos break; 389897be3a4Schristos case AF_INET6: 390897be3a4Schristos sockaddr->length = sizeof(sockaddr->type.sin6); 391897be3a4Schristos #ifdef ISC_PLATFORM_HAVESALEN 392897be3a4Schristos sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); 393897be3a4Schristos #endif 394897be3a4Schristos memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16); 395897be3a4Schristos #ifdef ISC_PLATFORM_HAVESCOPEID 396897be3a4Schristos sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na); 397897be3a4Schristos #endif 398897be3a4Schristos sockaddr->type.sin6.sin6_port = htons(port); 399897be3a4Schristos break; 400897be3a4Schristos default: 401897be3a4Schristos INSIST(0); 402897be3a4Schristos } 403897be3a4Schristos ISC_LINK_INIT(sockaddr, link); 404897be3a4Schristos } 405897be3a4Schristos 406897be3a4Schristos void 407897be3a4Schristos isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) { 408897be3a4Schristos switch (sockaddr->type.sa.sa_family) { 409897be3a4Schristos case AF_INET: 410897be3a4Schristos sockaddr->type.sin.sin_port = htons(port); 411897be3a4Schristos break; 412897be3a4Schristos case AF_INET6: 413897be3a4Schristos sockaddr->type.sin6.sin6_port = htons(port); 414897be3a4Schristos break; 415897be3a4Schristos default: 416897be3a4Schristos FATAL_ERROR(__FILE__, __LINE__, 417897be3a4Schristos "%s: %d", 418897be3a4Schristos isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 419897be3a4Schristos ISC_MSG_UNKNOWNFAMILY, 420897be3a4Schristos "unknown address family"), 421897be3a4Schristos (int)sockaddr->type.sa.sa_family); 422897be3a4Schristos } 423897be3a4Schristos } 424897be3a4Schristos 425897be3a4Schristos in_port_t 426897be3a4Schristos isc_sockaddr_getport(const isc_sockaddr_t *sockaddr) { 427897be3a4Schristos in_port_t port = 0; 428897be3a4Schristos 429897be3a4Schristos switch (sockaddr->type.sa.sa_family) { 430897be3a4Schristos case AF_INET: 431897be3a4Schristos port = ntohs(sockaddr->type.sin.sin_port); 432897be3a4Schristos break; 433897be3a4Schristos case AF_INET6: 434897be3a4Schristos port = ntohs(sockaddr->type.sin6.sin6_port); 435897be3a4Schristos break; 436897be3a4Schristos default: 437897be3a4Schristos FATAL_ERROR(__FILE__, __LINE__, 438897be3a4Schristos "%s: %d", 439897be3a4Schristos isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, 440897be3a4Schristos ISC_MSG_UNKNOWNFAMILY, 441897be3a4Schristos "unknown address family"), 442897be3a4Schristos (int)sockaddr->type.sa.sa_family); 443897be3a4Schristos } 444897be3a4Schristos 445897be3a4Schristos return (port); 446897be3a4Schristos } 447897be3a4Schristos 448897be3a4Schristos isc_boolean_t 449897be3a4Schristos isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) { 450897be3a4Schristos isc_netaddr_t netaddr; 451897be3a4Schristos 452897be3a4Schristos if (sockaddr->type.sa.sa_family == AF_INET || 453897be3a4Schristos sockaddr->type.sa.sa_family == AF_INET6) { 454897be3a4Schristos isc_netaddr_fromsockaddr(&netaddr, sockaddr); 455897be3a4Schristos return (isc_netaddr_ismulticast(&netaddr)); 456897be3a4Schristos } 457897be3a4Schristos return (ISC_FALSE); 458897be3a4Schristos } 459897be3a4Schristos 460897be3a4Schristos isc_boolean_t 461897be3a4Schristos isc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) { 462897be3a4Schristos isc_netaddr_t netaddr; 463897be3a4Schristos 464897be3a4Schristos if (sockaddr->type.sa.sa_family == AF_INET) { 465897be3a4Schristos isc_netaddr_fromsockaddr(&netaddr, sockaddr); 466897be3a4Schristos return (isc_netaddr_isexperimental(&netaddr)); 467897be3a4Schristos } 468897be3a4Schristos return (ISC_FALSE); 469897be3a4Schristos } 470897be3a4Schristos 471897be3a4Schristos isc_boolean_t 472897be3a4Schristos isc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) { 473897be3a4Schristos isc_netaddr_t netaddr; 474897be3a4Schristos 475897be3a4Schristos if (sockaddr->type.sa.sa_family == AF_INET6) { 476897be3a4Schristos isc_netaddr_fromsockaddr(&netaddr, sockaddr); 477897be3a4Schristos return (isc_netaddr_issitelocal(&netaddr)); 478897be3a4Schristos } 479897be3a4Schristos return (ISC_FALSE); 480897be3a4Schristos } 481897be3a4Schristos 482897be3a4Schristos isc_boolean_t 483897be3a4Schristos isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) { 484897be3a4Schristos isc_netaddr_t netaddr; 485897be3a4Schristos 486897be3a4Schristos if (sockaddr->type.sa.sa_family == AF_INET6) { 487897be3a4Schristos isc_netaddr_fromsockaddr(&netaddr, sockaddr); 488897be3a4Schristos return (isc_netaddr_islinklocal(&netaddr)); 489897be3a4Schristos } 490897be3a4Schristos return (ISC_FALSE); 491897be3a4Schristos } 492897be3a4Schristos 493897be3a4Schristos isc_result_t 494897be3a4Schristos isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) { 495897be3a4Schristos #ifdef ISC_PLATFORM_HAVESYSUNH 496897be3a4Schristos if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path)) 497897be3a4Schristos return (ISC_R_NOSPACE); 498897be3a4Schristos memset(sockaddr, 0, sizeof(*sockaddr)); 499897be3a4Schristos sockaddr->length = sizeof(sockaddr->type.sunix); 500897be3a4Schristos sockaddr->type.sunix.sun_family = AF_UNIX; 501897be3a4Schristos #ifdef ISC_PLATFORM_HAVESALEN 502897be3a4Schristos sockaddr->type.sunix.sun_len = 503897be3a4Schristos (unsigned char)sizeof(sockaddr->type.sunix); 504897be3a4Schristos #endif 505897be3a4Schristos strcpy(sockaddr->type.sunix.sun_path, path); 506897be3a4Schristos return (ISC_R_SUCCESS); 507897be3a4Schristos #else 508897be3a4Schristos UNUSED(sockaddr); 509897be3a4Schristos UNUSED(path); 510897be3a4Schristos return (ISC_R_NOTIMPLEMENTED); 511897be3a4Schristos #endif 512897be3a4Schristos } 513