2005-09-07 Dan Williams <dcbw@redhat.com>

* The great VPN Manager rewrite of 2005


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@946 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams 2005-09-07 19:12:52 +00:00
parent 88e3591ad3
commit 5c46be7149
25 changed files with 1655 additions and 653 deletions

View file

@ -1,3 +1,7 @@
2005-09-07 Dan Williams <dcbw@redhat.com>
* The great VPN Manager rewrite of 2005
2005-09-07 Christopher Aillon <caillon@redhat.com>
* gnome/applet/menu-items.c:

View file

@ -192,6 +192,22 @@ typedef enum NMVPNState
} NMVPNState;
/*
* VPN connection activation stages
*/
typedef enum NMVPNActStage
{
NM_VPN_ACT_STAGE_UNKNOWN = 0,
NM_VPN_ACT_STAGE_DISCONNECTED,
NM_VPN_ACT_STAGE_PREPARE,
NM_VPN_ACT_STAGE_CONNECT,
NM_VPN_ACT_STAGE_IP_CONFIG_GET,
NM_VPN_ACT_STAGE_ACTIVATED,
NM_VPN_ACT_STAGE_FAILED,
NM_VPN_ACT_STAGE_CANCELED
} NMVPNActStage;
/*
* Device activation stages
*/

View file

@ -36,43 +36,19 @@
static void nmwa_free_vpn_connections (NMWirelessApplet *applet);
/*
* nmwa_dbus_vpn_get_active_vpn_connection
*
* Get the active VPN connection from the dbus side of the applet
*
*/
VPNConnection *nmwa_dbus_vpn_get_active_vpn_connection (NMWirelessApplet *applet)
{
GSList *elt;
g_return_val_if_fail (applet != NULL, NULL);
for (elt = applet->vpn_connections; elt; elt = g_slist_next (elt))
{
VPNConnection *vpn = (VPNConnection*) elt->data;
NMVPNState vpn_state = nmwa_vpn_connection_get_state (vpn);
if (vpn_state == NM_VPN_STATE_STARTED)
return vpn;
}
return NULL;
}
/*
* nmwa_dbus_vpn_update_vpn_connection_state
*
* Sets the state for a dbus vpn connection and schedules a copy to the applet gui.
*/
void nmwa_dbus_vpn_update_vpn_connection_state (NMWirelessApplet *applet, const char *vpn_name, NMVPNState vpn_state)
void nmwa_dbus_vpn_update_vpn_connection_state (NMWirelessApplet *applet, const char *vpn_name, NMVPNActStage vpn_state)
{
VPNConnection *vpn;
g_return_if_fail (applet != NULL);
vpn = nmwa_vpn_connection_find_by_name (applet->vpn_connections, vpn_name);
if (vpn != NULL)
if ((vpn = nmwa_vpn_connection_find_by_name (applet->vpn_connections, vpn_name)))
nmwa_vpn_connection_set_state (vpn, vpn_state);
}
@ -106,7 +82,7 @@ static void nmwa_dbus_vpn_properties_cb (DBusPendingCall *pcall, void *user_data
const char * name;
const char * user_name;
const char * service;
NMVPNState state;
NMVPNActStage state;
dbus_uint32_t state_int;
g_return_if_fail (pcall != NULL);
@ -130,7 +106,7 @@ static void nmwa_dbus_vpn_properties_cb (DBusPendingCall *pcall, void *user_data
{
VPNConnection * vpn;
state = (NMVPNState) state_int;
state = (NMVPNActStage) state_int;
/* If its already there, update the service, otherwise add it to the list */
if ((vpn = nmwa_vpn_connection_find_by_name (applet->vpn_connections, name)))
@ -167,7 +143,7 @@ void nmwa_dbus_vpn_update_one_vpn_connection (NMWirelessApplet *applet, const ch
g_return_if_fail (applet != NULL);
g_return_if_fail (vpn_name != NULL);
nmwa_dbus_vpn_get_active_vpn_connection (applet);
nmwa_get_first_active_vpn_connection (applet);
if ((message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH_VPN, NM_DBUS_INTERFACE_VPN, "getVPNConnectionProperties")))
{
@ -241,7 +217,7 @@ void nmwa_dbus_vpn_update_vpn_connections (NMWirelessApplet *applet)
nmwa_free_vpn_connections (applet);
nmwa_dbus_vpn_get_active_vpn_connection (applet);
nmwa_get_first_active_vpn_connection (applet);
if ((message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH_VPN, NM_DBUS_INTERFACE_VPN, "getVPNConnections")))
{

View file

@ -33,6 +33,6 @@ void nmwa_dbus_vpn_remove_one_vpn_connection (NMWirelessApplet *applet, const
void nmwa_dbus_vpn_activate_connection (DBusConnection *connection, const char *name, GSList *passwords);
void nmwa_dbus_vpn_deactivate_connection (DBusConnection *connection);
void nmwa_dbus_vpn_update_vpn_connection_state (NMWirelessApplet *applet, const char *vpn_name, NMVPNState vpn_state);
void nmwa_dbus_vpn_update_vpn_connection_state (NMWirelessApplet *applet, const char *vpn_name, NMVPNActStage vpn_state);
#endif

View file

@ -224,12 +224,13 @@ static DBusHandlerResult nmwa_dbus_filter (DBusConnection *connection, DBusMessa
}
else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE_VPN, "VPNConnectionStateChange")) /* Active VPN connection changed */
{
char *name = NULL;
NMVPNState vpn_state;
dbus_uint32_t vpn_state_int;
char * name = NULL;
NMVPNActStage vpn_state;
dbus_uint32_t vpn_state_int;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_UINT32, &vpn_state_int, DBUS_TYPE_INVALID))
{
vpn_state = (NMVPNState) vpn_state_int;
vpn_state = (NMVPNActStage) vpn_state_int;
nmwa_dbus_vpn_update_vpn_connection_state (applet, name, vpn_state);
}
}

View file

@ -869,19 +869,23 @@ out:
}
VPNConnection* nmwa_get_active_vpn_connection (NMWirelessApplet *applet)
/*
* nmwa_get_first_active_vpn_connection
*
* Return the first active VPN connection, if any.
*
*/
VPNConnection *nmwa_get_first_active_vpn_connection (NMWirelessApplet *applet)
{
VPNConnection *vpn;
NMVPNState vpn_state;
GSList *elt;
VPNConnection * vpn;
NMVPNActStage vpn_state;
GSList * elt;
elt = applet->vpn_connections;
for (; elt; elt = g_slist_next (elt))
for (elt = applet->vpn_connections; elt; elt = g_slist_next (elt))
{
vpn = (VPNConnection*) elt->data;
vpn_state = nmwa_vpn_connection_get_state (vpn);
if (vpn_state == NM_VPN_STATE_STARTED)
if (vpn_state == NM_VPN_ACT_STAGE_ACTIVATED)
return vpn;
}
@ -899,7 +903,7 @@ static void nmwa_set_icon (NMWirelessApplet *applet, GdkPixbuf *new_icon)
composite = gdk_pixbuf_copy (new_icon);
vpn = nmwa_get_active_vpn_connection (applet);
vpn = nmwa_get_first_active_vpn_connection (applet);
if (vpn)
{
@ -1132,8 +1136,9 @@ done:
if (!applet->tooltips)
applet->tooltips = gtk_tooltips_new ();
vpn = nmwa_get_active_vpn_connection (applet);
if (vpn != NULL) {
vpn = nmwa_get_first_active_vpn_connection (applet);
if (vpn != NULL)
{
char *newtip;
char *vpntip;
@ -1313,8 +1318,8 @@ static void nmwa_menu_vpn_item_activate (GtkMenuItem *item, gpointer user_data)
VPNConnection *vpn = (VPNConnection *)tag;
const char *name = nmwa_vpn_connection_get_name (vpn);
GSList *passwords;
VPNConnection *active_vpn = nmwa_get_first_active_vpn_connection (applet);
VPNConnection *active_vpn = nmwa_get_active_vpn_connection (applet);
if (vpn != active_vpn)
{
char *gconf_key;
@ -1687,7 +1692,7 @@ static void nmwa_menu_add_vpn_menu (GtkWidget *menu, NMWirelessApplet *applet)
item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_VPN Connections")));
vpn_menu = GTK_MENU (gtk_menu_new ());
active_vpn = nmwa_get_active_vpn_connection (applet);
active_vpn = nmwa_get_first_active_vpn_connection (applet);
for (elt = applet->vpn_connections; elt; elt = g_slist_next (elt))
{

View file

@ -146,6 +146,7 @@ void nmwa_schedule_vpn_failure_dialog (NMWirelessApplet *applet, const char
void nmwa_schedule_vpn_login_banner_dialog (NMWirelessApplet *applet, const char *vpn_name, const char *banner);
NetworkDevice * nmwa_get_first_active_device (GSList *dev_list);
VPNConnection * nmwa_get_first_active_vpn_connection (NMWirelessApplet *applet);
NMWirelessScanMethod nmwa_gconf_get_wireless_scan_method (NMWirelessApplet *applet);

View file

@ -25,10 +25,10 @@
struct VPNConnection
{
int refcount;
char *name;
char *service;
NMVPNState state;
int refcount;
char * name;
char * service;
NMVPNActStage state;
};
@ -136,14 +136,14 @@ VPNConnection *nmwa_vpn_connection_find_by_name (GSList *list, const char *name)
return vpn;
}
NMVPNState nmwa_vpn_connection_get_state (VPNConnection *vpn)
NMVPNActStage nmwa_vpn_connection_get_state (VPNConnection *vpn)
{
g_return_val_if_fail (vpn != NULL, NM_VPN_STATE_UNKNOWN);
g_return_val_if_fail (vpn != NULL, NM_VPN_ACT_STAGE_UNKNOWN);
return vpn->state;
}
void nmwa_vpn_connection_set_state (VPNConnection *vpn, NMVPNState state)
void nmwa_vpn_connection_set_state (VPNConnection *vpn, NMVPNActStage state)
{
g_return_if_fail (vpn != NULL);

View file

@ -34,8 +34,8 @@ const char * nmwa_vpn_connection_get_name (VPNConnection *vpn);
const char * nmwa_vpn_connection_get_service (VPNConnection *vpn);
void nmwa_vpn_connection_set_service (VPNConnection *vpn, const char *service);
NMVPNState nmwa_vpn_connection_get_state (VPNConnection *vpn);
void nmwa_vpn_connection_set_state (VPNConnection *vpn, NMVPNState state);
NMVPNActStage nmwa_vpn_connection_get_state (VPNConnection *vpn);
void nmwa_vpn_connection_set_state (VPNConnection *vpn, NMVPNActStage state);
VPNConnection * nmwa_vpn_connection_find_by_name (GSList *list, const char *name);

View file

@ -166,8 +166,6 @@ nmwa_vpn_request_password (NMWirelessApplet *applet, const char *name, const cha
if (!retry)
argv[5] = NULL;
nm_debug ("retry = %d", retry);
child_status = -1;
if (!g_spawn_async_with_pipes (NULL, /* working_directory */

View file

@ -459,7 +459,7 @@ static void nm_data_free (NMData *data)
g_return_if_fail (data != NULL);
/* Kill any active VPN connection */
if (nm_vpn_manager_get_active_vpn_connection (data->vpn_manager))
if (nm_vpn_manager_get_vpn_act_request (data->vpn_manager))
nm_vpn_manager_deactivate_vpn_connection (data->vpn_manager);
/* Stop and destroy all devices */

View file

@ -46,6 +46,7 @@ typedef enum NMIntState
typedef struct NMDbusMethodList NMDbusMethodList;
typedef struct NMActRequest NMActRequest;
typedef struct NMVPNActRequest NMVPNActRequest;
typedef struct NMVPNManager NMVPNManager;
typedef struct NMDHCPManager NMDHCPManager;

View file

@ -413,10 +413,12 @@ static gboolean nm_policy_device_change_check (NMData *data)
/* Schedule new activation if the currently associated access point is not the "best" one
* or we've lost the link to the old access point.
*/
if ((strcmp (old_essid, new_essid) != 0) || !nm_device_has_active_link (old_dev))
gboolean es = (strcmp (old_essid, new_essid) != 0);
gboolean link = nm_device_has_active_link (old_dev);
if (es || !link)
{
nm_info ("SWITCH: found better connection '%s/%s' than current connection '%s/%s'.", nm_device_get_iface (new_dev),
new_essid, nm_device_get_iface (old_dev), old_essid);
nm_info ("SWITCH: found better connection '%s/%s' than current connection '%s/%s'. essid=%d, link=%d", nm_device_get_iface (new_dev),
new_essid, nm_device_get_iface (old_dev), old_essid, es, link);
do_switch = TRUE;
}
}

View file

@ -9,7 +9,9 @@ libvpn_manager_la_SOURCES = nm-dbus-vpn.c \
nm-vpn-manager.c \
nm-vpn-manager.h \
nm-vpn-service.c \
nm-vpn-service.h
nm-vpn-service.h \
nm-vpn-act-request.c \
nm-vpn-act-request.h
libvpn_manager_la_CPPFLAGS = $(DBUS_CFLAGS) \
$(GTHREAD_CFLAGS) \

View file

@ -28,6 +28,8 @@
#include "nm-dbus-vpn.h"
#include "nm-vpn-manager.h"
#include "nm-vpn-connection.h"
#include "nm-vpn-service.h"
#include "nm-vpn-act-request.h"
#include "nm-utils.h"
@ -64,12 +66,11 @@ void nm_dbus_vpn_signal_vpn_connection_update (DBusConnection *con, NMVPNConnect
*
* Notifies the bus that a VPN connection's state has changed.
*/
void nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *con, NMVPNConnection *vpn)
void nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *con, NMVPNConnection *vpn, NMVPNActStage new_stage)
{
DBusMessage *message;
const char *vpn_name;
NMVPNService *service;
NMVPNState vpn_state;
DBusMessage * message;
const char * vpn_name;
dbus_uint32_t int_stage = (dbus_uint32_t) new_stage;
g_return_if_fail (con != NULL);
g_return_if_fail (vpn != NULL);
@ -81,10 +82,7 @@ void nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *con, NMVPNC
}
vpn_name = nm_vpn_connection_get_name (vpn);
service = nm_vpn_connection_get_service (vpn);
vpn_state = nm_vpn_service_get_state (service);
dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_UINT32, &vpn_state, DBUS_TYPE_INVALID);
dbus_message_append_args (message, DBUS_TYPE_STRING, &vpn_name, DBUS_TYPE_UINT32, &int_stage, DBUS_TYPE_INVALID);
if (!dbus_connection_send (con, message, NULL))
nm_warning ("Could not raise the VPNConnectionStateChange signal!");
@ -358,12 +356,16 @@ static void nm_dbus_vpn_update_one_connection_cb (DBusPendingCall *pcall, void *
if (dbus_message_is_error (reply, "BadVPNConnectionData"))
{
NMVPNConnection *vpn = nm_vpn_manager_find_connection_by_name (cb_data->data->vpn_manager, cb_data->vpn);
NMVPNConnection *vpn;
nm_vpn_connection_ref (vpn);
nm_vpn_manager_remove_connection (cb_data->data->vpn_manager, vpn);
nm_dbus_vpn_signal_vpn_connection_update (cb_data->data->dbus_connection, vpn, "VPNConnectionRemoved");
nm_vpn_connection_unref (vpn);
/* Bad VPN, remove it from our VPN connection list */
if ((vpn = nm_vpn_manager_find_connection_by_name (cb_data->data->vpn_manager, cb_data->vpn)))
{
nm_vpn_connection_ref (vpn);
nm_vpn_manager_remove_connection (cb_data->data->vpn_manager, vpn);
nm_dbus_vpn_signal_vpn_connection_update (cb_data->data->dbus_connection, vpn, "VPNConnectionRemoved");
nm_vpn_connection_unref (vpn);
}
goto out;
}
@ -375,11 +377,19 @@ static void nm_dbus_vpn_update_one_connection_cb (DBusPendingCall *pcall, void *
if ((vpn = nm_vpn_manager_find_connection_by_name (cb_data->data->vpn_manager, con_name)))
{
nm_vpn_manager_remove_connection (cb_data->data->vpn_manager, vpn);
new = FALSE;
const char *vpn_service_name = nm_vpn_connection_get_service_name (vpn);
/* If all attributes of the existing connection are the same as the one we get from NMI,
* don't do anything.
*/
if (strcmp (vpn_service_name, service_name) || strcmp (nm_vpn_connection_get_user_name (vpn), user_name))
nm_vpn_manager_remove_connection (cb_data->data->vpn_manager, vpn);
else
new = FALSE;
}
vpn = nm_vpn_manager_add_connection (cb_data->data->vpn_manager, con_name, service_name, user_name);
if (new)
vpn = nm_vpn_manager_add_connection (cb_data->data->vpn_manager, con_name, service_name, user_name);
nm_dbus_vpn_signal_vpn_connection_update (cb_data->data->dbus_connection, vpn, new ? "VPNConnectionAdded" : "VPNConnectionUpdate");
}
dbus_message_unref (reply);
@ -389,6 +399,9 @@ out:
}
/* Should only be used by nm_dbus_vpn_connections_update_cb() */
GSList *nm_vpn_manager_vpn_connection_list_copy (NMVPNManager *manager);
/*
* nm_dbus_vpn_connections_update_cb
*
@ -400,6 +413,8 @@ static void nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, void *use
NMData * data = (NMData *) user_data;
DBusMessage * reply;
DBusMessageIter iter, array_iter;
GSList * remove_list = NULL;
GSList * elt;
g_return_if_fail (pcall);
g_return_if_fail (data != NULL);
@ -417,20 +432,27 @@ static void nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, void *use
nm_info ("Updating VPN Connections...");
remove_list = nm_vpn_manager_vpn_connection_list_copy (data->vpn_manager);
dbus_message_iter_init (reply, &iter);
dbus_message_iter_recurse (&iter, &array_iter);
while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING)
{
DBusMessage * message;
const char * value;
DBusMessage * message;
const char * con_name;
NMVPNConnection * vpn;
dbus_message_iter_get_basic (&array_iter, &value);
dbus_message_iter_get_basic (&array_iter, &con_name);
/* If the connection already exists, remove it from the remove list */
if ((vpn = nm_vpn_manager_find_connection_by_name (data->vpn_manager, con_name)))
remove_list = g_slist_remove (remove_list, vpn);
if ((message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getVPNConnectionProperties")))
{
DBusPendingCall * vpn_pcall = NULL;
dbus_message_append_args (message, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
dbus_message_append_args (message, DBUS_TYPE_STRING, &con_name, DBUS_TYPE_INVALID);
dbus_connection_send_with_reply (data->dbus_connection, message, &vpn_pcall, -1);
dbus_message_unref (message);
if (vpn_pcall)
@ -438,7 +460,7 @@ static void nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, void *use
UpdateOneVPNCBData * vpn_cb_data = g_malloc0 (sizeof (UpdateOneVPNCBData));
vpn_cb_data->data = data;
vpn_cb_data->vpn = g_strdup (value);
vpn_cb_data->vpn = g_strdup (con_name);
dbus_pending_call_set_notify (vpn_pcall, nm_dbus_vpn_update_one_connection_cb, vpn_cb_data, (DBusFreeFunction) free_update_one_vpn_cb_data);
}
}
@ -446,6 +468,15 @@ static void nm_dbus_vpn_connections_update_cb (DBusPendingCall *pcall, void *use
}
dbus_message_unref (reply);
/* VPN connections left in the remove list aren't known by NMI, therefore we delete them */
for (elt = remove_list; elt; elt = g_slist_next (elt))
{
nm_vpn_manager_remove_connection (data->vpn_manager, elt->data);
nm_vpn_connection_unref (elt->data);
}
g_slist_free (remove_list);
out:
dbus_pending_call_unref (pcall);
}
@ -501,9 +532,6 @@ static gboolean nm_dbus_vpn_connections_update_from_nmi (NMData *data)
g_return_val_if_fail (data->dbus_connection != NULL, FALSE);
g_return_val_if_fail (data->vpn_manager != NULL, FALSE);
/* Clear all existing connections in preparation for new ones */
nm_vpn_manager_clear_connections (data->vpn_manager);
if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getVPNConnections")))
{
nm_warning ("nm_dbus_vpn_connections_update (): Couldn't allocate the dbus message");
@ -596,19 +624,19 @@ out:
*/
static DBusMessage *nm_dbus_vpn_get_vpn_connection_properties (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
DBusMessage *reply = NULL;
DBusError error;
const char *name;
gboolean good = FALSE;
NMVPNConnection *vpn_con;
DBusMessage * reply = NULL;
DBusError error;
const char * name;
gboolean good = FALSE;
NMVPNManager * manager;
NMVPNConnection * vpn;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (data->data != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (data->data != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
/* Check for no VPN Manager */
if (!data->data->vpn_manager)
if (!(manager = data->data->vpn_manager))
return nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPN, "NoVPNConnections", "There are no available VPN connections.");
if (!(reply = dbus_message_new_method_return (message)))
@ -617,20 +645,26 @@ static DBusMessage *nm_dbus_vpn_get_vpn_connection_properties (DBusConnection *c
dbus_error_init (&error);
if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
{
if ((vpn_con = nm_vpn_manager_find_connection_by_name (data->data->vpn_manager, name)))
if ((vpn = nm_vpn_manager_find_connection_by_name (manager, name)))
{
const char *user_name;
const char *service_name;
NMVPNService *service;
NMVPNState state;
const char * user_name;
const char * service_name;
NMVPNService * service;
user_name = nm_vpn_connection_get_user_name (vpn_con);
service = nm_vpn_connection_get_service (vpn_con);
service_name = nm_vpn_service_get_service_name (service);
state = nm_vpn_service_get_state (service);
user_name = nm_vpn_connection_get_user_name (vpn);
service_name = nm_vpn_connection_get_service_name (vpn);
if ((service = nm_vpn_manager_find_service_by_name (data->data->vpn_manager, service_name)))
{
NMVPNActRequest * req = nm_vpn_manager_get_vpn_act_request (manager);
dbus_uint32_t stage = (dbus_uint32_t) NM_VPN_ACT_STAGE_DISCONNECTED;
dbus_message_append_args (reply, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user_name, DBUS_TYPE_STRING, &service_name, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID);
good = TRUE;
if (req && (nm_vpn_act_request_get_connection (req) == vpn))
stage = nm_vpn_act_request_get_stage (req);
dbus_message_append_args (reply, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &user_name,
DBUS_TYPE_STRING, &service_name, DBUS_TYPE_UINT32, &stage, DBUS_TYPE_INVALID);
good = TRUE;
}
}
}
@ -649,22 +683,21 @@ static DBusMessage *nm_dbus_vpn_get_vpn_connection_properties (DBusConnection *c
*/
static DBusMessage *nm_dbus_vpn_activate_connection (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
DBusError error;
const char *name;
char **passwords;
int num_passwords;
NMVPNConnection *vpn;
DBusError error;
const char * name;
char ** passwords;
int num_passwords;
NMVPNConnection * vpn;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (data->data != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
nm_info ("Entering");
dbus_error_init (&error);
if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &num_passwords, DBUS_TYPE_INVALID)) {
if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &passwords, &num_passwords, DBUS_TYPE_INVALID))
{
if ((vpn = nm_vpn_manager_find_connection_by_name (data->data->vpn_manager, name)))
{
int item_count = -1;
@ -672,21 +705,20 @@ static DBusMessage *nm_dbus_vpn_activate_connection (DBusConnection *connection,
if ((items = nm_dbus_vpn_get_vpn_data (connection, vpn, &item_count)))
{
char *joined_string = g_strjoinv (" / ", items);
NMVPNService *service = nm_vpn_connection_get_service (vpn);;
char * joined_string = g_strjoinv (" / ", items);
nm_info ("Will activate VPN connection '%s', service '%s', user_name '%s', vpn_data '%s'.",
name, nm_vpn_service_get_service_name (service), nm_vpn_connection_get_user_name (vpn), joined_string);
name, nm_vpn_connection_get_service_name (vpn), nm_vpn_connection_get_user_name (vpn), joined_string);
nm_vpn_manager_activate_vpn_connection (data->data->vpn_manager, vpn, passwords, num_passwords, items, item_count);
g_free (joined_string);
g_strfreev (items);
}
} else {
nm_warning ("Cannot find name '%s'", name);
nm_warning ("nm_dbus_vpn_activate_connection(): cannot find VPN connection '%s'", name);
}
} else {
nm_warning ("Syntax error receiving nm_dbus_vpn_activate_connection");
nm_warning ("nm_dbus_vpn_activate_connection(): syntax error in method arguments");
}
return NULL;
@ -701,12 +733,22 @@ static DBusMessage *nm_dbus_vpn_activate_connection (DBusConnection *connection,
*/
static DBusMessage *nm_dbus_vpn_deactivate_connection (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
NMVPNActRequest *req;
NMVPNConnection *vpn;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (data->data != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
nm_info ("Will deactivate the current VPN connection.");
if (!(req = nm_vpn_manager_get_vpn_act_request (data->data->vpn_manager)))
return NULL;
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_info ("Will deactivate the VPN connection '%s', service '%s'.", nm_vpn_connection_get_name (vpn),
nm_vpn_connection_get_service_name (vpn));
nm_vpn_manager_deactivate_vpn_connection (data->data->vpn_manager);
return NULL;

View file

@ -32,7 +32,7 @@ void nm_dbus_vpn_update_one_vpn_connection (DBusConnection *connection, cons
void nm_dbus_vpn_signal_vpn_connection_update (DBusConnection *con, NMVPNConnection *vpn, const char *signal);
void nm_dbus_vpn_signal_vpn_failed (DBusConnection *con, const char *signal, NMVPNConnection *vpn, const char *error_msg);
void nm_dbus_vpn_signal_vpn_login_banner (DBusConnection *con, NMVPNConnection *vpn, const char *banner);
void nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *con, NMVPNConnection *vpn);
void nm_dbus_vpn_signal_vpn_connection_state_change (DBusConnection *con, NMVPNConnection *vpn, NMVPNActStage new_stage);
char ** nm_dbus_vpn_get_routes (DBusConnection *connection, NMVPNConnection *vpn, int *num_items);

View file

@ -0,0 +1,265 @@
/* NetworkManager -- Network link manager
*
* Dan Williams <dcbw@redhat.com>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* (C) Copyright 2005 Red Hat, Inc.
*/
#include <glib.h>
#include <string.h>
#include "nm-vpn-act-request.h"
#include "nm-dbus-vpn.h"
struct NMVPNActRequest
{
guint refcount;
NMVPNActStage stage;
NMDevice * parent_dev;
NMVPNManager * manager;
NMVPNService * service;
NMVPNConnection * vpn;
char ** password_items;
int password_count;
char ** data_items;
int data_count;
guint daemon_wait_count;
guint callback_id;
gboolean canceled;
};
/* Ugly, I know. But we need it for now */
DBusConnection *nm_vpn_service_get_dbus_connection (NMVPNService *service);
NMVPNActRequest *nm_vpn_act_request_new (NMVPNManager *manager, NMVPNService *service, NMVPNConnection *vpn,
NMDevice *parent_dev, char **password_items, int password_count, char **data_items, int data_count)
{
NMVPNActRequest *req;
g_return_val_if_fail (manager != NULL, NULL);
g_return_val_if_fail (service != NULL, NULL);
g_return_val_if_fail (vpn != NULL, NULL);
g_return_val_if_fail (parent_dev != NULL, NULL);
g_return_val_if_fail (password_items != NULL, NULL);
g_return_val_if_fail (data_items != NULL, NULL);
req = g_malloc0 (sizeof (NMVPNActRequest));
req->refcount = 1;
req->stage = NM_VPN_ACT_STAGE_PREPARE;
req->manager = manager;
nm_device_ref (parent_dev);
req->parent_dev = parent_dev;
nm_vpn_service_ref (service);
req->service = service;
nm_vpn_connection_ref (vpn);
req->vpn = vpn;
req->password_items = g_strdupv (password_items);
req->password_count = password_count;
req->data_items = g_strdupv (data_items);
req->data_count = data_count;
return req;
}
void nm_vpn_act_request_ref (NMVPNActRequest *req)
{
g_return_if_fail (req != NULL);
req->refcount++;
}
void nm_vpn_act_request_unref (NMVPNActRequest *req)
{
g_return_if_fail (req != NULL);
req->refcount--;
if (req->refcount == 0)
{
nm_device_unref (req->parent_dev);
nm_vpn_service_unref (req->service);
nm_vpn_connection_unref (req->vpn);
g_strfreev (req->password_items);
g_strfreev (req->data_items);
memset (req, 0, sizeof (NMVPNActRequest));
g_free (req);
}
}
gboolean nm_vpn_act_request_is_activating (NMVPNActRequest *req)
{
gboolean activating = FALSE;
g_return_val_if_fail (req != NULL, FALSE);
switch (req->stage)
{
case NM_VPN_ACT_STAGE_PREPARE:
case NM_VPN_ACT_STAGE_CONNECT:
case NM_VPN_ACT_STAGE_IP_CONFIG_GET:
activating = TRUE;
break;
default:
break;
}
return activating;
}
gboolean nm_vpn_act_request_is_activated (NMVPNActRequest *req)
{
gboolean activated = FALSE;
g_return_val_if_fail (req != NULL, FALSE);
switch (req->stage)
{
case NM_VPN_ACT_STAGE_ACTIVATED:
activated = TRUE;
break;
default:
break;
}
return activated;
}
NMVPNManager *nm_vpn_act_request_get_manager (NMVPNActRequest *req)
{
g_return_val_if_fail (req != NULL, NULL);
return req->manager;
}
NMVPNService * nm_vpn_act_request_get_service (NMVPNActRequest *req)
{
g_return_val_if_fail (req != NULL, NULL);
return req->service;
}
NMVPNConnection * nm_vpn_act_request_get_connection (NMVPNActRequest *req)
{
g_return_val_if_fail (req != NULL, NULL);
return req->vpn;
}
NMDevice *nm_vpn_act_request_get_parent_dev (NMVPNActRequest *req)
{
g_return_val_if_fail (req != NULL, NULL);
return req->parent_dev;
}
const char ** nm_vpn_act_request_get_password_items (NMVPNActRequest *req, guint *count)
{
g_return_val_if_fail (req != NULL, NULL);
g_return_val_if_fail (count != NULL, NULL);
*count = req->password_count;
return (const char **) (req->password_items);
}
const char ** nm_vpn_act_request_get_data_items (NMVPNActRequest *req, guint *count)
{
g_return_val_if_fail (req != NULL, NULL);
g_return_val_if_fail (count != NULL, NULL);
*count = req->data_count;
return (const char **) (req->data_items);
}
void nm_vpn_act_request_cancel (NMVPNActRequest *req)
{
g_return_if_fail (req != NULL);
req->canceled = TRUE;
}
gboolean nm_vpn_act_request_should_cancel (NMVPNActRequest *req)
{
g_return_val_if_fail (req != NULL, FALSE);
return req->canceled;
}
NMVPNActStage nm_vpn_act_request_get_stage (NMVPNActRequest *req)
{
g_return_val_if_fail (req != NULL, NM_VPN_ACT_STAGE_UNKNOWN);
return req->stage;
}
void nm_vpn_act_request_set_stage (NMVPNActRequest *req, NMVPNActStage stage)
{
NMVPNActStage old_stage;
g_return_if_fail (req != NULL);
old_stage = req->stage;
if (old_stage != stage)
{
DBusConnection *dbus_connection = nm_vpn_service_get_dbus_connection (req->service);
req->stage = stage;
nm_dbus_vpn_signal_vpn_connection_state_change (dbus_connection, req->vpn, req->stage);
}
}
guint nm_vpn_act_request_get_daemon_wait_count (NMVPNActRequest *req)
{
g_return_val_if_fail (req != NULL, 0);
return req->daemon_wait_count;
}
void nm_vpn_act_request_set_daemon_wait_count (NMVPNActRequest *req, guint count)
{
g_return_if_fail (req != NULL);
req->daemon_wait_count = count;
}
guint nm_vpn_act_request_get_callback_id (NMVPNActRequest *req)
{
g_return_val_if_fail (req != NULL, 0);
return req->callback_id;
}
void nm_vpn_act_request_set_callback_id (NMVPNActRequest *req, guint id)
{
g_return_if_fail (req != NULL);
req->callback_id = id;
}

View file

@ -0,0 +1,59 @@
/* NetworkManager -- Network link manager
*
* Dan Williams <dcbw@redhat.com>
*
* 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* (C) Copyright 2005 Red Hat, Inc.
*/
#ifndef NM_VPN_ACT_REQUEST_H
#define NM_VPN_ACT_REQUEST_H
#include <glib.h>
#include "NetworkManager.h"
#include "nm-vpn-service.h"
#include "nm-vpn-connection.h"
NMVPNActRequest * nm_vpn_act_request_new (NMVPNManager *manager, NMVPNService *service, NMVPNConnection *vpn,
NMDevice *parent_dev, char **password_items, int password_count, char **data_items, int data_count);
void nm_vpn_act_request_ref (NMVPNActRequest *req);
void nm_vpn_act_request_unref (NMVPNActRequest *req);
gboolean nm_vpn_act_request_is_activating (NMVPNActRequest *req);
gboolean nm_vpn_act_request_is_activated (NMVPNActRequest *req);
NMVPNManager * nm_vpn_act_request_get_manager (NMVPNActRequest *req);
NMVPNService * nm_vpn_act_request_get_service (NMVPNActRequest *req);
NMVPNConnection * nm_vpn_act_request_get_connection (NMVPNActRequest *req);
NMDevice * nm_vpn_act_request_get_parent_dev (NMVPNActRequest *req);
const char ** nm_vpn_act_request_get_password_items (NMVPNActRequest *req, guint *count);
const char ** nm_vpn_act_request_get_data_items (NMVPNActRequest *req, guint *count);
void nm_vpn_act_request_cancel (NMVPNActRequest *req);
gboolean nm_vpn_act_request_should_cancel (NMVPNActRequest *req);
NMVPNActStage nm_vpn_act_request_get_stage (NMVPNActRequest *req);
void nm_vpn_act_request_set_stage (NMVPNActRequest *req, NMVPNActStage stage);
guint nm_vpn_act_request_get_daemon_wait_count (NMVPNActRequest *req);
void nm_vpn_act_request_set_daemon_wait_count (NMVPNActRequest *req, guint count);
guint nm_vpn_act_request_get_callback_id (NMVPNActRequest *req);
void nm_vpn_act_request_set_callback_id (NMVPNActRequest *req, guint timeout);
#endif

View file

@ -22,34 +22,56 @@
#include <glib.h>
#include <string.h>
#include "nm-vpn-connection.h"
#include "nm-dbus-vpn.h"
#include "NetworkManagerSystem.h"
struct NMVPNConnection
{
int refcount;
char *name;
char *user_name;
NMVPNService *service;
int refcount;
/* Won't change over life of object */
char * name;
char * user_name;
char * service_name;
NMNamedManager *named_manager;
DBusConnection *dbus_connection;
/* Change when connection is activated/deactivated */
NMDevice * parent_dev;
NMIP4Config * ip4_config;
char * vpn_iface;
};
NMVPNConnection *nm_vpn_connection_new (const char *name, const char *user_name, NMVPNService *service)
static void nm_vpn_connection_set_vpn_iface (NMVPNConnection *con, const char *vpn_iface);
static void nm_vpn_connection_set_ip4_config (NMVPNConnection *con, NMIP4Config *ip4_config);
static void nm_vpn_connection_set_parent_device(NMVPNConnection *con, NMDevice *parent_dev);
NMVPNConnection *nm_vpn_connection_new (const char *name, const char *user_name, const char *service_name,
NMNamedManager *named_manager, DBusConnection *dbus_connection)
{
NMVPNConnection *connection;
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (user_name != NULL, NULL);
g_return_val_if_fail (service != NULL, NULL);
g_return_val_if_fail (service_name != NULL, NULL);
g_return_val_if_fail (named_manager != NULL, NULL);
g_return_val_if_fail (dbus_connection != NULL, NULL);
connection = g_malloc0 (sizeof (NMVPNConnection));
connection->refcount = 1;
connection->name = g_strdup (name);
connection->user_name = g_strdup (user_name);
connection->service_name = g_strdup (service_name);
nm_vpn_service_ref (service);
connection->service = service;
g_object_ref (named_manager);
connection->named_manager = named_manager;
connection->dbus_connection = dbus_connection;
return connection;
}
@ -71,13 +93,84 @@ void nm_vpn_connection_unref (NMVPNConnection *connection)
{
g_free (connection->name);
g_free (connection->user_name);
nm_vpn_service_unref (connection->service);
g_free (connection->service_name);
if (connection->parent_dev)
nm_device_unref (connection->parent_dev);
if (connection->ip4_config)
nm_ip4_config_unref (connection->ip4_config);
g_free (connection->vpn_iface);
g_object_unref (connection->named_manager);
memset (connection, 0, sizeof (NMVPNConnection));
g_free (connection);
}
}
void nm_vpn_connection_activate (NMVPNConnection *connection)
{
g_return_if_fail (connection != NULL);
/* Nothing done here yet */
}
gboolean nm_vpn_connection_set_config (NMVPNConnection *connection, const char *vpn_iface, NMDevice *dev, NMIP4Config *ip4_config)
{
gboolean success = FALSE;
int num_routes = -1;
char ** routes;
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (vpn_iface != NULL, FALSE);
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (ip4_config != NULL, FALSE);
nm_vpn_connection_set_vpn_iface (connection, vpn_iface);
nm_vpn_connection_set_parent_device (connection, dev);
nm_vpn_connection_set_ip4_config (connection, ip4_config);
routes = nm_dbus_vpn_get_routes (connection->dbus_connection, connection, &num_routes);
nm_system_vpn_device_set_from_ip4_config (connection->named_manager, connection->parent_dev,
connection->vpn_iface, connection->ip4_config, routes, num_routes);
g_strfreev(routes);
success = TRUE;
return success;
}
void nm_vpn_connection_deactivate (NMVPNConnection *connection)
{
g_return_if_fail (connection != NULL);
if (connection->ip4_config)
{
nm_system_remove_ip4_config_nameservers (connection->named_manager, connection->ip4_config);
nm_system_remove_ip4_config_search_domains (connection->named_manager, connection->ip4_config);
}
if (connection->vpn_iface)
{
nm_system_device_set_up_down_with_iface (NULL, connection->vpn_iface, FALSE);
nm_system_device_flush_routes_with_iface (connection->vpn_iface);
nm_system_device_flush_addresses_with_iface (connection->vpn_iface);
}
if (connection->ip4_config)
{
/* Reset routes, nameservers, and domains of the currently active device */
nm_system_device_set_from_ip4_config (connection->parent_dev);
}
nm_vpn_connection_set_ip4_config (connection, NULL);
nm_vpn_connection_set_vpn_iface (connection, NULL);
nm_vpn_connection_set_parent_device (connection, NULL);
}
const char *nm_vpn_connection_get_name (NMVPNConnection *connection)
{
g_return_val_if_fail (connection != NULL, NULL);
@ -92,10 +185,58 @@ const char *nm_vpn_connection_get_user_name (NMVPNConnection *connection)
return connection->user_name;
}
NMVPNService *nm_vpn_connection_get_service (NMVPNConnection *connection)
const char *nm_vpn_connection_get_service_name (NMVPNConnection *connection)
{
g_return_val_if_fail (connection != NULL, NULL);
return connection->service;
return connection->service_name;
}
static void nm_vpn_connection_set_vpn_iface (NMVPNConnection *con, const char *vpn_iface)
{
g_return_if_fail (con != NULL);
if (con->vpn_iface)
{
g_free (con->vpn_iface);
con->vpn_iface = NULL;
}
if (vpn_iface)
con->vpn_iface = g_strdup (vpn_iface);
}
static void nm_vpn_connection_set_ip4_config (NMVPNConnection *con, NMIP4Config *ip4_config)
{
g_return_if_fail (con != NULL);
if (con->ip4_config)
{
nm_ip4_config_unref (con->ip4_config);
con->ip4_config = NULL;
}
if (ip4_config)
{
nm_ip4_config_ref (ip4_config);
con->ip4_config = ip4_config;
}
}
static void nm_vpn_connection_set_parent_device (NMVPNConnection *con, NMDevice *parent_dev)
{
g_return_if_fail (con != NULL);
if (con->parent_dev)
{
nm_device_unref (con->parent_dev);
con->parent_dev = NULL;
}
if (parent_dev)
{
nm_device_ref (parent_dev);
con->parent_dev = parent_dev;
}
}

View file

@ -20,17 +20,23 @@
#ifndef NM_VPN_CONNECTION_H
#define NM_VPN_CONNECTION_H
#include "nm-vpn-service.h"
#include "NetworkManagerDevice.h"
typedef struct NMVPNConnection NMVPNConnection;
NMVPNConnection *nm_vpn_connection_new (const char *name, const char *user_name, NMVPNService *service);
void nm_vpn_connection_ref (NMVPNConnection *connection);
void nm_vpn_connection_unref (NMVPNConnection *connection);
NMVPNConnection * nm_vpn_connection_new (const char *name, const char *user_name, const char *service_name,
NMNamedManager *named_manager, DBusConnection *dbus_connection);
void nm_vpn_connection_ref (NMVPNConnection *con);
void nm_vpn_connection_unref (NMVPNConnection *con);
const char * nm_vpn_connection_get_name (NMVPNConnection *connection);
const char * nm_vpn_connection_get_user_name (NMVPNConnection *connection);
NMVPNService * nm_vpn_connection_get_service (NMVPNConnection *connection);
const char * nm_vpn_connection_get_name (NMVPNConnection *con);
const char * nm_vpn_connection_get_user_name (NMVPNConnection *con);
const char * nm_vpn_connection_get_service_name (NMVPNConnection *con);
void nm_vpn_connection_activate (NMVPNConnection *con);
void nm_vpn_connection_deactivate (NMVPNConnection *con);
gboolean nm_vpn_connection_set_config (NMVPNConnection *con, const char *vpn_iface, NMDevice *dev, NMIP4Config *ip4_config);
#endif /* NM_VPN_MANAGER_H */

View file

@ -20,20 +20,16 @@
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <dbus/dbus.h>
#include "nm-vpn-manager.h"
#include "NetworkManager.h"
#include "NetworkManagerMain.h"
#include "NetworkManagerDbus.h"
#include "NetworkManagerSystem.h"
#include "nm-vpn-act-request.h"
#include "nm-vpn-connection.h"
#include "nm-vpn-service.h"
#include "nm-dbus-vpn.h"
#include "nm-activation-request.h"
#include "nm-utils.h"
#define VPN_SERVICE_FILE_PATH SYSCONFDIR"/NetworkManager/VPN"
@ -41,15 +37,13 @@
struct NMVPNManager
{
NMData * app_data;
GSList * services;
GHashTable * service_table;
GSList * connections;
NMVPNConnection * active;
char * active_device;
NMIP4Config * active_config;
NMVPNActRequest * act_req;
};
static GSList * nm_vpn_manager_load_services (void);
static void nm_vpn_manager_set_active_vpn_connection (NMVPNManager *manager, NMVPNConnection *con);
static void nm_vpn_manager_load_services (NMVPNManager *manager, GHashTable *table);
/*
* nm_vpn_manager_new
@ -59,14 +53,16 @@ static void nm_vpn_manager_set_active_vpn_connection (NMVPNManager *manager, NM
*/
NMVPNManager *nm_vpn_manager_new (NMData *app_data)
{
NMVPNManager *manager;
NMVPNManager * manager;
g_return_val_if_fail (app_data != NULL, NULL);
manager = g_malloc0 (sizeof (NMVPNManager));
manager->services = nm_vpn_manager_load_services ();
manager->app_data = app_data;
manager->service_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) nm_vpn_service_unref);
nm_vpn_manager_load_services (manager, manager->service_table);
return manager;
}
@ -81,73 +77,19 @@ void nm_vpn_manager_dispose (NMVPNManager *manager)
{
g_return_if_fail (manager != NULL);
nm_vpn_manager_set_active_vpn_connection (manager, NULL);
if (manager->active_device)
g_free (manager->active_device);
if (manager->active_config)
{
nm_system_remove_ip4_config_nameservers (manager->app_data->named_manager, manager->active_config);
nm_system_remove_ip4_config_search_domains (manager->app_data->named_manager, manager->active_config);
nm_ip4_config_unref (manager->active_config);
}
if (manager->act_req)
nm_vpn_manager_deactivate_vpn_connection (manager);
g_slist_foreach (manager->connections, (GFunc) nm_vpn_connection_unref, NULL);
g_slist_free (manager->connections);
g_slist_foreach (manager->services, (GFunc) nm_vpn_service_unref, NULL);
g_slist_free (manager->services);
g_hash_table_destroy (manager->service_table);
memset (manager, 0, sizeof (NMVPNManager));
g_free (manager);
}
/*
* nm_vpn_manager_clear_connections
*
* Dispose of all the VPN connections the manager knows about.
*
*/
void nm_vpn_manager_clear_connections (NMVPNManager *manager)
{
g_return_if_fail (manager != NULL);
g_slist_foreach (manager->connections, (GFunc) nm_vpn_connection_unref, NULL);
g_slist_free (manager->connections);
manager->connections = NULL;
}
/*
* find_vpn_service
*
* Return the VPN Service for a given vpn service name.
*
*/
static NMVPNService *find_service_by_name (NMVPNManager *manager, const char *service_name)
{
NMVPNService *service = NULL;
GSList *elt;
g_return_val_if_fail (manager != NULL, NULL);
g_return_val_if_fail (service_name != NULL, NULL);
for (elt = manager->services; elt; elt = g_slist_next (elt))
{
if ((service = (NMVPNService *)(elt->data)))
{
const char *search_name = nm_vpn_service_get_service_name (service);
if (search_name && (strcmp (service_name, search_name) == 0))
break;
}
service = NULL;
}
return service;
}
/*
* nm_vpn_manager_find_connection_by_name
*
@ -177,77 +119,34 @@ NMVPNConnection *nm_vpn_manager_find_connection_by_name (NMVPNManager *manager,
}
NMVPNService *nm_vpn_manager_find_service_by_name (NMVPNManager *manager, const char *service_name)
{
g_return_val_if_fail (manager != NULL, NULL);
g_return_val_if_fail (service_name != NULL, NULL);
return (NMVPNService *) g_hash_table_lookup (manager->service_table, service_name);
}
/*
* nm_vpn_manager_set_active_vpn_connection
* nm_vpn_manager_vpn_connection_list_copy
*
* Sets the active connection and adds a dbus signal filter for that
* connection's service name.
* Make a shallow copy of the VPN connection list, should
* only be used by nm-dbus-vpn.c
*
*/
static void nm_vpn_manager_set_active_vpn_connection (NMVPNManager *manager, NMVPNConnection *con)
GSList *nm_vpn_manager_vpn_connection_list_copy (NMVPNManager *manager)
{
char *match_string = NULL;
const char *service_name = NULL;
NMVPNConnection *active;
NMVPNService *service;
GSList * list;
GSList * elt;
g_return_if_fail (manager != NULL);
g_return_val_if_fail (manager != NULL, NULL);
if ((active = nm_vpn_manager_get_active_vpn_connection (manager)))
{
service = nm_vpn_connection_get_service (active);
if (service && (service_name = nm_vpn_service_get_service_name (service)))
{
/* Remove any previous watch on this VPN connection's service name */
match_string = g_strdup_printf ("type='signal',"
"interface='%s',"
"sender='%s'", service_name, service_name);
dbus_bus_remove_match (manager->app_data->dbus_connection, match_string, NULL);
g_free (match_string);
}
nm_vpn_connection_unref (active);
}
manager->active = NULL;
list = g_slist_copy (manager->connections);
for (elt = list; elt; elt = g_slist_next (elt))
nm_vpn_connection_ref (elt->data);
if (manager->active_config)
{
nm_system_remove_ip4_config_nameservers (manager->app_data->named_manager, manager->active_config);
nm_system_remove_ip4_config_search_domains (manager->app_data->named_manager, manager->active_config);
nm_ip4_config_unref (manager->active_config);
manager->active_config = NULL;
}
if (manager->active_device)
{
nm_system_device_set_up_down_with_iface (NULL, manager->active_device, FALSE);
nm_system_device_flush_routes_with_iface (manager->active_device);
nm_system_device_flush_addresses_with_iface (manager->active_device);
g_free (manager->active_device);
manager->active_device = NULL;
}
/* If passed NULL (clear active connection) there's nothing more to do */
if (!con)
return;
service = nm_vpn_connection_get_service (con);
if (!service || !(service_name = nm_vpn_service_get_service_name (service)))
{
nm_warning ("VPN connection could not be set active because it didn't have a VPN service.");
return;
}
nm_vpn_connection_ref (con);
manager->active = con;
/* Add a dbus filter for this connection's service name so its signals
* get delivered to us.
*/
match_string = g_strdup_printf ("type='signal',"
"interface='%s',"
"sender='%s'", service_name, service_name);
dbus_bus_add_match (manager->app_data->dbus_connection, match_string, NULL);
g_free (match_string);
return list;
}
@ -259,8 +158,8 @@ static void nm_vpn_manager_set_active_vpn_connection (NMVPNManager *manager, NMV
*/
NMVPNConnection *nm_vpn_manager_add_connection (NMVPNManager *manager, const char *name, const char *service_name, const char *user_name)
{
NMVPNConnection *connection = NULL;
NMVPNService *service;
NMVPNConnection * connection = NULL;
NMVPNService * service;
g_return_val_if_fail (manager != NULL, NULL);
g_return_val_if_fail (name != NULL, NULL);
@ -268,8 +167,11 @@ NMVPNConnection *nm_vpn_manager_add_connection (NMVPNManager *manager, const cha
g_return_val_if_fail (user_name != NULL, NULL);
/* Verify that the service name we are adding is in our allowed list */
service = find_service_by_name (manager, service_name);
if (service && (connection = nm_vpn_connection_new (name, user_name, service)))
if (!(service = nm_vpn_manager_find_service_by_name (manager, service_name)))
return NULL;
if ((connection = nm_vpn_connection_new (name, user_name, service_name, manager->app_data->named_manager,
manager->app_data->dbus_connection)))
{
GSList *elt;
@ -305,143 +207,24 @@ void nm_vpn_manager_remove_connection (NMVPNManager *manager, NMVPNConnection *v
g_return_if_fail (manager != NULL);
g_return_if_fail (vpn != NULL);
/* If this VPN is currently active, kill it */
if (manager->act_req && (nm_vpn_act_request_get_connection (manager->act_req) == vpn))
{
NMVPNService * service = nm_vpn_act_request_get_service (manager->act_req);
NMVPNConnection * vpn = nm_vpn_act_request_get_connection (manager->act_req);
nm_vpn_connection_deactivate (vpn);
nm_vpn_service_stop_connection (service, manager->act_req);
nm_vpn_act_request_unref (manager->act_req);
manager->act_req = NULL;
}
manager->connections = g_slist_remove (manager->connections, vpn);
nm_vpn_connection_unref (vpn);
}
/*
* Prints config returned from vpnc-helper
*/
static void print_vpn_config (guint32 ip4_vpn_gateway,
const char *tundev,
guint32 ip4_internal_address,
gint32 ip4_internal_netmask,
guint32 *ip4_internal_dns,
guint32 ip4_internal_dns_len,
guint32 *ip4_internal_nbns,
guint32 ip4_internal_nbns_len,
const char *dns_domain,
const char *login_banner)
{
struct in_addr temp_addr;
guint32 i;
temp_addr.s_addr = ip4_vpn_gateway;
nm_info ("VPN Gateway: %s", inet_ntoa (temp_addr));
nm_info ("Tunnel Device: %s", tundev);
temp_addr.s_addr = ip4_internal_address;
nm_info ("Internal IP4 Address: %s", inet_ntoa (temp_addr));
temp_addr.s_addr = ip4_internal_netmask;
nm_info ("Internal IP4 Netmask: %s", inet_ntoa (temp_addr));
for (i = 0; i < ip4_internal_dns_len; i++)
{
if (ip4_internal_dns[i] != 0)
{
temp_addr.s_addr = ip4_internal_dns[i];
nm_info ("Internal IP4 DNS: %s", inet_ntoa (temp_addr));
}
}
for (i = 0; i < ip4_internal_nbns_len; i++)
{
if (ip4_internal_nbns[i] != 0)
{
temp_addr.s_addr = ip4_internal_nbns[i];
nm_info ("Internal IP4 NBNS: %s", inet_ntoa (temp_addr));
}
}
nm_info ("DNS Domain: '%s'", dns_domain);
nm_info ("Login Banner:");
nm_info ("-----------------------------------------");
nm_info ("%s", login_banner);
nm_info ("-----------------------------------------");
}
/*
* nm_vpn_manager_handle_ip4_config_signal
*
* Configure a device with IPv4 config info in response the the VPN daemon.
*
*/
void nm_vpn_manager_handle_ip4_config_signal (NMVPNManager *manager, DBusMessage *message, NMVPNService *service, NMVPNConnection *con)
{
guint32 ip4_vpn_gateway;
char * tundev;
guint32 ip4_internal_address;
guint32 ip4_internal_netmask;
guint32 * ip4_internal_dns;
guint32 ip4_internal_dns_len;
guint32 * ip4_internal_nbns;
guint32 ip4_internal_nbns_len;
char * dns_domain;
char * login_banner;
g_return_if_fail (manager != NULL);
g_return_if_fail (message != NULL);
g_return_if_fail (service != NULL);
g_return_if_fail (con != NULL);
if (dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ip4_vpn_gateway,
DBUS_TYPE_STRING, &tundev,
DBUS_TYPE_UINT32, &ip4_internal_address,
DBUS_TYPE_UINT32, &ip4_internal_netmask,
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &ip4_internal_dns, &ip4_internal_dns_len,
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &ip4_internal_nbns, &ip4_internal_nbns_len,
DBUS_TYPE_STRING, &dns_domain,
DBUS_TYPE_STRING, &login_banner, DBUS_TYPE_INVALID))
{
NMIP4Config * config;
NMDevice * vpn_dev;
guint32 i;
#if 0
print_vpn_config (ip4_vpn_gateway, tundev, ip4_internal_address, ip4_internal_netmask,
ip4_internal_dns, ip4_internal_dns_len, ip4_internal_nbns, ip4_internal_nbns_len,
dns_domain, login_banner);
#endif
config = nm_ip4_config_new ();
nm_ip4_config_set_address (config, ip4_internal_address);
if (ip4_internal_netmask)
nm_ip4_config_set_netmask (config, ip4_internal_netmask);
else
nm_ip4_config_set_netmask (config, 0x00FF); /* Class C */
nm_ip4_config_set_gateway (config, ip4_vpn_gateway);
if (strlen (dns_domain))
nm_ip4_config_add_domain (config, dns_domain);
for (i = 0; i < ip4_internal_dns_len; i++)
{
if (ip4_internal_dns[i] != 0)
nm_ip4_config_add_nameserver (config, ip4_internal_dns[i]);
}
manager->active_device = g_strdup (tundev);
manager->active_config = config;
vpn_dev = nm_get_active_device (manager->app_data);
if (vpn_dev)
{
int num_routes = -1;
char **routes = nm_dbus_vpn_get_routes (manager->app_data->dbus_connection, con, &num_routes);
nm_system_vpn_device_set_from_ip4_config (manager->app_data->named_manager, vpn_dev,
manager->active_device, manager->active_config,
routes, num_routes);
if (login_banner && strlen (login_banner))
nm_dbus_vpn_signal_vpn_login_banner (manager->app_data->dbus_connection, con, login_banner);
g_strfreev(routes);
}
}
}
/*
* nm_vpn_manager_get_connection_names
*
@ -470,50 +253,25 @@ char **nm_vpn_manager_get_connection_names (NMVPNManager *manager)
/*
* nm_vpn_manager_get_active_vpn_connection
* nm_vpn_manager_get_vpn_act_request
*
* Return the active VPN connection, if any.
* Return the VPN activation request, if any.
*
*/
NMVPNConnection *nm_vpn_manager_get_active_vpn_connection (NMVPNManager *manager)
NMVPNActRequest *nm_vpn_manager_get_vpn_act_request (NMVPNManager *manager)
{
g_return_val_if_fail (manager != NULL, NULL);
return manager->active;
return manager->act_req;
}
/*
* construct_op_from_service_name
*
* Construct an object path from a dbus service name by replacing
* all "." in the service with "/" and prepending a "/" to the
* object path.
*
*/
static char *construct_op_from_service_name (const char *service_name)
static inline gboolean same_service_name (NMVPNService *service, NMVPNConnection *vpn)
{
char **split = NULL;
char *temp1;
char *temp2;
g_return_val_if_fail (service != NULL, FALSE);
g_return_val_if_fail (vpn != NULL, FALSE);
g_return_val_if_fail (service_name != NULL, NULL);
if (!(split = g_strsplit (service_name, ".", 0)))
return NULL;
temp1 = g_strjoinv ("/", split);
g_strfreev (split);
temp2 = g_strdup_printf ("/%s", temp1);
g_free (temp1);
if (!temp2 || !strlen (temp2))
{
g_free (temp2);
temp2 = NULL;
}
return temp2;
return (!strcmp (nm_vpn_service_get_service_name (service), nm_vpn_connection_get_service_name (vpn)));
}
@ -526,72 +284,21 @@ static char *construct_op_from_service_name (const char *service_name)
*/
gboolean nm_vpn_manager_process_signal (NMVPNManager *manager, DBusMessage *message)
{
const char * object_path;
const char * member;
const char * temp_op;
NMVPNConnection * active;
NMVPNService * service;
const char * service_name;
NMVPNService * service;
gboolean handled = FALSE;
g_return_val_if_fail (manager != NULL, FALSE);
g_return_val_if_fail (message != NULL, FALSE);
if (!(object_path = dbus_message_get_path (message)))
return FALSE;
if (!(member = dbus_message_get_member (message)))
return FALSE;
if (!(active = nm_vpn_manager_get_active_vpn_connection (manager)))
return FALSE;
service = nm_vpn_connection_get_service (active);
if (!service || !(service_name = nm_vpn_service_get_service_name (service)))
return FALSE;
temp_op = construct_op_from_service_name (service_name);
if (!temp_op || (strcmp (object_path, temp_op) != 0))
return FALSE;
if ( dbus_message_is_signal (message, service_name, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED)
|| dbus_message_is_signal (message, service_name, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED)
|| dbus_message_is_signal (message, service_name, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED)
|| dbus_message_is_signal (message, service_name, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD)
|| dbus_message_is_signal (message, service_name, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD))
service_name = dbus_message_get_interface (message);
if ((service = nm_vpn_manager_find_service_by_name (manager, service_name)))
{
char *error_msg;
if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID))
error_msg = (char *) "";
nm_warning ("VPN failed for service '%s', signal '%s', with message '%s'.", service_name, member, error_msg);
nm_dbus_vpn_signal_vpn_failed (manager->app_data->dbus_connection, member, active, error_msg);
nm_vpn_service_process_signal (service, manager->act_req, message);
handled = TRUE;
}
else if (dbus_message_is_signal (message, service_name, NM_DBUS_VPN_SIGNAL_STATE_CHANGE))
{
dbus_uint32_t old_state_int;
dbus_uint32_t new_state_int;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_UINT32, &old_state_int, DBUS_TYPE_UINT32, &new_state_int, DBUS_TYPE_INVALID))
{
NMVPNState old_state = (NMVPNState) old_state_int;
NMVPNState new_state = (NMVPNState) new_state_int;
nm_info ("VPN service '%s' signaled new state %d, old state %d.", service_name, new_state, old_state);
nm_vpn_service_set_state (service, new_state);
nm_dbus_vpn_signal_vpn_connection_state_change (manager->app_data->dbus_connection, active);
/* If the VPN daemon state is now stopped and it was starting, clear the active connection */
if (((new_state == NM_VPN_STATE_STOPPED) || (new_state == NM_VPN_STATE_SHUTDOWN) || (new_state == NM_VPN_STATE_STOPPING))
&& ((old_state == NM_VPN_STATE_STARTED) || (old_state == NM_VPN_STATE_STARTING)))
{
nm_vpn_manager_set_active_vpn_connection (manager, NULL);
}
}
}
else if (dbus_message_is_signal (message, service_name, NM_DBUS_VPN_SIGNAL_IP4_CONFIG))
nm_vpn_manager_handle_ip4_config_signal (manager, message, service, active);
return TRUE;
return handled;
}
@ -603,44 +310,20 @@ gboolean nm_vpn_manager_process_signal (NMVPNManager *manager, DBusMessage *mess
*/
gboolean nm_vpn_manager_process_name_owner_changed (NMVPNManager *manager, const char *changed_service_name, const char *old_owner, const char *new_owner)
{
NMVPNService *service;
NMVPNConnection *active;
gboolean old_owner_good = (old_owner && strlen (old_owner));
gboolean new_owner_good = (new_owner && strlen (new_owner));
NMVPNConnection * active;
NMVPNService * service;
gboolean handled = FALSE;
g_return_val_if_fail (manager != NULL, FALSE);
g_return_val_if_fail (changed_service_name != NULL, FALSE);
if (!(active = nm_vpn_manager_get_active_vpn_connection (manager)))
return FALSE;
nm_vpn_connection_ref (active);
if (!(service = nm_vpn_connection_get_service (active)))
if ((service = nm_vpn_manager_find_service_by_name (manager, changed_service_name)))
{
nm_vpn_connection_unref (active);
return FALSE;
nm_vpn_service_name_owner_changed (service, manager->act_req, old_owner, new_owner);
handled = TRUE;
}
/* Can't handle the signal if its not from our active VPN service */
if (strcmp (nm_vpn_service_get_service_name (service), changed_service_name) != 0)
{
nm_vpn_connection_unref (active);
return FALSE;
}
if (!old_owner_good && new_owner_good)
{
/* VPN service got created. */
}
else if (old_owner_good && !new_owner_good)
{
/* VPN service went away. */
nm_vpn_service_set_state (service, NM_VPN_STATE_SHUTDOWN);
nm_dbus_vpn_signal_vpn_connection_state_change (manager->app_data->dbus_connection, active);
}
nm_vpn_connection_unref (active);
return TRUE;
return handled;
}
@ -651,76 +334,36 @@ gboolean nm_vpn_manager_process_name_owner_changed (NMVPNManager *manager, const
* launching that daemon if necessary.
*
*/
void nm_vpn_manager_activate_vpn_connection (NMVPNManager *manager, NMVPNConnection *vpn, char **password_items, int password_count, char **data_items, int count)
void nm_vpn_manager_activate_vpn_connection (NMVPNManager *manager, NMVPNConnection *vpn,
char **password_items, int password_count, char **data_items, int data_count)
{
DBusMessage *message;
DBusMessage *reply;
char *op;
NMVPNService *service;
const char *service_name;
const char *name;
const char *user_name;
DBusError error;
NMDevice * parent_dev;
NMVPNActRequest * req;
NMVPNService * service;
const char * service_name;
g_return_if_fail (manager != NULL);
g_return_if_fail (manager->app_data != NULL);
g_return_if_fail (manager->app_data->dbus_connection != NULL);
g_return_if_fail (vpn != NULL);
g_return_if_fail (password_items != NULL);
g_return_if_fail (data_items != NULL);
nm_vpn_manager_set_active_vpn_connection (manager, NULL);
if (manager->act_req)
nm_vpn_manager_deactivate_vpn_connection (manager);
/* Construct a new method call with the correct service and object path */
if (!(service = nm_vpn_connection_get_service (vpn)) || !(service_name = nm_vpn_service_get_service_name (service)))
service_name = nm_vpn_connection_get_service_name (vpn);
if (!(service = nm_vpn_manager_find_service_by_name (manager, service_name)))
return;
nm_vpn_manager_set_active_vpn_connection (manager, vpn);
/* Start the daemon if its not already running */
if (!dbus_bus_name_has_owner (manager->app_data->dbus_connection, service_name, NULL))
if (!(parent_dev = nm_get_active_device (manager->app_data)))
{
if (!nm_vpn_service_exec_daemon (service))
{
nm_vpn_manager_set_active_vpn_connection (manager, NULL);
return;
}
}
/* Send the activate request to the daemon */
op = construct_op_from_service_name (service_name);
message = dbus_message_new_method_call (service_name, op, service_name, "startConnection");
g_free (op);
if (!message)
{
nm_warning ("Couldn't allocate dbus message.");
nm_vpn_manager_set_active_vpn_connection (manager, NULL);
nm_warning ("nm_vpn_manager_activate_vpn_connection(): no currently active network device, won't activate VPN.");
return;
}
name = nm_vpn_connection_get_name (vpn);
user_name = nm_vpn_connection_get_user_name (vpn);
req = nm_vpn_act_request_new (manager, service, vpn, parent_dev, password_items, password_count, data_items, data_count);
manager->act_req = req;
dbus_message_append_args (message, DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &user_name,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &password_items, password_count,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data_items, count,
DBUS_TYPE_INVALID);
/* Send the message to the daemon again, now that its running. */
dbus_error_init (&error);
reply = dbus_connection_send_with_reply_and_block (manager->app_data->dbus_connection, message, -1, &error);
dbus_message_unref (message);
if (dbus_error_is_set (&error))
{
nm_warning ("Could not activate the VPN service. dbus says: '%s' '%s'.", error.name, error.message);
dbus_error_free (&error);
nm_vpn_manager_set_active_vpn_connection (manager, NULL);
return;
}
if (reply)
dbus_message_unref (reply);
nm_vpn_service_start_connection (service, req);
}
@ -732,50 +375,105 @@ void nm_vpn_manager_activate_vpn_connection (NMVPNManager *manager, NMVPNConnect
*/
void nm_vpn_manager_deactivate_vpn_connection (NMVPNManager *manager)
{
DBusMessage * message;
char * op;
NMVPNService * service;
const char * service_name;
NMVPNConnection * active;
NMDevice * dev;
NMVPNConnection * vpn;
g_return_if_fail (manager != NULL);
if (!(active = nm_vpn_manager_get_active_vpn_connection (manager)))
if (!manager->act_req)
return;
nm_vpn_connection_ref (active);
/* Construct a new method call with the correct service and object path */
service = nm_vpn_connection_get_service (active);
service_name = nm_vpn_service_get_service_name (service);
op = construct_op_from_service_name (service_name);
message = dbus_message_new_method_call (service_name, op, service_name, "stopConnection");
g_free (op);
if (!message)
if (nm_vpn_act_request_is_activating (manager->act_req) || nm_vpn_act_request_is_activated (manager->act_req))
{
nm_warning ("Couldn't allocate dbus message.");
goto out;
if (nm_vpn_act_request_is_activated (manager->act_req))
{
vpn = nm_vpn_act_request_get_connection (manager->act_req);
g_assert (vpn);
nm_vpn_connection_deactivate (vpn);
}
service = nm_vpn_act_request_get_service (manager->act_req);
g_assert (service);
nm_vpn_service_stop_connection (service, manager->act_req);
}
/* Call the specific VPN service, let dbus activate it if needed */
dbus_connection_send (manager->app_data->dbus_connection, message, NULL);
dbus_message_unref (message);
nm_vpn_act_request_unref (manager->act_req);
manager->act_req = NULL;
}
out:
nm_vpn_connection_unref (active);
if ((dev = nm_get_active_device (manager->app_data)))
nm_system_device_set_from_ip4_config (dev);
static gboolean nm_vpn_manager_vpn_activation_failed (gpointer user_data)
{
NMVPNActRequest * req = (NMVPNActRequest *) user_data;
NMVPNManager * manager;
g_assert (req);
manager = nm_vpn_act_request_get_manager (req);
g_assert (manager);
if (manager->act_req == req)
nm_vpn_manager_deactivate_vpn_connection (manager);
return FALSE;
}
void nm_vpn_manager_schedule_vpn_activation_failed (NMVPNManager *manager, NMVPNActRequest *req)
{
GSource * source = NULL;
g_return_if_fail (manager != NULL);
g_return_if_fail (req != NULL);
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_vpn_manager_vpn_activation_failed, req, NULL);
g_source_attach (source, manager->app_data->main_context);
g_source_unref (source);
}
static gboolean nm_vpn_manager_vpn_connection_died (gpointer user_data)
{
NMVPNActRequest * req = (NMVPNActRequest *) user_data;
NMVPNManager * manager;
g_assert (req);
manager = nm_vpn_act_request_get_manager (req);
g_assert (manager);
if (manager->act_req == req)
nm_vpn_manager_deactivate_vpn_connection (manager);
return FALSE;
}
void nm_vpn_manager_schedule_vpn_connection_died (NMVPNManager *manager, NMVPNActRequest *req)
{
GSource * source = NULL;
g_return_if_fail (manager != NULL);
g_return_if_fail (req != NULL);
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_vpn_manager_vpn_connection_died, req, NULL);
g_source_attach (source, manager->app_data->main_context);
g_source_unref (source);
}
/*********************************************************************/
static GSList *nm_vpn_manager_load_services (void)
static void nm_vpn_manager_load_services (NMVPNManager *manager, GHashTable *table)
{
GSList *list = NULL;
GDir *vpn_dir;
g_return_if_fail (manager != NULL);
g_return_if_fail (table != NULL);
/* Load allowed service names */
if ((vpn_dir = g_dir_open (VPN_SERVICE_FILE_PATH, 0, NULL)))
{
@ -793,7 +491,7 @@ static GSList *nm_vpn_manager_load_services (void)
if (split_contents)
{
int i, len;
NMVPNService * service = nm_vpn_service_new ();
NMVPNService * service = nm_vpn_service_new (manager, manager->app_data);
gboolean have_name = FALSE;
gboolean have_service = FALSE;
gboolean have_program = FALSE;
@ -867,7 +565,7 @@ static GSList *nm_vpn_manager_load_services (void)
{
nm_info ("Adding VPN service '%s' with name '%s' and program '%s'", nm_vpn_service_get_service_name (service),
nm_vpn_service_get_name (service), nm_vpn_service_get_program (service));
list = g_slist_append (list, service);
g_hash_table_insert (table, (char *) nm_vpn_service_get_service_name (service), service);
}
else
nm_vpn_service_unref (service);
@ -879,7 +577,5 @@ static GSList *nm_vpn_manager_load_services (void)
g_dir_close (vpn_dir);
}
return list;
}

View file

@ -23,23 +23,28 @@
#include <dbus/dbus.h>
#include "NetworkManagerMain.h"
#include "nm-vpn-connection.h"
#include "nm-vpn-service.h"
NMVPNManager * nm_vpn_manager_new (NMData *app_data);
void nm_vpn_manager_clear_connections (NMVPNManager *manager);
NMVPNConnection * nm_vpn_manager_add_connection (NMVPNManager *manager, const char *name, const char *service_name, const char *user_name);
void nm_vpn_manager_remove_connection (NMVPNManager *manager, NMVPNConnection *vpn);
char ** nm_vpn_manager_get_connection_names (NMVPNManager *manager);
void nm_vpn_manager_dispose (NMVPNManager *manager);
NMVPNConnection * nm_vpn_manager_get_active_vpn_connection (NMVPNManager *manager);
NMVPNActRequest * nm_vpn_manager_get_vpn_act_request (NMVPNManager *manager);
void nm_vpn_manager_activate_vpn_connection (NMVPNManager *manager, NMVPNConnection *vpn, char **password_items, int password_count, char **data_items, int count);
void nm_vpn_manager_activate_vpn_connection (NMVPNManager *manager, NMVPNConnection *vpn, char **password_items,
int password_count, char **data_items, int data_count);
void nm_vpn_manager_deactivate_vpn_connection (NMVPNManager *manager);
NMVPNConnection * nm_vpn_manager_find_connection_by_name (NMVPNManager *manager, const char *con_name);
NMVPNService * nm_vpn_manager_find_service_by_name (NMVPNManager *manager, const char *service_name);
gboolean nm_vpn_manager_process_signal (NMVPNManager *manager, DBusMessage *signal);
gboolean nm_vpn_manager_process_name_owner_changed (NMVPNManager *manager, const char *service, const char *old_owner, const char *new_owner);
void nm_vpn_manager_schedule_vpn_activation_failed(NMVPNManager *manager, NMVPNActRequest *req);
void nm_vpn_manager_schedule_vpn_connection_died (NMVPNManager *manager, NMVPNActRequest *req);
#endif /* NM_VPN_MANAGER_H */

View file

@ -20,28 +20,67 @@
*/
#include <glib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <dbus/dbus.h>
#include "NetworkManagerDbus.h"
#include "nm-dbus-vpn.h"
#include "nm-vpn-service.h"
#include "nm-vpn-act-request.h"
#include "nm-utils.h"
struct NMVPNService
{
int refcount;
char *name;
char *service;
char *program;
NMVPNState state;
int refcount;
NMVPNManager * manager;
NMData * app_data;
gboolean watch_active;
char * name;
char * service;
char * program;
NMVPNState state;
};
NMVPNService *nm_vpn_service_new (void)
static void nm_vpn_service_add_watch (NMVPNService *service);
static void nm_vpn_service_remove_watch (NMVPNService *service);
static void nm_vpn_service_stop_connection_internal (NMVPNService *service);
static void print_vpn_config (guint32 ip4_vpn_gateway,
const char *tundev,
guint32 ip4_internal_address,
gint32 ip4_internal_netmask,
guint32 *ip4_internal_dns,
guint32 ip4_internal_dns_len,
guint32 *ip4_internal_nbns,
guint32 ip4_internal_nbns_len,
const char *dns_domain,
const char *login_banner);
static void nm_vpn_service_schedule_stage1_daemon_exec (NMVPNService *service, NMVPNActRequest *req);
static void nm_vpn_service_schedule_stage3_connect (NMVPNService *service, NMVPNActRequest *req);
static void nm_vpn_service_schedule_stage2_daemon_wait (NMVPNService *service, NMVPNActRequest *req);
static void nm_vpn_service_schedule_stage4_ip_config_get_timeout (NMVPNService *service, NMVPNActRequest *req);
static void nm_vpn_service_cancel_callback (NMVPNService *service, NMVPNActRequest *req);
/*
* nm_vpn_service_new
*
* Create a new VPNService object
*
*/
NMVPNService *nm_vpn_service_new (NMVPNManager *manager, NMData *app_data)
{
NMVPNService *service = g_malloc0 (sizeof (NMVPNService));
service->refcount = 1;
service->state = NM_VPN_STATE_SHUTDOWN;
service->app_data = app_data;
service->manager = manager;
return service;
}
@ -103,6 +142,10 @@ void nm_vpn_service_set_service_name (NMVPNService *service, const char *name)
if (service->service)
g_free (service->service);
service->service = g_strdup (name);
/* If the VPN daemon is currently running, tell it to stop */
if (!dbus_bus_name_has_owner (service->app_data->dbus_connection, service->service, NULL))
nm_vpn_service_stop_connection_internal (service);
}
@ -132,7 +175,7 @@ NMVPNState nm_vpn_service_get_state (NMVPNService *service)
}
void nm_vpn_service_set_state (NMVPNService *service, const NMVPNState state)
static void nm_vpn_service_set_state (NMVPNService *service, const NMVPNState state)
{
g_return_if_fail (service != NULL);
@ -140,35 +183,768 @@ void nm_vpn_service_set_state (NMVPNService *service, const NMVPNState state)
}
gboolean nm_vpn_service_exec_daemon (NMVPNService *service)
DBusConnection *nm_vpn_service_get_dbus_connection (NMVPNService *service)
{
GPtrArray *vpn_argv;
GError *error = NULL;
GPid pid;
g_return_val_if_fail (service != NULL, NULL);
g_return_val_if_fail (service != NULL, FALSE);
return service->app_data->dbus_connection;
}
if (!nm_vpn_service_get_program (service))
return FALSE;
/*
* construct_op_from_service_name
*
* Construct an object path from a dbus service name by replacing
* all "." in the service with "/" and prepending a "/" to the
* object path.
*
*/
static char *construct_op_from_service_name (const char *service_name)
{
char **split = NULL;
char *temp1;
char *temp2;
g_return_val_if_fail (service_name != NULL, NULL);
if (!(split = g_strsplit (service_name, ".", 0)))
return NULL;
temp1 = g_strjoinv ("/", split);
g_strfreev (split);
temp2 = g_strdup_printf ("/%s", temp1);
g_free (temp1);
return temp2;
}
/*
* nm_vpn_service_act_request_failed
*
* Clean up after an activation request and tell the VPN manager that it
* has failed.
*
*/
void nm_vpn_service_act_request_failed (NMVPNService *service, NMVPNActRequest *req)
{
NMVPNConnection *vpn;
g_return_if_fail (service != NULL);
g_return_if_fail (req != NULL);
/* Sanity checks */
if (nm_vpn_act_request_get_service (req) != service)
return;
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_vpn_service_cancel_callback (service, req);
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_FAILED);
nm_info ("VPN Activation (%s) failed.", nm_vpn_connection_get_name (vpn));
nm_vpn_act_request_unref (req);
nm_vpn_manager_schedule_vpn_activation_failed (service->manager, req);
}
static void nm_vpn_service_activation_success (NMVPNService *service, NMVPNActRequest *req)
{
GSource * source = NULL;
NMVPNConnection * vpn = NULL;
g_assert (service != NULL);
g_assert (req != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_vpn_service_cancel_callback (service, req);
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_ACTIVATED);
nm_info ("VPN Activation (%s) successful.", nm_vpn_connection_get_name (vpn));
}
/*
* nm_vpn_service_start_connection
*
* Kick off the VPN connection process.
*
*/
void nm_vpn_service_start_connection (NMVPNService *service, NMVPNActRequest *req)
{
g_return_if_fail (service != NULL);
g_return_if_fail (req != NULL);
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_PREPARE);
nm_vpn_service_add_watch (service);
/* Start the daemon if it's not already running */
nm_vpn_act_request_ref (req);
if (!dbus_bus_name_has_owner (service->app_data->dbus_connection, service->service, NULL))
nm_vpn_service_schedule_stage1_daemon_exec (service, req);
else
nm_vpn_service_schedule_stage3_connect (service, req);
}
/*
* nm_vpn_service_stage_1_daemon_exec
*
* Execute the VPN service daemon.
*
*/
static gboolean nm_vpn_service_stage1_daemon_exec (gpointer user_data)
{
NMVPNActRequest * req = (NMVPNActRequest *) user_data;
NMVPNService * service;
GPtrArray * vpn_argv;
GError * error = NULL;
GPid pid;
g_assert (req != NULL);
service = nm_vpn_act_request_get_service (req);
g_assert (service != NULL);
g_assert (service->program != NULL);
nm_vpn_act_request_set_callback_id (req, 0);
vpn_argv = g_ptr_array_new ();
g_ptr_array_add (vpn_argv, (char *) nm_vpn_service_get_program (service));
g_ptr_array_add (vpn_argv, service->program);
g_ptr_array_add (vpn_argv, NULL);
if (!g_spawn_async (NULL, (char **) vpn_argv->pdata, NULL, 0, NULL, NULL, &pid, &error))
{
g_ptr_array_free (vpn_argv, TRUE);
nm_warning ("Could not activate the VPN service '%s'. error: '%s'.", nm_vpn_service_get_service_name (service), error->message);
nm_warning ("nm_vpn_service_stage1_daemon_exec(%s): could not launch the VPN service. error: '%s'.", service->service, error->message);
g_error_free (error);
return FALSE;
nm_vpn_service_act_request_failed (service, req);
goto out;
}
g_ptr_array_free (vpn_argv, TRUE);
nm_info ("Activated the VPN service '%s' with PID %d.", nm_vpn_service_get_service_name (service), pid);
nm_info ("nm_vpn_service_stage1_daemon_exec(%s): execed the VPN service, PID is %d.", service->service, pid);
/* Wait a bit for the daemon to start up */
/* FIXME: don't sleep, keep retrying dbus message or something */
sleep (1);
nm_vpn_service_schedule_stage2_daemon_wait (service, req);
out:
return FALSE;
}
static void nm_vpn_service_schedule_stage1_daemon_exec (NMVPNService *service, NMVPNActRequest *req)
{
GSource * source = NULL;
NMVPNConnection * vpn = NULL;
guint id;
g_assert (service != NULL);
g_assert (req != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_PREPARE);
nm_vpn_service_set_state (service, NM_VPN_STATE_SHUTDOWN);
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_vpn_service_stage1_daemon_exec, req, NULL);
id = g_source_attach (source, service->app_data->main_context);
nm_vpn_act_request_set_callback_id (req, id);
g_source_unref (source);
nm_info ("VPN Activation (%s) Stage 1 (Connection Prepare) scheduled...", nm_vpn_connection_get_name (vpn));
}
/*
* nm_vpn_service_stage2_daemon_wait
*
* Wait until the VPN daemon has become active.
*
*/
gboolean nm_vpn_service_stage2_daemon_wait (gpointer user_data)
{
NMVPNActRequest * req = (NMVPNActRequest *) user_data;
NMVPNService * service;
g_assert (req != NULL);
service = nm_vpn_act_request_get_service (req);
g_assert (service != NULL);
nm_vpn_act_request_set_callback_id (req, 0);
if (service->state == NM_VPN_STATE_STOPPED)
nm_vpn_service_schedule_stage3_connect (service, req);
else if (nm_vpn_act_request_get_daemon_wait_count (req) >= 4)
{
/* We only wait 2s (4 * 500 milliseconds) for the service to start up */
nm_vpn_service_act_request_failed (service, req);
}
else
nm_vpn_service_schedule_stage2_daemon_wait (service, req);
return FALSE;
}
static void nm_vpn_service_schedule_stage2_daemon_wait (NMVPNService *service, NMVPNActRequest *req)
{
GSource * source = NULL;
NMVPNConnection * vpn = NULL;
guint id;
g_assert (service != NULL);
g_assert (req != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_PREPARE);
nm_vpn_act_request_set_daemon_wait_count (req, nm_vpn_act_request_get_daemon_wait_count (req) + 1);
source = g_timeout_source_new (500);
g_source_set_callback (source, (GSourceFunc) nm_vpn_service_stage2_daemon_wait, req, NULL);
id = g_source_attach (source, service->app_data->main_context);
nm_vpn_act_request_set_callback_id (req, id);
g_source_unref (source);
nm_info ("VPN Activation (%s) Stage 2 (Connection Prepare Wait) scheduled...", nm_vpn_connection_get_name (vpn));
}
static void nm_vpn_service_stage3_connect_cb (DBusPendingCall *pcall, void *user_data)
{
DBusMessage * reply;
NMVPNActRequest * req = (NMVPNActRequest *) user_data;
NMVPNService * service;
NMVPNConnection * vpn;
g_assert (pcall != NULL);
g_assert (req != NULL);
service = nm_vpn_act_request_get_service (req);
g_assert (service != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_info ("VPN Activation (%s) Stage 3 (Connect) reply received.", nm_vpn_connection_get_name (vpn));
if (!(reply = dbus_pending_call_steal_reply (pcall)))
{
nm_warning ("nm_vpn_service_stage3_connect_cb(%s): could not obtain VPN service's reply.", service->service);
nm_vpn_service_act_request_failed (service, req);
goto out;
}
if (message_is_error (reply))
{
const char *member = dbus_message_get_member (reply);
char *message;
if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &message, NULL))
message = (char *) "";
nm_warning ("nm_vpn_service_stage3_connect_cb(%s): could not start the VPN '%s'. dbus says: '%s' '%s'.",
service->service, nm_vpn_connection_get_name (vpn), member, message);
nm_vpn_service_act_request_failed (service, req);
}
else
{
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_IP_CONFIG_GET);
nm_vpn_service_schedule_stage4_ip_config_get_timeout (service, req);
nm_info ("VPN Activation (%s) Stage 4 (IP Config Get) reply expected soon...", nm_vpn_connection_get_name (vpn));
}
dbus_message_unref (reply);
out:
dbus_pending_call_unref (pcall);
}
static gboolean nm_vpn_service_stage3_connect (gpointer user_data)
{
NMVPNActRequest * req = (NMVPNActRequest *) user_data;
NMVPNService * service;
NMVPNConnection * vpn;
char * op;
const char * name;
const char * user_name;
char ** password_items;
dbus_uint32_t password_count;
char ** data_items;
dbus_uint32_t data_count;
DBusError error;
DBusMessage * message;
DBusPendingCall * pcall = NULL;
g_assert (req != NULL);
service = nm_vpn_act_request_get_service (req);
g_assert (service != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn != NULL);
nm_vpn_act_request_set_callback_id (req, 0);
/* Send the start vpn request to the daemon */
op = construct_op_from_service_name (service->service);
message = dbus_message_new_method_call (service->service, op, service->service, "startConnection");
g_free (op);
if (!message)
{
nm_warning ("nm_vpn_service_stage3_connect(%s): couldn't allocate dbus message.", service->service);
nm_vpn_service_act_request_failed (service, req);
return FALSE;
}
name = nm_vpn_connection_get_name (vpn);
user_name = nm_vpn_connection_get_user_name (vpn);
password_items = (char **) nm_vpn_act_request_get_password_items (req, &password_count);
data_items = (char **) nm_vpn_act_request_get_data_items (req, &data_count);
dbus_message_append_args (message, DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &user_name,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &password_items, password_count,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data_items, data_count,
DBUS_TYPE_INVALID);
dbus_connection_send_with_reply (service->app_data->dbus_connection, message, &pcall, -1);
if (pcall)
{
dbus_pending_call_set_notify (pcall, nm_vpn_service_stage3_connect_cb, req, NULL);
nm_info ("VPN Activation (%s) Stage 3 (Connect) reply expected soon...", nm_vpn_connection_get_name (vpn));
}
else
nm_vpn_service_act_request_failed (service, req);
dbus_message_unref (message);
return FALSE;
}
static void nm_vpn_service_schedule_stage3_connect (NMVPNService *service, NMVPNActRequest *req)
{
GSource * source = NULL;
NMVPNConnection * vpn = NULL;
guint id;
g_assert (service != NULL);
g_assert (req != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_CONNECT);
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_vpn_service_stage3_connect, req, NULL);
id = g_source_attach (source, service->app_data->main_context);
nm_vpn_act_request_set_callback_id (req, id);
g_source_unref (source);
nm_info ("VPN Activation (%s) Stage 3 (Connect) scheduled...", nm_vpn_connection_get_name (vpn));
}
static gboolean nm_vpn_service_stage4_ip_config_get_timeout (gpointer *user_data)
{
NMVPNActRequest * req = (NMVPNActRequest *) user_data;
NMVPNService * service;
NMVPNConnection * vpn;
g_assert (req != NULL);
service = nm_vpn_act_request_get_service (req);
g_assert (service != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn != NULL);
nm_vpn_act_request_set_callback_id (req, 0);
/* If the activation request's state is still IP_CONFIG_GET and we're
* in this timeout, cancel activation because it's taken too long.
*/
if (nm_vpn_act_request_get_stage (req) == NM_VPN_ACT_STAGE_IP_CONFIG_GET)
{
nm_info ("VPN Activation (%s) Stage 4 (IP Config Get) timeout exceeded.", nm_vpn_connection_get_name (vpn));
nm_vpn_service_act_request_failed (service, req);
}
return FALSE;
}
static void nm_vpn_service_schedule_stage4_ip_config_get_timeout (NMVPNService *service, NMVPNActRequest *req)
{
GSource * source = NULL;
NMVPNConnection * vpn = NULL;
guint id;
g_assert (service != NULL);
g_assert (req != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_IP_CONFIG_GET);
/* 20 second timeout waiting for IP config signal from VPN service */
source = g_timeout_source_new (20000);
g_source_set_callback (source, (GSourceFunc) nm_vpn_service_stage4_ip_config_get_timeout, req, NULL);
id = g_source_attach (source, service->app_data->main_context);
nm_vpn_act_request_set_callback_id (req, id);
g_source_unref (source);
nm_info ("VPN Activation (%s) Stage 4 (IP Config Get) timeout scheduled...", nm_vpn_connection_get_name (vpn));
}
static void nm_vpn_service_cancel_callback (NMVPNService *service, NMVPNActRequest *req)
{
guint id;
g_return_if_fail (service != NULL);
g_return_if_fail (req != NULL);
if ((id = nm_vpn_act_request_get_callback_id (req)) != 0)
{
g_source_destroy (g_main_context_find_source_by_id (service->app_data->main_context, id));
nm_vpn_act_request_set_callback_id (req, 0);
}
}
/*
* nm_vpn_service_stage4_ip_config_get
*
* Configure a device with IPv4 config info in response the the VPN daemon.
*
*/
static void nm_vpn_service_stage4_ip_config_get (NMVPNService *service, NMVPNActRequest *req, DBusMessage *message)
{
NMVPNConnection * vpn;
guint32 ip4_vpn_gateway;
char * tundev;
guint32 ip4_internal_address;
guint32 ip4_internal_netmask;
guint32 * ip4_internal_dns;
guint32 ip4_internal_dns_len;
guint32 * ip4_internal_nbns;
guint32 ip4_internal_nbns_len;
char * dns_domain;
char * login_banner;
gboolean success = FALSE;
g_return_if_fail (service != NULL);
g_return_if_fail (message != NULL);
g_return_if_fail (req != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_info ("VPN Activation (%s) Stage 4 (IP Config Get) reply received.", nm_vpn_connection_get_name (vpn));
if (dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ip4_vpn_gateway,
DBUS_TYPE_STRING, &tundev,
DBUS_TYPE_UINT32, &ip4_internal_address,
DBUS_TYPE_UINT32, &ip4_internal_netmask,
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &ip4_internal_dns, &ip4_internal_dns_len,
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &ip4_internal_nbns, &ip4_internal_nbns_len,
DBUS_TYPE_STRING, &dns_domain,
DBUS_TYPE_STRING, &login_banner, DBUS_TYPE_INVALID))
{
NMIP4Config * config;
NMDevice * parent_dev;
guint32 i;
#if 0
print_vpn_config (ip4_vpn_gateway, tundev, ip4_internal_address, ip4_internal_netmask,
ip4_internal_dns, ip4_internal_dns_len, ip4_internal_nbns, ip4_internal_nbns_len,
dns_domain, login_banner);
#endif
config = nm_ip4_config_new ();
nm_ip4_config_set_address (config, ip4_internal_address);
if (ip4_internal_netmask)
nm_ip4_config_set_netmask (config, ip4_internal_netmask);
else
nm_ip4_config_set_netmask (config, 0x00FF); /* Class C */
nm_ip4_config_set_gateway (config, ip4_vpn_gateway);
if (strlen (dns_domain))
nm_ip4_config_add_domain (config, dns_domain);
for (i = 0; i < ip4_internal_dns_len; i++)
{
if (ip4_internal_dns[i] != 0)
nm_ip4_config_add_nameserver (config, ip4_internal_dns[i]);
}
parent_dev = nm_vpn_act_request_get_parent_dev (req);
g_assert (parent_dev);
if (nm_vpn_connection_set_config (vpn, tundev, parent_dev, config))
{
if (login_banner && strlen (login_banner))
nm_dbus_vpn_signal_vpn_login_banner (service->app_data->dbus_connection, vpn, login_banner);
success = TRUE;
}
}
if (!success)
{
nm_warning ("nm_vpn_service_stage4_ip_config_get(%s): did not receive valid IP config information.", service->service);
nm_vpn_service_act_request_failed (service, req);
}
else
nm_vpn_service_activation_success (service, req);
}
static void nm_vpn_service_stop_connection_internal (NMVPNService *service)
{
DBusMessage * message;
char * op;
g_return_if_fail (service != NULL);
/* Construct a new method call with the correct service and object path */
op = construct_op_from_service_name (service->service);
if ((message = dbus_message_new_method_call (service->service, op, service->service, "stopConnection")))
{
dbus_connection_send (service->app_data->dbus_connection, message, NULL);
dbus_message_unref (message);
}
else
nm_warning ("nm_vpn_service_stop_connection(): error, couldn't allocate dbus message.");
g_free (op);
}
void nm_vpn_service_stop_connection (NMVPNService *service, NMVPNActRequest *req)
{
NMVPNConnection *vpn;
g_return_if_fail (service != NULL);
g_return_if_fail (req != NULL);
vpn = nm_vpn_act_request_get_connection (req);
g_assert (vpn);
nm_vpn_service_cancel_callback (service, req);
nm_vpn_act_request_set_stage (req, NM_VPN_ACT_STAGE_DISCONNECTED);
/* Ensure we can stop the connection in this state */
if ((service->state != NM_VPN_STATE_STARTED) && (service->state != NM_VPN_STATE_STARTING))
{
nm_info ("nm_vpn_service_start_connection(%s): could not stop connection '%s' because service was not STARTED.",
service->service, nm_vpn_connection_get_name (vpn));
return;
}
nm_vpn_service_stop_connection_internal (service);
nm_vpn_service_set_state (service, NM_VPN_STATE_STOPPED);
}
static void nm_vpn_service_add_watch (NMVPNService *service)
{
char * match_string = NULL;
g_return_if_fail (service != NULL);
if (service->watch_active)
return;
/* Add a dbus filter for this connection's service name so its signals
* get delivered to us.
*/
match_string = g_strdup_printf ("type='signal',"
"interface='%s',"
"sender='%s'", service->service, service->service);
dbus_bus_add_match (service->app_data->dbus_connection, match_string, NULL);
g_free (match_string);
service->watch_active = TRUE;
}
static void nm_vpn_service_remove_watch (NMVPNService *service)
{
char * match_string = NULL;
g_return_if_fail (service != NULL);
if (!service->watch_active)
return;
match_string = g_strdup_printf ("type='signal',"
"interface='%s',"
"sender='%s'", service->service, service->service);
dbus_bus_remove_match (service->app_data->dbus_connection, match_string, NULL);
g_free (match_string);
service->watch_active = FALSE;
}
static inline gboolean same_service_name (NMVPNService *service, NMVPNConnection *vpn)
{
g_return_val_if_fail (service != NULL, FALSE);
g_return_val_if_fail (vpn != NULL, FALSE);
return (!strcmp (nm_vpn_service_get_service_name (service), nm_vpn_connection_get_service_name (vpn)));
}
gboolean nm_vpn_service_name_owner_changed (NMVPNService *service, NMVPNActRequest *req, const char *old, const char *new)
{
NMVPNConnection * vpn;
gboolean valid_vpn = FALSE;
gboolean old_owner_good = (old && strlen (old));
gboolean new_owner_good = (new && strlen (new));
g_return_val_if_fail (service != NULL, FALSE);
g_return_val_if_fail (req != NULL, FALSE);
if (req && (vpn = nm_vpn_act_request_get_connection (req)))
valid_vpn = same_service_name (service, vpn);
if (!old_owner_good && new_owner_good)
{
/* VPN service started. */
nm_vpn_service_add_watch (service);
nm_vpn_service_set_state (service, NM_VPN_STATE_INIT);
}
else if (old_owner_good && !new_owner_good)
{
/* VPN service went away. */
nm_vpn_service_set_state (service, NM_VPN_STATE_SHUTDOWN);
nm_vpn_service_remove_watch (service);
if (valid_vpn)
{
nm_vpn_act_request_unref (req);
nm_vpn_manager_schedule_vpn_connection_died (service->manager, req);
}
}
return TRUE;
}
gboolean nm_vpn_service_process_signal (NMVPNService *service, NMVPNActRequest *req, DBusMessage *message)
{
NMVPNConnection * vpn = NULL;
gboolean valid_vpn = FALSE;
g_return_val_if_fail (service != NULL, FALSE);
g_return_val_if_fail (message != NULL, FALSE);
if (req && (vpn = nm_vpn_act_request_get_connection (req)))
valid_vpn = same_service_name (service, vpn);
if ( dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED)
|| dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED)
|| dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED)
|| dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD)
|| dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD))
{
const char * member = dbus_message_get_member (message);
char * error_msg;
if (valid_vpn)
{
if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID))
error_msg = (char *) "";
nm_warning ("VPN failed for service '%s', signal '%s', with message '%s'.", service->service, member, error_msg);
nm_dbus_vpn_signal_vpn_failed (service->app_data->dbus_connection, member, vpn, error_msg);
/* Don't deal with VPN Connection stopping here, we'll do that when we get the STOPPED or STOPPING signal below */
}
}
else if (dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_STATE_CHANGE))
{
dbus_uint32_t old_state_int;
dbus_uint32_t new_state_int;
if (dbus_message_get_args (message, NULL, DBUS_TYPE_UINT32, &old_state_int, DBUS_TYPE_UINT32, &new_state_int, DBUS_TYPE_INVALID))
{
NMVPNState old_state = (NMVPNState) old_state_int;
NMVPNState new_state = (NMVPNState) new_state_int;
nm_info ("VPN service '%s' signaled new state %d, old state %d.", service->service, new_state, old_state);
nm_vpn_service_set_state (service, new_state);
/* If the VPN daemon state is now stopped and it was starting, clear the active connection */
if (((new_state == NM_VPN_STATE_STOPPED) || (new_state == NM_VPN_STATE_SHUTDOWN) || (new_state == NM_VPN_STATE_STOPPING))
&& ((old_state == NM_VPN_STATE_STARTED) || (old_state == NM_VPN_STATE_STARTING)))
{
nm_vpn_act_request_unref (req);
nm_vpn_manager_schedule_vpn_connection_died (service->manager, req);
}
}
}
else if (valid_vpn && dbus_message_is_signal (message, service->service, NM_DBUS_VPN_SIGNAL_IP4_CONFIG))
nm_vpn_service_stage4_ip_config_get (service, req, message);
return TRUE;
}
/*
* Prints config returned from the service daemo
*/
static void print_vpn_config (guint32 ip4_vpn_gateway,
const char *tundev,
guint32 ip4_internal_address,
gint32 ip4_internal_netmask,
guint32 *ip4_internal_dns,
guint32 ip4_internal_dns_len,
guint32 *ip4_internal_nbns,
guint32 ip4_internal_nbns_len,
const char *dns_domain,
const char *login_banner)
{
struct in_addr temp_addr;
guint32 i;
temp_addr.s_addr = ip4_vpn_gateway;
nm_info ("VPN Gateway: %s", inet_ntoa (temp_addr));
nm_info ("Tunnel Device: %s", tundev);
temp_addr.s_addr = ip4_internal_address;
nm_info ("Internal IP4 Address: %s", inet_ntoa (temp_addr));
temp_addr.s_addr = ip4_internal_netmask;
nm_info ("Internal IP4 Netmask: %s", inet_ntoa (temp_addr));
for (i = 0; i < ip4_internal_dns_len; i++)
{
if (ip4_internal_dns[i] != 0)
{
temp_addr.s_addr = ip4_internal_dns[i];
nm_info ("Internal IP4 DNS: %s", inet_ntoa (temp_addr));
}
}
for (i = 0; i < ip4_internal_nbns_len; i++)
{
if (ip4_internal_nbns[i] != 0)
{
temp_addr.s_addr = ip4_internal_nbns[i];
nm_info ("Internal IP4 NBNS: %s", inet_ntoa (temp_addr));
}
}
nm_info ("DNS Domain: '%s'", dns_domain);
nm_info ("Login Banner:");
nm_info ("-----------------------------------------");
nm_info ("%s", login_banner);
nm_info ("-----------------------------------------");
}

View file

@ -25,27 +25,32 @@
#include <dbus/dbus.h>
#include "NetworkManager.h"
#include "NetworkManagerMain.h"
#include "nm-vpn-connection.h"
typedef struct NMVPNService NMVPNService;
NMVPNService * nm_vpn_service_new (void);
void nm_vpn_service_ref (NMVPNService *service);
void nm_vpn_service_unref (NMVPNService *service);
NMVPNService * nm_vpn_service_new (NMVPNManager *manager, NMData *app_data);
const char * nm_vpn_service_get_name (NMVPNService *service);
void nm_vpn_service_set_name (NMVPNService *service, const char *name);
void nm_vpn_service_ref (NMVPNService *service);
void nm_vpn_service_unref (NMVPNService *service);
const char * nm_vpn_service_get_service_name (NMVPNService *service);
void nm_vpn_service_set_service_name (NMVPNService *service, const char *name);
const char * nm_vpn_service_get_name (NMVPNService *service);
void nm_vpn_service_set_name (NMVPNService *service, const char *name);
const char * nm_vpn_service_get_program (NMVPNService *service);
void nm_vpn_service_set_program (NMVPNService *service, const char *program);
const char * nm_vpn_service_get_service_name (NMVPNService *service);
void nm_vpn_service_set_service_name (NMVPNService *service, const char *name);
NMVPNState nm_vpn_service_get_state (NMVPNService *service);
void nm_vpn_service_set_state (NMVPNService *service, const NMVPNState state);
const char * nm_vpn_service_get_program (NMVPNService *service);
void nm_vpn_service_set_program (NMVPNService *service, const char *program);
gboolean nm_vpn_service_exec_daemon (NMVPNService *service);
NMVPNState nm_vpn_service_get_state (NMVPNService *service);
gboolean nm_vpn_service_name_owner_changed (NMVPNService *service, NMVPNActRequest *req, const char *old, const char *new);
gboolean nm_vpn_service_process_signal (NMVPNService *service, NMVPNActRequest *req, DBusMessage *message);
void nm_vpn_service_start_connection (NMVPNService *service, NMVPNActRequest *req);
void nm_vpn_service_stop_connection (NMVPNService *service, NMVPNActRequest *req);
#endif

View file

@ -1024,6 +1024,7 @@ static DBusHandlerResult nm_vpnc_dbus_filter (DBusConnection *con, DBusMessage *
{
/* If NM goes away, we don't stick around */
nm_vpnc_dbus_handle_stop_vpn (data);
g_main_loop_quit (data->loop);
}
}
}