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>
44 #define DBUS_TIMEOUT 10000
46 static DBusConnection *connection;
48 static GHashTable *vpn_connections = NULL;
49 static gboolean starting_vpnd = TRUE;
51 static guint added_watch;
52 static guint removed_watch;
53 static guint property_watch;
62 struct connection_data {
64 struct connman_provider *provider;
66 DBusPendingCall *call;
75 GHashTable *server_routes;
76 GHashTable *user_routes;
77 GHashTable *setting_strings;
79 struct connman_ipaddress *ip;
82 static int set_string(struct connman_provider *provider,
83 const char *key, const char *value)
85 struct connection_data *data;
87 data = connman_provider_get_data(provider);
91 DBG("data %p provider %p key %s value %s", data, provider, key, value);
93 if (g_str_equal(key, "Type") == TRUE) {
95 data->type = g_strdup(value);
96 } else if (g_str_equal(key, "Name") == TRUE) {
98 data->name = g_strdup(value);
99 } else if (g_str_equal(key, "Host") == TRUE) {
101 data->host = g_strdup(value);
102 } else if (g_str_equal(key, "VPN.Domain") == TRUE ||
103 g_str_equal(key, "Domain") == TRUE) {
104 g_free(data->domain);
105 data->domain = g_strdup(value);
107 g_hash_table_replace(data->setting_strings,
108 g_strdup(key), g_strdup(value));
112 static const char *get_string(struct connman_provider *provider,
115 struct connection_data *data;
117 data = connman_provider_get_data(provider);
121 DBG("data %p provider %p key %s", data, provider, key);
123 if (g_str_equal(key, "Type") == TRUE)
125 else if (g_str_equal(key, "Name") == TRUE)
127 else if (g_str_equal(key, "Host") == TRUE)
129 else if (g_str_equal(key, "VPN.Domain") == TRUE)
132 return g_hash_table_lookup(data->setting_strings, key);
135 static char *get_ident(const char *path)
142 pos = strrchr(path, '/');
149 static void set_provider_state(struct connection_data *data)
151 if (g_str_equal(data->state, "ready") == TRUE)
152 connman_provider_set_state(data->provider,
153 CONNMAN_PROVIDER_STATE_READY);
154 else if (g_str_equal(data->state, "configuration") == TRUE)
155 connman_provider_set_state(data->provider,
156 CONNMAN_PROVIDER_STATE_CONNECT);
157 else if (g_str_equal(data->state, "idle") == TRUE)
158 connman_provider_set_state(data->provider,
159 CONNMAN_PROVIDER_STATE_IDLE);
160 else if (g_str_equal(data->state, "disconnect") == TRUE)
161 connman_provider_set_state(data->provider,
162 CONNMAN_PROVIDER_STATE_DISCONNECT);
163 else if (g_str_equal(data->state, "failure") == TRUE)
164 connman_provider_set_state(data->provider,
165 CONNMAN_PROVIDER_STATE_FAILURE);
167 connman_provider_set_state(data->provider,
168 CONNMAN_PROVIDER_STATE_UNKNOWN);
171 static int create_provider(struct connection_data *data, void *user_data)
173 struct connman_provider_driver *driver = user_data;
177 DBG("%s", data->path);
179 ident = g_strdup(get_ident(data->path));
181 data->provider = connman_provider_get(ident);
182 if (data->provider == NULL) {
187 DBG("provider %p name %s", data->provider, data->name);
189 connman_provider_set_data(data->provider, data);
190 connman_provider_set_driver(data->provider, driver);
192 err = connman_provider_create_service(data->provider);
194 if (g_str_equal(data->state, "ready") == TRUE) {
195 connman_provider_set_index(data->provider,
197 if (data->ip != NULL)
198 connman_provider_set_ipaddress(data->provider,
202 set_provider_state(data);
210 static void destroy_route(gpointer user_data)
212 struct vpn_route *route = user_data;
214 g_free(route->network);
215 g_free(route->netmask);
216 g_free(route->gateway);
220 static struct connection_data *create_connection_data(const char *path)
222 struct connection_data *data;
224 data = g_try_new0(struct connection_data, 1);
228 DBG("path %s", path);
230 data->path = g_strdup(path);
233 data->setting_strings = g_hash_table_new_full(g_str_hash,
234 g_str_equal, g_free, g_free);
236 data->server_routes = g_hash_table_new_full(g_direct_hash,
237 g_str_equal, g_free, destroy_route);
238 data->user_routes = g_hash_table_new_full(g_str_hash,
239 g_str_equal, g_free, destroy_route);
244 static int extract_ip(DBusMessageIter *array, int family,
245 struct connection_data *data)
247 DBusMessageIter dict;
248 char *address = NULL, *gateway = NULL, *netmask = NULL, *peer = NULL;
249 unsigned char prefix_len;
251 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
254 dbus_message_iter_recurse(array, &dict);
256 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
257 DBusMessageIter entry, value;
260 dbus_message_iter_recurse(&dict, &entry);
261 dbus_message_iter_get_basic(&entry, &key);
263 dbus_message_iter_next(&entry);
264 dbus_message_iter_recurse(&entry, &value);
266 if (g_str_equal(key, "Address") == TRUE) {
267 dbus_message_iter_get_basic(&value, &address);
268 DBG("address %s", address);
269 } else if (g_str_equal(key, "Netmask") == TRUE) {
270 dbus_message_iter_get_basic(&value, &netmask);
271 DBG("netmask %s", netmask);
272 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
273 dbus_message_iter_get_basic(&value, &netmask);
274 DBG("prefix length %s", netmask);
275 } else if (g_str_equal(key, "Peer") == TRUE) {
276 dbus_message_iter_get_basic(&value, &peer);
277 DBG("peer %s", peer);
278 } else if (g_str_equal(key, "Gateway") == TRUE) {
279 dbus_message_iter_get_basic(&value, &gateway);
280 DBG("gateway %s", gateway);
283 dbus_message_iter_next(&dict);
286 data->ip = connman_ipaddress_alloc(family);
287 if (data->ip == NULL)
292 connman_ipaddress_set_ipv4(data->ip, address, netmask,
296 prefix_len = atoi(netmask);
297 connman_ipaddress_set_ipv6(data->ip, address, prefix_len,
304 connman_ipaddress_set_peer(data->ip, peer);
309 static int extract_nameservers(DBusMessageIter *array,
310 struct connection_data *data)
312 DBusMessageIter entry;
313 char **nameservers = NULL;
316 dbus_message_iter_recurse(array, &entry);
318 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
319 const char *nameserver;
321 dbus_message_iter_get_basic(&entry, &nameserver);
323 nameservers = g_try_renew(char *, nameservers, i + 2);
324 if (nameservers == NULL)
327 DBG("[%d] %s", i, nameserver);
329 nameservers[i] = g_strdup(nameserver);
330 if (nameservers[i] == NULL)
333 nameservers[++i] = NULL;
335 dbus_message_iter_next(&entry);
338 g_strfreev(data->nameservers);
339 data->nameservers = nameservers;
344 static void connect_reply(DBusPendingCall *call, void *user_data)
349 if (dbus_pending_call_get_completed(call) == FALSE)
352 DBG("user_data %p", user_data);
354 reply = dbus_pending_call_steal_reply(call);
356 dbus_error_init(&error);
358 if (dbus_set_error_from_message(&error, reply) == TRUE) {
359 if (dbus_error_has_name(&error, CONNMAN_ERROR_INTERFACE
360 ".InProgress") == FALSE) {
361 connman_error("Connect reply: %s (%s)", error.message,
363 dbus_error_free(&error);
366 dbus_error_free(&error);
370 * The vpn connection is up when we get a "ready" state
371 * property so at this point we do nothing for the provider
376 dbus_message_unref(reply);
378 dbus_pending_call_unref(call);
381 static int connect_provider(struct connection_data *data, void *user_data)
383 DBusPendingCall *call;
384 DBusMessage *message;
386 DBG("data %p", data);
388 message = dbus_message_new_method_call(VPN_SERVICE, data->path,
389 VPN_CONNECTION_INTERFACE,
394 if (dbus_connection_send_with_reply(connection, message,
395 &call, DBUS_TIMEOUT) == FALSE) {
396 connman_error("Unable to call %s.%s()",
397 VPN_CONNECTION_INTERFACE, VPN_CONNECT);
398 dbus_message_unref(message);
403 dbus_message_unref(message);
407 dbus_pending_call_set_notify(call, connect_reply, NULL, NULL);
409 dbus_message_unref(message);
414 static void add_connection(const char *path, DBusMessageIter *properties,
417 struct connection_data *data;
420 data = g_hash_table_lookup(vpn_connections, path);
424 data = create_connection_data(path);
428 DBG("data %p path %s", data, path);
430 while (dbus_message_iter_get_arg_type(properties) ==
431 DBUS_TYPE_DICT_ENTRY) {
432 DBusMessageIter entry, value;
436 dbus_message_iter_recurse(properties, &entry);
437 dbus_message_iter_get_basic(&entry, &key);
439 dbus_message_iter_next(&entry);
440 dbus_message_iter_recurse(&entry, &value);
442 if (g_str_equal(key, "State") == TRUE) {
443 dbus_message_iter_get_basic(&value, &str);
444 DBG("state %s -> %s", data->state, str);
445 data->state = g_strdup(str);
446 } else if (g_str_equal(key, "IPv4") == TRUE) {
447 extract_ip(&value, AF_INET, data);
448 } else if (g_str_equal(key, "IPv6") == TRUE) {
449 extract_ip(&value, AF_INET6, data);
450 } else if (g_str_equal(key, "Name") == TRUE) {
451 dbus_message_iter_get_basic(&value, &str);
452 data->name = g_strdup(str);
453 } else if (g_str_equal(key, "Type") == TRUE) {
454 dbus_message_iter_get_basic(&value, &str);
455 data->type = g_strdup(str);
456 } else if (g_str_equal(key, "Host") == TRUE) {
457 dbus_message_iter_get_basic(&value, &str);
458 data->host = g_strdup(str);
459 } else if (g_str_equal(key, "Domain") == TRUE) {
460 dbus_message_iter_get_basic(&value, &str);
461 data->domain = g_strdup(str);
462 } else if (g_str_equal(key, "Nameservers") == TRUE) {
463 extract_nameservers(&value, data);
464 } else if (g_str_equal(key, "Index") == TRUE) {
465 dbus_message_iter_get_basic(&value, &data->index);
467 if (dbus_message_iter_get_arg_type(&value) ==
469 dbus_message_iter_get_basic(&value, &str);
470 g_hash_table_replace(data->setting_strings,
471 g_strdup(key), g_strdup(str));
473 DBG("unknown key %s", key);
477 dbus_message_iter_next(properties);
480 g_hash_table_insert(vpn_connections, g_strdup(path), data);
482 err = create_provider(data, user_data);
489 DBG("removing %s", path);
490 g_hash_table_remove(vpn_connections, path);
493 static void get_connections_reply(DBusPendingCall *call, void *user_data)
497 DBusMessageIter array, dict;
498 const char *signature = DBUS_TYPE_ARRAY_AS_STRING
499 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
500 DBUS_TYPE_OBJECT_PATH_AS_STRING
501 DBUS_TYPE_ARRAY_AS_STRING
502 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
503 DBUS_TYPE_STRING_AS_STRING
504 DBUS_TYPE_VARIANT_AS_STRING
505 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
506 DBUS_STRUCT_END_CHAR_AS_STRING;
510 reply = dbus_pending_call_steal_reply(call);
512 if (dbus_message_has_signature(reply, signature) == FALSE) {
513 connman_error("vpnd signature \"%s\" does not match "
515 dbus_message_get_signature(reply), signature);
519 dbus_error_init(&error);
521 if (dbus_set_error_from_message(&error, reply) == TRUE) {
522 connman_error("%s", error.message);
523 dbus_error_free(&error);
527 if (dbus_message_iter_init(reply, &array) == FALSE)
530 dbus_message_iter_recurse(&array, &dict);
532 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
533 DBusMessageIter value, properties;
536 dbus_message_iter_recurse(&dict, &value);
537 dbus_message_iter_get_basic(&value, &path);
539 dbus_message_iter_next(&value);
540 dbus_message_iter_recurse(&value, &properties);
542 add_connection(path, &properties, user_data);
544 dbus_message_iter_next(&dict);
548 dbus_message_unref(reply);
550 dbus_pending_call_unref(call);
553 static int get_connections(void *user_data)
555 DBusPendingCall *call;
556 DBusMessage *message;
560 message = dbus_message_new_method_call(VPN_SERVICE, "/",
561 VPN_MANAGER_INTERFACE,
566 if (dbus_connection_send_with_reply(connection, message,
567 &call, DBUS_TIMEOUT) == FALSE) {
568 connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
570 dbus_message_unref(message);
575 dbus_message_unref(message);
579 dbus_pending_call_set_notify(call, get_connections_reply,
582 dbus_message_unref(message);
587 static int provider_probe(struct connman_provider *provider)
592 static void remove_connection_reply(DBusPendingCall *call, void *user_data)
599 reply = dbus_pending_call_steal_reply(call);
601 dbus_error_init(&error);
603 if (dbus_set_error_from_message(&error, reply) == TRUE) {
605 * If the returned error is NotFound, it means that we
606 * have actually removed the provider in vpnd already.
608 if (dbus_error_has_name(&error, CONNMAN_ERROR_INTERFACE
609 ".NotFound") == FALSE)
610 connman_error("%s", error.message);
612 dbus_error_free(&error);
615 dbus_message_unref(reply);
617 dbus_pending_call_unref(call);
620 static int provider_remove(struct connman_provider *provider)
622 DBusPendingCall *call;
623 DBusMessage *message;
624 struct connection_data *data;
626 data = connman_provider_get_data(provider);
628 DBG("provider %p data %p", provider, data);
631 * When provider.c:provider_remove() calls this function,
632 * it will remove the provider itself after the call.
633 * This means that we cannot use the provider pointer later
634 * as it is no longer valid.
636 data->provider = NULL;
638 message = dbus_message_new_method_call(VPN_SERVICE, "/",
639 VPN_MANAGER_INTERFACE,
644 dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &data->path,
647 if (dbus_connection_send_with_reply(connection, message,
648 &call, DBUS_TIMEOUT) == FALSE) {
649 connman_error("Unable to call %s.%s()", VPN_MANAGER_INTERFACE,
651 dbus_message_unref(message);
656 dbus_message_unref(message);
660 dbus_pending_call_set_notify(call, remove_connection_reply,
663 dbus_message_unref(message);
668 static int provider_connect(struct connman_provider *provider)
670 struct connection_data *data;
672 data = connman_provider_get_data(provider);
676 return connect_provider(data, NULL);
680 static void disconnect_reply(DBusPendingCall *call, void *user_data)
687 reply = dbus_pending_call_steal_reply(call);
689 dbus_error_init(&error);
691 if (dbus_set_error_from_message(&error, reply) == TRUE) {
692 connman_error("%s", error.message);
693 dbus_error_free(&error);
698 dbus_message_unref(reply);
700 dbus_pending_call_unref(call);
703 static int disconnect_provider(struct connection_data *data)
705 DBusPendingCall *call;
706 DBusMessage *message;
708 DBG("data %p path %s", data, data->path);
710 message = dbus_message_new_method_call(VPN_SERVICE, data->path,
711 VPN_CONNECTION_INTERFACE,
716 if (dbus_connection_send_with_reply(connection, message,
717 &call, DBUS_TIMEOUT) == FALSE) {
718 connman_error("Unable to call %s.%s()",
719 VPN_CONNECTION_INTERFACE, VPN_DISCONNECT);
720 dbus_message_unref(message);
725 dbus_message_unref(message);
729 dbus_pending_call_set_notify(call, disconnect_reply, NULL, NULL);
731 dbus_message_unref(message);
733 connman_provider_set_state(data->provider,
734 CONNMAN_PROVIDER_STATE_DISCONNECT);
736 * We return 0 here instead of -EINPROGRESS because
737 * __connman_service_disconnect() needs to return something
738 * to gdbus so that gdbus will not call Disconnect() more
739 * than once. This way we do not need to pass the dbus reply
740 * message around the code.
745 static int provider_disconnect(struct connman_provider *provider)
747 struct connection_data *data;
749 DBG("provider %p", provider);
751 data = connman_provider_get_data(provider);
755 if (g_str_equal(data->state, "ready") == TRUE ||
756 g_str_equal(data->state, "configuration") == TRUE)
757 return disconnect_provider(data);
762 static void configuration_create_reply(DBusPendingCall *call, void *user_data)
766 DBusMessageIter iter;
767 const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
770 DBG("user %p", user_data);
772 reply = dbus_pending_call_steal_reply(call);
774 if (dbus_message_has_signature(reply, signature) == FALSE) {
775 connman_error("vpn configuration signature \"%s\" does not "
776 "match expected \"%s\"",
777 dbus_message_get_signature(reply), signature);
781 dbus_error_init(&error);
783 if (dbus_set_error_from_message(&error, reply) == TRUE) {
784 connman_error("dbus error: %s", error.message);
785 dbus_error_free(&error);
789 if (dbus_message_iter_init(reply, &iter) == FALSE)
792 dbus_message_iter_get_basic(&iter, &path);
795 * Then try to connect the VPN as expected by ConnectProvider API
800 dbus_message_unref(reply);
802 dbus_pending_call_unref(call);
805 static void set_dbus_ident(char *ident)
807 int i, len = strlen(ident);
809 for (i = 0; i < len; i++) {
810 if (ident[i] >= '0' && ident[i] <= '9')
812 if (ident[i] >= 'a' && ident[i] <= 'z')
814 if (ident[i] >= 'A' && ident[i] <= 'Z')
820 static struct vpn_route *parse_user_route(const char *user_route)
822 char *network, *netmask;
823 struct vpn_route *route = NULL;
824 int family = PF_UNSPEC;
825 char **elems = g_strsplit(user_route, "/", 0);
831 if (network == NULL || *network == '\0') {
832 DBG("no network/netmask set");
837 if (netmask != NULL && *netmask == '\0') {
838 DBG("no netmask set");
842 if (g_strrstr(network, ":") != NULL)
844 else if (g_strrstr(network, ".") != NULL) {
847 if (g_strrstr(netmask, ".") == NULL) {
848 /* We have netmask length */
850 struct in_addr netmask_in;
851 unsigned char prefix_len = 32;
853 if (netmask != NULL) {
855 long int value = strtol(netmask, &ptr, 10);
856 if (ptr != netmask && *ptr == '\0' &&
861 addr = 0xffffffff << (32 - prefix_len);
862 netmask_in.s_addr = htonl(addr);
863 netmask = inet_ntoa(netmask_in);
865 DBG("network %s netmask %s", network, netmask);
869 route = g_try_new(struct vpn_route, 1);
873 route->network = g_strdup(network);
874 route->netmask = g_strdup(netmask);
875 route->gateway = NULL;
876 route->family = family;
883 static GSList *get_user_networks(DBusMessageIter *array)
885 DBusMessageIter entry;
888 dbus_message_iter_recurse(array, &entry);
890 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
892 struct vpn_route *route;
894 dbus_message_iter_get_basic(&entry, &val);
896 route = parse_user_route(val);
898 list = g_slist_prepend(list, route);
900 dbus_message_iter_next(&entry);
906 static void append_route(DBusMessageIter *iter, void *user_data)
908 struct vpn_route *route = user_data;
909 DBusMessageIter item;
912 connman_dbus_dict_open(iter, &item);
917 if (route->family == AF_INET)
919 else if (route->family == AF_INET6)
923 connman_dbus_dict_append_basic(&item, "ProtocolFamily",
924 DBUS_TYPE_INT32, &family);
926 if (route->network != NULL)
927 connman_dbus_dict_append_basic(&item, "Network",
928 DBUS_TYPE_STRING, &route->network);
930 if (route->netmask != NULL)
931 connman_dbus_dict_append_basic(&item, "Netmask",
932 DBUS_TYPE_STRING, &route->netmask);
934 if (route->gateway != NULL)
935 connman_dbus_dict_append_basic(&item, "Gateway",
936 DBUS_TYPE_STRING, &route->gateway);
939 connman_dbus_dict_close(iter, &item);
942 static void append_routes(DBusMessageIter *iter, void *user_data)
944 GSList *list, *routes = user_data;
946 DBG("routes %p", routes);
948 for (list = routes; list != NULL; list = g_slist_next(list)) {
949 DBusMessageIter dict;
950 struct vpn_route *route = list->data;
952 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL,
954 append_route(&dict, route);
955 dbus_message_iter_close_container(iter, &dict);
959 static int create_configuration(DBusMessage *msg)
961 DBusMessage *new_msg;
962 DBusPendingCall *call;
963 DBusMessageIter iter, array, new_iter, new_dict;
964 const char *type = NULL, *name = NULL;
965 const char *host = NULL, *domain = NULL;
966 char *ident, *me = NULL;
969 struct connection_data *data;
970 GSList *networks = NULL;
973 * We copy the old message data into new message. We cannot
974 * just use the old message as is because the user route
975 * information is not in the same format in vpnd.
977 new_msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
978 dbus_message_iter_init_append(new_msg, &new_iter);
979 connman_dbus_dict_open(&new_iter, &new_dict);
981 dbus_message_iter_init(msg, &iter);
982 dbus_message_iter_recurse(&iter, &array);
984 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
985 DBusMessageIter entry, value;
990 dbus_message_iter_recurse(&array, &entry);
991 dbus_message_iter_get_basic(&entry, &key);
993 dbus_message_iter_next(&entry);
994 dbus_message_iter_recurse(&entry, &value);
996 value_type = dbus_message_iter_get_arg_type(&value);
999 switch (value_type) {
1000 case DBUS_TYPE_STRING:
1001 dbus_message_iter_get_basic(&value, &item_value);
1003 if (g_str_equal(key, "Type") == TRUE) {
1004 type = (const char *)item_value;
1005 } else if (g_str_equal(key, "Name") == TRUE) {
1006 name = (const char *)item_value;
1007 } else if (g_str_equal(key, "Host") == TRUE) {
1008 host = (const char *)item_value;
1009 } else if (g_str_equal(key, "VPN.Domain") == TRUE) {
1010 domain = (const char *)item_value;
1013 DBG("%s %s", key, (char *)item_value);
1015 if (item_value != NULL)
1016 connman_dbus_dict_append_basic(&new_dict, key,
1017 value_type, &item_value);
1019 case DBUS_TYPE_ARRAY:
1020 if (g_str_equal(key, "Networks") == TRUE) {
1021 networks = get_user_networks(&value);
1022 connman_dbus_dict_append_array(&new_dict,
1024 DBUS_TYPE_DICT_ENTRY,
1031 dbus_message_iter_next(&array);
1034 connman_dbus_dict_close(&new_iter, &new_dict);
1036 DBG("VPN type %s name %s host %s domain %s networks %p",
1037 type, name, host, domain, networks);
1039 if (host == NULL || domain == NULL) {
1044 if (type == NULL || name == NULL) {
1049 ident = g_strdup_printf("%s_%s", host, domain);
1050 set_dbus_ident(ident);
1052 DBG("ident %s", ident);
1054 data = g_hash_table_lookup(vpn_connections, ident);
1056 if (data->call != NULL) {
1057 connman_error("Dbus call already pending");
1062 data = create_connection_data(ident);
1068 g_hash_table_insert(vpn_connections, g_strdup(ident), data);
1072 * User called net.connman.Manager.ConnectProvider if we are here.
1073 * So use the data from original message in the new msg.
1075 me = g_strdup(dbus_message_get_destination(msg));
1077 dbus_message_set_interface(new_msg, VPN_MANAGER_INTERFACE);
1078 dbus_message_set_path(new_msg, "/");
1079 dbus_message_set_destination(new_msg, VPN_SERVICE);
1080 dbus_message_set_sender(new_msg, me);
1081 dbus_message_set_member(new_msg, "Create");
1083 result = dbus_connection_send_with_reply(connection, new_msg,
1084 &call, DBUS_TIMEOUT);
1085 if (result == FALSE || call == NULL) {
1090 dbus_pending_call_set_notify(call, configuration_create_reply,
1095 dbus_message_unref(new_msg);
1097 if (networks != NULL)
1098 g_slist_free_full(networks, destroy_route);
1105 static void set_route(struct connection_data *data, struct vpn_route *route)
1107 if (route->family == AF_INET6) {
1108 unsigned char prefix_len = atoi(route->netmask);
1110 connman_inet_add_ipv6_network_route(data->index,
1115 connman_inet_add_network_route(data->index, route->network,
1121 static int set_routes(struct connman_provider *provider,
1122 enum connman_provider_route_type type)
1124 struct connection_data *data;
1125 GHashTableIter iter;
1126 gpointer value, key;
1128 DBG("provider %p", provider);
1130 data = connman_provider_get_data(provider);
1134 if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
1135 type == CONNMAN_PROVIDER_ROUTE_USER) {
1136 g_hash_table_iter_init(&iter, data->user_routes);
1138 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
1139 set_route(data, value);
1142 if (type == CONNMAN_PROVIDER_ROUTE_ALL ||
1143 type == CONNMAN_PROVIDER_ROUTE_SERVER) {
1144 g_hash_table_iter_init(&iter, data->server_routes);
1146 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE)
1147 set_route(data, value);
1153 static connman_bool_t check_routes(struct connman_provider *provider)
1155 struct connection_data *data;
1157 DBG("provider %p", provider);
1159 data = connman_provider_get_data(provider);
1163 if (data->user_routes != NULL &&
1164 g_hash_table_size(data->user_routes) > 0)
1167 if (data->server_routes != NULL &&
1168 g_hash_table_size(data->server_routes) > 0)
1174 static struct connman_provider_driver provider_driver = {
1176 .type = CONNMAN_PROVIDER_TYPE_VPN,
1177 .probe = provider_probe,
1178 .remove = provider_remove,
1179 .connect = provider_connect,
1180 .disconnect = provider_disconnect,
1181 .set_property = set_string,
1182 .get_property = get_string,
1183 .create = create_configuration,
1184 .set_routes = set_routes,
1185 .check_routes = check_routes,
1188 static void destroy_provider(struct connection_data *data)
1190 DBG("data %p", data);
1192 if (g_str_equal(data->state, "ready") == TRUE ||
1193 g_str_equal(data->state, "configuration") == TRUE)
1194 connman_provider_disconnect(data->provider);
1196 if (data->call != NULL)
1197 dbus_pending_call_cancel(data->call);
1199 connman_provider_put(data->provider);
1201 data->provider = NULL;
1204 static void connection_destroy(gpointer hash_data)
1206 struct connection_data *data = hash_data;
1208 DBG("data %p", data);
1210 if (data->provider != NULL)
1211 destroy_provider(data);
1214 g_free(data->state);
1218 g_free(data->domain);
1219 g_hash_table_destroy(data->server_routes);
1220 g_hash_table_destroy(data->user_routes);
1221 g_strfreev(data->nameservers);
1222 g_hash_table_destroy(data->setting_strings);
1223 connman_ipaddress_free(data->ip);
1228 static void vpnd_created(DBusConnection *conn, void *user_data)
1230 DBG("connection %p", conn);
1232 if (starting_vpnd == TRUE) {
1233 vpn_connections = g_hash_table_new_full(g_str_hash,
1235 g_free, connection_destroy);
1236 get_connections(user_data);
1237 starting_vpnd = FALSE;
1241 static void vpnd_removed(DBusConnection *conn, void *user_data)
1243 DBG("connection %p", conn);
1245 g_hash_table_destroy(vpn_connections);
1246 vpn_connections = NULL;
1247 starting_vpnd = TRUE;
1250 static void remove_connection(DBusConnection *conn, const char *path)
1252 DBG("path %s", path);
1254 g_hash_table_remove(vpn_connections, path);
1257 static gboolean connection_removed(DBusConnection *conn, DBusMessage *message,
1261 const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
1263 if (dbus_message_has_signature(message, signature) == FALSE) {
1264 connman_error("vpn removed signature \"%s\" does not match "
1266 dbus_message_get_signature(message), signature);
1270 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
1272 remove_connection(conn, path);
1276 static gboolean connection_added(DBusConnection *conn, DBusMessage *message,
1279 DBusMessageIter iter, properties;
1281 const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING
1282 DBUS_TYPE_ARRAY_AS_STRING
1283 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1284 DBUS_TYPE_STRING_AS_STRING
1285 DBUS_TYPE_VARIANT_AS_STRING
1286 DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
1288 if (dbus_message_has_signature(message, signature) == FALSE) {
1289 connman_error("vpn ConnectionAdded signature \"%s\" does not "
1290 "match expected \"%s\"",
1291 dbus_message_get_signature(message), signature);
1297 if (dbus_message_iter_init(message, &iter) == FALSE)
1300 dbus_message_iter_get_basic(&iter, &path);
1302 dbus_message_iter_next(&iter);
1303 dbus_message_iter_recurse(&iter, &properties);
1305 add_connection(path, &properties, user_data);
1310 static int save_route(GHashTable *routes, int family, const char *network,
1311 const char *netmask, const char *gateway)
1313 struct vpn_route *route;
1314 char *key = g_strdup_printf("%d/%s/%s", family, network, netmask);
1316 DBG("family %d network %s netmask %s", family, network, netmask);
1318 route = g_hash_table_lookup(routes, key);
1319 if (route == NULL) {
1320 route = g_try_new0(struct vpn_route, 1);
1321 if (route == NULL) {
1322 connman_error("out of memory");
1326 route->family = family;
1327 route->network = g_strdup(network);
1328 route->netmask = g_strdup(netmask);
1329 route->gateway = g_strdup(gateway);
1331 g_hash_table_replace(routes, key, route);
1338 static int read_route_dict(GHashTable *routes, DBusMessageIter *dicts)
1340 DBusMessageIter dict;
1341 const char *network, *netmask, *gateway;
1344 dbus_message_iter_recurse(dicts, &dict);
1346 network = netmask = gateway = NULL;
1349 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1351 DBusMessageIter entry, value;
1354 dbus_message_iter_recurse(&dict, &entry);
1355 dbus_message_iter_get_basic(&entry, &key);
1357 dbus_message_iter_next(&entry);
1358 dbus_message_iter_recurse(&entry, &value);
1360 if (g_str_equal(key, "ProtocolFamily") == TRUE) {
1362 dbus_message_iter_get_basic(&value, &pf);
1371 DBG("family %d", family);
1372 } else if (g_str_equal(key, "Netmask") == TRUE) {
1373 dbus_message_iter_get_basic(&value, &netmask);
1374 DBG("netmask %s", netmask);
1375 } else if (g_str_equal(key, "Network") == TRUE) {
1376 dbus_message_iter_get_basic(&value, &network);
1377 DBG("host %s", network);
1378 } else if (g_str_equal(key, "Gateway") == TRUE) {
1379 dbus_message_iter_get_basic(&value, &gateway);
1380 DBG("gateway %s", gateway);
1383 dbus_message_iter_next(&dict);
1386 if (netmask == NULL || network == NULL || gateway == NULL) {
1387 DBG("Value missing.");
1391 return save_route(routes, family, network, netmask, gateway);
1394 static int routes_changed(DBusMessageIter *array, GHashTable *routes)
1396 DBusMessageIter entry;
1399 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) {
1400 DBG("Expecting array, ignoring routes.");
1404 while (dbus_message_iter_get_arg_type(array) == DBUS_TYPE_ARRAY) {
1406 dbus_message_iter_recurse(array, &entry);
1408 while (dbus_message_iter_get_arg_type(&entry) ==
1410 DBusMessageIter dicts;
1412 dbus_message_iter_recurse(&entry, &dicts);
1414 while (dbus_message_iter_get_arg_type(&dicts) ==
1416 int err = read_route_dict(routes, &dicts);
1419 dbus_message_iter_next(&dicts);
1422 dbus_message_iter_next(&entry);
1425 dbus_message_iter_next(array);
1431 static gboolean property_changed(DBusConnection *conn,
1432 DBusMessage *message,
1435 const char *path = dbus_message_get_path(message);
1436 struct connection_data *data = NULL;
1437 DBusMessageIter iter, value;
1438 connman_bool_t ip_set = FALSE;
1442 const char *signature = DBUS_TYPE_STRING_AS_STRING
1443 DBUS_TYPE_VARIANT_AS_STRING;
1445 if (dbus_message_has_signature(message, signature) == FALSE) {
1446 connman_error("vpn property signature \"%s\" does not match "
1448 dbus_message_get_signature(message), signature);
1452 data = g_hash_table_lookup(vpn_connections, path);
1456 if (dbus_message_iter_init(message, &iter) == FALSE)
1459 dbus_message_iter_get_basic(&iter, &key);
1461 dbus_message_iter_next(&iter);
1462 dbus_message_iter_recurse(&iter, &value);
1466 if (g_str_equal(key, "State") == TRUE) {
1467 dbus_message_iter_get_basic(&value, &str);
1469 DBG("%s %s -> %s", data->path, data->state, str);
1471 if (g_str_equal(data->state, str) == TRUE)
1474 g_free(data->state);
1475 data->state = g_strdup(str);
1477 set_provider_state(data);
1478 } else if (g_str_equal(key, "Index") == TRUE) {
1479 dbus_message_iter_get_basic(&value, &data->index);
1480 connman_provider_set_index(data->provider, data->index);
1481 } else if (g_str_equal(key, "IPv4") == TRUE) {
1482 err = extract_ip(&value, AF_INET, data);
1484 } else if (g_str_equal(key, "IPv6") == TRUE) {
1485 err = extract_ip(&value, AF_INET6, data);
1487 } else if (g_str_equal(key, "ServerRoutes") == TRUE) {
1488 err = routes_changed(&value, data->server_routes);
1490 * Note that the vpnd will delay the route sending a bit
1491 * (in order to collect the routes from VPN client),
1492 * so we might have got the State changed property before
1493 * we got ServerRoutes. This means that we must try to set
1494 * the routes here because they would be left unset otherwise.
1497 set_routes(data->provider,
1498 CONNMAN_PROVIDER_ROUTE_SERVER);
1499 } else if (g_str_equal(key, "UserRoutes") == TRUE) {
1500 err = routes_changed(&value, data->user_routes);
1502 set_routes(data->provider,
1503 CONNMAN_PROVIDER_ROUTE_USER);
1504 } else if (g_str_equal(key, "Nameservers") == TRUE) {
1505 extract_nameservers(&value, data);
1508 if (ip_set == TRUE && err == 0) {
1509 err = connman_provider_set_ipaddress(data->provider, data->ip);
1511 DBG("setting provider IP address failed (%s/%d)",
1512 strerror(-err), -err);
1518 static int vpn_init(void)
1522 connection = connman_dbus_get_connection();
1523 if (connection == NULL)
1526 watch = g_dbus_add_service_watch(connection, VPN_SERVICE,
1527 vpnd_created, vpnd_removed, &provider_driver, NULL);
1529 added_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1530 VPN_MANAGER_INTERFACE,
1531 CONNECTION_ADDED, connection_added,
1532 &provider_driver, NULL);
1534 removed_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1535 VPN_MANAGER_INTERFACE,
1536 CONNECTION_REMOVED, connection_removed,
1539 property_watch = g_dbus_add_signal_watch(connection, VPN_SERVICE, NULL,
1540 VPN_CONNECTION_INTERFACE,
1541 PROPERTY_CHANGED, property_changed,
1544 if (added_watch == 0 || removed_watch == 0 || property_watch == 0) {
1549 err = connman_provider_driver_register(&provider_driver);
1551 vpnd_created(connection, &provider_driver);
1556 g_dbus_remove_watch(connection, watch);
1557 g_dbus_remove_watch(connection, added_watch);
1558 g_dbus_remove_watch(connection, removed_watch);
1559 g_dbus_remove_watch(connection, property_watch);
1561 dbus_connection_unref(connection);
1566 static void vpn_exit(void)
1568 g_dbus_remove_watch(connection, watch);
1569 g_dbus_remove_watch(connection, added_watch);
1570 g_dbus_remove_watch(connection, removed_watch);
1571 g_dbus_remove_watch(connection, property_watch);
1573 connman_provider_driver_unregister(&provider_driver);
1575 g_hash_table_destroy(vpn_connections);
1577 dbus_connection_unref(connection);
1580 CONNMAN_PLUGIN_DEFINE(vpn, "VPN plugin", VERSION,
1581 CONNMAN_PLUGIN_PRIORITY_DEFAULT, vpn_init, vpn_exit)