aboutgitcodebugslistschat
path: root/udp.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2023-11-15 16:25:34 +1100
committerStefano Brivio <sbrivio@redhat.com>2023-11-19 09:08:39 +0100
commit457ff122e33cf6a6e559b073f41c530e42d9c597 (patch)
treed15cc8c40cb50cba4c1d2d7e756c95bc40b41a7a /udp.c
parent4ccdeecb744d48e0c70386d561d34ced860bfacd (diff)
downloadpasst-457ff122e33cf6a6e559b073f41c530e42d9c597.tar
passt-457ff122e33cf6a6e559b073f41c530e42d9c597.tar.gz
passt-457ff122e33cf6a6e559b073f41c530e42d9c597.tar.bz2
passt-457ff122e33cf6a6e559b073f41c530e42d9c597.tar.lz
passt-457ff122e33cf6a6e559b073f41c530e42d9c597.tar.xz
passt-457ff122e33cf6a6e559b073f41c530e42d9c597.tar.zst
passt-457ff122e33cf6a6e559b073f41c530e42d9c597.zip
udp,pasta: Periodically scan for ports to automatically forward
pasta supports automatic port forwarding, where we look for listening sockets in /proc/net (in both namespace and outside) and establish port forwarding to match. For TCP we do this scan both at initial startup, then periodically thereafter. For UDP however, we currently only scan at start. So unlike TCP we won't update forwarding to handle services that start after pasta has begun. There's no particular reason for that, other than that we didn't implement it. So, remove that difference, by scanning for new UDP forwards periodically too. The logic is basically identical to that for TCP, but it needs some changes to handle the mildly different data structures in the UDP case. Link: https://bugs.passt.top/show_bug.cgi?id=45 Link: https://github.com/rootless-containers/rootlesskit/issues/383 Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'udp.c')
-rw-r--r--udp.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/udp.c b/udp.c
index a13efd2..cc1ea9c 100644
--- a/udp.c
+++ b/udp.c
@@ -1187,6 +1187,66 @@ static void udp_timer_one(struct ctx *c, int v6, enum udp_act_type type,
}
/**
+ * udp_port_rebind() - Rebind ports to match forward maps
+ * @c: Execution context
+ * @outbound: True to remap outbound forwards, otherwise inbound
+ *
+ * Must be called in namespace context if @outbound is true.
+ */
+static void udp_port_rebind(struct ctx *c, bool outbound)
+{
+ const uint8_t *fmap
+ = outbound ? c->udp.fwd_out.f.map : c->udp.fwd_in.f.map;
+ const uint8_t *rmap
+ = outbound ? c->udp.fwd_in.f.map : c->udp.fwd_out.f.map;
+ struct udp_splice_port (*socks)[NUM_PORTS]
+ = outbound ? udp_splice_ns : udp_splice_init;
+ unsigned port;
+
+ for (port = 0; port < NUM_PORTS; port++) {
+ if (!bitmap_isset(fmap, port)) {
+ if (socks[V4][port].sock >= 0) {
+ close(socks[V4][port].sock);
+ socks[V4][port].sock = -1;
+ }
+
+ if (socks[V6][port].sock >= 0) {
+ close(socks[V6][port].sock);
+ socks[V6][port].sock = -1;
+ }
+
+ continue;
+ }
+
+ /* Don't loop back our own ports */
+ if (bitmap_isset(rmap, port))
+ continue;
+
+ if ((c->ifi4 && socks[V4][port].sock == -1) ||
+ (c->ifi6 && socks[V6][port].sock == -1))
+ udp_sock_init(c, outbound, AF_UNSPEC, NULL, NULL, port);
+ }
+}
+
+/**
+ * udp_port_rebind_outbound() - Rebind ports in namespace
+ * @arg: Execution context
+ *
+ * Called with NS_CALL()
+ *
+ * Return: 0
+ */
+static int udp_port_rebind_outbound(void *arg)
+{
+ struct ctx *c = (struct ctx *)arg;
+
+ ns_enter(c);
+ udp_port_rebind(c, true);
+
+ return 0;
+}
+
+/**
* udp_timer() - Scan activity bitmaps for ports with associated timed events
* @c: Execution context
* @ts: Timestamp from caller
@@ -1197,6 +1257,20 @@ void udp_timer(struct ctx *c, const struct timespec *ts)
unsigned int i;
long *word, tmp;
+ if (c->mode == MODE_PASTA) {
+ if (c->udp.fwd_out.f.mode == FWD_AUTO) {
+ port_fwd_scan_udp(&c->udp.fwd_out.f, &c->udp.fwd_in.f,
+ &c->tcp.fwd_out);
+ NS_CALL(udp_port_rebind_outbound, c);
+ }
+
+ if (c->udp.fwd_in.f.mode == FWD_AUTO) {
+ port_fwd_scan_udp(&c->udp.fwd_in.f, &c->udp.fwd_out.f,
+ &c->tcp.fwd_in);
+ udp_port_rebind(c, false);
+ }
+ }
+
if (!c->ifi4)
v6 = 1;
v6: