From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202408 header.b=govcBlHd; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 564345A004C for ; Thu, 29 Aug 2024 03:32:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202408; t=1724895163; bh=sbWKOYQRVyRn0p0PIRBEGcQvkjeI5qytDsyzS4RD03o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=govcBlHdfmYMCyFapidaY0jXA35BLF9rZ8q3EdKDxGwG30Js0JEpxvegdlow12kyt vLpSKfnrmgtrAL7ZJ3jlGZzGJi1qpLvU/vqC7IylHKpAe9ex7EGSdbdfT5/Ky3i8FS Pa60gJ79mrXN95i35wBNQFgGVIbKIGVmvc3NxR0Dg810bxcWW0wfY1UdZkXNzItPm4 ApJ8TRrUhGZC/7EdJvVjfWBBv/cZTVsTPflKALjuJHM9Ocaqw3KI+6oQTOyCwxr0zP jj6if0ooFWO0vX4zcpd7QS29aIoJW/4kgs7ZoIXsb2z/D7wVlnGZedgZu8yGw3j1dX JAvEUp4i+kj/g== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4WvP0q47cHz4wxJ; Thu, 29 Aug 2024 11:32:43 +1000 (AEST) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH v2 1/3] conf, fwd: Make ephemeral port logic more flexible Date: Thu, 29 Aug 2024 11:32:40 +1000 Message-ID: <20240829013242.3396770-2-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240829013242.3396770-1-david@gibson.dropbear.id.au> References: <20240829013242.3396770-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: U6QFN6BUZEXI65R3F42EU5UDKL2W2NYM X-Message-ID-Hash: U6QFN6BUZEXI65R3F42EU5UDKL2W2NYM X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson , Laurent Vivier X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: "Ephemeral" ports are those which the kernel may allocate as local port numbers for outgoing connections or datagrams. Because of that, they're generally not good choices for listening servers to bind to. Thefore when using -t all, -u all or exclude-only ranges, we map only non-ephemeral ports. Our logic for this is a bit rigid though: we assume the ephemeral ports are always a fixed range at the top of the port number space. We also assume PORT_EPHEMERAL_MIN is a multiple of 8, or we won't set the forward bitmap correctly. Make the logic in conf.c more flexible, using a helper moved into fwd.[ch], although we don't change which ports we consider ephemeral (yet). The new handling is undoubtedly more computationally expensive, but since it's a once-off operation at start off, I don't think it really matters. Signed-off-by: David Gibson Reviewed-by: Laurent Vivier --- conf.c | 12 ++++++++---- fwd.c | 17 +++++++++++++++++ fwd.h | 2 ++ util.h | 3 --- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/conf.c b/conf.c index e29b6a92..6b3dafd5 100644 --- a/conf.c +++ b/conf.c @@ -156,9 +156,12 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg, die("'all' port forwarding is only allowed for passt"); fwd->mode = FWD_ALL; - memset(fwd->map, 0xff, PORT_EPHEMERAL_MIN / 8); - for (i = 0; i < PORT_EPHEMERAL_MIN; i++) { + for (i = 0; i < NUM_PORTS; i++) { + if (fwd_port_is_ephemeral(i)) + continue; + + bitmap_set(fwd->map, i); if (optname == 't') { ret = tcp_sock_init(c, AF_UNSPEC, NULL, NULL, i); @@ -259,8 +262,9 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg, } while ((p = next_chunk(p, ','))); if (exclude_only) { - for (i = 0; i < PORT_EPHEMERAL_MIN; i++) { - if (bitmap_isset(exclude, i)) + for (i = 0; i < NUM_PORTS; i++) { + if (fwd_port_is_ephemeral(i) || + bitmap_isset(exclude, i)) continue; bitmap_set(fwd->map, i); diff --git a/fwd.c b/fwd.c index 2a0452fa..adf61cb5 100644 --- a/fwd.c +++ b/fwd.c @@ -27,6 +27,23 @@ #include "lineread.h" #include "flow_table.h" +/* Empheral port range: values from RFC 6335 */ +static const uint16_t fwd_ephemeral_min = (1 << 15) + (1 << 14); +static const uint16_t fwd_ephemeral_max = NUM_PORTS - 1; + +/** + * fwd_port_is_ephemeral() - Is port number ephemeral? + * @port: Port number + * + * Return: true if @port is ephemeral, that is may be allocated by the kernel as + * a local port for outgoing connections or datagrams, but should not be + * used for binding services to. + */ +bool fwd_port_is_ephemeral(uint16_t port) +{ + return (port >= fwd_ephemeral_min) && (port <= fwd_ephemeral_max); +} + /* See enum in kernel's include/net/tcp_states.h */ #define UDP_LISTEN 0x07 #define TCP_LISTEN 0x0a diff --git a/fwd.h b/fwd.h index b4aa8d57..42fe57eb 100644 --- a/fwd.h +++ b/fwd.h @@ -12,6 +12,8 @@ struct flowside; /* Number of ports for both TCP and UDP */ #define NUM_PORTS (1U << 16) +bool fwd_port_is_ephemeral(uint16_t port); + enum fwd_ports_mode { FWD_UNSET = 0, FWD_SPEC = 1, diff --git a/util.h b/util.h index 1463c921..c7a59d5d 100644 --- a/util.h +++ b/util.h @@ -95,9 +95,6 @@ #define FD_PROTO(x, proto) \ (IN_INTERVAL(c->proto.fd_min, c->proto.fd_max, (x))) -#define PORT_EPHEMERAL_MIN ((1 << 15) + (1 << 14)) /* RFC 6335 */ -#define PORT_IS_EPHEMERAL(port) ((port) >= PORT_EPHEMERAL_MIN) - #define MAC_ZERO ((uint8_t [ETH_ALEN]){ 0 }) #define MAC_IS_ZERO(addr) (!memcmp((addr), MAC_ZERO, ETH_ALEN)) -- 2.46.0