p-cscf: Add attribute handler for P-CSCF server addresses
authorTobias Brunner <tobias@strongswan.org>
Thu, 4 Feb 2016 17:26:29 +0000 (18:26 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 10 Mar 2016 10:57:38 +0000 (11:57 +0100)
src/libcharon/plugins/p_cscf/Makefile.am
src/libcharon/plugins/p_cscf/p_cscf_handler.c [new file with mode: 0644]
src/libcharon/plugins/p_cscf/p_cscf_handler.h [new file with mode: 0644]
src/libcharon/plugins/p_cscf/p_cscf_plugin.c

index 1789817..1e00a56 100644 (file)
@@ -13,6 +13,7 @@ plugin_LTLIBRARIES = libstrongswan-p-cscf.la
 endif
 
 libstrongswan_p_cscf_la_SOURCES = \
-       p_cscf_plugin.c p_cscf_plugin.h
+       p_cscf_plugin.c p_cscf_plugin.h \
+       p_cscf_handler.c p_cscf_handler.h
 
 libstrongswan_p_cscf_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/p_cscf/p_cscf_handler.c b/src/libcharon/plugins/p_cscf/p_cscf_handler.c
new file mode 100644 (file)
index 0000000..15313ea
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "p_cscf_handler.h"
+
+#include <networking/host.h>
+#include <utils/debug.h>
+
+typedef struct private_p_cscf_handler_t private_p_cscf_handler_t;
+
+/**
+ * Private data
+ */
+struct private_p_cscf_handler_t {
+
+       /**
+        * Public interface
+        */
+       p_cscf_handler_t public;
+};
+
+METHOD(attribute_handler_t, handle, bool,
+       private_p_cscf_handler_t *this, ike_sa_t *ike_sa,
+       configuration_attribute_type_t type, chunk_t data)
+{
+       host_t *server;
+       int family = AF_INET6;
+
+       switch (type)
+       {
+               case P_CSCF_IP4_ADDRESS:
+                       family = AF_INET;
+                       /* fall-through */
+               case P_CSCF_IP6_ADDRESS:
+                       server = host_create_from_chunk(family, data, 0);
+                       if (!server)
+                       {
+                               DBG1(DBG_CFG, "received invalid P-CSCF server IP");
+                               return FALSE;
+                       }
+                       DBG1(DBG_CFG, "received P-CSCF server IP %H", server);
+                       server->destroy(server);
+                       return TRUE;
+               default:
+                       return FALSE;
+       }
+}
+
+METHOD(attribute_handler_t, release, void,
+       private_p_cscf_handler_t *this, ike_sa_t *ike_sa,
+       configuration_attribute_type_t type, chunk_t data)
+{
+       switch (type)
+       {
+               case P_CSCF_IP4_ADDRESS:
+               case P_CSCF_IP6_ADDRESS:
+                       /* nothing to do as we only log the server IPs */
+                       break;
+               default:
+                       break;
+       }
+}
+
+/**
+ * Data for attribute enumerator
+ */
+typedef struct {
+       enumerator_t public;
+       bool request_ipv4;
+       bool request_ipv6;
+} attr_enumerator_t;
+
+METHOD(enumerator_t, enumerate_attrs, bool,
+       attr_enumerator_t *this, configuration_attribute_type_t *type,
+       chunk_t *data)
+{
+       if (this->request_ipv4)
+       {
+               *type = P_CSCF_IP4_ADDRESS;
+               *data = chunk_empty;
+               this->request_ipv4 = FALSE;
+               return TRUE;
+       }
+       if (this->request_ipv6)
+       {
+               *type = P_CSCF_IP6_ADDRESS;
+               *data = chunk_empty;
+               this->request_ipv6 = FALSE;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
+       private_p_cscf_handler_t *this, ike_sa_t *ike_sa,
+       linked_list_t *vips)
+{
+       attr_enumerator_t *enumerator;
+
+       if (ike_sa->get_version(ike_sa) == IKEV1)
+       {
+               return enumerator_create_empty();
+       }
+
+       INIT(enumerator,
+               .public = {
+                       .enumerate = (void*)_enumerate_attrs,
+                       .destroy = (void*)free,
+               },
+               .request_ipv4 = TRUE,
+               .request_ipv6 = TRUE,
+       );
+       return &enumerator->public;
+}
+
+METHOD(p_cscf_handler_t, destroy, void,
+       private_p_cscf_handler_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+p_cscf_handler_t *p_cscf_handler_create()
+{
+       private_p_cscf_handler_t *this;
+
+       INIT(this,
+               .public = {
+                       .handler = {
+                               .handle = _handle,
+                               .release = _release,
+                               .create_attribute_enumerator = _create_attribute_enumerator,
+                       },
+                       .destroy = _destroy,
+               },
+       );
+
+       return &this->public;
+}
diff --git a/src/libcharon/plugins/p_cscf/p_cscf_handler.h b/src/libcharon/plugins/p_cscf/p_cscf_handler.h
new file mode 100644 (file)
index 0000000..ad4f1ac
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup p_cscf_handler p_cscf_handler
+ * @{ @ingroup p_cscf
+ */
+
+#ifndef P_CSCF_HANDLER_H_
+#define P_CSCF_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct p_cscf_handler_t p_cscf_handler_t;
+
+/**
+ * Attribute handler for P-CSCF server addresses.
+ */
+struct p_cscf_handler_t {
+
+       /**
+        * Implements attribute_handler_t.
+        */
+       attribute_handler_t handler;
+
+       /**
+        * Destroy a p_cscf_handler_t.
+        */
+       void (*destroy)(p_cscf_handler_t *this);
+};
+
+/**
+ * Create an p_cscf_handler_t instance.
+ */
+p_cscf_handler_t *p_cscf_handler_create();
+
+#endif /** P_CSCF_HANDLER_H_ @}*/
index ff4753e..8e2bc72 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include "p_cscf_plugin.h"
+#include "p_cscf_handler.h"
 
 #include <daemon.h>
 
@@ -28,6 +29,11 @@ struct private_p_cscf_plugin_t {
         * Public interface
         */
        p_cscf_plugin_t public;
+
+       /**
+        * P-CSCF server address attribute handler
+        */
+       p_cscf_handler_t *handler;
 };
 
 METHOD(plugin_t, get_name, char*,
@@ -36,9 +42,40 @@ METHOD(plugin_t, get_name, char*,
        return "p-cscf";
 }
 
+/**
+ * Register handler
+ */
+static bool plugin_cb(private_p_cscf_plugin_t *this,
+                                         plugin_feature_t *feature, bool reg, void *cb_data)
+{
+       if (reg)
+       {
+               charon->attributes->add_handler(charon->attributes,
+                                                                               &this->handler->handler);
+       }
+       else
+       {
+               charon->attributes->remove_handler(charon->attributes,
+                                                                                  &this->handler->handler);
+       }
+       return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+       private_p_cscf_plugin_t *this, plugin_feature_t *features[])
+{
+       static plugin_feature_t f[] = {
+               PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+                       PLUGIN_PROVIDE(CUSTOM, "p-cscf"),
+       };
+       *features = f;
+       return countof(f);
+}
+
 METHOD(plugin_t, destroy, void,
        private_p_cscf_plugin_t *this)
 {
+       this->handler->destroy(this->handler);
        free(this);
 }
 
@@ -53,9 +90,11 @@ plugin_t *p_cscf_plugin_create()
                .public = {
                        .plugin = {
                                .get_name = _get_name,
+                               .get_features = _get_features,
                                .destroy = _destroy,
                        },
                },
+               .handler = p_cscf_handler_create(),
        );
 
        return &this->public.plugin;