1999-07-08 02:45:47 +00:00
|
|
|
/*
|
2008-06-23 23:47:11 +00:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
1999-07-08 02:45:47 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
1999-07-08 02:45:47 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
1999-07-08 02:45:47 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
2008-06-23 19:41:20 +00:00
|
|
|
* information regarding copyright ownership.
|
1999-07-08 02:45:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
2013-03-26 16:41:49 +11:00
|
|
|
#include <fcntl.h>
|
2022-12-16 11:04:39 +00:00
|
|
|
#include <netdb.h>
|
2024-09-20 08:45:46 +02:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/types.h>
|
2020-03-09 16:17:26 +01:00
|
|
|
#include <sys/uio.h>
|
1999-07-08 02:45:47 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2024-09-20 08:45:46 +02:00
|
|
|
#if HAVE_SYS_SYSCTL_H && !defined(__linux__)
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#endif
|
|
|
|
|
2000-12-19 01:36:52 +00:00
|
|
|
#include <isc/log.h>
|
1999-07-08 02:45:47 +00:00
|
|
|
#include <isc/net.h>
|
|
|
|
#include <isc/once.h>
|
2018-08-28 15:43:44 -07:00
|
|
|
#include <isc/strerr.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/string.h>
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
1999-07-08 02:45:47 +00:00
|
|
|
|
2008-06-23 19:41:20 +00:00
|
|
|
/*%
|
|
|
|
* Definitions about UDP port range specification. This is a total mess of
|
|
|
|
* portability variants: some use sysctl (but the sysctl names vary), some use
|
|
|
|
* system-specific interfaces, some have the same interface for IPv4 and IPv6,
|
|
|
|
* some separate them, etc...
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* The last resort defaults: use all non well known port space
|
|
|
|
*/
|
|
|
|
#ifndef ISC_NET_PORTRANGELOW
|
|
|
|
#define ISC_NET_PORTRANGELOW 1024
|
|
|
|
#endif /* ISC_NET_PORTRANGELOW */
|
|
|
|
#ifndef ISC_NET_PORTRANGEHIGH
|
|
|
|
#define ISC_NET_PORTRANGEHIGH 65535
|
|
|
|
#endif /* ISC_NET_PORTRANGEHIGH */
|
|
|
|
|
2008-07-04 05:52:31 +00:00
|
|
|
#ifdef HAVE_SYSCTLBYNAME
|
|
|
|
|
2008-06-23 19:41:20 +00:00
|
|
|
/*%
|
|
|
|
* sysctl variants
|
|
|
|
*/
|
2008-07-04 05:52:31 +00:00
|
|
|
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
|
2008-06-23 19:41:20 +00:00
|
|
|
#define USE_SYSCTL_PORTRANGE
|
2008-07-04 05:52:31 +00:00
|
|
|
#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.portrange.hifirst"
|
|
|
|
#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.portrange.hilast"
|
|
|
|
#define SYSCTL_V6PORTRANGE_LOW "net.inet.ip.portrange.hifirst"
|
|
|
|
#define SYSCTL_V6PORTRANGE_HIGH "net.inet.ip.portrange.hilast"
|
2008-06-23 19:41:20 +00:00
|
|
|
#endif /* if defined(__FreeBSD__) || defined(__APPLE__) || \
|
2008-07-04 05:52:31 +00:00
|
|
|
* defined(__DragonFly__) */
|
2008-06-23 19:41:20 +00:00
|
|
|
|
|
|
|
#ifdef __NetBSD__
|
|
|
|
#define USE_SYSCTL_PORTRANGE
|
|
|
|
#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.anonportmin"
|
|
|
|
#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.anonportmax"
|
2008-07-04 05:52:31 +00:00
|
|
|
#define SYSCTL_V6PORTRANGE_LOW "net.inet6.ip6.anonportmin"
|
|
|
|
#define SYSCTL_V6PORTRANGE_HIGH "net.inet6.ip6.anonportmax"
|
2008-06-23 19:41:20 +00:00
|
|
|
#endif /* ifdef __NetBSD__ */
|
|
|
|
|
2008-07-04 05:52:31 +00:00
|
|
|
#else /* !HAVE_SYSCTLBYNAME */
|
|
|
|
|
2008-06-23 19:41:20 +00:00
|
|
|
#ifdef __OpenBSD__
|
|
|
|
#define USE_SYSCTL_PORTRANGE
|
2008-07-04 05:52:31 +00:00
|
|
|
#define SYSCTL_V4PORTRANGE_LOW \
|
|
|
|
{ CTL_NET, PF_INET, IPPROTO_IP, IPCTL_IPPORT_HIFIRSTAUTO }
|
|
|
|
#define SYSCTL_V4PORTRANGE_HIGH \
|
|
|
|
{ CTL_NET, PF_INET, IPPROTO_IP, IPCTL_IPPORT_HILASTAUTO }
|
|
|
|
/* Same for IPv6 */
|
|
|
|
#define SYSCTL_V6PORTRANGE_LOW SYSCTL_V4PORTRANGE_LOW
|
|
|
|
#define SYSCTL_V6PORTRANGE_HIGH SYSCTL_V4PORTRANGE_HIGH
|
2008-06-23 19:41:20 +00:00
|
|
|
#endif /* ifdef __OpenBSD__ */
|
|
|
|
|
2008-07-04 05:52:31 +00:00
|
|
|
#endif /* HAVE_SYSCTLBYNAME */
|
|
|
|
|
2024-08-20 11:53:07 +02:00
|
|
|
static isc_result_t ipv4_result = ISC_R_SUCCESS;
|
|
|
|
static isc_result_t ipv6_result = ISC_R_SUCCESS;
|
1999-07-08 02:45:47 +00:00
|
|
|
|
|
|
|
isc_result_t
|
1999-07-19 23:54:09 +00:00
|
|
|
isc_net_probeipv4(void) {
|
1999-07-08 02:45:47 +00:00
|
|
|
return ipv4_result;
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
1999-07-19 23:54:09 +00:00
|
|
|
isc_net_probeipv6(void) {
|
1999-07-08 02:45:47 +00:00
|
|
|
return ipv6_result;
|
|
|
|
}
|
2002-10-29 04:40:26 +00:00
|
|
|
|
2008-07-04 05:52:31 +00:00
|
|
|
#if defined(USE_SYSCTL_PORTRANGE)
|
|
|
|
#if defined(HAVE_SYSCTLBYNAME)
|
2008-06-23 19:41:20 +00:00
|
|
|
static isc_result_t
|
|
|
|
getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
|
|
|
|
int port_low, port_high;
|
|
|
|
size_t portlen;
|
|
|
|
const char *sysctlname_lowport, *sysctlname_hiport;
|
|
|
|
|
|
|
|
if (af == AF_INET) {
|
|
|
|
sysctlname_lowport = SYSCTL_V4PORTRANGE_LOW;
|
|
|
|
sysctlname_hiport = SYSCTL_V4PORTRANGE_HIGH;
|
|
|
|
} else {
|
|
|
|
sysctlname_lowport = SYSCTL_V6PORTRANGE_LOW;
|
|
|
|
sysctlname_hiport = SYSCTL_V6PORTRANGE_HIGH;
|
|
|
|
}
|
2015-04-25 08:25:42 +10:00
|
|
|
portlen = sizeof(port_low);
|
2008-06-23 19:41:20 +00:00
|
|
|
if (sysctlbyname(sysctlname_lowport, &port_low, &portlen, NULL, 0) < 0)
|
|
|
|
{
|
|
|
|
return ISC_R_FAILURE;
|
|
|
|
}
|
2015-04-25 08:25:42 +10:00
|
|
|
portlen = sizeof(port_high);
|
2008-06-23 19:41:20 +00:00
|
|
|
if (sysctlbyname(sysctlname_hiport, &port_high, &portlen, NULL, 0) < 0)
|
|
|
|
{
|
|
|
|
return ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0) {
|
|
|
|
return ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-06-23 19:41:20 +00:00
|
|
|
|
|
|
|
*low = (in_port_t)port_low;
|
|
|
|
*high = (in_port_t)port_high;
|
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
2008-07-04 05:52:31 +00:00
|
|
|
#else /* !HAVE_SYSCTLBYNAME */
|
|
|
|
static isc_result_t
|
|
|
|
getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
|
|
|
|
int mib_lo4[4] = SYSCTL_V4PORTRANGE_LOW;
|
|
|
|
int mib_hi4[4] = SYSCTL_V4PORTRANGE_HIGH;
|
|
|
|
int mib_lo6[4] = SYSCTL_V6PORTRANGE_LOW;
|
|
|
|
int mib_hi6[4] = SYSCTL_V6PORTRANGE_HIGH;
|
|
|
|
int *mib_lo, *mib_hi, miblen;
|
|
|
|
int port_low, port_high;
|
|
|
|
size_t portlen;
|
|
|
|
|
|
|
|
if (af == AF_INET) {
|
|
|
|
mib_lo = mib_lo4;
|
|
|
|
mib_hi = mib_hi4;
|
|
|
|
miblen = sizeof(mib_lo4) / sizeof(mib_lo4[0]);
|
|
|
|
} else {
|
|
|
|
mib_lo = mib_lo6;
|
|
|
|
mib_hi = mib_hi6;
|
|
|
|
miblen = sizeof(mib_lo6) / sizeof(mib_lo6[0]);
|
|
|
|
}
|
|
|
|
|
2015-04-25 08:25:42 +10:00
|
|
|
portlen = sizeof(port_low);
|
2008-07-04 05:52:31 +00:00
|
|
|
if (sysctl(mib_lo, miblen, &port_low, &portlen, NULL, 0) < 0) {
|
|
|
|
return ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
2015-04-25 08:25:42 +10:00
|
|
|
portlen = sizeof(port_high);
|
2008-07-04 05:52:31 +00:00
|
|
|
if (sysctl(mib_hi, miblen, &port_high, &portlen, NULL, 0) < 0) {
|
|
|
|
return ISC_R_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0) {
|
|
|
|
return ISC_R_RANGE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-07-04 05:52:31 +00:00
|
|
|
|
|
|
|
*low = (in_port_t)port_low;
|
|
|
|
*high = (in_port_t)port_high;
|
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_SYSCTLBYNAME */
|
|
|
|
#endif /* USE_SYSCTL_PORTRANGE */
|
2008-06-23 19:41:20 +00:00
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
|
|
|
|
int result = ISC_R_FAILURE;
|
2015-04-25 08:25:42 +10:00
|
|
|
#if !defined(USE_SYSCTL_PORTRANGE) && defined(__linux)
|
|
|
|
FILE *fp;
|
|
|
|
#endif /* if !defined(USE_SYSCTL_PORTRANGE) && defined(__linux) */
|
2008-06-23 19:41:20 +00:00
|
|
|
|
|
|
|
REQUIRE(low != NULL && high != NULL);
|
|
|
|
|
2008-07-04 05:52:31 +00:00
|
|
|
#if defined(USE_SYSCTL_PORTRANGE)
|
2008-06-23 19:41:20 +00:00
|
|
|
result = getudpportrange_sysctl(af, low, high);
|
2015-04-25 08:25:42 +10:00
|
|
|
#elif defined(__linux)
|
|
|
|
|
|
|
|
UNUSED(af);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Linux local ports are address family agnostic.
|
|
|
|
*/
|
|
|
|
fp = fopen("/proc/sys/net/ipv4/ip_local_port_range", "r");
|
|
|
|
if (fp != NULL) {
|
|
|
|
int n;
|
|
|
|
unsigned int l, h;
|
|
|
|
|
|
|
|
n = fscanf(fp, "%u %u", &l, &h);
|
|
|
|
if (n == 2 && (l & ~0xffff) == 0 && (h & ~0xffff) == 0) {
|
|
|
|
*low = l;
|
|
|
|
*high = h;
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
}
|
2008-06-23 19:41:20 +00:00
|
|
|
#else /* if defined(USE_SYSCTL_PORTRANGE) */
|
|
|
|
UNUSED(af);
|
|
|
|
#endif /* if defined(USE_SYSCTL_PORTRANGE) */
|
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
*low = ISC_NET_PORTRANGELOW;
|
|
|
|
*high = ISC_NET_PORTRANGEHIGH;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ISC_R_SUCCESS; /* we currently never fail in this function */
|
|
|
|
}
|
|
|
|
|
2003-01-16 03:59:28 +00:00
|
|
|
void
|
|
|
|
isc_net_disableipv4(void) {
|
|
|
|
if (ipv4_result == ISC_R_SUCCESS) {
|
|
|
|
ipv4_result = ISC_R_DISABLED;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isc_net_disableipv6(void) {
|
|
|
|
if (ipv6_result == ISC_R_SUCCESS) {
|
|
|
|
ipv6_result = ISC_R_DISABLED;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isc_net_enableipv4(void) {
|
|
|
|
if (ipv4_result == ISC_R_DISABLED) {
|
|
|
|
ipv4_result = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
isc_net_enableipv6(void) {
|
|
|
|
if (ipv6_result == ISC_R_DISABLED) {
|
|
|
|
ipv6_result = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2003-01-16 03:59:28 +00:00
|
|
|
}
|