aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--passt.13
-rw-r--r--udp.c74
2 files changed, 75 insertions, 2 deletions
diff --git a/passt.1 b/passt.1
index 1ad4276..efd6bb7 100644
--- a/passt.1
+++ b/passt.1
@@ -496,8 +496,7 @@ Default is \fBauto\fR.
.BR \-u ", " \-\-udp-ports " " \fIspec
Configure UDP port forwarding to namespace. \fIspec\fR is as described for TCP
above, and the list of ports is derived from listening sockets reported by
-\fI/proc/net/udp\fR and \fI/proc/net/udp6\fR, see \fBproc\fR(5),
-when \fBpasta\fR starts (not periodically).
+\fI/proc/net/udp\fR and \fI/proc/net/udp6\fR, see \fBproc\fR(5).
Note: unless overridden, UDP ports with numbers corresponding to forwarded TCP
port numbers are forwarded too, without, however, any port translation.
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: