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