provider: Set nameservers if we receive them 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         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->nameservers != NULL)
647                 connman_provider_set_nameservers(data->provider,
648                                                 data->nameservers);
649
650         if (data->connect_pending == TRUE)
651                 connect_provider(data, data->cb_data);
652
653         return;
654
655 out:
656         DBG("removing %s", data->ident);
657         g_hash_table_remove(vpn_connections, data->ident);
658 }
659
660 static void get_connections_reply(DBusPendingCall *call, void *user_data)
661 {
662         DBusMessage *reply;
663         DBusError error;
664         DBusMessageIter array, dict;
665         const char *signature = DBUS_TYPE_ARRAY_AS_STRING
666                 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
667                 DBUS_TYPE_OBJECT_PATH_AS_STRING
668                 DBUS_TYPE_ARRAY_AS_STRING
669                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
670                 DBUS_TYPE_STRING_AS_STRING
671                 DBUS_TYPE_VARIANT_AS_STRING
672                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
673                 DBUS_STRUCT_END_CHAR_AS_STRING;
674
675         if (dbus_pending_call_get_completed(call) == FALSE)
676                 return;
677
678         DBG("");
679
680         reply = dbus_pending_call_steal_reply(call);
681
682         dbus_error_init(&error);
683
684         if (dbus_set_error_from_message(&error, reply) == TRUE) {
685                 connman_error("%s", error.message);
686                 dbus_error_free(&error);
687                 goto done;
688         }
689
690         if (dbus_message_has_signature(reply, signature) == FALSE) {
691                 connman_error("vpnd signature \"%s\" does not match "
692                                                         "expected \"%s\"",
693                         dbus_message_get_signature(reply), signature);
694                 goto done;
695         }
696
697         if (dbus_message_iter_init(reply, &array) == FALSE)
698                 goto done;
699
700         dbus_message_iter_recurse(&array, &dict);
701
702         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
703                 DBusMessageIter value, properties;
704                 const char *path;
705
706                 dbus_message_iter_recurse(&dict, &value);
707                 dbus_message_iter_get_basic(&value, &path);
708
709                 dbus_message_iter_next(&value);
710                 dbus_message_iter_recurse(&value, &properties);
711
712                 add_connection(path, &properties, user_data);
713
714                 dbus_message_iter_next(&dict);
715         }
716
717 done:
718         dbus_message_unref(reply);
719
720         dbus_pending_call_unref(call);
721 }
722
723 static int get_connections(void *user_data)
724 {
725         DBusPendingCall *call;
726         DBusMessage *message;
727
728         DBG("");
729
730         message = dbus_message_new_method_call(VPN_SERVICE, "/",
731                                         VPN_MANAGER_INTERFACE,
732                                         GET_CONNECTIONS);
733         if (message == NULL)
734                 return -ENOMEM;
735
736         if (dbus_connection_send_with_reply(connection, message,
737                                         &call, DBUS_TIMEOUT) == FALSE) {
738                 connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
739                                                         GET_CONNECTIONS);
740                 dbus_message_unref(message);
741                 return -EINVAL;
742         }
743
744         if (call == NULL) {
745                 dbus_message_unref(message);
746                 return -EINVAL;
747         }
748
749         dbus_pending_call_set_notify(call, get_connections_reply,
750                                                         user_data, NULL);
751
752         dbus_message_unref(message);
753
754         return -EINPROGRESS;
755 }
756
757 static int provider_probe(struct connman_provider *provider)
758 {
759         return 0;
760 }
761
762 static void remove_connection_reply(DBusPendingCall *call, void *user_data)
763 {
764         DBusMessage *reply;
765         DBusError error;
766
767         if (dbus_pending_call_get_completed(call) == FALSE)
768                 return;
769
770         DBG("");
771
772         reply = dbus_pending_call_steal_reply(call);
773
774         dbus_error_init(&error);
775
776         if (dbus_set_error_from_message(&error, reply) == TRUE) {
777                 /*
778                  * If the returned error is NotFound, it means that we
779                  * have actually removed the provider in vpnd already.
780                  */
781                 if (dbus_error_has_name(&error, CONNMAN_ERROR_INTERFACE
782                                                 ".NotFound") == FALSE)
783                         connman_error("%s", error.message);
784
785                 dbus_error_free(&error);
786         }
787
788         dbus_message_unref(reply);
789
790         dbus_pending_call_unref(call);
791 }
792
793 static int provider_remove(struct connman_provider *provider)
794 {
795         DBusPendingCall *call;
796         DBusMessage *message;
797         struct connection_data *data;
798
799         data = connman_provider_get_data(provider);
800
801         DBG("provider %p data %p", provider, data);
802
803         if (data == NULL) {
804                 /*
805                  * This means the provider is already removed,
806                  * just ignore the dbus in this case.
807                  */
808                 return -EALREADY;
809         }
810
811         /*
812          * When provider.c:provider_remove() calls this function,
813          * it will remove the provider itself after the call.
814          * This means that we cannot use the provider pointer later
815          * as it is no longer valid.
816          */
817         data->provider = NULL;
818
819         message = dbus_message_new_method_call(VPN_SERVICE, "/",
820                                         VPN_MANAGER_INTERFACE,
821                                         VPN_REMOVE);
822         if (message == NULL)
823                 return -ENOMEM;
824
825         dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &data->path,
826                                 NULL);
827
828         if (dbus_connection_send_with_reply(connection, message,
829                                         &call, DBUS_TIMEOUT) == FALSE) {
830                 connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
831                                                         VPN_REMOVE);
832                 dbus_message_unref(message);
833                 return -EINVAL;
834         }
835
836         if (call == NULL) {
837                 dbus_message_unref(message);
838                 return -EINVAL;
839         }
840
841         dbus_pending_call_set_notify(call, remove_connection_reply,
842                                                         NULL, NULL);
843
844         dbus_message_unref(message);
845
846         return 0;
847 }
848
849 static int provider_connect(struct connman_provider *provider)
850 {
851         struct connection_data *data;
852
853         data = connman_provider_get_data(provider);
854         if (data == NULL)
855                 return -EINVAL;
856
857         return connect_provider(data, NULL);
858 }
859
860 static void disconnect_reply(DBusPendingCall *call, void *user_data)
861 {
862         DBusMessage *reply;
863         DBusError error;
864
865         if (dbus_pending_call_get_completed(call) == FALSE)
866                 return;
867
868         DBG("user %p", user_data);
869
870         reply = dbus_pending_call_steal_reply(call);
871
872         dbus_error_init(&error);
873
874         if (dbus_set_error_from_message(&error, reply) == TRUE) {
875                 connman_error("%s", error.message);
876                 dbus_error_free(&error);
877                 goto done;
878         }
879
880 done:
881         dbus_message_unref(reply);
882
883         dbus_pending_call_unref(call);
884 }
885
886 static int disconnect_provider(struct connection_data *data)
887 {
888         DBusPendingCall *call;
889         DBusMessage *message;
890
891         DBG("data %p path %s", data, data->path);
892
893         message = dbus_message_new_method_call(VPN_SERVICE, data->path,
894                                         VPN_CONNECTION_INTERFACE,
895                                         VPN_DISCONNECT);
896         if (message == NULL)
897                 return -ENOMEM;
898
899         if (dbus_connection_send_with_reply(connection, message,
900                                         &call, DBUS_TIMEOUT) == FALSE) {
901                 connman_error("Unable to call %s.%s()",
902                         VPN_CONNECTION_INTERFACE, VPN_DISCONNECT);
903                 dbus_message_unref(message);
904                 return -EINVAL;
905         }
906
907         if (call == NULL) {
908                 dbus_message_unref(message);
909                 return -EINVAL;
910         }
911
912         dbus_pending_call_set_notify(call, disconnect_reply, NULL, NULL);
913
914         dbus_message_unref(message);
915
916         connman_provider_set_state(data->provider,
917                                         CONNMAN_PROVIDER_STATE_DISCONNECT);
918         /*
919          * We return 0 here instead of -EINPROGRESS because
920          * __connman_service_disconnect() needs to return something
921          * to gdbus so that gdbus will not call Disconnect() more
922          * than once. This way we do not need to pass the dbus reply
923          * message around the code.
924          */
925         return 0;
926 }
927
928 static int provider_disconnect(struct connman_provider *provider)
929 {
930         struct connection_data *data;
931
932         DBG("provider %p", provider);
933
934         data = connman_provider_get_data(provider);
935         if (data == NULL)
936                 return -EINVAL;
937
938         if (g_str_equal(data->state, "ready") == TRUE ||
939                         g_str_equal(data->state, "configuration") == TRUE)
940                 return disconnect_provider(data);
941
942         return 0;
943 }
944
945 static void configuration_create_reply(DBusPendingCall *call, void *user_data)
946 {
947         DBusMessage *reply;
948         DBusError error;
949         DBusMessageIter iter;
950         const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
951         const char *path;
952         char *ident;
953         struct connection_data *data;
954         struct config_create_data *cb_data = user_data;
955
956         if (dbus_pending_call_get_completed(call) == FALSE)
957                 return;
958
959         DBG("user %p", cb_data);
960
961         reply = dbus_pending_call_steal_reply(call);
962
963         dbus_error_init(&error);
964
965         if (dbus_set_error_from_message(&error, reply) == TRUE) {
966                 connman_error("dbus error: %s", error.message);
967                 dbus_error_free(&error);
968                 goto done;
969         }
970
971         if (dbus_message_has_signature(reply, signature) == FALSE) {
972                 connman_error("vpn configuration signature \"%s\" does not "
973                                                 "match expected \"%s\"",
974                         dbus_message_get_signature(reply), signature);
975                 goto done;
976         }
977
978         if (dbus_message_iter_init(reply, &iter) == FALSE)
979                 goto done;
980
981         dbus_message_iter_get_basic(&iter, &path);
982
983         /*
984          * Then try to connect the VPN as expected by ConnectProvider API
985          */
986         ident = get_ident(path);
987
988         data = g_hash_table_lookup(vpn_connections, ident);
989         if (data == NULL) {
990                 /*
991                  * Someone removed the data. We cannot really continue.
992                  */
993                 DBG("Pending data not found for %s, cannot continue!", ident);
994         } else {
995                 data->call = NULL;
996                 data->connect_pending = TRUE;
997
998                 if (data->cb_data == NULL)
999                         data->cb_data = cb_data;
1000                 else
1001                         DBG("Connection callback data already in use!");
1002
1003                 /*
1004                  * Connection is created in add_connections() after
1005                  * we have received the ConnectionAdded signal.
1006                  */
1007
1008                 DBG("cb %p msg %p", data->cb_data,
1009                         data->cb_data ? data->cb_data->message : NULL);
1010         }
1011
1012 done:
1013         dbus_message_unref(reply);
1014
1015         dbus_pending_call_unref(call);
1016 }
1017
1018 static void set_dbus_ident(char *ident)
1019 {
1020         int i, len = strlen(ident);
1021
1022         for (i = 0; i < len; i++) {
1023                 if (ident[i] >= '0' && ident[i] <= '9')
1024                         continue;
1025                 if (ident[i] >= 'a' && ident[i] <= 'z')
1026                         continue;
1027                 if (ident[i] >= 'A' && ident[i] <= 'Z')
1028                         continue;
1029                 ident[i] = '_';
1030         }
1031 }
1032
1033 static struct vpn_route *parse_user_route(const char *user_route)
1034 {
1035         char *network, *netmask;
1036         struct vpn_route *route = NULL;
1037         int family = PF_UNSPEC;
1038         char **elems = g_strsplit(user_route, "/", 0);
1039
1040         if (elems == NULL)
1041                 return NULL;
1042
1043         network = elems[0];
1044         if (network == NULL || *network == '\0') {
1045                 DBG("no network/netmask set");
1046                 goto out;
1047         }
1048
1049         netmask = elems[1];
1050         if (netmask != NULL && *netmask == '\0') {
1051                 DBG("no netmask set");
1052                 goto out;
1053         }
1054
1055         if (g_strrstr(network, ":") != NULL)
1056                 family = AF_INET6;
1057         else if (g_strrstr(network, ".") != NULL) {
1058                 family = AF_INET;
1059
1060                 if (g_strrstr(netmask, ".") == NULL) {
1061                         /* We have netmask length */
1062                         in_addr_t addr;
1063                         struct in_addr netmask_in;
1064                         unsigned char prefix_len = 32;
1065
1066                         if (netmask != NULL) {
1067                                 char *ptr;
1068                                 long int value = strtol(netmask, &ptr, 10);
1069                                 if (ptr != netmask && *ptr == '\0' &&
1070                                                                 value <= 32)
1071                                         prefix_len = value;
1072                         }
1073
1074                         addr = 0xffffffff << (32 - prefix_len);
1075                         netmask_in.s_addr = htonl(addr);
1076                         netmask = inet_ntoa(netmask_in);
1077
1078                         DBG("network %s netmask %s", network, netmask);
1079                 }
1080         }
1081
1082         route = g_try_new(struct vpn_route, 1);
1083         if (route == NULL)
1084                 goto out;
1085
1086         route->network = g_strdup(network);
1087         route->netmask = g_strdup(netmask);
1088         route->gateway = NULL;
1089         route->family = family;
1090
1091 out:
1092         g_strfreev(elems);
1093         return route;
1094 }
1095
1096 static GSList *get_user_networks(DBusMessageIter *array)
1097 {
1098         DBusMessageIter entry;
1099         GSList *list = NULL;
1100
1101         dbus_message_iter_recurse(array, &entry);
1102
1103         while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1104                 const char *val;
1105                 struct vpn_route *route;
1106
1107                 dbus_message_iter_get_basic(&entry, &val);
1108
1109                 route = parse_user_route(val);
1110                 if (route != NULL)
1111                         list = g_slist_prepend(list, route);
1112
1113                 dbus_message_iter_next(&entry);
1114         }
1115
1116         return list;
1117 }
1118
1119 static void append_route(DBusMessageIter *iter, void *user_data)
1120 {
1121         struct vpn_route *route = user_data;
1122         DBusMessageIter item;
1123         int family = 0;
1124
1125         connman_dbus_dict_open(iter, &item);
1126
1127         if (route == NULL)
1128                 goto empty_dict;
1129
1130         if (route->family == AF_INET)
1131                 family = 4;
1132         else if (route->family == AF_INET6)
1133                 family = 6;
1134
1135         if (family != 0)
1136                 connman_dbus_dict_append_basic(&item, "ProtocolFamily",
1137                                         DBUS_TYPE_INT32, &family);
1138
1139         if (route->network != NULL)
1140                 connman_dbus_dict_append_basic(&item, "Network",
1141                                         DBUS_TYPE_STRING, &route->network);
1142
1143         if (route->netmask != NULL)
1144                 connman_dbus_dict_append_basic(&item, "Netmask",
1145                                         DBUS_TYPE_STRING, &route->netmask);
1146
1147         if (route->gateway != NULL)
1148                 connman_dbus_dict_append_basic(&item, "Gateway",
1149                                         DBUS_TYPE_STRING, &route->gateway);
1150
1151 empty_dict:
1152         connman_dbus_dict_close(iter, &item);
1153 }
1154
1155 static void append_routes(DBusMessageIter *iter, void *user_data)
1156 {
1157         GSList *list, *routes = user_data;
1158
1159         DBG("routes %p", routes);
1160
1161         for (list = routes; list != NULL; list = g_slist_next(list)) {
1162                 DBusMessageIter dict;
1163                 struct vpn_route *route = list->data;
1164
1165                 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL,
1166                                                 &dict);
1167                 append_route(&dict, route);
1168                 dbus_message_iter_close_container(iter, &dict);
1169         }
1170 }
1171
1172 static int create_configuration(DBusMessage *msg, connection_ready_cb callback)
1173 {
1174         DBusMessage *new_msg = NULL;
1175         DBusPendingCall *call;
1176         DBusMessageIter iter, array, new_iter, new_dict;
1177         const char *type = NULL, *name = NULL;
1178         const char *host = NULL, *domain = NULL;
1179         char *ident, *me = NULL;
1180         int err = 0;
1181         dbus_bool_t result;
1182         struct connection_data *data;
1183         struct config_create_data *user_data = NULL;
1184         GSList *networks = NULL;
1185
1186         /*
1187          * We copy the old message data into new message. We cannot
1188          * just use the old message as is because the user route
1189          * information is not in the same format in vpnd.
1190          */
1191         new_msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
1192         dbus_message_iter_init_append(new_msg, &new_iter);
1193         connman_dbus_dict_open(&new_iter, &new_dict);
1194
1195         dbus_message_iter_init(msg, &iter);
1196         dbus_message_iter_recurse(&iter, &array);
1197
1198         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1199                 DBusMessageIter entry, value;
1200                 void *item_value;
1201                 const char *key;
1202                 int value_type;
1203
1204                 dbus_message_iter_recurse(&array, &entry);
1205                 dbus_message_iter_get_basic(&entry, &key);
1206
1207                 dbus_message_iter_next(&entry);
1208                 dbus_message_iter_recurse(&entry, &value);
1209
1210                 value_type = dbus_message_iter_get_arg_type(&value);
1211                 item_value = NULL;
1212
1213                 switch (value_type) {
1214                 case DBUS_TYPE_STRING:
1215                         dbus_message_iter_get_basic(&value, &item_value);
1216
1217                         if (g_str_equal(key, "Type") == TRUE) {
1218                                 type = (const char *)item_value;
1219                         } else if (g_str_equal(key, "Name") == TRUE) {
1220                                 name = (const char *)item_value;
1221                         } else if (g_str_equal(key, "Host") == TRUE) {
1222                                 host = (const char *)item_value;
1223                         } else if (g_str_equal(key, "VPN.Domain") == TRUE) {
1224                                 domain = (const char *)item_value;
1225                         }
1226
1227                         DBG("%s %s", key, (char *)item_value);
1228
1229                         if (item_value != NULL)
1230                                 connman_dbus_dict_append_basic(&new_dict, key,
1231                                                 value_type, &item_value);
1232                         break;
1233                 case DBUS_TYPE_ARRAY:
1234                         if (g_str_equal(key, "Networks") == TRUE) {
1235                                 networks = get_user_networks(&value);
1236                                 connman_dbus_dict_append_array(&new_dict,
1237                                                         "UserRoutes",
1238                                                         DBUS_TYPE_DICT_ENTRY,
1239                                                         append_routes,
1240                                                         networks);
1241                         }
1242                         break;
1243                 }
1244
1245                 dbus_message_iter_next(&array);
1246         }
1247
1248         connman_dbus_dict_close(&new_iter, &new_dict);
1249
1250         DBG("VPN type %s name %s host %s domain %s networks %p",
1251                 type, name, host, domain, networks);
1252
1253         if (host == NULL || domain == NULL) {
1254                 err = -EINVAL;
1255                 goto done;
1256         }
1257
1258         if (type == NULL || name == NULL) {
1259                 err = -EOPNOTSUPP;
1260                 goto done;
1261         }
1262
1263         ident = g_strdup_printf("%s_%s", host, domain);
1264         set_dbus_ident(ident);
1265
1266         DBG("ident %s", ident);
1267
1268         data = g_hash_table_lookup(vpn_connections, ident);
1269         if (data != NULL) {
1270                 if (data->call != NULL || data->cb_data != NULL) {
1271                         DBG("create configuration call already pending");
1272                         err = -EINPROGRESS;
1273                         goto done;
1274                 }
1275         } else {
1276                 char *path = g_strdup_printf("%s/connection/%s", VPN_PATH,
1277                                                                 ident);
1278                 data = create_connection_data(path);
1279                 g_free(path);
1280
1281                 if (data == NULL) {
1282                         err = -ENOMEM;
1283                         goto done;
1284                 }
1285
1286                 g_hash_table_insert(vpn_connections, g_strdup(ident), data);
1287         }
1288
1289         /*
1290          * User called net.connman.Manager.ConnectProvider if we are here.
1291          * So use the data from original message in the new msg.
1292          */
1293         me = g_strdup(dbus_message_get_destination(msg));
1294
1295         dbus_message_set_interface(new_msg, VPN_MANAGER_INTERFACE);
1296         dbus_message_set_path(new_msg, "/");
1297         dbus_message_set_destination(new_msg, VPN_SERVICE);
1298         dbus_message_set_sender(new_msg, me);
1299         dbus_message_set_member(new_msg, "Create");
1300
1301         user_data = g_try_new0(struct config_create_data, 1);
1302         if (user_data == NULL) {
1303                 err = -ENOMEM;
1304                 goto done;
1305         }
1306
1307         user_data->callback = callback;
1308         user_data->message = dbus_message_ref(msg);
1309         user_data->path = NULL;
1310
1311         DBG("cb %p msg %p", user_data, msg);
1312
1313         result = dbus_connection_send_with_reply(connection, new_msg,
1314                                                 &call, DBUS_TIMEOUT);
1315         if (result == FALSE || call == NULL) {
1316                 err = -EIO;
1317                 goto done;
1318         }
1319
1320         dbus_pending_call_set_notify(call, configuration_create_reply,
1321                                                         user_data, NULL);
1322         data->call = call;
1323
1324 done:
1325         if (new_msg != NULL)
1326                 dbus_message_unref(new_msg);
1327
1328         if (networks != NULL)
1329                 g_slist_free_full(networks, destroy_route);
1330
1331         g_free(me);
1332         return err;
1333 }
1334
1335 static connman_bool_t check_host(char **hosts, char *host)
1336 {
1337         int i;
1338
1339         if (hosts == NULL)
1340                 return FALSE;
1341
1342         for (i = 0; hosts[i] != NULL; i++) {
1343                 if (g_strcmp0(hosts[i], host) == 0)
1344                         return TRUE;
1345         }
1346
1347         return FALSE;
1348 }
1349
1350 static void set_route(struct connection_data *data, struct vpn_route *route)
1351 {
1352         /*
1353          * If the VPN administrator/user has given a route to
1354          * VPN server, then we must discard that because the
1355          * server cannot be contacted via VPN tunnel.
1356          */
1357         if (check_host(data->host_ip, route->network) == TRUE) {
1358                 DBG("Discarding VPN route to %s via %s at index %d",
1359                         route->network, route->gateway, data->index);
1360                 return;
1361         }
1362
1363         if (route->family == AF_INET6) {
1364                 unsigned char prefix_len = atoi(route->netmask);
1365
1366                 connman_inet_add_ipv6_network_route(data->index,
1367                                                         route->network,
1368                                                         route->gateway,
1369                                                         prefix_len);
1370         } else {
1371                 connman_inet_add_network_route(data->index, route->network,
1372                                                 route->gateway,
1373                                                 route->netmask);
1374         }
1375 }
1376
1377 static int set_routes(struct connman_provider *provider,
1378                                 enum connman_provider_route_type type)
1379 {
1380         struct connection_data *data;
1381         GHashTableIter iter;
1382         gpointer value, key;
1383
1384         DBG("provider %p", provider);
1385
1386         data = connman_provider_get_data(provider);
1387         if (data == NULL)
1388                 return -EINVAL;
1389
1390         if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
1391                                         type == CONNMAN_PROVIDER_ROUTE_USER) {
1392                 g_hash_table_iter_init(&iter, data->user_routes);
1393
1394                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
1395                         set_route(data, value);
1396         }
1397
1398         if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
1399                                 type == CONNMAN_PROVIDER_ROUTE_SERVER) {
1400                 g_hash_table_iter_init(&iter, data->server_routes);
1401
1402                 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
1403                         set_route(data, value);
1404         }
1405
1406         return 0;
1407 }
1408
1409 static connman_bool_t check_routes(struct connman_provider *provider)
1410 {
1411         struct connection_data *data;
1412
1413         DBG("provider %p", provider);
1414
1415         data = connman_provider_get_data(provider);
1416         if (data == NULL)
1417                 return FALSE;
1418
1419         if (data->user_routes != NULL &&
1420                         g_hash_table_size(data->user_routes) > 0)
1421                 return TRUE;
1422
1423         if (data->server_routes != NULL &&
1424                         g_hash_table_size(data->server_routes) > 0)
1425                 return TRUE;
1426
1427         return FALSE;
1428 }
1429
1430 static struct connman_provider_driver provider_driver = {
1431         .name = "VPN",
1432         .type = CONNMAN_PROVIDER_TYPE_VPN,
1433         .probe = provider_probe,
1434         .remove = provider_remove,
1435         .connect = provider_connect,
1436         .disconnect = provider_disconnect,
1437         .set_property = set_string,
1438         .get_property = get_string,
1439         .create = create_configuration,
1440         .set_routes = set_routes,
1441         .check_routes = check_routes,
1442 };
1443
1444 static void destroy_provider(struct connection_data *data)
1445 {
1446         DBG("data %p", data);
1447
1448         if (g_str_equal(data->state, "ready") == TRUE ||
1449                         g_str_equal(data->state, "configuration") == TRUE)
1450                 connman_provider_disconnect(data->provider);
1451
1452         if (data->call != NULL)
1453                 dbus_pending_call_cancel(data->call);
1454
1455         connman_provider_set_data(data->provider, NULL);
1456
1457         connman_provider_remove(data->provider);
1458
1459         data->provider = NULL;
1460 }
1461
1462 static void connection_destroy(gpointer hash_data)
1463 {
1464         struct connection_data *data = hash_data;
1465
1466         DBG("data %p", data);
1467
1468         if (data->provider != NULL)
1469                 destroy_provider(data);
1470
1471         g_free(data->path);
1472         g_free(data->ident);
1473         g_free(data->state);
1474         g_free(data->type);
1475         g_free(data->name);
1476         g_free(data->host);
1477         g_free(data->domain);
1478         g_hash_table_destroy(data->server_routes);
1479         g_hash_table_destroy(data->user_routes);
1480         g_strfreev(data->nameservers);
1481         g_hash_table_destroy(data->setting_strings);
1482         connman_ipaddress_free(data->ip);
1483
1484         cancel_host_resolv(data);
1485
1486         g_free(data);
1487 }
1488
1489 static void vpnd_created(DBusConnection *conn, void *user_data)
1490 {
1491         DBG("connection %p", conn);
1492
1493         get_connections(user_data);
1494 }
1495
1496 static void vpnd_removed(DBusConnection *conn, void *user_data)
1497 {
1498         DBG("connection %p", conn);
1499
1500         g_hash_table_remove_all(vpn_connections);
1501 }
1502
1503 static void remove_connection(DBusConnection *conn, const char *path)
1504 {
1505         DBG("path %s", path);
1506
1507         g_hash_table_remove(vpn_connections, get_ident(path));
1508 }
1509
1510 static gboolean connection_removed(DBusConnection *conn, DBusMessage *message,
1511                                 void *user_data)
1512 {
1513         const char *path;
1514         const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
1515         struct connection_data *data;
1516
1517         if (dbus_message_has_signature(message, signature) == FALSE) {
1518                 connman_error("vpn removed signature \"%s\" does not match "
1519                                                         "expected \"%s\"",
1520                         dbus_message_get_signature(message), signature);
1521                 return TRUE;
1522         }
1523
1524         dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1525                                 DBUS_TYPE_INVALID);
1526
1527         data = g_hash_table_lookup(vpn_connections, get_ident(path));
1528         if (data != NULL)
1529                 remove_connection(conn, path);
1530
1531         return TRUE;
1532 }
1533
1534 static gboolean connection_added(DBusConnection *conn, DBusMessage *message,
1535                                 void *user_data)
1536 {
1537         DBusMessageIter iter, properties;
1538         const char *path;
1539         const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING
1540                 DBUS_TYPE_ARRAY_AS_STRING
1541                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1542                 DBUS_TYPE_STRING_AS_STRING
1543                 DBUS_TYPE_VARIANT_AS_STRING
1544                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
1545
1546         if (dbus_message_has_signature(message, signature) == FALSE) {
1547                 connman_error("vpn ConnectionAdded signature \"%s\" does not "
1548                                                 "match expected \"%s\"",
1549                         dbus_message_get_signature(message), signature);
1550                 return TRUE;
1551         }
1552
1553         DBG("");
1554
1555         if (dbus_message_iter_init(message, &iter) == FALSE)
1556                 return TRUE;
1557
1558         dbus_message_iter_get_basic(&iter, &path);
1559
1560         dbus_message_iter_next(&iter);
1561         dbus_message_iter_recurse(&iter, &properties);
1562
1563         add_connection(path, &properties, user_data);
1564
1565         return TRUE;
1566 }
1567
1568 static int save_route(GHashTable *routes, int family, const char *network,
1569                         const char *netmask, const char *gateway)
1570 {
1571         struct vpn_route *route;
1572         char *key = g_strdup_printf("%d/%s/%s", family, network, netmask);
1573
1574         DBG("family %d network %s netmask %s", family, network, netmask);
1575
1576         route = g_hash_table_lookup(routes, key);
1577         if (route == NULL) {
1578                 route = g_try_new0(struct vpn_route, 1);
1579                 if (route == NULL) {
1580                         connman_error("out of memory");
1581                         return -ENOMEM;
1582                 }
1583
1584                 route->family = family;
1585                 route->network = g_strdup(network);
1586                 route->netmask = g_strdup(netmask);
1587                 route->gateway = g_strdup(gateway);
1588
1589                 g_hash_table_replace(routes, key, route);
1590         } else
1591                 g_free(key);
1592
1593         return 0;
1594 }
1595
1596 static int read_route_dict(GHashTable *routes, DBusMessageIter *dicts)
1597 {
1598         DBusMessageIter dict;
1599         const char *network, *netmask, *gateway;
1600         int family;
1601
1602         dbus_message_iter_recurse(dicts, &dict);
1603
1604         network = netmask = gateway = NULL;
1605         family = PF_UNSPEC;
1606
1607         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1608
1609                 DBusMessageIter entry, value;
1610                 const char *key;
1611
1612                 dbus_message_iter_recurse(&dict, &entry);
1613                 dbus_message_iter_get_basic(&entry, &key);
1614
1615                 dbus_message_iter_next(&entry);
1616                 dbus_message_iter_recurse(&entry, &value);
1617
1618                 if (g_str_equal(key, "ProtocolFamily") == TRUE) {
1619                         int pf;
1620                         dbus_message_iter_get_basic(&value, &pf);
1621                         switch (pf) {
1622                         case 4:
1623                                 family = AF_INET;
1624                                 break;
1625                         case 6:
1626                                 family = AF_INET6;
1627                                 break;
1628                         }
1629                         DBG("family %d", family);
1630                 } else if (g_str_equal(key, "Netmask") == TRUE) {
1631                         dbus_message_iter_get_basic(&value, &netmask);
1632                         DBG("netmask %s", netmask);
1633                 } else if (g_str_equal(key, "Network") == TRUE) {
1634                         dbus_message_iter_get_basic(&value, &network);
1635                         DBG("host %s", network);
1636                 } else if (g_str_equal(key, "Gateway") == TRUE) {
1637                         dbus_message_iter_get_basic(&value, &gateway);
1638                         DBG("gateway %s", gateway);
1639                 }
1640
1641                 dbus_message_iter_next(&dict);
1642         }
1643
1644         if (netmask == NULL || network == NULL || gateway == NULL) {
1645                 DBG("Value missing.");
1646                 return -EINVAL;
1647         }
1648
1649         return save_route(routes, family, network, netmask, gateway);
1650 }
1651
1652 static int routes_changed(DBusMessageIter *array, GHashTable *routes)
1653 {
1654         DBusMessageIter entry;
1655         int ret = -EINVAL;
1656
1657         if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) {
1658                 DBG("Expecting array, ignoring routes.");
1659                 return -EINVAL;
1660         }
1661
1662         while (dbus_message_iter_get_arg_type(array) == DBUS_TYPE_ARRAY) {
1663
1664                 dbus_message_iter_recurse(array, &entry);
1665
1666                 while (dbus_message_iter_get_arg_type(&entry) ==
1667                                                         DBUS_TYPE_STRUCT) {
1668                         DBusMessageIter dicts;
1669
1670                         dbus_message_iter_recurse(&entry, &dicts);
1671
1672                         while (dbus_message_iter_get_arg_type(&dicts) ==
1673                                                         DBUS_TYPE_ARRAY) {
1674                                 int err = read_route_dict(routes, &dicts);
1675                                 if (ret != 0)
1676                                         ret = err;
1677                                 dbus_message_iter_next(&dicts);
1678                         }
1679
1680                         dbus_message_iter_next(&entry);
1681                 }
1682
1683                 dbus_message_iter_next(array);
1684         }
1685
1686         return ret;
1687 }
1688
1689 static gboolean property_changed(DBusConnection *conn,
1690                                 DBusMessage *message,
1691                                 void *user_data)
1692 {
1693         const char *path = dbus_message_get_path(message);
1694         struct connection_data *data = NULL;
1695         DBusMessageIter iter, value;
1696         connman_bool_t ip_set = FALSE;
1697         int err;
1698         char *str;
1699         const char *key;
1700         const char *signature = DBUS_TYPE_STRING_AS_STRING
1701                 DBUS_TYPE_VARIANT_AS_STRING;
1702
1703         if (dbus_message_has_signature(message, signature) == FALSE) {
1704                 connman_error("vpn property signature \"%s\" does not match "
1705                                                         "expected \"%s\"",
1706                         dbus_message_get_signature(message), signature);
1707                 return TRUE;
1708         }
1709
1710         data = g_hash_table_lookup(vpn_connections, get_ident(path));
1711         if (data == NULL)
1712                 return TRUE;
1713
1714         if (dbus_message_iter_init(message, &iter) == FALSE)
1715                 return TRUE;
1716
1717         dbus_message_iter_get_basic(&iter, &key);
1718
1719         dbus_message_iter_next(&iter);
1720         dbus_message_iter_recurse(&iter, &value);
1721
1722         DBG("key %s", key);
1723
1724         if (g_str_equal(key, "State") == TRUE) {
1725                 dbus_message_iter_get_basic(&value, &str);
1726
1727                 DBG("%s %s -> %s", data->path, data->state, str);
1728
1729                 if (g_str_equal(data->state, str) == TRUE)
1730                         return TRUE;
1731
1732                 g_free(data->state);
1733                 data->state = g_strdup(str);
1734
1735                 set_provider_state(data);
1736         } else if (g_str_equal(key, "Index") == TRUE) {
1737                 dbus_message_iter_get_basic(&value, &data->index);
1738                 connman_provider_set_index(data->provider, data->index);
1739         } else if (g_str_equal(key, "IPv4") == TRUE) {
1740                 err = extract_ip(&value, AF_INET, data);
1741                 ip_set = TRUE;
1742         } else if (g_str_equal(key, "IPv6") == TRUE) {
1743                 err = extract_ip(&value, AF_INET6, data);
1744                 ip_set = TRUE;
1745         } else if (g_str_equal(key, "ServerRoutes") == TRUE) {
1746                 err = routes_changed(&value, data->server_routes);
1747                 /*
1748                  * Note that the vpnd will delay the route sending a bit
1749                  * (in order to collect the routes from VPN client),
1750                  * so we might have got the State changed property before
1751                  * we got ServerRoutes. This means that we must try to set
1752                  * the routes here because they would be left unset otherwise.
1753                  */
1754                 if (err == 0)
1755                         set_routes(data->provider,
1756                                                 CONNMAN_PROVIDER_ROUTE_SERVER);
1757         } else if (g_str_equal(key, "UserRoutes") == TRUE) {
1758                 err = routes_changed(&value, data->user_routes);
1759                 if (err == 0)
1760                         set_routes(data->provider,
1761                                                 CONNMAN_PROVIDER_ROUTE_USER);
1762         } else if (g_str_equal(key, "Nameservers") == TRUE) {
1763                 if (extract_nameservers(&value, data) == 0 &&
1764                                                 data->nameservers != NULL)
1765                         connman_provider_set_nameservers(data->provider,
1766                                                         data->nameservers);
1767         }
1768
1769         if (ip_set == TRUE && err == 0) {
1770                 err = connman_provider_set_ipaddress(data->provider, data->ip);
1771                 if (err < 0)
1772                         DBG("setting provider IP address failed (%s/%d)",
1773                                 strerror(-err), -err);
1774         }
1775
1776         return TRUE;
1777 }
1778
1779 static int vpn_init(void)
1780 {
1781         int err;
1782
1783         connection = connman_dbus_get_connection();
1784         if (connection == NULL)
1785                 return -EIO;
1786
1787         watch = g_dbus_add_service_watch(connection, VPN_SERVICE,
1788                         vpnd_created, vpnd_removed, &provider_driver, NULL);
1789
1790         added_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1791                                         VPN_MANAGER_INTERFACE,
1792                                         CONNECTION_ADDED, connection_added,
1793                                         &provider_driver, NULL);
1794
1795         removed_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1796                                         VPN_MANAGER_INTERFACE,
1797                                         CONNECTION_REMOVED, connection_removed,
1798                                         NULL, NULL);
1799
1800         property_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1801                                         VPN_CONNECTION_INTERFACE,
1802                                         PROPERTY_CHANGED, property_changed,
1803                                         NULL, NULL);
1804
1805         if (added_watch == 0 || removed_watch == 0 || property_watch == 0) {
1806                 err = -EIO;
1807                 goto remove;
1808         }
1809
1810         err = connman_provider_driver_register(&provider_driver);
1811         if (err == 0) {
1812                 vpn_connections = g_hash_table_new_full(g_str_hash,
1813                                                 g_str_equal,
1814                                                 g_free, connection_destroy);
1815
1816                 vpnd_created(connection, &provider_driver);
1817         }
1818
1819         return err;
1820
1821 remove:
1822         g_dbus_remove_watch(connection, watch);
1823         g_dbus_remove_watch(connection, added_watch);
1824         g_dbus_remove_watch(connection, removed_watch);
1825         g_dbus_remove_watch(connection, property_watch);
1826
1827         dbus_connection_unref(connection);
1828
1829         return err;
1830 }
1831
1832 static void vpn_exit(void)
1833 {
1834         g_dbus_remove_watch(connection, watch);
1835         g_dbus_remove_watch(connection, added_watch);
1836         g_dbus_remove_watch(connection, removed_watch);
1837         g_dbus_remove_watch(connection, property_watch);
1838
1839         connman_provider_driver_unregister(&provider_driver);
1840
1841         if (vpn_connections != NULL)
1842                 g_hash_table_destroy(vpn_connections);
1843
1844         dbus_connection_unref(connection);
1845 }
1846
1847 CONNMAN_PLUGIN_DEFINE(vpn, "VPN plugin", VERSION,
1848                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, vpn_init, vpn_exit)