port_fwd: Better parameterise procfs_scan_listen()

procfs_scan_listen() does some slightly clunky logic to deduce the fd it
wants to use, the path it wants to open and the state it's looking for
based on parameters for protocol, IP version and whether we're in the
namespace.

However, the caller already has to make choices based on similar parameters
so it can just pass in the things that procfs_scan_listen() needs directly.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2023-11-03 13:22:57 +11:00 committed by Stefano Brivio
parent e90f2770ae
commit 17d40d1cb5

View file

@ -23,39 +23,28 @@
#include "passt.h" #include "passt.h"
#include "lineread.h" #include "lineread.h"
/* See enum in kernel's include/net/tcp_states.h */
#define UDP_LISTEN 0x07
#define TCP_LISTEN 0x0a
/** /**
* procfs_scan_listen() - Set bits for listening TCP or UDP sockets from procfs * procfs_scan_listen() - Set bits for listening TCP or UDP sockets from procfs
* @proto: IPPROTO_TCP or IPPROTO_UDP * @fd: Pointer to fd for relevant /proc/net file
* @ip_version: IP version, V4 or V6 * @path: Path to /proc/net file to open (if fd is -1)
* @ns: Use saved file descriptors for namespace if set * @lstate: Code for listening state to scan for
* @map: Bitmap where numbers of ports in listening state will be set * @map: Bitmap where numbers of ports in listening state will be set
* @exclude: Bitmap of ports to exclude from setting (and clear) * @exclude: Bitmap of ports to exclude from setting (and clear)
* *
* #syscalls:pasta lseek * #syscalls:pasta lseek
* #syscalls:pasta ppc64le:_llseek ppc64:_llseek armv6l:_llseek armv7l:_llseek * #syscalls:pasta ppc64le:_llseek ppc64:_llseek armv6l:_llseek armv7l:_llseek
*/ */
static void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, static void procfs_scan_listen(int *fd, const char *path, unsigned int lstate,
int ns, uint8_t *map, const uint8_t *exclude) uint8_t *map, const uint8_t *exclude)
{ {
char *path, *line;
struct lineread lr; struct lineread lr;
unsigned long port; unsigned long port;
unsigned int state; unsigned int state;
int *fd; char *line;
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 (*fd != -1) {
if (lseek(*fd, 0, SEEK_SET)) { if (lseek(*fd, 0, SEEK_SET)) {
@ -73,9 +62,7 @@ static void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version,
if (sscanf(line, "%*u: %*x:%lx %*x:%*x %x", &port, &state) != 2) if (sscanf(line, "%*u: %*x:%lx %*x:%*x %x", &port, &state) != 2)
continue; continue;
/* See enum in kernel's include/net/tcp_states.h */ if (state != lstate)
if ((proto == IPPROTO_TCP && state != 0x0a) ||
(proto == IPPROTO_UDP && state != 0x07))
continue; continue;
if (bitmap_isset(exclude, port)) if (bitmap_isset(exclude, port))
@ -109,15 +96,21 @@ void get_bound_ports(struct ctx *c, int ns, uint8_t proto)
if (proto == IPPROTO_UDP) { if (proto == IPPROTO_UDP) {
memset(udp_map, 0, PORT_BITMAP_SIZE); memset(udp_map, 0, PORT_BITMAP_SIZE);
procfs_scan_listen(c, IPPROTO_UDP, V4, ns, udp_map, udp_excl); procfs_scan_listen(&c->proc_net_udp[V4][ns], "/proc/net/udp",
procfs_scan_listen(c, IPPROTO_UDP, V6, ns, udp_map, udp_excl); UDP_LISTEN, udp_map, udp_excl);
procfs_scan_listen(&c->proc_net_udp[V6][ns], "/proc/net/udp6",
UDP_LISTEN, udp_map, udp_excl);
procfs_scan_listen(c, IPPROTO_TCP, V4, ns, udp_map, udp_excl); procfs_scan_listen(&c->proc_net_tcp[V4][ns], "/proc/net/tcp",
procfs_scan_listen(c, IPPROTO_TCP, V6, ns, udp_map, udp_excl); TCP_LISTEN, udp_map, udp_excl);
procfs_scan_listen(&c->proc_net_tcp[V6][ns], "/proc/net/tcp6",
TCP_LISTEN, udp_map, udp_excl);
} else if (proto == IPPROTO_TCP) { } else if (proto == IPPROTO_TCP) {
memset(tcp_map, 0, PORT_BITMAP_SIZE); memset(tcp_map, 0, PORT_BITMAP_SIZE);
procfs_scan_listen(c, IPPROTO_TCP, V4, ns, tcp_map, tcp_excl); procfs_scan_listen(&c->proc_net_tcp[V4][ns], "/proc/net/tcp",
procfs_scan_listen(c, IPPROTO_TCP, V6, ns, tcp_map, tcp_excl); TCP_LISTEN, tcp_map, tcp_excl);
procfs_scan_listen(&c->proc_net_tcp[V6][ns], "/proc/net/tcp6",
TCP_LISTEN, tcp_map, tcp_excl);
} }
} }