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