vpn-plugin: Send proper response to caller and connect if needed
[platform/upstream/connman.git] / vpn / plugins / vpn.c
1 /*
2  *
3  *  ConnMan VPN daemon
4  *
5  *  Copyright (C) 2007-2012  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 == NULL)
79                 return -EINVAL;
80
81         name = vpn_provider_get_driver_name(provider);
82         if (name == NULL)
83                 return -EINVAL;
84
85         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
86
87         if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver != NULL &&
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 == NULL)
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 != NULL)
153                         vpn_data = g_hash_table_lookup(driver_hash, name);
154
155                 if (vpn_data != NULL &&
156                                 vpn_data->vpn_driver->error_code != NULL)
157                         ret = vpn_data->vpn_driver->error_code(exit_code);
158                 else
159                         ret = VPN_PROVIDER_ERROR_UNKNOWN;
160
161                 vpn_provider_indicate_error(provider, ret);
162
163                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
164         } else
165                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_IDLE);
166
167         vpn_provider_set_index(provider, -1);
168
169         if (data != NULL) {
170                 vpn_provider_unref(data->provider);
171                 g_free(data->if_name);
172                 g_free(data);
173         }
174
175         connman_task_destroy(task);
176 }
177
178 int vpn_set_ifname(struct vpn_provider *provider, const char *ifname)
179 {
180         struct vpn_data *data = vpn_provider_get_data(provider);
181         int index;
182
183         if (ifname == NULL || data == NULL)
184                 return  -EIO;
185
186         index = connman_inet_ifindex(ifname);
187         if (index < 0)
188                 return  -EIO;
189
190         if (data->if_name != NULL)
191                 g_free(data->if_name);
192
193         data->if_name = (char *)g_strdup(ifname);
194         vpn_provider_set_index(provider, index);
195
196         return 0;
197 }
198
199 static void vpn_newlink(unsigned flags, unsigned change, void *user_data)
200 {
201         struct vpn_provider *provider = user_data;
202         struct vpn_data *data = vpn_provider_get_data(provider);
203
204         if ((data->flags & IFF_UP) != (flags & IFF_UP)) {
205                 if (flags & IFF_UP) {
206                         data->state = VPN_STATE_READY;
207                         vpn_provider_set_state(provider,
208                                         VPN_PROVIDER_STATE_READY);
209                 }
210         }
211         data->flags = flags;
212 }
213
214 static DBusMessage *vpn_notify(struct connman_task *task,
215                         DBusMessage *msg, void *user_data)
216 {
217         struct vpn_provider *provider = user_data;
218         struct vpn_data *data;
219         struct vpn_driver_data *vpn_driver_data;
220         const char *name;
221         int state, index, err;
222
223         data = vpn_provider_get_data(provider);
224
225         name = vpn_provider_get_driver_name(provider);
226
227         if (name == NULL) {
228                 DBG("Cannot find VPN driver for provider %p", provider);
229                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
230                 return NULL;
231         }
232
233         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
234         if (vpn_driver_data == NULL) {
235                 DBG("Cannot find VPN driver data for name %s", name);
236                 vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
237                 return NULL;
238         }
239
240         state = vpn_driver_data->vpn_driver->notify(msg, provider);
241
242         DBG("provider %p driver %s state %d", provider, name, state);
243
244         switch (state) {
245         case VPN_STATE_CONNECT:
246         case VPN_STATE_READY:
247                 index = vpn_provider_get_index(provider);
248                 vpn_provider_ref(provider);
249                 data->watch = vpn_rtnl_add_newlink_watch(index,
250                                                      vpn_newlink, provider);
251                 err = connman_inet_ifup(index);
252                 if (err < 0) {
253                         if (err == -EALREADY)
254                                 /*
255                                  * So the interface is up already, that is just
256                                  * great. Unfortunately in this case the
257                                  * newlink watch might not have been called at
258                                  * all. We must manually call it here so that
259                                  * the provider can go to ready state and the
260                                  * routes are setup properly.
261                                  */
262                                 vpn_newlink(IFF_UP, 0, provider);
263                         else
264                                 DBG("Cannot take interface %d up err %d/%s",
265                                         index, -err, strerror(-err));
266                 }
267                 break;
268
269         case VPN_STATE_UNKNOWN:
270         case VPN_STATE_IDLE:
271         case VPN_STATE_DISCONNECT:
272         case VPN_STATE_FAILURE:
273                 vpn_provider_set_state(provider,
274                                         VPN_PROVIDER_STATE_DISCONNECT);
275                 break;
276
277         case VPN_STATE_AUTH_FAILURE:
278                 vpn_provider_indicate_error(provider,
279                                         VPN_PROVIDER_ERROR_AUTH_FAILED);
280                 break;
281         }
282
283         return NULL;
284 }
285
286 static int vpn_create_tun(struct vpn_provider *provider)
287 {
288         struct vpn_data *data = vpn_provider_get_data(provider);
289         struct ifreq ifr;
290         int i, fd, index;
291         int ret = 0;
292
293         if (data == NULL)
294                 return -EISCONN;
295
296         fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
297         if (fd < 0) {
298                 i = -errno;
299                 connman_error("Failed to open /dev/net/tun: %s",
300                               strerror(errno));
301                 ret = i;
302                 goto exist_err;
303         }
304
305         memset(&ifr, 0, sizeof(ifr));
306         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
307
308         for (i = 0; i < 256; i++) {
309                 sprintf(ifr.ifr_name, "vpn%d", i);
310
311                 if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
312                         break;
313         }
314
315         if (i == 256) {
316                 connman_error("Failed to find available tun device");
317                 close(fd);
318                 ret = -ENODEV;
319                 goto exist_err;
320         }
321
322         data->if_name = (char *)g_strdup(ifr.ifr_name);
323         if (data->if_name == NULL) {
324                 connman_error("Failed to allocate memory");
325                 close(fd);
326                 ret = -ENOMEM;
327                 goto exist_err;
328         }
329
330         if (ioctl(fd, TUNSETPERSIST, 1)) {
331                 i = -errno;
332                 connman_error("Failed to set tun persistent: %s",
333                               strerror(errno));
334                 close(fd);
335                 ret = i;
336                 goto exist_err;
337         }
338
339         close(fd);
340
341         index = connman_inet_ifindex(data->if_name);
342         if (index < 0) {
343                 connman_error("Failed to get tun ifindex");
344                 stop_vpn(provider);
345                 ret = -EIO;
346                 goto exist_err;
347         }
348         vpn_provider_set_index(provider, index);
349
350         return 0;
351
352 exist_err:
353         return ret;
354 }
355
356 static int vpn_connect(struct vpn_provider *provider,
357                         vpn_provider_connect_cb_t cb, void *user_data)
358 {
359         struct vpn_data *data = vpn_provider_get_data(provider);
360         struct vpn_driver_data *vpn_driver_data;
361         const char *name;
362         int ret = 0;
363         enum vpn_state state = VPN_STATE_UNKNOWN;
364
365         if (data != NULL)
366                 state = data->state;
367
368         DBG("data %p state %d", data, state);
369
370         switch (state) {
371         case VPN_STATE_UNKNOWN:
372                 data = g_try_new0(struct vpn_data, 1);
373                 if (data == NULL)
374                         return -ENOMEM;
375
376                 data->provider = vpn_provider_ref(provider);
377                 data->watch = 0;
378                 data->flags = 0;
379                 data->task = NULL;
380
381                 vpn_provider_set_data(provider, data);
382                 /* fall through */
383
384         case VPN_STATE_DISCONNECT:
385         case VPN_STATE_IDLE:
386         case VPN_STATE_FAILURE:
387         case VPN_STATE_AUTH_FAILURE:
388                 data->state = VPN_STATE_IDLE;
389                 break;
390
391         case VPN_STATE_CONNECT:
392                 return -EINPROGRESS;
393
394         case VPN_STATE_READY:
395                 return -EISCONN;
396         }
397
398         name = vpn_provider_get_driver_name(provider);
399         if (name == NULL)
400                 return -EINVAL;
401
402         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
403
404         if (vpn_driver_data == NULL || vpn_driver_data->vpn_driver == NULL) {
405                 ret = -EINVAL;
406                 goto exist_err;
407         }
408
409         if (vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
410                 ret = vpn_create_tun(provider);
411                 if (ret < 0)
412                         goto exist_err;
413         }
414
415         data->task = connman_task_create(vpn_driver_data->program);
416
417         if (data->task == NULL) {
418                 ret = -ENOMEM;
419                 stop_vpn(provider);
420                 goto exist_err;
421         }
422
423         if (connman_task_set_notify(data->task, "notify",
424                                         vpn_notify, provider)) {
425                 ret = -ENOMEM;
426                 stop_vpn(provider);
427                 connman_task_destroy(data->task);
428                 data->task = NULL;
429                 goto exist_err;
430         }
431
432         ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
433                                                 data->if_name, cb, user_data);
434         if (ret < 0 && ret != -EINPROGRESS) {
435                 stop_vpn(provider);
436                 connman_task_destroy(data->task);
437                 data->task = NULL;
438                 goto exist_err;
439         }
440
441         DBG("%s started with dev %s",
442                 vpn_driver_data->provider_driver.name, data->if_name);
443
444         data->state = VPN_STATE_CONNECT;
445
446         return -EINPROGRESS;
447
448 exist_err:
449         vpn_provider_set_index(provider, -1);
450         vpn_provider_set_data(provider, NULL);
451         vpn_provider_unref(data->provider);
452         g_free(data->if_name);
453         g_free(data);
454
455         return ret;
456 }
457
458 static int vpn_probe(struct vpn_provider *provider)
459 {
460         return 0;
461 }
462
463 static int vpn_disconnect(struct vpn_provider *provider)
464 {
465         struct vpn_data *data = vpn_provider_get_data(provider);
466         struct vpn_driver_data *vpn_driver_data;
467         const char *name;
468
469         DBG("disconnect provider %p:", provider);
470
471         if (data == NULL)
472                 return 0;
473
474         name = vpn_provider_get_driver_name(provider);
475         if (name == NULL)
476                 return 0;
477
478         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
479         if (vpn_driver_data->vpn_driver->disconnect)
480                 vpn_driver_data->vpn_driver->disconnect(provider);
481
482         if (data->watch != 0) {
483                 vpn_provider_unref(provider);
484                 vpn_rtnl_remove_watch(data->watch);
485                 data->watch = 0;
486         }
487
488         data->state = VPN_STATE_DISCONNECT;
489         connman_task_stop(data->task);
490
491         return 0;
492 }
493
494 static int vpn_remove(struct vpn_provider *provider)
495 {
496         struct vpn_data *data;
497
498         data = vpn_provider_get_data(provider);
499         if (data == NULL)
500                 return 0;
501
502         if (data->watch != 0) {
503                 vpn_provider_unref(provider);
504                 vpn_rtnl_remove_watch(data->watch);
505                 data->watch = 0;
506         }
507
508         connman_task_stop(data->task);
509
510         g_usleep(G_USEC_PER_SEC);
511         stop_vpn(provider);
512         return 0;
513 }
514
515 static int vpn_save(struct vpn_provider *provider, GKeyFile *keyfile)
516 {
517         struct vpn_driver_data *vpn_driver_data;
518         const char *name;
519
520         name = vpn_provider_get_driver_name(provider);
521         vpn_driver_data = g_hash_table_lookup(driver_hash, name);
522         if (vpn_driver_data != NULL &&
523                         vpn_driver_data->vpn_driver->save != NULL)
524                 return vpn_driver_data->vpn_driver->save(provider, keyfile);
525
526         return 0;
527 }
528
529 int vpn_register(const char *name, struct vpn_driver *vpn_driver,
530                         const char *program)
531 {
532         struct vpn_driver_data *data;
533
534         data = g_try_new0(struct vpn_driver_data, 1);
535         if (data == NULL)
536                 return -ENOMEM;
537
538         data->name = name;
539         data->program = program;
540
541         data->vpn_driver = vpn_driver;
542
543         data->provider_driver.name = name;
544         data->provider_driver.disconnect = vpn_disconnect;
545         data->provider_driver.connect = vpn_connect;
546         data->provider_driver.probe = vpn_probe;
547         data->provider_driver.remove = vpn_remove;
548         data->provider_driver.save = vpn_save;
549
550         if (driver_hash == NULL)
551                 driver_hash = g_hash_table_new_full(g_str_hash,
552                                                         g_str_equal,
553                                                         NULL, g_free);
554
555         if (driver_hash == NULL) {
556                 connman_error("driver_hash not initialized for %s", name);
557                 g_free(data);
558                 return -ENOMEM;
559         }
560
561         g_hash_table_replace(driver_hash, (char *)name, data);
562
563         vpn_provider_driver_register(&data->provider_driver);
564
565         return 0;
566 }
567
568 void vpn_unregister(const char *name)
569 {
570         struct vpn_driver_data *data;
571
572         data = g_hash_table_lookup(driver_hash, name);
573         if (data == NULL)
574                 return;
575
576         vpn_provider_driver_unregister(&data->provider_driver);
577
578         g_hash_table_remove(driver_hash, name);
579
580         if (g_hash_table_size(driver_hash) == 0)
581                 g_hash_table_destroy(driver_hash);
582 }