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