bypass-lan: Allow ignoring or only considering subnets of specific interfaces
authorTobias Brunner <tobias@strongswan.org>
Wed, 12 Oct 2016 13:56:12 +0000 (15:56 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 8 Feb 2017 09:38:28 +0000 (10:38 +0100)
The config can also be reloaded by sending a SIGHUP to charon.

conf/Makefile.am
conf/plugins/bypass-lan.opt [new file with mode: 0644]
src/libcharon/plugins/bypass_lan/bypass_lan_listener.c
src/libcharon/plugins/bypass_lan/bypass_lan_listener.h
src/libcharon/plugins/bypass_lan/bypass_lan_plugin.c

index c4b2c02..80fa31e 100644 (file)
@@ -32,6 +32,7 @@ plugins = \
        plugins/attr.opt \
        plugins/attr-sql.opt \
        plugins/bliss.opt \
+       plugins/bypass-lan.opt \
        plugins/certexpire.opt \
        plugins/coupling.opt \
        plugins/dhcp.opt \
diff --git a/conf/plugins/bypass-lan.opt b/conf/plugins/bypass-lan.opt
new file mode 100644 (file)
index 0000000..8c72fac
--- /dev/null
@@ -0,0 +1,8 @@
+charon.plugins.bypass-lan.interfaces_ignore
+       A comma-separated list of network interfaces for which connected subnets
+       should be ignored, if **interfaces_use** is specified this option has no
+       effect.
+
+charon.plugins.bypass-lan.interfaces_use
+       A comma-separated list of network interfaces for which connected subnets
+       should be considered. All other interfaces are ignored.
index a5e4df7..49f7cd3 100644 (file)
@@ -16,6 +16,7 @@
 #include "bypass_lan_listener.h"
 
 #include <collections/hashtable.h>
+#include <collections/linked_list.h>
 #include <threading/mutex.h>
 #include <processing/jobs/callback_job.h>
 
@@ -34,14 +35,26 @@ struct private_bypass_lan_listener_t {
        bypass_lan_listener_t public;
 
        /**
-        * Currently installed bypass policies, bypass_policy_t*
+        * Currently installed bypass policies, bypass_policy_t*.
         */
        hashtable_t *policies;
 
        /**
-        * Mutex to access list of policies
+        * Mutex to access list of policies.
         */
        mutex_t *mutex;
+
+       /**
+        * List of interface names to include or exclude (char*), NULL if interfaces
+        * are not filtered.
+        */
+       linked_list_t *ifaces_filter;
+
+       /**
+        * TRUE to exclude interfaces listed in ifaces_filter, FALSE to consider
+        * only those listed there.
+        */
+       bool ifaces_exclude;
 };
 
 /**
@@ -95,6 +108,22 @@ static bool policy_equals(bypass_policy_t *a, bypass_policy_t *b)
 }
 
 /**
+ * Check if an interface should be considered
+ */
+static bool consider_interface(private_bypass_lan_listener_t *this, char *iface)
+{
+       status_t expected;
+
+       if (!iface || !this->ifaces_filter)
+       {
+               return TRUE;
+       }
+       expected = this->ifaces_exclude ? NOT_FOUND : SUCCESS;
+       return this->ifaces_filter->find_first(this->ifaces_filter, (void*)streq,
+                                                                                  NULL, iface) == expected;
+}
+
+/**
  * Job updating bypass policies
  */
 static job_requeue_t update_bypass(private_bypass_lan_listener_t *this)
@@ -114,6 +143,11 @@ static job_requeue_t update_bypass(private_bypass_lan_listener_t *this)
        enumerator = charon->kernel->create_local_subnet_enumerator(charon->kernel);
        while (enumerator->enumerate(enumerator, &net, &mask, &iface))
        {
+               if (!consider_interface(this, iface))
+               {
+                       continue;
+               }
+
                INIT(lookup,
                        .net = net->clone(net),
                        .mask = mask,
@@ -178,6 +212,47 @@ METHOD(kernel_listener_t, roam, bool,
        return TRUE;
 }
 
+METHOD(bypass_lan_listener_t, reload_interfaces, void,
+       private_bypass_lan_listener_t *this)
+{
+       char *ifaces;
+
+       this->mutex->lock(this->mutex);
+       DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
+       this->ifaces_filter = NULL;
+       this->ifaces_exclude = FALSE;
+
+       ifaces = lib->settings->get_str(lib->settings,
+                                       "%s.plugins.bypass-lan.interfaces_use", NULL, lib->ns);
+       if (!ifaces)
+       {
+               this->ifaces_exclude = TRUE;
+               ifaces = lib->settings->get_str(lib->settings,
+                                       "%s.plugins.bypass-lan.interfaces_ignore", NULL, lib->ns);
+       }
+       if (ifaces)
+       {
+               enumerator_t *enumerator;
+               char *iface;
+
+               enumerator = enumerator_create_token(ifaces, ",", " ");
+               while (enumerator->enumerate(enumerator, &iface))
+               {
+                       if (!this->ifaces_filter)
+                       {
+                               this->ifaces_filter = linked_list_create();
+                       }
+                       this->ifaces_filter->insert_last(this->ifaces_filter,
+                                                                                        strdup(iface));
+               }
+               enumerator->destroy(enumerator);
+       }
+       this->mutex->unlock(this->mutex);
+       lib->processor->queue_job(lib->processor,
+                       (job_t*)callback_job_create((callback_job_cb_t)update_bypass, this,
+                                                                       NULL, (callback_job_cancel_t)return_false));
+}
+
 METHOD(bypass_lan_listener_t, destroy, void,
        private_bypass_lan_listener_t *this)
 {
@@ -190,6 +265,7 @@ METHOD(bypass_lan_listener_t, destroy, void,
                bypass_policy_destroy(policy);
        }
        enumerator->destroy(enumerator);
+       DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
        this->policies->destroy(this->policies);
        this->mutex->destroy(this->mutex);
        free(this);
@@ -207,6 +283,7 @@ bypass_lan_listener_t *bypass_lan_listener_create()
                        .listener = {
                                .roam = _roam,
                        },
+                       .reload_interfaces = _reload_interfaces,
                        .destroy = _destroy,
                },
                .policies = hashtable_create((hashtable_hash_t)policy_hash,
@@ -214,9 +291,6 @@ bypass_lan_listener_t *bypass_lan_listener_create()
                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
        );
 
-       /* FIXME: schedule this? */
-       lib->processor->queue_job(lib->processor,
-                       (job_t*)callback_job_create((callback_job_cb_t)update_bypass, this,
-                                                                       NULL, (callback_job_cancel_t)return_false));
+       reload_interfaces(this);
        return &this->public;
 }
index 5d4b732..737230d 100644 (file)
@@ -36,6 +36,11 @@ struct bypass_lan_listener_t {
        kernel_listener_t listener;
 
        /**
+        * Reload ignored/used interface names from config.
+        */
+       void (*reload_interfaces)(bypass_lan_listener_t *this);
+
+       /**
         * Destroy a bypass_lan_listener_t.
         */
        void (*destroy)(bypass_lan_listener_t *this);
index aea7ece..ccc05f0 100644 (file)
@@ -72,6 +72,13 @@ METHOD(plugin_t, get_features, int,
        return countof(f);
 }
 
+METHOD(plugin_t, reload, bool,
+       private_bypass_lan_plugin_t *this)
+{
+       this->listener->reload_interfaces(this->listener);
+       return TRUE;
+}
+
 METHOD(plugin_t, destroy, void,
        private_bypass_lan_plugin_t *this)
 {
@@ -91,6 +98,7 @@ plugin_t *bypass_lan_plugin_create()
                        .plugin = {
                                .get_name = _get_name,
                                .get_features = _get_features,
+                               .reload = _reload,
                                .destroy = _destroy,
                        },
                },