provider: Refactor server and user route handling
[platform/upstream/connman.git] / plugins / vpn.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 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 #include <string.h>
27 #include <errno.h>
28 #include <sys/socket.h>
29 #include <stdlib.h>
30 #include <glib.h>
31
32 #include <gdbus.h>
33
34 #define CONNMAN_API_SUBJECT_TO_CHANGE
35 #include <connman/technology.h>
36 #include <connman/plugin.h>
37 #include <connman/log.h>
38 #include <connman/dbus.h>
39 #include <connman/provider.h>
40 #include <connman/ipaddress.h>
41 #include <connman/vpn-dbus.h>
42 #include <connman/inet.h>
43
44 #define DBUS_TIMEOUT 10000
45
46 static DBusConnection *connection;
47
48 static GHashTable *vpn_connections = NULL;
49 static gboolean starting_vpnd = TRUE;
50 static guint watch;
51 static guint added_watch;
52 static guint removed_watch;
53 static guint property_watch;
54
55 struct vpn_route {
56         int family;
57         char *network;
58         char *netmask;
59         char *gateway;
60 };
61
62 struct connection_data {
63         char *path;
64         struct connman_provider *provider;
65         int index;
66         DBusPendingCall *call;
67
68         char *state;
69         char *type;
70         char *name;
71         char *host;
72         char *domain;
73         char **nameservers;
74
75         GHashTable *server_routes;
76         GHashTable *user_routes;
77         GHashTable *setting_strings;
78
79         struct connman_ipaddress *ip;
80 };
81
82 static int set_string(struct connman_provider *provider,
83                                         const char *key, const char *value)
84 {
85         struct connection_data *data;
86
87         data = connman_provider_get_data(provider);
88         if (data == NULL)
89                 return -EINVAL;
90
91         DBG("data %p provider %p key %s value %s", data, provider, key, value);
92
93         if (g_str_equal(key, "Type") == TRUE) {
94                 g_free(data->type);
95                 data->type = g_strdup(value);
96         } else if (g_str_equal(key, "Name") == TRUE) {
97                 g_free(data->name);
98                 data->name = g_strdup(value);
99         } else if (g_str_equal(key, "Host") == TRUE) {
100                 g_free(data->host);
101                 data->host = g_strdup(value);
102         } else if (g_str_equal(key, "VPN.Domain") == TRUE ||
103                                 g_str_equal(key, "Domain") == TRUE) {
104                 g_free(data->domain);
105                 data->domain = g_strdup(value);
106         } else
107                 g_hash_table_replace(data->setting_strings,
108                                 g_strdup(key), g_strdup(value));
109         return 0;
110 }
111
112 static const char *get_string(struct connman_provider *provider,
113                                                         const char *key)
114 {
115         struct connection_data *data;
116
117         data = connman_provider_get_data(provider);
118         if (data == NULL)
119                 return NULL;
120
121         DBG("data %p provider %p key %s", data, provider, key);
122
123         if (g_str_equal(key, "Type") == TRUE)
124                 return data->type;
125         else if (g_str_equal(key, "Name") == TRUE)
126                 return data->name;
127         else if (g_str_equal(key, "Host") == TRUE)
128                 return data->host;
129         else if (g_str_equal(key, "VPN.Domain") == TRUE)
130                 return data->domain;
131
132         return g_hash_table_lookup(data->setting_strings, key);
133 }
134
135 static char *get_ident(const char *path)
136 {
137         char *pos;
138
139         if (*path != '/')
140                 return NULL;
141
142         pos = strrchr(path, '/');
143         if (pos == NULL)
144                 return NULL;
145
146         return pos + 1;
147 }
148
149 static void set_provider_state(struct connection_data *data)
150 {
151         if (g_str_equal(data->state, "ready") == TRUE)
152                 connman_provider_set_state(data->provider,
153                                         CONNMAN_PROVIDER_STATE_READY);
154         else if (g_str_equal(data->state, "configuration") == TRUE)
155                 connman_provider_set_state(data->provider,
156                                         CONNMAN_PROVIDER_STATE_CONNECT);
157         else if (g_str_equal(data->state, "idle") == TRUE)
158                 connman_provider_set_state(data->provider,
159                                         CONNMAN_PROVIDER_STATE_IDLE);
160         else if (g_str_equal(data->state, "disconnect") == TRUE)
161                 connman_provider_set_state(data->provider,
162                                         CONNMAN_PROVIDER_STATE_DISCONNECT);
163         else if (g_str_equal(data->state, "failure") == TRUE)
164                 connman_provider_set_state(data->provider,
165                                         CONNMAN_PROVIDER_STATE_FAILURE);
166         else
167                 connman_provider_set_state(data->provider,
168                                         CONNMAN_PROVIDER_STATE_UNKNOWN);
169 }
170
171 static int create_provider(struct connection_data *data, void *user_data)
172 {
173         struct connman_provider_driver *driver = user_data;
174         char *ident;
175         int err = 0;
176
177         DBG("%s", data->path);
178
179         ident = g_strdup(get_ident(data->path));
180
181         data->provider = connman_provider_get(ident);
182         if (data->provider == NULL) {
183                 err = -ENOMEM;
184                 goto out;
185         }
186
187         DBG("provider %p name %s", data->provider, data->name);
188
189         connman_provider_set_data(data->provider, data);
190         connman_provider_set_driver(data->provider, driver);
191
192         err = connman_provider_create_service(data->provider);
193         if (err == 0) {
194                 if (g_str_equal(data->state, "ready") == TRUE) {
195                         connman_provider_set_index(data->provider,
196                                                         data->index);
197                         if (data->ip != NULL)
198                                 connman_provider_set_ipaddress(data->provider,
199                                                                 data->ip);
200                 }
201
202                 set_provider_state(data);
203         }
204
205 out:
206         g_free(ident);
207         return err;
208 }
209
210 static void destroy_route(gpointer user_data)
211 {
212         struct vpn_route *route = user_data;
213
214         g_free(route->network);
215         g_free(route->netmask);
216         g_free(route->gateway);
217         g_free(route);
218 }
219
220 static struct connection_data *create_connection_data(const char *path)
221 {
222         struct connection_data *data;
223
224         data = g_try_new0(struct connection_data, 1);
225         if (data == NULL)
226                 return NULL;
227
228         DBG("path %s", path);
229
230         data->path = g_strdup(path);
231         data->index = -1;
232
233         data->setting_strings = g_hash_table_new_full(g_str_hash,
234                                                 g_str_equal, g_free, g_free);
235
236         data->server_routes = g_hash_table_new_full(g_direct_hash,
237                                         g_str_equal, g_free, destroy_route);
238         data->user_routes = g_hash_table_new_full(g_str_hash,
239                                         g_str_equal, g_free, destroy_route);
240
241         return data;
242 }
243
244 static int extract_ip(DBusMessageIter *array, int family,
245                                                 struct connection_data *data)
246 {
247         DBusMessageIter dict;
248         char *address = NULL, *gateway = NULL, *netmask = NULL, *peer = NULL;
249         unsigned char prefix_len;
250
251         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
252                 return -EINVAL;
253
254         dbus_message_iter_recurse(array, &dict);
255
256         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
257                 DBusMessageIter entry, value;
258                 const char *key;
259
260                 dbus_message_iter_recurse(&dict, &entry);
261                 dbus_message_iter_get_basic(&entry, &key);
262
263                 dbus_message_iter_next(&entry);
264                 dbus_message_iter_recurse(&entry, &value);
265
266                 if (g_str_equal(key, "Address") == TRUE) {
267                         dbus_message_iter_get_basic(&value, &address);
268                         DBG("address %s", address);
269                 } else if (g_str_equal(key, "Netmask") == TRUE) {
270                         dbus_message_iter_get_basic(&value, &netmask);
271                         DBG("netmask %s", netmask);
272                 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
273                         dbus_message_iter_get_basic(&value, &netmask);
274                         DBG("prefix length %s", netmask);
275                 } else if (g_str_equal(key, "Peer") == TRUE) {
276                         dbus_message_iter_get_basic(&value, &peer);
277                         DBG("peer %s", peer);
278                 } else if (g_str_equal(key, "Gateway") == TRUE) {
279                         dbus_message_iter_get_basic(&value, &gateway);
280                         DBG("gateway %s", gateway);
281                 }
282
283                 dbus_message_iter_next(&dict);
284         }
285
286         data->ip = connman_ipaddress_alloc(family);
287         if (data->ip == NULL)
288                 return -ENOMEM;
289
290         switch (family) {
291         case AF_INET:
292                 connman_ipaddress_set_ipv4(data->ip, address, netmask,
293                                                                 gateway);
294                 break;
295         case AF_INET6:
296                 prefix_len = atoi(netmask);
297                 connman_ipaddress_set_ipv6(data->ip, address, prefix_len,
298                                                                 gateway);
299                 break;
300         default:
301                 return -EINVAL;
302         }
303
304         connman_ipaddress_set_peer(data->ip, peer);
305
306         return 0;
307 }
308
309 static int extract_nameservers(DBusMessageIter *array,
310                                                 struct connection_data *data)
311 {
312         DBusMessageIter entry;
313         char **nameservers = NULL;
314         int i = 0;
315
316         dbus_message_iter_recurse(array, &entry);
317
318         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
319                 const char *nameserver;
320
321                 dbus_message_iter_get_basic(&entry, &nameserver);
322
323                 nameservers = g_try_renew(char *, nameservers, i + 2);
324                 if (nameservers == NULL)
325                         return -ENOMEM;
326
327                 DBG("[%d] %s", i, nameserver);
328
329                 nameservers[i] = g_strdup(nameserver);
330                 if (nameservers[i] == NULL)
331                         return -ENOMEM;
332
333                 nameservers[++i] = NULL;
334
335                 dbus_message_iter_next(&entry);
336         }
337
338         g_strfreev(data->nameservers);
339         data->nameservers = nameservers;
340
341         return 0;
342 }
343
344 static void connect_reply(DBusPendingCall *call, void *user_data)
345 {
346         DBusMessage *reply;
347         DBusError error;
348
349         if (dbus_pending_call_get_completed(call) == FALSE)
350                 return;
351
352         DBG("user_data %p", user_data);
353
354         reply = dbus_pending_call_steal_reply(call);
355
356         dbus_error_init(&error);
357
358         if (dbus_set_error_from_message(&error, reply) == TRUE) {
359                 if (dbus_error_has_name(&error, CONNMAN_ERROR_INTERFACE
360                                                 ".InProgress") == FALSE) {
361                         connman_error("Connect reply: %s (%s)", error.message,
362                                                                 error.name);
363                         dbus_error_free(&error);
364                         goto done;
365                 }
366                 dbus_error_free(&error);
367         }
368
369         /*
370          * The vpn connection is up when we get a "ready" state
371          * property so at this point we do nothing for the provider
372          * state.
373          */
374
375 done:
376         dbus_message_unref(reply);
377
378         dbus_pending_call_unref(call);
379 }
380
381 static int connect_provider(struct connection_data *data, void *user_data)
382 {
383         DBusPendingCall *call;
384         DBusMessage *message;
385
386         DBG("data %p", data);
387
388         message = dbus_message_new_method_call(VPN_SERVICE, data->path,
389                                         VPN_CONNECTION_INTERFACE,
390                                         VPN_CONNECT);
391         if (message == NULL)
392                 return -ENOMEM;
393
394         if (dbus_connection_send_with_reply(connection, message,
395                                         &call, DBUS_TIMEOUT) == FALSE) {
396                 connman_error("Unable to call %s.%s()",
397                         VPN_CONNECTION_INTERFACE, VPN_CONNECT);
398                 dbus_message_unref(message);
399                 return -EINVAL;
400         }
401
402         if (call == NULL) {
403                 dbus_message_unref(message);
404                 return -EINVAL;
405         }
406
407         dbus_pending_call_set_notify(call, connect_reply, NULL, NULL);
408
409         dbus_message_unref(message);
410
411         return -EINPROGRESS;
412 }
413
414 static void add_connection(const char *path, DBusMessageIter *properties,
415                         void *user_data)
416 {
417         struct connection_data *data;
418         int err;
419
420         data = g_hash_table_lookup(vpn_connections, path);
421         if (data != NULL)
422                 return;
423
424         data = create_connection_data(path);
425         if (data == NULL)
426                 return;
427
428         DBG("data %p path %s", data, path);
429
430         while (dbus_message_iter_get_arg_type(properties) ==
431                         DBUS_TYPE_DICT_ENTRY) {
432                 DBusMessageIter entry, value;
433                 const char *key;
434                 char *str;
435
436                 dbus_message_iter_recurse(properties, &entry);
437                 dbus_message_iter_get_basic(&entry, &key);
438
439                 dbus_message_iter_next(&entry);
440                 dbus_message_iter_recurse(&entry, &value);
441
442                 if (g_str_equal(key, "State") == TRUE) {
443                         dbus_message_iter_get_basic(&value, &str);
444                         DBG("state %s -> %s", data->state, str);
445                         data->state = g_strdup(str);
446                 } else if (g_str_equal(key, "IPv4") == TRUE) {
447                         extract_ip(&value, AF_INET, data);
448                 } else if (g_str_equal(key, "IPv6") == TRUE) {
449                         extract_ip(&value, AF_INET6, data);
450                 } else if (g_str_equal(key, "Name") == TRUE) {
451                         dbus_message_iter_get_basic(&value, &str);
452                         data->name = g_strdup(str);
453                 } else if (g_str_equal(key, "Type") == TRUE) {
454                         dbus_message_iter_get_basic(&value, &str);
455                         data->type = g_strdup(str);
456                 } else if (g_str_equal(key, "Host") == TRUE) {
457                         dbus_message_iter_get_basic(&value, &str);
458                         data->host = g_strdup(str);
459                 } else if (g_str_equal(key, "Domain") == TRUE) {
460                         dbus_message_iter_get_basic(&value, &str);
461                         data->domain = g_strdup(str);
462                 } else if (g_str_equal(key, "Nameservers") == TRUE) {
463                         extract_nameservers(&value, data);
464                 } else if (g_str_equal(key, "Index") == TRUE) {
465                         dbus_message_iter_get_basic(&value, &data->index);
466                 } else {
467                         if (dbus_message_iter_get_arg_type(&value) ==
468                                                         DBUS_TYPE_STRING) {
469                                 dbus_message_iter_get_basic(&value, &str);
470                                 g_hash_table_replace(data->setting_strings,
471                                                 g_strdup(key), g_strdup(str));
472                         } else {
473                                 DBG("unknown key %s", key);
474                         }
475                 }
476
477                 dbus_message_iter_next(properties);
478         }
479
480         g_hash_table_insert(vpn_connections, g_strdup(path), data);
481
482         err = create_provider(data, user_data);
483         if (err < 0)
484                 goto out;
485
486         return;
487
488 out:
489         DBG("removing %s", path);
490         g_hash_table_remove(vpn_connections, path);
491 }
492
493 static void get_connections_reply(DBusPendingCall *call, void *user_data)
494 {
495         DBusMessage *reply;
496         DBusError error;
497         DBusMessageIter array, dict;
498         const char *signature = DBUS_TYPE_ARRAY_AS_STRING
499                 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
500                 DBUS_TYPE_OBJECT_PATH_AS_STRING
501                 DBUS_TYPE_ARRAY_AS_STRING
502                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
503                 DBUS_TYPE_STRING_AS_STRING
504                 DBUS_TYPE_VARIANT_AS_STRING
505                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
506                 DBUS_STRUCT_END_CHAR_AS_STRING;
507
508         DBG("");
509
510         reply = dbus_pending_call_steal_reply(call);
511
512         if (dbus_message_has_signature(reply, signature) == FALSE) {
513                 connman_error("vpnd signature \"%s\" does not match "
514                                                         "expected \"%s\"",
515                         dbus_message_get_signature(reply), signature);
516                 goto done;
517         }
518
519         dbus_error_init(&error);
520
521         if (dbus_set_error_from_message(&error, reply) == TRUE) {
522                 connman_error("%s", error.message);
523                 dbus_error_free(&error);
524                 goto done;
525         }
526
527         if (dbus_message_iter_init(reply, &array) == FALSE)
528                 goto done;
529
530         dbus_message_iter_recurse(&array, &dict);
531
532         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
533                 DBusMessageIter value, properties;
534                 const char *path;
535
536                 dbus_message_iter_recurse(&dict, &value);
537                 dbus_message_iter_get_basic(&value, &path);
538
539                 dbus_message_iter_next(&value);
540                 dbus_message_iter_recurse(&value, &properties);
541
542                 add_connection(path, &properties, user_data);
543
544                 dbus_message_iter_next(&dict);
545         }
546
547 done:
548         dbus_message_unref(reply);
549
550         dbus_pending_call_unref(call);
551 }
552
553 static int get_connections(void *user_data)
554 {
555         DBusPendingCall *call;
556         DBusMessage *message;
557
558         DBG("");
559
560         message = dbus_message_new_method_call(VPN_SERVICE, "/",
561                                         VPN_MANAGER_INTERFACE,
562                                         GET_CONNECTIONS);
563         if (message == NULL)
564                 return -ENOMEM;
565
566         if (dbus_connection_send_with_reply(connection, message,
567                                         &call, DBUS_TIMEOUT) == FALSE) {
568                 connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
569                                                         GET_CONNECTIONS);
570                 dbus_message_unref(message);
571                 return -EINVAL;
572         }
573
574         if (call == NULL) {
575                 dbus_message_unref(message);
576                 return -EINVAL;
577         }
578
579         dbus_pending_call_set_notify(call, get_connections_reply,
580                                                         user_data, NULL);
581
582         dbus_message_unref(message);
583
584         return -EINPROGRESS;
585 }
586
587 static int provider_probe(struct connman_provider *provider)
588 {
589         return 0;
590 }
591
592 static void remove_connection_reply(DBusPendingCall *call, void *user_data)
593 {
594         DBusMessage *reply;
595         DBusError error;
596
597         DBG("");
598
599         reply = dbus_pending_call_steal_reply(call);
600
601         dbus_error_init(&error);
602
603         if (dbus_set_error_from_message(&error, reply) == TRUE) {
604                 /*
605                  * If the returned error is NotFound, it means that we
606                  * have actually removed the provider in vpnd already.
607                  */
608                 if (dbus_error_has_name(&error, CONNMAN_ERROR_INTERFACE
609                                                 ".NotFound") == FALSE)
610                         connman_error("%s", error.message);
611
612                 dbus_error_free(&error);
613         }
614
615         dbus_message_unref(reply);
616
617         dbus_pending_call_unref(call);
618 }
619
620 static int provider_remove(struct connman_provider *provider)
621 {
622         DBusPendingCall *call;
623         DBusMessage *message;
624         struct connection_data *data;
625
626         data = connman_provider_get_data(provider);
627
628         DBG("provider %p data %p", provider, data);
629
630         /*
631          * When provider.c:provider_remove() calls this function,
632          * it will remove the provider itself after the call.
633          * This means that we cannot use the provider pointer later
634          * as it is no longer valid.
635          */
636         data->provider = NULL;
637
638         message = dbus_message_new_method_call(VPN_SERVICE, "/",
639                                         VPN_MANAGER_INTERFACE,
640                                         VPN_REMOVE);
641         if (message == NULL)
642                 return -ENOMEM;
643
644         dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &data->path,
645                                 NULL);
646
647         if (dbus_connection_send_with_reply(connection, message,
648                                         &call, DBUS_TIMEOUT) == FALSE) {
649                 connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
650                                                         VPN_REMOVE);
651                 dbus_message_unref(message);
652                 return -EINVAL;
653         }
654
655         if (call == NULL) {
656                 dbus_message_unref(message);
657                 return -EINVAL;
658         }
659
660         dbus_pending_call_set_notify(call, remove_connection_reply,
661                                                         NULL, NULL);
662
663         dbus_message_unref(message);
664
665         return 0;
666 }
667
668 static int provider_connect(struct connman_provider *provider)
669 {
670         struct connection_data *data;
671
672         data = connman_provider_get_data(provider);
673         if (data == NULL)
674                 return -EINVAL;
675
676         return connect_provider(data, NULL);
677
678 }
679
680 static void disconnect_reply(DBusPendingCall *call, void *user_data)
681 {
682         DBusMessage *reply;
683         DBusError error;
684
685         DBG("");
686
687         reply = dbus_pending_call_steal_reply(call);
688
689         dbus_error_init(&error);
690
691         if (dbus_set_error_from_message(&error, reply) == TRUE) {
692                 connman_error("%s", error.message);
693                 dbus_error_free(&error);
694                 goto done;
695         }
696
697 done:
698         dbus_message_unref(reply);
699
700         dbus_pending_call_unref(call);
701 }
702
703 static int disconnect_provider(struct connection_data *data)
704 {
705         DBusPendingCall *call;
706         DBusMessage *message;
707
708         DBG("data %p path %s", data, data->path);
709
710         message = dbus_message_new_method_call(VPN_SERVICE, data->path,
711                                         VPN_CONNECTION_INTERFACE,
712                                         VPN_DISCONNECT);
713         if (message == NULL)
714                 return -ENOMEM;
715
716         if (dbus_connection_send_with_reply(connection, message,
717                                         &call, DBUS_TIMEOUT) == FALSE) {
718                 connman_error("Unable to call %s.%s()",
719                         VPN_CONNECTION_INTERFACE, VPN_DISCONNECT);
720                 dbus_message_unref(message);
721                 return -EINVAL;
722         }
723
724         if (call == NULL) {
725                 dbus_message_unref(message);
726                 return -EINVAL;
727         }
728
729         dbus_pending_call_set_notify(call, disconnect_reply, NULL, NULL);
730
731         dbus_message_unref(message);
732
733         connman_provider_set_state(data->provider,
734                                         CONNMAN_PROVIDER_STATE_DISCONNECT);
735         /*
736          * We return 0 here instead of -EINPROGRESS because
737          * __connman_service_disconnect() needs to return something
738          * to gdbus so that gdbus will not call Disconnect() more
739          * than once. This way we do not need to pass the dbus reply
740          * message around the code.
741          */
742         return 0;
743 }
744
745 static int provider_disconnect(struct connman_provider *provider)
746 {
747         struct connection_data *data;
748
749         DBG("provider %p", provider);
750
751         data = connman_provider_get_data(provider);
752         if (data == NULL)
753                 return -EINVAL;
754
755         if (g_str_equal(data->state, "ready") == TRUE ||
756                         g_str_equal(data->state, "configuration") == TRUE)
757                 return disconnect_provider(data);
758
759         return 0;
760 }
761
762 static void configuration_create_reply(DBusPendingCall *call, void *user_data)
763 {
764         DBusMessage *reply;
765         DBusError error;
766         DBusMessageIter iter;
767         const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
768         const char *path;
769
770         DBG("user %p", user_data);
771
772         reply = dbus_pending_call_steal_reply(call);
773
774         if (dbus_message_has_signature(reply, signature) == FALSE) {
775                 connman_error("vpn configuration signature \"%s\" does not "
776                                                 "match expected \"%s\"",
777                         dbus_message_get_signature(reply), signature);
778                 goto done;
779         }
780
781         dbus_error_init(&error);
782
783         if (dbus_set_error_from_message(&error, reply) == TRUE) {
784                 connman_error("dbus error: %s", error.message);
785                 dbus_error_free(&error);
786                 goto done;
787         }
788
789         if (dbus_message_iter_init(reply, &iter) == FALSE)
790                 goto done;
791
792         dbus_message_iter_get_basic(&iter, &path);
793
794         /*
795          * Then try to connect the VPN as expected by ConnectProvider API
796          */
797         // XXX:
798
799 done:
800         dbus_message_unref(reply);
801
802         dbus_pending_call_unref(call);
803 }
804
805 static void set_dbus_ident(char *ident)
806 {
807         int i, len = strlen(ident);
808
809         for (i = 0; i < len; i++) {
810                 if (ident[i] >= '0' && ident[i] <= '9')
811                         continue;
812                 if (ident[i] >= 'a' && ident[i] <= 'z')
813                         continue;
814                 if (ident[i] >= 'A' && ident[i] <= 'Z')
815                         continue;
816                 ident[i] = '_';
817         }
818 }
819
820 static struct vpn_route *parse_user_route(const char *user_route)
821 {
822         char *network, *netmask;
823         struct vpn_route *route = NULL;
824         int family = PF_UNSPEC;
825         char **elems = g_strsplit(user_route, "/", 0);
826
827         if (elems == NULL)
828                 return NULL;
829
830         network = elems[0];
831         if (network == NULL || *network == '\0') {
832                 DBG("no network/netmask set");
833                 goto out;
834         }
835
836         netmask = elems[1];
837         if (netmask != NULL && *netmask == '\0') {
838                 DBG("no netmask set");
839                 goto out;
840         }
841
842         if (g_strrstr(network, ":") != NULL)
843                 family = AF_INET6;
844         else if (g_strrstr(network, ".") != NULL) {
845                 family = AF_INET;
846
847                 if (g_strrstr(netmask, ".") == NULL) {
848                         /* We have netmask length */
849                         in_addr_t addr;
850                         struct in_addr netmask_in;
851                         unsigned char prefix_len = 32;
852
853                         if (netmask != NULL) {
854                                 char *ptr;
855                                 long int value = strtol(netmask, &ptr, 10);
856                                 if (ptr != netmask && *ptr == '\0' &&
857                                                                 value <= 32)
858                                         prefix_len = value;
859                         }
860
861                         addr = 0xffffffff << (32 - prefix_len);
862                         netmask_in.s_addr = htonl(addr);
863                         netmask = inet_ntoa(netmask_in);
864
865                         DBG("network %s netmask %s", network, netmask);
866                 }
867         }
868
869         route = g_try_new(struct vpn_route, 1);
870         if (route == NULL)
871                 goto out;
872
873         route->network = g_strdup(network);
874         route->netmask = g_strdup(netmask);
875         route->gateway = NULL;
876         route->family = family;
877
878 out:
879         g_strfreev(elems);
880         return route;
881 }
882
883 static GSList *get_user_networks(DBusMessageIter *array)
884 {
885         DBusMessageIter entry;
886         GSList *list = NULL;
887
888         dbus_message_iter_recurse(array, &entry);
889
890         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
891                 const char *val;
892                 struct vpn_route *route;
893
894                 dbus_message_iter_get_basic(&entry, &val);
895
896                 route = parse_user_route(val);
897                 if (route != NULL)
898                         list = g_slist_prepend(list, route);
899
900                 dbus_message_iter_next(&entry);
901         }
902
903         return list;
904 }
905
906 static void append_route(DBusMessageIter *iter, void *user_data)
907 {
908         struct vpn_route *route = user_data;
909         DBusMessageIter item;
910         int family = 0;
911
912         connman_dbus_dict_open(iter, &item);
913
914         if (route == NULL)
915                 goto empty_dict;
916
917         if (route->family == AF_INET)
918                 family = 4;
919         else if (route->family == AF_INET6)
920                 family = 6;
921
922         if (family != 0)
923                 connman_dbus_dict_append_basic(&item, "ProtocolFamily",
924                                         DBUS_TYPE_INT32, &family);
925
926         if (route->network != NULL)
927                 connman_dbus_dict_append_basic(&item, "Network",
928                                         DBUS_TYPE_STRING, &route->network);
929
930         if (route->netmask != NULL)
931                 connman_dbus_dict_append_basic(&item, "Netmask",
932                                         DBUS_TYPE_STRING, &route->netmask);
933
934         if (route->gateway != NULL)
935                 connman_dbus_dict_append_basic(&item, "Gateway",
936                                         DBUS_TYPE_STRING, &route->gateway);
937
938 empty_dict:
939         connman_dbus_dict_close(iter, &item);
940 }
941
942 static void append_routes(DBusMessageIter *iter, void *user_data)
943 {
944         GSList *list, *routes = user_data;
945
946         DBG("routes %p", routes);
947
948         for (list = routes; list != NULL; list = g_slist_next(list)) {
949                 DBusMessageIter dict;
950                 struct vpn_route *route = list->data;
951
952                 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL,
953                                                 &dict);
954                 append_route(&dict, route);
955                 dbus_message_iter_close_container(iter, &dict);
956         }
957 }
958
959 static int create_configuration(DBusMessage *msg)
960 {
961         DBusMessage *new_msg;
962         DBusPendingCall *call;
963         DBusMessageIter iter, array, new_iter, new_dict;
964         const char *type = NULL, *name = NULL;
965         const char *host = NULL, *domain = NULL;
966         char *ident, *me = NULL;
967         int err = 0;
968         dbus_bool_t result;
969         struct connection_data *data;
970         GSList *networks = NULL;
971
972         /*
973          * We copy the old message data into new message. We cannot
974          * just use the old message as is because the user route
975          * information is not in the same format in vpnd.
976          */
977         new_msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
978         dbus_message_iter_init_append(new_msg, &new_iter);
979         connman_dbus_dict_open(&new_iter, &new_dict);
980
981         dbus_message_iter_init(msg, &iter);
982         dbus_message_iter_recurse(&iter, &array);
983
984         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
985                 DBusMessageIter entry, value;
986                 void *item_value;
987                 const char *key;
988                 int value_type;
989
990                 dbus_message_iter_recurse(&array, &entry);
991                 dbus_message_iter_get_basic(&entry, &key);
992
993                 dbus_message_iter_next(&entry);
994                 dbus_message_iter_recurse(&entry, &value);
995
996                 value_type = dbus_message_iter_get_arg_type(&value);
997                 item_value = NULL;
998
999                 switch (value_type) {
1000                 case DBUS_TYPE_STRING:
1001                         dbus_message_iter_get_basic(&value, &item_value);
1002
1003                         if (g_str_equal(key, "Type") == TRUE) {
1004                                 type = (const char *)item_value;
1005                         } else if (g_str_equal(key, "Name") == TRUE) {
1006                                 name = (const char *)item_value;
1007                         } else if (g_str_equal(key, "Host") == TRUE) {
1008                                 host = (const char *)item_value;
1009                         } else if (g_str_equal(key, "VPN.Domain") == TRUE) {
1010                                 domain = (const char *)item_value;
1011                         }
1012
1013                         DBG("%s %s", key, (char *)item_value);
1014
1015                         if (item_value != NULL)
1016                                 connman_dbus_dict_append_basic(&new_dict, key,
1017                                                 value_type, &item_value);
1018                         break;
1019                 case DBUS_TYPE_ARRAY:
1020                         if (g_str_equal(key, "Networks") == TRUE) {
1021                                 networks = get_user_networks(&value);
1022                                 connman_dbus_dict_append_array(&new_dict,
1023                                                         "UserRoutes",
1024                                                         DBUS_TYPE_DICT_ENTRY,
1025                                                         append_routes,
1026                                                         networks);
1027                         }
1028                         break;
1029                 }
1030
1031                 dbus_message_iter_next(&array);
1032         }
1033
1034         connman_dbus_dict_close(&new_iter, &new_dict);
1035
1036         DBG("VPN type %s name %s host %s domain %s networks %p",
1037                 type, name, host, domain, networks);
1038
1039         if (host == NULL || domain == NULL) {
1040                 err = -EINVAL;
1041                 goto done;
1042         }
1043
1044         if (type == NULL || name == NULL) {
1045                 err = -EOPNOTSUPP;
1046                 goto done;
1047         }
1048
1049         ident = g_strdup_printf("%s_%s", host, domain);
1050         set_dbus_ident(ident);
1051
1052         DBG("ident %s", ident);
1053
1054         data = g_hash_table_lookup(vpn_connections, ident);
1055         if (data != NULL) {
1056                 if (data->call != NULL) {
1057                         connman_error("Dbus call already pending");
1058                         err = -EINPROGRESS;
1059                         goto done;
1060                 }
1061         } else {
1062                 data = create_connection_data(ident);
1063                 if (data == NULL) {
1064                         err = -ENOMEM;
1065                         goto done;
1066                 }
1067
1068                 g_hash_table_insert(vpn_connections, g_strdup(ident), data);
1069         }
1070
1071         /*
1072          * User called net.connman.Manager.ConnectProvider if we are here.
1073          * So use the data from original message in the new msg.
1074          */
1075         me = g_strdup(dbus_message_get_destination(msg));
1076
1077         dbus_message_set_interface(new_msg, VPN_MANAGER_INTERFACE);
1078         dbus_message_set_path(new_msg, "/");
1079         dbus_message_set_destination(new_msg, VPN_SERVICE);
1080         dbus_message_set_sender(new_msg, me);
1081         dbus_message_set_member(new_msg, "Create");
1082
1083         result = dbus_connection_send_with_reply(connection, new_msg,
1084                                                 &call, DBUS_TIMEOUT);
1085         if (result == FALSE || call == NULL) {
1086                 err = -EIO;
1087                 goto done;
1088         }
1089
1090         dbus_pending_call_set_notify(call, configuration_create_reply,
1091                                                                 NULL, NULL);
1092         data->call = call;
1093
1094 done:
1095         dbus_message_unref(new_msg);
1096
1097         if (networks != NULL)
1098                 g_slist_free_full(networks, destroy_route);
1099
1100
1101         g_free(me);
1102         return err;
1103 }
1104
1105 static void set_route(struct connection_data *data, struct vpn_route *route)
1106 {
1107         if (route->family == AF_INET6) {
1108                 unsigned char prefix_len = atoi(route->netmask);
1109
1110                 connman_inet_add_ipv6_network_route(data->index,
1111                                                         route->network,
1112                                                         route->gateway,
1113                                                         prefix_len);
1114         } else {
1115                 connman_inet_add_network_route(data->index, route->network,
1116                                                 route->gateway,
1117                                                 route->netmask);
1118         }
1119 }
1120
1121 static int set_routes(struct connman_provider *provider,
1122                                 enum connman_provider_route_type type)
1123 {
1124         struct connection_data *data;
1125         GHashTableIter iter;
1126         gpointer value, key;
1127
1128         DBG("provider %p", provider);
1129
1130         data = connman_provider_get_data(provider);
1131         if (data == NULL)
1132                 return -EINVAL;
1133
1134         if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
1135                                         type == CONNMAN_PROVIDER_ROUTE_USER) {
1136                 g_hash_table_iter_init(&iter, data->user_routes);
1137
1138                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
1139                         set_route(data, value);
1140         }
1141
1142         if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
1143                                 type == CONNMAN_PROVIDER_ROUTE_SERVER) {
1144                 g_hash_table_iter_init(&iter, data->server_routes);
1145
1146                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
1147                         set_route(data, value);
1148         }
1149
1150         return 0;
1151 }
1152
1153 static connman_bool_t check_routes(struct connman_provider *provider)
1154 {
1155         struct connection_data *data;
1156
1157         DBG("provider %p", provider);
1158
1159         data = connman_provider_get_data(provider);
1160         if (data == NULL)
1161                 return FALSE;
1162
1163         if (data->user_routes != NULL &&
1164                         g_hash_table_size(data->user_routes) > 0)
1165                 return TRUE;
1166
1167         if (data->server_routes != NULL &&
1168                         g_hash_table_size(data->server_routes) > 0)
1169                 return TRUE;
1170
1171         return FALSE;
1172 }
1173
1174 static struct connman_provider_driver provider_driver = {
1175         .name = "VPN",
1176         .type = CONNMAN_PROVIDER_TYPE_VPN,
1177         .probe = provider_probe,
1178         .remove = provider_remove,
1179         .connect = provider_connect,
1180         .disconnect = provider_disconnect,
1181         .set_property = set_string,
1182         .get_property = get_string,
1183         .create = create_configuration,
1184         .set_routes = set_routes,
1185         .check_routes = check_routes,
1186 };
1187
1188 static void destroy_provider(struct connection_data *data)
1189 {
1190         DBG("data %p", data);
1191
1192         if (g_str_equal(data->state, "ready") == TRUE ||
1193                         g_str_equal(data->state, "configuration") == TRUE)
1194                 connman_provider_disconnect(data->provider);
1195
1196         if (data->call != NULL)
1197                 dbus_pending_call_cancel(data->call);
1198
1199         connman_provider_put(data->provider);
1200
1201         data->provider = NULL;
1202 }
1203
1204 static void connection_destroy(gpointer hash_data)
1205 {
1206         struct connection_data *data = hash_data;
1207
1208         DBG("data %p", data);
1209
1210         if (data->provider != NULL)
1211                 destroy_provider(data);
1212
1213         g_free(data->path);
1214         g_free(data->state);
1215         g_free(data->type);
1216         g_free(data->name);
1217         g_free(data->host);
1218         g_free(data->domain);
1219         g_hash_table_destroy(data->server_routes);
1220         g_hash_table_destroy(data->user_routes);
1221         g_strfreev(data->nameservers);
1222         g_hash_table_destroy(data->setting_strings);
1223         connman_ipaddress_free(data->ip);
1224
1225         g_free(data);
1226 }
1227
1228 static void vpnd_created(DBusConnection *conn, void *user_data)
1229 {
1230         DBG("connection %p", conn);
1231
1232         if (starting_vpnd == TRUE) {
1233                 vpn_connections = g_hash_table_new_full(g_str_hash,
1234                                                 g_str_equal,
1235                                                 g_free, connection_destroy);
1236                 get_connections(user_data);
1237                 starting_vpnd = FALSE;
1238         }
1239 }
1240
1241 static void vpnd_removed(DBusConnection *conn, void *user_data)
1242 {
1243         DBG("connection %p", conn);
1244
1245         g_hash_table_destroy(vpn_connections);
1246         vpn_connections = NULL;
1247         starting_vpnd = TRUE;
1248 }
1249
1250 static void remove_connection(DBusConnection *conn, const char *path)
1251 {
1252         DBG("path %s", path);
1253
1254         g_hash_table_remove(vpn_connections, path);
1255 }
1256
1257 static gboolean connection_removed(DBusConnection *conn, DBusMessage *message,
1258                                 void *user_data)
1259 {
1260         const char *path;
1261         const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
1262
1263         if (dbus_message_has_signature(message, signature) == FALSE) {
1264                 connman_error("vpn removed signature \"%s\" does not match "
1265                                                         "expected \"%s\"",
1266                         dbus_message_get_signature(message), signature);
1267                 return TRUE;
1268         }
1269
1270         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1271                                 DBUS_TYPE_INVALID);
1272         remove_connection(conn, path);
1273         return TRUE;
1274 }
1275
1276 static gboolean connection_added(DBusConnection *conn, DBusMessage *message,
1277                                 void *user_data)
1278 {
1279         DBusMessageIter iter, properties;
1280         const char *path;
1281         const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING
1282                 DBUS_TYPE_ARRAY_AS_STRING
1283                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1284                 DBUS_TYPE_STRING_AS_STRING
1285                 DBUS_TYPE_VARIANT_AS_STRING
1286                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
1287
1288         if (dbus_message_has_signature(message, signature) == FALSE) {
1289                 connman_error("vpn ConnectionAdded signature \"%s\" does not "
1290                                                 "match expected \"%s\"",
1291                         dbus_message_get_signature(message), signature);
1292                 return TRUE;
1293         }
1294
1295         DBG("");
1296
1297         if (dbus_message_iter_init(message, &iter) == FALSE)
1298                 return TRUE;
1299
1300         dbus_message_iter_get_basic(&iter, &path);
1301
1302         dbus_message_iter_next(&iter);
1303         dbus_message_iter_recurse(&iter, &properties);
1304
1305         add_connection(path, &properties, user_data);
1306
1307         return TRUE;
1308 }
1309
1310 static int save_route(GHashTable *routes, int family, const char *network,
1311                         const char *netmask, const char *gateway)
1312 {
1313         struct vpn_route *route;
1314         char *key = g_strdup_printf("%d/%s/%s", family, network, netmask);
1315
1316         DBG("family %d network %s netmask %s", family, network, netmask);
1317
1318         route = g_hash_table_lookup(routes, key);
1319         if (route == NULL) {
1320                 route = g_try_new0(struct vpn_route, 1);
1321                 if (route == NULL) {
1322                         connman_error("out of memory");
1323                         return -ENOMEM;
1324                 }
1325
1326                 route->family = family;
1327                 route->network = g_strdup(network);
1328                 route->netmask = g_strdup(netmask);
1329                 route->gateway = g_strdup(gateway);
1330
1331                 g_hash_table_replace(routes, key, route);
1332         } else
1333                 g_free(key);
1334
1335         return 0;
1336 }
1337
1338 static int read_route_dict(GHashTable *routes, DBusMessageIter *dicts)
1339 {
1340         DBusMessageIter dict;
1341         const char *network, *netmask, *gateway;
1342         int family;
1343
1344         dbus_message_iter_recurse(dicts, &dict);
1345
1346         network = netmask = gateway = NULL;
1347         family = PF_UNSPEC;
1348
1349         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1350
1351                 DBusMessageIter entry, value;
1352                 const char *key;
1353
1354                 dbus_message_iter_recurse(&dict, &entry);
1355                 dbus_message_iter_get_basic(&entry, &key);
1356
1357                 dbus_message_iter_next(&entry);
1358                 dbus_message_iter_recurse(&entry, &value);
1359
1360                 if (g_str_equal(key, "ProtocolFamily") == TRUE) {
1361                         int pf;
1362                         dbus_message_iter_get_basic(&value, &pf);
1363                         switch (pf) {
1364                         case 4:
1365                                 family = AF_INET;
1366                                 break;
1367                         case 6:
1368                                 family = AF_INET6;
1369                                 break;
1370                         }
1371                         DBG("family %d", family);
1372                 } else if (g_str_equal(key, "Netmask") == TRUE) {
1373                         dbus_message_iter_get_basic(&value, &netmask);
1374                         DBG("netmask %s", netmask);
1375                 } else if (g_str_equal(key, "Network") == TRUE) {
1376                         dbus_message_iter_get_basic(&value, &network);
1377                         DBG("host %s", network);
1378                 } else if (g_str_equal(key, "Gateway") == TRUE) {
1379                         dbus_message_iter_get_basic(&value, &gateway);
1380                         DBG("gateway %s", gateway);
1381                 }
1382
1383                 dbus_message_iter_next(&dict);
1384         }
1385
1386         if (netmask == NULL || network == NULL || gateway == NULL) {
1387                 DBG("Value missing.");
1388                 return -EINVAL;
1389         }
1390
1391         return save_route(routes, family, network, netmask, gateway);
1392 }
1393
1394 static int routes_changed(DBusMessageIter *array, GHashTable *routes)
1395 {
1396         DBusMessageIter entry;
1397         int ret = -EINVAL;
1398
1399         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) {
1400                 DBG("Expecting array, ignoring routes.");
1401                 return -EINVAL;
1402         }
1403
1404         while (dbus_message_iter_get_arg_type(array) == DBUS_TYPE_ARRAY) {
1405
1406                 dbus_message_iter_recurse(array, &entry);
1407
1408                 while (dbus_message_iter_get_arg_type(&entry) ==
1409                                                         DBUS_TYPE_STRUCT) {
1410                         DBusMessageIter dicts;
1411
1412                         dbus_message_iter_recurse(&entry, &dicts);
1413
1414                         while (dbus_message_iter_get_arg_type(&dicts) ==
1415                                                         DBUS_TYPE_ARRAY) {
1416                                 int err = read_route_dict(routes, &dicts);
1417                                 if (ret != 0)
1418                                         ret = err;
1419                                 dbus_message_iter_next(&dicts);
1420                         }
1421
1422                         dbus_message_iter_next(&entry);
1423                 }
1424
1425                 dbus_message_iter_next(array);
1426         }
1427
1428         return ret;
1429 }
1430
1431 static gboolean property_changed(DBusConnection *conn,
1432                                 DBusMessage *message,
1433                                 void *user_data)
1434 {
1435         const char *path = dbus_message_get_path(message);
1436         struct connection_data *data = NULL;
1437         DBusMessageIter iter, value;
1438         connman_bool_t ip_set = FALSE;
1439         int err;
1440         char *str;
1441         const char *key;
1442         const char *signature = DBUS_TYPE_STRING_AS_STRING
1443                 DBUS_TYPE_VARIANT_AS_STRING;
1444
1445         if (dbus_message_has_signature(message, signature) == FALSE) {
1446                 connman_error("vpn property signature \"%s\" does not match "
1447                                                         "expected \"%s\"",
1448                         dbus_message_get_signature(message), signature);
1449                 return TRUE;
1450         }
1451
1452         data = g_hash_table_lookup(vpn_connections, path);
1453         if (data == NULL)
1454                 return TRUE;
1455
1456         if (dbus_message_iter_init(message, &iter) == FALSE)
1457                 return TRUE;
1458
1459         dbus_message_iter_get_basic(&iter, &key);
1460
1461         dbus_message_iter_next(&iter);
1462         dbus_message_iter_recurse(&iter, &value);
1463
1464         DBG("key %s", key);
1465
1466         if (g_str_equal(key, "State") == TRUE) {
1467                 dbus_message_iter_get_basic(&value, &str);
1468
1469                 DBG("%s %s -> %s", data->path, data->state, str);
1470
1471                 if (g_str_equal(data->state, str) == TRUE)
1472                         return TRUE;
1473
1474                 g_free(data->state);
1475                 data->state = g_strdup(str);
1476
1477                 set_provider_state(data);
1478         } else if (g_str_equal(key, "Index") == TRUE) {
1479                 dbus_message_iter_get_basic(&value, &data->index);
1480                 connman_provider_set_index(data->provider, data->index);
1481         } else if (g_str_equal(key, "IPv4") == TRUE) {
1482                 err = extract_ip(&value, AF_INET, data);
1483                 ip_set = TRUE;
1484         } else if (g_str_equal(key, "IPv6") == TRUE) {
1485                 err = extract_ip(&value, AF_INET6, data);
1486                 ip_set = TRUE;
1487         } else if (g_str_equal(key, "ServerRoutes") == TRUE) {
1488                 err = routes_changed(&value, data->server_routes);
1489                 /*
1490                  * Note that the vpnd will delay the route sending a bit
1491                  * (in order to collect the routes from VPN client),
1492                  * so we might have got the State changed property before
1493                  * we got ServerRoutes. This means that we must try to set
1494                  * the routes here because they would be left unset otherwise.
1495                  */
1496                 if (err == 0)
1497                         set_routes(data->provider,
1498                                                 CONNMAN_PROVIDER_ROUTE_SERVER);
1499         } else if (g_str_equal(key, "UserRoutes") == TRUE) {
1500                 err = routes_changed(&value, data->user_routes);
1501                 if (err == 0)
1502                         set_routes(data->provider,
1503                                                 CONNMAN_PROVIDER_ROUTE_USER);
1504         } else if (g_str_equal(key, "Nameservers") == TRUE) {
1505                 extract_nameservers(&value, data);
1506         }
1507
1508         if (ip_set == TRUE && err == 0) {
1509                 err = connman_provider_set_ipaddress(data->provider, data->ip);
1510                 if (err < 0)
1511                         DBG("setting provider IP address failed (%s/%d)",
1512                                 strerror(-err), -err);
1513         }
1514
1515         return TRUE;
1516 }
1517
1518 static int vpn_init(void)
1519 {
1520         int err;
1521
1522         connection = connman_dbus_get_connection();
1523         if (connection == NULL)
1524                 return -EIO;
1525
1526         watch = g_dbus_add_service_watch(connection, VPN_SERVICE,
1527                         vpnd_created, vpnd_removed, &provider_driver, NULL);
1528
1529         added_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1530                                         VPN_MANAGER_INTERFACE,
1531                                         CONNECTION_ADDED, connection_added,
1532                                         &provider_driver, NULL);
1533
1534         removed_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1535                                         VPN_MANAGER_INTERFACE,
1536                                         CONNECTION_REMOVED, connection_removed,
1537                                         NULL, NULL);
1538
1539         property_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1540                                         VPN_CONNECTION_INTERFACE,
1541                                         PROPERTY_CHANGED, property_changed,
1542                                         NULL, NULL);
1543
1544         if (added_watch == 0 || removed_watch == 0 || property_watch == 0) {
1545                 err = -EIO;
1546                 goto remove;
1547         }
1548
1549         err = connman_provider_driver_register(&provider_driver);
1550         if (err == 0)
1551                 vpnd_created(connection, &provider_driver);
1552
1553         return err;
1554
1555 remove:
1556         g_dbus_remove_watch(connection, watch);
1557         g_dbus_remove_watch(connection, added_watch);
1558         g_dbus_remove_watch(connection, removed_watch);
1559         g_dbus_remove_watch(connection, property_watch);
1560
1561         dbus_connection_unref(connection);
1562
1563         return err;
1564 }
1565
1566 static void vpn_exit(void)
1567 {
1568         g_dbus_remove_watch(connection, watch);
1569         g_dbus_remove_watch(connection, added_watch);
1570         g_dbus_remove_watch(connection, removed_watch);
1571         g_dbus_remove_watch(connection, property_watch);
1572
1573         connman_provider_driver_unregister(&provider_driver);
1574
1575         g_hash_table_destroy(vpn_connections);
1576
1577         dbus_connection_unref(connection);
1578 }
1579
1580 CONNMAN_PLUGIN_DEFINE(vpn, "VPN plugin", VERSION,
1581                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, vpn_init, vpn_exit)