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