5 * Copyright (C) 2012 Intel Corporation. All rights reserved.
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.
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.
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
28 #include <sys/socket.h>
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>
45 #define DBUS_TIMEOUT 10000
47 static DBusConnection *connection;
49 static GHashTable *vpn_connections = NULL;
50 static gboolean starting_vpnd = TRUE;
52 static guint added_watch;
53 static guint removed_watch;
54 static guint property_watch;
63 struct config_create_data {
64 connection_ready_cb callback;
69 struct connection_data {
72 struct connman_provider *provider;
74 DBusPendingCall *call;
75 connman_bool_t connect_pending;
76 struct config_create_data *cb_data;
86 GHashTable *server_routes;
87 GHashTable *user_routes;
88 GHashTable *setting_strings;
90 struct connman_ipaddress *ip;
96 static int set_string(struct connman_provider *provider,
97 const char *key, const char *value)
99 struct connection_data *data;
101 data = connman_provider_get_data(provider);
105 DBG("data %p provider %p key %s value %s", data, provider, key, value);
107 if (g_str_equal(key, "Type") == TRUE) {
109 data->type = g_strdup(value);
110 } else if (g_str_equal(key, "Name") == TRUE) {
112 data->name = g_strdup(value);
113 } else if (g_str_equal(key, "Host") == TRUE) {
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);
121 g_hash_table_replace(data->setting_strings,
122 g_strdup(key), g_strdup(value));
126 static const char *get_string(struct connman_provider *provider,
129 struct connection_data *data;
131 data = connman_provider_get_data(provider);
135 DBG("data %p provider %p key %s", data, provider, key);
137 if (g_str_equal(key, "Type") == TRUE)
139 else if (g_str_equal(key, "Name") == TRUE)
141 else if (g_str_equal(key, "Host") == TRUE)
143 else if (g_str_equal(key, "HostIP") == TRUE) {
144 if (data->host_ip == NULL ||
145 data->host_ip[0] == NULL)
148 return data->host_ip[0];
149 } else if (g_str_equal(key, "VPN.Domain") == TRUE)
152 return g_hash_table_lookup(data->setting_strings, key);
155 static char *get_ident(const char *path)
162 pos = strrchr(path, '/');
169 static void cancel_host_resolv(struct connection_data *data)
171 if (data->resolv_id != 0)
172 g_resolv_cancel_lookup(data->resolv, data->resolv_id);
176 g_resolv_unref(data->resolv);
180 static gboolean remove_resolv(gpointer user_data)
182 struct connection_data *data = user_data;
184 cancel_host_resolv(data);
189 static void resolv_result(GResolvResultStatus status,
190 char **results, gpointer user_data)
192 struct connection_data *data = user_data;
194 DBG("status %d", status);
196 if (status == G_RESOLV_RESULT_STATUS_SUCCESS && results != NULL &&
197 g_strv_length(results) > 0)
198 data->host_ip = g_strdupv(results);
201 * We cannot unref the resolver here as resolv struct is manipulated
202 * by gresolv.c after we return from this callback.
204 g_timeout_add_seconds(0, remove_resolv, data);
209 static void resolv_host_addr(struct connection_data *data)
211 if (data->host == NULL)
214 if (connman_inet_check_ipaddress(data->host) > 0)
217 if (data->host_ip != NULL)
220 data->resolv = g_resolv_new(0);
221 if (data->resolv == NULL) {
222 DBG("Cannot resolv %s", data->host);
226 DBG("Trying to resolv %s", data->host);
228 data->resolv_id = g_resolv_lookup_hostname(data->resolv, data->host,
229 resolv_result, data);
232 static void free_config_cb_data(struct config_create_data *cb_data)
237 g_free(cb_data->path);
238 cb_data->path = NULL;
240 if (cb_data->message != NULL) {
241 dbus_message_unref(cb_data->message);
242 cb_data->message = NULL;
245 cb_data->callback = NULL;
250 static void set_provider_state(struct connection_data *data)
252 enum connman_provider_state state = CONNMAN_PROVIDER_STATE_UNKNOWN;
255 if (g_str_equal(data->state, "ready") == TRUE) {
256 state = CONNMAN_PROVIDER_STATE_READY;
258 } else if (g_str_equal(data->state, "configuration") == TRUE) {
259 state = CONNMAN_PROVIDER_STATE_CONNECT;
260 } else if (g_str_equal(data->state, "idle") == TRUE) {
261 state = CONNMAN_PROVIDER_STATE_IDLE;
262 } else if (g_str_equal(data->state, "disconnect") == TRUE) {
264 state = CONNMAN_PROVIDER_STATE_DISCONNECT;
266 } else if (g_str_equal(data->state, "failure") == TRUE) {
268 state = CONNMAN_PROVIDER_STATE_FAILURE;
272 connman_provider_set_state(data->provider, state);
276 if (data->cb_data != NULL)
277 data->cb_data->callback(data->cb_data->message,
280 connman_provider_set_state(data->provider, state);
282 free_config_cb_data(data->cb_data);
283 data->cb_data = NULL;
286 static int create_provider(struct connection_data *data, void *user_data)
288 struct connman_provider_driver *driver = user_data;
291 DBG("%s", data->path);
293 data->provider = connman_provider_get(data->ident);
294 if (data->provider == NULL)
297 DBG("provider %p name %s", data->provider, data->name);
299 connman_provider_set_data(data->provider, data);
300 connman_provider_set_driver(data->provider, driver);
302 err = connman_provider_create_service(data->provider);
304 if (g_str_equal(data->state, "ready") == TRUE) {
305 connman_provider_set_index(data->provider,
307 if (data->ip != NULL)
308 connman_provider_set_ipaddress(data->provider,
312 set_provider_state(data);
318 static void destroy_route(gpointer user_data)
320 struct vpn_route *route = user_data;
322 g_free(route->network);
323 g_free(route->netmask);
324 g_free(route->gateway);
328 static struct connection_data *create_connection_data(const char *path)
330 struct connection_data *data;
332 data = g_try_new0(struct connection_data, 1);
336 DBG("path %s", path);
338 data->path = g_strdup(path);
339 data->ident = g_strdup(get_ident(path));
342 data->setting_strings = g_hash_table_new_full(g_str_hash,
343 g_str_equal, g_free, g_free);
345 data->server_routes = g_hash_table_new_full(g_direct_hash,
346 g_str_equal, g_free, destroy_route);
347 data->user_routes = g_hash_table_new_full(g_str_hash,
348 g_str_equal, g_free, destroy_route);
353 static int extract_ip(DBusMessageIter *array, int family,
354 struct connection_data *data)
356 DBusMessageIter dict;
357 char *address = NULL, *gateway = NULL, *netmask = NULL, *peer = NULL;
358 unsigned char prefix_len;
360 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
363 dbus_message_iter_recurse(array, &dict);
365 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
366 DBusMessageIter entry, value;
369 dbus_message_iter_recurse(&dict, &entry);
370 dbus_message_iter_get_basic(&entry, &key);
372 dbus_message_iter_next(&entry);
373 dbus_message_iter_recurse(&entry, &value);
375 if (g_str_equal(key, "Address") == TRUE) {
376 dbus_message_iter_get_basic(&value, &address);
377 DBG("address %s", address);
378 } else if (g_str_equal(key, "Netmask") == TRUE) {
379 dbus_message_iter_get_basic(&value, &netmask);
380 DBG("netmask %s", netmask);
381 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
382 dbus_message_iter_get_basic(&value, &netmask);
383 DBG("prefix length %s", netmask);
384 } else if (g_str_equal(key, "Peer") == TRUE) {
385 dbus_message_iter_get_basic(&value, &peer);
386 DBG("peer %s", peer);
387 } else if (g_str_equal(key, "Gateway") == TRUE) {
388 dbus_message_iter_get_basic(&value, &gateway);
389 DBG("gateway %s", gateway);
392 dbus_message_iter_next(&dict);
395 data->ip = connman_ipaddress_alloc(family);
396 if (data->ip == NULL)
401 connman_ipaddress_set_ipv4(data->ip, address, netmask,
405 prefix_len = atoi(netmask);
406 connman_ipaddress_set_ipv6(data->ip, address, prefix_len,
413 connman_ipaddress_set_peer(data->ip, peer);
418 static int extract_nameservers(DBusMessageIter *array,
419 struct connection_data *data)
421 DBusMessageIter entry;
422 char **nameservers = NULL;
425 dbus_message_iter_recurse(array, &entry);
427 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
428 const char *nameserver;
430 dbus_message_iter_get_basic(&entry, &nameserver);
432 nameservers = g_try_renew(char *, nameservers, i + 2);
433 if (nameservers == NULL)
436 DBG("[%d] %s", i, nameserver);
438 nameservers[i] = g_strdup(nameserver);
439 if (nameservers[i] == NULL)
442 nameservers[++i] = NULL;
444 dbus_message_iter_next(&entry);
447 g_strfreev(data->nameservers);
448 data->nameservers = nameservers;
453 static void connect_reply(DBusPendingCall *call, void *user_data)
457 struct connection_data *data;
458 struct config_create_data *cb_data = user_data;
460 if (dbus_pending_call_get_completed(call) == FALSE)
463 DBG("user_data %p path %s", user_data, cb_data ? cb_data->path : NULL);
465 reply = dbus_pending_call_steal_reply(call);
467 dbus_error_init(&error);
469 if (dbus_set_error_from_message(&error, reply) == TRUE) {
470 if (dbus_error_has_name(&error, CONNMAN_ERROR_INTERFACE
471 ".InProgress") == FALSE) {
472 connman_error("Connect reply: %s (%s)", error.message,
474 dbus_error_free(&error);
476 if (cb_data != NULL) {
477 cb_data->callback(cb_data->message,
479 free_config_cb_data(cb_data);
481 data->cb_data = NULL;
484 dbus_error_free(&error);
488 * The vpn connection is up when we get a "ready" state
489 * property so at this point we do nothing for the provider
494 dbus_message_unref(reply);
496 dbus_pending_call_unref(call);
499 static int connect_provider(struct connection_data *data, void *user_data)
501 DBusPendingCall *call;
502 DBusMessage *message;
503 struct config_create_data *cb_data = user_data;
505 DBG("data %p user %p path %s", data, cb_data, data->path);
507 message = dbus_message_new_method_call(VPN_SERVICE, data->path,
508 VPN_CONNECTION_INTERFACE,
513 if (dbus_connection_send_with_reply(connection, message,
514 &call, DBUS_TIMEOUT) == FALSE) {
515 connman_error("Unable to call %s.%s()",
516 VPN_CONNECTION_INTERFACE, VPN_CONNECT);
517 dbus_message_unref(message);
522 dbus_message_unref(message);
526 if (cb_data != NULL) {
527 g_free(cb_data->path);
528 cb_data->path = g_strdup(data->path);
531 dbus_pending_call_set_notify(call, connect_reply, cb_data, NULL);
533 dbus_message_unref(message);
538 static void add_connection(const char *path, DBusMessageIter *properties,
541 struct connection_data *data;
543 char *ident = get_ident(path);
544 connman_bool_t found = FALSE;
546 data = g_hash_table_lookup(vpn_connections, ident);
549 * We might have a dummy connection struct here that
550 * was created by configuration_create_reply() so in
551 * that case just continue.
553 if (data->connect_pending == FALSE)
558 data = create_connection_data(path);
563 DBG("data %p path %s", data, path);
565 while (dbus_message_iter_get_arg_type(properties) ==
566 DBUS_TYPE_DICT_ENTRY) {
567 DBusMessageIter entry, value;
571 dbus_message_iter_recurse(properties, &entry);
572 dbus_message_iter_get_basic(&entry, &key);
574 dbus_message_iter_next(&entry);
575 dbus_message_iter_recurse(&entry, &value);
577 if (g_str_equal(key, "State") == TRUE) {
578 dbus_message_iter_get_basic(&value, &str);
579 DBG("state %s -> %s", data->state, str);
580 data->state = g_strdup(str);
581 } else if (g_str_equal(key, "IPv4") == TRUE) {
582 extract_ip(&value, AF_INET, data);
583 } else if (g_str_equal(key, "IPv6") == TRUE) {
584 extract_ip(&value, AF_INET6, data);
585 } else if (g_str_equal(key, "Name") == TRUE) {
586 dbus_message_iter_get_basic(&value, &str);
587 data->name = g_strdup(str);
588 } else if (g_str_equal(key, "Type") == TRUE) {
589 dbus_message_iter_get_basic(&value, &str);
590 data->type = g_strdup(str);
591 } else if (g_str_equal(key, "Host") == TRUE) {
592 dbus_message_iter_get_basic(&value, &str);
593 data->host = g_strdup(str);
594 } else if (g_str_equal(key, "Domain") == TRUE) {
595 dbus_message_iter_get_basic(&value, &str);
596 data->domain = g_strdup(str);
597 } else if (g_str_equal(key, "Nameservers") == TRUE) {
598 extract_nameservers(&value, data);
599 } else if (g_str_equal(key, "Index") == TRUE) {
600 dbus_message_iter_get_basic(&value, &data->index);
602 if (dbus_message_iter_get_arg_type(&value) ==
604 dbus_message_iter_get_basic(&value, &str);
605 g_hash_table_replace(data->setting_strings,
606 g_strdup(key), g_strdup(str));
608 DBG("unknown key %s", key);
612 dbus_message_iter_next(properties);
616 g_hash_table_insert(vpn_connections, g_strdup(data->ident),
619 err = create_provider(data, user_data);
623 resolv_host_addr(data);
625 if (data->connect_pending == TRUE)
626 connect_provider(data, data->cb_data);
631 DBG("removing %s", data->ident);
632 g_hash_table_remove(vpn_connections, data->ident);
635 static void get_connections_reply(DBusPendingCall *call, void *user_data)
639 DBusMessageIter array, dict;
640 const char *signature = DBUS_TYPE_ARRAY_AS_STRING
641 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
642 DBUS_TYPE_OBJECT_PATH_AS_STRING
643 DBUS_TYPE_ARRAY_AS_STRING
644 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
645 DBUS_TYPE_STRING_AS_STRING
646 DBUS_TYPE_VARIANT_AS_STRING
647 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
648 DBUS_STRUCT_END_CHAR_AS_STRING;
650 if (dbus_pending_call_get_completed(call) == FALSE)
655 reply = dbus_pending_call_steal_reply(call);
657 dbus_error_init(&error);
659 if (dbus_set_error_from_message(&error, reply) == TRUE) {
660 connman_error("%s", error.message);
661 dbus_error_free(&error);
665 if (dbus_message_has_signature(reply, signature) == FALSE) {
666 connman_error("vpnd signature \"%s\" does not match "
668 dbus_message_get_signature(reply), signature);
672 if (dbus_message_iter_init(reply, &array) == FALSE)
675 dbus_message_iter_recurse(&array, &dict);
677 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
678 DBusMessageIter value, properties;
681 dbus_message_iter_recurse(&dict, &value);
682 dbus_message_iter_get_basic(&value, &path);
684 dbus_message_iter_next(&value);
685 dbus_message_iter_recurse(&value, &properties);
687 add_connection(path, &properties, user_data);
689 dbus_message_iter_next(&dict);
693 dbus_message_unref(reply);
695 dbus_pending_call_unref(call);
698 static int get_connections(void *user_data)
700 DBusPendingCall *call;
701 DBusMessage *message;
705 message = dbus_message_new_method_call(VPN_SERVICE, "/",
706 VPN_MANAGER_INTERFACE,
711 if (dbus_connection_send_with_reply(connection, message,
712 &call, DBUS_TIMEOUT) == FALSE) {
713 connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
715 dbus_message_unref(message);
720 dbus_message_unref(message);
724 dbus_pending_call_set_notify(call, get_connections_reply,
727 dbus_message_unref(message);
732 static int provider_probe(struct connman_provider *provider)
737 static void remove_connection_reply(DBusPendingCall *call, void *user_data)
742 if (dbus_pending_call_get_completed(call) == FALSE)
747 reply = dbus_pending_call_steal_reply(call);
749 dbus_error_init(&error);
751 if (dbus_set_error_from_message(&error, reply) == TRUE) {
753 * If the returned error is NotFound, it means that we
754 * have actually removed the provider in vpnd already.
756 if (dbus_error_has_name(&error, CONNMAN_ERROR_INTERFACE
757 ".NotFound") == FALSE)
758 connman_error("%s", error.message);
760 dbus_error_free(&error);
763 dbus_message_unref(reply);
765 dbus_pending_call_unref(call);
768 static int provider_remove(struct connman_provider *provider)
770 DBusPendingCall *call;
771 DBusMessage *message;
772 struct connection_data *data;
774 data = connman_provider_get_data(provider);
776 DBG("provider %p data %p", provider, data);
779 * When provider.c:provider_remove() calls this function,
780 * it will remove the provider itself after the call.
781 * This means that we cannot use the provider pointer later
782 * as it is no longer valid.
784 data->provider = NULL;
786 message = dbus_message_new_method_call(VPN_SERVICE, "/",
787 VPN_MANAGER_INTERFACE,
792 dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &data->path,
795 if (dbus_connection_send_with_reply(connection, message,
796 &call, DBUS_TIMEOUT) == FALSE) {
797 connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
799 dbus_message_unref(message);
804 dbus_message_unref(message);
808 dbus_pending_call_set_notify(call, remove_connection_reply,
811 dbus_message_unref(message);
816 static int provider_connect(struct connman_provider *provider)
818 struct connection_data *data;
820 data = connman_provider_get_data(provider);
824 return connect_provider(data, NULL);
827 static void disconnect_reply(DBusPendingCall *call, void *user_data)
832 if (dbus_pending_call_get_completed(call) == FALSE)
835 DBG("user %p", user_data);
837 reply = dbus_pending_call_steal_reply(call);
839 dbus_error_init(&error);
841 if (dbus_set_error_from_message(&error, reply) == TRUE) {
842 connman_error("%s", error.message);
843 dbus_error_free(&error);
848 dbus_message_unref(reply);
850 dbus_pending_call_unref(call);
853 static int disconnect_provider(struct connection_data *data)
855 DBusPendingCall *call;
856 DBusMessage *message;
858 DBG("data %p path %s", data, data->path);
860 message = dbus_message_new_method_call(VPN_SERVICE, data->path,
861 VPN_CONNECTION_INTERFACE,
866 if (dbus_connection_send_with_reply(connection, message,
867 &call, DBUS_TIMEOUT) == FALSE) {
868 connman_error("Unable to call %s.%s()",
869 VPN_CONNECTION_INTERFACE, VPN_DISCONNECT);
870 dbus_message_unref(message);
875 dbus_message_unref(message);
879 dbus_pending_call_set_notify(call, disconnect_reply, NULL, NULL);
881 dbus_message_unref(message);
883 connman_provider_set_state(data->provider,
884 CONNMAN_PROVIDER_STATE_DISCONNECT);
886 * We return 0 here instead of -EINPROGRESS because
887 * __connman_service_disconnect() needs to return something
888 * to gdbus so that gdbus will not call Disconnect() more
889 * than once. This way we do not need to pass the dbus reply
890 * message around the code.
895 static int provider_disconnect(struct connman_provider *provider)
897 struct connection_data *data;
899 DBG("provider %p", provider);
901 data = connman_provider_get_data(provider);
905 if (g_str_equal(data->state, "ready") == TRUE ||
906 g_str_equal(data->state, "configuration") == TRUE)
907 return disconnect_provider(data);
912 static void configuration_create_reply(DBusPendingCall *call, void *user_data)
916 DBusMessageIter iter;
917 const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
920 struct connection_data *data;
921 struct config_create_data *cb_data = user_data;
923 if (dbus_pending_call_get_completed(call) == FALSE)
926 DBG("user %p", cb_data);
928 reply = dbus_pending_call_steal_reply(call);
930 dbus_error_init(&error);
932 if (dbus_set_error_from_message(&error, reply) == TRUE) {
933 connman_error("dbus error: %s", error.message);
934 dbus_error_free(&error);
938 if (dbus_message_has_signature(reply, signature) == FALSE) {
939 connman_error("vpn configuration signature \"%s\" does not "
940 "match expected \"%s\"",
941 dbus_message_get_signature(reply), signature);
945 if (dbus_message_iter_init(reply, &iter) == FALSE)
948 dbus_message_iter_get_basic(&iter, &path);
951 * Then try to connect the VPN as expected by ConnectProvider API
953 ident = get_ident(path);
955 data = g_hash_table_lookup(vpn_connections, ident);
958 * Someone removed the data. We cannot really continue.
960 DBG("Pending data not found for %s, cannot continue!", ident);
963 data->connect_pending = TRUE;
965 if (data->cb_data == NULL)
966 data->cb_data = cb_data;
968 DBG("Connection callback data already in use!");
971 * Connection is created in add_connections() after
972 * we have received the ConnectionAdded signal.
975 DBG("cb %p msg %p", data->cb_data,
976 data->cb_data ? data->cb_data->message : NULL);
980 dbus_message_unref(reply);
982 dbus_pending_call_unref(call);
985 static void set_dbus_ident(char *ident)
987 int i, len = strlen(ident);
989 for (i = 0; i < len; i++) {
990 if (ident[i] >= '0' && ident[i] <= '9')
992 if (ident[i] >= 'a' && ident[i] <= 'z')
994 if (ident[i] >= 'A' && ident[i] <= 'Z')
1000 static struct vpn_route *parse_user_route(const char *user_route)
1002 char *network, *netmask;
1003 struct vpn_route *route = NULL;
1004 int family = PF_UNSPEC;
1005 char **elems = g_strsplit(user_route, "/", 0);
1011 if (network == NULL || *network == '\0') {
1012 DBG("no network/netmask set");
1017 if (netmask != NULL && *netmask == '\0') {
1018 DBG("no netmask set");
1022 if (g_strrstr(network, ":") != NULL)
1024 else if (g_strrstr(network, ".") != NULL) {
1027 if (g_strrstr(netmask, ".") == NULL) {
1028 /* We have netmask length */
1030 struct in_addr netmask_in;
1031 unsigned char prefix_len = 32;
1033 if (netmask != NULL) {
1035 long int value = strtol(netmask, &ptr, 10);
1036 if (ptr != netmask && *ptr == '\0' &&
1041 addr = 0xffffffff << (32 - prefix_len);
1042 netmask_in.s_addr = htonl(addr);
1043 netmask = inet_ntoa(netmask_in);
1045 DBG("network %s netmask %s", network, netmask);
1049 route = g_try_new(struct vpn_route, 1);
1053 route->network = g_strdup(network);
1054 route->netmask = g_strdup(netmask);
1055 route->gateway = NULL;
1056 route->family = family;
1063 static GSList *get_user_networks(DBusMessageIter *array)
1065 DBusMessageIter entry;
1066 GSList *list = NULL;
1068 dbus_message_iter_recurse(array, &entry);
1070 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1072 struct vpn_route *route;
1074 dbus_message_iter_get_basic(&entry, &val);
1076 route = parse_user_route(val);
1078 list = g_slist_prepend(list, route);
1080 dbus_message_iter_next(&entry);
1086 static void append_route(DBusMessageIter *iter, void *user_data)
1088 struct vpn_route *route = user_data;
1089 DBusMessageIter item;
1092 connman_dbus_dict_open(iter, &item);
1097 if (route->family == AF_INET)
1099 else if (route->family == AF_INET6)
1103 connman_dbus_dict_append_basic(&item, "ProtocolFamily",
1104 DBUS_TYPE_INT32, &family);
1106 if (route->network != NULL)
1107 connman_dbus_dict_append_basic(&item, "Network",
1108 DBUS_TYPE_STRING, &route->network);
1110 if (route->netmask != NULL)
1111 connman_dbus_dict_append_basic(&item, "Netmask",
1112 DBUS_TYPE_STRING, &route->netmask);
1114 if (route->gateway != NULL)
1115 connman_dbus_dict_append_basic(&item, "Gateway",
1116 DBUS_TYPE_STRING, &route->gateway);
1119 connman_dbus_dict_close(iter, &item);
1122 static void append_routes(DBusMessageIter *iter, void *user_data)
1124 GSList *list, *routes = user_data;
1126 DBG("routes %p", routes);
1128 for (list = routes; list != NULL; list = g_slist_next(list)) {
1129 DBusMessageIter dict;
1130 struct vpn_route *route = list->data;
1132 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL,
1134 append_route(&dict, route);
1135 dbus_message_iter_close_container(iter, &dict);
1139 static int create_configuration(DBusMessage *msg, connection_ready_cb callback)
1141 DBusMessage *new_msg = NULL;
1142 DBusPendingCall *call;
1143 DBusMessageIter iter, array, new_iter, new_dict;
1144 const char *type = NULL, *name = NULL;
1145 const char *host = NULL, *domain = NULL;
1146 char *ident, *me = NULL;
1149 struct connection_data *data;
1150 struct config_create_data *user_data = NULL;
1151 GSList *networks = NULL;
1154 * We copy the old message data into new message. We cannot
1155 * just use the old message as is because the user route
1156 * information is not in the same format in vpnd.
1158 new_msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
1159 dbus_message_iter_init_append(new_msg, &new_iter);
1160 connman_dbus_dict_open(&new_iter, &new_dict);
1162 dbus_message_iter_init(msg, &iter);
1163 dbus_message_iter_recurse(&iter, &array);
1165 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1166 DBusMessageIter entry, value;
1171 dbus_message_iter_recurse(&array, &entry);
1172 dbus_message_iter_get_basic(&entry, &key);
1174 dbus_message_iter_next(&entry);
1175 dbus_message_iter_recurse(&entry, &value);
1177 value_type = dbus_message_iter_get_arg_type(&value);
1180 switch (value_type) {
1181 case DBUS_TYPE_STRING:
1182 dbus_message_iter_get_basic(&value, &item_value);
1184 if (g_str_equal(key, "Type") == TRUE) {
1185 type = (const char *)item_value;
1186 } else if (g_str_equal(key, "Name") == TRUE) {
1187 name = (const char *)item_value;
1188 } else if (g_str_equal(key, "Host") == TRUE) {
1189 host = (const char *)item_value;
1190 } else if (g_str_equal(key, "VPN.Domain") == TRUE) {
1191 domain = (const char *)item_value;
1194 DBG("%s %s", key, (char *)item_value);
1196 if (item_value != NULL)
1197 connman_dbus_dict_append_basic(&new_dict, key,
1198 value_type, &item_value);
1200 case DBUS_TYPE_ARRAY:
1201 if (g_str_equal(key, "Networks") == TRUE) {
1202 networks = get_user_networks(&value);
1203 connman_dbus_dict_append_array(&new_dict,
1205 DBUS_TYPE_DICT_ENTRY,
1212 dbus_message_iter_next(&array);
1215 connman_dbus_dict_close(&new_iter, &new_dict);
1217 DBG("VPN type %s name %s host %s domain %s networks %p",
1218 type, name, host, domain, networks);
1220 if (host == NULL || domain == NULL) {
1225 if (type == NULL || name == NULL) {
1230 ident = g_strdup_printf("%s_%s", host, domain);
1231 set_dbus_ident(ident);
1233 DBG("ident %s", ident);
1235 data = g_hash_table_lookup(vpn_connections, ident);
1237 if (data->call != NULL) {
1238 connman_error("Dbus call already pending");
1243 char *path = g_strdup_printf("%s/connection/%s", VPN_PATH,
1245 data = create_connection_data(path);
1253 g_hash_table_insert(vpn_connections, g_strdup(ident), data);
1257 * User called net.connman.Manager.ConnectProvider if we are here.
1258 * So use the data from original message in the new msg.
1260 me = g_strdup(dbus_message_get_destination(msg));
1262 dbus_message_set_interface(new_msg, VPN_MANAGER_INTERFACE);
1263 dbus_message_set_path(new_msg, "/");
1264 dbus_message_set_destination(new_msg, VPN_SERVICE);
1265 dbus_message_set_sender(new_msg, me);
1266 dbus_message_set_member(new_msg, "Create");
1268 result = dbus_connection_send_with_reply(connection, new_msg,
1269 &call, DBUS_TIMEOUT);
1270 if (result == FALSE || call == NULL) {
1275 if (data->cb_data == NULL) {
1276 user_data = g_try_new(struct config_create_data, 1);
1277 if (user_data != NULL) {
1278 user_data->callback = callback;
1279 user_data->message = dbus_message_ref(msg);
1280 user_data->path = NULL;
1282 DBG("cb %p msg %p", user_data, msg);
1285 DBG("Configuration callback data already pending, "
1286 "discarding new data.");
1289 dbus_pending_call_set_notify(call, configuration_create_reply,
1294 if (new_msg != NULL)
1295 dbus_message_unref(new_msg);
1297 if (networks != NULL)
1298 g_slist_free_full(networks, destroy_route);
1304 static connman_bool_t check_host(char **hosts, char *host)
1311 for (i = 0; hosts[i] != NULL; i++) {
1312 if (g_strcmp0(hosts[i], host) == 0)
1319 static void set_route(struct connection_data *data, struct vpn_route *route)
1322 * If the VPN administrator/user has given a route to
1323 * VPN server, then we must discard that because the
1324 * server cannot be contacted via VPN tunnel.
1326 if (check_host(data->host_ip, route->network) == TRUE) {
1327 DBG("Discarding VPN route to %s via %s at index %d",
1328 route->network, route->gateway, data->index);
1332 if (route->family == AF_INET6) {
1333 unsigned char prefix_len = atoi(route->netmask);
1335 connman_inet_add_ipv6_network_route(data->index,
1340 connman_inet_add_network_route(data->index, route->network,
1346 static int set_routes(struct connman_provider *provider,
1347 enum connman_provider_route_type type)
1349 struct connection_data *data;
1350 GHashTableIter iter;
1351 gpointer value, key;
1353 DBG("provider %p", provider);
1355 data = connman_provider_get_data(provider);
1359 if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
1360 type == CONNMAN_PROVIDER_ROUTE_USER) {
1361 g_hash_table_iter_init(&iter, data->user_routes);
1363 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
1364 set_route(data, value);
1367 if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
1368 type == CONNMAN_PROVIDER_ROUTE_SERVER) {
1369 g_hash_table_iter_init(&iter, data->server_routes);
1371 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
1372 set_route(data, value);
1378 static connman_bool_t check_routes(struct connman_provider *provider)
1380 struct connection_data *data;
1382 DBG("provider %p", provider);
1384 data = connman_provider_get_data(provider);
1388 if (data->user_routes != NULL &&
1389 g_hash_table_size(data->user_routes) > 0)
1392 if (data->server_routes != NULL &&
1393 g_hash_table_size(data->server_routes) > 0)
1399 static struct connman_provider_driver provider_driver = {
1401 .type = CONNMAN_PROVIDER_TYPE_VPN,
1402 .probe = provider_probe,
1403 .remove = provider_remove,
1404 .connect = provider_connect,
1405 .disconnect = provider_disconnect,
1406 .set_property = set_string,
1407 .get_property = get_string,
1408 .create = create_configuration,
1409 .set_routes = set_routes,
1410 .check_routes = check_routes,
1413 static void destroy_provider(struct connection_data *data)
1415 DBG("data %p", data);
1417 if (g_str_equal(data->state, "ready") == TRUE ||
1418 g_str_equal(data->state, "configuration") == TRUE)
1419 connman_provider_disconnect(data->provider);
1421 if (data->call != NULL)
1422 dbus_pending_call_cancel(data->call);
1424 connman_provider_put(data->provider);
1426 data->provider = NULL;
1429 static void connection_destroy(gpointer hash_data)
1431 struct connection_data *data = hash_data;
1433 DBG("data %p", data);
1435 if (data->provider != NULL)
1436 destroy_provider(data);
1439 g_free(data->ident);
1440 g_free(data->state);
1444 g_free(data->domain);
1445 g_hash_table_destroy(data->server_routes);
1446 g_hash_table_destroy(data->user_routes);
1447 g_strfreev(data->nameservers);
1448 g_hash_table_destroy(data->setting_strings);
1449 connman_ipaddress_free(data->ip);
1451 cancel_host_resolv(data);
1456 static void vpnd_created(DBusConnection *conn, void *user_data)
1458 DBG("connection %p", conn);
1460 if (starting_vpnd == TRUE) {
1461 vpn_connections = g_hash_table_new_full(g_str_hash,
1463 g_free, connection_destroy);
1464 get_connections(user_data);
1465 starting_vpnd = FALSE;
1469 static void vpnd_removed(DBusConnection *conn, void *user_data)
1471 DBG("connection %p", conn);
1473 g_hash_table_destroy(vpn_connections);
1474 vpn_connections = NULL;
1475 starting_vpnd = TRUE;
1478 static void remove_connection(DBusConnection *conn, const char *path)
1480 DBG("path %s", path);
1482 g_hash_table_remove(vpn_connections, get_ident(path));
1485 static gboolean connection_removed(DBusConnection *conn, DBusMessage *message,
1489 const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
1491 if (dbus_message_has_signature(message, signature) == FALSE) {
1492 connman_error("vpn removed signature \"%s\" does not match "
1494 dbus_message_get_signature(message), signature);
1498 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1500 remove_connection(conn, path);
1504 static gboolean connection_added(DBusConnection *conn, DBusMessage *message,
1507 DBusMessageIter iter, properties;
1509 const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING
1510 DBUS_TYPE_ARRAY_AS_STRING
1511 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1512 DBUS_TYPE_STRING_AS_STRING
1513 DBUS_TYPE_VARIANT_AS_STRING
1514 DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
1516 if (dbus_message_has_signature(message, signature) == FALSE) {
1517 connman_error("vpn ConnectionAdded signature \"%s\" does not "
1518 "match expected \"%s\"",
1519 dbus_message_get_signature(message), signature);
1525 if (dbus_message_iter_init(message, &iter) == FALSE)
1528 dbus_message_iter_get_basic(&iter, &path);
1530 dbus_message_iter_next(&iter);
1531 dbus_message_iter_recurse(&iter, &properties);
1533 add_connection(path, &properties, user_data);
1538 static int save_route(GHashTable *routes, int family, const char *network,
1539 const char *netmask, const char *gateway)
1541 struct vpn_route *route;
1542 char *key = g_strdup_printf("%d/%s/%s", family, network, netmask);
1544 DBG("family %d network %s netmask %s", family, network, netmask);
1546 route = g_hash_table_lookup(routes, key);
1547 if (route == NULL) {
1548 route = g_try_new0(struct vpn_route, 1);
1549 if (route == NULL) {
1550 connman_error("out of memory");
1554 route->family = family;
1555 route->network = g_strdup(network);
1556 route->netmask = g_strdup(netmask);
1557 route->gateway = g_strdup(gateway);
1559 g_hash_table_replace(routes, key, route);
1566 static int read_route_dict(GHashTable *routes, DBusMessageIter *dicts)
1568 DBusMessageIter dict;
1569 const char *network, *netmask, *gateway;
1572 dbus_message_iter_recurse(dicts, &dict);
1574 network = netmask = gateway = NULL;
1577 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1579 DBusMessageIter entry, value;
1582 dbus_message_iter_recurse(&dict, &entry);
1583 dbus_message_iter_get_basic(&entry, &key);
1585 dbus_message_iter_next(&entry);
1586 dbus_message_iter_recurse(&entry, &value);
1588 if (g_str_equal(key, "ProtocolFamily") == TRUE) {
1590 dbus_message_iter_get_basic(&value, &pf);
1599 DBG("family %d", family);
1600 } else if (g_str_equal(key, "Netmask") == TRUE) {
1601 dbus_message_iter_get_basic(&value, &netmask);
1602 DBG("netmask %s", netmask);
1603 } else if (g_str_equal(key, "Network") == TRUE) {
1604 dbus_message_iter_get_basic(&value, &network);
1605 DBG("host %s", network);
1606 } else if (g_str_equal(key, "Gateway") == TRUE) {
1607 dbus_message_iter_get_basic(&value, &gateway);
1608 DBG("gateway %s", gateway);
1611 dbus_message_iter_next(&dict);
1614 if (netmask == NULL || network == NULL || gateway == NULL) {
1615 DBG("Value missing.");
1619 return save_route(routes, family, network, netmask, gateway);
1622 static int routes_changed(DBusMessageIter *array, GHashTable *routes)
1624 DBusMessageIter entry;
1627 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) {
1628 DBG("Expecting array, ignoring routes.");
1632 while (dbus_message_iter_get_arg_type(array) == DBUS_TYPE_ARRAY) {
1634 dbus_message_iter_recurse(array, &entry);
1636 while (dbus_message_iter_get_arg_type(&entry) ==
1638 DBusMessageIter dicts;
1640 dbus_message_iter_recurse(&entry, &dicts);
1642 while (dbus_message_iter_get_arg_type(&dicts) ==
1644 int err = read_route_dict(routes, &dicts);
1647 dbus_message_iter_next(&dicts);
1650 dbus_message_iter_next(&entry);
1653 dbus_message_iter_next(array);
1659 static gboolean property_changed(DBusConnection *conn,
1660 DBusMessage *message,
1663 const char *path = dbus_message_get_path(message);
1664 struct connection_data *data = NULL;
1665 DBusMessageIter iter, value;
1666 connman_bool_t ip_set = FALSE;
1670 const char *signature = DBUS_TYPE_STRING_AS_STRING
1671 DBUS_TYPE_VARIANT_AS_STRING;
1673 if (dbus_message_has_signature(message, signature) == FALSE) {
1674 connman_error("vpn property signature \"%s\" does not match "
1676 dbus_message_get_signature(message), signature);
1680 data = g_hash_table_lookup(vpn_connections, get_ident(path));
1684 if (dbus_message_iter_init(message, &iter) == FALSE)
1687 dbus_message_iter_get_basic(&iter, &key);
1689 dbus_message_iter_next(&iter);
1690 dbus_message_iter_recurse(&iter, &value);
1694 if (g_str_equal(key, "State") == TRUE) {
1695 dbus_message_iter_get_basic(&value, &str);
1697 DBG("%s %s -> %s", data->path, data->state, str);
1699 if (g_str_equal(data->state, str) == TRUE)
1702 g_free(data->state);
1703 data->state = g_strdup(str);
1705 set_provider_state(data);
1706 } else if (g_str_equal(key, "Index") == TRUE) {
1707 dbus_message_iter_get_basic(&value, &data->index);
1708 connman_provider_set_index(data->provider, data->index);
1709 } else if (g_str_equal(key, "IPv4") == TRUE) {
1710 err = extract_ip(&value, AF_INET, data);
1712 } else if (g_str_equal(key, "IPv6") == TRUE) {
1713 err = extract_ip(&value, AF_INET6, data);
1715 } else if (g_str_equal(key, "ServerRoutes") == TRUE) {
1716 err = routes_changed(&value, data->server_routes);
1718 * Note that the vpnd will delay the route sending a bit
1719 * (in order to collect the routes from VPN client),
1720 * so we might have got the State changed property before
1721 * we got ServerRoutes. This means that we must try to set
1722 * the routes here because they would be left unset otherwise.
1725 set_routes(data->provider,
1726 CONNMAN_PROVIDER_ROUTE_SERVER);
1727 } else if (g_str_equal(key, "UserRoutes") == TRUE) {
1728 err = routes_changed(&value, data->user_routes);
1730 set_routes(data->provider,
1731 CONNMAN_PROVIDER_ROUTE_USER);
1732 } else if (g_str_equal(key, "Nameservers") == TRUE) {
1733 extract_nameservers(&value, data);
1736 if (ip_set == TRUE && err == 0) {
1737 err = connman_provider_set_ipaddress(data->provider, data->ip);
1739 DBG("setting provider IP address failed (%s/%d)",
1740 strerror(-err), -err);
1746 static int vpn_init(void)
1750 connection = connman_dbus_get_connection();
1751 if (connection == NULL)
1754 watch = g_dbus_add_service_watch(connection, VPN_SERVICE,
1755 vpnd_created, vpnd_removed, &provider_driver, NULL);
1757 added_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1758 VPN_MANAGER_INTERFACE,
1759 CONNECTION_ADDED, connection_added,
1760 &provider_driver, NULL);
1762 removed_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1763 VPN_MANAGER_INTERFACE,
1764 CONNECTION_REMOVED, connection_removed,
1767 property_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1768 VPN_CONNECTION_INTERFACE,
1769 PROPERTY_CHANGED, property_changed,
1772 if (added_watch == 0 || removed_watch == 0 || property_watch == 0) {
1777 err = connman_provider_driver_register(&provider_driver);
1779 vpnd_created(connection, &provider_driver);
1784 g_dbus_remove_watch(connection, watch);
1785 g_dbus_remove_watch(connection, added_watch);
1786 g_dbus_remove_watch(connection, removed_watch);
1787 g_dbus_remove_watch(connection, property_watch);
1789 dbus_connection_unref(connection);
1794 static void vpn_exit(void)
1796 g_dbus_remove_watch(connection, watch);
1797 g_dbus_remove_watch(connection, added_watch);
1798 g_dbus_remove_watch(connection, removed_watch);
1799 g_dbus_remove_watch(connection, property_watch);
1801 connman_provider_driver_unregister(&provider_driver);
1803 g_hash_table_destroy(vpn_connections);
1805 dbus_connection_unref(connection);
1808 CONNMAN_PLUGIN_DEFINE(vpn, "VPN plugin", VERSION,
1809 CONNMAN_PLUGIN_PRIORITY_DEFAULT, vpn_init, vpn_exit)