Emit hotplug calls when flushing / creating zone chains
authorJo-Philipp Wich <jow@openwrt.org>
Tue, 12 Mar 2013 18:43:41 +0000 (19:43 +0100)
committerJo-Philipp Wich <jow@openwrt.org>
Wed, 13 Mar 2013 14:16:29 +0000 (15:16 +0100)
main.c
options.h
utils.c
utils.h
zones.c
zones.h

diff --git a/main.c b/main.c
index c1f6505be173fd251110df27a56bca67655095b1..3c2b4eb1e6e4ea645c977bb98ec9a987c0518fea 100644 (file)
--- 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;
index 392db13467ed30d548374df9e47da3e6bb2e1bbd..c84fd289f65b48a31e8bcce93506a2f3113cb215 100644 (file)
--- 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 1942cbc71068effda0c923f4e4f0ec55cfaf0aa9..dbc713cd36e8ff675813b6d0a5f0f7117bd293c4 100644 (file)
--- 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 e28408bd8774c2f8c5269f2003d9ab2834eef873..eee1f40b81915f56c73350e4e4aee528c6abbe35 100644 (file)
--- 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 79f037e98306602fe9f6fe50fd5571ca159642b1..846e43015d7b41e8980f2139dd1589236fb32d61 100644 (file)
--- 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 8f94ccff7f5d67b0b456bea83937c06bb622a830..bda96ab2873cb67ef1d15139d2faa7714b741093 100644 (file)
--- 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