aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--conf.c73
-rw-r--r--passt.h1
-rw-r--r--port_fwd.h19
-rw-r--r--tcp.c12
-rw-r--r--tcp.h12
-rw-r--r--udp.h12
7 files changed, 76 insertions, 55 deletions
diff --git a/Makefile b/Makefile
index 4ccca67..42bc0ac 100644
--- a/Makefile
+++ b/Makefile
@@ -41,7 +41,7 @@ MANPAGES = passt.1 pasta.1 qrap.1
PASST_HEADERS = arch.h arp.h checksum.h conf.h dhcp.h dhcpv6.h icmp.h \
isolation.h lineread.h ndp.h netlink.h packet.h passt.h pasta.h \
- pcap.h siphash.h tap.h tcp.h tcp_splice.h udp.h util.h
+ pcap.h port_fwd.h siphash.h tap.h tcp.h tcp_splice.h udp.h util.h
HEADERS = $(PASST_HEADERS) seccomp.h
# On gcc 11.2, with -O2 and -flto, tcp_hash() and siphash_20b(), if inlined,
diff --git a/conf.c b/conf.c
index 7ecfa1e..8b1437d 100644
--- a/conf.c
+++ b/conf.c
@@ -64,14 +64,14 @@ void get_bound_ports(struct ctx *c, int ns, uint8_t proto)
}
if (proto == IPPROTO_UDP) {
- memset(udp_map, 0, USHRT_MAX / 8);
+ memset(udp_map, 0, PORT_BITMAP_SIZE);
procfs_scan_listen(c, IPPROTO_UDP, V4, ns, udp_map, udp_excl);
procfs_scan_listen(c, IPPROTO_UDP, V6, ns, udp_map, udp_excl);
procfs_scan_listen(c, IPPROTO_TCP, V4, ns, udp_map, udp_excl);
procfs_scan_listen(c, IPPROTO_TCP, V6, ns, udp_map, udp_excl);
} else if (proto == IPPROTO_TCP) {
- memset(tcp_map, 0, USHRT_MAX / 8);
+ memset(tcp_map, 0, PORT_BITMAP_SIZE);
procfs_scan_listen(c, IPPROTO_TCP, V4, ns, tcp_map, tcp_excl);
procfs_scan_listen(c, IPPROTO_TCP, V6, ns, tcp_map, tcp_excl);
}
@@ -106,31 +106,25 @@ static int get_bound_ports_ns(void *arg)
return 0;
}
-enum conf_port_type {
- PORT_SPEC = 1,
- PORT_NONE,
- PORT_AUTO,
- PORT_ALL,
-};
-
/**
* conf_ports() - Parse port configuration options, initialise UDP/TCP sockets
* @c: Execution context
* @optname: Short option name, t, T, u, or U
* @optarg: Option argument (port specification)
- * @set: Pointer to @conf_port_type to be set (port binding type)
+ * @set: Pointer to @port_fwd_mode to be set (port forwarding mode)
*
* Return: -EINVAL on parsing error, 0 otherwise
*/
static int conf_ports(struct ctx *c, char optname, const char *optarg,
- enum conf_port_type *set)
+ enum port_fwd_mode *set)
{
int start_src, end_src, start_dst, end_dst, exclude_only = 1, i, port;
char addr_buf[sizeof(struct in6_addr)] = { 0 }, *addr = addr_buf;
- uint8_t *map, exclude[DIV_ROUND_UP(USHRT_MAX, 8)] = { 0 };
void (*remap)(in_port_t port, in_port_t delta);
+ uint8_t exclude[PORT_BITMAP_SIZE] = { 0 };
char buf[BUFSIZ], *sep, *spec, *p;
sa_family_t af = AF_UNSPEC;
+ uint8_t *map;
if (optname == 't') {
map = c->tcp.port_to_tap;
@@ -151,14 +145,14 @@ static int conf_ports(struct ctx *c, char optname, const char *optarg,
if (!strcmp(optarg, "none")) {
if (*set)
return -EINVAL;
- *set = PORT_NONE;
+ *set = FWD_NONE;
return 0;
}
if (!strcmp(optarg, "auto")) {
if (*set || c->mode != MODE_PASTA)
return -EINVAL;
- *set = PORT_AUTO;
+ *set = FWD_AUTO;
return 0;
}
@@ -167,7 +161,7 @@ static int conf_ports(struct ctx *c, char optname, const char *optarg,
if (*set || c->mode != MODE_PASST)
return -EINVAL;
- *set = PORT_ALL;
+ *set = FWD_ALL;
memset(map, 0xff, PORT_EPHEMERAL_MIN / 8);
for (i = 0; i < PORT_EPHEMERAL_MIN; i++) {
@@ -180,10 +174,10 @@ static int conf_ports(struct ctx *c, char optname, const char *optarg,
return 0;
}
- if (*set > PORT_SPEC)
+ if (*set > FWD_SPEC)
return -EINVAL;
- *set = PORT_SPEC;
+ *set = FWD_SPEC;
strncpy(buf, optarg, sizeof(buf) - 1);
@@ -1088,8 +1082,6 @@ void conf(struct ctx *c, int argc, char **argv)
};
struct get_bound_ports_ns_arg ns_ports_arg = { .c = c };
char userns[PATH_MAX] = { 0 }, netns[PATH_MAX] = { 0 };
- enum conf_port_type tcp_tap = 0, tcp_init = 0;
- enum conf_port_type udp_tap = 0, udp_init = 0;
bool v4_only = false, v6_only = false;
struct in6_addr *dns6 = c->ip6.dns;
struct fqdn *dnss = c->dns_search;
@@ -1103,6 +1095,9 @@ void conf(struct ctx *c, int argc, char **argv)
if (c->mode == MODE_PASTA)
c->no_dhcp_dns = c->no_dhcp_dns_search = 1;
+ c->tcp.fwd_mode_in = c->tcp.fwd_mode_out = 0;
+ c->udp.fwd_mode_in = c->udp.fwd_mode_out = 0;
+
do {
const char *optstring;
@@ -1553,7 +1548,7 @@ void conf(struct ctx *c, int argc, char **argv)
/* Now we can process port configuration options */
optind = 1;
do {
- enum conf_port_type *set = NULL;
+ enum port_fwd_mode *fwd = NULL;
const char *optstring;
if (c->mode == MODE_PASST)
@@ -1568,15 +1563,15 @@ void conf(struct ctx *c, int argc, char **argv)
case 'T':
case 'U':
if (name == 't')
- set = &tcp_tap;
+ fwd = &c->tcp.fwd_mode_in;
else if (name == 'T')
- set = &tcp_init;
+ fwd = &c->tcp.fwd_mode_out;
else if (name == 'u')
- set = &udp_tap;
+ fwd = &c->udp.fwd_mode_in;
else if (name == 'U')
- set = &udp_init;
+ fwd = &c->udp.fwd_mode_out;
- if (!optarg || conf_ports(c, name, optarg, set))
+ if (!optarg || conf_ports(c, name, optarg, fwd))
usage(argv[0]);
break;
@@ -1605,33 +1600,39 @@ void conf(struct ctx *c, int argc, char **argv)
if_indextoname(c->ifi6, c->pasta_ifn);
}
- c->tcp.ns_detect_ports = c->udp.ns_detect_ports = 0;
- c->tcp.init_detect_ports = c->udp.init_detect_ports = 0;
-
if (c->mode == MODE_PASTA) {
c->proc_net_tcp[V4][0] = c->proc_net_tcp[V4][1] = -1;
c->proc_net_tcp[V6][0] = c->proc_net_tcp[V6][1] = -1;
c->proc_net_udp[V4][0] = c->proc_net_udp[V4][1] = -1;
c->proc_net_udp[V6][0] = c->proc_net_udp[V6][1] = -1;
- if (!tcp_tap || tcp_tap == PORT_AUTO) {
- c->tcp.ns_detect_ports = 1;
+ if (!c->tcp.fwd_mode_in || c->tcp.fwd_mode_in == FWD_AUTO) {
+ c->tcp.fwd_mode_in = FWD_AUTO;
ns_ports_arg.proto = IPPROTO_TCP;
NS_CALL(get_bound_ports_ns, &ns_ports_arg);
}
- if (!udp_tap || udp_tap == PORT_AUTO) {
- c->udp.ns_detect_ports = 1;
+ if (!c->udp.fwd_mode_in || c->udp.fwd_mode_in == FWD_AUTO) {
+ c->udp.fwd_mode_in = FWD_AUTO;
ns_ports_arg.proto = IPPROTO_UDP;
NS_CALL(get_bound_ports_ns, &ns_ports_arg);
}
- if (!tcp_init || tcp_init == PORT_AUTO) {
- c->tcp.init_detect_ports = 1;
+ if (!c->tcp.fwd_mode_out || c->tcp.fwd_mode_out == FWD_AUTO) {
+ c->tcp.fwd_mode_out = FWD_AUTO;
get_bound_ports(c, 0, IPPROTO_TCP);
}
- if (!udp_init || udp_init == PORT_AUTO) {
- c->udp.init_detect_ports = 1;
+ if (!c->udp.fwd_mode_out || c->udp.fwd_mode_out == FWD_AUTO) {
+ c->udp.fwd_mode_out = FWD_AUTO;
get_bound_ports(c, 0, IPPROTO_UDP);
}
+ } else {
+ if (!c->tcp.fwd_mode_in)
+ c->tcp.fwd_mode_in = FWD_NONE;
+ if (!c->tcp.fwd_mode_out)
+ c->tcp.fwd_mode_out= FWD_NONE;
+ if (!c->udp.fwd_mode_in)
+ c->udp.fwd_mode_in = FWD_NONE;
+ if (!c->udp.fwd_mode_out)
+ c->udp.fwd_mode_out = FWD_NONE;
}
if (!c->quiet)
diff --git a/passt.h b/passt.h
index 8c8d710..48e1096 100644
--- a/passt.h
+++ b/passt.h
@@ -33,6 +33,7 @@ union epoll_ref;
#include "packet.h"
#include "icmp.h"
+#include "port_fwd.h"
#include "tcp.h"
#include "udp.h"
diff --git a/port_fwd.h b/port_fwd.h
new file mode 100644
index 0000000..b938022
--- /dev/null
+++ b/port_fwd.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: AGPL-3.0-or-later
+ * Copyright Red Hat
+ * Author: Stefano Brivio <sbrivio@redhat.com>
+ * Author: David Gibson <david@gibson.dropbear.id.au>
+ */
+
+#ifndef PORT_FWD_H
+#define PORT_FWD_H
+
+enum port_fwd_mode {
+ FWD_SPEC = 1,
+ FWD_NONE,
+ FWD_AUTO,
+ FWD_ALL,
+};
+
+#define PORT_BITMAP_SIZE DIV_ROUND_UP(USHRT_MAX, 8)
+
+#endif /* PORT_FWD_H */
diff --git a/tcp.c b/tcp.c
index ec8c32e..0bdef7f 100644
--- a/tcp.c
+++ b/tcp.c
@@ -3133,7 +3133,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af,
else
s = -1;
- if (c->tcp.init_detect_ports)
+ if (c->tcp.fwd_mode_in == FWD_AUTO)
tcp_sock_init_ext[port][V4] = s;
}
@@ -3148,7 +3148,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af,
else
s = -1;
- if (c->tcp.ns_detect_ports) {
+ if (c->tcp.fwd_mode_out == FWD_AUTO) {
if (ns)
tcp_sock_ns[port][V4] = s;
else
@@ -3174,7 +3174,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af,
else
s = -1;
- if (c->tcp.init_detect_ports)
+ if (c->tcp.fwd_mode_in == FWD_AUTO)
tcp_sock_init_ext[port][V6] = s;
}
@@ -3189,7 +3189,7 @@ void tcp_sock_init(const struct ctx *c, int ns, sa_family_t af,
else
s = -1;
- if (c->tcp.ns_detect_ports) {
+ if (c->tcp.fwd_mode_out == FWD_AUTO) {
if (ns)
tcp_sock_ns[port][V6] = s;
else
@@ -3489,14 +3489,14 @@ void tcp_timer(struct ctx *c, const struct timespec *ts)
struct tcp_port_detect_arg detect_arg = { c, 0 };
struct tcp_port_rebind_arg rebind_arg = { c, 0 };
- if (c->tcp.init_detect_ports) {
+ if (c->tcp.fwd_mode_in == FWD_AUTO) {
detect_arg.detect_in_ns = 0;
tcp_port_detect(&detect_arg);
rebind_arg.bind_in_ns = 1;
NS_CALL(tcp_port_rebind, &rebind_arg);
}
- if (c->tcp.ns_detect_ports) {
+ if (c->tcp.fwd_mode_out == FWD_AUTO) {
detect_arg.detect_in_ns = 1;
NS_CALL(tcp_port_detect, &detect_arg);
rebind_arg.bind_in_ns = 0;
diff --git a/tcp.h b/tcp.h
index 6431b75..ed797d9 100644
--- a/tcp.h
+++ b/tcp.h
@@ -58,9 +58,9 @@ union tcp_epoll_ref {
* @conn_count: Count of connections (not spliced) in connection table
* @splice_conn_count: Count of spliced connections in connection table
* @port_to_tap: Ports bound host-side, packets to tap or spliced
- * @init_detect_ports: If set, periodically detect ports bound in init
+ * @fwd_mode_in: Port forwarding mode for inbound packets
* @port_to_init: Ports bound namespace-side, spliced to init
- * @ns_detect_ports: If set, periodically detect ports bound in namespace
+ * @fwd_mode_out: Port forwarding mode for outbound packets
* @timer_run: Timestamp of most recent timer run
* @kernel_snd_wnd: Kernel reports sending window (with commit 8f7baad7f035)
* @pipe_size: Size of pipes for spliced connections
@@ -69,10 +69,10 @@ struct tcp_ctx {
uint64_t hash_secret[2];
int conn_count;
int splice_conn_count;
- uint8_t port_to_tap [DIV_ROUND_UP(USHRT_MAX, 8)];
- int init_detect_ports;
- uint8_t port_to_init [DIV_ROUND_UP(USHRT_MAX, 8)];
- int ns_detect_ports;
+ uint8_t port_to_tap [PORT_BITMAP_SIZE];
+ enum port_fwd_mode fwd_mode_in;
+ uint8_t port_to_init [PORT_BITMAP_SIZE];
+ enum port_fwd_mode fwd_mode_out;
struct timespec timer_run;
#ifdef HAS_SND_WND
int kernel_snd_wnd;
diff --git a/udp.h b/udp.h
index 8f82842..706306c 100644
--- a/udp.h
+++ b/udp.h
@@ -47,16 +47,16 @@ union udp_epoll_ref {
/**
* struct udp_ctx - Execution context for UDP
* @port_to_tap: Ports bound host-side, data to tap or ns L4 socket
- * @init_detect_ports: If set, periodically detect ports bound in init (TODO)
+ * @fwd_mode_in: Port forwarding mode for inbound packets
* @port_to_init: Ports bound namespace-side, data to init L4 socket
- * @ns_detect_ports: If set, periodically detect ports bound in namespace
+ * @fwd_mode_out: Port forwarding mode for outbound packets
* @timer_run: Timestamp of most recent timer run
*/
struct udp_ctx {
- uint8_t port_to_tap [DIV_ROUND_UP(USHRT_MAX, 8)];
- int init_detect_ports;
- uint8_t port_to_init [DIV_ROUND_UP(USHRT_MAX, 8)];
- int ns_detect_ports;
+ uint8_t port_to_tap [PORT_BITMAP_SIZE];
+ enum port_fwd_mode fwd_mode_in;
+ uint8_t port_to_init [PORT_BITMAP_SIZE];
+ enum port_fwd_mode fwd_mode_out;
struct timespec timer_run;
};