Imported Upstream version 1.24
[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 #define _GNU_SOURCE
27 #include <string.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
35 #include <linux/if_tun.h>
36 #include <net/if.h>
37
38 #include <dbus/dbus.h>
39
40 #include <glib/gprintf.h>
41
42 #include <connman/log.h>
43 #include <connman/rtnl.h>
44 #include <connman/task.h>
45 #include <connman/inet.h>
46
47 #include "../vpn-rtnl.h"
48 #include "../vpn-provider.h"
49
50 #include "vpn.h"
51
52 struct vpn_data {
53         struct vpn_provider *provider;
54         char *if_name;
55         unsigned flags;
56         unsigned int watch;
57         enum vpn_state state;
58         struct connman_task *task;
59 };
60
61 struct vpn_driver_data {
62         const char *name;
63         const char *program;
64         struct vpn_driver *vpn_driver;
65         struct vpn_provider_driver provider_driver;
66 };
67
68 GHashTable *driver_hash = NULL;
69
70 static int stop_vpn(struct vpn_provider *provider)
71 {
72         struct vpn_data *data = vpn_provider_get_data(provider);
73         struct vpn_driver_data *vpn_driver_data;
74         const char *name;
75         struct ifreq ifr;
76         int fd, err;
77
78         if (!data)
79                 return -EINVAL;
80
81         name = vpn_provider_get_driver_name(provider);
82         if (!name)
83                 return -EINVAL;
84
85         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
86
87         if (vpn_driver_data && vpn_driver_data->vpn_driver &&
88                         vpn_driver_data->vpn_driver->flags == VPN_FLAG_NO_TUN)
89                 return 0;
90
91         memset(&ifr, 0, sizeof(ifr));
92         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
93         sprintf(ifr.ifr_name, "%s", data->if_name);
94
95         fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
96         if (fd < 0) {
97                 err = -errno;
98                 connman_error("Failed to open /dev/net/tun to device %s: %s",
99                               data->if_name, strerror(errno));
100                 return err;
101         }
102
103         if (ioctl(fd, TUNSETIFF, (void *)&ifr)) {
104                 err = -errno;
105                 connman_error("Failed to TUNSETIFF for device %s to it: %s",
106                               data->if_name, strerror(errno));
107                 close(fd);
108                 return err;
109         }
110
111         if (ioctl(fd, TUNSETPERSIST, 0)) {
112                 err = -errno;
113                 connman_error("Failed to set tun device %s nonpersistent: %s",
114                               data->if_name, strerror(errno));
115                 close(fd);
116                 return err;
117         }
118         close(fd);
119         DBG("Killed tun device %s", data->if_name);
120         return 0;
121 }
122
123 void vpn_died(struct connman_task *task, int exit_code, void *user_data)
124 {
125         struct vpn_provider *provider = user_data;
126         struct vpn_data *data = vpn_provider_get_data(provider);
127         int state = VPN_STATE_FAILURE;
128         enum vpn_provider_error ret;
129
130         DBG("provider %p data %p", provider, data);
131
132         if (!data)
133                 goto vpn_exit;
134
135         state = data->state;
136
137         stop_vpn(provider);
138         vpn_provider_set_data(provider, NULL);
139
140         if (data->watch != 0) {
141                 vpn_provider_unref(provider);
142                 vpn_rtnl_remove_watch(data->watch);
143                 data->watch = 0;
144         }
145
146 vpn_exit:
147         if (state != VPN_STATE_READY && state != VPN_STATE_DISCONNECT) {
148                 const char *name;
149                 struct vpn_driver_data *vpn_data = NULL;
150
151                 name = vpn_provider_get_driver_name(provider);
152                 if (name)
153                         vpn_data = g_hash_table_lookup(driver_hash, name);
154
155                 if (vpn_data &&
156                                 vpn_data->vpn_driver->error_code)
157                         ret = vpn_data->vpn_driver->error_code(provider,
158                                         exit_code);
159                 else
160                         ret = VPN_PROVIDER_ERROR_UNKNOWN;
161
162                 vpn_provider_indicate_error(provider, ret);
163
164                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
165         } else
166                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_IDLE);
167
168         vpn_provider_set_index(provider, -1);
169
170         if (data) {
171                 vpn_provider_unref(data->provider);
172                 g_free(data->if_name);
173                 g_free(data);
174         }
175
176         connman_task_destroy(task);
177 }
178
179 int vpn_set_ifname(struct vpn_provider *provider, const char *ifname)
180 {
181         struct vpn_data *data = vpn_provider_get_data(provider);
182         int index;
183
184         if (!ifname || !data)
185                 return  -EIO;
186
187         index = connman_inet_ifindex(ifname);
188         if (index < 0)
189                 return  -EIO;
190
191         if (data->if_name)
192                 g_free(data->if_name);
193
194         data->if_name = (char *)g_strdup(ifname);
195         vpn_provider_set_index(provider, index);
196
197         return 0;
198 }
199
200 static void vpn_newlink(unsigned flags, unsigned change, void *user_data)
201 {
202         struct vpn_provider *provider = user_data;
203         struct vpn_data *data = vpn_provider_get_data(provider);
204
205         if ((data->flags & IFF_UP) != (flags & IFF_UP)) {
206                 if (flags & IFF_UP) {
207                         data->state = VPN_STATE_READY;
208                         vpn_provider_set_state(provider,
209                                         VPN_PROVIDER_STATE_READY);
210                 }
211         }
212         data->flags = flags;
213 }
214
215 static DBusMessage *vpn_notify(struct connman_task *task,
216                         DBusMessage *msg, void *user_data)
217 {
218         struct vpn_provider *provider = user_data;
219         struct vpn_data *data;
220         struct vpn_driver_data *vpn_driver_data;
221         const char *name;
222         int state, index, err;
223
224         data = vpn_provider_get_data(provider);
225
226         name = vpn_provider_get_driver_name(provider);
227
228         if (!name) {
229                 DBG("Cannot find VPN driver for provider %p", provider);
230                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
231                 return NULL;
232         }
233
234         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
235         if (!vpn_driver_data) {
236                 DBG("Cannot find VPN driver data for name %s", name);
237                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
238                 return NULL;
239         }
240
241         state = vpn_driver_data->vpn_driver->notify(msg, provider);
242
243         DBG("provider %p driver %s state %d", provider, name, state);
244
245         switch (state) {
246         case VPN_STATE_CONNECT:
247         case VPN_STATE_READY:
248                 index = vpn_provider_get_index(provider);
249                 vpn_provider_ref(provider);
250                 data->watch = vpn_rtnl_add_newlink_watch(index,
251                                                      vpn_newlink, provider);
252                 err = connman_inet_ifup(index);
253                 if (err < 0) {
254                         if (err == -EALREADY)
255                                 /*
256                                  * So the interface is up already, that is just
257                                  * great. Unfortunately in this case the
258                                  * newlink watch might not have been called at
259                                  * all. We must manually call it here so that
260                                  * the provider can go to ready state and the
261                                  * routes are setup properly.
262                                  */
263                                 vpn_newlink(IFF_UP, 0, provider);
264                         else
265                                 DBG("Cannot take interface %d up err %d/%s",
266                                         index, -err, strerror(-err));
267                 }
268                 break;
269
270         case VPN_STATE_UNKNOWN:
271         case VPN_STATE_IDLE:
272         case VPN_STATE_DISCONNECT:
273         case VPN_STATE_FAILURE:
274                 vpn_provider_set_state(provider,
275                                         VPN_PROVIDER_STATE_DISCONNECT);
276                 break;
277
278         case VPN_STATE_AUTH_FAILURE:
279                 vpn_provider_indicate_error(provider,
280                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
281                 break;
282         }
283
284         return NULL;
285 }
286
287 static int vpn_create_tun(struct vpn_provider *provider)
288 {
289         struct vpn_data *data = vpn_provider_get_data(provider);
290         struct ifreq ifr;
291         int i, fd, index;
292         int ret = 0;
293
294         if (!data)
295                 return -EISCONN;
296
297         fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
298         if (fd < 0) {
299                 i = -errno;
300                 connman_error("Failed to open /dev/net/tun: %s",
301                               strerror(errno));
302                 ret = i;
303                 goto exist_err;
304         }
305
306         memset(&ifr, 0, sizeof(ifr));
307         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
308
309         for (i = 0; i < 256; i++) {
310                 sprintf(ifr.ifr_name, "vpn%d", i);
311
312                 if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
313                         break;
314         }
315
316         if (i == 256) {
317                 connman_error("Failed to find available tun device");
318                 close(fd);
319                 ret = -ENODEV;
320                 goto exist_err;
321         }
322
323         data->if_name = (char *)g_strdup(ifr.ifr_name);
324         if (!data->if_name) {
325                 connman_error("Failed to allocate memory");
326                 close(fd);
327                 ret = -ENOMEM;
328                 goto exist_err;
329         }
330
331         if (ioctl(fd, TUNSETPERSIST, 1)) {
332                 i = -errno;
333                 connman_error("Failed to set tun persistent: %s",
334                               strerror(errno));
335                 close(fd);
336                 ret = i;
337                 goto exist_err;
338         }
339
340         close(fd);
341
342         index = connman_inet_ifindex(data->if_name);
343         if (index < 0) {
344                 connman_error("Failed to get tun ifindex");
345                 stop_vpn(provider);
346                 ret = -EIO;
347                 goto exist_err;
348         }
349         vpn_provider_set_index(provider, index);
350
351         return 0;
352
353 exist_err:
354         return ret;
355 }
356
357 static int vpn_connect(struct vpn_provider *provider,
358                         vpn_provider_connect_cb_t cb,
359                         const char *dbus_sender, void *user_data)
360 {
361         struct vpn_data *data = vpn_provider_get_data(provider);
362         struct vpn_driver_data *vpn_driver_data;
363         const char *name;
364         int ret = 0;
365         enum vpn_state state = VPN_STATE_UNKNOWN;
366
367         if (data)
368                 state = data->state;
369
370         DBG("data %p state %d", data, state);
371
372         switch (state) {
373         case VPN_STATE_UNKNOWN:
374                 data = g_try_new0(struct vpn_data, 1);
375                 if (!data)
376                         return -ENOMEM;
377
378                 data->provider = vpn_provider_ref(provider);
379                 data->watch = 0;
380                 data->flags = 0;
381                 data->task = NULL;
382
383                 vpn_provider_set_data(provider, data);
384                 /* fall through */
385
386         case VPN_STATE_DISCONNECT:
387         case VPN_STATE_IDLE:
388         case VPN_STATE_FAILURE:
389         case VPN_STATE_AUTH_FAILURE:
390                 data->state = VPN_STATE_IDLE;
391                 break;
392
393         case VPN_STATE_CONNECT:
394                 return -EINPROGRESS;
395
396         case VPN_STATE_READY:
397                 return -EISCONN;
398         }
399
400         name = vpn_provider_get_driver_name(provider);
401         if (!name)
402                 return -EINVAL;
403
404         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
405
406         if (!vpn_driver_data || !vpn_driver_data->vpn_driver) {
407                 ret = -EINVAL;
408                 goto exist_err;
409         }
410
411         if (vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
412                 ret = vpn_create_tun(provider);
413                 if (ret < 0)
414                         goto exist_err;
415         }
416
417         data->task = connman_task_create(vpn_driver_data->program);
418
419         if (!data->task) {
420                 ret = -ENOMEM;
421                 stop_vpn(provider);
422                 goto exist_err;
423         }
424
425         if (connman_task_set_notify(data->task, "notify",
426                                         vpn_notify, provider)) {
427                 ret = -ENOMEM;
428                 stop_vpn(provider);
429                 connman_task_destroy(data->task);
430                 data->task = NULL;
431                 goto exist_err;
432         }
433
434         ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
435                                                 data->if_name, cb, dbus_sender,
436                                                 user_data);
437         if (ret < 0 && ret != -EINPROGRESS) {
438                 stop_vpn(provider);
439                 connman_task_destroy(data->task);
440                 data->task = NULL;
441                 goto exist_err;
442         }
443
444         DBG("%s started with dev %s",
445                 vpn_driver_data->provider_driver.name, data->if_name);
446
447         data->state = VPN_STATE_CONNECT;
448
449         return -EINPROGRESS;
450
451 exist_err:
452         vpn_provider_set_index(provider, -1);
453         vpn_provider_set_data(provider, NULL);
454         vpn_provider_unref(data->provider);
455         g_free(data->if_name);
456         g_free(data);
457
458         return ret;
459 }
460
461 static int vpn_probe(struct vpn_provider *provider)
462 {
463         return 0;
464 }
465
466 static int vpn_disconnect(struct vpn_provider *provider)
467 {
468         struct vpn_data *data = vpn_provider_get_data(provider);
469         struct vpn_driver_data *vpn_driver_data;
470         const char *name;
471
472         DBG("disconnect provider %p:", provider);
473
474         if (!data)
475                 return 0;
476
477         name = vpn_provider_get_driver_name(provider);
478         if (!name)
479                 return 0;
480
481         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
482         if (vpn_driver_data->vpn_driver->disconnect)
483                 vpn_driver_data->vpn_driver->disconnect(provider);
484
485         if (data->watch != 0) {
486                 vpn_provider_unref(provider);
487                 vpn_rtnl_remove_watch(data->watch);
488                 data->watch = 0;
489         }
490
491         data->state = VPN_STATE_DISCONNECT;
492         connman_task_stop(data->task);
493
494         return 0;
495 }
496
497 static int vpn_remove(struct vpn_provider *provider)
498 {
499         struct vpn_data *data;
500
501         data = vpn_provider_get_data(provider);
502         if (!data)
503                 return 0;
504
505         if (data->watch != 0) {
506                 vpn_provider_unref(provider);
507                 vpn_rtnl_remove_watch(data->watch);
508                 data->watch = 0;
509         }
510
511         connman_task_stop(data->task);
512
513         g_usleep(G_USEC_PER_SEC);
514         stop_vpn(provider);
515         return 0;
516 }
517
518 static int vpn_save(struct vpn_provider *provider, GKeyFile *keyfile)
519 {
520         struct vpn_driver_data *vpn_driver_data;
521         const char *name;
522
523         name = vpn_provider_get_driver_name(provider);
524         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
525         if (vpn_driver_data &&
526                         vpn_driver_data->vpn_driver->save)
527                 return vpn_driver_data->vpn_driver->save(provider, keyfile);
528
529         return 0;
530 }
531
532 int vpn_register(const char *name, struct vpn_driver *vpn_driver,
533                         const char *program)
534 {
535         struct vpn_driver_data *data;
536
537         data = g_try_new0(struct vpn_driver_data, 1);
538         if (!data)
539                 return -ENOMEM;
540
541         data->name = name;
542         data->program = program;
543
544         data->vpn_driver = vpn_driver;
545
546         data->provider_driver.name = name;
547         data->provider_driver.disconnect = vpn_disconnect;
548         data->provider_driver.connect = vpn_connect;
549         data->provider_driver.probe = vpn_probe;
550         data->provider_driver.remove = vpn_remove;
551         data->provider_driver.save = vpn_save;
552
553         if (!driver_hash)
554                 driver_hash = g_hash_table_new_full(g_str_hash,
555                                                         g_str_equal,
556                                                         NULL, g_free);
557
558         if (!driver_hash) {
559                 connman_error("driver_hash not initialized for %s", name);
560                 g_free(data);
561                 return -ENOMEM;
562         }
563
564         g_hash_table_replace(driver_hash, (char *)name, data);
565
566         vpn_provider_driver_register(&data->provider_driver);
567
568         return 0;
569 }
570
571 void vpn_unregister(const char *name)
572 {
573         struct vpn_driver_data *data;
574
575         data = g_hash_table_lookup(driver_hash, name);
576         if (!data)
577                 return;
578
579         vpn_provider_driver_unregister(&data->provider_driver);
580
581         g_hash_table_remove(driver_hash, name);
582
583         if (g_hash_table_size(driver_hash) == 0)
584                 g_hash_table_destroy(driver_hash);
585 }