aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--conf.c85
-rw-r--r--conf.h1
-rw-r--r--port_fwd.c179
-rw-r--r--port_fwd.h3
-rw-r--r--tcp.c1
-rw-r--r--util.c65
-rw-r--r--util.h2
8 files changed, 185 insertions, 153 deletions
diff --git a/Makefile b/Makefile
index 941086a..0324fdd 100644
--- a/Makefile
+++ b/Makefile
@@ -45,7 +45,7 @@ FLAGS += -DDUAL_STACK_SOCKETS=$(DUAL_STACK_SOCKETS)
PASST_SRCS = arch.c arp.c checksum.c conf.c dhcp.c dhcpv6.c icmp.c igmp.c \
isolation.c lineread.c log.c mld.c ndp.c netlink.c packet.c passt.c \
- pasta.c pcap.c tap.c tcp.c tcp_splice.c udp.c util.c
+ pasta.c pcap.c port_fwd.c tap.c tcp.c tcp_splice.c udp.c util.c
QRAP_SRCS = qrap.c
SRCS = $(PASST_SRCS) $(QRAP_SRCS)
diff --git a/conf.c b/conf.c
index 4d37af1..d3e6eb2 100644
--- a/conf.c
+++ b/conf.c
@@ -45,72 +45,6 @@
#include "log.h"
/**
- * get_bound_ports() - Get maps of ports with bound sockets
- * @c: Execution context
- * @ns: If set, set bitmaps for ports to tap/ns -- to init otherwise
- * @proto: Protocol number (IPPROTO_TCP or IPPROTO_UDP)
- */
-void get_bound_ports(struct ctx *c, int ns, uint8_t proto)
-{
- uint8_t *udp_map, *udp_excl, *tcp_map, *tcp_excl;
-
- if (ns) {
- udp_map = c->udp.fwd_in.f.map;
- udp_excl = c->udp.fwd_out.f.map;
- tcp_map = c->tcp.fwd_in.map;
- tcp_excl = c->tcp.fwd_out.map;
- } else {
- udp_map = c->udp.fwd_out.f.map;
- udp_excl = c->udp.fwd_in.f.map;
- tcp_map = c->tcp.fwd_out.map;
- tcp_excl = c->tcp.fwd_in.map;
- }
-
- if (proto == IPPROTO_UDP) {
- 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, 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);
- }
-}
-
-/**
- * struct get_bound_ports_ns_arg - Arguments for get_bound_ports_ns()
- * @c: Execution context
- * @proto: Protocol number (IPPROTO_TCP or IPPROTO_UDP)
- */
-struct get_bound_ports_ns_arg {
- struct ctx *c;
- uint8_t proto;
-};
-
-/**
- * get_bound_ports_ns() - Get maps of ports in namespace with bound sockets
- * @arg: See struct get_bound_ports_ns_arg
- *
- * Return: 0
- */
-static int get_bound_ports_ns(void *arg)
-{
- struct get_bound_ports_ns_arg *a = (struct get_bound_ports_ns_arg *)arg;
- struct ctx *c = a->c;
-
- if (!c->pasta_netns_fd)
- return 0;
-
- ns_enter(c);
- get_bound_ports(c, 1, a->proto);
-
- return 0;
-}
-
-/**
* next_chunk - Return the next piece of a string delimited by a character
* @s: String to search
* @c: Delimiter character
@@ -1235,7 +1169,6 @@ void conf(struct ctx *c, int argc, char **argv)
{"no-copy-addrs", no_argument, NULL, 19 },
{ 0 },
};
- struct get_bound_ports_ns_arg ns_ports_arg = { .c = c };
char userns[PATH_MAX] = { 0 }, netns[PATH_MAX] = { 0 };
bool copy_addrs_opt = false, copy_routes_opt = false;
enum port_fwd_mode fwd_default = FWD_NONE;
@@ -1814,23 +1747,7 @@ void conf(struct ctx *c, int argc, char **argv)
if (!c->udp.fwd_out.f.mode)
c->udp.fwd_out.f.mode = fwd_default;
- 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 (c->tcp.fwd_in.mode == FWD_AUTO) {
- ns_ports_arg.proto = IPPROTO_TCP;
- NS_CALL(get_bound_ports_ns, &ns_ports_arg);
- }
- if (c->udp.fwd_in.f.mode == FWD_AUTO) {
- ns_ports_arg.proto = IPPROTO_UDP;
- NS_CALL(get_bound_ports_ns, &ns_ports_arg);
- }
- if (c->tcp.fwd_out.mode == FWD_AUTO)
- get_bound_ports(c, 0, IPPROTO_TCP);
- if (c->udp.fwd_out.f.mode == FWD_AUTO)
- get_bound_ports(c, 0, IPPROTO_UDP);
+ port_fwd_init(c);
if (!c->quiet)
conf_print(c);
diff --git a/conf.h b/conf.h
index ce7b8c5..9d2143d 100644
--- a/conf.h
+++ b/conf.h
@@ -7,6 +7,5 @@
#define CONF_H
void conf(struct ctx *c, int argc, char **argv);
-void get_bound_ports(struct ctx *c, int ns, uint8_t proto);
#endif /* CONF_H */
diff --git a/port_fwd.c b/port_fwd.c
new file mode 100644
index 0000000..136a450
--- /dev/null
+++ b/port_fwd.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/* PASST - Plug A Simple Socket Transport
+ * for qemu/UNIX domain socket mode
+ *
+ * PASTA - Pack A Subtle Tap Abstraction
+ * for network namespace/tap device mode
+ *
+ * port_fwd.c - Port forwarding helpers
+ *
+ * Copyright Red Hat
+ * Author: Stefano Brivio <sbrivio@redhat.com>
+ * Author: David Gibson <david@gibson.dropbear.id.au>
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
+
+#include "util.h"
+#include "port_fwd.h"
+#include "passt.h"
+#include "lineread.h"
+
+/**
+ * procfs_scan_listen() - Set bits for listening TCP or UDP sockets from procfs
+ * @proto: IPPROTO_TCP or IPPROTO_UDP
+ * @ip_version: IP version, V4 or V6
+ * @ns: Use saved file descriptors for namespace if set
+ * @map: Bitmap where numbers of ports in listening state will be set
+ * @exclude: Bitmap of ports to exclude from setting (and clear)
+ *
+ * #syscalls:pasta lseek
+ * #syscalls:pasta ppc64le:_llseek ppc64:_llseek armv6l:_llseek armv7l:_llseek
+ */
+static void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version,
+ int ns, uint8_t *map, const uint8_t *exclude)
+{
+ char *path, *line;
+ struct lineread lr;
+ unsigned long port;
+ unsigned int state;
+ int *fd;
+
+ if (proto == IPPROTO_TCP) {
+ fd = &c->proc_net_tcp[ip_version][ns];
+ if (ip_version == V4)
+ path = "/proc/net/tcp";
+ else
+ path = "/proc/net/tcp6";
+ } else {
+ fd = &c->proc_net_udp[ip_version][ns];
+ if (ip_version == V4)
+ path = "/proc/net/udp";
+ else
+ path = "/proc/net/udp6";
+ }
+
+ if (*fd != -1) {
+ if (lseek(*fd, 0, SEEK_SET)) {
+ warn("lseek() failed on %s: %s", path, strerror(errno));
+ return;
+ }
+ } else if ((*fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
+ return;
+ }
+
+ lineread_init(&lr, *fd);
+ lineread_get(&lr, &line); /* throw away header */
+ while (lineread_get(&lr, &line) > 0) {
+ /* NOLINTNEXTLINE(cert-err34-c): != 2 if conversion fails */
+ if (sscanf(line, "%*u: %*x:%lx %*x:%*x %x", &port, &state) != 2)
+ continue;
+
+ /* See enum in kernel's include/net/tcp_states.h */
+ if ((proto == IPPROTO_TCP && state != 0x0a) ||
+ (proto == IPPROTO_UDP && state != 0x07))
+ continue;
+
+ if (bitmap_isset(exclude, port))
+ bitmap_clear(map, port);
+ else
+ bitmap_set(map, port);
+ }
+}
+
+/**
+ * get_bound_ports() - Get maps of ports with bound sockets
+ * @c: Execution context
+ * @ns: If set, set bitmaps for ports to tap/ns -- to init otherwise
+ * @proto: Protocol number (IPPROTO_TCP or IPPROTO_UDP)
+ */
+void get_bound_ports(struct ctx *c, int ns, uint8_t proto)
+{
+ uint8_t *udp_map, *udp_excl, *tcp_map, *tcp_excl;
+
+ if (ns) {
+ udp_map = c->udp.fwd_in.f.map;
+ udp_excl = c->udp.fwd_out.f.map;
+ tcp_map = c->tcp.fwd_in.map;
+ tcp_excl = c->tcp.fwd_out.map;
+ } else {
+ udp_map = c->udp.fwd_out.f.map;
+ udp_excl = c->udp.fwd_in.f.map;
+ tcp_map = c->tcp.fwd_out.map;
+ tcp_excl = c->tcp.fwd_in.map;
+ }
+
+ if (proto == IPPROTO_UDP) {
+ 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, 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);
+ }
+}
+
+/**
+ * struct get_bound_ports_ns_arg - Arguments for get_bound_ports_ns()
+ * @c: Execution context
+ * @proto: Protocol number (IPPROTO_TCP or IPPROTO_UDP)
+ */
+struct get_bound_ports_ns_arg {
+ struct ctx *c;
+ uint8_t proto;
+};
+
+/**
+ * get_bound_ports_ns() - Get maps of ports in namespace with bound sockets
+ * @arg: See struct get_bound_ports_ns_arg
+ *
+ * Return: 0
+ */
+static int get_bound_ports_ns(void *arg)
+{
+ struct get_bound_ports_ns_arg *a = (struct get_bound_ports_ns_arg *)arg;
+ struct ctx *c = a->c;
+
+ if (!c->pasta_netns_fd)
+ return 0;
+
+ ns_enter(c);
+ get_bound_ports(c, 1, a->proto);
+
+ return 0;
+}
+
+/**
+ * port_fwd_init() - Initial setup for port forwarding
+ * @c: Execution context
+ */
+void port_fwd_init(struct ctx *c)
+{
+ struct get_bound_ports_ns_arg ns_ports_arg = { .c = c };
+
+ 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 (c->tcp.fwd_in.mode == FWD_AUTO) {
+ ns_ports_arg.proto = IPPROTO_TCP;
+ NS_CALL(get_bound_ports_ns, &ns_ports_arg);
+ }
+ if (c->udp.fwd_in.f.mode == FWD_AUTO) {
+ ns_ports_arg.proto = IPPROTO_UDP;
+ NS_CALL(get_bound_ports_ns, &ns_ports_arg);
+ }
+ if (c->tcp.fwd_out.mode == FWD_AUTO)
+ get_bound_ports(c, 0, IPPROTO_TCP);
+ if (c->udp.fwd_out.f.mode == FWD_AUTO)
+ get_bound_ports(c, 0, IPPROTO_UDP);
+}
diff --git a/port_fwd.h b/port_fwd.h
index 6ed3f14..ad8ed1f 100644
--- a/port_fwd.h
+++ b/port_fwd.h
@@ -31,4 +31,7 @@ struct port_fwd {
in_port_t delta[NUM_PORTS];
};
+void get_bound_ports(struct ctx *c, int ns, uint8_t proto);
+void port_fwd_init(struct ctx *c);
+
#endif /* PORT_FWD_H */
diff --git a/tcp.c b/tcp.c
index 945023c..c6cc020 100644
--- a/tcp.c
+++ b/tcp.c
@@ -298,7 +298,6 @@
#include "tap.h"
#include "siphash.h"
#include "pcap.h"
-#include "conf.h"
#include "tcp_splice.h"
#include "log.h"
#include "inany.h"
diff --git a/util.c b/util.c
index 1f35382..a8f3b35 100644
--- a/util.c
+++ b/util.c
@@ -28,7 +28,6 @@
#include "util.h"
#include "passt.h"
#include "packet.h"
-#include "lineread.h"
#include "log.h"
#define IPV6_NH_OPT(nh) \
@@ -326,69 +325,7 @@ int bitmap_isset(const uint8_t *map, int bit)
return !!(*word & BITMAP_BIT(bit));
}
-/**
- * procfs_scan_listen() - Set bits for listening TCP or UDP sockets from procfs
- * @proto: IPPROTO_TCP or IPPROTO_UDP
- * @ip_version: IP version, V4 or V6
- * @ns: Use saved file descriptors for namespace if set
- * @map: Bitmap where numbers of ports in listening state will be set
- * @exclude: Bitmap of ports to exclude from setting (and clear)
- *
- * #syscalls:pasta lseek
- * #syscalls:pasta ppc64le:_llseek ppc64:_llseek armv6l:_llseek armv7l:_llseek
- */
-void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
- uint8_t *map, const uint8_t *exclude)
-{
- char *path, *line;
- struct lineread lr;
- unsigned long port;
- unsigned int state;
- int *fd;
-
- if (proto == IPPROTO_TCP) {
- fd = &c->proc_net_tcp[ip_version][ns];
- if (ip_version == V4)
- path = "/proc/net/tcp";
- else
- path = "/proc/net/tcp6";
- } else {
- fd = &c->proc_net_udp[ip_version][ns];
- if (ip_version == V4)
- path = "/proc/net/udp";
- else
- path = "/proc/net/udp6";
- }
-
- if (*fd != -1) {
- if (lseek(*fd, 0, SEEK_SET)) {
- warn("lseek() failed on %s: %s", path, strerror(errno));
- return;
- }
- } else if ((*fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
- return;
- }
-
- lineread_init(&lr, *fd);
- lineread_get(&lr, &line); /* throw away header */
- while (lineread_get(&lr, &line) > 0) {
- /* NOLINTNEXTLINE(cert-err34-c): != 2 if conversion fails */
- if (sscanf(line, "%*u: %*x:%lx %*x:%*x %x", &port, &state) != 2)
- continue;
-
- /* See enum in kernel's include/net/tcp_states.h */
- if ((proto == IPPROTO_TCP && state != 0x0a) ||
- (proto == IPPROTO_UDP && state != 0x07))
- continue;
-
- if (bitmap_isset(exclude, port))
- bitmap_clear(map, port);
- else
- bitmap_set(map, port);
- }
-}
-
-/**
+/*
* ns_enter() - Enter configured user (unless already joined) and network ns
* @c: Execution context
*
diff --git a/util.h b/util.h
index 60d6872..9effc54 100644
--- a/util.h
+++ b/util.h
@@ -217,8 +217,6 @@ void bitmap_set(uint8_t *map, int bit);
void bitmap_clear(uint8_t *map, int bit);
int bitmap_isset(const uint8_t *map, int bit);
char *line_read(char *buf, size_t len, int fd);
-void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
- uint8_t *map, const uint8_t *exclude);
void ns_enter(const struct ctx *c);
bool ns_is_init(void);
void write_pidfile(int fd, pid_t pid);