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