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