From 6da847c446c29c349b0edd757c1afd529565c619 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 12 Mar 2013 19:43:41 +0100 Subject: [PATCH] Emit hotplug calls when flushing / creating zone chains --- main.c | 12 +++++++++--- options.h | 1 + utils.c | 41 +++++++++++++++++++++++++++++++++++++++++ utils.h | 3 +++ zones.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ zones.h | 7 ++++--- 6 files changed, 112 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index c1f6505..3c2b4eb 100644 --- a/main.c +++ b/main.c @@ -171,6 +171,9 @@ stop(struct fw3_state *state, bool complete, bool reload) return rv; } + if (!print_rules) + fw3_hotplug_zones(false, state); + for (family = FW3_FAMILY_V4; family <= FW3_FAMILY_V6; family++) { if (!complete && !family_running(state, family)) @@ -303,11 +306,14 @@ start(struct fw3_state *state, bool reload) { fw3_set_defaults(state); - if (!reload && !print_rules) - fw3_run_includes(state); - if (!print_rules) + { + if (!reload) + fw3_run_includes(state); + + fw3_hotplug_zones(true, state); fw3_write_statefile(state); + } } return rv; diff --git a/options.h b/options.h index 392db13..c84fd28 100644 --- a/options.h +++ b/options.h @@ -77,6 +77,7 @@ enum fw3_flag FW3_FLAG_SYN_FLOOD = 16, FW3_FLAG_MTU_FIX = 17, FW3_FLAG_DROP_INVALID = 18, + FW3_FLAG_HOTPLUG = 19, __FW3_FLAG_MAX }; diff --git a/utils.c b/utils.c index 1942cbc..dbc713c 100644 --- a/utils.c +++ b/utils.c @@ -244,6 +244,7 @@ __fw3_command_pipe(bool silent, const char *command, ...) signal(SIGPIPE, SIG_IGN); pipe_pid = pid; close(pfds[0]); + fcntl(pfds[1], F_SETFD, fcntl(pfds[1], F_GETFD) | FD_CLOEXEC); } pipe_fd = fdopen(pfds[1], "w"); @@ -597,3 +598,43 @@ fw3_pr_rulespec(int table, int family, uint32_t *flags, uint32_t mask, return rv; } + + +bool +fw3_hotplug(bool add, void *zone, void *device) +{ + struct fw3_zone *z = zone; + struct fw3_device *d = device; + + if (!d->network) + return false; + + switch (fork()) + { + case -1: + warn("Unable to fork(): %s\n", strerror(errno)); + return false; + + case 0: + break; + + default: + return true; + } + + close(0); + close(1); + close(2); + chdir("/"); + + clearenv(); + setenv("ACTION", add ? "add" : "remove", 1); + setenv("ZONE", z->name, 1); + setenv("INTERFACE", d->network->name, 1); + setenv("DEVICE", d->name, 1); + + execl(FW3_HOTPLUG, FW3_HOTPLUG, "firewall", NULL); + + /* unreached */ + return false; +} diff --git a/utils.h b/utils.h index e28408b..eee1f40 100644 --- a/utils.h +++ b/utils.h @@ -35,6 +35,7 @@ #define FW3_STATEFILE "/var/run/fw3.state" #define FW3_LOCKFILE "/var/run/fw3.lock" +#define FW3_HOTPLUG "/sbin/hotplug-call" extern bool fw3_pr_debug; @@ -109,4 +110,6 @@ struct fw3_rule_spec { bool fw3_pr_rulespec(int table, int family, uint32_t *flags, uint32_t mask, const struct fw3_rule_spec *r, const char *fmt, ...); +bool fw3_hotplug(bool add, void *zone, void *device); + #endif diff --git a/zones.c b/zones.c index 79f037e..846e430 100644 --- a/zones.c +++ b/zones.c @@ -521,6 +521,40 @@ fw3_flush_zones(enum fw3_table table, enum fw3_family family, } } +void +fw3_hotplug_zones(bool add, struct fw3_state *state) +{ + struct fw3_zone *z; + struct fw3_device *d; + + if (add) + { + list_for_each_entry(z, &state->running_zones, running_list) + { + if (!hasbit(z->flags[0], FW3_FLAG_HOTPLUG)) + { + list_for_each_entry(d, &z->devices, list) + fw3_hotplug(add, z, d); + + setbit(z->flags[0], FW3_FLAG_HOTPLUG); + } + } + } + else + { + list_for_each_entry(z, &state->running_zones, running_list) + { + if (hasbit(z->flags[0], FW3_FLAG_HOTPLUG)) + { + list_for_each_entry(d, &z->running_devices, list) + fw3_hotplug(add, z, d); + + delbit(z->flags[0], FW3_FLAG_HOTPLUG); + } + } + } +} + struct fw3_zone * fw3_lookup_zone(struct fw3_state *state, const char *name, bool running) { @@ -542,3 +576,23 @@ fw3_lookup_zone(struct fw3_state *state, const char *name, bool running) return NULL; } + +void +fw3_free_zone(struct fw3_zone *zone) +{ + struct fw3_device *dev, *tmp; + + list_for_each_entry_safe(dev, tmp, &zone->running_devices, list) + { + list_del(&dev->list); + free(dev); + } + + list_for_each_entry_safe(dev, tmp, &zone->running_networks, list) + { + list_del(&dev->list); + free(dev); + } + + fw3_free_object(zone, fw3_zone_opts); +} diff --git a/zones.h b/zones.h index 8f94ccf..bda96ab 100644 --- a/zones.h +++ b/zones.h @@ -36,13 +36,14 @@ void fw3_print_zone_rules(enum fw3_table table, enum fw3_family family, void fw3_flush_zones(enum fw3_table table, enum fw3_family family, bool pass2, bool reload, struct fw3_state *state); +void fw3_hotplug_zones(bool add, struct fw3_state *state); + struct fw3_zone * fw3_lookup_zone(struct fw3_state *state, const char *name, bool running); +void fw3_free_zone(struct fw3_zone *zone); + #define fw3_to_src_target(t) \ (FW3_FLAG_SRC_ACCEPT - FW3_FLAG_ACCEPT + t) -#define fw3_free_zone(zone) \ - fw3_free_object(zone, fw3_zone_opts) - #endif -- 2.11.0