reimplemented dbus plugin for NetworkManager 0.7, renamed to nm
parent
2d87903db9
commit
6dbce9c803
16
configure.in
16
configure.in
|
@ -563,6 +563,14 @@ AC_ARG_ENABLE(
|
|||
fi]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
[nm],
|
||||
AS_HELP_STRING([--enable-nm],[enable NetworkManager plugin (default is NO).]),
|
||||
[if test x$enableval = xyes; then
|
||||
nm=true
|
||||
fi]
|
||||
)
|
||||
|
||||
dnl =========================
|
||||
dnl check required programs
|
||||
dnl =========================
|
||||
|
@ -705,6 +713,12 @@ if test x$uci = xtrue; then
|
|||
AC_CHECK_HEADER([uci.h],,[AC_MSG_ERROR([UCI header uci.h not found!])])
|
||||
fi
|
||||
|
||||
if test x$nm = xtrue; then
|
||||
PKG_CHECK_MODULES(nm, [NetworkManager libnm_glib_vpn gthread-2.0])
|
||||
AC_SUBST(nm_CFLAGS)
|
||||
AC_SUBST(nm_LIBS)
|
||||
fi
|
||||
|
||||
dnl ======================================
|
||||
dnl collect all plugins for libstrongswan
|
||||
dnl ======================================
|
||||
|
@ -798,6 +812,7 @@ dnl ==============
|
|||
AM_CONDITIONAL(USE_STROKE, test x$stroke = xtrue)
|
||||
AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue)
|
||||
AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue)
|
||||
AM_CONDITIONAL(USE_NM, test x$nm = xtrue)
|
||||
AM_CONDITIONAL(USE_UCI, test x$uci = xtrue)
|
||||
AM_CONDITIONAL(USE_SMP, test x$smp = xtrue)
|
||||
AM_CONDITIONAL(USE_SQL, test x$sql = xtrue)
|
||||
|
@ -876,6 +891,7 @@ AC_OUTPUT(
|
|||
src/charon/plugins/sql/Makefile
|
||||
src/charon/plugins/medsrv/Makefile
|
||||
src/charon/plugins/medcli/Makefile
|
||||
src/charon/plugins/nm/Makefile
|
||||
src/charon/plugins/uci/Makefile
|
||||
src/charon/plugins/stroke/Makefile
|
||||
src/charon/plugins/unit_tester/Makefile
|
||||
|
|
|
@ -180,6 +180,11 @@ if USE_MEDCLI
|
|||
PLUGINS += medcli
|
||||
endif
|
||||
|
||||
if USE_NM
|
||||
SUBDIRS += plugins/nm
|
||||
PLUGINS += nm
|
||||
endif
|
||||
|
||||
if USE_UCI
|
||||
SUBDIRS += plugins/uci
|
||||
PLUGINS += uci
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
|
||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${dbus_CFLAGS}
|
||||
|
||||
AM_CFLAGS = -rdynamic
|
||||
|
||||
plugin_LTLIBRARIES = libstrongswan-dbus.la
|
||||
|
||||
libstrongswan_dbus_la_SOURCES = dbus.h dbus.c
|
||||
libstrongswan_dbus_la_LDFLAGS = -module
|
||||
libstrongswan_dbus_la_LIBADD = ${dbus_LIBS}
|
||||
|
|
@ -1,422 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007 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$
|
||||
*/
|
||||
|
||||
#define DBUS_API_SUBJECT_TO_CHANGE
|
||||
#include <dbus/dbus.h>
|
||||
#include <NetworkManager/NetworkManager.h>
|
||||
#include <NetworkManager/NetworkManagerVPN.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dbus.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <daemon.h>
|
||||
#include <processing/jobs/callback_job.h>
|
||||
|
||||
|
||||
#define NM_DBUS_SERVICE_STRONG "org.freedesktop.NetworkManager.strongswan"
|
||||
#define NM_dbus_STRONG "org.freedesktop.NetworkManager.strongswan"
|
||||
#define NM_DBUS_PATH_STRONG "/org/freedesktop/NetworkManager/strongswan"
|
||||
|
||||
typedef struct private_dbus_t private_dbus_t;
|
||||
|
||||
/**
|
||||
* Private data of an dbus_t object.
|
||||
*/
|
||||
struct private_dbus_t {
|
||||
|
||||
/**
|
||||
* Public part of dbus_t object.
|
||||
*/
|
||||
dbus_t public;
|
||||
|
||||
/**
|
||||
* DBUS connection
|
||||
*/
|
||||
DBusConnection* conn;
|
||||
|
||||
/**
|
||||
* error value used here and there
|
||||
*/
|
||||
DBusError err;
|
||||
|
||||
/**
|
||||
* state of the daemon
|
||||
*/
|
||||
NMVPNState state;
|
||||
|
||||
/**
|
||||
* job accepting stroke messages
|
||||
*/
|
||||
callback_job_t *job;
|
||||
|
||||
/**
|
||||
* name of the currently active connection
|
||||
*/
|
||||
char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* set daemon state and send StateChange signal to the bus
|
||||
*/
|
||||
static void set_state(private_dbus_t *this, NMVPNState state)
|
||||
{
|
||||
DBusMessage* msg;
|
||||
|
||||
msg = dbus_message_new_signal(NM_DBUS_PATH_STRONG, NM_dbus_STRONG, NM_DBUS_VPN_SIGNAL_STATE_CHANGE);
|
||||
|
||||
if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &this->state,
|
||||
DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID) ||
|
||||
!dbus_connection_send(this->conn, msg, NULL))
|
||||
{
|
||||
DBG1(DBG_CFG, "unable to send DBUS StateChange signal");
|
||||
}
|
||||
dbus_connection_flush(this->conn);
|
||||
dbus_message_unref(msg);
|
||||
this->state = state;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get the child_cfg with the same name as the peer cfg
|
||||
*/
|
||||
static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
|
||||
{
|
||||
child_cfg_t *current, *found = NULL;
|
||||
iterator_t *iterator;
|
||||
|
||||
iterator = peer_cfg->create_child_cfg_iterator(peer_cfg);
|
||||
while (iterator->iterate(iterator, (void**)¤t))
|
||||
{
|
||||
if (streq(current->get_name(current), name))
|
||||
{
|
||||
found = current;
|
||||
found->get_ref(found);
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* process NetworkManagers startConnection method call
|
||||
*/
|
||||
static bool start_connection(private_dbus_t *this, DBusMessage* msg)
|
||||
{
|
||||
DBusMessage *reply, *signal;
|
||||
char *name, *user, **data, **passwords, **routes;
|
||||
int data_count, passwords_count, routes_count;
|
||||
u_int32_t me, other, p2p, netmask, mss;
|
||||
char *dev, *domain, *banner;
|
||||
const dbus_int32_t array[] = {};
|
||||
const dbus_int32_t *varray = array;
|
||||
peer_cfg_t *peer_cfg;
|
||||
child_cfg_t *child_cfg;
|
||||
status_t status = FAILED;
|
||||
|
||||
dbus_error_free(&this->err);
|
||||
|
||||
if (!dbus_message_get_args(msg, &this->err,
|
||||
DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &passwords_count,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data, &data_count,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &routes, &routes_count,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
set_state(this, NM_VPN_STATE_STARTING);
|
||||
|
||||
peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
|
||||
if (peer_cfg)
|
||||
{
|
||||
free(this->name);
|
||||
this->name = strdup(peer_cfg->get_name(peer_cfg));
|
||||
child_cfg = get_child_from_peer(peer_cfg, name);
|
||||
if (child_cfg)
|
||||
{
|
||||
status = charon->controller->initiate(charon->controller,
|
||||
peer_cfg, child_cfg, controller_cb_empty, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
peer_cfg->destroy(peer_cfg);
|
||||
}
|
||||
}
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
dbus_connection_send(this->conn, reply, NULL);
|
||||
dbus_message_unref(reply);
|
||||
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
|
||||
set_state(this, NM_VPN_STATE_STARTED);
|
||||
signal = dbus_message_new_signal(NM_DBUS_PATH_STRONG,
|
||||
NM_dbus_STRONG,
|
||||
NM_DBUS_VPN_SIGNAL_IP4_CONFIG);
|
||||
me = other = p2p = mss = netmask = 0;
|
||||
dev = domain = banner = "";
|
||||
if (dbus_message_append_args(signal,
|
||||
DBUS_TYPE_UINT32, &other,
|
||||
DBUS_TYPE_STRING, &dev,
|
||||
DBUS_TYPE_UINT32, &me,
|
||||
DBUS_TYPE_UINT32, &p2p,
|
||||
DBUS_TYPE_UINT32, &netmask,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0,
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &varray, 0,
|
||||
DBUS_TYPE_UINT32, &mss,
|
||||
DBUS_TYPE_STRING, &domain,
|
||||
DBUS_TYPE_STRING, &banner, DBUS_TYPE_INVALID))
|
||||
{
|
||||
dbus_connection_send(this->conn, signal, NULL);
|
||||
}
|
||||
dbus_message_unref(signal);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_state(this, NM_VPN_STATE_STOPPED);
|
||||
}
|
||||
|
||||
dbus_connection_flush(this->conn);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* process NetworkManagers stopConnection method call
|
||||
*/
|
||||
static bool stop_connection(private_dbus_t *this, DBusMessage* msg)
|
||||
{
|
||||
u_int32_t id;
|
||||
enumerator_t *enumerator;
|
||||
ike_sa_t *ike_sa;
|
||||
|
||||
if (this->name == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_error_free(&this->err);
|
||||
|
||||
set_state(this, NM_VPN_STATE_STOPPING);
|
||||
|
||||
enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
|
||||
while (enumerator->enumerate(enumerator, (void**)&ike_sa))
|
||||
{
|
||||
child_sa_t *child_sa;
|
||||
iterator_t *children;
|
||||
|
||||
if (this->name && streq(this->name, ike_sa->get_name(ike_sa)))
|
||||
{
|
||||
id = ike_sa->get_unique_id(ike_sa);
|
||||
enumerator->destroy(enumerator);
|
||||
charon->controller->terminate_ike(charon->controller, id, NULL, NULL);
|
||||
set_state(this, NM_VPN_STATE_STOPPED);
|
||||
return TRUE;;
|
||||
}
|
||||
children = ike_sa->create_child_sa_iterator(ike_sa);
|
||||
while (children->iterate(children, (void**)&child_sa))
|
||||
{
|
||||
if (this->name && streq(this->name, child_sa->get_name(child_sa)))
|
||||
{
|
||||
id = child_sa->get_reqid(child_sa);
|
||||
children->destroy(children);
|
||||
enumerator->destroy(enumerator);
|
||||
charon->controller->terminate_child(charon->controller, id, NULL, NULL);
|
||||
set_state(this, NM_VPN_STATE_STOPPED);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
children->destroy(children);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
set_state(this, NM_VPN_STATE_STOPPED);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* process NetworkManagers getState method call
|
||||
*/
|
||||
static bool get_state(private_dbus_t *this, DBusMessage* msg)
|
||||
{
|
||||
DBusMessage* reply;
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
if (!reply || !dbus_message_append_args(reply,
|
||||
DBUS_TYPE_UINT32, &this->state,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
dbus_connection_send(this->conn, reply, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming messages
|
||||
*/
|
||||
static DBusHandlerResult message_handler(DBusConnection *con, DBusMessage *msg,
|
||||
private_dbus_t *this)
|
||||
{
|
||||
bool handled;
|
||||
|
||||
if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
|
||||
"startConnection"))
|
||||
{
|
||||
handled = start_connection(this, msg);
|
||||
}
|
||||
else if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
|
||||
"stopConnection"))
|
||||
{
|
||||
handled = stop_connection(this, msg);
|
||||
}
|
||||
else if (dbus_message_is_method_call(msg, NM_dbus_STRONG,
|
||||
"getState"))
|
||||
{
|
||||
handled = get_state(this, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_CFG, "ignoring DBUS message %s.%s",
|
||||
dbus_message_get_interface(msg), dbus_message_get_member(msg));
|
||||
handled = FALSE;
|
||||
}
|
||||
|
||||
if (handled)
|
||||
{
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle received signals
|
||||
|
||||
static DBusHandlerResult signal_handler(DBusConnection *con, DBusMessage *msg,
|
||||
private_dbus_t *this)
|
||||
{
|
||||
bool handled;
|
||||
|
||||
if (dbus_message_is_signal(msg, NM_dbus, "VPNConnectionStateChange"))
|
||||
{
|
||||
NMVPNState state;
|
||||
char *name;
|
||||
|
||||
if (dbus_message_get_args(msg, &this->err, DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID))
|
||||
{
|
||||
DBG1(DBG_CFG, "got state %d for %s", state, name);
|
||||
}
|
||||
handled = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_CFG, "ignoring DBUS signal %s.%s",
|
||||
dbus_message_get_interface(msg), dbus_message_get_member(msg));
|
||||
handled = FALSE;
|
||||
}
|
||||
if (handled)
|
||||
{
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
} */
|
||||
|
||||
/**
|
||||
* dispatcher function processed by a seperate thread
|
||||
*/
|
||||
static job_requeue_t dispatch(private_dbus_t *this)
|
||||
{
|
||||
if (dbus_connection_read_write_dispatch(this->conn, -1))
|
||||
{
|
||||
return JOB_REQUEUE_DIRECT;
|
||||
}
|
||||
return JOB_REQUEUE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of interface_t.destroy.
|
||||
*/
|
||||
static void destroy(private_dbus_t *this)
|
||||
{
|
||||
this->job->cancel(this->job);
|
||||
dbus_connection_close(this->conn);
|
||||
dbus_error_free(&this->err);
|
||||
dbus_shutdown();
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header file
|
||||
*/
|
||||
plugin_t *plugin_create()
|
||||
{
|
||||
int ret;
|
||||
DBusObjectPathVTable v = {NULL, (void*)&message_handler, NULL, NULL, NULL, NULL};
|
||||
private_dbus_t *this = malloc_thing(private_dbus_t);
|
||||
|
||||
this->public.plugin.destroy = (void (*)(plugin_t*))destroy;
|
||||
|
||||
dbus_error_init(&this->err);
|
||||
this->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &this->err);
|
||||
if (dbus_error_is_set(&this->err))
|
||||
{
|
||||
DBG1(DBG_CFG, "unable to open DBUS connection: %s", this->err.message);
|
||||
charon->kill(charon, "DBUS initialization failed");
|
||||
}
|
||||
dbus_connection_set_exit_on_disconnect(this->conn, FALSE);
|
||||
|
||||
ret = dbus_bus_request_name(this->conn, NM_DBUS_SERVICE_STRONG,
|
||||
DBUS_NAME_FLAG_REPLACE_EXISTING , &this->err);
|
||||
if (dbus_error_is_set(&this->err))
|
||||
{
|
||||
DBG1(DBG_CFG, "unable to set DBUS name: %s", this->err.message);
|
||||
charon->kill(charon, "unable to set DBUS name");
|
||||
}
|
||||
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
|
||||
{
|
||||
charon->kill(charon, "DBUS name already owned");
|
||||
}
|
||||
if (!dbus_connection_register_object_path(this->conn, NM_DBUS_PATH_STRONG, &v, this))
|
||||
{
|
||||
charon->kill(charon, "unable to register DBUS message handler");
|
||||
}
|
||||
/*
|
||||
if (!dbus_connection_add_filter(this->conn, (void*)signal_handler, this, NULL))
|
||||
{
|
||||
charon->kill(charon, "unable to register DBUS signal handler");
|
||||
}
|
||||
|
||||
dbus_bus_add_match(this->conn, "type='signal', "
|
||||
"interface='" NM_dbus_VPN "',"
|
||||
"path='" NM_DBUS_PATH_VPN "'", &this->err);
|
||||
if (dbus_error_is_set (&this->err))
|
||||
{
|
||||
charon->kill(charon, "unable to add DBUS signal match");
|
||||
}*/
|
||||
|
||||
this->name = NULL;
|
||||
this->state = NM_VPN_STATE_INIT;
|
||||
set_state(this, NM_VPN_STATE_STOPPED);
|
||||
|
||||
this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
|
||||
charon->processor->queue_job(charon->processor, (job_t*)this->job);
|
||||
|
||||
return &this->public.plugin;
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<policy user="root">
|
||||
<allow own="org.freedesktop.NetworkManager.strongswan"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.NetworkManager.strongswan"/>
|
||||
<allow send_interface="org.freedesktop.NetworkManager.strongswan"/>
|
||||
</policy>
|
||||
<policy at_console="true">
|
||||
<allow send_destination="org.freedesktop.NetworkManager.strongswan"/>
|
||||
<allow send_interface="org.freedesktop.NetworkManager.strongswan"/>
|
||||
</policy>
|
||||
<policy context="default">
|
||||
<deny own="org.strongswan.charon"/>
|
||||
<deny send_destination="org.freedesktop.NetworkManager.strongswan"/>
|
||||
<deny send_interface="org.freedesktop.NetworkManager.strongswan"/>
|
||||
</policy>
|
||||
</busconfig>
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
[VPN Connection]
|
||||
name=strongSwan
|
||||
service=org.freedesktop.NetworkManager.strongswan
|
||||
program=/usr/local/libexec/ipsec/charon
|
||||
|
||||
[GNOME]
|
||||
auth-dialog=/home/martin/strongswan/trunk/src/networkmanager/nm_applet_auth
|
||||
properties=/home/martin/strongswan/trunk/src/networkmanager/strongswan.so
|
|
@ -1,11 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
char buf[1];
|
||||
printf("PASSWORDL\n");
|
||||
printf ("\n\n");
|
||||
//fread (buf, sizeof (char), sizeof (buf), stdin);
|
||||
return 0;
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007 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 <glade/glade.h>
|
||||
|
||||
#define NM_VPN_API_SUBJECT_TO_CHANGE
|
||||
#include <nm-vpn-ui-interface.h>
|
||||
|
||||
|
||||
typedef struct private_nm_applet_gui_t private_nm_applet_gui_t;
|
||||
|
||||
/**
|
||||
* Private data of an nm_applet_gui_t object.
|
||||
*/
|
||||
struct private_nm_applet_gui_t {
|
||||
|
||||
/**
|
||||
* Implements NetworkManagerVpnUI interface.
|
||||
*/
|
||||
NetworkManagerVpnUI public;
|
||||
|
||||
/**
|
||||
* callback registered by NM to update validity
|
||||
*/
|
||||
NetworkManagerVpnUIDialogValidityCallback callback;
|
||||
|
||||
/**
|
||||
* loaded Glade XML interface description
|
||||
*/
|
||||
GladeXML *xml;
|
||||
|
||||
/**
|
||||
* root widget to return to druid
|
||||
*/
|
||||
GtkWidget *widget;
|
||||
|
||||
/**
|
||||
* name of the connection
|
||||
*/
|
||||
GtkEntry *name;
|
||||
|
||||
/**
|
||||
* gateway address
|
||||
*/
|
||||
GtkEntry *gateway;
|
||||
|
||||
/**
|
||||
* username
|
||||
*/
|
||||
GtkEntry *user;
|
||||
};
|
||||
|
||||
static const char *get_display_name(private_nm_applet_gui_t *this)
|
||||
{
|
||||
return "strongSwan (IPsec/IKEv2)";
|
||||
}
|
||||
|
||||
static const char *get_service_name(private_nm_applet_gui_t *this)
|
||||
{
|
||||
return "org.freedesktop.NetworkManager.strongswan";
|
||||
}
|
||||
|
||||
static GtkWidget *get_widget(private_nm_applet_gui_t *this, GSList *properties,
|
||||
GSList *routes, const char *connection_name)
|
||||
{
|
||||
GSList *i;
|
||||
|
||||
gtk_entry_set_text(this->name, "");
|
||||
gtk_entry_set_text(this->gateway, "");
|
||||
gtk_entry_set_text(this->user, "");
|
||||
|
||||
if (connection_name)
|
||||
{
|
||||
gtk_entry_set_text(this->name, connection_name);
|
||||
}
|
||||
|
||||
while (properties)
|
||||
{
|
||||
const char *key;
|
||||
const char *value;
|
||||
|
||||
key = properties->data;
|
||||
properties = g_slist_next(properties);
|
||||
if (properties)
|
||||
{
|
||||
value = properties->data;
|
||||
if (strcmp(key, "gateway") == 0)
|
||||
{
|
||||
gtk_entry_set_text(this->gateway, value);
|
||||
}
|
||||
if (strcmp(key, "user") == 0)
|
||||
{
|
||||
gtk_entry_set_text(this->user, value);
|
||||
}
|
||||
properties = g_slist_next(properties);
|
||||
}
|
||||
}
|
||||
return this->widget;
|
||||
}
|
||||
|
||||
static GSList *get_properties(private_nm_applet_gui_t *this)
|
||||
{
|
||||
GSList *props = NULL;
|
||||
|
||||
props = g_slist_append(props, g_strdup("gateway"));
|
||||
props = g_slist_append(props, g_strdup(gtk_entry_get_text(this->gateway)));
|
||||
props = g_slist_append(props, g_strdup("user"));
|
||||
props = g_slist_append(props, g_strdup(gtk_entry_get_text(this->user)));
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
static GSList *get_routes(private_nm_applet_gui_t *this)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *get_connection_name(private_nm_applet_gui_t *this)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = gtk_entry_get_text(this->name);
|
||||
if (name != NULL)
|
||||
{
|
||||
return g_strdup(name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean is_valid(private_nm_applet_gui_t *this)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void set_validity_changed_callback(private_nm_applet_gui_t *this,
|
||||
NetworkManagerVpnUIDialogValidityCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
this->callback = callback;
|
||||
}
|
||||
|
||||
static void get_confirmation_details(private_nm_applet_gui_t *this, gchar **retval)
|
||||
{
|
||||
*retval = g_strdup_printf("connection %s\n", gtk_entry_get_text(this->name));
|
||||
}
|
||||
|
||||
static gboolean can_export(private_nm_applet_gui_t *this)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean import_file (private_nm_applet_gui_t *this, const char *path)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean export(private_nm_applet_gui_t *this, GSList *properties,
|
||||
GSList *routes, const char *connection_name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NetworkManagerVpnUI* nm_vpn_properties_factory(void)
|
||||
{
|
||||
private_nm_applet_gui_t *this = g_new0(private_nm_applet_gui_t, 1);
|
||||
|
||||
this->public.get_display_name = (const char *(*)(NetworkManagerVpnUI *))get_display_name;
|
||||
this->public.get_service_name = (const char *(*) (NetworkManagerVpnUI *))get_service_name;
|
||||
this->public.get_widget = (GtkWidget *(*) (NetworkManagerVpnUI *self, GSList *, GSList *, const char *))get_widget;
|
||||
this->public.get_connection_name = (char *(*) (NetworkManagerVpnUI *))get_connection_name;
|
||||
this->public.get_properties = (GSList *(*) (NetworkManagerVpnUI *))get_properties;
|
||||
this->public.get_routes = (GSList *(*) (NetworkManagerVpnUI *))get_routes;
|
||||
this->public.set_validity_changed_callback = (void (*) (NetworkManagerVpnUI *, NetworkManagerVpnUIDialogValidityCallback, gpointer))set_validity_changed_callback;
|
||||
this->public.is_valid = (gboolean (*) (NetworkManagerVpnUI *))is_valid;
|
||||
this->public.get_confirmation_details = (void (*)(NetworkManagerVpnUI *, gchar **))get_confirmation_details;
|
||||
this->public.can_export = (gboolean (*) (NetworkManagerVpnUI *))can_export;
|
||||
this->public.import_file = (gboolean (*) (NetworkManagerVpnUI *, const char *))import_file;
|
||||
this->public.export = (gboolean (*) (NetworkManagerVpnUI *, GSList *, GSList *, const char *))export;
|
||||
this->public.data = NULL;
|
||||
|
||||
this->callback = NULL;
|
||||
this->xml = glade_xml_new("/home/martin/strongswan/trunk/src/charon/plugins/dbus/nm_applet_gui.xml", NULL, NULL);
|
||||
|
||||
if (this->xml != NULL)
|
||||
{
|
||||
this->widget = glade_xml_get_widget(this->xml, "main");
|
||||
this->name = GTK_ENTRY(glade_xml_get_widget(this->xml, "name"));
|
||||
this->gateway = GTK_ENTRY(glade_xml_get_widget(this->xml, "gateway"));
|
||||
this->user = GTK_ENTRY(glade_xml_get_widget(this->xml, "user"));
|
||||
|
||||
if (this->widget && this->name && this->gateway && this->user)
|
||||
{
|
||||
return &this->public;
|
||||
}
|
||||
}
|
||||
g_free(this);
|
||||
return NULL;
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.0 on Sat Mar 15 17:12:28 2008 -->
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window1">
|
||||
<child>
|
||||
<widget class="GtkTable" id="main">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="column_spacing">5</property>
|
||||
<property name="row_spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="user">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Username</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_CENTER</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="gateway">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Gateway</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_RIGHT</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="name">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Connection _name</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_FILL</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options">GTK_FILL</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon ${nm_CFLAGS}
|
||||
|
||||
AM_CFLAGS = -rdynamic
|
||||
|
||||
plugin_LTLIBRARIES = libstrongswan-nm.la
|
||||
libstrongswan_nm_la_SOURCES = \
|
||||
nm_plugin.h nm_plugin.c nm_service.h nm_service.c
|
||||
libstrongswan_nm_la_LDFLAGS = -module
|
||||
libstrongswan_nm_la_LIBADD = ${nm_LIBS}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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_plugin.h"
|
||||
#include "nm_service.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <processing/jobs/callback_job.h>
|
||||
|
||||
typedef struct private_nm_plugin_t private_nm_plugin_t;
|
||||
|
||||
/**
|
||||
* private data of nm plugin
|
||||
*/
|
||||
struct private_nm_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
*/
|
||||
nm_plugin_t public;
|
||||
|
||||
GMainLoop *loop;
|
||||
};
|
||||
|
||||
/**
|
||||
* NM plugin processing routine, creates and handles NMVPNPlugin
|
||||
*/
|
||||
static job_requeue_t run(private_nm_plugin_t *this)
|
||||
{
|
||||
NMStrongswanPlugin *plugin;
|
||||
GMainLoop *loop;
|
||||
|
||||
plugin = nm_strongswan_plugin_new();
|
||||
|
||||
this->loop = loop = g_main_loop_new(NULL, FALSE);
|
||||
g_main_loop_run(loop);
|
||||
|
||||
g_main_loop_unref(loop);
|
||||
g_object_unref(plugin);
|
||||
|
||||
return JOB_REQUEUE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of plugin_t.destroy
|
||||
*/
|
||||
static void destroy(private_nm_plugin_t *this)
|
||||
{
|
||||
if (this->loop)
|
||||
{
|
||||
g_main_loop_quit(this->loop);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* see header file
|
||||
*/
|
||||
plugin_t *plugin_create()
|
||||
{
|
||||
private_nm_plugin_t *this = malloc_thing(private_nm_plugin_t);
|
||||
|
||||
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
|
||||
|
||||
this->loop = NULL;
|
||||
g_type_init ();
|
||||
if (!g_thread_supported())
|
||||
{
|
||||
g_thread_init(NULL);
|
||||
}
|
||||
|
||||
charon->processor->queue_job(charon->processor,
|
||||
(job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL));
|
||||
|
||||
return &this->public.plugin;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2008 Martin Willi
|
||||
* Copyright (C) 2008 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -11,30 +11,29 @@
|
|||
* 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 dbus dbus
|
||||
* @defgroup nm nm
|
||||
* @ingroup cplugins
|
||||
*
|
||||
* @defgroup dbus_i dbus
|
||||
* @{ @ingroup dbus
|
||||
* @defgroup nm_plugin nm_plugin
|
||||
* @{ @ingroup nm
|
||||
*/
|
||||
|
||||
#ifndef DBUS_H_
|
||||
#define DBUS_H_
|
||||
#ifndef NM_PLUGIN_H_
|
||||
#define NM_PLUGIN_H_
|
||||
|
||||
#include <plugins/plugin.h>
|
||||
|
||||
typedef struct dbus_t dbus_t;
|
||||
typedef struct nm_plugin_t nm_plugin_t;
|
||||
|
||||
/**
|
||||
* NetworkManager DBUS control plugin.
|
||||
*
|
||||
* This plugin uses a DBUS connection. It is designed to work in conjuction
|
||||
* with NetworkManager to configure and control the daemon.
|
||||
* NetworkManager integration plugin.
|
||||
*/
|
||||
struct dbus_t {
|
||||
struct nm_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
|
@ -43,8 +42,8 @@ struct dbus_t {
|
|||
};
|
||||
|
||||
/**
|
||||
* Create a dbus plugin instance.
|
||||
* Create a nm_plugin instance.
|
||||
*/
|
||||
plugin_t *plugin_create();
|
||||
|
||||
#endif /* DBUS_H_ @}*/
|
||||
#endif /* NM_PLUGIN_H_ @}*/
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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-setting-vpn.h>
|
||||
#include <nm-setting-vpn-properties.h>
|
||||
#include "nm_service.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <utils/host.h>
|
||||
#include <utils/identification.h>
|
||||
#include <config/peer_cfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define CONFIG_NAME "NetworkManager"
|
||||
|
||||
G_DEFINE_TYPE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_PLUGIN)
|
||||
|
||||
/**
|
||||
* Private data of NMStrongswanPlugin
|
||||
*/
|
||||
typedef struct {
|
||||
bus_listener_t listener;
|
||||
ike_sa_t *ike_sa;
|
||||
NMVPNPlugin *plugin;
|
||||
} NMStrongswanPluginPrivate;
|
||||
|
||||
#define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((o), \
|
||||
NM_TYPE_STRONGSWAN_PLUGIN, NMStrongswanPluginPrivate))
|
||||
|
||||
/**
|
||||
* convert a traffic selector address range to subnet and its mask.
|
||||
*/
|
||||
static u_int ts2subnet(traffic_selector_t* ts, u_int8_t *mask)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
from = ts->get_from_address(ts);
|
||||
to = ts->get_to_address(ts);
|
||||
|
||||
*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;
|
||||
}
|
||||
|
||||
/**
|
||||
* signal IPv4 config to NM, set connection as established
|
||||
*/
|
||||
static void signal_ipv4_config(NMVPNPlugin *plugin, child_sa_t *child_sa)
|
||||
{
|
||||
linked_list_t *list;
|
||||
traffic_selector_t *ts = NULL;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
list = child_sa->get_traffic_selectors(child_sa, FALSE);
|
||||
enumerator = list->create_enumerator(list);
|
||||
while (enumerator->enumerate(enumerator, &ts))
|
||||
{
|
||||
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);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bus listen function to wait for SA establishing
|
||||
*/
|
||||
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)
|
||||
{
|
||||
NMStrongswanPluginPrivate *private = (NMStrongswanPluginPrivate*)listener;
|
||||
|
||||
if (private->ike_sa == ike_sa)
|
||||
{
|
||||
switch (signal)
|
||||
{
|
||||
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:
|
||||
nm_vpn_plugin_failure(private->plugin,
|
||||
NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
|
||||
/* TODO: NM does not react on this failure!? So additionaly
|
||||
* reset state */
|
||||
nm_vpn_plugin_set_state(private->plugin,
|
||||
NM_VPN_SERVICE_STATE_STOPPED);
|
||||
return FALSE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a string from a hash table using a given key
|
||||
*/
|
||||
static char* get_str(GHashTable *hash, char *key)
|
||||
{
|
||||
GValue *value;
|
||||
|
||||
value = g_hash_table_lookup(hash, key);
|
||||
if (G_VALUE_TYPE (value) == G_TYPE_STRING)
|
||||
{
|
||||
return (char*)g_value_get_string(value);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect function called from NM via DBUS
|
||||
*/
|
||||
static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
GError **err)
|
||||
{
|
||||
NMSettingVPNProperties *properties;
|
||||
identification_t *user = NULL;
|
||||
char *address, *str;
|
||||
ike_cfg_t *ike_cfg;
|
||||
peer_cfg_t *peer_cfg;
|
||||
child_cfg_t *child_cfg;
|
||||
traffic_selector_t *ts;
|
||||
ike_sa_t *ike_sa;
|
||||
|
||||
/**
|
||||
* Read parameters
|
||||
*/
|
||||
properties = NM_SETTING_VPN_PROPERTIES(
|
||||
nm_connection_get_setting(connection, NM_TYPE_SETTING_VPN_PROPERTIES));
|
||||
|
||||
if (!properties)
|
||||
{
|
||||
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
|
||||
"%s", "Invalid arguments.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DBG2(DBG_CFG, "received NetworkManager connection: %s",
|
||||
nm_setting_to_string(NM_SETTING(properties)));
|
||||
|
||||
str = get_str(properties->data, "user");
|
||||
if (str)
|
||||
{
|
||||
user = identification_create_from_string(str);
|
||||
}
|
||||
if (!user)
|
||||
{
|
||||
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
|
||||
"Username '%s' invalid.", str);
|
||||
return FALSE;
|
||||
}
|
||||
address = get_str(properties->data, "address");
|
||||
if (!address || !*address)
|
||||
{
|
||||
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
|
||||
"Gateway address missing.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up configurations
|
||||
*/
|
||||
ike_cfg = ike_cfg_create(TRUE, TRUE, "0.0.0.0", address);
|
||||
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
|
||||
peer_cfg = peer_cfg_create(CONFIG_NAME, 2, ike_cfg, user,
|
||||
identification_create_from_encoding(ID_ANY, chunk_empty),
|
||||
CERT_SEND_IF_ASKED, UNIQUE_REPLACE, CONF_AUTH_PUBKEY,
|
||||
0, 0, 1, /* EAP method, vendor, keyingtries */
|
||||
18000, 0, /* rekey 5h, reauth none */
|
||||
600, 600, /* jitter, over 10min */
|
||||
TRUE, 0, /* mobike, DPD */
|
||||
host_create_from_string("0.0.0.0", 0), /* virtual ip */
|
||||
NULL, FALSE, NULL, NULL); /* pool, mediation */
|
||||
child_cfg = child_cfg_create(CONFIG_NAME,
|
||||
3600, 3000, /* lifetime 1h, rekey 50min */
|
||||
300, /* jitter 5min */
|
||||
NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
|
||||
ACTION_NONE, ACTION_NONE, FALSE); /* ipcomp */
|
||||
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
|
||||
ts = traffic_selector_create_dynamic(0, 0, 65535);
|
||||
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
|
||||
ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
|
||||
"0.0.0.0", 0,
|
||||
"255.255.255.255", 65535);
|
||||
child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
|
||||
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
|
||||
|
||||
/**
|
||||
* Start to initiate
|
||||
*/
|
||||
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
|
||||
peer_cfg);
|
||||
if (!ike_sa->get_peer_cfg(ike_sa))
|
||||
{
|
||||
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
|
||||
}
|
||||
else
|
||||
{
|
||||
peer_cfg->destroy(peer_cfg);
|
||||
}
|
||||
if (ike_sa->initiate(ike_sa, child_cfg) != SUCCESS)
|
||||
{
|
||||
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
|
||||
|
||||
g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
|
||||
"Initiating failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener
|
||||
*/
|
||||
NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->ike_sa = ike_sa;
|
||||
charon->bus->add_listener(charon->bus,
|
||||
&NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->listener);
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* NeedSecrets called from NM via DBUS
|
||||
*/
|
||||
static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
|
||||
char **setting_name, GError **error)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect called from NM via DBUS
|
||||
*/
|
||||
static gboolean disconnect(NMVPNPlugin *plugin, GError **err)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
ike_sa_t *ike_sa;
|
||||
u_int id;
|
||||
|
||||
enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
|
||||
while (enumerator->enumerate(enumerator, &ike_sa))
|
||||
{
|
||||
if (streq(CONFIG_NAME, ike_sa->get_name(ike_sa)))
|
||||
{
|
||||
id = ike_sa->get_unique_id(ike_sa);
|
||||
enumerator->destroy(enumerator);
|
||||
charon->controller->terminate_ike(charon->controller, id,
|
||||
controller_cb_empty, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializer
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*/
|
||||
static void nm_strongswan_plugin_class_init(
|
||||
NMStrongswanPluginClass *strongswan_class)
|
||||
{
|
||||
NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS(strongswan_class);
|
||||
|
||||
g_type_class_add_private(G_OBJECT_CLASS(strongswan_class),
|
||||
sizeof(NMStrongswanPluginPrivate));
|
||||
parent_class->connect = connect_;
|
||||
parent_class->need_secrets = need_secrets;
|
||||
parent_class->disconnect = disconnect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object constructor
|
||||
*/
|
||||
NMStrongswanPlugin *nm_strongswan_plugin_new(void)
|
||||
{
|
||||
return (NMStrongswanPlugin *)g_object_new (
|
||||
NM_TYPE_STRONGSWAN_PLUGIN, NM_VPN_PLUGIN_DBUS_SERVICE_NAME,
|
||||
NM_DBUS_SERVICE_STRONGSWAN, NULL);
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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_service nm_service
|
||||
* @{ @ingroup nm
|
||||
*/
|
||||
|
||||
#ifndef NM_SERVICE_H_
|
||||
#define NM_SERVICE_H_
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib-object.h>
|
||||
#include <nm-vpn-plugin.h>
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
|
||||
#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))
|
||||
#define NM_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass))
|
||||
#define NM_IS_STRONGSWAN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN))
|
||||
#define NM_IS_STRONGSWAN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_STRONGSWAN_PLUGIN))
|
||||
#define NM_STRONGSWAN_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_STRONGSWAN_PLUGIN, NMSTRONGSWANPluginClass))
|
||||
|
||||
#define NM_DBUS_SERVICE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
|
||||
#define NM_DBUS_INTERFACE_STRONGSWAN "org.freedesktop.NetworkManager.strongswan"
|
||||
#define NM_DBUS_PATH_STRONGSWAN "/org/freedesktop/NetworkManager/strongswan"
|
||||
|
||||
typedef struct {
|
||||
NMVPNPlugin parent;
|
||||
} NMStrongswanPlugin;
|
||||
|
||||
typedef struct {
|
||||
NMVPNPluginClass parent;
|
||||
} NMStrongswanPluginClass;
|
||||
|
||||
GType nm_strongswan_plugin_get_type(void);
|
||||
|
||||
NMStrongswanPlugin *nm_strongswan_plugin_new(void);
|
||||
|
||||
#endif /* NM_SERVICE_H_ */
|
Loading…
Reference in New Issue