From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202602 header.b=EzMFU+K4; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 9DF4C5A0625 for ; Mon, 23 Mar 2026 09:33:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1774254767; bh=MVGShlZA9N5ZsOyQx4Z4Fz4Tp5ulFrip+qiF4a4P9Zs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EzMFU+K4JbRUhTBhhynRl9kueyLRDaF5iGeL1DiRBgm9U+kcfaRYLamGVwngYHZTK F7FyskUBVMpQ/XZJLbXlowUm6Ewgl9VpIY6PuDzmV9gCh3Zf2ywG4r/2uFZKvnB/NX LGxPLU9B/ta3X8hTpCKllSVOoBZKfk+j59t/Fv0BPQ0j5t3N38kow1C/BB/B6a8JsK Qj915VR8bvr6NAu83CbVPnCCaDUcglBkn/sPlDrXVGf0VkEyyMuZiECW8IPlyqlewj qKhVgWVkkySylIzjatBSEGU0U3lvqB88CYg2wrII6znD4mBSettGy0az/1NDH7r0JR 8MuyOtKJdnj1A== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4ffRHz69pjz4wSZ; Mon, 23 Mar 2026 19:32:47 +1100 (AEDT) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH v3 24/25] pesto, conf: Parse, send and receive new rules Date: Mon, 23 Mar 2026 18:37:31 +1100 Message-ID: <20260323073732.3158468-25-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260323073732.3158468-1-david@gibson.dropbear.id.au> References: <20260323073732.3158468-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: EJHB52OUFXMYANCEOLMZ2C5HGYCPSRM3 X-Message-ID-Hash: EJHB52OUFXMYANCEOLMZ2C5HGYCPSRM3 X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Stefano Brivio This adds parsing of options using conf_ports() in pesto, builds rules, and sends them one by one to passt, which now receives them and stores then in a different table. We debug print the rules in the "pending" table but don't yet attempt to activate them. Signed-off-by: Stefano Brivio Message-ID: <20260322141843.4095972-3-sbrivio@redhat.com> [dwg: Rebased on changes to my earlier patches] [dwg: Properly preserve the rule flags when they're read in] [dwg: Removed the non-working logic to activate the new table] Signed-off-by: David Gibson --- Makefile | 2 +- conf.c | 60 ++++++++++++++++++++++++++++++++++++-- fwd.c | 9 +++++- passt.h | 2 ++ pesto.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- pif.h | 2 ++ 6 files changed, 157 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index b6b6a823..24235702 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ SRCS = $(PASST_SRCS) $(QRAP_SRCS) $(PASST_REPAIR_SRCS) $(PESTO_SRCS) MANPAGES = passt.1 pasta.1 pesto.1 qrap.1 passt-repair.1 PESTO_HEADERS = common.h fwd_rule.h inany.h ip.h pesto.h serialise.h ports.h \ - lineread.h + lineread.h pif.h PASST_HEADERS = arch.h arp.h checksum.h conf.h dhcp.h dhcpv6.h epoll_ctl.h \ flow.h fwd.h flow_table.h icmp.h icmp_flow.h iov.h isolation.h \ lineread.h log.h migrate.h ndp.h netlink.h packet.h passt.h pasta.h \ diff --git a/conf.c b/conf.c index 7f624db6..b4c2074e 100644 --- a/conf.c +++ b/conf.c @@ -2046,6 +2046,50 @@ static int conf_send_rules(const struct ctx *c, int fd) return 0; } +/** + * conf_send_rules() - Send current forwarding rules to dynamic update client (pesto) + * @c: Execution context + * @fd: Socket to the client + * + * Return: 0 on success, -1 on failure + */ +static int conf_recv_rules(const struct ctx *c, int fd) +{ + while (1) { + struct fwd_table *fwd; + struct fwd_rule r; + uint32_t count; + uint8_t pif; + unsigned i; + + if (read_u8(fd, &pif)) + return -1; + + if (pif == PIF_NONE) + break; + + fwd = c->fwd_pending[pif]; + if (!fwd) { + err("Received rules for non-existent table"); + return -1; + } + + /* Clear pending table */ + memset(fwd, 0, sizeof(*fwd)); + + if (read_u32(fd, &count)) + return -1; + + for (i = 0; i < count; i++) { + fwd_rule_read(fd, &r); + fwd_rule_add(fwd, r.proto, r.flags, &r.addr, NULL, + r.first, r.last, r.to); + } + } + + return 0; +} + /** * conf_listen_handler() - Handle events on configuration listening socket * @c: Execution context @@ -2060,14 +2104,14 @@ void conf_listen_handler(struct ctx *c, uint32_t events) union epoll_ref ref = { .type = EPOLL_TYPE_CONF }; struct ucred uc = { 0 }; socklen_t len = sizeof(uc); - int fd, rc; + int fd, rc, i; if (events != EPOLLIN) { err("Unexpected event 0x%04x on configuration socket", events); return; } - fd = accept4(c->fd_control_listen, NULL, NULL, SOCK_NONBLOCK); + fd = accept4(c->fd_control_listen, NULL, NULL, 0); if (fd < 0) { warn_perror("accept4() on configuration listening socket"); return; @@ -2108,6 +2152,18 @@ void conf_listen_handler(struct ctx *c, uint32_t events) if (conf_send_rules(c, fd) < 0) goto fail; + if (conf_recv_rules(c, fd) < 0) + goto fail; + + info("Received new forwarding table:"); + for (i = 0; i < PIF_NUM_TYPES; i++) { + if (!c->fwd_pending[i]) + continue; + + info("Forwarding from %s:", pif_name(i)); + fwd_rules_print(c->fwd_pending[i]); + } + return; fail: diff --git a/fwd.c b/fwd.c index 4592af25..d54a1f15 100644 --- a/fwd.c +++ b/fwd.c @@ -247,6 +247,9 @@ void fwd_neigh_table_init(const struct ctx *c) static struct fwd_table fwd_in; static struct fwd_table fwd_out; +static struct fwd_table fwd_in_pending; +static struct fwd_table fwd_out_pending; + /** * fwd_rule_init() - Initialise forwarding tables * @c: Execution context @@ -254,8 +257,12 @@ static struct fwd_table fwd_out; void fwd_rule_init(struct ctx *c) { c->fwd[PIF_HOST] = &fwd_in; - if (c->mode == MODE_PASTA) + c->fwd_pending[PIF_HOST] = &fwd_in_pending; + + if (c->mode == MODE_PASTA) { c->fwd[PIF_SPLICE] = &fwd_out; + c->fwd_pending[PIF_SPLICE] = &fwd_out_pending; + } } /** diff --git a/passt.h b/passt.h index b3f049de..1726965d 100644 --- a/passt.h +++ b/passt.h @@ -188,6 +188,7 @@ struct ip6_ctx { * @pasta_ifi: Index of namespace interface for pasta * @pasta_conf_ns: Configure namespace after creating it * @fwd: Forwarding tables + * @fwd_pending: Pending forward tables * @no_tcp: Disable TCP operation * @tcp: Context for TCP protocol handler * @no_udp: Disable UDP operation @@ -270,6 +271,7 @@ struct ctx { int pasta_conf_ns; struct fwd_table *fwd[PIF_NUM_TYPES]; + struct fwd_table *fwd_pending[PIF_NUM_TYPES]; int no_tcp; struct tcp_ctx tcp; diff --git a/pesto.c b/pesto.c index aa1d584c..5ee0352e 100644 --- a/pesto.c +++ b/pesto.c @@ -38,6 +38,7 @@ #include "fwd_rule.h" #include "pesto.h" #include "log.h" +#include "pif.h" int verbosity = 1; @@ -65,6 +66,36 @@ static void usage(const char *name, FILE *f, int status) FPRINTF(f, "Usage: %s [OPTION]... PATH\n", name); FPRINTF(f, "\n" + " -t, --tcp-ports SPEC TCP inbound port forwarding\n" + " can be specified multiple times\n" + " SPEC can be:\n" + " 'none': don't forward any ports\n" + " 'auto': forward all ports currently bound in namespace\n" + " 'all': forward all unbound, non-ephemeral ports\n" + " a comma-separated list, optionally ranged with '-'\n" + " and optional target ports after ':', with optional\n" + " address specification suffixed by '/' and optional\n" + " interface prefixed by '%%'. Examples:\n" + " -t 22 Forward local port 22 to port 22 in netns\n" + " -t 22:23 Forward local port 22 to port 23\n" + " -t 22,25 Forward ports 22, 25 to ports 22, 25\n" + " -t 22-80 Forward ports 22 to 80\n" + " -t 22-80:32-90 Forward ports 22 to 80 to\n" + " corresponding port numbers plus 10\n" + " -t 192.0.2.1/5 Bind port 5 of 192.0.2.1\n" + " -t 5-25,~10-20 Forward ports 5 to 9, and 21 to 25\n" + " -t ~25 Forward all bound ports except for 25\n" + " IPv6 bound ports are also forwarded for IPv4\n" + " -u, --udp-ports SPEC UDP inbound port forwarding\n" + " SPEC is as described for TCP above\n" + " IPv6 bound ports are also forwarded for IPv4\n" + " unless specified, with '-t auto', UDP ports with numbers\n" + " corresponding to forwarded TCP port numbers are\n" + " forwarded too\n" + " -T, --tcp-ns SPEC TCP port forwarding to init namespace\n" + " SPEC is as described above\n" + " -U, --udp-ns SPEC UDP port forwarding to init namespace\n" + " SPEC is as described above\n" " -v, --verbose Be more verbose\n" " -q, --quiet Be less verbose\n" " -h, --help Display this help message and exit\n" @@ -221,7 +252,7 @@ static void show_state(const struct conf_state *state) * * Return: 0 on success, won't return on failure * - * #syscalls:pesto connect write close exit_group fstat brk getrandom + * #syscalls:pesto connect write close exit_group fstat brk getrandom openat * #syscalls:pesto socket s390x:socketcall i686:socketcall * #syscalls:pesto recvfrom recvmsg arm:recv ppc64le:recv * #syscalls:pesto sendto sendmsg arm:send ppc64le:send @@ -233,15 +264,22 @@ int main(int argc, char **argv) {"verbose", no_argument, NULL, 'v' }, {"help", no_argument, NULL, 'h' }, {"version", no_argument, NULL, 1 }, + {"tcp-ports", required_argument, NULL, 't' }, + {"udp-ports", required_argument, NULL, 'u' }, + {"tcp-ns", required_argument, NULL, 'T' }, + {"udp-ns", required_argument, NULL, 'U' }, { 0 }, }; + struct fwd_table fwd_in = { .count = 0 }, fwd_out = { .count = 0 }; struct sockaddr_un a = { AF_UNIX, "" }; - const char *optstring = "vh"; + const char *optstring = "vht:u:T:U:"; + enum fwd_mode fwd_default; struct pesto_hello hello; struct conf_state *state; struct sock_fprog prog; int optname, ret, s; uint32_t s_version; + unsigned i; prog.len = (unsigned short)sizeof(filter_pesto) / sizeof(filter_pesto[0]); @@ -250,6 +288,8 @@ int main(int argc, char **argv) prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) die("Failed to apply seccomp filter"); + fwd_probe_ephemeral(); + do { optname = getopt_long(argc, argv, optstring, options, NULL); @@ -266,6 +306,18 @@ int main(int argc, char **argv) case 'v': verbosity++; break; + case 't': + case 'u': + fwd_default = FWD_MODE_UNSET; + conf_ports(optname, optarg, &fwd_in, &fwd_default, + true, true, true); + break; + case 'T': + case 'U': + fwd_default = FWD_MODE_UNSET; + conf_ports(optname, optarg, &fwd_out, &fwd_default, + true, true, true); + break; case 1: FPRINTF(stdout, "pesto "); FPRINTF(stdout, VERSION_BLOB); @@ -291,6 +343,22 @@ int main(int argc, char **argv) a.sun_path, strerror(errno)); } + debug("Inbound rules from command line:"); + for (i = 0; i < fwd_in.count; i++) { + const struct fwd_rule *rule = &fwd_in.rules[i].rule; + char rulestr[FWD_RULE_STRLEN]; + + debug(" %s", fwd_rule_ntop(rule, rulestr, sizeof(rulestr))); + } + + debug("Outbound rules from command line:"); + for (i = 0; i < fwd_out.count; i++) { + const struct fwd_rule *rule = &fwd_out.rules[i].rule; + char rulestr[FWD_RULE_STRLEN]; + + debug(" %s", fwd_rule_ntop(rule, rulestr, sizeof(rulestr))); + } + debug("Connected to passt/pasta control socket"); ret = read_all_buf(s, &hello, sizeof(hello)); @@ -324,5 +392,21 @@ int main(int argc, char **argv) show_state(state); + if (fwd_in.count) { + write_u8(s, PIF_HOST); + write_u32(s, fwd_in.count); + for (i = 0; i < fwd_in.count; i++) + fwd_rule_write(s, &fwd_in.rules[i].rule); + } + + if (fwd_out.count) { + write_u8(s, PIF_SPLICE); + write_u32(s, fwd_out.count); + for (i = 0; i < fwd_out.count; i++) + fwd_rule_write(s, &fwd_out.rules[i].rule); + } + + write_u8(s, PIF_NONE); + exit(0); } diff --git a/pif.h b/pif.h index 7bb58e5c..c96a0900 100644 --- a/pif.h +++ b/pif.h @@ -35,6 +35,7 @@ enum pif_type { PIF_NUM_TYPES, }; +#ifndef PESTO extern const char *pif_type_str[]; static inline const char *pif_type(enum pif_type pt) @@ -66,5 +67,6 @@ void pif_sockaddr(const struct ctx *c, union sockaddr_inany *sa, int pif_listen(const struct ctx *c, enum epoll_type type, uint8_t pif, const union inany_addr *addr, const char *ifname, in_port_t port, unsigned rule); +#endif /* !PESTO */ #endif /* PIF_H */ -- 2.53.0