diff options
| author | Hayato Kiwata <dev@haytok.jp> | 2026-10-30 01:28:58 +0900 |
|---|---|---|
| committer | Stefano Brivio <sbrivio@redhat.com> | 2026-11-10 23:51:34 +0100 |
| commit | 1776dcb7317ef1daab3d73c6262609c1ce6e0ee1 (patch) | |
| tree | 3f2e92b5ff8d3959301a0b5ed5592c5e98af5380 | |
| parent | 943f29f82ada14b7d540ee1634060bd6be0d62b7 (diff) | |
| download | passt-1776dcb7317ef1daab3d73c6262609c1ce6e0ee1.tar passt-1776dcb7317ef1daab3d73c6262609c1ce6e0ee1.tar.gz passt-1776dcb7317ef1daab3d73c6262609c1ce6e0ee1.tar.bz2 passt-1776dcb7317ef1daab3d73c6262609c1ce6e0ee1.tar.lz passt-1776dcb7317ef1daab3d73c6262609c1ce6e0ee1.tar.xz passt-1776dcb7317ef1daab3d73c6262609c1ce6e0ee1.tar.zst passt-1776dcb7317ef1daab3d73c6262609c1ce6e0ee1.zip | |
fwd, conf: Roll back to old rules if switching to new ones fails
If fwd_listen_init() fails while switching to new forwarding rules
received from pesto, we currently close the old listening sockets,
report an error and keep the (partially bound) new rules. That leaves
pasta in a state the user didn't ask for.
Make fwd_listen_switch() return the result of fwd_listen_init(), and
call it a second time from conf_handler() on failure to switch back
to the old rules.
Don't reset the count of the old table after closing its sockets, so
that the old rules stay in c->fwd_pending and can be restored. The
pending tables are cleared by conf_handler() before receiving new
rules anyway.
Note that reporting the failure to the client is left for a later patch.
Link: https://archives.passt.top/passt-dev/20261025153025.600a4fe9@elisabeth/
Signed-off-by: Hayato Kiwata <dev@haytok.jp>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
| -rw-r--r-- | conf.c | 7 | ||||
| -rw-r--r-- | fwd.c | 10 | ||||
| -rw-r--r-- | fwd.h | 2 |
3 files changed, 12 insertions, 7 deletions
@@ -2250,7 +2250,12 @@ void conf_handler(struct ctx *c, uint32_t events) " ", ""); } - fwd_listen_switch(c); + if (fwd_listen_switch(c) < 0) { + err("Error switching to new forwarding rules"); + /* Switch back to old rules (still in c->fwd_pending) */ + if (fwd_listen_switch(c) < 0) + err("Couldn't restore old forwarding rules"); + } } if (events & EPOLLHUP) { @@ -536,8 +536,10 @@ int fwd_listen_init(const struct ctx *c) /** * fwd_listen_switch() - Switch from current to pending rules table * @c: Execution context + * + * Return: 0 on success, -1 on failure */ -void fwd_listen_switch(struct ctx *c) +int fwd_listen_switch(struct ctx *c) { struct fwd_table *tmp[PIF_NUM_TYPES]; unsigned i; @@ -549,9 +551,8 @@ void fwd_listen_switch(struct ctx *c) if (!fwd) continue; - debug("Flushing %u old %s rules", fwd->count, pif_name(i)); + debug("Flushing %u %s rules", fwd->count, pif_name(i)); fwd_listen_close(fwd); - fwd->count = fwd->sock_count = 0; } /* Swap active and pending tables */ @@ -563,8 +564,7 @@ void fwd_listen_switch(struct ctx *c) memcpy((void *)c->fwd_pending, &tmp, sizeof(c->fwd_pending)); /* Start listening on the new tables */ - if (fwd_listen_init(c) < 0) - err("Error switching to new forwarding rules"); + return fwd_listen_init(c); } /* See enum in kernel's include/net/tcp_states.h */ @@ -61,7 +61,7 @@ int fwd_listen_sync(const struct ctx *c, uint8_t pif, const struct fwd_scan *tcp, const struct fwd_scan *udp); void fwd_listen_close(const struct fwd_table *fwd); int fwd_listen_init(const struct ctx *c); -void fwd_listen_switch(struct ctx *c); +int fwd_listen_switch(struct ctx *c); bool nat_inbound(const struct ctx *c, const union inany_addr *addr, union inany_addr *translated); |
