Merge tag 'upstream/1.40' into tizen.
[platform/upstream/connman.git] / vpn / plugins / vpn.c
1 /*
2  *
3  *  ConnMan VPN daemon
4  *
5  *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #include <stdio.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <linux/if_tun.h>
35 #include <net/if.h>
36 #include <sys/types.h>
37 #include <pwd.h>
38 #include <grp.h>
39
40 #include <dbus/dbus.h>
41
42 #include <glib/gprintf.h>
43
44 #include <connman/log.h>
45 #include <connman/rtnl.h>
46 #include <connman/task.h>
47 #include <connman/inet.h>
48
49 #include "../vpn-rtnl.h"
50 #include "../vpn-provider.h"
51
52 #include "vpn.h"
53 #include "../vpn.h"
54
55 struct vpn_data {
56         struct vpn_provider *provider;
57         char *if_name;
58         unsigned flags;
59         unsigned int watch;
60         enum vpn_state state;
61         struct connman_task *task;
62         int tun_flags;
63 };
64
65 struct vpn_driver_data {
66         const char *name;
67         const char *program;
68         const struct vpn_driver *vpn_driver;
69         struct vpn_provider_driver provider_driver;
70 };
71
72 GHashTable *driver_hash = NULL;
73
74 static int stop_vpn(struct vpn_provider *provider)
75 {
76         struct vpn_data *data = vpn_provider_get_data(provider);
77         struct vpn_driver_data *vpn_driver_data;
78         const char *name;
79         struct ifreq ifr;
80         int fd, err;
81
82         if (!data)
83                 return -EINVAL;
84
85         name = vpn_provider_get_driver_name(provider);
86         if (!name)
87                 return -EINVAL;
88
89         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
90
91         if (vpn_driver_data && vpn_driver_data->vpn_driver &&
92                         vpn_driver_data->vpn_driver->flags & VPN_FLAG_NO_TUN) {
93                 vpn_driver_data->vpn_driver->disconnect(data->provider);
94                 return 0;
95         }
96
97         memset(&ifr, 0, sizeof(ifr));
98         ifr.ifr_flags = data->tun_flags | IFF_NO_PI;
99         sprintf(ifr.ifr_name, "%s", data->if_name);
100
101         fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
102         if (fd < 0) {
103                 err = -errno;
104                 connman_error("Failed to open /dev/net/tun to device %s: %s",
105                               data->if_name, strerror(errno));
106                 return err;
107         }
108
109         if (ioctl(fd, TUNSETIFF, (void *)&ifr)) {
110                 err = -errno;
111                 connman_error("Failed to TUNSETIFF for device %s to it: %s",
112                               data->if_name, strerror(errno));
113                 close(fd);
114                 return err;
115         }
116
117         if (ioctl(fd, TUNSETPERSIST, 0)) {
118                 err = -errno;
119                 connman_error("Failed to set tun device %s nonpersistent: %s",
120                               data->if_name, strerror(errno));
121                 close(fd);
122                 return err;
123         }
124         close(fd);
125         DBG("Killed tun device %s", data->if_name);
126         return 0;
127 }
128
129 void vpn_died(struct connman_task *task, int exit_code, void *user_data)
130 {
131         struct vpn_provider *provider = user_data;
132         struct vpn_data *data = vpn_provider_get_data(provider);
133         int state = VPN_STATE_FAILURE;
134         enum vpn_provider_error ret;
135
136         DBG("provider %p data %p", provider, data);
137
138         if (!data)
139                 goto vpn_exit;
140
141         /* The task may die after we have already started the new one */
142         if (data->task != task)
143                 goto done;
144
145         state = data->state;
146
147         stop_vpn(provider);
148         vpn_provider_set_data(provider, NULL);
149
150         if (data->watch != 0) {
151                 vpn_rtnl_remove_watch(data->watch);
152                 data->watch = 0;
153                 vpn_provider_unref(provider);
154         }
155
156 vpn_exit:
157         if (state != VPN_STATE_READY && state != VPN_STATE_DISCONNECT) {
158                 const char *name;
159                 struct vpn_driver_data *vpn_data = NULL;
160
161                 name = vpn_provider_get_driver_name(provider);
162                 if (name)
163                         vpn_data = g_hash_table_lookup(driver_hash, name);
164
165                 if (vpn_data &&
166                                 vpn_data->vpn_driver->error_code)
167                         ret = vpn_data->vpn_driver->error_code(provider,
168                                         exit_code);
169                 else
170                         ret = VPN_PROVIDER_ERROR_UNKNOWN;
171
172                 vpn_provider_indicate_error(provider, ret);
173         } else
174                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_IDLE);
175
176         vpn_provider_set_index(provider, -1);
177
178         if (data) {
179                 vpn_provider_unref(data->provider);
180                 g_free(data->if_name);
181                 g_free(data);
182         }
183
184 done:
185         connman_task_destroy(task);
186 }
187
188 int vpn_set_ifname(struct vpn_provider *provider, const char *ifname)
189 {
190         struct vpn_data *data = vpn_provider_get_data(provider);
191         int index;
192
193         if (!ifname || !data)
194                 return  -EIO;
195
196         index = connman_inet_ifindex(ifname);
197         if (index < 0)
198                 return  -EIO;
199
200         if (data->if_name)
201                 g_free(data->if_name);
202
203         data->if_name = (char *)g_strdup(ifname);
204         vpn_provider_set_index(provider, index);
205
206         return 0;
207 }
208
209 static int vpn_set_state(struct vpn_provider *provider,
210                                                 enum vpn_provider_state state)
211 {
212         struct vpn_data *data = vpn_provider_get_data(provider);
213         if (!data)
214                 return -EINVAL;
215
216         switch (state) {
217         case VPN_PROVIDER_STATE_UNKNOWN:
218                 return -EINVAL;
219         case VPN_PROVIDER_STATE_IDLE:
220                 data->state = VPN_STATE_IDLE;
221                 break;
222         case VPN_PROVIDER_STATE_CONNECT:
223         case VPN_PROVIDER_STATE_READY:
224                 data->state = VPN_STATE_CONNECT;
225                 break;
226         case VPN_PROVIDER_STATE_DISCONNECT:
227                 data->state = VPN_STATE_DISCONNECT;
228                 break;
229         case VPN_PROVIDER_STATE_FAILURE:
230                 data->state = VPN_STATE_FAILURE;
231                 break;
232         }
233
234         return 0;
235 }
236
237 static void vpn_newlink(unsigned flags, unsigned change, void *user_data)
238 {
239         struct vpn_provider *provider = user_data;
240         struct vpn_data *data = vpn_provider_get_data(provider);
241
242         if ((data->flags & IFF_UP) != (flags & IFF_UP)) {
243                 if (flags & IFF_UP) {
244                         data->state = VPN_STATE_READY;
245                         vpn_provider_set_state(provider,
246                                         VPN_PROVIDER_STATE_READY);
247                 }
248         }
249         data->flags = flags;
250 }
251
252 static DBusMessage *vpn_notify(struct connman_task *task,
253                         DBusMessage *msg, void *user_data)
254 {
255         struct vpn_provider *provider = user_data;
256         struct vpn_data *data;
257         struct vpn_driver_data *vpn_driver_data;
258         const char *name;
259         int state, index, err;
260
261         data = vpn_provider_get_data(provider);
262
263         name = vpn_provider_get_driver_name(provider);
264
265         if (!name) {
266                 DBG("Cannot find VPN driver for provider %p", provider);
267                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
268                 return NULL;
269         }
270
271         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
272         if (!vpn_driver_data) {
273                 DBG("Cannot find VPN driver data for name %s", name);
274                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
275                 return NULL;
276         }
277
278         state = vpn_driver_data->vpn_driver->notify(msg, provider);
279
280         DBG("provider %p driver %s state %d", provider, name, state);
281
282         switch (state) {
283         case VPN_STATE_CONNECT:
284         case VPN_STATE_READY:
285                 if (data->state == VPN_STATE_READY) {
286                         /*
287                          * This is the restart case, in which case we must
288                          * just set the IP address.
289                          *
290                          * We need to remove first the old address, just
291                          * replacing the old address will not work as expected
292                          * because the old address will linger in the interface
293                          * and not disappear so the clearing is needed here.
294                          *
295                          * Also the state must change, otherwise the routes
296                          * will not be set properly.
297                          */
298                         vpn_provider_set_state(provider,
299                                                 VPN_PROVIDER_STATE_CONNECT);
300
301                         vpn_provider_clear_address(provider, AF_INET);
302                         vpn_provider_clear_address(provider, AF_INET6);
303
304                         vpn_provider_change_address(provider);
305                         vpn_provider_set_state(provider,
306                                                 VPN_PROVIDER_STATE_READY);
307                         break;
308                 }
309
310                 index = vpn_provider_get_index(provider);
311                 vpn_provider_ref(provider);
312                 data->watch = vpn_rtnl_add_newlink_watch(index,
313                                                      vpn_newlink, provider);
314                 err = connman_inet_ifup(index);
315                 if (err < 0) {
316                         if (err == -EALREADY) {
317                                 /*
318                                  * So the interface is up already, that is just
319                                  * great. Unfortunately in this case the
320                                  * newlink watch might not have been called at
321                                  * all. We must manually call it here so that
322                                  * the provider can go to ready state and the
323                                  * routes are setup properly. Also reset flags
324                                  * so vpn_newlink() can handle the change.
325                                  */
326                                 data->flags = 0;
327                                 vpn_newlink(IFF_UP, 0, provider);
328                         } else {
329                                 DBG("Cannot take interface %d up err %d/%s",
330                                         index, -err, strerror(-err));
331                         }
332                 }
333                 break;
334
335         case VPN_STATE_UNKNOWN:
336         case VPN_STATE_IDLE:
337         case VPN_STATE_DISCONNECT:
338         case VPN_STATE_FAILURE:
339                 vpn_provider_set_state(provider,
340                                         VPN_PROVIDER_STATE_DISCONNECT);
341                 break;
342
343         case VPN_STATE_AUTH_FAILURE:
344                 vpn_provider_indicate_error(provider,
345                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
346                 break;
347         }
348
349         return NULL;
350 }
351
352 #if defined TIZEN_EXT
353 static void vpn_event(struct vpn_provider *provider, int state)
354 {
355         struct vpn_driver_data *vpn_driver_data;
356         const char *name;
357
358         name = vpn_provider_get_driver_name(provider);
359         if (!name) {
360                 DBG("Cannot find VPN driver for provider %p", provider);
361                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
362                 return;
363         }
364
365         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
366         if (!vpn_driver_data) {
367                 DBG("Cannot find VPN driver data for name %s", name);
368                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
369                 return;
370         }
371
372         DBG("provider %p driver %s state %d", provider, name, state);
373
374         switch (state) {
375         case VPN_STATE_CONNECT:
376                 vpn_provider_set_state(provider,
377                                 VPN_PROVIDER_STATE_CONNECT);
378                 break;
379         case VPN_STATE_READY:
380                 vpn_provider_set_state(provider,
381                                 VPN_PROVIDER_STATE_READY);
382                 break;
383
384         case VPN_STATE_UNKNOWN:
385         case VPN_STATE_IDLE:
386         case VPN_STATE_DISCONNECT:
387         case VPN_STATE_FAILURE:
388                 vpn_provider_set_state(provider,
389                                         VPN_PROVIDER_STATE_DISCONNECT);
390                 break;
391
392         case VPN_STATE_AUTH_FAILURE:
393                 vpn_provider_indicate_error(provider,
394                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
395                 break;
396         }
397
398         return;
399 }
400 #endif
401
402 static int vpn_create_tun(struct vpn_provider *provider, int flags)
403 {
404         struct vpn_data *data = vpn_provider_get_data(provider);
405         struct ifreq ifr;
406         int i, fd, index;
407         int ret = 0;
408
409         if (!data)
410                 return -EISCONN;
411
412         fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
413         if (fd < 0) {
414                 i = -errno;
415                 connman_error("Failed to open /dev/net/tun: %s",
416                               strerror(errno));
417                 ret = i;
418                 goto exist_err;
419         }
420
421         memset(&ifr, 0, sizeof(ifr));
422         ifr.ifr_flags = flags | IFF_NO_PI;
423
424         for (i = 0; i < 256; i++) {
425                 sprintf(ifr.ifr_name, "vpn%d", i);
426
427                 if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
428                         break;
429         }
430
431         if (i == 256) {
432                 connman_error("Failed to find available tun device");
433                 close(fd);
434                 ret = -ENODEV;
435                 goto exist_err;
436         }
437
438         data->tun_flags = flags;
439         g_free(data->if_name);
440         data->if_name = (char *)g_strdup(ifr.ifr_name);
441         if (!data->if_name) {
442                 connman_error("Failed to allocate memory");
443                 close(fd);
444                 ret = -ENOMEM;
445                 goto exist_err;
446         }
447
448         if (ioctl(fd, TUNSETPERSIST, 1)) {
449                 i = -errno;
450                 connman_error("Failed to set tun persistent: %s",
451                               strerror(errno));
452                 close(fd);
453                 ret = i;
454                 goto exist_err;
455         }
456
457         close(fd);
458
459         index = connman_inet_ifindex(data->if_name);
460         if (index < 0) {
461                 connman_error("Failed to get tun ifindex");
462                 stop_vpn(provider);
463                 ret = -EIO;
464                 goto exist_err;
465         }
466         vpn_provider_set_index(provider, index);
467
468         return 0;
469
470 exist_err:
471         return ret;
472 }
473
474 static gid_t get_gid(const char *group_name)
475 {
476         struct group *grp;
477
478         grp = vpn_util_get_group(group_name);
479         if (grp)
480                 return grp->gr_gid;
481
482         return -1;
483 }
484
485 static uid_t get_uid(const char *user_name)
486 {
487         struct passwd *pw;
488
489         pw = vpn_util_get_passwd(user_name);
490         if (pw)
491                 return pw->pw_uid;
492
493         return -1;
494 }
495
496 static gint get_supplementary_gids(gchar **groups, gid_t **gid_list)
497 {
498         gint group_count = 0;
499         gid_t *list = NULL;
500         int i;
501
502         if (groups) {
503                 for(i = 0; groups[i]; i++) {
504                         group_count++;
505
506                         list = (gid_t*)g_try_realloc(list,
507                                                 sizeof(gid_t) * group_count);
508
509                         if (!list) {
510                                 DBG("cannot allocate supplementary group list");
511                                 break;
512                         }
513
514                         list[i] = get_gid(groups[i]);
515                 }
516         }
517
518         *gid_list = list;
519
520         return group_count;
521 }
522
523 static void vpn_task_setup(gpointer user_data)
524 {
525         struct vpn_plugin_data *data;
526         uid_t uid;
527         gid_t gid;
528         gid_t *gid_list = NULL;
529         size_t gid_list_size;
530         const gchar *user;
531         const gchar *group;
532         gchar **suppl_groups;
533
534         data = user_data;
535         user = vpn_settings_get_binary_user(data);
536         group = vpn_settings_get_binary_group(data);
537         suppl_groups = vpn_settings_get_binary_supplementary_groups(data);
538
539         uid = get_uid(user);
540         gid = get_gid(group);
541         gid_list_size = get_supplementary_gids(suppl_groups, &gid_list);
542
543         DBG("vpn_task_setup uid:%d gid:%d supplementary group list size:%zu",
544                                         uid, gid, gid_list_size);
545
546
547         /* Change group if proper group name was set, requires CAP_SETGID.*/
548         if (gid > 0 && setgid(gid))
549                 connman_error("error setting gid %d %s", gid, strerror(errno));
550
551         /* Set the supplementary groups if list exists, requires CAP_SETGID. */
552         if (gid_list_size && gid_list && setgroups(gid_list_size, gid_list))
553                 connman_error("error setting gid list %s", strerror(errno));
554
555         /* Change user for the task if set, requires CAP_SETUID */
556         if (uid > 0 && setuid(uid))
557                 connman_error("error setting uid %d %s", uid, strerror(errno));
558 }
559
560
561 static gboolean update_provider_state(gpointer data)
562 {
563         struct vpn_provider *provider = data;
564         struct vpn_data *vpn_data;
565         int index;
566
567         DBG("");
568
569         vpn_data = vpn_provider_get_data(provider);
570
571         index = vpn_provider_get_index(provider);
572         DBG("index to watch %d", index);
573         vpn_provider_ref(provider);
574         vpn_data->watch = vpn_rtnl_add_newlink_watch(index,
575                                                 vpn_newlink, provider);
576         connman_inet_ifup(index);
577
578         return FALSE;
579 }
580
581 static int vpn_connect(struct vpn_provider *provider,
582                         vpn_provider_connect_cb_t cb,
583                         const char *dbus_sender, void *user_data)
584 {
585         struct vpn_data *data = vpn_provider_get_data(provider);
586         struct vpn_driver_data *vpn_driver_data;
587         struct vpn_plugin_data *vpn_plugin_data;
588         const char *name;
589         int ret = 0, tun_flags = IFF_TUN;
590         enum vpn_state state = VPN_STATE_UNKNOWN;
591
592         if (data)
593                 state = data->state;
594
595         DBG("data %p state %d", data, state);
596
597         switch (state) {
598         case VPN_STATE_UNKNOWN:
599                 data = g_try_new0(struct vpn_data, 1);
600                 if (!data)
601                         return -ENOMEM;
602
603                 data->provider = vpn_provider_ref(provider);
604                 data->watch = 0;
605                 data->flags = 0;
606                 data->task = NULL;
607
608                 vpn_provider_set_data(provider, data);
609                 /* fall through */
610
611         case VPN_STATE_DISCONNECT:
612         case VPN_STATE_IDLE:
613         case VPN_STATE_FAILURE:
614         case VPN_STATE_AUTH_FAILURE:
615                 data->state = VPN_STATE_IDLE;
616                 break;
617
618         case VPN_STATE_CONNECT:
619                 return -EINPROGRESS;
620
621         case VPN_STATE_READY:
622                 return -EISCONN;
623         }
624
625         name = vpn_provider_get_driver_name(provider);
626         if (!name)
627                 return -EINVAL;
628
629         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
630
631         if (!vpn_driver_data || !vpn_driver_data->vpn_driver) {
632                 ret = -EINVAL;
633                 goto exist_err;
634         }
635
636         if (!(vpn_driver_data->vpn_driver->flags & VPN_FLAG_NO_TUN)) {
637                 if (vpn_driver_data->vpn_driver->device_flags) {
638                         tun_flags = vpn_driver_data->vpn_driver->device_flags(provider);
639                 }
640                 ret = vpn_create_tun(provider, tun_flags);
641                 if (ret < 0)
642                         goto exist_err;
643         }
644
645
646         if (vpn_driver_data && vpn_driver_data->vpn_driver &&
647                         vpn_driver_data->vpn_driver->flags & VPN_FLAG_NO_DAEMON) {
648
649                 ret = vpn_driver_data->vpn_driver->connect(provider,
650                                         NULL, NULL, cb, dbus_sender, user_data);
651                 if (ret) {
652                         stop_vpn(provider);
653                         goto exist_err;
654                 }
655
656                 DBG("%s started with dev %s",
657                         vpn_driver_data->provider_driver.name, data->if_name);
658
659                 data->state = VPN_STATE_CONNECT;
660
661                 g_timeout_add(1, update_provider_state, provider);
662                 return -EINPROGRESS;
663         }
664
665         vpn_plugin_data =
666                 vpn_settings_get_vpn_plugin_config(vpn_driver_data->name);
667         data->task = connman_task_create(vpn_driver_data->program,
668                                         vpn_task_setup, vpn_plugin_data);
669
670         if (!data->task) {
671                 ret = -ENOMEM;
672                 stop_vpn(provider);
673                 goto exist_err;
674         }
675
676         if (connman_task_set_notify(data->task, "notify",
677                                         vpn_notify, provider)) {
678                 ret = -ENOMEM;
679                 stop_vpn(provider);
680                 connman_task_destroy(data->task);
681                 data->task = NULL;
682                 goto exist_err;
683         }
684
685 #if defined TIZEN_EXT
686         if(vpn_driver_data->vpn_driver->set_event_cb)
687                 vpn_driver_data->vpn_driver->set_event_cb(vpn_event, provider);
688 #endif
689
690         ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
691                                                 data->if_name, cb, dbus_sender,
692                                                 user_data);
693         if (ret < 0 && ret != -EINPROGRESS) {
694                 stop_vpn(provider);
695                 connman_task_destroy(data->task);
696                 data->task = NULL;
697                 goto exist_err;
698         }
699
700         DBG("%s started with dev %s",
701                 vpn_driver_data->provider_driver.name, data->if_name);
702
703         data->state = VPN_STATE_CONNECT;
704
705         return -EINPROGRESS;
706
707 exist_err:
708         vpn_provider_set_index(provider, -1);
709         vpn_provider_set_data(provider, NULL);
710         vpn_provider_unref(data->provider);
711         g_free(data->if_name);
712         g_free(data);
713
714         return ret;
715 }
716
717 static int vpn_probe(struct vpn_provider *provider)
718 {
719         return 0;
720 }
721
722 static int vpn_disconnect(struct vpn_provider *provider)
723 {
724         struct vpn_data *data = vpn_provider_get_data(provider);
725         struct vpn_driver_data *vpn_driver_data;
726         const char *name;
727
728         DBG("disconnect provider %p:", provider);
729
730         if (!data)
731                 return 0;
732
733         name = vpn_provider_get_driver_name(provider);
734         if (!name)
735                 return 0;
736
737         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
738         if (vpn_driver_data->vpn_driver->disconnect)
739                 vpn_driver_data->vpn_driver->disconnect(provider);
740
741         if (data->watch != 0) {
742                 vpn_provider_unref(provider);
743                 vpn_rtnl_remove_watch(data->watch);
744                 data->watch = 0;
745         }
746
747         data->state = VPN_STATE_DISCONNECT;
748
749         if (!vpn_driver_data->vpn_driver->disconnect) {
750                 DBG("Driver has no disconnect() implementation, set provider "
751                                         "state to disconnect.");
752                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_DISCONNECT);
753         }
754
755         if (data->task)
756                 connman_task_stop(data->task);
757
758         return 0;
759 }
760
761 static int vpn_remove(struct vpn_provider *provider)
762 {
763         struct vpn_data *data;
764         struct vpn_driver_data *driver_data;
765         const char *name;
766         int err = 0;
767
768         data = vpn_provider_get_data(provider);
769         name = vpn_provider_get_driver_name(provider);
770
771         if (!data)
772                 goto call_remove;
773
774         if (data->watch != 0) {
775                 vpn_provider_unref(provider);
776                 vpn_rtnl_remove_watch(data->watch);
777                 data->watch = 0;
778         }
779
780         if (data->task)
781                 connman_task_stop(data->task);
782
783         g_usleep(G_USEC_PER_SEC);
784         stop_vpn(provider);
785
786 call_remove:
787         if (!name)
788                 return 0;
789
790         driver_data = g_hash_table_lookup(driver_hash, name);
791
792         if (driver_data && driver_data->vpn_driver->remove)
793                 err = driver_data->vpn_driver->remove(provider);
794
795         if (err)
796                 DBG("%p vpn_driver->remove() returned %d", provider, err);
797
798         return err;
799 }
800
801 static int vpn_save(struct vpn_provider *provider, GKeyFile *keyfile)
802 {
803         struct vpn_driver_data *vpn_driver_data;
804         const char *name;
805
806         name = vpn_provider_get_driver_name(provider);
807         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
808         if (vpn_driver_data &&
809                         vpn_driver_data->vpn_driver->save)
810                 return vpn_driver_data->vpn_driver->save(provider, keyfile);
811
812         return 0;
813 }
814
815 static int vpn_route_env_parse(struct vpn_provider *provider, const char *key,
816                         int *family, unsigned long *idx,
817                         enum vpn_provider_route_type *type)
818 {
819         struct vpn_driver_data *vpn_driver_data = NULL;
820         const char *name = NULL;
821
822         if (!provider)
823                 return -EINVAL;
824
825         name = vpn_provider_get_driver_name(provider);
826         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
827
828         if (vpn_driver_data && vpn_driver_data->vpn_driver->route_env_parse)
829                 return vpn_driver_data->vpn_driver->route_env_parse(provider, key,
830                         family, idx, type);
831
832         return 0;
833 }
834
835 int vpn_register(const char *name, const struct vpn_driver *vpn_driver,
836                         const char *program)
837 {
838         struct vpn_driver_data *data;
839
840         data = g_try_new0(struct vpn_driver_data, 1);
841         if (!data)
842                 return -ENOMEM;
843
844         data->name = name;
845         data->program = program;
846
847         if (vpn_settings_parse_vpn_plugin_config(data->name) != 0)
848                 DBG("No configuration provided for VPN plugin %s", data->name);
849
850         data->vpn_driver = vpn_driver;
851
852         data->provider_driver.name = name;
853         data->provider_driver.disconnect = vpn_disconnect;
854         data->provider_driver.connect = vpn_connect;
855         data->provider_driver.probe = vpn_probe;
856         data->provider_driver.remove = vpn_remove;
857         data->provider_driver.save = vpn_save;
858         data->provider_driver.set_state = vpn_set_state;
859         data->provider_driver.route_env_parse = vpn_route_env_parse;
860
861         if (!driver_hash)
862                 driver_hash = g_hash_table_new_full(g_str_hash,
863                                                         g_str_equal,
864                                                         NULL, g_free);
865
866         if (!driver_hash) {
867                 connman_error("driver_hash not initialized for %s", name);
868                 g_free(data);
869                 return -ENOMEM;
870         }
871
872         g_hash_table_replace(driver_hash, (char *)name, data);
873
874         vpn_provider_driver_register(&data->provider_driver);
875
876         return 0;
877 }
878
879 void vpn_unregister(const char *name)
880 {
881         struct vpn_driver_data *data;
882
883         data = g_hash_table_lookup(driver_hash, name);
884         if (!data)
885                 return;
886
887         vpn_provider_driver_unregister(&data->provider_driver);
888         vpn_settings_delete_vpn_plugin_config(name);
889
890         g_hash_table_remove(driver_hash, name);
891
892         if (g_hash_table_size(driver_hash) == 0)
893                 g_hash_table_destroy(driver_hash);
894 }