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