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"
33 static gboolean impl_vpn_plugin_connect (NMVPNPlugin *plugin,
34 GHashTable *connection,
37 static gboolean impl_vpn_plugin_connect_interactive (NMVPNPlugin *plugin,
38 GHashTable *connection,
42 static gboolean impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin,
43 GHashTable *connection,
47 static gboolean impl_vpn_plugin_new_secrets (NMVPNPlugin *plugin,
48 GHashTable *connection,
51 static gboolean impl_vpn_plugin_disconnect (NMVPNPlugin *plugin,
54 static gboolean impl_vpn_plugin_set_config (NMVPNPlugin *plugin,
58 static gboolean impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
62 static gboolean impl_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
66 static gboolean impl_vpn_plugin_set_failure (NMVPNPlugin *plugin,
70 #include "nm-vpn-plugin-glue.h"
72 #define NM_VPN_PLUGIN_QUIT_TIMER 180
74 G_DEFINE_ABSTRACT_TYPE (NMVPNPlugin, nm_vpn_plugin, G_TYPE_OBJECT)
77 NMVPNServiceState state;
80 DBusGConnection *connection;
81 char *dbus_service_name;
90 gboolean has_ip4, got_ip4;
91 gboolean has_ip6, got_ip6;
93 /* Config stuff copied from config to ip4config */
94 GValue banner, tundev, gateway, mtu;
97 #define NM_VPN_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN, NMVPNPluginPrivate))
112 static guint signals[LAST_SIGNAL] = { 0 };
116 PROP_DBUS_SERVICE_NAME,
122 static GSList *active_plugins = NULL;
126 nm_vpn_plugin_error_quark (void)
128 static GQuark quark = 0;
131 quark = g_quark_from_static_string ("nm_vpn_plugin_error");
138 nm_vpn_plugin_set_connection (NMVPNPlugin *plugin,
139 DBusGConnection *connection)
141 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
143 if (priv->connection)
144 dbus_g_connection_unref (priv->connection);
146 priv->connection = connection;
150 nm_vpn_plugin_get_connection (NMVPNPlugin *plugin)
152 DBusGConnection *connection;
154 g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), NULL);
156 connection = NM_VPN_PLUGIN_GET_PRIVATE (plugin)->connection;
159 dbus_g_connection_ref (connection);
165 nm_vpn_plugin_get_state (NMVPNPlugin *plugin)
167 g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), NM_VPN_SERVICE_STATE_UNKNOWN);
169 return NM_VPN_PLUGIN_GET_PRIVATE (plugin)->state;
173 nm_vpn_plugin_set_state (NMVPNPlugin *plugin,
174 NMVPNServiceState state)
176 NMVPNPluginPrivate *priv;
178 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
180 priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
181 if (priv->state != state) {
183 g_signal_emit (plugin, signals[STATE_CHANGED], 0, state);
188 nm_vpn_plugin_set_login_banner (NMVPNPlugin *plugin,
191 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
192 g_return_if_fail (banner != NULL);
194 g_signal_emit (plugin, signals[LOGIN_BANNER], 0, banner);
198 nm_vpn_plugin_failure (NMVPNPlugin *plugin,
199 NMVPNPluginFailure reason)
201 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
203 g_signal_emit (plugin, signals[FAILURE], 0, reason);
207 nm_vpn_plugin_disconnect (NMVPNPlugin *plugin, GError **err)
209 gboolean ret = FALSE;
210 NMVPNServiceState state;
212 g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
214 state = nm_vpn_plugin_get_state (plugin);
216 case NM_VPN_SERVICE_STATE_STOPPING:
219 NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
221 "Could not process the request because the VPN connection is already being stopped.");
223 case NM_VPN_SERVICE_STATE_STOPPED:
226 NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,
228 "Could not process the request because no VPN connection was active.");
230 case NM_VPN_SERVICE_STATE_STARTING:
231 case NM_VPN_SERVICE_STATE_STARTED:
232 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPING);
233 ret = NM_VPN_PLUGIN_GET_CLASS (plugin)->disconnect (plugin, err);
234 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED);
236 case NM_VPN_SERVICE_STATE_INIT:
241 g_warning ("Unhandled VPN service state %d", state);
242 g_assert_not_reached ();
250 nm_vpn_plugin_emit_quit (NMVPNPlugin *plugin)
252 g_signal_emit (plugin, signals[QUIT], 0);
256 connect_timer_expired (gpointer data)
258 NMVPNPlugin *plugin = NM_VPN_PLUGIN (data);
261 NM_VPN_PLUGIN_GET_PRIVATE (plugin)->connect_timer = 0;
262 g_message ("Connect timer expired, disconnecting.");
263 nm_vpn_plugin_disconnect (plugin, &err);
265 g_warning ("Disconnect failed: %s", err->message);
269 return G_SOURCE_REMOVE;
273 quit_timer_expired (gpointer data)
275 NMVPNPlugin *self = NM_VPN_PLUGIN (data);
277 NM_VPN_PLUGIN_GET_PRIVATE (self)->quit_timer = 0;
278 nm_vpn_plugin_emit_quit (self);
279 return G_SOURCE_REMOVE;
283 schedule_quit_timer (NMVPNPlugin *self)
285 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (self);
287 nm_clear_g_source (&priv->quit_timer);
288 priv->quit_timer = g_timeout_add_seconds (NM_VPN_PLUGIN_QUIT_TIMER,
294 fail_stop (gpointer data)
296 NMVPNPlugin *self = NM_VPN_PLUGIN (data);
298 NM_VPN_PLUGIN_GET_PRIVATE (self)->fail_stop_id = 0;
299 nm_vpn_plugin_set_state (self, NM_VPN_SERVICE_STATE_STOPPED);
300 return G_SOURCE_REMOVE;
304 schedule_fail_stop (NMVPNPlugin *plugin, guint timeout_secs)
306 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
308 nm_clear_g_source (&priv->fail_stop_id);
310 priv->fail_stop_id = g_timeout_add_seconds (timeout_secs, fail_stop, plugin);
312 priv->fail_stop_id = g_idle_add (fail_stop, plugin);
316 _g_value_set (GValue *dst, GValue *src)
319 GType type = G_VALUE_TYPE (src);
321 if (G_IS_VALUE (dst))
323 g_value_init (dst, type);
324 g_value_copy (src, dst);
325 } else if (G_IS_VALUE (dst))
330 nm_vpn_plugin_set_config (NMVPNPlugin *plugin,
333 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
336 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
337 g_return_if_fail (config != NULL);
339 priv->got_config = TRUE;
341 val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP4);
342 if (val && g_value_get_boolean (val))
343 priv->has_ip4 = TRUE;
344 val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP6);
345 if (val && g_value_get_boolean (val))
346 priv->has_ip6 = TRUE;
348 /* Record the items that need to also be inserted into the
349 * ip4config, for compatibility with older daemons.
351 _g_value_set (&priv->banner, g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_BANNER));
352 _g_value_set (&priv->tundev, g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_TUNDEV));
353 _g_value_set (&priv->gateway, g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY));
354 _g_value_set (&priv->mtu, g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_MTU));
356 g_signal_emit (plugin, signals[CONFIG], 0, config);
360 nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
361 GHashTable *ip4_config)
363 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
364 GHashTable *combined_config;
368 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
369 g_return_if_fail (ip4_config != NULL);
371 priv->got_ip4 = TRUE;
373 /* Old plugins won't send the "config" signal and thus can't send
374 * NM_VPN_PLUGIN_CONFIG_HAS_IP4 either. But since they don't support IPv6,
375 * we can safely assume that, if we don't receive a "config" signal but do
376 * receive an "ip4-config" signal, the old plugin supports IPv4.
378 if (!priv->got_config)
379 priv->has_ip4 = TRUE;
381 /* Older NetworkManager daemons expect all config info to be in
382 * the ip4 config, so they won't even notice the "config" signal
383 * being emitted. So just copy all of that data into the ip4
386 combined_config = g_hash_table_new (g_str_hash, g_str_equal);
387 g_hash_table_iter_init (&iter, ip4_config);
388 while (g_hash_table_iter_next (&iter, &key, &value))
389 g_hash_table_insert (combined_config, key, value);
391 if (G_VALUE_TYPE (&priv->banner) != G_TYPE_INVALID)
392 g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_BANNER, &priv->banner);
393 if (G_VALUE_TYPE (&priv->tundev) != G_TYPE_INVALID)
394 g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, &priv->tundev);
395 if (G_VALUE_TYPE (&priv->gateway) != G_TYPE_INVALID)
396 g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, &priv->gateway);
397 if (G_VALUE_TYPE (&priv->mtu) != G_TYPE_INVALID)
398 g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_MTU, &priv->mtu);
400 g_signal_emit (plugin, signals[IP4_CONFIG], 0, combined_config);
401 g_hash_table_destroy (combined_config);
403 if ( priv->has_ip4 == priv->got_ip4
404 && priv->has_ip6 == priv->got_ip6)
405 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
409 nm_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
410 GHashTable *ip6_config)
412 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
414 g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
415 g_return_if_fail (ip6_config != NULL);
417 priv->got_ip6 = TRUE;
418 g_signal_emit (plugin, signals[IP6_CONFIG], 0, ip6_config);
420 if ( priv->has_ip4 == priv->got_ip4
421 && priv->has_ip6 == priv->got_ip6)
422 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
426 connect_timer_start (NMVPNPlugin *plugin)
428 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
430 nm_clear_g_source (&priv->connect_timer);
431 priv->connect_timer = g_timeout_add_seconds (60, connect_timer_expired, plugin);
435 _connect_generic (NMVPNPlugin *plugin,
436 GHashTable *properties,
440 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
441 NMVPNPluginClass *vpn_class = NM_VPN_PLUGIN_GET_CLASS (plugin);
442 NMConnection *connection;
443 gboolean success = FALSE;
444 GError *local = NULL;
445 guint fail_stop_timeout = 0;
447 if (priv->state != NM_VPN_SERVICE_STATE_STOPPED &&
448 priv->state != NM_VPN_SERVICE_STATE_INIT) {
449 g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_WRONG_STATE,
450 "Could not start connection: wrong plugin state %d",
455 connection = nm_connection_new_from_hash (properties, &local);
457 g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
458 "Invalid connection: %s", local->message);
459 g_clear_error (&local);
463 priv->interactive = FALSE;
464 if (details && !vpn_class->connect_interactive) {
465 g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED,
466 "Plugin does not implement ConnectInteractive()");
470 nm_clear_g_source (&priv->fail_stop_id);
473 priv->interactive = TRUE;
474 success = vpn_class->connect_interactive (plugin, connection, details, &local);
475 if (g_error_matches (local, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED)) {
476 /* Give NetworkManager a bit of time to fall back to Connect() */
477 fail_stop_timeout = 5;
479 g_propagate_error (error, local);
481 success = vpn_class->connect (plugin, connection, error);
484 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING);
486 /* Add a timer to make sure we do not wait indefinitely for the successful connect. */
487 connect_timer_start (plugin);
489 /* Stop the plugin from an idle handler so that the Connect
490 * method return gets sent before the STOP StateChanged signal.
492 schedule_fail_stop (plugin, fail_stop_timeout);
495 g_object_unref (connection);
500 impl_vpn_plugin_connect (NMVPNPlugin *plugin,
501 GHashTable *connection,
504 return _connect_generic (plugin, connection, NULL, error);
508 impl_vpn_plugin_connect_interactive (NMVPNPlugin *plugin,
509 GHashTable *connection,
513 return _connect_generic (plugin, connection, details, error);
516 /***************************************************************/
519 impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin,
520 GHashTable *properties,
524 gboolean ret = FALSE;
525 NMConnection *connection;
527 GError *ns_err = NULL;
528 gboolean needed = FALSE;
529 GError *cnfh_err = NULL;
531 g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE);
532 g_return_val_if_fail (properties != NULL, FALSE);
534 connection = nm_connection_new_from_hash (properties, &cnfh_err);
538 NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID,
539 "The connection was invalid: '%s' / '%s' invalid.",
540 g_type_name (nm_connection_lookup_setting_type_by_quark (cnfh_err->domain)),
542 g_error_free (cnfh_err);
546 if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets) {
552 needed = NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets (plugin, connection, &sn, &ns_err);
554 *err = g_error_copy (ns_err);
555 g_error_free (ns_err);
561 /* Push back the quit timer so the VPN plugin doesn't quit in the
562 * middle of asking the user for secrets.
564 schedule_quit_timer (plugin);
567 *setting_name = g_strdup (sn);
569 /* No secrets required */
570 *setting_name = g_strdup ("");
578 impl_vpn_plugin_new_secrets (NMVPNPlugin *plugin,
579 GHashTable *properties,
582 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
583 NMConnection *connection;
584 GError *local = NULL;
587 if (priv->state != NM_VPN_SERVICE_STATE_STARTING) {
588 g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_WRONG_STATE,
589 "Could not accept new secrets: wrong plugin state %d",
594 connection = nm_connection_new_from_hash (properties, &local);
596 g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
597 "Invalid connection: %s",
599 g_clear_error (&local);
603 if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->new_secrets) {
604 g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED,
605 "Could not accept new secrets: plugin cannot process interactive secrets");
606 g_object_unref (connection);
610 success = NM_VPN_PLUGIN_GET_CLASS (plugin)->new_secrets (plugin, connection, error);
612 /* Add a timer to make sure we do not wait indefinitely for the successful connect. */
613 connect_timer_start (plugin);
615 /* Stop the plugin from and idle handler so that the NewSecrets
616 * method return gets sent before the STOP StateChanged signal.
618 schedule_fail_stop (plugin, 0);
621 g_object_unref (connection);
626 * nm_vpn_plugin_secrets_required:
627 * @plugin: the #NMVPNPlugin
628 * @message: an information message about why secrets are required, if any
629 * @hints: VPN specific secret names for required new secrets
631 * Called by VPN plugin implementations to signal to NetworkManager that secrets
632 * are required during the connection process. This signal may be used to
633 * request new secrets when the secrets originally provided by NetworkManager
634 * are insufficient, or the VPN process indicates that it needs additional
635 * information to complete the request.
640 nm_vpn_plugin_secrets_required (NMVPNPlugin *plugin,
644 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
646 /* Plugin must be able to accept the new secrets if it calls this method */
647 g_return_if_fail (NM_VPN_PLUGIN_GET_CLASS (plugin)->new_secrets);
649 /* Plugin cannot call this method if NetworkManager didn't originally call
650 * ConnectInteractive().
652 g_return_if_fail (priv->interactive == TRUE);
654 /* Cancel the connect timer since secrets might take a while. It'll
655 * get restarted when the secrets come back via NewSecrets().
657 nm_clear_g_source (&priv->connect_timer);
659 g_signal_emit (plugin, signals[SECRETS_REQUIRED], 0, message, hints);
662 /***************************************************************/
665 impl_vpn_plugin_disconnect (NMVPNPlugin *plugin,
668 return nm_vpn_plugin_disconnect (plugin, err);
672 impl_vpn_plugin_set_config (NMVPNPlugin *plugin,
676 nm_vpn_plugin_set_config (plugin, config);
682 impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
686 nm_vpn_plugin_set_ip4_config (plugin, config);
692 impl_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
696 nm_vpn_plugin_set_ip6_config (plugin, config);
702 impl_vpn_plugin_set_failure (NMVPNPlugin *plugin,
706 nm_vpn_plugin_failure (plugin, NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG);
711 /*********************************************************************/
714 sigterm_handler (int signum)
716 g_slist_foreach (active_plugins, (GFunc) nm_vpn_plugin_emit_quit, NULL);
720 setup_unix_signal_handler (void)
722 struct sigaction action;
725 action.sa_handler = sigterm_handler;
726 sigemptyset (&block_mask);
727 action.sa_mask = block_mask;
729 sigaction (SIGINT, &action, NULL);
730 sigaction (SIGTERM, &action, NULL);
733 /*********************************************************************/
736 one_plugin_destroyed (gpointer data,
739 active_plugins = g_slist_remove (active_plugins, object);
743 nm_vpn_plugin_init (NMVPNPlugin *plugin)
745 active_plugins = g_slist_append (active_plugins, plugin);
746 g_object_weak_ref (G_OBJECT (plugin),
747 one_plugin_destroyed,
752 constructor (GType type,
753 guint n_construct_params,
754 GObjectConstructParam *construct_params)
758 NMVPNPluginPrivate *priv;
759 DBusGConnection *connection;
761 guint request_name_result;
764 object = G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->constructor (type,
770 priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
771 if (!priv->dbus_service_name)
774 connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
778 proxy = dbus_g_proxy_new_for_name (connection,
781 DBUS_INTERFACE_DBUS);
783 if (!dbus_g_proxy_call (proxy, "RequestName", &err,
784 G_TYPE_STRING, priv->dbus_service_name,
787 G_TYPE_UINT, &request_name_result,
789 g_object_unref (proxy);
793 g_object_unref (proxy);
795 dbus_g_connection_register_g_object (connection,
796 NM_VPN_DBUS_PLUGIN_PATH,
799 plugin = NM_VPN_PLUGIN (object);
801 nm_vpn_plugin_set_connection (plugin, connection);
802 nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_INIT);
808 g_warning ("Failed to initialize VPN plugin: %s", err->message);
813 g_object_unref (object);
819 set_property (GObject *object, guint prop_id,
820 const GValue *value, GParamSpec *pspec)
822 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
825 case PROP_DBUS_SERVICE_NAME:
827 priv->dbus_service_name = g_strdup (g_value_get_string (value));
830 nm_vpn_plugin_set_state (NM_VPN_PLUGIN (object),
831 (NMVPNServiceState) g_value_get_uint (value));
834 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
840 get_property (GObject *object, guint prop_id,
841 GValue *value, GParamSpec *pspec)
843 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
846 case PROP_DBUS_SERVICE_NAME:
847 g_value_set_string (value, priv->dbus_service_name);
850 g_value_set_uint (value, nm_vpn_plugin_get_state (NM_VPN_PLUGIN (object)));
853 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
859 dispose (GObject *object)
861 NMVPNPlugin *plugin = NM_VPN_PLUGIN (object);
862 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
863 NMVPNServiceState state;
866 nm_clear_g_source (&priv->fail_stop_id);
867 nm_clear_g_source (&priv->quit_timer);
868 nm_clear_g_source (&priv->connect_timer);
870 state = nm_vpn_plugin_get_state (plugin);
872 if (state == NM_VPN_SERVICE_STATE_STARTED ||
873 state == NM_VPN_SERVICE_STATE_STARTING)
874 nm_vpn_plugin_disconnect (plugin, &err);
877 g_warning ("Error disconnecting VPN connection: %s", err->message);
881 G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->dispose (object);
885 finalize (GObject *object)
887 NMVPNPlugin *plugin = NM_VPN_PLUGIN (object);
888 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
890 nm_vpn_plugin_set_connection (plugin, NULL);
891 g_free (priv->dbus_service_name);
893 if (G_IS_VALUE (&priv->banner))
894 g_value_unset (&priv->banner);
895 if (G_IS_VALUE (&priv->tundev))
896 g_value_unset (&priv->tundev);
897 if (G_IS_VALUE (&priv->gateway))
898 g_value_unset (&priv->gateway);
899 if (G_IS_VALUE (&priv->mtu))
900 g_value_unset (&priv->mtu);
902 G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->finalize (object);
906 state_changed (NMVPNPlugin *plugin, NMVPNServiceState state)
908 NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
911 case NM_VPN_SERVICE_STATE_STARTING:
912 nm_clear_g_source (&priv->quit_timer);
913 nm_clear_g_source (&priv->fail_stop_id);
915 case NM_VPN_SERVICE_STATE_STOPPED:
916 schedule_quit_timer (plugin);
919 /* Clean up all timers we might have set up. */
920 nm_clear_g_source (&priv->connect_timer);
921 nm_clear_g_source (&priv->quit_timer);
922 nm_clear_g_source (&priv->fail_stop_id);
928 nm_vpn_plugin_class_init (NMVPNPluginClass *plugin_class)
930 GObjectClass *object_class = G_OBJECT_CLASS (plugin_class);
932 g_type_class_add_private (object_class, sizeof (NMVPNPluginPrivate));
934 dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (plugin_class),
935 &dbus_glib_nm_vpn_plugin_object_info);
937 /* virtual methods */
938 object_class->constructor = constructor;
939 object_class->set_property = set_property;
940 object_class->get_property = get_property;
941 object_class->dispose = dispose;
942 object_class->finalize = finalize;
944 plugin_class->state_changed = state_changed;
949 * NMVPNPlugin:service-name:
951 * The D-Bus service name of this plugin.
953 g_object_class_install_property
954 (object_class, PROP_DBUS_SERVICE_NAME,
955 g_param_spec_string (NM_VPN_PLUGIN_DBUS_SERVICE_NAME, "", "",
958 G_PARAM_CONSTRUCT_ONLY |
959 G_PARAM_STATIC_STRINGS));
964 * The state of the plugin.
966 g_object_class_install_property
967 (object_class, PROP_STATE,
968 g_param_spec_uint (NM_VPN_PLUGIN_STATE, "", "",
969 NM_VPN_SERVICE_STATE_UNKNOWN,
970 NM_VPN_SERVICE_STATE_STOPPED,
971 NM_VPN_SERVICE_STATE_INIT,
973 G_PARAM_STATIC_STRINGS));
976 signals[STATE_CHANGED] =
977 g_signal_new ("state-changed",
978 G_OBJECT_CLASS_TYPE (object_class),
980 G_STRUCT_OFFSET (NMVPNPluginClass, state_changed),
982 g_cclosure_marshal_VOID__UINT,
986 signals[SECRETS_REQUIRED] =
987 g_signal_new ("secrets-required",
988 G_OBJECT_CLASS_TYPE (object_class),
992 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRV);
995 g_signal_new ("config",
996 G_OBJECT_CLASS_TYPE (object_class),
998 G_STRUCT_OFFSET (NMVPNPluginClass, config),
1000 g_cclosure_marshal_VOID__BOXED,
1002 DBUS_TYPE_G_MAP_OF_VARIANT);
1004 signals[IP4_CONFIG] =
1005 g_signal_new ("ip4-config",
1006 G_OBJECT_CLASS_TYPE (object_class),
1008 G_STRUCT_OFFSET (NMVPNPluginClass, ip4_config),
1010 g_cclosure_marshal_VOID__BOXED,
1012 DBUS_TYPE_G_MAP_OF_VARIANT);
1014 signals[IP6_CONFIG] =
1015 g_signal_new ("ip6-config",
1016 G_OBJECT_CLASS_TYPE (object_class),
1018 G_STRUCT_OFFSET (NMVPNPluginClass, ip6_config),
1020 g_cclosure_marshal_VOID__BOXED,
1022 DBUS_TYPE_G_MAP_OF_VARIANT);
1024 signals[LOGIN_BANNER] =
1025 g_signal_new ("login-banner",
1026 G_OBJECT_CLASS_TYPE (object_class),
1028 G_STRUCT_OFFSET (NMVPNPluginClass, login_banner),
1030 g_cclosure_marshal_VOID__STRING,
1035 g_signal_new ("failure",
1036 G_OBJECT_CLASS_TYPE (object_class),
1038 G_STRUCT_OFFSET (NMVPNPluginClass, failure),
1040 g_cclosure_marshal_VOID__UINT,
1045 g_signal_new ("quit",
1046 G_OBJECT_CLASS_TYPE (object_class),
1048 G_STRUCT_OFFSET (NMVPNPluginClass, quit),
1050 g_cclosure_marshal_VOID__VOID,
1054 dbus_g_error_domain_register (NM_VPN_PLUGIN_ERROR,
1055 NM_DBUS_VPN_ERROR_PREFIX,
1056 NM_TYPE_VPN_PLUGIN_ERROR);
1058 setup_unix_signal_handler ();