From be3a380b08ab2d07f257eff662fa49cfd9e109f6 Mon Sep 17 00:00:00 2001 From: Tambet Ingo Date: Wed, 12 Sep 2007 16:18:15 +0000 Subject: [PATCH] 2007-09-12 Tambet Ingo * src/nm-vpnc-service.[ch]: Rewrite. Derive from NMVPNPlugin. * src/nm-vpnc-service-vpnc-helper.c: Rewrite using dbus-glib. * auth-dialog/main.c: Populate the properties hash with the * passwords. * properties/nm-vpnc.c: The VPN connection properties are all * hash tables now. * src/nm-utils.[ch]: Remove. Use the same things from * libnm-util. * configure.in: Check libnm_glib module as well now that we use * NMVPNPlugin. git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2797 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- vpn-daemons/vpnc/ChangeLog | 14 + vpn-daemons/vpnc/auth-dialog/Makefile.am | 1 + vpn-daemons/vpnc/auth-dialog/main.c | 17 +- vpn-daemons/vpnc/configure.in | 2 +- vpn-daemons/vpnc/properties/nm-vpnc.c | 198 +-- vpn-daemons/vpnc/src/Makefile.am | 9 +- vpn-daemons/vpnc/src/nm-utils.c | 132 -- vpn-daemons/vpnc/src/nm-utils.h | 131 -- .../vpnc/src/nm-vpnc-service-vpnc-helper.c | 418 +++--- vpn-daemons/vpnc/src/nm-vpnc-service.c | 1266 +++-------------- vpn-daemons/vpnc/src/nm-vpnc-service.h | 73 +- 11 files changed, 537 insertions(+), 1724 deletions(-) delete mode 100644 vpn-daemons/vpnc/src/nm-utils.c delete mode 100644 vpn-daemons/vpnc/src/nm-utils.h diff --git a/vpn-daemons/vpnc/ChangeLog b/vpn-daemons/vpnc/ChangeLog index bda4f06a4c..93bc75d87d 100644 --- a/vpn-daemons/vpnc/ChangeLog +++ b/vpn-daemons/vpnc/ChangeLog @@ -1,3 +1,17 @@ +2007-09-12 Tambet Ingo + + * src/nm-vpnc-service.[ch]: Rewrite. Derive from NMVPNPlugin. + + * src/nm-vpnc-service-vpnc-helper.c: Rewrite using dbus-glib. + + * auth-dialog/main.c: Populate the properties hash with the passwords. + + * properties/nm-vpnc.c: The VPN connection properties are all hash tables now. + + * src/nm-utils.[ch]: Remove. Use the same things from libnm-util. + + * configure.in: Check libnm_glib module as well now that we use NMVPNPlugin. + 2007-08-15 Tambet Ingo * nm-vpnc-service.name.in: Use upper-case macro names as that's what the diff --git a/vpn-daemons/vpnc/auth-dialog/Makefile.am b/vpn-daemons/vpnc/auth-dialog/Makefile.am index 09211c8709..84bac97907 100644 --- a/vpn-daemons/vpnc/auth-dialog/Makefile.am +++ b/vpn-daemons/vpnc/auth-dialog/Makefile.am @@ -3,6 +3,7 @@ INCLUDES = -I${top_srcdir} -I${top_srcdir}/utils libexec_PROGRAMS = nm-vpnc-auth-dialog nm_vpnc_auth_dialog_CPPFLAGS = \ + $(NM_UTILS_CFLAGS) \ $(GTHREAD_CFLAGS) \ $(GTK_CFLAGS) \ $(LIBGNOMEUI_CFLAGS) \ diff --git a/vpn-daemons/vpnc/auth-dialog/main.c b/vpn-daemons/vpnc/auth-dialog/main.c index aa5a0425f1..cfbe622de1 100644 --- a/vpn-daemons/vpnc/auth-dialog/main.c +++ b/vpn-daemons/vpnc/auth-dialog/main.c @@ -29,10 +29,9 @@ #include #include +#include "../src/nm-vpnc-service.h" #include "gnome-two-password-dialog.h" -#define VPN_SERVICE "org.freedesktop.NetworkManager.vpnc" - static GSList * lookup_pass (const char *vpn_name, const char *vpn_service, gboolean *is_session) { @@ -222,12 +221,10 @@ get_passwords (const char *vpn_name, const char *vpn_service, gboolean retry) int main (int argc, char *argv[]) { - GSList *i; GSList *passwords; static gboolean retry = FALSE; static gchar *vpn_name = NULL; static gchar *vpn_service = NULL; - GError *error = NULL; GOptionContext *context; GnomeProgram *program; GOptionEntry entries[] = @@ -260,8 +257,8 @@ main (int argc, char *argv[]) goto out; } - if (strcmp (vpn_service, VPN_SERVICE) != 0) { - fprintf (stderr, "This dialog only works with the '%s' service\n", VPN_SERVICE); + if (strcmp (vpn_service, NM_DBUS_SERVICE_VPNC) != 0) { + fprintf (stderr, "This dialog only works with the '%s' service\n", NM_DBUS_SERVICE_VPNC); goto out; } @@ -270,11 +267,11 @@ main (int argc, char *argv[]) goto out; /* dump the passwords to stdout */ - for (i = passwords; i != NULL; i = g_slist_next (i)) { - char *password = (char *) i->data; - printf ("%s\n", password); - } + + printf ("%s\n%s\n", NM_VPNC_KEY_SECRET, (char *) passwords->data); + printf ("%s\n%s\n", NM_VPNC_KEY_XAUTH_PASSWORD, (char *) passwords->next->data); printf ("\n\n"); + /* for good measure, flush stdout since Kansas is going Bye-Bye */ fflush (stdout); diff --git a/vpn-daemons/vpnc/configure.in b/vpn-daemons/vpnc/configure.in index 014e0d558c..611f2c81c2 100644 --- a/vpn-daemons/vpnc/configure.in +++ b/vpn-daemons/vpnc/configure.in @@ -82,7 +82,7 @@ if test x"$with_gnome" != xno; then AC_SUBST(GNOMEKEYRING_LIBS) fi -PKG_CHECK_MODULES(NM_UTILS, NetworkManager >= 0.7.0 libnm-util) +PKG_CHECK_MODULES(NM_UTILS, NetworkManager >= 0.7.0 libnm-util libnm_glib) AC_SUBST(NM_UTILS_CFLAGS) AC_SUBST(NM_UTILS_LIBS) diff --git a/vpn-daemons/vpnc/properties/nm-vpnc.c b/vpn-daemons/vpnc/properties/nm-vpnc.c index f23dbbe432..6db029e597 100644 --- a/vpn-daemons/vpnc/properties/nm-vpnc.c +++ b/vpn-daemons/vpnc/properties/nm-vpnc.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /*************************************************************************** * CVSID: $Id$ * @@ -25,6 +26,7 @@ #include #endif +#include #include #include #include @@ -32,6 +34,7 @@ #define NM_VPN_API_SUBJECT_TO_CHANGE #include +#include "../src/nm-vpnc-service.h" #include "pcf-file.h" typedef struct _NetworkManagerVpnUIImpl NetworkManagerVpnUIImpl; @@ -97,47 +100,49 @@ impl_get_service_name (NetworkManagerVpnUI *self) return "org.freedesktop.NetworkManager.vpnc"; } -static GtkWidget * -impl_get_widget (NetworkManagerVpnUI *self, GSList *properties, GSList *routes, const char *connection_name) +static void +set_property (gpointer key, gpointer val, gpointer user_data) +{ + NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) user_data; + const char *name = (const char *) key; + GValue *value = (GValue *) val; + + if (!strcmp (name, NM_VPNC_KEY_GATEWAY)) { + gtk_entry_set_text (impl->w_gateway, g_value_get_string (value)); + } else if (!strcmp (name, NM_VPNC_KEY_ID)) { + gtk_entry_set_text (impl->w_group_name, g_value_get_string (value)); + } else if (!strcmp (name, NM_VPNC_KEY_XAUTH_USER)) { + gtk_entry_set_text (impl->w_username, g_value_get_string (value)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_alternate_username), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_username), TRUE); + } else if (!strcmp (name, NM_VPNC_KEY_DOMAIN)) { + gtk_entry_set_text (impl->w_domain, g_value_get_string (value)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_domain), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_domain), TRUE); + } else if (!strcmp (name, NM_VPNC_KEY_NAT_KEEPALIVE)) { + gtk_entry_set_text (impl->w_keepalive, g_value_get_string (value)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_keepalive), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (impl->w_keepalive), TRUE); + } else if (!strcmp (name, NM_VPNC_KEY_DISABLE_NAT)) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_disable_natt), g_value_get_boolean (value)); + } else if (!strcmp (name, NM_VPNC_KEY_SINGLE_DES)) { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_enable_singledes), g_value_get_boolean (value)); + } +} + +static GtkWidget * +impl_get_widget (NetworkManagerVpnUI *self, GHashTable *properties, GSList *routes, const char *connection_name) { - GSList *i; NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; + GSList *i; vpnc_clear_widget (impl); if (connection_name != NULL) gtk_entry_set_text (impl->w_connection_name, connection_name); - for (i = properties; i != NULL && g_slist_next (i) != NULL; i = g_slist_next (g_slist_next (i))) { - const char *key; - const char *value; - - key = i->data; - value = (g_slist_next (i))->data; - - if (strcmp (key, "IPSec gateway") == 0) { - gtk_entry_set_text (impl->w_gateway, value); - } else if (strcmp (key, "IPSec ID") == 0) { - gtk_entry_set_text (impl->w_group_name, value); - } else if (strcmp (key, "Xauth username") == 0) { - gtk_entry_set_text (impl->w_username, value); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_alternate_username), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_username), TRUE); - } else if (strcmp (key, "Domain") == 0) { - gtk_entry_set_text (impl->w_domain, value); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_domain), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_domain), TRUE); - } else if (strcmp (key, "NAT-Keepalive packet interval") == 0) { - gtk_entry_set_text (impl->w_keepalive, value); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_use_keepalive), TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (impl->w_keepalive), TRUE); - } else if (strcmp (key, "Disable NAT Traversal") == 0) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_disable_natt), TRUE); - } else if (strcmp (key, "Enable Single DES") == 0) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->w_enable_singledes), TRUE); - } - } - + if (properties) + g_hash_table_foreach (properties, set_property, self); if (routes != NULL) { GString *route_str; @@ -164,15 +169,36 @@ impl_get_widget (NetworkManagerVpnUI *self, GSList *properties, GSList *routes, return impl->widget; } -static GSList * -impl_get_properties (NetworkManagerVpnUI *self) +static GValue * +str_to_gvalue (const char *str) +{ + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, G_TYPE_STRING); + g_value_set_string (value, str); + + return value; +} + +static GValue * +bool_to_gvalue (gboolean b) +{ + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, G_TYPE_BOOLEAN); + g_value_set_boolean (value, b); + + return value; +} + +static gboolean +impl_get_properties (NetworkManagerVpnUI *self, GHashTable *properties) { - GSList *data; NetworkManagerVpnUIImpl *impl = (NetworkManagerVpnUIImpl *) self->data; - const char *connectionname; const char *gateway; const char *groupname; - const char *secret; gboolean use_alternate_username; const char *username; gboolean use_keepalive; @@ -182,7 +208,6 @@ impl_get_properties (NetworkManagerVpnUI *self) gboolean enable_singledes; const char *domain; - connectionname = gtk_entry_get_text (impl->w_connection_name); gateway = gtk_entry_get_text (impl->w_gateway); groupname = gtk_entry_get_text (impl->w_group_name); use_alternate_username = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_use_alternate_username)); @@ -194,33 +219,21 @@ impl_get_properties (NetworkManagerVpnUI *self) enable_singledes = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (impl->w_enable_singledes)); domain = gtk_entry_get_text (impl->w_domain); - data = NULL; - data = g_slist_append (data, g_strdup ("IPSec gateway")); - data = g_slist_append (data, g_strdup (gateway)); - data = g_slist_append (data, g_strdup ("IPSec ID")); - data = g_slist_append (data, g_strdup (groupname)); - if (use_alternate_username) { - data = g_slist_append (data, g_strdup ("Xauth username")); - data = g_slist_append (data, g_strdup (username)); - } - if (use_domain) { - data = g_slist_append (data, g_strdup ("Domain")); - data = g_slist_append (data, g_strdup (domain)); - } - if (use_keepalive) { - data = g_slist_append (data, g_strdup ("NAT-Keepalive packet interval")); - data = g_slist_append (data, g_strdup (keepalive)); - } - if (enable_singledes) { - data = g_slist_append (data, g_strdup ("Enable Single DES")); - data = g_slist_append (data, g_strdup ("")); - } - if (disable_natt) { - data = g_slist_append (data, g_strdup ("Disable NAT Traversal")); - data = g_slist_append (data, g_strdup ("")); - } + g_hash_table_insert (properties, NM_VPNC_KEY_GATEWAY, str_to_gvalue (gateway)); + g_hash_table_insert (properties, NM_VPNC_KEY_ID, str_to_gvalue (groupname)); - return data; + if (use_alternate_username) + g_hash_table_insert (properties, NM_VPNC_KEY_XAUTH_USER, str_to_gvalue (username)); + if (use_domain) + g_hash_table_insert (properties, NM_VPNC_KEY_DOMAIN, str_to_gvalue (domain)); + if (use_keepalive) + g_hash_table_insert (properties, NM_VPNC_KEY_NAT_KEEPALIVE, str_to_gvalue (keepalive)); + if (enable_singledes) + g_hash_table_insert (properties, NM_VPNC_KEY_SINGLE_DES, bool_to_gvalue (TRUE)); + if (disable_natt) + g_hash_table_insert (properties, NM_VPNC_KEY_DISABLE_NAT, bool_to_gvalue (TRUE)); + + return TRUE; } static GSList * @@ -702,10 +715,14 @@ impl_import_file (NetworkManagerVpnUI *self, const char *path) } static gboolean -export_to_file (NetworkManagerVpnUIImpl *impl, const char *path, - GSList *properties, GSList *routes, const char *connection_name) +export_to_file (NetworkManagerVpnUIImpl *impl, + const char *path, + GHashTable *properties, + GSList *routes, + const char *connection_name) { FILE *f; + GValue *val; GSList *i; const char *gateway = NULL; const char *keepalive = "0"; @@ -719,30 +736,33 @@ export_to_file (NetworkManagerVpnUIImpl *impl, const char *path, /*printf ("in export_to_file; path='%s'\n", path);*/ - for (i = properties; i != NULL && g_slist_next (i) != NULL; i = g_slist_next (g_slist_next (i))) { - const char *key; - const char *value; + val = (GValue *) g_hash_table_lookup (properties, NM_VPNC_KEY_GATEWAY); + if (val) + gateway = g_value_get_string (val); - key = i->data; - value = (g_slist_next (i))->data; + val = (GValue *) g_hash_table_lookup (properties, NM_VPNC_KEY_ID); + if (val) + groupname = g_value_get_string (val); - if (strcmp (key, "IPSec gateway") == 0) { - gateway = value; - } else if (strcmp (key, "IPSec ID") == 0) { - groupname = value; - } else if (strcmp (key, "Xauth username") == 0) { - username = value; - } else if (strcmp (key, "Domain") == 0) { - domain = value; - } else if (strcmp (key, "Disable NAT Traversal") == 0) { - enablenat = "0"; - } else if (strcmp (key, "Enable Single DES") == 0) { - singledes = "1"; - } else if (strcmp (key, "NAT-Keepalive packet interval") == 0) { - keepalive = value; - } - } + val = (GValue *) g_hash_table_lookup (properties, NM_VPNC_KEY_XAUTH_USER); + if (val) + username = g_value_get_string (val); + val = (GValue *) g_hash_table_lookup (properties, NM_VPNC_KEY_DOMAIN); + if (val) + domain = g_value_get_string (val); + + val = (GValue *) g_hash_table_lookup (properties, NM_VPNC_KEY_DISABLE_NAT); + if (val) + enablenat = g_value_get_boolean (val) ? "0" : "1"; + + val = (GValue *) g_hash_table_lookup (properties, NM_VPNC_KEY_SINGLE_DES); + if (val) + singledes = g_value_get_boolean (val) ? "1" : "0"; + + val = (GValue *) g_hash_table_lookup (properties, NM_VPNC_KEY_NAT_KEEPALIVE); + if (val) + keepalive = g_value_get_string (val); if (routes != NULL) { GString *str; @@ -828,7 +848,7 @@ out: static gboolean -impl_export (NetworkManagerVpnUI *self, GSList *properties, GSList *routes, const char *connection_name) +impl_export (NetworkManagerVpnUI *self, GHashTable *properties, GSList *routes, const char *connection_name) { char *suggested_name; char *path = NULL; diff --git a/vpn-daemons/vpnc/src/Makefile.am b/vpn-daemons/vpnc/src/Makefile.am index a62aa440bd..13aa2da079 100644 --- a/vpn-daemons/vpnc/src/Makefile.am +++ b/vpn-daemons/vpnc/src/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I${top_srcdir} -I${top_srcdir}/utils -I${top_srcdir}/vpn-daemons/vpnc +INCLUDES = -I${top_srcdir} AM_CPPFLAGS = \ $(DBUS_CFLAGS) \ @@ -20,15 +20,14 @@ bin_PROGRAMS = nm-vpnc-service nm-vpnc-service-vpnc-helper nm_vpnc_service_SOURCES = \ nm-vpnc-service.c \ - nm-vpnc-service.h \ - nm-utils.c \ - nm-utils.h + nm-vpnc-service.h nm_vpnc_service_LDADD = \ $(DBUS_LIBS) \ $(GTHREAD_LIBS) \ - $(NM_UTILS_LIBS) + $(NM_UTILS_LIBS) \ + -lnm_glib_vpn nm_vpnc_service_vpnc_helper_SOURCES = \ diff --git a/vpn-daemons/vpnc/src/nm-utils.c b/vpn-daemons/vpnc/src/nm-utils.c deleted file mode 100644 index fbcabe912d..0000000000 --- a/vpn-daemons/vpnc/src/nm-utils.c +++ /dev/null @@ -1,132 +0,0 @@ -/* NetworkManager -- Network link manager - * - * Ray Strode - * - * 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 -#include -#include - -#include -#include "nm-utils.h" - -gchar *nm_dbus_escape_object_path (const gchar *utf8_string) -{ - const gchar *p; - gchar *object_path; - GString *string; - - g_return_val_if_fail (utf8_string != NULL, NULL); - g_return_val_if_fail (g_utf8_validate (utf8_string, -1, NULL), NULL); - - string = g_string_sized_new ((strlen (utf8_string) + 1) * 6); - - for (p = utf8_string; *p != '\0'; p = g_utf8_next_char (p)) - { - gunichar character; - - character = g_utf8_get_char (p); - - if (((character >= ((gunichar) 'a')) && - (character <= ((gunichar) 'z'))) || - ((character >= ((gunichar) 'A')) && - (character <= ((gunichar) 'Z'))) || - ((character >= ((gunichar) '0')) && - (character <= ((gunichar) '9'))) || - (character == ((gunichar) '/'))) - { - g_string_append_c (string, (gchar) character); - continue; - } - - g_string_append_printf (string, "_%x_", character); - } - - object_path = string->str; - - g_string_free (string, FALSE); - - return object_path; -} - -gchar *nm_dbus_unescape_object_path (const gchar *object_path) -{ - const gchar *p; - gchar *utf8_string; - GString *string; - - g_return_val_if_fail (object_path != NULL, NULL); - - string = g_string_sized_new (strlen (object_path) + 1); - - for (p = object_path; *p != '\0'; p++) - { - const gchar *q; - gchar *hex_digits, *end, utf8_character[6] = { '\0' }; - gint utf8_character_size; - gunichar character; - gulong hex_value; - - if (*p != '_') - { - g_string_append_c (string, *p); - continue; - } - - q = strchr (p + 1, '_'); - - if ((q == NULL) || (q == p + 1)) - { - g_string_free (string, TRUE); - return NULL; - } - - hex_digits = g_strndup (p + 1, (q - 1) - p); - - hex_value = strtoul (hex_digits, &end, 16); - - character = (gunichar) hex_value; - - if (((hex_value == G_MAXLONG) && (errno == ERANGE)) || - (hex_value > G_MAXUINT32) || - (*end != '\0') || - (!g_unichar_validate (character))) - { - g_free (hex_digits); - g_string_free (string, TRUE); - return NULL; - } - - utf8_character_size = - g_unichar_to_utf8 (character, utf8_character); - - g_assert (utf8_character_size > 0); - - g_string_append_len (string, utf8_character, - utf8_character_size); - - p = q; - } - - utf8_string = string->str; - - g_string_free (string, FALSE); - - return utf8_string; -} diff --git a/vpn-daemons/vpnc/src/nm-utils.h b/vpn-daemons/vpnc/src/nm-utils.h deleted file mode 100644 index 276f4e2540..0000000000 --- a/vpn-daemons/vpnc/src/nm-utils.h +++ /dev/null @@ -1,131 +0,0 @@ -/* NetworkManager -- Network link manager - * - * Ray Strode - * - * 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_UTILS_H -#define NM_UTILS_H - -#include -#include - -#define nm_print_backtrace() \ -G_STMT_START \ -{ \ - void *_call_stack[512]; \ - int _call_stack_size; \ - char **_symbols; \ - _call_stack_size = backtrace (_call_stack, \ - G_N_ELEMENTS (_call_stack)); \ - _symbols = backtrace_symbols (_call_stack, _call_stack_size); \ - if (_symbols != NULL) \ - { \ - int _i; \ - _i = 0; \ - g_critical ("traceback:\n"); \ - while (_i < _call_stack_size) \ - { \ - g_critical ("\t%s\n", _symbols[_i]); \ - _i++; \ - } \ - free (_symbols); \ - } \ -} \ -G_STMT_END - -#define nm_get_timestamp(timestamp) \ -G_STMT_START \ -{ \ - GTimeVal _tv; \ - g_get_current_time (&_tv); \ - *timestamp = (_tv.tv_sec * (1.0 * G_USEC_PER_SEC) + \ - _tv.tv_usec) / G_USEC_PER_SEC; \ -} \ -G_STMT_END - -#define nm_info(fmt, args...) \ -G_STMT_START \ -{ \ - g_message ("\t" fmt "\n", ##args); \ -} G_STMT_END - -#define nm_info_str(fmt_str, args...) \ -G_STMT_START \ -{ \ - g_message ("\t%s\n", fmt_str, ##args); \ -} G_STMT_END - -#define nm_debug(fmt, args...) \ -G_STMT_START \ -{ \ - gdouble _timestamp; \ - nm_get_timestamp (&_timestamp); \ - g_debug ("\t[%f] %s (): " fmt "\n", _timestamp, \ - G_STRFUNC, ##args); \ -} G_STMT_END - -#define nm_debug_str(fmt_str, args...) \ -G_STMT_START \ -{ \ - gdouble _timestamp; \ - nm_get_timestamp (&_timestamp); \ - g_debug ("\t[%f] %s (): %s\n", _timestamp, \ - G_STRFUNC, fmt_str, ##args); \ -} G_STMT_END - -#define nm_warning(fmt, args...) \ -G_STMT_START \ -{ \ - g_warning ("\t %s (): " fmt "\n", \ - G_STRFUNC, ##args); \ -} G_STMT_END - -#define nm_warning_str(fmt_str, args...) \ -G_STMT_START \ -{ \ - g_warning ("\t %s (): %s\n", \ - G_STRFUNC, fmt_str, ##args); \ -} G_STMT_END - -#define nm_error(fmt, args...) \ -G_STMT_START \ -{ \ - gdouble _timestamp; \ - nm_get_timestamp (&_timestamp); \ - g_critical ("\t[%f] %s (): " fmt "\n", _timestamp, \ - G_STRFUNC, ##args); \ - nm_print_backtrace (); \ - G_BREAKPOINT (); \ -} G_STMT_END - -#define nm_error_str(fmt_str, args...) \ -G_STMT_START \ -{ \ - gdouble _timestamp; \ - nm_get_timestamp (&_timestamp); \ - g_critical ("\t[%f] %s (): %s\n", _timestamp, \ - G_STRFUNC, fmt_str, ##args); \ - nm_print_backtrace (); \ - G_BREAKPOINT (); \ -} G_STMT_END - -gchar *nm_dbus_escape_object_path (const gchar *utf8_string); -gchar *nm_dbus_unescape_object_path (const gchar *object_path); - -#endif /* NM_UTILS_H */ diff --git a/vpn-daemons/vpnc/src/nm-vpnc-service-vpnc-helper.c b/vpn-daemons/vpnc/src/nm-vpnc-service-vpnc-helper.c index 758d55c1e6..2551b7725a 100644 --- a/vpn-daemons/vpnc/src/nm-vpnc-service-vpnc-helper.c +++ b/vpn-daemons/vpnc/src/nm-vpnc-service-vpnc-helper.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ /* nm-vpnc-service - vpnc integration with NetworkManager * * Dan Williams @@ -34,170 +35,136 @@ #include "nm-vpnc-service.h" #include "nm-utils.h" - -/* - * send_config_error - * - * Notify nm-vpnc-service of a config error from 'vpnc'. - * - */ -static void send_config_error (DBusConnection *con, const char *item) +static void +helper_failed (DBusGConnection *connection, const char *reason) { - DBusMessage *message; + DBusGProxy *proxy; + GError *err = NULL; - g_return_if_fail (con != NULL); - g_return_if_fail (item != NULL); + nm_warning ("nm-nvpnc-service-vpnc-helper did not receive a valid %s from vpnc", reason); - if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE_VPNC, NM_DBUS_PATH_VPNC, NM_DBUS_INTERFACE_VPNC, "signalConfigError"))) - { - nm_warning ("send_config_error(): Couldn't allocate the dbus message"); - return; + proxy = dbus_g_proxy_new_for_name (connection, + NM_DBUS_SERVICE_VPNC, + NM_VPN_DBUS_PLUGIN_PATH, + NM_VPN_DBUS_PLUGIN_INTERFACE); + + dbus_g_proxy_call (proxy, "SetFailure", &err, + G_TYPE_STRING, reason, + G_TYPE_INVALID, + G_TYPE_INVALID); + + if (err) { + nm_warning ("Could not send failure information: %s", err->message); + g_error_free (err); } - dbus_message_append_args (message, DBUS_TYPE_STRING, &item, DBUS_TYPE_INVALID); - if (!dbus_connection_send (con, message, NULL)) - nm_warning ("send_config_error(): could not send dbus message"); + g_object_unref (proxy); - dbus_message_unref (message); + exit (1); } - -/* - * send_config_info - * - * Send IP config info to nm-vpnc-service - * - */ -static gboolean send_config_info (DBusConnection *con, const char *str_vpn_gateway, - const char *tundev, - const char *str_internal_ip4_address, - const char *str_internal_ip4_netmask, - const char *str_internal_ip4_dns, - const char *str_internal_ip4_nbns, - const char *cisco_def_domain, - const char *cisco_banner) +static void +send_ip4_config (DBusGConnection *connection, GHashTable *config) +{ + DBusGProxy *proxy; + GError *err = NULL; + + proxy = dbus_g_proxy_new_for_name (connection, + NM_DBUS_SERVICE_VPNC, + NM_VPN_DBUS_PLUGIN_PATH, + NM_VPN_DBUS_PLUGIN_INTERFACE); + + dbus_g_proxy_call (proxy, "SetIp4Config", &err, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + config, + G_TYPE_INVALID, + G_TYPE_INVALID); + + if (err) { + nm_warning ("Could not send failure information: %s", err->message); + g_error_free (err); + } + + g_object_unref (proxy); +} + +static GValue * +str_to_gvalue (const char *str, gboolean try_convert) +{ + GValue *val; + + /* Empty */ + if (!str || strlen (str) < 1) + return NULL; + + if (!g_utf8_validate (str, -1, NULL)) { + if (try_convert && !(str = g_convert (str, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL))) + str = g_convert (str, -1, "C", "UTF-8", NULL, NULL, NULL); + + if (!str) + /* Invalid */ + return NULL; + } + + val = g_new (GValue, 1); + g_value_init (val, G_TYPE_STRING); + g_value_set_string (val, str); + + return val; +} + +static GValue * +addr_to_gvalue (const char *str) { - DBusMessage * message; struct in_addr temp_addr; - guint32 uint_vpn_gateway = 0; - guint32 uint_internal_ip4_address = 0; - guint32 uint_internal_ip4_netmask = 0xFFFFFFFF; /* Default mask of 255.255.255.255 */ - guint32 * uint_internal_ip4_dns = NULL; - guint32 uint_internal_ip4_dns_len = 0; - guint32 * uint_internal_ip4_nbns = NULL; - guint32 uint_internal_ip4_nbns_len = 0; - char ** split; - char ** item; - guint32 num_valid = 0, i; - gboolean success = FALSE; + GValue *val; - g_return_val_if_fail (con != NULL, FALSE); + /* Empty */ + if (!str || strlen (str) < 1) + return NULL; - if (!(message = dbus_message_new_method_call (NM_DBUS_SERVICE_VPNC, NM_DBUS_PATH_VPNC, NM_DBUS_INTERFACE_VPNC, "signalIP4Config"))) - { - nm_warning ("send_config_error(): Couldn't allocate the dbus message"); - return FALSE; - } + if (!inet_aton (str, &temp_addr)) + return NULL; - /* Convert IPv4 address arguments from strings into numbers */ - if (!inet_aton (str_vpn_gateway, &temp_addr)) - { - nm_warning ("nm-vpnc-service-vpnc-helper didn't receive a valid VPN Gateway from vpnc."); - send_config_error (con, "VPN Gateway"); - goto out; - } - uint_vpn_gateway = temp_addr.s_addr; + val = g_new (GValue, 1); + g_value_init (val, G_TYPE_UINT); + g_value_set_uint (val, temp_addr.s_addr); - if (!inet_aton (str_internal_ip4_address, &temp_addr)) - { - nm_warning ("nm-vpnc-service-vpnc-helper didn't receive a valid Internal IP4 Address from vpnc."); - send_config_error (con, "IP4 Address"); - goto out; - } - uint_internal_ip4_address = temp_addr.s_addr; - - if (strlen (str_internal_ip4_netmask) && inet_aton (str_internal_ip4_netmask, &temp_addr)) - uint_internal_ip4_netmask = temp_addr.s_addr; - - if (strlen (str_internal_ip4_dns)) - { - if ((split = g_strsplit (str_internal_ip4_dns, " ", -1))) - { - /* Pass over the array first to determine how many valid entries there are */ - num_valid = 0; - for (item = split; *item; item++) - if (inet_aton (*item, &temp_addr)) - num_valid++; - - /* Do the actual string->int conversion and assign to the array. */ - if (num_valid > 0) - { - uint_internal_ip4_dns = g_new0 (guint32, num_valid); - for (item = split, i = 0; *item; item++, i++) - if (inet_aton (*item, &temp_addr)) - uint_internal_ip4_dns[i] = temp_addr.s_addr; - } - - g_strfreev (split); - uint_internal_ip4_dns_len = num_valid; - } - } - if (!uint_internal_ip4_dns) - { - uint_internal_ip4_dns = g_malloc0 (sizeof (guint32)); - uint_internal_ip4_dns[0] = 0; - uint_internal_ip4_dns_len = 1; - } - - if (strlen (str_internal_ip4_nbns)) - { - if ((split = g_strsplit (str_internal_ip4_nbns, " ", -1))) - { - /* Pass over the array first to determine how many valid entries there are */ - num_valid = 0; - for (item = split; *item; item++) - if (inet_aton (*item, &temp_addr)) - num_valid++; - - /* Do the actual string->int conversion and assign to the array. */ - if (num_valid > 0) - { - uint_internal_ip4_nbns = g_new0 (guint32, num_valid); - for (item = split, i = 0; *item; item++, i++) - if (inet_aton (*item, &temp_addr)) - uint_internal_ip4_nbns[i] = temp_addr.s_addr; - } - - g_strfreev (split); - uint_internal_ip4_nbns_len = num_valid; - } - } - if (!uint_internal_ip4_nbns) - { - uint_internal_ip4_nbns = g_malloc0 (sizeof (guint32)); - uint_internal_ip4_nbns[0] = 0; - uint_internal_ip4_nbns_len = 1; - } - - dbus_message_append_args (message, DBUS_TYPE_UINT32, &uint_vpn_gateway, - DBUS_TYPE_STRING, &tundev, - DBUS_TYPE_UINT32, &uint_internal_ip4_address, - DBUS_TYPE_UINT32, &uint_internal_ip4_netmask, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &uint_internal_ip4_dns, uint_internal_ip4_dns_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &uint_internal_ip4_nbns, uint_internal_ip4_nbns_len, - DBUS_TYPE_STRING, &cisco_def_domain, - DBUS_TYPE_STRING, &cisco_banner, DBUS_TYPE_INVALID); - if (dbus_connection_send (con, message, NULL)) - success = TRUE; - else - nm_warning ("send_config_error(): could not send dbus message"); - - dbus_message_unref (message); - -out: - return success; + return val; } +static GValue * +addr_list_to_gvalue (const char *str) +{ + GValue *val; + char **split; + int i; + struct in_addr temp_addr; + GSList *list = NULL; + + /* Empty */ + if (!str || strlen (str) < 1) + return NULL; + + split = g_strsplit (str, " ", -1); + for (i = 0; split[i]; i++) { + if (inet_aton (split[i], &temp_addr)) + list = g_slist_append (list, GUINT_TO_POINTER (temp_addr.s_addr)); + else { + g_strfreev (split); + g_slist_free (list); + return NULL; + } + } + + g_strfreev (split); + + val = g_new0 (GValue, 1); + g_value_init (val, dbus_g_type_get_collection ("GSList", G_TYPE_UINT)); + g_value_set_boxed (val, list); + + return val; +} /* * Environment variables passed back from 'vpnc': @@ -212,119 +179,80 @@ out: * CISCO_BANNER -- banner from server * */ - -/* - * main - * - */ -int main( int argc, char *argv[] ) +int +main (int argc, char *argv[]) { - DBusConnection * con; - DBusError error; - char * reason = NULL; - char * vpn_gateway = NULL; - char * tundev = NULL; - char * internal_ip4_address = NULL; - char * internal_ip4_netmask = NULL; - char * internal_ip4_dns = NULL; - char * internal_ip4_nbns = NULL; - char * cisco_def_domain = NULL; - char * cisco_banner = NULL; + DBusGConnection *connection; + char *tmp; + GHashTable *config; + GValue *val; + GError *err = NULL; g_type_init (); - if (!g_thread_supported ()) - g_thread_init (NULL); - - dbus_error_init (&error); - con = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if ((con == NULL) || dbus_error_is_set (&error)) - { - nm_warning ("Could not get the system bus. Make sure the message bus daemon is running?"); - exit (1); - } - dbus_connection_set_exit_on_disconnect (con, FALSE); /* vpnc 0.3.3 gives us a "reason" code. If we are given one, * don't proceed unless its "connect". */ - reason = getenv ("reason"); - if (reason && strcmp (reason, "connect") != 0) + tmp = getenv ("reason"); + if (tmp && strcmp (tmp, "connect") != 0) exit (0); - vpn_gateway = getenv ("VPNGATEWAY"); - tundev = getenv ("TUNDEV"); - internal_ip4_address = getenv ("INTERNAL_IP4_ADDRESS"); - internal_ip4_netmask = getenv ("INTERNAL_IP4_NETMASK"); - internal_ip4_dns = getenv ("INTERNAL_IP4_DNS"); - internal_ip4_nbns = getenv ("INTERNAL_IP4_NBNS"); - cisco_def_domain = getenv ("CISCO_DEF_DOMAIN"); - cisco_banner = getenv ("CISCO_BANNER"); - -#if 0 - { - FILE *file = fopen ("/tmp/vpnstuff", "w"); - fprintf (file, "VPNGATEWAY: '%s'\n", vpn_gateway); - fprintf (file, "TUNDEF: '%s'\n", tundev); - fprintf (file, "INTERNAL_IP4_ADDRESS: '%s'\n", internal_ip4_address); - fprintf (file, "INTERNAL_IP4_NETMASK: '%s'\n", internal_ip4_netmask); - fprintf (file, "INTERNAL_IP4_DNS: '%s'\n", internal_ip4_dns); - fprintf (file, "INTERNAL_IP4_NBNS: '%s'\n", internal_ip4_nbns); - fprintf (file, "CISCO_DEF_DOMAIN: '%s'\n", cisco_def_domain); - fprintf (file, "CISCO_BANNER: '%s'\n", cisco_banner); - fclose (file); - } -#endif - - if (!vpn_gateway) - { - nm_warning ("nm-vpnc-service-vpnc-helper didn't receive a VPN Gateway from vpnc."); - send_config_error (con, "VPN Gateway"); - exit (1); - } - if (!tundev || !g_utf8_validate (tundev, -1, NULL)) - { - nm_warning ("nm-vpnc-service-vpnc-helper didn't receive a Tunnel Device from vpnc, or the tunnel device was not valid UTF-8."); - send_config_error (con, "Tunnel Device"); - exit (1); - } - if (!internal_ip4_address) - { - nm_warning ("nm-vpnc-service-vpnc-helper didn't receive an Internal IP4 Address from vpnc."); - send_config_error (con, "IP4 Address"); + connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); + if (!connection) { + nm_warning ("Could not get the system bus: %s", err->message); exit (1); } - if (!internal_ip4_netmask) - internal_ip4_netmask = g_strdup (""); - if (!internal_ip4_dns) - internal_ip4_dns = g_strdup (""); - if (!internal_ip4_nbns) - internal_ip4_nbns = g_strdup (""); + config = g_hash_table_new (g_str_hash, g_str_equal); - /* Ensure strings from network are UTF-8 */ - if (cisco_def_domain && !g_utf8_validate (cisco_def_domain, -1, NULL)) - { - if (!(cisco_def_domain = g_convert (cisco_def_domain, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL))) - cisco_def_domain = g_convert (cisco_def_domain, -1, "C", "UTF-8", NULL, NULL, NULL); - } - if (!cisco_def_domain) - cisco_def_domain = g_strdup (""); + /* Gateway */ + val = addr_to_gvalue (getenv ("VPNGATEWAY")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY, val); + else + helper_failed (connection, "VPN Gateway"); - if (cisco_banner && !g_utf8_validate (cisco_banner, -1, NULL)) - { - if (!(cisco_banner = g_convert (cisco_banner, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL))) - cisco_banner = g_convert (cisco_banner, -1, "C", "UTF-8", NULL, NULL, NULL); - } - if (!cisco_banner) - cisco_banner = g_strdup (""); + /* Tunnel device */ + val = str_to_gvalue (getenv ("TUNDEV"), FALSE); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, val); + else + helper_failed (connection, "Tunnel Device"); + + /* IP address */ + val = addr_to_gvalue (getenv ("INTERNAL_IP4_ADDRESS")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS, val); + else + helper_failed (connection, "IP4 Address"); + + /* Netmask */ + val = addr_to_gvalue (getenv ("INTERNAL_IP4_NETMASK")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_NETMASK, val); + + /* DNS */ + val = addr_list_to_gvalue (getenv ("INTERNAL_IP4_DNS")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_DNS, val); + + /* WINS servers */ + val = addr_list_to_gvalue (getenv ("INTERNAL_IP4_NBNS")); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, val); + + /* Default domain */ + val = str_to_gvalue (getenv ("CISCO_DEF_DOMAIN"), TRUE); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN, val); + + /* Banner */ + val = str_to_gvalue (getenv ("CISCO_BANNER"), TRUE); + if (val) + g_hash_table_insert (config, NM_VPN_PLUGIN_IP4_CONFIG_BANNER, val); /* Send the config info to nm-vpnc-service */ - if (!send_config_info (con, vpn_gateway, tundev, internal_ip4_address, internal_ip4_netmask, - internal_ip4_dns, internal_ip4_nbns, cisco_def_domain, cisco_banner)) - { - exit (1); - } + send_ip4_config (connection, config); exit (0); } - diff --git a/vpn-daemons/vpnc/src/nm-vpnc-service.c b/vpn-daemons/vpnc/src/nm-vpnc-service.c index 1ec1f7c7a5..8e9c01f434 100644 --- a/vpn-daemons/vpnc/src/nm-vpnc-service.c +++ b/vpn-daemons/vpnc/src/nm-vpnc-service.c @@ -1,33 +1,5 @@ -/* nm-vpnc-service - vpnc integration with NetworkManager - * - * Dan Williams - * - * 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. - */ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include #include #include #include @@ -36,18 +8,17 @@ #include #include #include -#include -#include -#include -#include - -#include -#include #include "nm-vpnc-service.h" #include "nm-utils.h" -#include "dbus-dict-helpers.h" +G_DEFINE_TYPE (NMVPNCPlugin, nm_vpnc_plugin, NM_TYPE_VPN_PLUGIN) + +typedef struct { + GPid pid; +} NMVPNCPluginPrivate; + +#define NM_VPNC_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPNC_PLUGIN, NMVPNCPluginPrivate)) static const char *vpnc_binary_paths[] = { @@ -61,252 +32,72 @@ static const char *vpnc_binary_paths[] = #define NM_VPNC_UDP_ENCAPSULATION_PORT 0 /* random port */ #define NM_VPNC_REKEYING_INTERVAL 7200 /* default interval of 2 hours */ -typedef struct NmVpncData +typedef struct { + const char *name; + GType type; +} ValidProperty; + +static ValidProperty valid_properties[] = { + { NM_VPNC_KEY_GATEWAY, G_TYPE_STRING }, + { NM_VPNC_KEY_ID, G_TYPE_STRING }, + { NM_VPNC_KEY_SECRET, G_TYPE_STRING }, + { NM_VPNC_KEY_XAUTH_USER, G_TYPE_STRING }, + { NM_VPNC_KEY_XAUTH_PASSWORD, G_TYPE_STRING }, + { NM_VPNC_KEY_UDP_ENCAPS, G_TYPE_BOOLEAN }, + { NM_VPNC_KEY_UDP_ENCAPS_PORT, G_TYPE_INT }, + { NM_VPNC_KEY_DOMAIN, G_TYPE_STRING }, + { NM_VPNC_KEY_DHGROUP, G_TYPE_STRING }, + { NM_VPNC_KEY_PERFECT_FORWARD, G_TYPE_STRING }, + { NM_VPNC_KEY_APP_VERSION, G_TYPE_STRING }, + { NM_VPNC_KEY_REKEYING, G_TYPE_INT }, + { NM_VPNC_KEY_NAT_KEEPALIVE, G_TYPE_STRING }, + { NM_VPNC_KEY_DISABLE_NAT, G_TYPE_BOOLEAN }, + { NM_VPNC_KEY_SINGLE_DES, G_TYPE_BOOLEAN }, + { NULL, G_TYPE_NONE } +}; + +static void +validate_one_property (gpointer key, gpointer val, gpointer user_data) { - GMainLoop * loop; - DBusConnection * con; - NMVPNServiceState state; - GPid pid; - guint quit_timer; - guint helper_timer; -} NmVpncData; + gboolean *failed = (gboolean *) user_data; + int i; - -static gboolean nm_vpnc_dbus_handle_stop_vpn (NmVpncData *data); - - -/* - * nm_dbus_create_error_message - * - * Make a DBus error message - * - */ -static DBusMessage *nm_dbus_create_error_message (DBusMessage *message, const char *exception_namespace, - const char *exception, const char *format, ...) -{ - char *exception_text; - DBusMessage *reply; - va_list args; - char error_text[512]; - - va_start (args, format); - vsnprintf (error_text, 512, format, args); - va_end (args); - - exception_text = g_strdup_printf ("%s.%s", exception_namespace, exception); - reply = dbus_message_new_error (message, exception_text, error_text); - g_free (exception_text); - - return (reply); -} - - -/* - * nm_vpnc_dbus_signal_failure - * - * Signal the bus that some VPN operation failed. - * - */ -static void nm_vpnc_dbus_signal_failure (NmVpncData *data, const char *signal) -{ - DBusMessage *message; - const char *error_msg = NULL; - - g_return_if_fail (data != NULL); - g_return_if_fail (signal != NULL); - - if (!strcmp (signal, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED)) - error_msg = _("The VPN login failed because the user name and password were not accepted."); - else if (!strcmp (signal, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED)) - error_msg = _("The VPN login failed because the VPN program could not be started."); - else if (!strcmp (signal, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED)) - error_msg = _("The VPN login failed because the VPN program could not connect to the VPN server."); - else if (!strcmp (signal, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD)) - error_msg = _("The VPN login failed because the VPN configuration options were invalid."); - else if (!strcmp (signal, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD)) - error_msg = _("The VPN login failed because the VPN program received an invalid configuration from the VPN server."); - - if (!error_msg) + if (*failed) return; - if (!(message = dbus_message_new_signal (NM_DBUS_PATH_VPNC, NM_DBUS_INTERFACE_VPNC, signal))) - { - nm_warning ("Not enough memory for new dbus message!"); - return; + for (i = 0; valid_properties[i].name; i++) { + ValidProperty prop = valid_properties[i]; + + if (!strcmp (prop.name, (char *) key) && prop.type == G_VALUE_TYPE ((GValue *) val)) + /* Property is ok */ + return; } - dbus_message_append_args (message, DBUS_TYPE_STRING, &error_msg, DBUS_TYPE_INVALID); - if (!dbus_connection_send (data->con, message, NULL)) - nm_warning ("Could not raise the signal!"); - - dbus_message_unref (message); + /* Did not find the property from valid_properties or the type did not match */ + *failed = TRUE; } - -/* - * nm_vpnc_dbus_signal_state_change - * - * Signal the bus that our state changed. - * - */ -static void nm_vpnc_dbus_signal_state_change (NmVpncData *data, NMVPNServiceState old_state) +static gboolean +nm_vpnc_properties_validate (GHashTable *properties) { - DBusMessage *message; + gboolean failed = FALSE; - g_return_if_fail (data != NULL); + if (g_hash_table_size (properties) < 1) + return failed; - if (!(message = dbus_message_new_signal (NM_DBUS_PATH_VPNC, NM_DBUS_INTERFACE_VPNC, NM_DBUS_VPN_SIGNAL_STATE_CHANGE))) - { - nm_warning ("nm_vpnc_dbus_signal_state_change(): Not enough memory for new dbus message!"); - return; - } + g_hash_table_foreach (properties, validate_one_property, &failed); - dbus_message_append_args (message, DBUS_TYPE_UINT32, &old_state, DBUS_TYPE_UINT32, &(data->state), DBUS_TYPE_INVALID); - - if (!dbus_connection_send (data->con, message, NULL)) - nm_warning ("nm_vpnc_dbus_signal_state_change(): Could not raise the signal!"); - - dbus_message_unref (message); + return !failed; } - -/* - * nm_vpnc_set_state - * - * Set our state and make sure to signal the bus. - * - */ -static void nm_vpnc_set_state (NmVpncData *data, NMVPNServiceState new_state) +static void +vpnc_watch_cb (GPid pid, gint status, gpointer user_data) { - NMVPNServiceState old_state; + NMVPNCPlugin *plugin = NM_VPNC_PLUGIN (user_data); + NMVPNCPluginPrivate *priv = NM_VPNC_PLUGIN_GET_PRIVATE (plugin); + guint error; - g_return_if_fail (data != NULL); - - old_state = data->state; - - if (old_state != new_state) - { - data->state = new_state; - nm_vpnc_dbus_signal_state_change (data, old_state); - } -} - - -/* - * nm_vpnc_quit_timer_cb - * - * Callback to quit nm-vpnc-service after a certain period of time. - * - */ -static gboolean nm_vpnc_quit_timer_cb (NmVpncData *data) -{ - data->quit_timer = 0; - - g_return_val_if_fail (data != NULL, FALSE); - - g_main_loop_quit (data->loop); - - return FALSE; -} - - -/* - * nm_vpnc_schedule_quit_timer - * - * If vpnc isn't running, and we haven't been asked to do anything in a while, - * then we just exit since NetworkManager will re-launch us later. - * - */ -static void nm_vpnc_schedule_quit_timer (NmVpncData *data, guint interval) -{ - g_return_if_fail (data != NULL); - - if (data->quit_timer == 0) - data->quit_timer = g_timeout_add (interval, (GSourceFunc) nm_vpnc_quit_timer_cb, data); -} - - -/* - * nm_vpnc_cancel_quit_timer - * - * Cancel a quit timer that we've scheduled before. - * - */ -static void nm_vpnc_cancel_quit_timer (NmVpncData *data) -{ - g_return_if_fail (data != NULL); - - if (data->quit_timer > 0) - g_source_remove (data->quit_timer); -} - - -/* - * nm_vpnc_helper_timer_cb - * - * If we haven't received the IP4 config info from the helper before the timeout - * occurs, we kill vpnc. - * - */ -static gboolean nm_vpnc_helper_timer_cb (NmVpncData *data) -{ - data->helper_timer = 0; - - g_return_val_if_fail (data != NULL, FALSE); - - nm_vpnc_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED); - nm_vpnc_dbus_handle_stop_vpn (data); - - return FALSE; -} - - -/* - * nm_vpnc_schedule_helper_timer - * - * Once vpnc is running, we wait for the helper to return the IP4 configuration - * information to us. If we don't receive that information within 7 seconds, - * we kill vpnc. - * - */ -static void nm_vpnc_schedule_helper_timer (NmVpncData *data) -{ - g_return_if_fail (data != NULL); - - if (data->helper_timer == 0) - data->helper_timer = g_timeout_add (10000, (GSourceFunc) nm_vpnc_helper_timer_cb, data); -} - - -/* - * nm_vpnc_cancel_helper_timer - * - * Cancel a helper timer that we've scheduled before. - * - */ -static void nm_vpnc_cancel_helper_timer (NmVpncData *data) -{ - g_return_if_fail (data != NULL); - - if (data->helper_timer > 0) - g_source_remove (data->helper_timer); -} - - -/* - * vpnc_watch_cb - * - * Watch our child vpnc process and get notified of events from it. - * - */ -static void vpnc_watch_cb (GPid pid, gint status, gpointer user_data) -{ - guint error = -1; - - NmVpncData *data = (NmVpncData *)user_data; - - if (WIFEXITED (status)) - { + if (WIFEXITED (status)) { error = WEXITSTATUS (status); if (error != 0) nm_warning ("vpnc exited with error code %d", error); @@ -319,59 +110,45 @@ static void vpnc_watch_cb (GPid pid, gint status, gpointer user_data) nm_warning ("vpnc died from an unknown cause"); /* Reap child if needed. */ - waitpid (data->pid, NULL, WNOHANG); - data->pid = 0; + waitpid (priv->pid, NULL, WNOHANG); + priv->pid = 0; /* Must be after data->state is set since signals use data->state */ - switch (error) - { - case 2: /* Couldn't log in due to bad user/pass */ - nm_vpnc_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED); - break; - - case 1: /* Other error (couldn't bind to address, etc) */ - nm_vpnc_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED); - break; - - default: - break; + switch (error) { + case 2: + /* Couldn't log in due to bad user/pass */ + nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED); + break; + case 1: + /* Other error (couldn't bind to address, etc) */ + nm_vpn_plugin_failure (NM_VPN_PLUGIN (plugin), NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED); + break; + default: + break; } - nm_vpnc_set_state (data, NM_VPN_SERVICE_STATE_STOPPED); - nm_vpnc_schedule_quit_timer (data, 10000); + nm_vpn_plugin_set_state (NM_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_STOPPED); } - -/* - * nm_vpnc_start_vpn_binary - * - * Start the vpnc binary with a set of arguments and a config file. - * - */ -static gint nm_vpnc_start_vpnc_binary (NmVpncData *data) +static gint +nm_vpnc_start_vpnc_binary (NMVPNCPlugin *plugin) { - GPid pid; - const char ** vpnc_binary = NULL; - GPtrArray * vpnc_argv; - GError * error = NULL; - GSource * vpnc_watch; - gint stdin_fd = -1; - - g_return_val_if_fail (data != NULL, -1); - - data->pid = 0; + GPid pid; + const char **vpnc_binary = NULL; + GPtrArray *vpnc_argv; + GError *err = NULL; + GSource *vpnc_watch; + gint stdin_fd; /* Find vpnc */ vpnc_binary = vpnc_binary_paths; - while (*vpnc_binary != NULL) - { + while (*vpnc_binary != NULL) { if (g_file_test (*vpnc_binary, G_FILE_TEST_EXISTS)) break; vpnc_binary++; } - if (!*vpnc_binary) - { + if (!*vpnc_binary) { nm_info ("Could not find vpnc binary."); return -1; } @@ -384,37 +161,28 @@ static gint nm_vpnc_start_vpnc_binary (NmVpncData *data) g_ptr_array_add (vpnc_argv, NULL); if (!g_spawn_async_with_pipes (NULL, (char **) vpnc_argv->pdata, NULL, - G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &stdin_fd, - NULL, NULL, &error)) - { + G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &stdin_fd, + NULL, NULL, &err)) { g_ptr_array_free (vpnc_argv, TRUE); - nm_warning ("vpnc failed to start. error: '%s'", error->message); - g_error_free(error); + nm_warning ("vpnc failed to start. error: '%s'", err->message); + g_error_free (err); return -1; } g_ptr_array_free (vpnc_argv, TRUE); nm_info ("vpnc started with pid %d", pid); - data->pid = pid; + NM_VPNC_PLUGIN_GET_PRIVATE (plugin)->pid = pid; vpnc_watch = g_child_watch_source_new (pid); - g_source_set_callback (vpnc_watch, (GSourceFunc) vpnc_watch_cb, data, NULL); + g_source_set_callback (vpnc_watch, (GSourceFunc) vpnc_watch_cb, plugin, NULL); g_source_attach (vpnc_watch, NULL); g_source_unref (vpnc_watch); - nm_vpnc_schedule_helper_timer (data); - return stdin_fd; } - -/* - * write_config_option - * - * Helper that writes a formatted string to an fd - * - */ -static inline void write_config_option (int fd, const char *format, ...) +static inline void +write_config_option (int fd, const char *format, ...) { char * string; va_list args; @@ -422,830 +190,158 @@ static inline void write_config_option (int fd, const char *format, ...) va_start (args, format); string = g_strdup_vprintf (format, args); + g_print ("|%s|\n", string); x = write (fd, string, strlen (string)); g_free (string); va_end (args); } -/* - * nm_vpnc_config_write - * - * Write the vpnc config to the vpnc process' stdin pipe - * - */ -static gboolean nm_vpnc_config_write (guint vpnc_fd, const char *user_name, char **password_items, - const int num_passwords, char **data_items, const int num_items) +static void +write_one_property (gpointer key, gpointer val, gpointer user_data) { - int i; - gboolean has_user_name = FALSE; - gboolean has_rekey_interval = FALSE; + gint vpnc_fd = GPOINTER_TO_INT (user_data); + GValue *value = (GValue *) val; + GType type; - g_return_val_if_fail (user_name != NULL, FALSE); - g_return_val_if_fail (password_items != NULL, FALSE); - g_return_val_if_fail (data_items != NULL, FALSE); - g_return_val_if_fail (num_passwords == 2, FALSE); + type = G_VALUE_TYPE (value); + if (type == G_TYPE_STRING) + write_config_option (vpnc_fd, "%s %s\n", (char *) key, g_value_get_string (value)); + else if (type == G_TYPE_BOOLEAN) + write_config_option (vpnc_fd, "%s\n", (char *) key); + else if (type == G_TYPE_INT) + write_config_option (vpnc_fd, "%s %d\n", (char *) key, g_value_get_int (value)); + else if (type == DBUS_TYPE_G_UCHAR_ARRAY) { + char *tmp; + tmp = nm_utils_garray_to_string ((GArray *) g_value_get_boxed (value)); + write_config_option (vpnc_fd, "%s %s\n", tmp); + g_free (tmp); + } + + else + nm_warning ("Don't know how to write property '%s' with type %s", + (char *) key, g_type_name (type)); +} + +static void +nm_vpnc_config_write (gint vpnc_fd, GHashTable *properties) +{ write_config_option (vpnc_fd, "Script " NM_VPNC_HELPER_PATH "\n"); write_config_option (vpnc_fd, "UDP Encapsulate\n"); write_config_option (vpnc_fd, "UDP Encapsulation Port %d\n", NM_VPNC_UDP_ENCAPSULATION_PORT); - write_config_option (vpnc_fd, "IPSec secret %s\n", password_items[0]); - write_config_option (vpnc_fd, "Xauth password %s\n", password_items[1]); - for (i = 0; i < num_items; i += 2) - { - write_config_option (vpnc_fd, "%s %s\n", data_items[i], data_items[i+1]); - if (strcmp (data_items[i], "Xauth username") == 0) - has_user_name = TRUE; - else if (strcmp (data_items[i], "Rekeying interval") == 0) - has_rekey_interval = TRUE; - } + g_hash_table_foreach (properties, write_one_property, GINT_TO_POINTER (vpnc_fd)); - /* if user name isn't specified, use the name of the logged in user */ - if (!has_user_name) - write_config_option (vpnc_fd, "Xauth username %s\n", user_name); - - if (!has_rekey_interval) +#if 0 + if (!g_hash_table_lookup (properties, "Rekeying interval")) write_config_option (vpnc_fd, "Rekeying interval %d\n", NM_VPNC_REKEYING_INTERVAL); - - return TRUE; +#endif } - -typedef enum OptType +static gboolean +real_connect (NMVPNPlugin *plugin, + GHashTable *properties, + char **routes, + GError **err) { - OPT_TYPE_UNKNOWN = 0, - OPT_TYPE_ADDRESS, - OPT_TYPE_ASCII, - OPT_TYPE_NONE -} OptType; + gint vpnc_fd; -typedef struct Option -{ - const char *name; - OptType type; -} Option; - -/* - * nm_vpnc_config_options_validate - * - * Make sure the config options are sane - * - */ -static gboolean nm_vpnc_config_options_validate (char **data_items, int num_items) -{ - Option allowed_opts[] = { - { "IPSec gateway", OPT_TYPE_ADDRESS }, - { "IPSec ID", OPT_TYPE_ASCII }, - { "IPSec secret", OPT_TYPE_ASCII }, - { "Xauth username", OPT_TYPE_ASCII }, - { "UDP Encapsulate", OPT_TYPE_NONE }, - { "UDP Encapsulation Port", OPT_TYPE_ASCII }, - { "Domain", OPT_TYPE_ASCII }, - { "IKE DH Group", OPT_TYPE_ASCII }, - { "Perfect Forward Secrecy", OPT_TYPE_ASCII }, - { "Application Version", OPT_TYPE_ASCII }, - { "Rekeying interval", OPT_TYPE_ASCII }, - { "NAT-Keepalive packet interval", OPT_TYPE_ASCII }, - { "Disable NAT Traversal", OPT_TYPE_NONE }, - { "Enable Single DES", OPT_TYPE_NONE }, - { NULL, OPT_TYPE_UNKNOWN } - }; - - unsigned int i; - - g_return_val_if_fail (data_items != NULL, FALSE); - g_return_val_if_fail (num_items >= 2, FALSE); - - /* Must be an even numbers of config options */ - if ((num_items % 2) != 0) - { - nm_warning ("The number of VPN config options was not even."); + if (!nm_vpnc_properties_validate (properties)) { + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "%s", + "Invalid arguments."); return FALSE; } - for (i = 0; i < num_items; i += 2) - { - Option *opt = NULL; - unsigned int t, len; - char *opt_value; - - if (!data_items[i] || !data_items[i+1]) - return FALSE; - opt_value = data_items[i+1]; - - /* Find the option in the allowed list */ - for (t = 0; t < sizeof (allowed_opts) / sizeof (Option); t++) - { - opt = &allowed_opts[t]; - if (opt->name && !strcmp (opt->name, data_items[i])) - break; - } - if (!opt->name) /* not found */ - { - nm_warning ("VPN option '%s' is not allowed.", data_items[i]); - return FALSE; - } - - /* Don't allow control characters at all */ - len = strlen (opt_value); - for (t = 0; t < len; t++) - { - if (iscntrl (opt_value[t])) - { - nm_warning ("There were invalid characters in the VPN option '%s' - '%s'.", data_items[i], opt_value); - return FALSE; - } - } - - /* Validate the option's data */ - switch (opt->type) - { - case OPT_TYPE_ASCII: - /* What other characters should we reject?? */ - break; - - case OPT_TYPE_NONE: - /* These have blank data */ - break; - - case OPT_TYPE_ADDRESS: - /* Can be any legal hostname or IP address */ - break; - - default: - return FALSE; - break; - } - } - - return TRUE; -} - -/* - * nm_vpnc_dbus_handle_start_vpn - * - * Parse message arguments and start the VPN connection. - * - */ -static gboolean nm_vpnc_dbus_handle_start_vpn (DBusMessage *message, NmVpncData *data) -{ - char ** data_items = NULL; - int num_items = -1; - char ** password_items = NULL; - int num_passwords = -1; - char ** user_routes = NULL; - int user_routes_count = -1; - const char * name = NULL; - const char * user_name = NULL; - DBusError error; - gboolean success = FALSE; - gint vpnc_fd = -1; - - g_return_val_if_fail (message != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - nm_vpnc_set_state (data, NM_VPN_SERVICE_STATE_STARTING); - - dbus_error_init (&error); - if (!dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &user_name, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &password_items, &num_passwords, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &data_items, &num_items, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &user_routes, &user_routes_count, - DBUS_TYPE_INVALID)) - { - nm_warning ("Could not process the request because its arguments were invalid. dbus said: '%s'", error.message); - nm_vpnc_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD); - dbus_error_free (&error); - goto out; - } - - if (!nm_vpnc_config_options_validate (data_items, num_items)) - { - nm_vpnc_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD); - goto out; - } - - /* Now we can finally try to activate the VPN */ - if ((vpnc_fd = nm_vpnc_start_vpnc_binary (data)) >= 0) - { - if (nm_vpnc_config_write (vpnc_fd, user_name, password_items, num_passwords, data_items, num_items)) - success = TRUE; - else - nm_vpnc_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED); + if ((vpnc_fd = nm_vpnc_start_vpnc_binary (NM_VPNC_PLUGIN (plugin))) >= 0) + nm_vpnc_config_write (vpnc_fd, properties); + else { + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, + "%s", + "Could not start vpnc binary."); close (vpnc_fd); - } - -out: - dbus_free_string_array (data_items); - dbus_free_string_array (password_items); - dbus_free_string_array (user_routes); - if (!success) - nm_vpnc_set_state (data, NM_VPN_SERVICE_STATE_STOPPED); - return success; -} - - -/* - * nm_vpnc_dbus_handle_stop_vpn - * - * Stop the running vpnc dameon. - * - */ -static gboolean nm_vpnc_dbus_handle_stop_vpn (NmVpncData *data) -{ - g_return_val_if_fail (data != NULL, FALSE); - - if (data->pid > 0) - { - nm_vpnc_set_state (data, NM_VPN_SERVICE_STATE_STOPPING); - - kill (data->pid, SIGTERM); - nm_info ("Terminated vpnc daemon with PID %d.", data->pid); - data->pid = 0; - - nm_vpnc_set_state (data, NM_VPN_SERVICE_STATE_STOPPED); - nm_vpnc_schedule_quit_timer (data, 10000); + return FALSE; } return TRUE; } - -/* - * nm_vpnc_dbus_start_vpn - * - * Begin a VPN connection. - * - */ -static DBusMessage *nm_vpnc_dbus_start_vpn (DBusConnection *con, DBusMessage *message, NmVpncData *data) +static gboolean +real_disconnect (NMVPNPlugin *plugin, + GError **err) { - DBusMessage *reply = NULL; + NMVPNCPluginPrivate *priv = NM_VPNC_PLUGIN_GET_PRIVATE (plugin); - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (con != NULL, NULL); - g_return_val_if_fail (message != NULL, NULL); - - switch (data->state) - { - case NM_VPN_SERVICE_STATE_STARTING: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPNC, NM_DBUS_VPN_STARTING_IN_PROGRESS, - "Could not process the request because the VPN connection is already being started."); - break; - - case NM_VPN_SERVICE_STATE_STARTED: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPNC, NM_DBUS_VPN_ALREADY_STARTED, - "Could not process the request because a VPN connection was already active."); - break; - - case NM_VPN_SERVICE_STATE_STOPPING: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPNC, NM_DBUS_VPN_STOPPING_IN_PROGRESS, - "Could not process the request because the VPN connection is being stopped."); - break; - - case NM_VPN_SERVICE_STATE_STOPPED: - nm_vpnc_cancel_quit_timer (data); - nm_vpnc_dbus_handle_start_vpn (message, data); - reply = dbus_message_new_method_return (message); - break; - - default: - g_assert_not_reached(); - break; + if (priv->pid) { + kill (priv->pid, SIGTERM); + nm_info ("Terminated vpnc daemon with PID %d.", priv->pid); + priv->pid = 0; } - return reply; + return TRUE; } - -/* - * nm_vpnc_dbus_stop_vpn - * - * Terminate a VPN connection. - * - */ -static DBusMessage *nm_vpnc_dbus_stop_vpn (DBusConnection *con, DBusMessage *message, NmVpncData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (con != NULL, NULL); - g_return_val_if_fail (message != NULL, NULL); - - switch (data->state) - { - case NM_VPN_SERVICE_STATE_STOPPING: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPNC, NM_DBUS_VPN_STOPPING_IN_PROGRESS, - "Could not process the request because the VPN connection is already being stopped."); - break; - - case NM_VPN_SERVICE_STATE_STOPPED: - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPNC, NM_DBUS_VPN_ALREADY_STOPPED, - "Could not process the request because no VPN connection was active."); - break; - - case NM_VPN_SERVICE_STATE_STARTING: - case NM_VPN_SERVICE_STATE_STARTED: - nm_vpnc_dbus_handle_stop_vpn (data); - reply = dbus_message_new_method_return (message); - break; - - default: - g_assert_not_reached(); - break; - } - - return reply; -} - - -/* - * nm_vpnc_dbus_get_state - * - * Return some state information to NetworkManager. - * - */ -static DBusMessage *nm_vpnc_dbus_get_state (DBusConnection *con, DBusMessage *message, NmVpncData *data) -{ - DBusMessage *reply = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (con != NULL, NULL); - g_return_val_if_fail (message != NULL, NULL); - - if ((reply = dbus_message_new_method_return (message))) - dbus_message_append_args (reply, DBUS_TYPE_UINT32, &(data->state), DBUS_TYPE_INVALID); - - return reply; -} - - -/* - * nm_vpnc_dbus_process_helper_config_error - * - * Signal the bus that the helper could not get all the configuration information - * it needed. - * - */ -static void nm_vpnc_dbus_process_helper_config_error (DBusConnection *con, DBusMessage *message, NmVpncData *data) -{ - char *error_item; - - g_return_if_fail (data != NULL); - g_return_if_fail (con != NULL); - g_return_if_fail (message != NULL); - - /* Only accept the config info if we're in STARTING state */ - if (data->state != NM_VPN_SERVICE_STATE_STARTING) - return; - - if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &error_item, DBUS_TYPE_INVALID)) - { - nm_warning ("vpnc helper did not receive adequate configuration information from vpnc. It is missing '%s'.", error_item); - nm_vpnc_dbus_signal_failure (data, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD); - } - - nm_vpnc_cancel_helper_timer (data); - nm_vpnc_dbus_handle_stop_vpn (data); -} - -#if 0 -/* - * Prints config returned from vpnc-helper - */ static void -print_vpn_config (guint32 ip4_vpn_gateway, - const char *tundev, - guint32 ip4_address, - guint32 ip4_ptp_address, - gint32 ip4_netmask, - guint32 *ip4_dns, - guint32 ip4_dns_len, - guint32 *ip4_nbns, - guint32 ip4_nbns_len, - const char *cisco_def_domain, - const char *cisco_banner) +nm_vpnc_plugin_init (NMVPNCPlugin *plugin) { - 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_address; - nm_info ("Internal IP4 Address: %s", inet_ntoa (temp_addr)); - temp_addr.s_addr = ip4_netmask; - nm_info ("Internal IP4 Netmask: %s", inet_ntoa (temp_addr)); - temp_addr.s_addr = ip4_ptp_address; - nm_info ("Internal IP4 Point-to-Point Address: %s", inet_ntoa (temp_addr)); - - for (i = 0; i < ip4_dns_len; i++) - { - if (ip4_dns[i] != 0) - { - temp_addr.s_addr = ip4_dns[i]; - nm_info ("Internal IP4 DNS: %s", inet_ntoa (temp_addr)); - } - } - - for (i = 0; i < ip4_nbns_len; i++) - { - if (ip4_nbns[i] != 0) - { - temp_addr.s_addr = ip4_nbns[i]; - nm_info ("Internal IP4 NBNS: %s", inet_ntoa (temp_addr)); - } - } - - nm_info ("Cisco Default Domain: '%s'", cisco_def_domain); - nm_info ("Cisco Banner:"); - nm_info ("-----------------------------------------"); - nm_info ("%s", cisco_banner); - nm_info ("-----------------------------------------"); } -#endif -/* - * nm_vpnc_dbus_process_helper_ip4_config - * - * Signal the bus - * - */ static void -nm_vpnc_dbus_process_helper_ip4_config (DBusConnection *con, - DBusMessage *message, - NmVpncData *data) +nm_vpnc_plugin_class_init (NMVPNCPluginClass *vpnc_class) { - guint32 ip4_vpn_gateway; - char * tundev; - guint32 ip4_address; - guint32 ip4_ptp_address; - guint32 ip4_netmask; - guint32 * ip4_dns; - guint32 ip4_dns_len; - guint32 * ip4_nbns; - guint32 ip4_nbns_len; - char * cisco_def_domain; - char * cisco_banner; - gboolean success = FALSE; - DBusMessage * signal; - DBusMessageIter iter, iter_dict; + GObjectClass *object_class = G_OBJECT_CLASS (vpnc_class); + NMVPNPluginClass *parent_class = NM_VPN_PLUGIN_CLASS (vpnc_class); - g_return_if_fail (data != NULL); - g_return_if_fail (con != NULL); - g_return_if_fail (message != NULL); + g_type_class_add_private (object_class, sizeof (NMVPNCPluginPrivate)); - /* Only accept the config info if we're in STARTING state */ - if (data->state != NM_VPN_SERVICE_STATE_STARTING) - return; - - nm_vpnc_cancel_helper_timer (data); - - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_UINT32, &ip4_vpn_gateway, - DBUS_TYPE_STRING, &tundev, - DBUS_TYPE_UINT32, &ip4_address, - DBUS_TYPE_UINT32, &ip4_netmask, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &ip4_dns, &ip4_dns_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &ip4_nbns, &ip4_nbns_len, - DBUS_TYPE_STRING, &cisco_def_domain, - DBUS_TYPE_STRING, &cisco_banner, DBUS_TYPE_INVALID)) - goto out; - - /* For Cisco/vpnc, PtP address == local VPN address */ - ip4_ptp_address = ip4_address; - -#if 0 - print_vpn_config (ip4_vpn_gateway, tundev, ip4_address, ip4_netmask, - ip4_dns, ip4_dns_len, ip4_nbns, ip4_nbns_len, - cisco_def_domain, cisco_banner); -#endif - - signal = dbus_message_new_signal (NM_DBUS_PATH_VPNC, - NM_DBUS_INTERFACE_VPNC, - NM_DBUS_VPN_SIGNAL_IP4_CONFIG); - if (signal == NULL) - goto out; - - dbus_message_iter_init_append (signal, &iter); - if (!nmu_dbus_dict_open_write (&iter, &iter_dict)) { - nm_warning ("dict open write failed!"); - goto out; - } - - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "gateway", ip4_vpn_gateway)) { - nm_warning ("couldn't append gateway to dict"); - goto out; - } - - if (!nmu_dbus_dict_append_string (&iter_dict, "tundev", tundev)) { - nm_warning ("couldn't append tundev to dict"); - goto out; - } - - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "local_addr", ip4_address)) { - nm_warning ("couldn't append local_address to dict"); - goto out; - } - - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "ptp_addr", ip4_ptp_address)) { - nm_warning ("couldn't append ptp_address to dict"); - goto out; - } - - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "netmask", ip4_netmask)) { - nm_warning ("couldn't append local_address to dict"); - goto out; - } - - if (ip4_dns_len > 0) { - if (!nmu_dbus_dict_append_uint32_array (&iter_dict, - "dns_server", - ip4_dns, - ip4_dns_len)) { - nm_warning ("couldn't append dns_servers to dict"); - goto out; - } - } - - if (ip4_nbns_len > 0) { - if (!nmu_dbus_dict_append_uint32_array (&iter_dict, - "nbns_server", - ip4_nbns, - ip4_nbns_len)) { - nm_warning ("couldn't append nbns_servers to dict"); - goto out; - } - } - - if (!nmu_dbus_dict_append_uint32 (&iter_dict, "mtu", 1412)) { - nm_warning ("couldn't append mtu to dict"); - goto out; - } - - if (!nmu_dbus_dict_append_string (&iter_dict, - "dns_domain", - cisco_def_domain)) { - nm_warning ("couldn't append DNS domain"); - } - - if (cisco_banner && strlen (cisco_banner)) { - if (!nmu_dbus_dict_append_string (&iter_dict, - "banner", - cisco_banner)) { - nm_warning ("couldn't append login banner"); - } - } - - if (!nmu_dbus_dict_close_write (&iter, &iter_dict)) { - nm_warning ("dict close write failed!"); - goto out; - } - - if (!dbus_connection_send (data->con, signal, NULL)) { - nm_warning ("Could not raise the "NM_DBUS_VPN_SIGNAL_IP4_CONFIG" signal!"); - goto out; - } - - dbus_message_unref (signal); - nm_vpnc_set_state (data, NM_VPN_SERVICE_STATE_STARTED); - success = TRUE; - -out: - if (!success) { - nm_warning ("Received invalid IP4 Config information from helper, terminating vpnc."); - nm_vpnc_dbus_handle_stop_vpn (data); - } + /* virtual methods */ + parent_class->connect = real_connect; + parent_class->disconnect = real_disconnect; } - -/* - * nm_vpnc_dbus_message_handler - * - * Handle requests for our services. - * - */ -static DBusHandlerResult nm_vpnc_dbus_message_handler (DBusConnection *con, DBusMessage *message, void *user_data) +NMVPNCPlugin * +nm_vpnc_plugin_new (void) { - NmVpncData *data = (NmVpncData *)user_data; - const char *method; - const char *path; - DBusMessage *reply = NULL; - gboolean handled = TRUE; - - g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (con != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - method = dbus_message_get_member (message); - path = dbus_message_get_path (message); - - /* nm_info ("nm_vpnc_dbus_message_handler() got method '%s' for path '%s'.", method, path); */ - - /* If we aren't ready to accept dbus messages, don't */ - if ((data->state == NM_VPN_SERVICE_STATE_INIT) || (data->state == NM_VPN_SERVICE_STATE_SHUTDOWN)) - { - nm_warning ("Received dbus messages but couldn't handle them due to INIT or SHUTDOWN states."); - reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE_VPNC, NM_DBUS_VPN_WRONG_STATE, - "Could not process the request due to current state of STATE_INIT or STATE_SHUTDOWN."); - goto reply; - } - - if (strcmp ("startConnection", method) == 0) - reply = nm_vpnc_dbus_start_vpn (con, message, data); - else if (strcmp ("stopConnection", method) == 0) - reply = nm_vpnc_dbus_stop_vpn (con, message, data); - else if (strcmp ("getState", method) == 0) - reply = nm_vpnc_dbus_get_state (con, message, data); - else if (strcmp ("signalConfigError", method) == 0) - nm_vpnc_dbus_process_helper_config_error (con, message, data); - else if (strcmp ("signalIP4Config", method) == 0) - nm_vpnc_dbus_process_helper_ip4_config (con, message, data); - else - handled = FALSE; - -reply: - if (reply) - { - dbus_connection_send (con, reply, NULL); - dbus_message_unref (reply); - } - - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + return (NMVPNCPlugin *) g_object_new (NM_TYPE_VPNC_PLUGIN, + NM_VPN_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_VPNC, + NULL); } - -/* - * nm_vpnc_dbus_filter - * - * Handle signals from the bus, like NetworkManager network state - * signals. - * - */ -static DBusHandlerResult nm_vpnc_dbus_filter (DBusConnection *con, DBusMessage *message, void *user_data) +static void +quit_mainloop (NMVPNCPlugin *plugin, gpointer user_data) { - NmVpncData *data = (NmVpncData *)user_data; - gboolean handled = FALSE; - DBusError error; - - g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (con != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - - if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) - { - char *service; - char *old_owner; - char *new_owner; - - dbus_error_init (&error); - if ( dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &service, - DBUS_TYPE_STRING, &old_owner, - DBUS_TYPE_STRING, &new_owner, - DBUS_TYPE_INVALID)) - { - gboolean old_owner_good = (old_owner && (strlen (old_owner) > 0)); - gboolean new_owner_good = (new_owner && (strlen (new_owner) > 0)); - - if ((!old_owner_good && new_owner_good) && (strcmp (service, NM_DBUS_SERVICE) == 0)) /* Equivalent to old ServiceCreated signal */ - { - } - else if ((old_owner_good && !new_owner_good) && (strcmp (service, NM_DBUS_SERVICE) == 0)) /* Equivalent to old ServiceDeleted signal */ - { - /* If NM goes away, we don't stick around */ - nm_vpnc_dbus_handle_stop_vpn (data); - g_main_loop_quit (data->loop); - } - } - } - else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNoLongerActive")) - { - /* If the active device goes down our VPN is certainly not going to work. */ - nm_vpnc_dbus_handle_stop_vpn (data); - } - - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_main_loop_quit ((GMainLoop *) user_data); } - -/* - * nm_vpnc_dbus_init - * - * Grab our connection to the system bus, return NULL if anything goes wrong. - * - */ -DBusConnection *nm_vpnc_dbus_init (NmVpncData *data) +int +main (int argc, char *argv[]) { - DBusConnection *connection = NULL; - DBusError error; - DBusObjectPathVTable vtable = { NULL, &nm_vpnc_dbus_message_handler, NULL, NULL, NULL, NULL }; - - g_return_val_if_fail (data != NULL, NULL); - - dbus_error_init (&error); - if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error))) - { - nm_warning ("Error connecting to system bus: '%s'", error.message); - goto out; - } - - dbus_connection_setup_with_g_main (connection, NULL); - - dbus_error_init (&error); - dbus_bus_request_name (connection, NM_DBUS_SERVICE_VPNC, 0, &error); - if (dbus_error_is_set (&error)) - { - nm_warning ("Could not acquire the dbus service. dbus_bus_request_name() says: '%s'", error.message); - goto out; - } - - if (!dbus_connection_register_object_path (connection, NM_DBUS_PATH_VPNC, &vtable, data)) - { - nm_warning ("Could not register a dbus handler for nm-vpnc-service. Not enough memory?"); - return NULL; - } - - if (!dbus_connection_add_filter (connection, nm_vpnc_dbus_filter, data, NULL)) - return NULL; - - dbus_error_init (&error); - dbus_bus_add_match (connection, - "type='signal'," - "interface='" NM_DBUS_INTERFACE "'," - "sender='" NM_DBUS_SERVICE "'," - "path='" NM_DBUS_PATH "'", - &error); - if (dbus_error_is_set (&error)) - goto out; - - dbus_bus_add_match (connection, - "type='signal'," - "interface='" DBUS_INTERFACE_DBUS "'," - "sender='" DBUS_SERVICE_DBUS "'", - &error); - if (dbus_error_is_set (&error)) - goto out; - -out: - if (dbus_error_is_set (&error)) - { - dbus_error_free (&error); - connection = NULL; - } - return connection; -} - -NmVpncData *vpn_data = NULL; - -static void sigterm_handler (int signum) -{ - nm_info ("nm-vpnc-service caught SIGINT/SIGTERM"); - - g_main_loop_quit (vpn_data->loop); -} - - -/* - * main - * - */ -int main( int argc, char *argv[] ) -{ - struct sigaction action; - sigset_t block_mask; + NMVPNCPlugin *plugin; + GMainLoop *main_loop; g_type_init (); - if (!g_thread_supported ()) - g_thread_init (NULL); - - vpn_data = g_malloc0 (sizeof (NmVpncData)); - - vpn_data->state = NM_VPN_SERVICE_STATE_INIT; - - vpn_data->loop = g_main_loop_new (NULL, FALSE); if (system ("/sbin/modprobe tun") == -1) exit (EXIT_FAILURE); - if (!(vpn_data->con = nm_vpnc_dbus_init (vpn_data))) + plugin = nm_vpnc_plugin_new (); + if (!plugin) exit (EXIT_FAILURE); - action.sa_handler = sigterm_handler; - sigemptyset (&block_mask); - action.sa_mask = block_mask; - action.sa_flags = 0; - sigaction (SIGINT, &action, NULL); - sigaction (SIGTERM, &action, NULL); + main_loop = g_main_loop_new (NULL, FALSE); - nm_vpnc_set_state (vpn_data, NM_VPN_SERVICE_STATE_STOPPED); - g_main_loop_run (vpn_data->loop); + g_signal_connect (plugin, "quit", + G_CALLBACK (quit_mainloop), + main_loop); - nm_vpnc_dbus_handle_stop_vpn (vpn_data); + g_main_loop_run (main_loop); - g_main_loop_unref (vpn_data->loop); - g_free (vpn_data); + g_main_loop_unref (main_loop); + g_object_unref (plugin); exit (EXIT_SUCCESS); } diff --git a/vpn-daemons/vpnc/src/nm-vpnc-service.h b/vpn-daemons/vpnc/src/nm-vpnc-service.h index 995038b4e1..613d5b5474 100644 --- a/vpn-daemons/vpnc/src/nm-vpnc-service.h +++ b/vpn-daemons/vpnc/src/nm-vpnc-service.h @@ -1,29 +1,50 @@ -/* nm-vpnc-service - vpnc integration with NetworkManager - * - * Dan Williams - * - * 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. - */ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ -#ifndef NM_VPNC_SERVICE_H -#define NM_VPNC_SERVICE_H +#ifndef NM_VPNC_PLUGIN_H +#define NM_VPNC_PLUGIN_H -#define NM_DBUS_SERVICE_VPNC "org.freedesktop.NetworkManager.vpnc" -#define NM_DBUS_INTERFACE_VPNC "org.freedesktop.NetworkManager.vpnc" -#define NM_DBUS_PATH_VPNC "/org/freedesktop/NetworkManager/vpnc" +#include +#include +#include -#endif +#define NM_TYPE_VPNC_PLUGIN (nm_vpnc_plugin_get_type ()) +#define NM_VPNC_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPNC_PLUGIN, NMVPNCPlugin)) +#define NM_VPNC_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPNC_PLUGIN, NMVPNCPluginClass)) +#define NM_IS_VPNC_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPNC_PLUGIN)) +#define NM_IS_VPNC_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_VPNC_PLUGIN)) +#define NM_VPNC_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPNC_PLUGIN, NMVPNCPluginClass)) + +#define NM_DBUS_SERVICE_VPNC "org.freedesktop.NetworkManager.vpnc" +#define NM_DBUS_INTERFACE_VPNC "org.freedesktop.NetworkManager.vpnc" +#define NM_DBUS_PATH_VPNC "/org/freedesktop/NetworkManager/vpnc" + +#define NM_VPNC_KEY_GATEWAY "IPSec gateway" +#define NM_VPNC_KEY_ID "IPSec ID" +#define NM_VPNC_KEY_SECRET "IPSec secret" +#define NM_VPNC_KEY_XAUTH_USER "Xauth username" +#define NM_VPNC_KEY_XAUTH_PASSWORD "Xauth password" +#define NM_VPNC_KEY_UDP_ENCAPS "UDP Encapsulate" +#define NM_VPNC_KEY_UDP_ENCAPS_PORT "UDP Encapsulation Port" +#define NM_VPNC_KEY_DOMAIN "Domain" +#define NM_VPNC_KEY_DHGROUP "IKE DH Group" +#define NM_VPNC_KEY_PERFECT_FORWARD "Perfect Forward Secrecy" +#define NM_VPNC_KEY_APP_VERSION "Application Version" +#define NM_VPNC_KEY_REKEYING "Rekeying interval" +#define NM_VPNC_KEY_NAT_KEEPALIVE "NAT-Keepalive package interval" +#define NM_VPNC_KEY_DISABLE_NAT "Disable NAT Traversal" +#define NM_VPNC_KEY_SINGLE_DES "Enable Single DES" + + +typedef struct { + NMVPNPlugin parent; +} NMVPNCPlugin; + +typedef struct { + NMVPNPluginClass parent; +} NMVPNCPluginClass; + +GType nm_vpnc_plugin_get_type (void); + +NMVPNCPlugin *nm_vpnc_plugin_new (void); + +#endif /* NM_VPNC_PLUGIN_H */