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