nm plugin handles DNS/NBNS configuration attributes
authorMartin Willi <martin@strongswan.org>
Mon, 27 Apr 2009 09:38:31 +0000 (09:38 -0000)
committerMartin Willi <martin@strongswan.org>
Mon, 27 Apr 2009 09:38:31 +0000 (09:38 -0000)
src/charon/plugins/nm/Makefile.am
src/charon/plugins/nm/nm_handler.c [new file with mode: 0644]
src/charon/plugins/nm/nm_handler.h [new file with mode: 0644]
src/charon/plugins/nm/nm_plugin.c
src/charon/plugins/nm/nm_service.c
src/charon/plugins/nm/nm_service.h

index ffd38e8..30c1c00 100644 (file)
@@ -5,6 +5,9 @@ AM_CFLAGS = -rdynamic -Wformat=0
 
 plugin_LTLIBRARIES = libstrongswan-nm.la
 libstrongswan_nm_la_SOURCES = \
-  nm_plugin.h nm_plugin.c nm_service.h nm_service.c nm_creds.h nm_creds.c
+  nm_plugin.h nm_plugin.c \
+  nm_service.h nm_service.c \
+  nm_creds.h nm_creds.c \
+  nm_handler.h nm_handler.c
 libstrongswan_nm_la_LDFLAGS = -module
 libstrongswan_nm_la_LIBADD = ${nm_LIBS}
diff --git a/src/charon/plugins/nm/nm_handler.c b/src/charon/plugins/nm/nm_handler.c
new file mode 100644 (file)
index 0000000..6ff13e5
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * 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.
+ *
+ * $Id$
+ */
+
+#include "nm_handler.h"
+
+#include <daemon.h>
+
+typedef struct private_nm_handler_t private_nm_handler_t;
+
+/**
+ * Private data of an nm_handler_t object.
+ */
+struct private_nm_handler_t {
+       
+       /**
+        * Public nm_handler_t interface.
+        */
+       nm_handler_t public;
+       
+       /**
+        * list of received DNS server attributes, pointer to 4 byte data
+        */
+       linked_list_t *dns;
+       
+       /**
+        * list of received NBNS server attributes, pointer to 4 byte data
+        */
+       linked_list_t *nbns;
+};
+
+/**
+ * Implementation of attribute_handler_t.handle
+ */
+static bool handle(private_nm_handler_t *this, ike_sa_t *ike_sa,
+                                  configuration_attribute_type_t type, chunk_t data)
+{
+       linked_list_t *list;
+       
+       switch (type)
+       {
+               case INTERNAL_IP4_DNS:
+                       list = this->dns;
+                       break;
+               case INTERNAL_IP4_NBNS:
+                       list = this->nbns;
+                       break;
+               default:
+                       return FALSE;
+       }
+       if (data.len != 4)
+       {
+               return FALSE;
+       }
+       list->insert_last(list, chunk_clone(data).ptr);
+       return TRUE;
+}
+
+/**
+ * convert plain byte ptrs to handy chunk during enumeration
+ */
+static bool filter_chunks(void* null, char **in, chunk_t *out)
+{
+       *out = chunk_create(*in, 4);
+       return TRUE;
+}
+
+/**
+ * Implementation of nm_handler_t.create_enumerator
+ */
+static enumerator_t* create_enumerator(private_nm_handler_t *this,
+                                                                          configuration_attribute_type_t type)
+{
+       linked_list_t *list;
+       
+       switch (type)
+       {
+               case INTERNAL_IP4_DNS:
+                       list = this->dns;
+                       break;
+               case INTERNAL_IP4_NBNS:
+                       list = this->nbns;
+               default:
+                       return enumerator_create_empty();
+       }
+       return enumerator_create_filter(list->create_enumerator(list),
+                                               (void*)filter_chunks, NULL, NULL);
+}
+
+/**
+ * Implementation of nm_handler_t.reset
+ */
+static void reset(private_nm_handler_t *this)
+{
+       void *data;
+       
+       while (this->dns->remove_last(this->dns, (void**)&data) == SUCCESS)
+       {
+               free(data);
+       }
+       while (this->nbns->remove_last(this->nbns, (void**)&data) == SUCCESS)
+       {
+               free(data);
+       }
+}
+
+/**
+ * Implementation of nm_handler_t.destroy.
+ */
+static void destroy(private_nm_handler_t *this)
+{
+       reset(this);
+       this->dns->destroy(this->dns);
+       this->nbns->destroy(this->nbns);
+       free(this);
+}
+
+/**
+ * See header
+ */
+nm_handler_t *nm_handler_create()
+{
+       private_nm_handler_t *this = malloc_thing(private_nm_handler_t);
+       
+       this->public.handler.handle = (bool(*)(attribute_handler_t*, ike_sa_t*, configuration_attribute_type_t, chunk_t))handle;
+       this->public.handler.release = (void(*)(attribute_handler_t*, ike_sa_t*, configuration_attribute_type_t, chunk_t))nop;
+       this->public.create_enumerator = (enumerator_t*(*)(nm_handler_t*, configuration_attribute_type_t type))create_enumerator;
+       this->public.reset = (void(*)(nm_handler_t*))reset;
+       this->public.destroy = (void(*)(nm_handler_t*))destroy;
+       
+       this->dns = linked_list_create();
+       this->nbns = linked_list_create();
+       
+       return &this->public;
+}
+
diff --git a/src/charon/plugins/nm/nm_handler.h b/src/charon/plugins/nm/nm_handler.h
new file mode 100644 (file)
index 0000000..d8a11c4
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup nm_handler nm_handler
+ * @{ @ingroup nm
+ */
+
+#ifndef NM_HANDLER_H_
+#define NM_HANDLER_H_
+
+#include <config/attributes/attribute_handler.h>
+
+typedef struct nm_handler_t nm_handler_t;
+
+/**
+ * Handles DNS/NBNS attributes to pass to NM.
+ */
+struct nm_handler_t {
+       
+       /**
+        * Implements attribute handler interface
+        */
+       attribute_handler_t handler;
+       
+       /**
+        * Create an enumerator over received attributes of a given kind.
+        *
+        * @param type          type of attributes to enumerate
+        * @return                      enumerator over attribute data (chunk_t)
+        */
+       enumerator_t* (*create_enumerator)(nm_handler_t *this,
+                                                                          configuration_attribute_type_t type);
+       /**
+        * Reset state, flush all received attributes.
+        */
+       void (*reset)(nm_handler_t *this);
+       
+       /**
+        * Destroy a nm_handler_t.
+        */
+       void (*destroy)(nm_handler_t *this);
+};
+
+/**
+ * Create a nm_handler instance.
+ */
+nm_handler_t *nm_handler_create();
+
+#endif /* NM_HANDLER_ @}*/
index 1336293..afe0b64 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008-2009 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
 #include "nm_plugin.h"
 #include "nm_service.h"
 #include "nm_creds.h"
+#include "nm_handler.h"
 
 #include <daemon.h>
 #include <processing/jobs/callback_job.h>
@@ -50,6 +51,11 @@ struct private_nm_plugin_t {
         * credential set registered at the daemon
         */
        nm_creds_t *creds;
+       
+       /**
+        * attribute handler regeisterd at the daemon
+        */
+       nm_handler_t *handler;
 };
 
 /**
@@ -79,6 +85,8 @@ static void destroy(private_nm_plugin_t *this)
        }
        charon->credentials->remove_set(charon->credentials, &this->creds->set);
        this->creds->destroy(this->creds);
+       charon->attributes->remove_handler(charon->attributes, &this->handler->handler);
+       this->handler->destroy(this->handler);
        free(this);
 }
 
@@ -99,8 +107,10 @@ plugin_t *plugin_create()
        }
        
        this->creds = nm_creds_create();
+       this->handler = nm_handler_create();
        charon->credentials->add_set(charon->credentials, &this->creds->set);
-       this->plugin = nm_strongswan_plugin_new(this->creds);
+       charon->attributes->add_handler(charon->attributes, &this->handler->handler);
+       this->plugin = nm_strongswan_plugin_new(this->creds, this->handler);
        if (!this->plugin)
        {
                DBG1(DBG_CFG, "DBUS binding failed");
index abe55eb..8131ba1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008-2009 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -34,10 +34,16 @@ G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
  * Private data of NMStrongswanPlugin
  */
 typedef struct {
+       /* implements bus listener interface */
        listener_t listener;
+       /* IKE_SA we are listening on */
        ike_sa_t *ike_sa;
+       /* backref to public plugin */
        NMVPNPlugin *plugin;
+       /* credentials to use for authentication */
        nm_creds_t *creds;
+       /* attribute handler for DNS/NBNS server information */
+       nm_handler_t *handler;
 } NMStrongswanPluginPrivate;
 
 #define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
@@ -45,6 +51,31 @@ typedef struct {
                                NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
 
 /**
+ * convert enumerated handler chunks to a UINT_ARRAY GValue
+ */
+static GValue* handler_to_val(nm_handler_t *handler,
+                                                        configuration_attribute_type_t type)
+{
+       GValue *val;
+       GArray *array;
+       enumerator_t *enumerator;
+       chunk_t chunk;
+       
+       enumerator = handler->create_enumerator(handler, type);
+       array = g_array_new (FALSE, TRUE, sizeof (guint32));
+       while (enumerator->enumerate(enumerator, &chunk))
+       {
+               g_array_append_val (array, *(u_int32_t*)chunk.ptr);
+       }
+       enumerator->destroy(enumerator);
+       val = g_slice_new0 (GValue);
+       g_value_init (val, DBUS_TYPE_G_UINT_ARRAY);
+       g_value_set_boxed (val, array);
+       
+       return val;
+}
+
+/**
  * signal IPv4 config to NM, set connection as established
  */
 static void signal_ipv4_config(NMVPNPlugin *plugin,
@@ -53,10 +84,12 @@ static void signal_ipv4_config(NMVPNPlugin *plugin,
        GValue *val;
        GHashTable *config;
        host_t *me, *other;
+       nm_handler_t *handler;
        
        config = g_hash_table_new(g_str_hash, g_str_equal);
        me = ike_sa->get_my_host(ike_sa);
        other = ike_sa->get_other_host(ike_sa);
+       handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
        
        /* NM requires a tundev, but netkey does not use one. Passing an invalid
         * iface makes NM complain, but it accepts it without fiddling on eth0. */
@@ -75,6 +108,14 @@ static void signal_ipv4_config(NMVPNPlugin *plugin,
        g_value_set_uint(val, me->get_address(me).len * 8);
        g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
        
+       val = handler_to_val(handler, INTERNAL_IP4_DNS);
+       g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val);
+       
+       val = handler_to_val(handler, INTERNAL_IP4_NBNS);
+       g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val);
+       
+       handler->reset(handler);
+       
        nm_vpn_plugin_set_ip4_config(plugin, config);
 }
 
@@ -83,6 +124,10 @@ static void signal_ipv4_config(NMVPNPlugin *plugin,
  */
 static void signal_failure(NMVPNPlugin *plugin)
 {
+       nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler;
+       
+       handler->reset(handler);
+       
        /* TODO: NM does not handle this failure!? */
        nm_vpn_plugin_failure(plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); 
        nm_vpn_plugin_set_state(plugin, NM_VPN_SERVICE_STATE_STOPPED);
@@ -223,7 +268,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
                str = nm_setting_vpn_get_data_item(settings, "user");
                if (str)
                {
-                       user = identification_create_from_string(str);
+                       user = identification_create_from_string((char*)str);
                        str = nm_setting_vpn_get_secret(settings, "password");
                        creds->set_username_password(creds, user, (char*)str);
                }
@@ -494,7 +539,8 @@ static void nm_strongswan_plugin_class_init(
 /**
  * Object constructor
  */
-NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds)
+NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
+                                                                                        nm_handler_t *handler)
 {
        NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_object_new (
                                        NM_TYPE_STRONGSWAN_PLUGIN,
@@ -503,6 +549,7 @@ NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds)
        if (plugin)
        {
                NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->creds = creds;
+               NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler = handler;
        }
        return plugin;
 }
index bc6ebcf..03ce6ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008-2009 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 #include <nm-vpn-plugin.h>
 
 #include "nm_creds.h"
+#include "nm_handler.h"
 
 #define NM_TYPE_STRONGSWAN_PLUGIN            (nm_strongswan_plugin_get_type ())
 #define NM_STRONGSWAN_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPlugin))
@@ -50,6 +51,7 @@ typedef struct {
 
 GType nm_strongswan_plugin_get_type(void);
 
-NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds);
+NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
+                                                                                        nm_handler_t *handler);
 
 #endif /** NM_SERVICE_H_ @}*/