libnm: accept invalid connections in NMVpnServicePlugin
[NetworkManager.git] / libnm / nm-vpn-plugin-old.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
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.
7  *
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.
12  *
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.
17  *
18  * Copyright 2007 - 2008 Novell, Inc.
19  * Copyright 2007 - 2008 Red Hat, Inc.
20  */
21
22 #include "nm-default.h"
23
24 #include "nm-vpn-plugin-old.h"
25
26 #include <errno.h>
27 #include <signal.h>
28 #include <stdlib.h>
29
30 #include "nm-enum-types.h"
31 #include "nm-utils.h"
32 #include "nm-connection.h"
33 #include "nm-dbus-helpers.h"
34 #include "nm-core-internal.h"
35 #include "nm-simple-connection.h"
36
37 #include "nmdbus-vpn-plugin.h"
38
39 #define NM_VPN_PLUGIN_OLD_QUIT_TIMER    180
40
41 static void nm_vpn_plugin_old_initable_iface_init (GInitableIface *iface);
42
43 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMVpnPluginOld, nm_vpn_plugin_old, G_TYPE_OBJECT,
44                                   G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_vpn_plugin_old_initable_iface_init);
45                                   )
46
47 typedef struct {
48         NMVpnServiceState state;
49
50         /* DBUS-y stuff */
51         GDBusConnection *connection;
52         NMDBusVpnPlugin *dbus_vpn_plugin_old;
53         char *dbus_service_name;
54
55         /* Temporary stuff */
56         guint connect_timer;
57         guint quit_timer;
58         guint fail_stop_id;
59         gboolean interactive;
60
61         gboolean got_config;
62         gboolean has_ip4, got_ip4;
63         gboolean has_ip6, got_ip6;
64
65         /* Config stuff copied from config to ip4config */
66         GVariant *banner, *tundev, *gateway, *mtu;
67 } NMVpnPluginOldPrivate;
68
69 #define NM_VPN_PLUGIN_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN_OLD, NMVpnPluginOldPrivate))
70
71 enum {
72         STATE_CHANGED,
73         CONFIG,
74         IP4_CONFIG,
75         IP6_CONFIG,
76         LOGIN_BANNER,
77         FAILURE,
78         QUIT,
79         SECRETS_REQUIRED,
80
81         LAST_SIGNAL
82 };
83
84 static guint signals[LAST_SIGNAL] = { 0 };
85
86 enum {
87         PROP_0,
88         PROP_DBUS_SERVICE_NAME,
89         PROP_STATE,
90
91         LAST_PROP
92 };
93
94 static GSList *active_plugins = NULL;
95
96
97 static void
98 nm_vpn_plugin_old_set_connection (NMVpnPluginOld *plugin,
99                                   GDBusConnection *connection)
100 {
101         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
102
103         g_clear_object (&priv->connection);
104
105         if (connection)
106                 priv->connection = g_object_ref (connection);
107 }
108
109 /**
110  * nm_vpn_plugin_old_get_connection:
111  *
112  * Returns: (transfer full):
113  *
114  * Deprecated: 1.2: replaced by NMVpnServicePlugin
115  */
116 GDBusConnection *
117 nm_vpn_plugin_old_get_connection (NMVpnPluginOld *plugin)
118 {
119         GDBusConnection *connection;
120
121         g_return_val_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin), NULL);
122
123         connection = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin)->connection;
124
125         if (connection)
126                 g_object_ref (connection);
127
128         return connection;
129 }
130
131 /**
132  * nm_vpn_plugin_old_get_state:
133  *
134  * Deprecated: 1.2: replaced by NMVpnServicePlugin
135  */
136 NMVpnServiceState
137 nm_vpn_plugin_old_get_state (NMVpnPluginOld *plugin)
138 {
139         g_return_val_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin), NM_VPN_SERVICE_STATE_UNKNOWN);
140
141         return NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin)->state;
142 }
143
144 /**
145  * nm_vpn_plugin_old_set_state:
146  *
147  * Deprecated: 1.2: replaced by NMVpnServicePlugin
148  */
149 void
150 nm_vpn_plugin_old_set_state (NMVpnPluginOld *plugin,
151                              NMVpnServiceState state)
152 {
153         NMVpnPluginOldPrivate *priv;
154
155         g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin));
156
157         priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
158         if (priv->state != state) {
159                 priv->state = state;
160                 g_signal_emit (plugin, signals[STATE_CHANGED], 0, state);
161         }
162 }
163
164 /**
165  * nm_vpn_plugin_old_set_login_banner:
166  *
167  * Deprecated: 1.2: replaced by NMVpnServicePlugin
168  */
169 void
170 nm_vpn_plugin_old_set_login_banner (NMVpnPluginOld *plugin,
171                                     const char *banner)
172 {
173         g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin));
174         g_return_if_fail (banner != NULL);
175
176         g_signal_emit (plugin, signals[LOGIN_BANNER], 0, banner);
177 }
178
179 /**
180  * nm_vpn_plugin_old_failure:
181  *
182  * Deprecated: 1.2: replaced by NMVpnServicePlugin
183  */
184 void
185 nm_vpn_plugin_old_failure (NMVpnPluginOld *plugin,
186                            NMVpnPluginFailure reason)
187 {
188         g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin));
189
190         g_signal_emit (plugin, signals[FAILURE], 0, reason);
191 }
192
193 /**
194  * nm_vpn_plugin_old_disconnect:
195  *
196  * Deprecated: 1.2: replaced by NMVpnServicePlugin
197  */
198 gboolean
199 nm_vpn_plugin_old_disconnect (NMVpnPluginOld *plugin, GError **err)
200 {
201         gboolean ret = FALSE;
202         NMVpnServiceState state;
203
204         g_return_val_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin), FALSE);
205
206         state = nm_vpn_plugin_old_get_state (plugin);
207         switch (state) {
208         case NM_VPN_SERVICE_STATE_STOPPING:
209                 g_set_error (err,
210                              NM_VPN_PLUGIN_ERROR,
211                              NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
212                              "%s",
213                              "Could not process the request because the VPN connection is already being stopped.");
214                 break;
215         case NM_VPN_SERVICE_STATE_STOPPED:
216                 g_set_error (err,
217                              NM_VPN_PLUGIN_ERROR,
218                              NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,
219                              "%s",
220                              "Could not process the request because no VPN connection was active.");
221                 break;
222         case NM_VPN_SERVICE_STATE_STARTING:
223         case NM_VPN_SERVICE_STATE_STARTED:
224                 nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPING);
225                 ret = NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->disconnect (plugin, err);
226                 nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED);
227                 break;
228         case NM_VPN_SERVICE_STATE_INIT:
229                 ret = TRUE;
230                 break;
231
232         default:
233                 g_warning ("Unhandled VPN service state %d", state);
234                 g_assert_not_reached ();
235                 break;
236         }
237
238         return ret;
239 }
240
241 static void
242 nm_vpn_plugin_old_emit_quit (NMVpnPluginOld *plugin)
243 {
244         g_signal_emit (plugin, signals[QUIT], 0);
245 }
246
247 static gboolean
248 connect_timer_expired (gpointer data)
249 {
250         NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (data);
251         GError *err = NULL;
252
253         NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin)->connect_timer = 0;
254         g_message ("Connect timer expired, disconnecting.");
255         nm_vpn_plugin_old_disconnect (plugin, &err);
256         if (err) {
257                 g_warning ("Disconnect failed: %s", err->message);
258                 g_error_free (err);
259         }
260
261         return G_SOURCE_REMOVE;
262 }
263
264 static gboolean
265 quit_timer_expired (gpointer data)
266 {
267         NMVpnPluginOld *self = NM_VPN_PLUGIN_OLD (data);
268
269         NM_VPN_PLUGIN_OLD_GET_PRIVATE (self)->quit_timer = 0;
270         nm_vpn_plugin_old_emit_quit (self);
271         return G_SOURCE_REMOVE;
272 }
273
274 static void
275 schedule_quit_timer (NMVpnPluginOld *self)
276 {
277         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (self);
278
279         nm_clear_g_source (&priv->quit_timer);
280         priv->quit_timer = g_timeout_add_seconds (NM_VPN_PLUGIN_OLD_QUIT_TIMER,
281                                                   quit_timer_expired,
282                                                   self);
283 }
284
285 static gboolean
286 fail_stop (gpointer data)
287 {
288         NMVpnPluginOld *self = NM_VPN_PLUGIN_OLD (data);
289
290         NM_VPN_PLUGIN_OLD_GET_PRIVATE (self)->fail_stop_id = 0;
291         nm_vpn_plugin_old_set_state (self, NM_VPN_SERVICE_STATE_STOPPED);
292         return G_SOURCE_REMOVE;
293 }
294
295 static void
296 schedule_fail_stop (NMVpnPluginOld *plugin, guint timeout_secs)
297 {
298         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
299
300         nm_clear_g_source (&priv->fail_stop_id);
301         if (timeout_secs)
302                 priv->fail_stop_id = g_timeout_add_seconds (timeout_secs, fail_stop, plugin);
303         else
304                 priv->fail_stop_id = g_idle_add (fail_stop, plugin);
305 }
306
307 /**
308  * nm_vpn_plugin_old_set_config:
309  *
310  * Deprecated: 1.2: replaced by NMVpnServicePlugin
311  */
312 void
313 nm_vpn_plugin_old_set_config (NMVpnPluginOld *plugin,
314                               GVariant *config)
315 {
316         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
317
318         g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin));
319         g_return_if_fail (config != NULL);
320
321         priv->got_config = TRUE;
322
323         (void) g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP4, "b", &priv->has_ip4);
324         (void) g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP6, "b", &priv->has_ip6);
325
326         g_warn_if_fail (priv->has_ip4 || priv->has_ip6);
327
328         /* Record the items that need to also be inserted into the
329          * ip4config, for compatibility with older daemons.
330          */
331         if (priv->banner)
332                 g_variant_unref (priv->banner);
333         priv->banner = g_variant_lookup_value (config, NM_VPN_PLUGIN_CONFIG_BANNER,
334                                                G_VARIANT_TYPE ("s"));
335         if (priv->tundev)
336                 g_variant_unref (priv->tundev);
337         priv->tundev = g_variant_lookup_value (config, NM_VPN_PLUGIN_CONFIG_TUNDEV,
338                                                G_VARIANT_TYPE ("s"));
339         if (priv->gateway)
340                 g_variant_unref (priv->gateway);
341         priv->gateway = g_variant_lookup_value (config, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY,
342                                                 G_VARIANT_TYPE ("u"));
343         if (priv->mtu)
344                 g_variant_unref (priv->mtu);
345         priv->mtu = g_variant_lookup_value (config, NM_VPN_PLUGIN_CONFIG_MTU,
346                                             G_VARIANT_TYPE ("u"));
347
348         g_signal_emit (plugin, signals[CONFIG], 0, config);
349 }
350
351 /**
352  * nm_vpn_plugin_old_set_ip4_config:
353  *
354  * Deprecated: 1.2: replaced by NMVpnServicePlugin
355  */
356 void
357 nm_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin,
358                                   GVariant *ip4_config)
359 {
360         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
361         GVariant *combined_config;
362         GVariantBuilder builder;
363         GVariantIter iter;
364         const char *key;
365         GVariant *value;
366
367         g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin));
368         g_return_if_fail (ip4_config != NULL);
369
370         priv->got_ip4 = TRUE;
371
372         /* Old plugins won't send the "config" signal and thus can't send
373          * NM_VPN_PLUGIN_OLD_CONFIG_HAS_IP4 either.  But since they don't support IPv6,
374          * we can safely assume that, if we don't receive a "config" signal but do
375          * receive an "ip4-config" signal, the old plugin supports IPv4.
376          */
377         if (!priv->got_config)
378                 priv->has_ip4 = TRUE;
379
380         /* Older NetworkManager daemons expect all config info to be in
381          * the ip4 config, so they won't even notice the "config" signal
382          * being emitted. So just copy all of that data into the ip4
383          * config too.
384          */
385         g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
386         g_variant_iter_init (&iter, ip4_config);
387         while (g_variant_iter_next (&iter, "{&sv}", &key, &value)) {
388                 g_variant_builder_add (&builder, "{sv}", key, value);
389                 g_variant_unref (value);
390         }
391
392         if (priv->banner)
393                 g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_BANNER, &priv->banner);
394         if (priv->tundev)
395                 g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, &priv->tundev);
396         if (priv->gateway)
397                 g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, &priv->gateway);
398         if (priv->mtu)
399                 g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_MTU, &priv->mtu);
400
401         combined_config = g_variant_builder_end (&builder);
402         g_variant_ref_sink (combined_config);
403         g_signal_emit (plugin, signals[IP4_CONFIG], 0, combined_config);
404         g_variant_unref (combined_config);
405
406         if (   priv->has_ip4 == priv->got_ip4
407             && priv->has_ip6 == priv->got_ip6)
408                 nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
409 }
410
411 /**
412  * nm_vpn_plugin_old_set_ip6_config:
413  *
414  * Deprecated: 1.2: replaced by NMVpnServicePlugin
415  */
416 void
417 nm_vpn_plugin_old_set_ip6_config (NMVpnPluginOld *plugin,
418                                   GVariant *ip6_config)
419 {
420         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
421
422         g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin));
423         g_return_if_fail (ip6_config != NULL);
424
425         g_variant_ref_sink (ip6_config);
426
427         priv->got_ip6 = TRUE;
428         g_signal_emit (plugin, signals[IP6_CONFIG], 0, ip6_config);
429
430         g_variant_unref (ip6_config);
431
432         if (   priv->has_ip4 == priv->got_ip4
433             && priv->has_ip6 == priv->got_ip6)
434                 nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
435 }
436
437 static void
438 connect_timer_start (NMVpnPluginOld *plugin)
439 {
440         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
441
442         priv->connect_timer = g_timeout_add_seconds (60, connect_timer_expired, plugin);
443 }
444
445 static void
446 _connect_generic (NMVpnPluginOld *plugin,
447                   GDBusMethodInvocation *context,
448                   GVariant *properties,
449                   GVariant *details)
450 {
451         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
452         NMVpnPluginOldClass *vpn_class = NM_VPN_PLUGIN_OLD_GET_CLASS (plugin);
453         NMConnection *connection;
454         gboolean success = FALSE;
455         GError *error = NULL;
456         guint fail_stop_timeout = 0;
457
458         if (priv->state != NM_VPN_SERVICE_STATE_STOPPED &&
459             priv->state != NM_VPN_SERVICE_STATE_INIT) {
460                 g_dbus_method_invocation_return_error (context,
461                                                        NM_VPN_PLUGIN_ERROR,
462                                                        NM_VPN_PLUGIN_ERROR_WRONG_STATE,
463                                                        "Could not start connection: wrong plugin state %d",
464                                                        priv->state);
465                 return;
466         }
467
468         connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error);
469         if (!connection) {
470                 g_dbus_method_invocation_return_error (context,
471                                                        NM_VPN_PLUGIN_ERROR,
472                                                        NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
473                                                        "Invalid connection: %s",
474                                                        error->message);
475                 g_clear_error (&error);
476         }
477
478         priv->interactive = FALSE;
479         if (details && !vpn_class->connect_interactive) {
480                 g_dbus_method_invocation_return_error (context,
481                                                        NM_VPN_PLUGIN_ERROR,
482                                                        NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED,
483                                                        "Plugin does not implement ConnectInteractive()");
484                 return;
485         }
486
487         nm_clear_g_source (&priv->fail_stop_id);
488
489         if (details) {
490                 priv->interactive = TRUE;
491                 success = vpn_class->connect_interactive (plugin, connection, details, &error);
492                 if (g_error_matches (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED)) {
493                         /* Give NetworkManager a bit of time to fall back to Connect() */
494                         fail_stop_timeout = 5;
495                 }
496         } else
497                 success = vpn_class->connect (plugin, connection, &error);
498
499         if (success) {
500                 nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING);
501
502                 g_dbus_method_invocation_return_value (context, NULL);
503
504                 /* Add a timer to make sure we do not wait indefinitely for the successful connect. */
505                 connect_timer_start (plugin);
506         } else {
507                 g_dbus_method_invocation_take_error (context, error);
508
509                 /* Stop the plugin from an idle handler so that the Connect
510                  * method return gets sent before the STOP StateChanged signal.
511                  */
512                 schedule_fail_stop (plugin, fail_stop_timeout);
513         }
514
515         g_object_unref (connection);
516 }
517
518 static void
519 impl_vpn_plugin_old_connect (NMVpnPluginOld *plugin,
520                              GDBusMethodInvocation *context,
521                              GVariant *connection,
522                              gpointer user_data)
523 {
524         _connect_generic (plugin, context, connection, NULL);
525 }
526
527 static void
528 impl_vpn_plugin_old_connect_interactive (NMVpnPluginOld *plugin,
529                                          GDBusMethodInvocation *context,
530                                          GVariant *connection,
531                                          GVariant *details,
532                                          gpointer user_data)
533 {
534         _connect_generic (plugin, context, connection, details);
535 }
536
537 /***************************************************************/
538
539 static void
540 impl_vpn_plugin_old_need_secrets (NMVpnPluginOld *plugin,
541                                   GDBusMethodInvocation *context,
542                                   GVariant *properties,
543                                   gpointer user_data)
544 {
545         NMConnection *connection;
546         const char *setting_name;
547         gboolean needed;
548         GError *error = NULL;
549
550         connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error);
551         if (!connection) {
552                 g_dbus_method_invocation_return_error (context,
553                                                        NM_VPN_PLUGIN_ERROR,
554                                                        NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION,
555                                                        "The connection was invalid: %s",
556                                                        error->message);
557                 g_error_free (error);
558                 return;
559         }
560
561         if (!NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->need_secrets) {
562                 g_dbus_method_invocation_return_value (context,
563                                                        g_variant_new ("(s)", ""));
564                 return;
565         }
566
567         needed = NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->need_secrets (plugin, connection, &setting_name, &error);
568         if (error) {
569                 g_dbus_method_invocation_take_error (context, error);
570                 return;
571         }
572
573         if (needed) {
574                 /* Push back the quit timer so the VPN plugin doesn't quit in the
575                  * middle of asking the user for secrets.
576                  */
577                 schedule_quit_timer (plugin);
578
579                 g_assert (setting_name);
580                 g_dbus_method_invocation_return_value (context,
581                                                        g_variant_new ("(s)", setting_name));
582         } else {
583                 /* No secrets required */
584                 g_dbus_method_invocation_return_value (context,
585                                                        g_variant_new ("(s)", ""));
586         }
587 }
588
589 static void
590 impl_vpn_plugin_old_new_secrets (NMVpnPluginOld *plugin,
591                                  GDBusMethodInvocation *context,
592                                  GVariant *properties,
593                                  gpointer user_data)
594 {
595         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
596         NMConnection *connection;
597         GError *error = NULL;
598         gboolean success;
599
600         if (priv->state != NM_VPN_SERVICE_STATE_STARTING) {
601                 g_dbus_method_invocation_return_error (context,
602                                                        NM_VPN_PLUGIN_ERROR,
603                                                        NM_VPN_PLUGIN_ERROR_WRONG_STATE,
604                                                        "Could not accept new secrets: wrong plugin state %d",
605                                                        priv->state);
606                 return;
607         }
608
609         connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error);
610         if (!connection) {
611                 g_dbus_method_invocation_return_error (context,
612                                                        NM_VPN_PLUGIN_ERROR,
613                                                        NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
614                                                        "Invalid connection: %s",
615                                                        error->message);
616                 g_clear_error (&error);
617                 return;
618         }
619
620         if (!NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->new_secrets) {
621                 g_dbus_method_invocation_return_error (context,
622                                                        NM_VPN_PLUGIN_ERROR,
623                                                        NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED,
624                                                        "Could not accept new secrets: plugin cannot process interactive secrets");
625                 g_object_unref (connection);
626                 return;
627         }
628
629         success = NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->new_secrets (plugin, connection, &error);
630         if (success) {
631                 g_dbus_method_invocation_return_value (context, NULL);
632
633                 /* Add a timer to make sure we do not wait indefinitely for the successful connect. */
634                 connect_timer_start (plugin);
635         } else {
636                 g_dbus_method_invocation_take_error (context, error);
637
638                 /* Stop the plugin from and idle handler so that the NewSecrets
639                  * method return gets sent before the STOP StateChanged signal.
640                  */
641                 schedule_fail_stop (plugin, 0);
642         }
643
644         g_object_unref (connection);
645 }
646
647 /**
648  * nm_vpn_plugin_old_secrets_required:
649  * @plugin: the #NMVpnPluginOld
650  * @message: an information message about why secrets are required, if any
651  * @hints: VPN specific secret names for required new secrets
652  *
653  * Called by VPN plugin implementations to signal to NetworkManager that secrets
654  * are required during the connection process.  This signal may be used to
655  * request new secrets when the secrets originally provided by NetworkManager
656  * are insufficient, or the VPN process indicates that it needs additional
657  * information to complete the request.
658  *
659  * Deprecated: 1.2: replaced by NMVpnServicePlugin
660  */
661 void
662 nm_vpn_plugin_old_secrets_required (NMVpnPluginOld *plugin,
663                                     const char *message,
664                                     const char **hints)
665 {
666         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
667
668         /* Plugin must be able to accept the new secrets if it calls this method */
669         g_return_if_fail (NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->new_secrets);
670
671         /* Plugin cannot call this method if NetworkManager didn't originally call
672          * ConnectInteractive().
673          */
674         g_return_if_fail (priv->interactive == TRUE);
675
676         /* Cancel the connect timer since secrets might take a while.  It'll
677          * get restarted when the secrets come back via NewSecrets().
678          */
679         nm_clear_g_source (&priv->connect_timer);
680
681         g_signal_emit (plugin, signals[SECRETS_REQUIRED], 0, message, hints);
682 }
683
684 /***************************************************************/
685
686 #define DATA_KEY_TAG "DATA_KEY="
687 #define DATA_VAL_TAG "DATA_VAL="
688 #define SECRET_KEY_TAG "SECRET_KEY="
689 #define SECRET_VAL_TAG "SECRET_VAL="
690
691 static void
692 free_secret (gpointer data)
693 {
694         char *secret = data;
695
696         memset (secret, 0, strlen (secret));
697         g_free (secret);
698 }
699
700 /**
701  * nm_vpn_plugin_old_read_vpn_details:
702  * @fd: file descriptor to read from, usually stdin (0)
703  * @out_data: (out) (transfer full): on successful return, a hash table
704  * (mapping char*:char*) containing the key/value pairs of VPN data items
705  * @out_secrets: (out) (transfer full): on successful return, a hash table
706  * (mapping char*:char*) containing the key/value pairsof VPN secrets
707  *
708  * Parses key/value pairs from a file descriptor (normally stdin) passed by
709  * an applet when the applet calls the authentication dialog of the VPN plugin.
710  *
711  * Returns: %TRUE if reading values was successful, %FALSE if not
712  *
713  * Deprecated: 1.2: replaced by NMVpnServicePlugin
714  **/
715 gboolean
716 nm_vpn_plugin_old_read_vpn_details (int fd,
717                                     GHashTable **out_data,
718                                     GHashTable **out_secrets)
719 {
720         GHashTable *data, *secrets;
721         gboolean success = FALSE;
722         char *key = NULL, *val = NULL;
723         GString *line;
724         gchar c;
725
726         if (out_data)
727                 g_return_val_if_fail (*out_data == NULL, FALSE);
728         if (out_secrets)
729                 g_return_val_if_fail (*out_secrets == NULL, FALSE);
730
731         data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
732         secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_secret);
733
734         line = g_string_new (NULL);
735
736         /* Read stdin for data and secret items until we get a DONE */
737         while (1) {
738                 ssize_t nr;
739                 GHashTable *hash = NULL;
740
741                 errno = 0;
742                 nr = read (fd, &c, 1);
743                 if (nr == -1) {
744                         if (errno == EAGAIN) {
745                                 g_usleep (100);
746                                 continue;
747                         }
748                         break;
749                 }
750
751                 if (c != '\n') {
752                         g_string_append_c (line, c);
753                         continue;
754                 }
755
756                 /* Check for the finish marker */
757                 if (strcmp (line->str, "DONE") == 0)
758                         break;
759
760                 /* Otherwise it's a data/secret item */
761                 if (strncmp (line->str, DATA_KEY_TAG, strlen (DATA_KEY_TAG)) == 0) {
762                         hash = data;
763                         key = g_strdup (line->str + strlen (DATA_KEY_TAG));
764                 } else if (strncmp (line->str, DATA_VAL_TAG, strlen (DATA_VAL_TAG)) == 0) {
765                         hash = data;
766                         val = g_strdup (line->str + strlen (DATA_VAL_TAG));
767                 } else if (strncmp (line->str, SECRET_KEY_TAG, strlen (SECRET_KEY_TAG)) == 0) {
768                         hash = secrets;
769                         key = g_strdup (line->str + strlen (SECRET_KEY_TAG));
770                 } else if (strncmp (line->str, SECRET_VAL_TAG, strlen (SECRET_VAL_TAG)) == 0) {
771                         hash = secrets;
772                         val = g_strdup (line->str + strlen (SECRET_VAL_TAG));
773                 }
774                 g_string_truncate (line, 0);
775
776                 if (key && val && hash) {
777                         g_hash_table_insert (hash, key, val);
778                         key = NULL;
779                         val = NULL;
780                         success = TRUE;  /* Got at least one value */
781                 }
782         }
783
784         if (success) {
785                 if (out_data)
786                         *out_data = data;
787                 else
788                         g_hash_table_destroy (data);
789
790                 if (out_secrets)
791                         *out_secrets = secrets;
792                 else
793                         g_hash_table_destroy (secrets);
794         } else {
795                 g_hash_table_destroy (data);
796                 g_hash_table_destroy (secrets);
797         }
798
799         g_string_free (line, TRUE);
800         return success;
801 }
802
803 /**
804  * nm_vpn_plugin_old_get_secret_flags:
805  * @data: hash table containing VPN key/value pair data items
806  * @secret_name: VPN secret key name for which to retrieve flags for
807  * @out_flags: (out): on success, the flags associated with @secret_name
808  *
809  * Given a VPN secret key name, attempts to find the corresponding flags data
810  * item in @data.  If found, converts the flags data item to
811  * #NMSettingSecretFlags and returns it.
812  *
813  * Returns: %TRUE if the flag data item was found and successfully converted
814  * to flags, %FALSE if not
815  *
816  * Deprecated: 1.2: replaced by NMVpnServicePlugin
817  **/
818 gboolean
819 nm_vpn_plugin_old_get_secret_flags (GHashTable *data,
820                                     const char *secret_name,
821                                     NMSettingSecretFlags *out_flags)
822 {
823         char *flag_name;
824         const char *val;
825         unsigned long tmp;
826         gboolean success = FALSE;
827
828         g_return_val_if_fail (data != NULL, FALSE);
829         g_return_val_if_fail (secret_name != NULL, FALSE);
830         g_return_val_if_fail (out_flags != NULL, FALSE);
831         g_return_val_if_fail (*out_flags == NM_SETTING_SECRET_FLAG_NONE, FALSE);
832
833         flag_name = g_strdup_printf ("%s-flags", secret_name);
834
835         /* Try new flags value first */
836         val = g_hash_table_lookup (data, flag_name);
837         if (val) {
838                 errno = 0;
839                 tmp = strtoul (val, NULL, 10);
840                 if (errno == 0 && tmp <= NM_SETTING_SECRET_FLAGS_ALL) {
841                         *out_flags = (NMSettingSecretFlags) tmp;
842                         success = TRUE;
843                 }
844         }
845
846         g_free (flag_name);
847         return success;
848 }
849
850 /***************************************************************/
851
852 static void
853 impl_vpn_plugin_old_disconnect (NMVpnPluginOld *plugin,
854                                 GDBusMethodInvocation *context,
855                                 gpointer user_data)
856 {
857         GError *error = NULL;
858
859         if (nm_vpn_plugin_old_disconnect (plugin, &error))
860                 g_dbus_method_invocation_return_value (context, NULL);
861         else
862                 g_dbus_method_invocation_take_error (context, error);
863 }
864
865 static void
866 impl_vpn_plugin_old_set_config (NMVpnPluginOld *plugin,
867                                 GDBusMethodInvocation *context,
868                                 GVariant *config,
869                                 gpointer user_data)
870 {
871         nm_vpn_plugin_old_set_config (plugin, config);
872         g_dbus_method_invocation_return_value (context, NULL);
873 }
874
875 static void
876 impl_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin,
877                                     GDBusMethodInvocation *context,
878                                     GVariant *config,
879                                     gpointer user_data)
880 {
881         nm_vpn_plugin_old_set_ip4_config (plugin, config);
882         g_dbus_method_invocation_return_value (context, NULL);
883 }
884
885 static void
886 impl_vpn_plugin_old_set_ip6_config (NMVpnPluginOld *plugin,
887                                     GDBusMethodInvocation *context,
888                                     GVariant *config,
889                                     gpointer user_data)
890 {
891         nm_vpn_plugin_old_set_ip6_config (plugin, config);
892         g_dbus_method_invocation_return_value (context, NULL);
893 }
894
895 static void
896 impl_vpn_plugin_old_set_failure (NMVpnPluginOld *plugin,
897                                  GDBusMethodInvocation *context,
898                                  char *reason,
899                                  gpointer user_data)
900 {
901         nm_vpn_plugin_old_failure (plugin, NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG);
902         g_dbus_method_invocation_return_value (context, NULL);
903 }
904
905 /*********************************************************************/
906
907 static void
908 sigterm_handler (int signum)
909 {
910         g_slist_foreach (active_plugins, (GFunc) nm_vpn_plugin_old_emit_quit, NULL);
911 }
912
913 static void
914 setup_unix_signal_handler (void)
915 {
916         struct sigaction action;
917         sigset_t block_mask;
918
919         action.sa_handler = sigterm_handler;
920         sigemptyset (&block_mask);
921         action.sa_mask = block_mask;
922         action.sa_flags = 0;
923         sigaction (SIGINT, &action, NULL);
924         sigaction (SIGTERM, &action, NULL);
925 }
926
927 /*********************************************************************/
928
929 static void
930 one_plugin_destroyed (gpointer data,
931                       GObject *object)
932 {
933         active_plugins = g_slist_remove (active_plugins, object);
934 }
935
936 static void
937 nm_vpn_plugin_old_init (NMVpnPluginOld *plugin)
938 {
939         active_plugins = g_slist_append (active_plugins, plugin);
940         g_object_weak_ref (G_OBJECT (plugin),
941                            one_plugin_destroyed,
942                            NULL);
943 }
944
945 static gboolean
946 init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
947 {
948         NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (initable);
949         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
950         GDBusConnection *connection = NULL;
951         GDBusProxy *proxy;
952         GVariant *ret;
953         gboolean success = FALSE;
954
955         if (!priv->dbus_service_name) {
956                 g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
957                                      _("No service name specified"));
958                 return FALSE;
959         }
960
961         connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
962         if (!connection)
963                 return FALSE;
964
965         proxy = g_dbus_proxy_new_sync (connection,
966                                        G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
967                                        G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
968                                        NULL,
969                                        DBUS_SERVICE_DBUS,
970                                        DBUS_PATH_DBUS,
971                                        DBUS_INTERFACE_DBUS,
972                                        cancellable, error);
973         if (!proxy)
974                 goto out;
975
976         ret = g_dbus_proxy_call_sync (proxy,
977                                       "RequestName",
978                                       g_variant_new ("(su)", priv->dbus_service_name, 0),
979                                       G_DBUS_CALL_FLAGS_NONE, -1,
980                                       cancellable, error);
981         g_object_unref (proxy);
982         if (!ret) {
983                 if (error && *error)
984                         g_dbus_error_strip_remote_error (*error);
985                 goto out;
986         }
987         g_variant_unref (ret);
988
989         priv->dbus_vpn_plugin_old = nmdbus_vpn_plugin_skeleton_new ();
990         if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_vpn_plugin_old),
991                                                connection,
992                                                NM_VPN_DBUS_PLUGIN_PATH,
993                                                error))
994                 goto out;
995
996         _nm_dbus_bind_properties (plugin, priv->dbus_vpn_plugin_old);
997         _nm_dbus_bind_methods (plugin, priv->dbus_vpn_plugin_old,
998                                "Connect", impl_vpn_plugin_old_connect,
999                                "ConnectInteractive", impl_vpn_plugin_old_connect_interactive,
1000                                "NeedSecrets", impl_vpn_plugin_old_need_secrets,
1001                                "NewSecrets", impl_vpn_plugin_old_new_secrets,
1002                                "Disconnect", impl_vpn_plugin_old_disconnect,
1003                                "SetConfig", impl_vpn_plugin_old_set_config,
1004                                "SetIp4Config", impl_vpn_plugin_old_set_ip4_config,
1005                                "SetIp6Config", impl_vpn_plugin_old_set_ip6_config,
1006                                "SetFailure", impl_vpn_plugin_old_set_failure,
1007                                NULL);
1008
1009         nm_vpn_plugin_old_set_connection (plugin, connection);
1010         nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_INIT);
1011
1012         success = TRUE;
1013
1014  out:
1015         g_clear_object (&connection);
1016
1017         return success;
1018 }
1019
1020 static void
1021 set_property (GObject *object, guint prop_id,
1022               const GValue *value, GParamSpec *pspec)
1023 {
1024         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (object);
1025
1026         switch (prop_id) {
1027         case PROP_DBUS_SERVICE_NAME:
1028                 /* Construct-only */
1029                 priv->dbus_service_name = g_value_dup_string (value);
1030                 break;
1031         case PROP_STATE:
1032                 nm_vpn_plugin_old_set_state (NM_VPN_PLUGIN_OLD (object),
1033                                              (NMVpnServiceState) g_value_get_enum (value));
1034                 break;
1035         default:
1036                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1037                 break;
1038         }
1039 }
1040
1041 static void
1042 get_property (GObject *object, guint prop_id,
1043               GValue *value, GParamSpec *pspec)
1044 {
1045         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (object);
1046
1047         switch (prop_id) {
1048         case PROP_DBUS_SERVICE_NAME:
1049                 g_value_set_string (value, priv->dbus_service_name);
1050                 break;
1051         case PROP_STATE:
1052                 g_value_set_enum (value, nm_vpn_plugin_old_get_state (NM_VPN_PLUGIN_OLD (object)));
1053                 break;
1054         default:
1055                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1056                 break;
1057         }
1058 }
1059
1060 static void
1061 dispose (GObject *object)
1062 {
1063         NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (object);
1064         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
1065         NMVpnServiceState state;
1066         GError *err = NULL;
1067
1068         nm_clear_g_source (&priv->fail_stop_id);
1069         nm_clear_g_source (&priv->quit_timer);
1070         nm_clear_g_source (&priv->connect_timer);
1071
1072         state = nm_vpn_plugin_old_get_state (plugin);
1073
1074         if (state == NM_VPN_SERVICE_STATE_STARTED ||
1075             state == NM_VPN_SERVICE_STATE_STARTING)
1076                 nm_vpn_plugin_old_disconnect (plugin, &err);
1077
1078         if (err) {
1079                 g_warning ("Error disconnecting VPN connection: %s", err->message);
1080                 g_error_free (err);
1081         }
1082
1083         G_OBJECT_CLASS (nm_vpn_plugin_old_parent_class)->dispose (object);
1084 }
1085
1086 static void
1087 finalize (GObject *object)
1088 {
1089         NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (object);
1090         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
1091
1092         nm_vpn_plugin_old_set_connection (plugin, NULL);
1093         g_free (priv->dbus_service_name);
1094
1095         g_clear_pointer (&priv->banner, g_variant_unref);
1096         g_clear_pointer (&priv->tundev, g_variant_unref);
1097         g_clear_pointer (&priv->gateway, g_variant_unref);
1098         g_clear_pointer (&priv->mtu, g_variant_unref);
1099
1100         G_OBJECT_CLASS (nm_vpn_plugin_old_parent_class)->finalize (object);
1101 }
1102
1103 static void
1104 state_changed (NMVpnPluginOld *plugin, NMVpnServiceState state)
1105 {
1106         NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin);
1107
1108         switch (state) {
1109         case NM_VPN_SERVICE_STATE_STARTING:
1110                 nm_clear_g_source (&priv->quit_timer);
1111                 nm_clear_g_source (&priv->fail_stop_id);
1112                 break;
1113         case NM_VPN_SERVICE_STATE_STOPPED:
1114                 schedule_quit_timer (plugin);
1115                 break;
1116         default:
1117                 /* Clean up all timers we might have set up. */
1118                 nm_clear_g_source (&priv->connect_timer);
1119                 nm_clear_g_source (&priv->quit_timer);
1120                 nm_clear_g_source (&priv->fail_stop_id);
1121                 break;
1122         }
1123 }
1124
1125 static void
1126 nm_vpn_plugin_old_class_init (NMVpnPluginOldClass *plugin_class)
1127 {
1128         GObjectClass *object_class = G_OBJECT_CLASS (plugin_class);
1129
1130         g_type_class_add_private (object_class, sizeof (NMVpnPluginOldPrivate));
1131
1132         /* virtual methods */
1133         object_class->set_property = set_property;
1134         object_class->get_property = get_property;
1135         object_class->dispose      = dispose;
1136         object_class->finalize     = finalize;
1137
1138         plugin_class->state_changed = state_changed;
1139
1140         /* properties */
1141
1142         /**
1143          * NMVpnPluginOld:service-name:
1144          *
1145          * The D-Bus service name of this plugin.
1146          *
1147          * Deprecated: 1.2: replaced by NMVpnServicePlugin
1148          */
1149         g_object_class_install_property
1150                 (object_class, PROP_DBUS_SERVICE_NAME,
1151                  g_param_spec_string (NM_VPN_PLUGIN_OLD_DBUS_SERVICE_NAME, "", "",
1152                                       NULL,
1153                                       G_PARAM_READWRITE |
1154                                       G_PARAM_CONSTRUCT_ONLY |
1155                                       G_PARAM_STATIC_STRINGS));
1156
1157         /**
1158          * NMVpnPluginOld:state:
1159          *
1160          * The state of the plugin.
1161          *
1162          * Deprecated: 1.2: replaced by NMVpnServicePlugin
1163          */
1164         g_object_class_install_property
1165                 (object_class, PROP_STATE,
1166                  g_param_spec_enum (NM_VPN_PLUGIN_OLD_STATE, "", "",
1167                                     NM_TYPE_VPN_SERVICE_STATE,
1168                                     NM_VPN_SERVICE_STATE_INIT,
1169                                     G_PARAM_READWRITE |
1170                                     G_PARAM_STATIC_STRINGS));
1171
1172         /* signals */
1173         signals[STATE_CHANGED] =
1174                 g_signal_new ("state-changed",
1175                               G_OBJECT_CLASS_TYPE (object_class),
1176                               G_SIGNAL_RUN_FIRST,
1177                               G_STRUCT_OFFSET (NMVpnPluginOldClass, state_changed),
1178                               NULL, NULL,
1179                               NULL,
1180                               G_TYPE_NONE, 1,
1181                               G_TYPE_UINT);
1182
1183         signals[SECRETS_REQUIRED] =
1184                 g_signal_new ("secrets-required",
1185                               G_OBJECT_CLASS_TYPE (object_class),
1186                               G_SIGNAL_RUN_FIRST,
1187                               0, NULL, NULL,
1188                               NULL,
1189                               G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRV);
1190
1191         signals[CONFIG] =
1192                 g_signal_new ("config",
1193                               G_OBJECT_CLASS_TYPE (object_class),
1194                               G_SIGNAL_RUN_FIRST,
1195                               G_STRUCT_OFFSET (NMVpnPluginOldClass, config),
1196                               NULL, NULL,
1197                               NULL,
1198                               G_TYPE_NONE, 1,
1199                               G_TYPE_VARIANT);
1200
1201         signals[IP4_CONFIG] =
1202                 g_signal_new ("ip4-config",
1203                               G_OBJECT_CLASS_TYPE (object_class),
1204                               G_SIGNAL_RUN_FIRST,
1205                               G_STRUCT_OFFSET (NMVpnPluginOldClass, ip4_config),
1206                               NULL, NULL,
1207                               NULL,
1208                               G_TYPE_NONE, 1,
1209                               G_TYPE_VARIANT);
1210
1211         signals[IP6_CONFIG] =
1212                 g_signal_new ("ip6-config",
1213                               G_OBJECT_CLASS_TYPE (object_class),
1214                               G_SIGNAL_RUN_FIRST,
1215                               G_STRUCT_OFFSET (NMVpnPluginOldClass, ip6_config),
1216                               NULL, NULL,
1217                               NULL,
1218                               G_TYPE_NONE, 1,
1219                               G_TYPE_VARIANT);
1220
1221         signals[LOGIN_BANNER] =
1222                 g_signal_new ("login-banner",
1223                               G_OBJECT_CLASS_TYPE (object_class),
1224                               G_SIGNAL_RUN_FIRST,
1225                               G_STRUCT_OFFSET (NMVpnPluginOldClass, login_banner),
1226                               NULL, NULL,
1227                               NULL,
1228                               G_TYPE_NONE, 1,
1229                               G_TYPE_STRING);
1230
1231         signals[FAILURE] =
1232                 g_signal_new ("failure",
1233                               G_OBJECT_CLASS_TYPE (object_class),
1234                               G_SIGNAL_RUN_FIRST,
1235                               G_STRUCT_OFFSET (NMVpnPluginOldClass, failure),
1236                               NULL, NULL,
1237                               NULL,
1238                               G_TYPE_NONE, 1,
1239                               G_TYPE_UINT);
1240
1241         signals[QUIT] =
1242                 g_signal_new ("quit",
1243                               G_OBJECT_CLASS_TYPE (object_class),
1244                               G_SIGNAL_RUN_FIRST,
1245                               G_STRUCT_OFFSET (NMVpnPluginOldClass, quit),
1246                               NULL, NULL,
1247                               NULL,
1248                               G_TYPE_NONE, 0,
1249                               G_TYPE_NONE);
1250
1251         setup_unix_signal_handler ();
1252 }
1253
1254 static void
1255 nm_vpn_plugin_old_initable_iface_init (GInitableIface *iface)
1256 {
1257         iface->init = init_sync;
1258 }