1*eabc0478Schristos /* $NetBSD: net.c,v 1.2 2024/08/18 20:47:16 christos Exp $ */ 2897be3a4Schristos 3897be3a4Schristos /* 4897be3a4Schristos * Copyright (C) 2004, 2005, 2007, 2008, 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 #include <config.h> 23897be3a4Schristos 24897be3a4Schristos #include <sys/types.h> 25897be3a4Schristos 26897be3a4Schristos #if defined(HAVE_SYS_SYSCTL_H) 27897be3a4Schristos #if defined(HAVE_SYS_PARAM_H) 28897be3a4Schristos #include <sys/param.h> 29897be3a4Schristos #endif 30897be3a4Schristos #include <sys/sysctl.h> 31897be3a4Schristos #endif 32897be3a4Schristos 33897be3a4Schristos #include <errno.h> 34897be3a4Schristos #include <unistd.h> 35897be3a4Schristos 36897be3a4Schristos #include <isc/log.h> 37897be3a4Schristos #include <isc/msgs.h> 38897be3a4Schristos #include <isc/net.h> 39897be3a4Schristos #include <isc/once.h> 40897be3a4Schristos #include <isc/strerror.h> 41897be3a4Schristos #include <isc/string.h> 42897be3a4Schristos #include <isc/util.h> 43897be3a4Schristos 44897be3a4Schristos /*% 45897be3a4Schristos * Definitions about UDP port range specification. This is a total mess of 46897be3a4Schristos * portability variants: some use sysctl (but the sysctl names vary), some use 47897be3a4Schristos * system-specific interfaces, some have the same interface for IPv4 and IPv6, 48897be3a4Schristos * some separate them, etc... 49897be3a4Schristos */ 50897be3a4Schristos 51897be3a4Schristos /*% 52897be3a4Schristos * The last resort defaults: use all non well known port space 53897be3a4Schristos */ 54897be3a4Schristos #ifndef ISC_NET_PORTRANGELOW 55897be3a4Schristos #define ISC_NET_PORTRANGELOW 1024 56897be3a4Schristos #endif /* ISC_NET_PORTRANGELOW */ 57897be3a4Schristos #ifndef ISC_NET_PORTRANGEHIGH 58897be3a4Schristos #define ISC_NET_PORTRANGEHIGH 65535 59897be3a4Schristos #endif /* ISC_NET_PORTRANGEHIGH */ 60897be3a4Schristos 61897be3a4Schristos #ifdef HAVE_SYSCTLBYNAME 62897be3a4Schristos 63897be3a4Schristos /*% 64897be3a4Schristos * sysctl variants 65897be3a4Schristos */ 66897be3a4Schristos #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__) 67897be3a4Schristos #define USE_SYSCTL_PORTRANGE 68897be3a4Schristos #define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.portrange.hifirst" 69897be3a4Schristos #define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.portrange.hilast" 70897be3a4Schristos #define SYSCTL_V6PORTRANGE_LOW "net.inet.ip.portrange.hifirst" 71897be3a4Schristos #define SYSCTL_V6PORTRANGE_HIGH "net.inet.ip.portrange.hilast" 72897be3a4Schristos #endif 73897be3a4Schristos 74897be3a4Schristos #ifdef __NetBSD__ 75897be3a4Schristos #define USE_SYSCTL_PORTRANGE 76897be3a4Schristos #define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.anonportmin" 77897be3a4Schristos #define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.anonportmax" 78897be3a4Schristos #define SYSCTL_V6PORTRANGE_LOW "net.inet6.ip6.anonportmin" 79897be3a4Schristos #define SYSCTL_V6PORTRANGE_HIGH "net.inet6.ip6.anonportmax" 80897be3a4Schristos #endif 81897be3a4Schristos 82897be3a4Schristos #else /* !HAVE_SYSCTLBYNAME */ 83897be3a4Schristos 84897be3a4Schristos #ifdef __OpenBSD__ 85897be3a4Schristos #define USE_SYSCTL_PORTRANGE 86897be3a4Schristos #define SYSCTL_V4PORTRANGE_LOW { CTL_NET, PF_INET, IPPROTO_IP, \ 87897be3a4Schristos IPCTL_IPPORT_HIFIRSTAUTO } 88897be3a4Schristos #define SYSCTL_V4PORTRANGE_HIGH { CTL_NET, PF_INET, IPPROTO_IP, \ 89897be3a4Schristos IPCTL_IPPORT_HILASTAUTO } 90897be3a4Schristos /* Same for IPv6 */ 91897be3a4Schristos #define SYSCTL_V6PORTRANGE_LOW SYSCTL_V4PORTRANGE_LOW 92897be3a4Schristos #define SYSCTL_V6PORTRANGE_HIGH SYSCTL_V4PORTRANGE_HIGH 93897be3a4Schristos #endif 94897be3a4Schristos 95897be3a4Schristos #endif /* HAVE_SYSCTLBYNAME */ 96897be3a4Schristos 97897be3a4Schristos #if defined(ISC_PLATFORM_NEEDIN6ADDRANY) 98897be3a4Schristos const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT; 99897be3a4Schristos #endif 100897be3a4Schristos 101897be3a4Schristos #if defined(ISC_PLATFORM_HAVEIPV6) 102897be3a4Schristos 103897be3a4Schristos # if defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK) 104897be3a4Schristos const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT; 105897be3a4Schristos # endif 106897be3a4Schristos 107897be3a4Schristos # if defined(WANT_IPV6) 108897be3a4Schristos static isc_once_t once_ipv6only = ISC_ONCE_INIT; 109897be3a4Schristos # endif 110897be3a4Schristos 111897be3a4Schristos # if defined(ISC_PLATFORM_HAVEIPV6) && \ 112897be3a4Schristos defined(WANT_IPV6) && defined(ISC_PLATFORM_HAVEIN6PKTINFO) 113897be3a4Schristos static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; 114897be3a4Schristos # endif 115897be3a4Schristos #endif /* ISC_PLATFORM_HAVEIPV6 */ 116897be3a4Schristos 117897be3a4Schristos static isc_once_t once = ISC_ONCE_INIT; 118897be3a4Schristos 119897be3a4Schristos static isc_result_t ipv4_result = ISC_R_NOTFOUND; 120897be3a4Schristos static isc_result_t ipv6_result = ISC_R_NOTFOUND; 121897be3a4Schristos static isc_result_t unix_result = ISC_R_NOTFOUND; 122897be3a4Schristos static isc_result_t ipv6only_result = ISC_R_NOTFOUND; 123897be3a4Schristos static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND; 124897be3a4Schristos 125897be3a4Schristos static isc_result_t 126897be3a4Schristos try_proto(int domain) { 127897be3a4Schristos int s; 128897be3a4Schristos isc_result_t result = ISC_R_SUCCESS; 129897be3a4Schristos char strbuf[ISC_STRERRORSIZE]; 130897be3a4Schristos 131897be3a4Schristos s = socket(domain, SOCK_STREAM, 0); 132897be3a4Schristos if (s == -1) { 133897be3a4Schristos switch (errno) { 134897be3a4Schristos #ifdef EAFNOSUPPORT 135897be3a4Schristos case EAFNOSUPPORT: 136897be3a4Schristos #endif 137897be3a4Schristos #ifdef EPROTONOSUPPORT 138897be3a4Schristos case EPROTONOSUPPORT: 139897be3a4Schristos #endif 140897be3a4Schristos #ifdef EINVAL 141897be3a4Schristos case EINVAL: 142897be3a4Schristos #endif 143897be3a4Schristos return (ISC_R_NOTFOUND); 144897be3a4Schristos default: 145897be3a4Schristos isc__strerror(errno, strbuf, sizeof(strbuf)); 146897be3a4Schristos UNEXPECTED_ERROR(__FILE__, __LINE__, 147897be3a4Schristos "socket() %s: %s", 148897be3a4Schristos isc_msgcat_get(isc_msgcat, 149897be3a4Schristos ISC_MSGSET_GENERAL, 150897be3a4Schristos ISC_MSG_FAILED, 151897be3a4Schristos "failed"), 152897be3a4Schristos strbuf); 153897be3a4Schristos return (ISC_R_UNEXPECTED); 154897be3a4Schristos } 155897be3a4Schristos } 156897be3a4Schristos 157897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIPV6 158897be3a4Schristos #ifdef WANT_IPV6 159897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIN6PKTINFO 160897be3a4Schristos if (domain == PF_INET6) { 161897be3a4Schristos struct sockaddr_in6 sin6; 162897be3a4Schristos GETSOCKNAME_SOCKLEN_TYPE len; /* NTP local change */ 163897be3a4Schristos 164897be3a4Schristos /* 165897be3a4Schristos * Check to see if IPv6 is broken, as is common on Linux. 166897be3a4Schristos */ 167897be3a4Schristos len = sizeof(sin6); 168897be3a4Schristos if (getsockname(s, (struct sockaddr *)&sin6, &len) < 0) 169897be3a4Schristos { 170897be3a4Schristos isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 171897be3a4Schristos ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, 172897be3a4Schristos "retrieving the address of an IPv6 " 173897be3a4Schristos "socket from the kernel failed."); 174897be3a4Schristos isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, 175897be3a4Schristos ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, 176897be3a4Schristos "IPv6 is not supported."); 177897be3a4Schristos result = ISC_R_NOTFOUND; 178897be3a4Schristos } else { 179897be3a4Schristos if (len == sizeof(struct sockaddr_in6)) 180897be3a4Schristos result = ISC_R_SUCCESS; 181897be3a4Schristos else { 182897be3a4Schristos isc_log_write(isc_lctx, 183897be3a4Schristos ISC_LOGCATEGORY_GENERAL, 184897be3a4Schristos ISC_LOGMODULE_SOCKET, 185897be3a4Schristos ISC_LOG_ERROR, 186897be3a4Schristos "IPv6 structures in kernel and " 187897be3a4Schristos "user space do not match."); 188897be3a4Schristos isc_log_write(isc_lctx, 189897be3a4Schristos ISC_LOGCATEGORY_GENERAL, 190897be3a4Schristos ISC_LOGMODULE_SOCKET, 191897be3a4Schristos ISC_LOG_ERROR, 192897be3a4Schristos "IPv6 is not supported."); 193897be3a4Schristos result = ISC_R_NOTFOUND; 194897be3a4Schristos } 195897be3a4Schristos } 196897be3a4Schristos } 197897be3a4Schristos #endif 198897be3a4Schristos #endif 199897be3a4Schristos #endif 200897be3a4Schristos 201897be3a4Schristos (void)close(s); 202897be3a4Schristos 203897be3a4Schristos return (result); 204897be3a4Schristos } 205897be3a4Schristos 206897be3a4Schristos static void 207897be3a4Schristos initialize_action(void) { 208897be3a4Schristos ipv4_result = try_proto(PF_INET); 209897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIPV6 210897be3a4Schristos #ifdef WANT_IPV6 211897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIN6PKTINFO 212897be3a4Schristos ipv6_result = try_proto(PF_INET6); 213897be3a4Schristos #endif 214897be3a4Schristos #endif 215897be3a4Schristos #endif 216897be3a4Schristos #ifdef ISC_PLATFORM_HAVESYSUNH 217897be3a4Schristos unix_result = try_proto(PF_UNIX); 218897be3a4Schristos #endif 219897be3a4Schristos } 220897be3a4Schristos 221897be3a4Schristos static void 222897be3a4Schristos initialize(void) { 223897be3a4Schristos RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); 224897be3a4Schristos } 225897be3a4Schristos 226897be3a4Schristos isc_result_t 227897be3a4Schristos isc_net_probeipv4(void) { 228897be3a4Schristos initialize(); 229897be3a4Schristos return (ipv4_result); 230897be3a4Schristos } 231897be3a4Schristos 232897be3a4Schristos isc_result_t 233897be3a4Schristos isc_net_probeipv6(void) { 234897be3a4Schristos initialize(); 235897be3a4Schristos return (ipv6_result); 236897be3a4Schristos } 237897be3a4Schristos 238897be3a4Schristos isc_result_t 239897be3a4Schristos isc_net_probeunix(void) { 240897be3a4Schristos initialize(); 241897be3a4Schristos return (unix_result); 242897be3a4Schristos } 243897be3a4Schristos 244897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIPV6 245897be3a4Schristos #ifdef WANT_IPV6 246897be3a4Schristos static void 247897be3a4Schristos try_ipv6only(void) { 248897be3a4Schristos #ifdef IPV6_V6ONLY 249897be3a4Schristos int s, on; 250897be3a4Schristos char strbuf[ISC_STRERRORSIZE]; 251897be3a4Schristos #endif 252897be3a4Schristos isc_result_t result; 253897be3a4Schristos 254897be3a4Schristos result = isc_net_probeipv6(); 255897be3a4Schristos if (result != ISC_R_SUCCESS) { 256897be3a4Schristos ipv6only_result = result; 257897be3a4Schristos return; 258897be3a4Schristos } 259897be3a4Schristos 260897be3a4Schristos #ifndef IPV6_V6ONLY 261897be3a4Schristos ipv6only_result = ISC_R_NOTFOUND; 262897be3a4Schristos return; 263897be3a4Schristos #else 264897be3a4Schristos /* check for TCP sockets */ 265897be3a4Schristos s = socket(PF_INET6, SOCK_STREAM, 0); 266897be3a4Schristos if (s == -1) { 267897be3a4Schristos isc__strerror(errno, strbuf, sizeof(strbuf)); 268897be3a4Schristos UNEXPECTED_ERROR(__FILE__, __LINE__, 269897be3a4Schristos "socket() %s: %s", 270897be3a4Schristos isc_msgcat_get(isc_msgcat, 271897be3a4Schristos ISC_MSGSET_GENERAL, 272897be3a4Schristos ISC_MSG_FAILED, 273897be3a4Schristos "failed"), 274897be3a4Schristos strbuf); 275897be3a4Schristos ipv6only_result = ISC_R_UNEXPECTED; 276897be3a4Schristos return; 277897be3a4Schristos } 278897be3a4Schristos 279897be3a4Schristos on = 1; 280897be3a4Schristos if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { 281897be3a4Schristos ipv6only_result = ISC_R_NOTFOUND; 282897be3a4Schristos goto close; 283897be3a4Schristos } 284897be3a4Schristos 285897be3a4Schristos close(s); 286897be3a4Schristos 287897be3a4Schristos /* check for UDP sockets */ 288897be3a4Schristos s = socket(PF_INET6, SOCK_DGRAM, 0); 289897be3a4Schristos if (s == -1) { 290897be3a4Schristos isc__strerror(errno, strbuf, sizeof(strbuf)); 291897be3a4Schristos UNEXPECTED_ERROR(__FILE__, __LINE__, 292897be3a4Schristos "socket() %s: %s", 293897be3a4Schristos isc_msgcat_get(isc_msgcat, 294897be3a4Schristos ISC_MSGSET_GENERAL, 295897be3a4Schristos ISC_MSG_FAILED, 296897be3a4Schristos "failed"), 297897be3a4Schristos strbuf); 298897be3a4Schristos ipv6only_result = ISC_R_UNEXPECTED; 299897be3a4Schristos return; 300897be3a4Schristos } 301897be3a4Schristos 302897be3a4Schristos on = 1; 303897be3a4Schristos if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { 304897be3a4Schristos ipv6only_result = ISC_R_NOTFOUND; 305897be3a4Schristos goto close; 306897be3a4Schristos } 307897be3a4Schristos 308897be3a4Schristos ipv6only_result = ISC_R_SUCCESS; 309897be3a4Schristos 310897be3a4Schristos close: 311897be3a4Schristos close(s); 312897be3a4Schristos return; 313897be3a4Schristos #endif /* IPV6_V6ONLY */ 314897be3a4Schristos } 315897be3a4Schristos 316897be3a4Schristos static void 317897be3a4Schristos initialize_ipv6only(void) { 318897be3a4Schristos RUNTIME_CHECK(isc_once_do(&once_ipv6only, 319897be3a4Schristos try_ipv6only) == ISC_R_SUCCESS); 320897be3a4Schristos } 321897be3a4Schristos 322897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIN6PKTINFO 323897be3a4Schristos static void 324897be3a4Schristos try_ipv6pktinfo(void) { 325897be3a4Schristos int s, on; 326897be3a4Schristos char strbuf[ISC_STRERRORSIZE]; 327897be3a4Schristos isc_result_t result; 328897be3a4Schristos int optname; 329897be3a4Schristos 330897be3a4Schristos result = isc_net_probeipv6(); 331897be3a4Schristos if (result != ISC_R_SUCCESS) { 332897be3a4Schristos ipv6pktinfo_result = result; 333897be3a4Schristos return; 334897be3a4Schristos } 335897be3a4Schristos 336897be3a4Schristos /* we only use this for UDP sockets */ 337897be3a4Schristos s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 338897be3a4Schristos if (s == -1) { 339897be3a4Schristos isc__strerror(errno, strbuf, sizeof(strbuf)); 340897be3a4Schristos UNEXPECTED_ERROR(__FILE__, __LINE__, 341897be3a4Schristos "socket() %s: %s", 342897be3a4Schristos isc_msgcat_get(isc_msgcat, 343897be3a4Schristos ISC_MSGSET_GENERAL, 344897be3a4Schristos ISC_MSG_FAILED, 345897be3a4Schristos "failed"), 346897be3a4Schristos strbuf); 347897be3a4Schristos ipv6pktinfo_result = ISC_R_UNEXPECTED; 348897be3a4Schristos return; 349897be3a4Schristos } 350897be3a4Schristos 351897be3a4Schristos #ifdef IPV6_RECVPKTINFO 352897be3a4Schristos optname = IPV6_RECVPKTINFO; 353897be3a4Schristos #else 354897be3a4Schristos optname = IPV6_PKTINFO; 355897be3a4Schristos #endif 356897be3a4Schristos on = 1; 357897be3a4Schristos if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) { 358897be3a4Schristos ipv6pktinfo_result = ISC_R_NOTFOUND; 359897be3a4Schristos goto close; 360897be3a4Schristos } 361897be3a4Schristos 362897be3a4Schristos ipv6pktinfo_result = ISC_R_SUCCESS; 363897be3a4Schristos 364897be3a4Schristos close: 365897be3a4Schristos close(s); 366897be3a4Schristos return; 367897be3a4Schristos } 368897be3a4Schristos 369897be3a4Schristos static void 370897be3a4Schristos initialize_ipv6pktinfo(void) { 371897be3a4Schristos RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo, 372897be3a4Schristos try_ipv6pktinfo) == ISC_R_SUCCESS); 373897be3a4Schristos } 374897be3a4Schristos #endif /* ISC_PLATFORM_HAVEIN6PKTINFO */ 375897be3a4Schristos #endif /* WANT_IPV6 */ 376897be3a4Schristos #endif /* ISC_PLATFORM_HAVEIPV6 */ 377897be3a4Schristos 378897be3a4Schristos isc_result_t 379897be3a4Schristos isc_net_probe_ipv6only(void) { 380897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIPV6 381897be3a4Schristos #ifdef WANT_IPV6 382897be3a4Schristos initialize_ipv6only(); 383897be3a4Schristos #else 384897be3a4Schristos ipv6only_result = ISC_R_NOTFOUND; 385897be3a4Schristos #endif 386897be3a4Schristos #endif 387897be3a4Schristos return (ipv6only_result); 388897be3a4Schristos } 389897be3a4Schristos 390897be3a4Schristos isc_result_t 391897be3a4Schristos isc_net_probe_ipv6pktinfo(void) { 392897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIPV6 393897be3a4Schristos #ifdef ISC_PLATFORM_HAVEIN6PKTINFO 394897be3a4Schristos #ifdef WANT_IPV6 395897be3a4Schristos initialize_ipv6pktinfo(); 396897be3a4Schristos #else 397897be3a4Schristos ipv6pktinfo_result = ISC_R_NOTFOUND; 398897be3a4Schristos #endif 399897be3a4Schristos #endif 400897be3a4Schristos #endif 401897be3a4Schristos return (ipv6pktinfo_result); 402897be3a4Schristos } 403897be3a4Schristos 404897be3a4Schristos #if defined(USE_SYSCTL_PORTRANGE) 405897be3a4Schristos #if defined(HAVE_SYSCTLBYNAME) 406897be3a4Schristos static isc_result_t 407897be3a4Schristos getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) { 408897be3a4Schristos int port_low, port_high; 409897be3a4Schristos size_t portlen; 410897be3a4Schristos const char *sysctlname_lowport, *sysctlname_hiport; 411897be3a4Schristos 412897be3a4Schristos if (af == AF_INET) { 413897be3a4Schristos sysctlname_lowport = SYSCTL_V4PORTRANGE_LOW; 414897be3a4Schristos sysctlname_hiport = SYSCTL_V4PORTRANGE_HIGH; 415897be3a4Schristos } else { 416897be3a4Schristos sysctlname_lowport = SYSCTL_V6PORTRANGE_LOW; 417897be3a4Schristos sysctlname_hiport = SYSCTL_V6PORTRANGE_HIGH; 418897be3a4Schristos } 419897be3a4Schristos portlen = sizeof(portlen); 420897be3a4Schristos if (sysctlbyname(sysctlname_lowport, &port_low, &portlen, 421897be3a4Schristos NULL, 0) < 0) { 422897be3a4Schristos return (ISC_R_FAILURE); 423897be3a4Schristos } 424897be3a4Schristos portlen = sizeof(portlen); 425897be3a4Schristos if (sysctlbyname(sysctlname_hiport, &port_high, &portlen, 426897be3a4Schristos NULL, 0) < 0) { 427897be3a4Schristos return (ISC_R_FAILURE); 428897be3a4Schristos } 429897be3a4Schristos if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0) 430897be3a4Schristos return (ISC_R_RANGE); 431897be3a4Schristos 432897be3a4Schristos *low = (in_port_t)port_low; 433897be3a4Schristos *high = (in_port_t)port_high; 434897be3a4Schristos 435897be3a4Schristos return (ISC_R_SUCCESS); 436897be3a4Schristos } 437897be3a4Schristos #else /* !HAVE_SYSCTLBYNAME */ 438897be3a4Schristos static isc_result_t 439897be3a4Schristos getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) { 440897be3a4Schristos int mib_lo4[4] = SYSCTL_V4PORTRANGE_LOW; 441897be3a4Schristos int mib_hi4[4] = SYSCTL_V4PORTRANGE_HIGH; 442897be3a4Schristos int mib_lo6[4] = SYSCTL_V6PORTRANGE_LOW; 443897be3a4Schristos int mib_hi6[4] = SYSCTL_V6PORTRANGE_HIGH; 444897be3a4Schristos int *mib_lo, *mib_hi, miblen; 445897be3a4Schristos int port_low, port_high; 446897be3a4Schristos size_t portlen; 447897be3a4Schristos 448897be3a4Schristos if (af == AF_INET) { 449897be3a4Schristos mib_lo = mib_lo4; 450897be3a4Schristos mib_hi = mib_hi4; 451897be3a4Schristos miblen = sizeof(mib_lo4) / sizeof(mib_lo4[0]); 452897be3a4Schristos } else { 453897be3a4Schristos mib_lo = mib_lo6; 454897be3a4Schristos mib_hi = mib_hi6; 455897be3a4Schristos miblen = sizeof(mib_lo6) / sizeof(mib_lo6[0]); 456897be3a4Schristos } 457897be3a4Schristos 458897be3a4Schristos portlen = sizeof(portlen); 459897be3a4Schristos if (sysctl(mib_lo, miblen, &port_low, &portlen, NULL, 0) < 0) { 460897be3a4Schristos return (ISC_R_FAILURE); 461897be3a4Schristos } 462897be3a4Schristos 463897be3a4Schristos portlen = sizeof(portlen); 464897be3a4Schristos if (sysctl(mib_hi, miblen, &port_high, &portlen, NULL, 0) < 0) { 465897be3a4Schristos return (ISC_R_FAILURE); 466897be3a4Schristos } 467897be3a4Schristos 468897be3a4Schristos if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0) 469897be3a4Schristos return (ISC_R_RANGE); 470897be3a4Schristos 471897be3a4Schristos *low = (in_port_t) port_low; 472897be3a4Schristos *high = (in_port_t) port_high; 473897be3a4Schristos 474897be3a4Schristos return (ISC_R_SUCCESS); 475897be3a4Schristos } 476897be3a4Schristos #endif /* HAVE_SYSCTLBYNAME */ 477897be3a4Schristos #endif /* USE_SYSCTL_PORTRANGE */ 478897be3a4Schristos 479897be3a4Schristos isc_result_t 480897be3a4Schristos isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) { 481897be3a4Schristos int result = ISC_R_FAILURE; 482897be3a4Schristos 483897be3a4Schristos REQUIRE(low != NULL && high != NULL); 484897be3a4Schristos 485897be3a4Schristos #if defined(USE_SYSCTL_PORTRANGE) 486897be3a4Schristos result = getudpportrange_sysctl(af, low, high); 487897be3a4Schristos #else 488897be3a4Schristos UNUSED(af); 489897be3a4Schristos #endif 490897be3a4Schristos 491897be3a4Schristos if (result != ISC_R_SUCCESS) { 492897be3a4Schristos *low = ISC_NET_PORTRANGELOW; 493897be3a4Schristos *high = ISC_NET_PORTRANGEHIGH; 494897be3a4Schristos } 495897be3a4Schristos 496897be3a4Schristos return (ISC_R_SUCCESS); /* we currently never fail in this function */ 497897be3a4Schristos } 498897be3a4Schristos 499897be3a4Schristos void 500897be3a4Schristos isc_net_disableipv4(void) { 501897be3a4Schristos initialize(); 502897be3a4Schristos if (ipv4_result == ISC_R_SUCCESS) 503897be3a4Schristos ipv4_result = ISC_R_DISABLED; 504897be3a4Schristos } 505897be3a4Schristos 506897be3a4Schristos void 507897be3a4Schristos isc_net_disableipv6(void) { 508897be3a4Schristos initialize(); 509897be3a4Schristos if (ipv6_result == ISC_R_SUCCESS) 510897be3a4Schristos ipv6_result = ISC_R_DISABLED; 511897be3a4Schristos } 512897be3a4Schristos 513897be3a4Schristos void 514897be3a4Schristos isc_net_enableipv4(void) { 515897be3a4Schristos initialize(); 516897be3a4Schristos if (ipv4_result == ISC_R_DISABLED) 517897be3a4Schristos ipv4_result = ISC_R_SUCCESS; 518897be3a4Schristos } 519897be3a4Schristos 520897be3a4Schristos void 521897be3a4Schristos isc_net_enableipv6(void) { 522897be3a4Schristos initialize(); 523897be3a4Schristos if (ipv6_result == ISC_R_DISABLED) 524897be3a4Schristos ipv6_result = ISC_R_SUCCESS; 525897be3a4Schristos } 526