From 761cf19d7bc4b5950caff33965508d9fb7bbb547 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 15 Sep 2020 19:58:44 +0200 Subject: firewall-util: introduce context structure for planned nft backend we have three choices: - open/close a new nfnetlink socket for every operation - keep a nfnetlink socket open internally - expose a opaque fw_ctx and stash all internal data here. Originally I opted for the 2nd option, but during review it was suggested to avoid static storage duration because of perceived problems with threaded applications. This adds fw_ctx and new/free functions, then converts the existing api and nspawn and networkd to use it. --- src/nspawn/nspawn-expose-ports.c | 12 +++++++----- src/nspawn/nspawn-expose-ports.h | 6 ++++-- src/nspawn/nspawn.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 35 insertions(+), 17 deletions(-) (limited to 'src/nspawn') diff --git a/src/nspawn/nspawn-expose-ports.c b/src/nspawn/nspawn-expose-ports.c index db076c50c0..c368b20563 100644 --- a/src/nspawn/nspawn-expose-ports.c +++ b/src/nspawn/nspawn-expose-ports.c @@ -82,7 +82,7 @@ void expose_port_free_all(ExposePort *p) { } } -int expose_port_flush(ExposePort* l, union in_addr_union *exposed) { +int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, union in_addr_union *exposed) { ExposePort *p; int r, af = AF_INET; @@ -97,7 +97,8 @@ int expose_port_flush(ExposePort* l, union in_addr_union *exposed) { log_debug("Lost IP address."); LIST_FOREACH(ports, p, l) { - r = fw_add_local_dnat(false, + r = fw_add_local_dnat(fw_ctx, + false, af, p->protocol, p->host_port, @@ -112,7 +113,7 @@ int expose_port_flush(ExposePort* l, union in_addr_union *exposed) { return 0; } -int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *exposed) { +int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, union in_addr_union *exposed) { _cleanup_free_ struct local_address *addresses = NULL; union in_addr_union new_exposed; ExposePort *p; @@ -136,7 +137,7 @@ int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *ex addresses[0].scope < RT_SCOPE_LINK; if (!add) - return expose_port_flush(l, exposed); + return expose_port_flush(fw_ctx, l, exposed); new_exposed = addresses[0].address; if (in_addr_equal(af, exposed, &new_exposed)) @@ -150,7 +151,8 @@ int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *ex LIST_FOREACH(ports, p, l) { - r = fw_add_local_dnat(true, + r = fw_add_local_dnat(fw_ctx, + true, af, p->protocol, p->host_port, diff --git a/src/nspawn/nspawn-expose-ports.h b/src/nspawn/nspawn-expose-ports.h index d0c1cecbe8..c1677cb61b 100644 --- a/src/nspawn/nspawn-expose-ports.h +++ b/src/nspawn/nspawn-expose-ports.h @@ -3,6 +3,8 @@ #include +#include "firewall-util.h" + #include "sd-event.h" #include "sd-netlink.h" @@ -22,5 +24,5 @@ int expose_port_parse(ExposePort **l, const char *s); int expose_port_watch_rtnl(sd_event *event, int recv_fd, sd_netlink_message_handler_t handler, void *userdata, sd_netlink **ret); int expose_port_send_rtnl(int send_fd); -int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *exposed); -int expose_port_flush(ExposePort* l, union in_addr_union *exposed); +int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, union in_addr_union *exposed); +int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, union in_addr_union *exposed); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index cfbc8f11bf..a6f64e8415 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2474,14 +2474,19 @@ static int setup_kmsg(int kmsg_socket) { return 0; } +struct ExposeArgs { + union in_addr_union address; + struct FirewallContext *fw_ctx; +}; + static int on_address_change(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - union in_addr_union *exposed = userdata; + struct ExposeArgs *args = userdata; assert(rtnl); assert(m); - assert(exposed); + assert(args); - expose_port_execute(rtnl, arg_expose_ports, exposed); + expose_port_execute(rtnl, &args->fw_ctx, arg_expose_ports, &args->address); return 0; } @@ -4466,7 +4471,7 @@ static int run_container( bool secondary, FDSet *fds, char veth_name[IFNAMSIZ], bool *veth_created, - union in_addr_union *exposed, + struct ExposeArgs *expose_args, int *master, pid_t *pid, int *ret) { static const struct sigaction sa = { @@ -4895,11 +4900,11 @@ static int run_container( (void) sd_event_add_signal(event, NULL, SIGCHLD, on_sigchld, PID_TO_PTR(*pid)); if (arg_expose_ports) { - r = expose_port_watch_rtnl(event, rtnl_socket_pair[0], on_address_change, exposed, &rtnl); + r = expose_port_watch_rtnl(event, rtnl_socket_pair[0], on_address_change, expose_args, &rtnl); if (r < 0) return r; - (void) expose_port_execute(rtnl, arg_expose_ports, exposed); + (void) expose_port_execute(rtnl, &expose_args->fw_ctx, arg_expose_ports, &expose_args->address); } rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); @@ -5026,7 +5031,7 @@ static int run_container( return 0; /* finito */ } - expose_port_flush(arg_expose_ports, exposed); + expose_port_flush(&expose_args->fw_ctx, arg_expose_ports, &expose_args->address); (void) remove_veth_links(veth_name, arg_network_veth_extra); *veth_created = false; @@ -5155,12 +5160,13 @@ static int run(int argc, char *argv[]) { _cleanup_fdset_free_ FDSet *fds = NULL; int r, n_fd_passed, ret = EXIT_SUCCESS; char veth_name[IFNAMSIZ] = ""; - union in_addr_union exposed = {}; + struct ExposeArgs expose_args = {}; _cleanup_(release_lock_file) LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT; char tmprootdir[] = "/tmp/nspawn-root-XXXXXX"; _cleanup_(loop_device_unrefp) LoopDevice *loop = NULL; _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL; + _cleanup_(fw_ctx_freep) FirewallContext *fw_ctx = NULL; pid_t pid = 0; log_parse_environment(); @@ -5517,12 +5523,20 @@ static int run(int argc, char *argv[]) { goto finish; } + if (arg_expose_ports) { + r = fw_ctx_new(&fw_ctx); + if (r < 0) { + log_error_errno(r, "Cannot expose configured ports, firewall initialization failed: %m"); + goto finish; + } + expose_args.fw_ctx = fw_ctx; + } for (;;) { r = run_container(dissected_image, secondary, fds, veth_name, &veth_created, - &exposed, &master, + &expose_args, &master, &pid, &ret); if (r <= 0) break; @@ -5572,7 +5586,7 @@ finish: (void) rm_rf(p, REMOVE_ROOT); } - expose_port_flush(arg_expose_ports, &exposed); + expose_port_flush(&fw_ctx, arg_expose_ports, &expose_args.address); if (veth_created) (void) remove_veth_links(veth_name, arg_network_veth_extra); -- cgit v1.2.1