diff --git a/conf.c b/conf.c index 3eb117f..b275886 100644 --- a/conf.c +++ b/conf.c @@ -1721,6 +1721,7 @@ void conf(struct ctx *c, int argc, char **argv) /* Inbound port options & DNS can be parsed now (after IPv4/IPv6 * settings) */ + fwd_probe_ephemeral(); udp_portmap_clear(); optind = 0; do { diff --git a/fwd.c b/fwd.c index 8fa312a..a505098 100644 --- a/fwd.c +++ b/fwd.c @@ -28,8 +28,65 @@ #include "flow_table.h" /* Empheral port range: values from RFC 6335 */ -static const in_port_t fwd_ephemeral_min = (1 << 15) + (1 << 14); -static const in_port_t fwd_ephemeral_max = NUM_PORTS - 1; +static in_port_t fwd_ephemeral_min = (1 << 15) + (1 << 14); +static in_port_t fwd_ephemeral_max = NUM_PORTS - 1; + +#define PORT_RANGE_SYSCTL "/proc/sys/net/ipv4/ip_local_port_range" + +/** fwd_probe_ephemeral() - Determine what ports this host considers ephemeral + * + * Work out what ports the host thinks are emphemeral and record it for later + * use by fwd_port_is_ephemeral(). If we're unable to probe, assume the range + * recommended by RFC 6335. + */ +void fwd_probe_ephemeral(void) +{ + char *line, *tab, *end; + struct lineread lr; + long min, max; + ssize_t len; + int fd; + + fd = open(PORT_RANGE_SYSCTL, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + warn_perror("Unable to open %s", PORT_RANGE_SYSCTL); + return; + } + + lineread_init(&lr, fd); + len = lineread_get(&lr, &line); + close(fd); + + if (len < 0) + goto parse_err; + + tab = strchr(line, '\t'); + if (!tab) + goto parse_err; + *tab = '\0'; + + errno = 0; + min = strtol(line, &end, 10); + if (*end || errno) + goto parse_err; + + errno = 0; + max = strtol(tab + 1, &end, 10); + if (*end || errno) + goto parse_err; + + if (min < 0 || min >= NUM_PORTS || + max < 0 || max >= NUM_PORTS) + goto parse_err; + + fwd_ephemeral_min = min; + fwd_ephemeral_max = max; + + return; + +parse_err: + warn("Unable to parse %s", PORT_RANGE_SYSCTL); +} /** * fwd_port_is_ephemeral() - Is port number ephemeral? diff --git a/fwd.h b/fwd.h index 99dd66c..3562f3c 100644 --- a/fwd.h +++ b/fwd.h @@ -12,6 +12,7 @@ struct flowside; /* Number of ports for both TCP and UDP */ #define NUM_PORTS (1U << 16) +void fwd_probe_ephemeral(void); bool fwd_port_is_ephemeral(in_port_t port); enum fwd_ports_mode {