1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the
15 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301 USA.
18 * Copyright 2007 - 2008 Novell, Inc.
19 * Copyright 2007 - 2008 Red Hat, Inc.
22 #include "nm-default.h"
24 #include "nm-vpn-plugin.h"
28 #include "nm-vpn-enum-types.h"
30 #include "nm-connection.h"
31 #include "nm-dbus-glib-types.h"
32 #include "nm-setting-private.h"
34 static gboolean impl_vpn_plugin_connect (NMVPNPlugin *plugin,
35 GHashTable *connection,
38 static gboolean impl_vpn_plugin_connect_interactive (NMVPNPlugin *plugin,
39 GHashTable *connection,
43 static gboolean impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin,
44 GHashTable *connection,
48 static gboolean impl_vpn_plugin_new_secrets (NMVPNPlugin *plugin,
49 GHashTable *connection,
52 static gboolean impl_vpn_plugin_disconnect (NMVPNPlugin *plugin,
55 static gboolean impl_vpn_plugin_set_config (NMVPNPlugin *plugin,
59 static gboolean impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
63 static gboolean impl_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
67 static gboolean impl_vpn_plugin_set_failure (NMVPNPlugin *plugin,
71 #include "nm-vpn-plugin-glue.h"
73 #define NM_VPN_PLUGIN_QUIT_TIMER 180
75 G_DEFINE_ABSTRACT_TYPE (NMVPNPlugin, nm_vpn_plugin, G_TYPE_OBJECT)
78 NMVPNServiceState state;
81 DBusGConnection *connection;
82 char *dbus_service_name;
91 gboolean has_ip4, got_ip4;
92 gboolean has_ip6, got_ip6;
94 /* Config stuff copied from config to ip4config */
95 GValue banner, tundev, gateway, mtu;
98 #define NM_VPN_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN, NMVPNPluginPrivate))
113 static guint signals[LAST_SIGNAL] = { 0 };
117 PROP_DBUS_SERVICE_NAME,
123 static GSList *active_plugins = NULL;
127 nm_vpn_plugin_error_quark (void)
129 static GQuark quark = 0;
132 quark = g_quark_from_static_string ("nm_vpn_plugin_error");
139 nm_vpn_plugin_set_connection (NMVPNPlugin *plugin,
140 DBusGConnection *connection)
142 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
144 if (priv->connection)
145 dbus_g_connection_unref (priv->connection);
147 priv->connection = connection;
151 nm_vpn_plugin_get_connection (NMVPNPlugin *plugin)
153 DBusGConnection *connection;
155 g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), NULL);
157 connection = NM_VPN_PLUGIN_GET_PRIVATE (plugin)->connection;
160 dbus_g_connection_ref (connection);
166 nm_vpn_plugin_get_state (NMVPNPlugin *plugin)
168 g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_UNKNOWN);
170 return NM_VPN_PLUGIN_GET_PRIVATE (plugin)->state;
174 nm_vpn_plugin_set_state (NMVPNPlugin *plugin,
175 NMVPNServiceState state)
177 NMVPNPluginPrivate *priv;
179 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
181 priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
182 if (priv->state != state) {
184 g_signal_emit (plugin, signals[STATE_CHANGED], 0, state);
189 nm_vpn_plugin_set_login_banner (NMVPNPlugin *plugin,
192 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
193 g_return_if_fail (banner != NULL);
195 g_signal_emit (plugin, signals[LOGIN_BANNER], 0, banner);
199 nm_vpn_plugin_failure (NMVPNPlugin *plugin,
200 NMVPNPluginFailure reason)
202 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
204 g_signal_emit (plugin, signals[FAILURE], 0, reason);
208 nm_vpn_plugin_disconnect (NMVPNPlugin *plugin, GError **err)
210 gboolean ret = FALSE;
211 NMVPNServiceState state;
213 g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
215 state = nm_vpn_plugin_get_state (plugin);
217 case NM_VPN_SERVICE_STATE_STOPPING:
220 NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
222 "Could not process the request because the VPN connection is already being stopped.");
224 case NM_VPN_SERVICE_STATE_STOPPED:
227 NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,
229 "Could not process the request because no VPN connection was active.");
231 case NM_VPN_SERVICE_STATE_STARTING:
232 case NM_VPN_SERVICE_STATE_STARTED:
233 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPING);
234 ret = NM_VPN_PLUGIN_GET_CLASS (plugin)->disconnect (plugin, err);
235 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED);
237 case NM_VPN_SERVICE_STATE_INIT:
242 g_warning ("Unhandled VPN service state %d", state);
243 g_assert_not_reached ();
251 nm_vpn_plugin_emit_quit (NMVPNPlugin *plugin)
253 g_signal_emit (plugin, signals[QUIT], 0);
257 connect_timer_expired (gpointer data)
259 NMVPNPlugin *plugin = NM_VPN_PLUGIN (data);
262 NM_VPN_PLUGIN_GET_PRIVATE (plugin)->connect_timer = 0;
263 g_message ("Connect timer expired, disconnecting.");
264 nm_vpn_plugin_disconnect (plugin, &err);
266 g_warning ("Disconnect failed: %s", err->message);
270 return G_SOURCE_REMOVE;
274 quit_timer_expired (gpointer data)
276 NMVPNPlugin *self = NM_VPN_PLUGIN (data);
278 NM_VPN_PLUGIN_GET_PRIVATE (self)->quit_timer = 0;
279 nm_vpn_plugin_emit_quit (self);
280 return G_SOURCE_REMOVE;
284 schedule_quit_timer (NMVPNPlugin *self)
286 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (self);
288 nm_clear_g_source (&priv->quit_timer);
289 priv->quit_timer = g_timeout_add_seconds (NM_VPN_PLUGIN_QUIT_TIMER,
295 fail_stop (gpointer data)
297 NMVPNPlugin *self = NM_VPN_PLUGIN (data);
299 NM_VPN_PLUGIN_GET_PRIVATE (self)->fail_stop_id = 0;
300 nm_vpn_plugin_set_state (self, NM_VPN_SERVICE_STATE_STOPPED);
301 return G_SOURCE_REMOVE;
305 schedule_fail_stop (NMVPNPlugin *plugin, guint timeout_secs)
307 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
309 nm_clear_g_source (&priv->fail_stop_id);
311 priv->fail_stop_id = g_timeout_add_seconds (timeout_secs, fail_stop, plugin);
313 priv->fail_stop_id = g_idle_add (fail_stop, plugin);
317 _g_value_set (GValue *dst, GValue *src)
320 GType type = G_VALUE_TYPE (src);
322 if (G_IS_VALUE (dst))
324 g_value_init (dst, type);
325 g_value_copy (src, dst);
326 } else if (G_IS_VALUE (dst))
331 nm_vpn_plugin_set_config (NMVPNPlugin *plugin,
334 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
337 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
338 g_return_if_fail (config != NULL);
340 priv->got_config = TRUE;
342 val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP4);
343 if (val && g_value_get_boolean (val))
344 priv->has_ip4 = TRUE;
345 val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP6);
346 if (val && g_value_get_boolean (val))
347 priv->has_ip6 = TRUE;
349 /* Record the items that need to also be inserted into the
350 * ip4config, for compatibility with older daemons.
352 _g_value_set (&priv->banner, g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_BANNER));
353 _g_value_set (&priv->tundev, g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_TUNDEV));
354 _g_value_set (&priv->gateway, g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY));
355 _g_value_set (&priv->mtu, g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_MTU));
357 g_signal_emit (plugin, signals[CONFIG], 0, config);
361 nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
362 GHashTable *ip4_config)
364 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
365 GHashTable *combined_config;
369 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
370 g_return_if_fail (ip4_config != NULL);
372 priv->got_ip4 = TRUE;
374 /* Old plugins won't send the "config" signal and thus can't send
375 * NM_VPN_PLUGIN_CONFIG_HAS_IP4 either. But since they don't support IPv6,
376 * we can safely assume that, if we don't receive a "config" signal but do
377 * receive an "ip4-config" signal, the old plugin supports IPv4.
379 if (!priv->got_config)
380 priv->has_ip4 = TRUE;
382 /* Older NetworkManager daemons expect all config info to be in
383 * the ip4 config, so they won't even notice the "config" signal
384 * being emitted. So just copy all of that data into the ip4
387 combined_config = g_hash_table_new (g_str_hash, g_str_equal);
388 g_hash_table_iter_init (&iter, ip4_config);
389 while (g_hash_table_iter_next (&iter, &key, &value))
390 g_hash_table_insert (combined_config, key, value);
392 if (G_VALUE_TYPE (&priv->banner) != G_TYPE_INVALID)
393 g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_BANNER, &priv->banner);
394 if (G_VALUE_TYPE (&priv->tundev) != G_TYPE_INVALID)
395 g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, &priv->tundev);
396 if (G_VALUE_TYPE (&priv->gateway) != G_TYPE_INVALID)
397 g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, &priv->gateway);
398 if (G_VALUE_TYPE (&priv->mtu) != G_TYPE_INVALID)
399 g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_MTU, &priv->mtu);
401 g_signal_emit (plugin, signals[IP4_CONFIG], 0, combined_config);
402 g_hash_table_destroy (combined_config);
404 if ( priv->has_ip4 == priv->got_ip4
405 && priv->has_ip6 == priv->got_ip6)
406 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
410 nm_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
411 GHashTable *ip6_config)
413 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
415 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
416 g_return_if_fail (ip6_config != NULL);
418 priv->got_ip6 = TRUE;
419 g_signal_emit (plugin, signals[IP6_CONFIG], 0, ip6_config);
421 if ( priv->has_ip4 == priv->got_ip4
422 && priv->has_ip6 == priv->got_ip6)
423 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
427 connect_timer_start (NMVPNPlugin *plugin)
429 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
431 nm_clear_g_source (&priv->connect_timer);
432 priv->connect_timer = g_timeout_add_seconds (60, connect_timer_expired, plugin);
436 _connect_generic (NMVPNPlugin *plugin,
437 GHashTable *properties,
441 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
442 NMVPNPluginClass *vpn_class = NM_VPN_PLUGIN_GET_CLASS (plugin);
443 NMConnection *connection;
444 gboolean success = FALSE;
445 GError *local = NULL;
446 guint fail_stop_timeout = 0;
448 if (priv->state != NM_VPN_SERVICE_STATE_STOPPED &&
449 priv->state != NM_VPN_SERVICE_STATE_INIT) {
450 g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_WRONG_STATE,
451 "Could not start connection: wrong plugin state %d",
456 connection = _nm_connection_new_from_hash (properties);
458 priv->interactive = FALSE;
459 if (details && !vpn_class->connect_interactive) {
460 g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED,
461 "Plugin does not implement ConnectInteractive()");
465 nm_clear_g_source (&priv->fail_stop_id);
468 priv->interactive = TRUE;
469 success = vpn_class->connect_interactive (plugin, connection, details, &local);
470 if (g_error_matches (local, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED)) {
471 /* Give NetworkManager a bit of time to fall back to Connect() */
472 fail_stop_timeout = 5;
474 g_propagate_error (error, local);
476 success = vpn_class->connect (plugin, connection, error);
479 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING);
481 /* Add a timer to make sure we do not wait indefinitely for the successful connect. */
482 connect_timer_start (plugin);
484 /* Stop the plugin from an idle handler so that the Connect
485 * method return gets sent before the STOP StateChanged signal.
487 schedule_fail_stop (plugin, fail_stop_timeout);
490 g_object_unref (connection);
495 impl_vpn_plugin_connect (NMVPNPlugin *plugin,
496 GHashTable *connection,
499 return _connect_generic (plugin, connection, NULL, error);
503 impl_vpn_plugin_connect_interactive (NMVPNPlugin *plugin,
504 GHashTable *connection,
508 return _connect_generic (plugin, connection, details, error);
511 /***************************************************************/
514 impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin,
515 GHashTable *properties,
519 gboolean ret = FALSE;
520 NMConnection *connection;
522 GError *ns_err = NULL;
523 gboolean needed = FALSE;
525 g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
526 g_return_val_if_fail (properties != NULL, FALSE);
528 connection = _nm_connection_new_from_hash (properties);
530 if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets) {
536 needed = NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets (plugin, connection, &sn, &ns_err);
538 *err = g_error_copy (ns_err);
539 g_error_free (ns_err);
545 /* Push back the quit timer so the VPN plugin doesn't quit in the
546 * middle of asking the user for secrets.
548 schedule_quit_timer (plugin);
551 *setting_name = g_strdup (sn);
553 /* No secrets required */
554 *setting_name = g_strdup ("");
562 impl_vpn_plugin_new_secrets (NMVPNPlugin *plugin,
563 GHashTable *properties,
566 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
567 NMConnection *connection;
570 if (priv->state != NM_VPN_SERVICE_STATE_STARTING) {
571 g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_WRONG_STATE,
572 "Could not accept new secrets: wrong plugin state %d",
577 connection = _nm_connection_new_from_hash (properties);
579 if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->new_secrets) {
580 g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED,
581 "Could not accept new secrets: plugin cannot process interactive secrets");
582 g_object_unref (connection);
586 success = NM_VPN_PLUGIN_GET_CLASS (plugin)->new_secrets (plugin, connection, error);
588 /* Add a timer to make sure we do not wait indefinitely for the successful connect. */
589 connect_timer_start (plugin);
591 /* Stop the plugin from and idle handler so that the NewSecrets
592 * method return gets sent before the STOP StateChanged signal.
594 schedule_fail_stop (plugin, 0);
597 g_object_unref (connection);
602 * nm_vpn_plugin_secrets_required:
603 * @plugin: the #NMVPNPlugin
604 * @message: an information message about why secrets are required, if any
605 * @hints: VPN specific secret names for required new secrets
607 * Called by VPN plugin implementations to signal to NetworkManager that secrets
608 * are required during the connection process. This signal may be used to
609 * request new secrets when the secrets originally provided by NetworkManager
610 * are insufficient, or the VPN process indicates that it needs additional
611 * information to complete the request.
616 nm_vpn_plugin_secrets_required (NMVPNPlugin *plugin,
620 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
622 /* Plugin must be able to accept the new secrets if it calls this method */
623 g_return_if_fail (NM_VPN_PLUGIN_GET_CLASS (plugin)->new_secrets);
625 /* Plugin cannot call this method if NetworkManager didn't originally call
626 * ConnectInteractive().
628 g_return_if_fail (priv->interactive == TRUE);
630 /* Cancel the connect timer since secrets might take a while. It'll
631 * get restarted when the secrets come back via NewSecrets().
633 nm_clear_g_source (&priv->connect_timer);
635 g_signal_emit (plugin, signals[SECRETS_REQUIRED], 0, message, hints);
638 /***************************************************************/
641 impl_vpn_plugin_disconnect (NMVPNPlugin *plugin,
644 return nm_vpn_plugin_disconnect (plugin, err);
648 impl_vpn_plugin_set_config (NMVPNPlugin *plugin,
652 nm_vpn_plugin_set_config (plugin, config);
658 impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
662 nm_vpn_plugin_set_ip4_config (plugin, config);
668 impl_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
672 nm_vpn_plugin_set_ip6_config (plugin, config);
678 impl_vpn_plugin_set_failure (NMVPNPlugin *plugin,
682 nm_vpn_plugin_failure (plugin, NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG);
687 /*********************************************************************/
690 sigterm_handler (int signum)
692 g_slist_foreach (active_plugins, (GFunc) nm_vpn_plugin_emit_quit, NULL);
696 setup_unix_signal_handler (void)
698 struct sigaction action;
701 action.sa_handler = sigterm_handler;
702 sigemptyset (&block_mask);
703 action.sa_mask = block_mask;
705 sigaction (SIGINT, &action, NULL);
706 sigaction (SIGTERM, &action, NULL);
709 /*********************************************************************/
712 one_plugin_destroyed (gpointer data,
715 active_plugins = g_slist_remove (active_plugins, object);
719 nm_vpn_plugin_init (NMVPNPlugin *plugin)
721 active_plugins = g_slist_append (active_plugins, plugin);
722 g_object_weak_ref (G_OBJECT (plugin),
723 one_plugin_destroyed,
728 constructor (GType type,
729 guint n_construct_params,
730 GObjectConstructParam *construct_params)
734 NMVPNPluginPrivate *priv;
735 DBusGConnection *connection;
737 guint request_name_result;
740 object = G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->constructor (type,
746 priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
747 if (!priv->dbus_service_name)
750 connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
754 proxy = dbus_g_proxy_new_for_name (connection,
757 DBUS_INTERFACE_DBUS);
759 if (!dbus_g_proxy_call (proxy, "RequestName", &err,
760 G_TYPE_STRING, priv->dbus_service_name,
763 G_TYPE_UINT, &request_name_result,
765 g_object_unref (proxy);
769 g_object_unref (proxy);
771 dbus_g_connection_register_g_object (connection,
772 NM_VPN_DBUS_PLUGIN_PATH,
775 plugin = NM_VPN_PLUGIN (object);
777 nm_vpn_plugin_set_connection (plugin, connection);
778 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_INIT);
784 g_warning ("Failed to initialize VPN plugin: %s", err->message);
789 g_object_unref (object);
795 set_property (GObject *object, guint prop_id,
796 const GValue *value, GParamSpec *pspec)
798 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
801 case PROP_DBUS_SERVICE_NAME:
803 priv->dbus_service_name = g_strdup (g_value_get_string (value));
806 nm_vpn_plugin_set_state (NM_VPN_PLUGIN (object),
807 (NMVPNServiceState) g_value_get_uint (value));
810 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
816 get_property (GObject *object, guint prop_id,
817 GValue *value, GParamSpec *pspec)
819 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
822 case PROP_DBUS_SERVICE_NAME:
823 g_value_set_string (value, priv->dbus_service_name);
826 g_value_set_uint (value, nm_vpn_plugin_get_state (NM_VPN_PLUGIN (object)));
829 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
835 dispose (GObject *object)
837 NMVPNPlugin *plugin = NM_VPN_PLUGIN (object);
838 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
839 NMVPNServiceState state;
842 nm_clear_g_source (&priv->fail_stop_id);
843 nm_clear_g_source (&priv->quit_timer);
844 nm_clear_g_source (&priv->connect_timer);
846 state = nm_vpn_plugin_get_state (plugin);
848 if (state == NM_VPN_SERVICE_STATE_STARTED ||
849 state == NM_VPN_SERVICE_STATE_STARTING)
850 nm_vpn_plugin_disconnect (plugin, &err);
853 g_warning ("Error disconnecting VPN connection: %s", err->message);
857 G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->dispose (object);
861 finalize (GObject *object)
863 NMVPNPlugin *plugin = NM_VPN_PLUGIN (object);
864 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
866 nm_vpn_plugin_set_connection (plugin, NULL);
867 g_free (priv->dbus_service_name);
869 if (G_IS_VALUE (&priv->banner))
870 g_value_unset (&priv->banner);
871 if (G_IS_VALUE (&priv->tundev))
872 g_value_unset (&priv->tundev);
873 if (G_IS_VALUE (&priv->gateway))
874 g_value_unset (&priv->gateway);
875 if (G_IS_VALUE (&priv->mtu))
876 g_value_unset (&priv->mtu);
878 G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->finalize (object);
882 state_changed (NMVPNPlugin *plugin, NMVPNServiceState state)
884 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
887 case NM_VPN_SERVICE_STATE_STARTING:
888 nm_clear_g_source (&priv->quit_timer);
889 nm_clear_g_source (&priv->fail_stop_id);
891 case NM_VPN_SERVICE_STATE_STOPPED:
892 schedule_quit_timer (plugin);
895 /* Clean up all timers we might have set up. */
896 nm_clear_g_source (&priv->connect_timer);
897 nm_clear_g_source (&priv->quit_timer);
898 nm_clear_g_source (&priv->fail_stop_id);
904 nm_vpn_plugin_class_init (NMVPNPluginClass *plugin_class)
906 GObjectClass *object_class = G_OBJECT_CLASS (plugin_class);
908 g_type_class_add_private (object_class, sizeof (NMVPNPluginPrivate));
910 dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (plugin_class),
911 &dbus_glib_nm_vpn_plugin_object_info);
913 /* virtual methods */
914 object_class->constructor = constructor;
915 object_class->set_property = set_property;
916 object_class->get_property = get_property;
917 object_class->dispose = dispose;
918 object_class->finalize = finalize;
920 plugin_class->state_changed = state_changed;
925 * NMVPNPlugin:service-name:
927 * The D-Bus service name of this plugin.
929 g_object_class_install_property
930 (object_class, PROP_DBUS_SERVICE_NAME,
931 g_param_spec_string (NM_VPN_PLUGIN_DBUS_SERVICE_NAME, "", "",
934 G_PARAM_CONSTRUCT_ONLY |
935 G_PARAM_STATIC_STRINGS));
940 * The state of the plugin.
942 g_object_class_install_property
943 (object_class, PROP_STATE,
944 g_param_spec_uint (NM_VPN_PLUGIN_STATE, "", "",
945 NM_VPN_SERVICE_STATE_UNKNOWN,
946 NM_VPN_SERVICE_STATE_STOPPED,
947 NM_VPN_SERVICE_STATE_INIT,
949 G_PARAM_STATIC_STRINGS));
952 signals[STATE_CHANGED] =
953 g_signal_new ("state-changed",
954 G_OBJECT_CLASS_TYPE (object_class),
956 G_STRUCT_OFFSET (NMVPNPluginClass, state_changed),
958 g_cclosure_marshal_VOID__UINT,
962 signals[SECRETS_REQUIRED] =
963 g_signal_new ("secrets-required",
964 G_OBJECT_CLASS_TYPE (object_class),
968 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRV);
971 g_signal_new ("config",
972 G_OBJECT_CLASS_TYPE (object_class),
974 G_STRUCT_OFFSET (NMVPNPluginClass, config),
976 g_cclosure_marshal_VOID__BOXED,
978 DBUS_TYPE_G_MAP_OF_VARIANT);
980 signals[IP4_CONFIG] =
981 g_signal_new ("ip4-config",
982 G_OBJECT_CLASS_TYPE (object_class),
984 G_STRUCT_OFFSET (NMVPNPluginClass, ip4_config),
986 g_cclosure_marshal_VOID__BOXED,
988 DBUS_TYPE_G_MAP_OF_VARIANT);
990 signals[IP6_CONFIG] =
991 g_signal_new ("ip6-config",
992 G_OBJECT_CLASS_TYPE (object_class),
994 G_STRUCT_OFFSET (NMVPNPluginClass, ip6_config),
996 g_cclosure_marshal_VOID__BOXED,
998 DBUS_TYPE_G_MAP_OF_VARIANT);
1000 signals[LOGIN_BANNER] =
1001 g_signal_new ("login-banner",
1002 G_OBJECT_CLASS_TYPE (object_class),
1004 G_STRUCT_OFFSET (NMVPNPluginClass, login_banner),
1006 g_cclosure_marshal_VOID__STRING,
1011 g_signal_new ("failure",
1012 G_OBJECT_CLASS_TYPE (object_class),
1014 G_STRUCT_OFFSET (NMVPNPluginClass, failure),
1016 g_cclosure_marshal_VOID__UINT,
1021 g_signal_new ("quit",
1022 G_OBJECT_CLASS_TYPE (object_class),
1024 G_STRUCT_OFFSET (NMVPNPluginClass, quit),
1026 g_cclosure_marshal_VOID__VOID,
1030 dbus_g_error_domain_register (NM_VPN_PLUGIN_ERROR,
1031 NM_DBUS_VPN_ERROR_PREFIX,
1032 NM_TYPE_VPN_PLUGIN_ERROR);
1034 setup_unix_signal_handler ();