summaryrefslogtreecommitdiff
path: root/src/charon/plugins/nm
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/plugins/nm')
-rw-r--r--src/charon/plugins/nm/Makefile.am2
-rw-r--r--src/charon/plugins/nm/Makefile.in2
-rw-r--r--src/charon/plugins/nm/nm_creds.c38
-rw-r--r--src/charon/plugins/nm/nm_service.c154
4 files changed, 89 insertions, 107 deletions
diff --git a/src/charon/plugins/nm/Makefile.am b/src/charon/plugins/nm/Makefile.am
index 107ca1a31..bb5436443 100644
--- a/src/charon/plugins/nm/Makefile.am
+++ b/src/charon/plugins/nm/Makefile.am
@@ -25,4 +25,4 @@ EXTRA_DIST = gnome/configure gnome/po/LINGUAS gnome/po/POTFILES.in gnome/po/Make
gnome/config.sub gnome/missing
gnome/configure : gnome/configure.in
- cd gnome && ./autogen.sh; cd ..
+ (cd `dirname $<` && ./autogen.sh)
diff --git a/src/charon/plugins/nm/Makefile.in b/src/charon/plugins/nm/Makefile.in
index 46e4ab851..4f75da14f 100644
--- a/src/charon/plugins/nm/Makefile.in
+++ b/src/charon/plugins/nm/Makefile.in
@@ -513,7 +513,7 @@ uninstall-am: uninstall-pluginLTLIBRARIES
gnome/configure : gnome/configure.in
- cd gnome && ./autogen.sh; cd ..
+ (cd `dirname $<` && ./autogen.sh)
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/src/charon/plugins/nm/nm_creds.c b/src/charon/plugins/nm/nm_creds.c
index f165653ae..e7cd640a7 100644
--- a/src/charon/plugins/nm/nm_creds.c
+++ b/src/charon/plugins/nm/nm_creds.c
@@ -15,12 +15,10 @@
* $Id$
*/
-#define _GNU_SOURCE
-#include <pthread.h>
-
#include "nm_creds.h"
#include <daemon.h>
+#include <utils/mutex.h>
typedef struct private_nm_creds_t private_nm_creds_t;
@@ -62,7 +60,7 @@ struct private_nm_creds_t {
/**
* read/write lock
*/
- pthread_rwlock_t lock;
+ rwlock_t *lock;
};
/**
@@ -91,10 +89,10 @@ static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
}
public->destroy(public);
}
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_cleaner(
enumerator_create_single(this->usercert, NULL),
- (void*)pthread_rwlock_unlock, &this->lock);
+ (void*)this->lock->unlock, this->lock);
}
/**
@@ -138,9 +136,9 @@ static enumerator_t* create_cert_enumerator(private_nm_creds_t *this,
}
public->destroy(public);
}
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_cleaner(enumerator_create_single(this->cert, NULL),
- (void*)pthread_rwlock_unlock, &this->lock);
+ (void*)this->lock->unlock, this->lock);
}
/**
@@ -167,9 +165,9 @@ static enumerator_t* create_private_enumerator(private_nm_creds_t *this,
return NULL;
}
}
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
return enumerator_create_cleaner(enumerator_create_single(this->key, NULL),
- (void*)pthread_rwlock_unlock, &this->lock);
+ (void*)this->lock->unlock, this->lock);
}
/**
@@ -205,7 +203,7 @@ static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key,
static void shared_destroy(shared_enumerator_t *this)
{
this->key->destroy(this->key);
- pthread_rwlock_unlock(&this->this->lock);
+ this->this->lock->unlock(this->this->lock);
free(this);
}
/**
@@ -235,7 +233,7 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
enumerator->public.destroy = (void*)shared_destroy;
enumerator->this = this;
enumerator->done = FALSE;
- pthread_rwlock_rdlock(&this->lock);
+ this->lock->read_lock(this->lock);
enumerator->key = shared_key_create(type,
chunk_clone(chunk_create(this->pass,
strlen(this->pass))));
@@ -247,10 +245,10 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this,
*/
static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
{
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
DESTROY_IF(this->cert);
this->cert = cert;
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -259,14 +257,14 @@ static void set_certificate(private_nm_creds_t *this, certificate_t *cert)
static void set_username_password(private_nm_creds_t *this, identification_t *id,
char *password)
{
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
DESTROY_IF(this->user);
/* for EAP authentication, we use always use ID_EAP type */
this->user = identification_create_from_encoding(ID_EAP,
id->get_encoding(id));
free(this->pass);
this->pass = password ? strdup(password) : NULL;
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -275,12 +273,12 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id
static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert,
private_key_t *key)
{
- pthread_rwlock_wrlock(&this->lock);
+ this->lock->write_lock(this->lock);
DESTROY_IF(this->key);
DESTROY_IF(this->usercert);
this->key = key;
this->usercert = cert;
- pthread_rwlock_unlock(&this->lock);
+ this->lock->unlock(this->lock);
}
/**
@@ -306,7 +304,7 @@ static void clear(private_nm_creds_t *this)
static void destroy(private_nm_creds_t *this)
{
clear(this);
- pthread_rwlock_destroy(&this->lock);
+ this->lock->destroy(this->lock);
free(this);
}
@@ -328,7 +326,7 @@ nm_creds_t *nm_creds_create()
this->public.clear = (void(*)(nm_creds_t*))clear;
this->public.destroy = (void(*)(nm_creds_t*))destroy;
- pthread_rwlock_init(&this->lock, NULL);
+ this->lock = rwlock_create(RWLOCK_DEFAULT);
this->cert = NULL;
this->user = NULL;
diff --git a/src/charon/plugins/nm/nm_service.c b/src/charon/plugins/nm/nm_service.c
index fbc094a3b..f90bfa448 100644
--- a/src/charon/plugins/nm/nm_service.c
+++ b/src/charon/plugins/nm/nm_service.c
@@ -34,7 +34,7 @@ G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
* Private data of NMStrongswanPlugin
*/
typedef struct {
- bus_listener_t listener;
+ listener_t listener;
ike_sa_t *ike_sa;
NMVPNPlugin *plugin;
nm_creds_t *creds;
@@ -45,109 +45,88 @@ typedef struct {
NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
/**
- * convert a traffic selector address range to subnet and its mask.
+ * signal IPv4 config to NM, set connection as established
*/
-static u_int ts2subnet(traffic_selector_t* ts, u_int8_t *mask)
+static void signal_ipv4_config(NMVPNPlugin *plugin,
+ ike_sa_t *ike_sa, child_sa_t *child_sa)
{
- /* there is no way to do this cleanly, as the address range may
- * be anything else but a subnet. We use from_addr as subnet
- * and try to calculate a usable subnet mask.
- */
- int byte, bit, net;
- bool found = FALSE;
- chunk_t from, to;
- size_t size = (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) ? 4 : 16;
+ GValue *val;
+ GHashTable *config;
+ host_t *me, *other;
- from = ts->get_from_address(ts);
- to = ts->get_to_address(ts);
+ 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);
- *mask = (size * 8);
- /* go trough all bits of the addresses, beginning in the front.
- * as long as they are equal, the subnet gets larger
- */
- for (byte = 0; byte < size; byte++)
- {
- for (bit = 7; bit >= 0; bit--)
- {
- if ((1<<bit & from.ptr[byte]) != (1<<bit & to.ptr[byte]))
- {
- *mask = ((7 - bit) + (byte * 8));
- found = TRUE;
- break;
- }
- }
- if (found)
- {
- break;
- }
- }
- net = *(u_int32_t*)from.ptr;
- chunk_free(&from);
- chunk_free(&to);
- return net;
+ /* 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. */
+ val = g_slice_new0 (GValue);
+ g_value_init (val, G_TYPE_STRING);
+ g_value_set_string (val, "none");
+ g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val);
+
+ val = g_slice_new0(GValue);
+ g_value_init(val, G_TYPE_UINT);
+ g_value_set_uint(val, *(u_int32_t*)me->get_address(me).ptr);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
+
+ val = g_slice_new0(GValue);
+ g_value_init(val, G_TYPE_UINT);
+ g_value_set_uint(val, me->get_address(me).len * 8);
+ g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
+
+ nm_vpn_plugin_set_ip4_config(plugin, config);
}
/**
- * signal IPv4 config to NM, set connection as established
+ * signal failure to NM, connecting failed
*/
-static void signal_ipv4_config(NMVPNPlugin *plugin, child_sa_t *child_sa)
+static void signal_failure(NMVPNPlugin *plugin)
{
- linked_list_t *list;
- traffic_selector_t *ts = NULL;
- enumerator_t *enumerator;
+ /* 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);
+}
+
+/**
+ * Implementation of listener_t.ike_state_change
+ */
+static bool ike_state_change(listener_t *listener, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
+{
+ NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
- list = child_sa->get_traffic_selectors(child_sa, FALSE);
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &ts))
+ if (private->ike_sa == ike_sa)
{
- GValue *val;
- GHashTable *config;
- u_int8_t mask;
-
- config = g_hash_table_new(g_str_hash, g_str_equal);
-
- val = g_slice_new0(GValue);
- g_value_init(val, G_TYPE_UINT);
- g_value_set_uint(val, ts2subnet(ts, &mask));
- g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val);
-
- val = g_slice_new0(GValue);
- g_value_init(val, G_TYPE_UINT);
- g_value_set_uint(val, mask);
- g_hash_table_insert(config, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX, val);
-
- nm_vpn_plugin_set_ip4_config(plugin, config);
+ switch (state)
+ {
+ case IKE_DESTROYING:
+ signal_failure(private->plugin);
+ return FALSE;
+ default:
+ break;
+ }
}
- enumerator->destroy(enumerator);
+ return TRUE;
}
/**
- * Bus listen function to wait for SA establishing
+ * Implementation of listener_t.child_state_change
*/
-bool listen_bus(bus_listener_t *listener, signal_t signal, level_t level,
- int thread, ike_sa_t *ike_sa, void *data,
- char* format, va_list args)
+static bool child_state_change(listener_t *listener, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
{
NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
-
+
if (private->ike_sa == ike_sa)
{
- switch (signal)
+ switch (state)
{
- case CHD_UP_SUCCESS:
- if (data)
- {
- signal_ipv4_config(private->plugin, (child_sa_t*)data);
- return FALSE;
- }
- /* FALL */
- case IKE_UP_FAILED:
- case CHD_UP_FAILED:
- /* TODO: NM does not handle this failure!?
- nm_vpn_plugin_failure(private->plugin,
- NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); */
- nm_vpn_plugin_set_state(private->plugin,
- NM_VPN_SERVICE_STATE_STOPPED);
+ case CHILD_INSTALLED:
+ signal_ipv4_config(private->plugin, ike_sa, child_sa);
+ return FALSE;
+ case CHILD_DESTROYING:
+ signal_failure(private->plugin);
return FALSE;
default:
break;
@@ -462,8 +441,13 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
*/
static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
{
- NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->plugin = NM_VPN_PLUGIN(plugin);
- NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->listener.signal = listen_bus;
+ NMStrongswanPluginPrivate *private;
+
+ private = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
+ private->plugin = NM_VPN_PLUGIN(plugin);
+ memset(&private->listener.log, 0, sizeof(listener_t));
+ private->listener.ike_state_change = ike_state_change;
+ private->listener.child_state_change = child_state_change;
}
/**