5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
6 * Copyright (C) 2011-2014 BMW Car IT GmbH.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 static DBusConnection *connection;
34 static GHashTable *session_hash;
35 static GHashTable *service_hash;
36 static struct connman_session *ecall_session;
37 static uint32_t session_mark = 256;
40 struct connman_session_config config;
41 enum connman_session_state state;
44 struct connman_session {
52 struct session_info *info;
53 struct session_info *info_last;
54 struct connman_service *service;
55 struct connman_service *service_last;
56 struct connman_session_config *policy_config;
57 GSList *user_allowed_bearers;
58 char *user_allowed_interface;
62 enum connman_session_id_type id_type;
63 struct firewall_context *fw;
68 unsigned char prefixlen;
73 struct connman_service_info {
74 struct connman_service *service;
83 struct firewall_context *fw;
88 static struct connman_session_policy *policy;
89 static void session_activate(struct connman_session *session);
90 static void session_deactivate(struct connman_session *session);
91 static void update_session_state(struct connman_session *session);
93 static void cleanup_service(gpointer data)
95 struct connman_service_info *info = data;
97 g_slist_free(info->sessions);
101 static const char *state2string(enum connman_session_state state)
104 case CONNMAN_SESSION_STATE_DISCONNECTED:
105 return "disconnected";
106 case CONNMAN_SESSION_STATE_CONNECTED:
108 case CONNMAN_SESSION_STATE_ONLINE:
115 static const char *type2string(enum connman_session_type type)
118 case CONNMAN_SESSION_TYPE_UNKNOWN:
120 case CONNMAN_SESSION_TYPE_ANY:
122 case CONNMAN_SESSION_TYPE_LOCAL:
124 case CONNMAN_SESSION_TYPE_INTERNET:
131 enum connman_session_roaming_policy connman_session_parse_roaming_policy(const char *policy)
133 if (g_strcmp0(policy, "default") == 0)
134 return CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
135 else if (g_strcmp0(policy, "always") == 0)
136 return CONNMAN_SESSION_ROAMING_POLICY_ALWAYS;
137 else if (g_strcmp0(policy, "forbidden") == 0)
138 return CONNMAN_SESSION_ROAMING_POLICY_FORBIDDEN;
139 else if (g_strcmp0(policy, "national") == 0)
140 return CONNMAN_SESSION_ROAMING_POLICY_NATIONAL;
141 else if (g_strcmp0(policy, "international") == 0)
142 return CONNMAN_SESSION_ROAMING_POLICY_INTERNATIONAL;
144 return CONNMAN_SESSION_ROAMING_POLICY_UNKNOWN;
147 enum connman_session_type connman_session_parse_connection_type(const char *type)
149 if (g_strcmp0(type, "any") == 0)
150 return CONNMAN_SESSION_TYPE_ANY;
151 if (g_strcmp0(type, "local") == 0)
152 return CONNMAN_SESSION_TYPE_LOCAL;
153 else if (g_strcmp0(type, "internet") == 0)
154 return CONNMAN_SESSION_TYPE_INTERNET;
156 return CONNMAN_SESSION_TYPE_UNKNOWN;
159 static int bearer2service(const char *bearer, enum connman_service_type *type)
161 if (g_strcmp0(bearer, "ethernet") == 0)
162 *type = CONNMAN_SERVICE_TYPE_ETHERNET;
163 else if (g_strcmp0(bearer, "wifi") == 0)
164 *type = CONNMAN_SERVICE_TYPE_WIFI;
165 else if (g_strcmp0(bearer, "gadget") == 0)
166 *type = CONNMAN_SERVICE_TYPE_GADGET;
167 else if (g_strcmp0(bearer, "bluetooth") == 0)
168 *type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
169 else if (g_strcmp0(bearer, "cellular") == 0)
170 *type = CONNMAN_SERVICE_TYPE_CELLULAR;
171 else if (g_strcmp0(bearer, "vpn") == 0)
172 *type = CONNMAN_SERVICE_TYPE_VPN;
179 static char *service2bearer(enum connman_service_type type)
182 case CONNMAN_SERVICE_TYPE_ETHERNET:
184 case CONNMAN_SERVICE_TYPE_GADGET:
186 case CONNMAN_SERVICE_TYPE_WIFI:
188 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
190 case CONNMAN_SERVICE_TYPE_CELLULAR:
192 case CONNMAN_SERVICE_TYPE_VPN:
194 case CONNMAN_SERVICE_TYPE_SYSTEM:
195 case CONNMAN_SERVICE_TYPE_GPS:
196 case CONNMAN_SERVICE_TYPE_P2P:
197 case CONNMAN_SERVICE_TYPE_UNKNOWN:
204 static struct fw_snat *fw_snat_lookup(int index, const char *addr)
206 struct fw_snat *fw_snat;
209 for (list = fw_snat_list; list; list = list->next) {
210 fw_snat = list->data;
212 if (fw_snat->index == index) {
213 if (g_strcmp0(addr, fw_snat->addr) != 0)
221 static int fw_snat_create(struct connman_session *session,
222 int index, const char *ifname, const char *addr)
224 struct fw_snat *fw_snat;
227 fw_snat = g_new0(struct fw_snat, 1);
229 fw_snat->fw = __connman_firewall_create();
230 fw_snat->index = index;
231 fw_snat->addr = g_strdup(addr);
233 fw_snat->id = __connman_firewall_enable_snat(fw_snat->fw,
234 index, ifname, addr);
235 if (fw_snat->id < 0) {
240 fw_snat_list = g_slist_prepend(fw_snat_list, fw_snat);
241 fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
245 __connman_firewall_destroy(fw_snat->fw);
246 g_free(fw_snat->addr);
251 static void fw_snat_ref(struct connman_session *session,
252 struct fw_snat *fw_snat)
254 if (g_slist_find(fw_snat->sessions, session))
256 fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
259 static void fw_snat_unref(struct connman_session *session,
260 struct fw_snat *fw_snat)
262 fw_snat->sessions = g_slist_remove(fw_snat->sessions, session);
263 if (fw_snat->sessions)
266 fw_snat_list = g_slist_remove(fw_snat_list, fw_snat);
268 __connman_firewall_disable_snat(fw_snat->fw);
269 __connman_firewall_destroy(fw_snat->fw);
273 static int init_firewall_session(struct connman_session *session)
275 struct firewall_context *fw;
277 struct connman_ipconfig *ipconfig = NULL;
278 const char *addr = NULL;
280 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
281 !session->info->config.source_ip_rule)
286 if (session->info->config.source_ip_rule) {
287 ipconfig = __connman_service_get_ip4config(session->service);
288 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN && !ipconfig)
292 fw = __connman_firewall_create();
296 if (session->info->config.source_ip_rule && ipconfig) {
297 addr = __connman_ipconfig_get_local(ipconfig);
300 err =__connman_firewall_enable_marking(fw,
301 session->policy_config->id_type,
302 session->policy_config->id,
303 addr, session->mark);
305 __connman_firewall_destroy(fw);
308 session->id_type = session->policy_config->id_type;
314 static void cleanup_firewall_session(struct connman_session *session)
319 __connman_firewall_disable_marking(session->fw);
320 __connman_firewall_disable_snat(session->fw);
321 __connman_firewall_destroy(session->fw);
326 static int init_routing_table(struct connman_session *session)
330 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
331 !session->info->config.source_ip_rule)
334 if (!session->service)
339 err = __connman_inet_add_fwmark_rule(session->mark,
340 AF_INET, session->mark);
344 err = __connman_inet_add_fwmark_rule(session->mark,
345 AF_INET6, session->mark);
347 __connman_inet_del_fwmark_rule(session->mark,
348 AF_INET, session->mark);
349 session->policy_routing = true;
354 static void del_default_route(struct connman_session *session)
356 if (!session->gateway)
359 DBG("index %d routing table %d default gateway %s/%u",
360 session->index, session->mark, session->gateway, session->prefixlen);
362 __connman_inet_del_subnet_from_table(session->mark,
363 session->index, session->gateway, session->prefixlen);
365 __connman_inet_del_default_from_table(session->mark,
366 session->index, session->gateway);
367 g_free(session->gateway);
368 session->gateway = NULL;
369 session->prefixlen = 0;
373 static void add_default_route(struct connman_session *session)
375 struct connman_ipconfig *ipconfig;
377 struct in_addr addr = { INADDR_ANY };
379 if (!session->service)
382 ipconfig = __connman_service_get_ip4config(session->service);
383 session->index = __connman_ipconfig_get_index(ipconfig);
384 session->gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig));
386 if (!session->gateway)
387 session->gateway = g_strdup(inet_ntoa(addr));
389 session->prefixlen = __connman_ipconfig_get_prefixlen(ipconfig);
391 DBG("index %d routing table %d default gateway %s/%u",
392 session->index, session->mark, session->gateway, session->prefixlen);
394 err = __connman_inet_add_default_to_table(session->mark,
395 session->index, session->gateway);
397 DBG("session %p %s", session, strerror(-err));
399 err = __connman_inet_add_subnet_to_table(session->mark,
400 session->index, session->gateway, session->prefixlen);
402 DBG("session add subnet route %p %s", session, strerror(-err));
405 static void del_nat_rules(struct connman_session *session)
407 struct fw_snat *fw_snat;
409 if (!session->snat_enabled)
412 session->snat_enabled = false;
413 fw_snat = fw_snat_lookup(session->index, session->addr);
418 fw_snat_unref(session, fw_snat);
421 static void add_nat_rules(struct connman_session *session)
423 struct connman_ipconfig *ipconfig;
424 struct fw_snat *fw_snat;
429 if (!session->service)
432 ipconfig = __connman_service_get_ip4config(session->service);
433 index = __connman_ipconfig_get_index(ipconfig);
434 ifname = connman_inet_ifname(index);
435 addr = __connman_ipconfig_get_local(ipconfig);
440 g_free(session->addr);
441 session->addr = g_strdup(addr);
443 session->snat_enabled = true;
444 fw_snat = fw_snat_lookup(index, session->addr);
446 fw_snat_ref(session, fw_snat);
450 err = fw_snat_create(session, index, ifname, addr);
452 DBG("failed to add SNAT rule");
453 session->snat_enabled = false;
459 uint32_t connman_session_firewall_get_fwmark(struct connman_session *session)
461 return session->mark;
464 static void cleanup_routing_table(struct connman_session *session)
468 if (session->policy_routing) {
469 __connman_inet_del_fwmark_rule(session->mark,
470 AF_INET6, session->mark);
472 __connman_inet_del_fwmark_rule(session->mark,
473 AF_INET, session->mark);
474 session->policy_routing = false;
477 del_default_route(session);
480 static void update_firewall(struct connman_session *session)
482 cleanup_firewall_session(session);
483 init_firewall_session(session);
486 static void update_routing_table(struct connman_session *session)
488 cleanup_routing_table(session);
489 init_routing_table(session);
490 add_default_route(session);
493 static void cleanup_nat_rules(struct connman_session *session)
495 del_nat_rules(session);
498 static void destroy_policy_config(struct connman_session *session)
501 g_free(session->policy_config);
505 policy->destroy(session);
508 static void free_session(struct connman_session *session)
513 if (session->notify_watch > 0)
514 g_dbus_remove_watch(connection, session->notify_watch);
516 g_dbus_unregister_interface(connection, session->session_path,
517 CONNMAN_SESSION_INTERFACE);
519 destroy_policy_config(session);
520 g_slist_free(session->info->config.allowed_bearers);
521 g_free(session->info->config.allowed_interface);
522 g_free(session->owner);
523 g_free(session->session_path);
524 g_free(session->notify_path);
525 g_free(session->info);
526 g_free(session->info_last);
527 g_free(session->gateway);
528 g_free(session->addr);
533 static void set_active_session(struct connman_session *session, bool enable)
536 if (policy && policy->session_changed)
537 policy->session_changed(session, enable,
538 session->info->config.allowed_bearers);
540 __connman_service_set_active_session(enable,
541 session->info->config.allowed_bearers);
544 static void cleanup_session(gpointer user_data)
546 struct connman_session *session = user_data;
548 DBG("remove %s", session->session_path);
550 cleanup_nat_rules(session);
551 cleanup_routing_table(session);
552 cleanup_firewall_session(session);
555 set_active_session(session, false);
557 session_deactivate(session);
558 update_session_state(session);
560 g_slist_free(session->user_allowed_bearers);
561 g_free(session->user_allowed_interface);
563 free_session(session);
566 struct creation_data {
567 DBusMessage *pending;
568 struct connman_session *session;
571 enum connman_session_type type;
572 GSList *allowed_bearers;
573 char *allowed_interface;
575 char *context_identifier;
578 static void cleanup_creation_data(struct creation_data *creation_data)
583 if (creation_data->pending)
584 dbus_message_unref(creation_data->pending);
585 if (creation_data->context_identifier)
586 g_free(creation_data->context_identifier);
588 g_slist_free(creation_data->allowed_bearers);
589 g_free(creation_data->allowed_interface);
590 g_free(creation_data);
593 static int create_policy_config(struct connman_session *session,
594 connman_session_config_func_t cb,
595 struct creation_data *creation_data)
597 struct connman_session_config *config;
600 config = connman_session_create_default_config();
602 free_session(session);
603 cleanup_creation_data(creation_data);
607 return cb(session, config, creation_data, 0);
610 return policy->create(session, cb, creation_data);
613 int connman_session_policy_register(struct connman_session_policy *plugin)
618 if (!plugin->create || !plugin->destroy)
621 DBG("name %s", plugin->name);
628 void connman_session_policy_unregister(struct connman_session_policy *plugin)
630 if (plugin != policy)
633 DBG("name %s", policy->name);
638 static int default_bearers[] = {
639 CONNMAN_SERVICE_TYPE_ETHERNET,
640 CONNMAN_SERVICE_TYPE_WIFI,
641 CONNMAN_SERVICE_TYPE_BLUETOOTH,
642 CONNMAN_SERVICE_TYPE_CELLULAR,
643 CONNMAN_SERVICE_TYPE_GADGET,
646 static void add_default_bearer_types(GSList **list)
650 for (i = 0; i < G_N_ELEMENTS(default_bearers); i++)
651 *list = g_slist_append(*list,
652 GINT_TO_POINTER(default_bearers[i]));
655 void connman_session_set_default_config(struct connman_session_config *config)
657 config->id_type = CONNMAN_SESSION_ID_TYPE_UNKNOWN;
661 config->priority = FALSE;
662 config->roaming_policy = CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
663 config->type = CONNMAN_SESSION_TYPE_ANY;
664 config->ecall = FALSE;
666 g_slist_free(config->allowed_bearers);
667 config->allowed_bearers = NULL;
668 add_default_bearer_types(&config->allowed_bearers);
671 struct connman_session_config *connman_session_create_default_config(void)
673 struct connman_session_config *config;
675 config = g_new0(struct connman_session_config, 1);
676 connman_session_set_default_config(config);
681 static enum connman_session_type apply_policy_on_type(
682 enum connman_session_type policy,
683 enum connman_session_type type)
685 if (type == CONNMAN_SESSION_TYPE_UNKNOWN)
686 return CONNMAN_SESSION_TYPE_UNKNOWN;
688 if (policy == CONNMAN_SESSION_TYPE_ANY)
691 if (policy == CONNMAN_SESSION_TYPE_LOCAL)
692 return CONNMAN_SESSION_TYPE_LOCAL;
694 return CONNMAN_SESSION_TYPE_INTERNET;
697 int connman_session_parse_bearers(const char *token, GSList **list)
699 enum connman_service_type bearer;
702 if (g_strcmp0(token, "") == 0)
705 if (g_strcmp0(token, "*") == 0) {
706 add_default_bearer_types(list);
710 err = bearer2service(token, &bearer);
714 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
719 static int parse_bearers(DBusMessageIter *iter, GSList **list)
721 DBusMessageIter array;
724 dbus_message_iter_recurse(iter, &array);
728 while ((type = dbus_message_iter_get_arg_type(&array)) !=
730 char *bearer_name = NULL;
732 if (type != DBUS_TYPE_STRING) {
738 dbus_message_iter_get_basic(&array, &bearer_name);
740 err = connman_session_parse_bearers(bearer_name, list);
747 dbus_message_iter_next(&array);
753 static void filter_bearer(GSList *bearers,
754 enum connman_service_type policy,
757 enum connman_service_type bearer;
763 for (it = bearers; it; it = it->next) {
764 bearer = GPOINTER_TO_INT(it->data);
766 if (policy != bearer)
769 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
774 static void apply_policy_on_bearers(GSList *policy_bearers, GSList *bearers,
777 enum connman_service_type policy_bearer;
782 for (it = policy_bearers; it; it = it->next) {
783 policy_bearer = GPOINTER_TO_INT(it->data);
785 filter_bearer(bearers, policy_bearer, list);
789 static char * apply_policy_on_interface(const char *policy_interface,
790 const char *user_interface)
792 if (policy_interface)
793 return g_strdup(policy_interface);
794 else if (user_interface)
795 return g_strdup(user_interface);
800 const char *connman_session_get_owner(struct connman_session *session)
802 return session->owner;
805 static void append_allowed_bearers(DBusMessageIter *iter, void *user_data)
807 struct session_info *info = user_data;
810 for (list = info->config.allowed_bearers;
811 list; list = list->next) {
812 enum connman_service_type bearer = GPOINTER_TO_INT(list->data);
813 const char *name = __connman_service_type2string(bearer);
818 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
823 static void append_ipconfig_ipv4(DBusMessageIter *iter, void *user_data)
825 struct connman_service *service = user_data;
826 struct connman_ipconfig *ipconfig_ipv4;
831 if (!__connman_service_is_connected_state(service,
832 CONNMAN_IPCONFIG_TYPE_IPV4))
835 ipconfig_ipv4 = __connman_service_get_ip4config(service);
839 __connman_ipconfig_append_ipv4(ipconfig_ipv4, iter);
842 static void append_ipconfig_ipv6(DBusMessageIter *iter, void *user_data)
844 struct connman_service *service = user_data;
845 struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
850 if (!__connman_service_is_connected_state(service,
851 CONNMAN_IPCONFIG_TYPE_IPV6))
854 ipconfig_ipv4 = __connman_service_get_ip4config(service);
855 ipconfig_ipv6 = __connman_service_get_ip6config(service);
859 __connman_ipconfig_append_ipv6(ipconfig_ipv6, iter, ipconfig_ipv4);
862 static void append_notify(DBusMessageIter *dict,
863 struct connman_session *session)
865 struct session_info *info = session->info;
866 struct session_info *info_last = session->info_last;
867 struct connman_service *service;
868 enum connman_service_type type;
869 const char *name, *bearer;
873 if (session->append_all || info->state != info_last->state) {
874 const char *state = state2string(info->state);
876 connman_dbus_dict_append_basic(dict, "State",
879 info_last->state = info->state;
882 if (session->append_all || session->service != session->service_last) {
883 if (session->service) {
884 service = session->service;
885 name = __connman_service_get_name(service);
886 idx = __connman_service_get_index(service);
888 ifname = connman_inet_ifname(idx);
890 ifname = g_strdup("");
892 type = connman_service_get_type(service);
893 bearer = service2bearer(type);
897 ifname = g_strdup("");
901 connman_dbus_dict_append_basic(dict, "Name",
905 connman_dbus_dict_append_dict(dict, "IPv4",
906 append_ipconfig_ipv4,
909 connman_dbus_dict_append_dict(dict, "IPv6",
910 append_ipconfig_ipv6,
913 connman_dbus_dict_append_basic(dict, "Interface",
917 connman_dbus_dict_append_basic(dict, "Bearer",
923 session->service_last = session->service;
926 if (session->append_all ||
927 info->config.type != info_last->config.type) {
928 const char *type = type2string(info->config.type);
930 connman_dbus_dict_append_basic(dict, "ConnectionType",
933 info_last->config.type = info->config.type;
936 if (session->append_all ||
937 info->config.allowed_bearers != info_last->config.allowed_bearers) {
938 connman_dbus_dict_append_array(dict, "AllowedBearers",
940 append_allowed_bearers,
942 info_last->config.allowed_bearers = info->config.allowed_bearers;
945 if (session->append_all ||
946 info->config.allowed_interface != info_last->config.allowed_interface) {
947 char *ifname = info->config.allowed_interface;
950 connman_dbus_dict_append_basic(dict, "AllowedInterface",
953 info_last->config.allowed_interface = info->config.allowed_interface;
956 if (session->append_all ||
957 info->config.context_identifier != info_last->config.context_identifier) {
958 char *ifname = info->config.context_identifier;
961 connman_dbus_dict_append_basic(dict, "ContextIdentifier",
964 info_last->config.context_identifier = info->config.context_identifier;
967 if (session->append_all ||
968 info->config.source_ip_rule != info_last->config.source_ip_rule) {
969 dbus_bool_t source_ip_rule = FALSE;
970 if (info->config.source_ip_rule)
971 source_ip_rule = TRUE;
972 connman_dbus_dict_append_basic(dict, "SourceIPRule",
975 info_last->config.source_ip_rule = info->config.source_ip_rule;
978 session->append_all = false;
981 static bool compute_notifiable_changes(struct connman_session *session)
983 struct session_info *info_last = session->info_last;
984 struct session_info *info = session->info;
986 if (session->append_all)
989 if (info->state != info_last->state)
992 if (session->service != session->service_last &&
993 info->state >= CONNMAN_SESSION_STATE_CONNECTED)
996 if (info->config.allowed_bearers != info_last->config.allowed_bearers ||
997 info->config.type != info_last->config.type ||
998 info->config.allowed_interface != info_last->config.allowed_interface ||
999 info->config.source_ip_rule != info_last->config.source_ip_rule)
1005 static gboolean session_notify(gpointer user_data)
1007 struct connman_session *session = user_data;
1009 DBusMessageIter array, dict;
1011 if (!compute_notifiable_changes(session))
1014 DBG("session %p owner %s notify_path %s", session,
1015 session->owner, session->notify_path);
1017 msg = dbus_message_new_method_call(session->owner, session->notify_path,
1018 CONNMAN_NOTIFICATION_INTERFACE,
1023 dbus_message_iter_init_append(msg, &array);
1024 connman_dbus_dict_open(&array, &dict);
1026 append_notify(&dict, session);
1028 connman_dbus_dict_close(&array, &dict);
1030 g_dbus_send_message(connection, msg);
1035 static void ipconfig_ipv4_changed(struct connman_session *session)
1037 connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1038 "IPv4", append_ipconfig_ipv4,
1042 static void ipconfig_ipv6_changed(struct connman_session *session)
1044 connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1045 "IPv6", append_ipconfig_ipv6,
1049 int connman_session_config_update(struct connman_session *session)
1051 struct session_info *info = session->info;
1052 GSList *allowed_bearers;
1053 char *allowed_interface;
1056 DBG("session %p", session);
1059 * We update all configuration even though only one entry
1060 * might have changed. We can still optimize this later.
1063 if (session->id_type != session->policy_config->id_type) {
1064 cleanup_firewall_session(session);
1065 err = init_firewall_session(session);
1067 connman_session_destroy(session);
1071 session->id_type = session->policy_config->id_type;
1074 apply_policy_on_bearers(
1075 session->policy_config->allowed_bearers,
1076 session->user_allowed_bearers,
1079 allowed_interface = apply_policy_on_interface(
1080 session->policy_config->allowed_interface,
1081 session->user_allowed_interface);
1083 if (session->active)
1084 set_active_session(session, false);
1086 session->active = false;
1087 session_deactivate(session);
1089 g_slist_free(info->config.allowed_bearers);
1090 info->config.allowed_bearers = allowed_bearers;
1092 g_free(info->config.allowed_interface);
1093 info->config.allowed_interface = allowed_interface;
1095 session_activate(session);
1097 info->config.type = apply_policy_on_type(
1098 session->policy_config->type,
1101 info->config.roaming_policy = session->policy_config->roaming_policy;
1103 info->config.ecall = session->policy_config->ecall;
1104 if (info->config.ecall)
1105 ecall_session = session;
1107 info->config.priority = session->policy_config->priority;
1109 session_notify(session);
1114 static DBusMessage *connect_session(DBusConnection *conn,
1115 DBusMessage *msg, void *user_data)
1117 struct connman_session *session = user_data;
1119 DBG("session %p", session);
1121 if (ecall_session) {
1122 if (ecall_session->ecall && ecall_session != session)
1123 return __connman_error_failed(msg, EBUSY);
1125 session->ecall = true;
1128 if (!session->active) {
1129 session->active = true;
1130 set_active_session(session, true);
1133 session_activate(session);
1135 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1137 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1140 static DBusMessage *disconnect_session(DBusConnection *conn,
1141 DBusMessage *msg, void *user_data)
1143 struct connman_session *session = user_data;
1145 DBG("session %p", session);
1147 if (ecall_session) {
1148 if (ecall_session->ecall && ecall_session != session)
1149 return __connman_error_failed(msg, EBUSY);
1151 session->ecall = false;
1154 if (session->active) {
1155 session->active = false;
1156 set_active_session(session, false);
1159 session_deactivate(session);
1160 update_session_state(session);
1162 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1165 static DBusMessage *change_session(DBusConnection *conn,
1166 DBusMessage *msg, void *user_data)
1168 struct connman_session *session = user_data;
1169 struct session_info *info = session->info;
1170 DBusMessageIter iter, value;
1173 GSList *allowed_bearers;
1176 DBG("session %p", session);
1177 if (!dbus_message_iter_init(msg, &iter))
1178 return __connman_error_invalid_arguments(msg);
1180 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1181 return __connman_error_invalid_arguments(msg);
1183 dbus_message_iter_get_basic(&iter, &name);
1184 dbus_message_iter_next(&iter);
1186 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1187 return __connman_error_invalid_arguments(msg);
1189 dbus_message_iter_recurse(&iter, &value);
1191 switch (dbus_message_iter_get_arg_type(&value)) {
1192 case DBUS_TYPE_ARRAY:
1193 if (g_str_equal(name, "AllowedBearers")) {
1194 err = parse_bearers(&value, &allowed_bearers);
1196 return __connman_error_failed(msg, -err);
1198 if (session->active)
1199 set_active_session(session, false);
1201 session->active = false;
1202 session_deactivate(session);
1203 update_session_state(session);
1205 g_slist_free(info->config.allowed_bearers);
1206 session->user_allowed_bearers = allowed_bearers;
1208 apply_policy_on_bearers(
1209 session->policy_config->allowed_bearers,
1210 session->user_allowed_bearers,
1211 &info->config.allowed_bearers);
1213 session_activate(session);
1218 case DBUS_TYPE_STRING:
1219 if (g_str_equal(name, "ConnectionType")) {
1220 dbus_message_iter_get_basic(&value, &val);
1221 info->config.type = apply_policy_on_type(
1222 session->policy_config->type,
1223 connman_session_parse_connection_type(val));
1224 } else if (g_str_equal(name, "AllowedInterface")) {
1225 dbus_message_iter_get_basic(&value, &val);
1226 if (session->active)
1227 set_active_session(session, false);
1229 session->active = false;
1230 session_deactivate(session);
1231 update_session_state(session);
1233 g_free(session->user_allowed_interface);
1234 /* empty string means allow any interface */
1235 if (!g_strcmp0(val, ""))
1236 session->user_allowed_interface = NULL;
1238 session->user_allowed_interface = g_strdup(val);
1240 info->config.allowed_interface = apply_policy_on_interface(
1241 session->policy_config->allowed_interface,
1242 session->user_allowed_interface);
1244 session_activate(session);
1249 case DBUS_TYPE_BOOLEAN:
1250 if (g_str_equal(name, "SourceIPRule")) {
1251 dbus_bool_t source_ip_rule;
1252 dbus_message_iter_get_basic(&value, &source_ip_rule);
1254 info->config.source_ip_rule = source_ip_rule;
1255 update_session_state(session);
1264 session_notify(session);
1266 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1269 return __connman_error_invalid_arguments(msg);
1272 static void release_session(gpointer key, gpointer value, gpointer user_data)
1274 struct connman_session *session = value;
1275 DBusMessage *message;
1277 DBG("owner %s path %s", session->owner, session->notify_path);
1279 if (session->notify_watch > 0)
1280 g_dbus_remove_watch(connection, session->notify_watch);
1282 g_dbus_unregister_interface(connection, session->session_path,
1283 CONNMAN_SESSION_INTERFACE);
1285 message = dbus_message_new_method_call(session->owner,
1286 session->notify_path,
1287 CONNMAN_NOTIFICATION_INTERFACE,
1292 dbus_message_set_no_reply(message, TRUE);
1294 g_dbus_send_message(connection, message);
1297 static int session_disconnect(struct connman_session *session)
1299 DBG("session %p, %s", session, session->owner);
1301 if (session->notify_watch > 0)
1302 g_dbus_remove_watch(connection, session->notify_watch);
1304 g_dbus_unregister_interface(connection, session->session_path,
1305 CONNMAN_SESSION_INTERFACE);
1307 g_hash_table_remove(session_hash, session->session_path);
1312 static void owner_disconnect(DBusConnection *conn, void *user_data)
1314 struct connman_session *session = user_data;
1316 DBG("session %p, %s died", session, session->owner);
1318 session_disconnect(session);
1321 static DBusMessage *destroy_session(DBusConnection *conn,
1322 DBusMessage *msg, void *user_data)
1324 struct connman_session *session = user_data;
1326 DBG("session %p", session);
1328 if (ecall_session && ecall_session != session)
1329 return __connman_error_failed(msg, EBUSY);
1331 session_disconnect(session);
1333 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1336 static const GDBusMethodTable session_methods[] = {
1337 { GDBUS_METHOD("Destroy", NULL, NULL, destroy_session) },
1338 { GDBUS_METHOD("Connect", NULL, NULL, connect_session) },
1339 { GDBUS_METHOD("Disconnect", NULL, NULL,
1340 disconnect_session ) },
1341 { GDBUS_METHOD("Change",
1342 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1343 NULL, change_session) },
1347 static int session_policy_config_cb(struct connman_session *session,
1348 struct connman_session_config *config,
1349 void *user_data, int err)
1351 struct creation_data *creation_data = user_data;
1352 struct session_info *info, *info_last;
1355 DBG("session %p config %p", session, config);
1360 session->policy_config = config;
1361 session->info->config.source_ip_rule = creation_data->source_ip_rule;
1363 session->mark = session_mark++;
1364 session->index = -1;
1366 err = init_firewall_session(session);
1370 err = init_routing_table(session);
1374 info = session->info;
1375 info_last = session->info_last;
1377 if (session->policy_config->ecall)
1378 ecall_session = session;
1380 info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1381 info->config.type = apply_policy_on_type(
1382 session->policy_config->type,
1383 creation_data->type);
1384 info->config.priority = session->policy_config->priority;
1385 info->config.roaming_policy = session->policy_config->roaming_policy;
1387 session->user_allowed_bearers = creation_data->allowed_bearers;
1388 creation_data->allowed_bearers = NULL;
1390 session->user_allowed_interface = creation_data->allowed_interface;
1391 creation_data->allowed_interface = NULL;
1393 apply_policy_on_bearers(
1394 session->policy_config->allowed_bearers,
1395 session->user_allowed_bearers,
1396 &info->config.allowed_bearers);
1398 info->config.allowed_interface = apply_policy_on_interface(
1399 session->policy_config->allowed_interface,
1400 session->user_allowed_interface);
1402 g_hash_table_replace(session_hash, session->session_path, session);
1404 DBG("add %s", session->session_path);
1406 if (!g_dbus_register_interface(connection, session->session_path,
1407 CONNMAN_SESSION_INTERFACE,
1408 session_methods, NULL, NULL,
1410 connman_error("Failed to register %s", session->session_path);
1411 g_hash_table_remove(session_hash, session->session_path);
1416 reply = g_dbus_create_reply(creation_data->pending,
1417 DBUS_TYPE_OBJECT_PATH, &session->session_path,
1419 g_dbus_send_message(connection, reply);
1420 creation_data->pending = NULL;
1422 info_last->state = info->state;
1423 info_last->config.priority = info->config.priority;
1424 info_last->config.roaming_policy = info->config.roaming_policy;
1425 info_last->config.allowed_bearers = info->config.allowed_bearers;
1426 info_last->config.allowed_interface = info->config.allowed_interface;
1427 info_last->config.source_ip_rule = info->config.source_ip_rule;
1429 session->append_all = true;
1431 cleanup_creation_data(creation_data);
1433 session_activate(session);
1438 cleanup_session(session);
1441 reply = __connman_error_failed(creation_data->pending, -err);
1442 g_dbus_send_message(connection, reply);
1443 creation_data->pending = NULL;
1445 cleanup_creation_data(creation_data);
1450 int __connman_session_create(DBusMessage *msg)
1452 const char *owner, *notify_path;
1453 char *session_path = NULL;
1454 DBusMessageIter iter, array;
1455 struct connman_session *session = NULL;
1456 struct creation_data *creation_data = NULL;
1457 bool user_allowed_bearers = false;
1458 bool user_connection_type = false;
1462 owner = dbus_message_get_sender(msg);
1464 DBG("owner %s", owner);
1466 if (ecall_session && ecall_session->ecall) {
1468 * If there is an emergency call already going on,
1469 * ignore session creation attempt
1475 creation_data = g_try_new0(struct creation_data, 1);
1476 if (!creation_data) {
1481 creation_data->pending = dbus_message_ref(msg);
1483 dbus_message_iter_init(msg, &iter);
1484 dbus_message_iter_recurse(&iter, &array);
1486 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1487 DBusMessageIter entry, value;
1488 const char *key, *val;
1490 dbus_message_iter_recurse(&array, &entry);
1491 dbus_message_iter_get_basic(&entry, &key);
1493 dbus_message_iter_next(&entry);
1494 dbus_message_iter_recurse(&entry, &value);
1496 switch (dbus_message_iter_get_arg_type(&value)) {
1497 case DBUS_TYPE_ARRAY:
1498 if (g_str_equal(key, "AllowedBearers")) {
1499 err = parse_bearers(&value,
1500 &creation_data->allowed_bearers);
1504 user_allowed_bearers = true;
1510 case DBUS_TYPE_STRING:
1511 if (g_str_equal(key, "ConnectionType")) {
1512 dbus_message_iter_get_basic(&value, &val);
1513 creation_data->type =
1514 connman_session_parse_connection_type(val);
1516 user_connection_type = true;
1517 } else if (g_str_equal(key, "ContextIdentifier")) {
1518 dbus_message_iter_get_basic(&value, &val);
1519 creation_data->context_identifier = g_strdup(val);
1520 } else if (g_str_equal(key, "AllowedInterface")) {
1521 dbus_message_iter_get_basic(&value, &val);
1522 creation_data->allowed_interface = g_strdup(val);
1528 case DBUS_TYPE_BOOLEAN:
1529 if (g_str_equal(key, "SourceIPRule")) {
1530 dbus_bool_t source_ip_rule;
1531 dbus_message_iter_get_basic(&value, &source_ip_rule);
1532 creation_data->source_ip_rule = source_ip_rule;
1543 dbus_message_iter_next(&array);
1547 * If the user hasn't provided a configuration, we set
1548 * the default configuration.
1550 * For AllowedBearers this is '*', ...
1552 if (!user_allowed_bearers) {
1553 add_default_bearer_types(&creation_data->allowed_bearers);
1554 if (!creation_data->allowed_bearers) {
1560 /* ... and for ConnectionType it is 'any'. */
1561 if (!user_connection_type)
1562 creation_data->type = CONNMAN_SESSION_TYPE_ANY;
1564 dbus_message_iter_next(&iter);
1565 dbus_message_iter_get_basic(&iter, ¬ify_path);
1572 str = g_strdup(owner);
1573 for (i = 0; str[i] != '\0'; i++)
1574 if (str[i] == ':' || str[i] == '.')
1576 session_path = g_strdup_printf("/sessions/%s%s", str, notify_path);
1579 if (!session_path) {
1584 session = g_hash_table_lookup(session_hash, session_path);
1586 g_free(session_path);
1592 session = g_try_new0(struct connman_session, 1);
1594 g_free(session_path);
1599 creation_data->session = session;
1600 session->session_path = session_path;
1602 session->info = g_try_new0(struct session_info, 1);
1603 if (!session->info) {
1608 session->info_last = g_try_new0(struct session_info, 1);
1609 if (!session->info_last) {
1614 session->owner = g_strdup(owner);
1615 session->notify_path = g_strdup(notify_path);
1616 session->notify_watch =
1617 g_dbus_add_disconnect_watch(connection, session->owner,
1618 owner_disconnect, session, NULL);
1620 err = create_policy_config(session, session_policy_config_cb,
1622 if (err < 0 && err != -EINPROGRESS)
1625 return -EINPROGRESS;
1628 connman_error("Failed to create session");
1630 free_session(session);
1632 cleanup_creation_data(creation_data);
1636 bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason)
1638 if (!policy || !policy->autoconnect)
1641 return policy->autoconnect(reason);
1644 void connman_session_destroy(struct connman_session *session)
1646 DBG("session %p", session);
1648 session_disconnect(session);
1651 int __connman_session_destroy(DBusMessage *msg)
1653 const char *owner, *session_path;
1654 struct connman_session *session;
1656 owner = dbus_message_get_sender(msg);
1658 DBG("owner %s", owner);
1660 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &session_path,
1665 session = g_hash_table_lookup(session_hash, session_path);
1669 if (g_strcmp0(owner, session->owner) != 0)
1672 connman_session_destroy(session);
1677 int connman_session_connect(struct connman_service *service)
1679 DBG("service %p name %s", service, __connman_service_get_name(service));
1681 return __connman_service_connect(service,
1682 CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1685 int connman_session_disconnect(struct connman_service *service)
1687 DBG("service %p", service);
1689 return __connman_service_disconnect(service);
1692 static enum connman_session_state service_to_session_state(
1693 enum connman_service_state state)
1696 case CONNMAN_SERVICE_STATE_UNKNOWN:
1697 case CONNMAN_SERVICE_STATE_IDLE:
1698 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1699 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1700 case CONNMAN_SERVICE_STATE_DISCONNECT:
1701 case CONNMAN_SERVICE_STATE_FAILURE:
1703 case CONNMAN_SERVICE_STATE_READY:
1704 return CONNMAN_SESSION_STATE_CONNECTED;
1705 case CONNMAN_SERVICE_STATE_ONLINE:
1706 return CONNMAN_SESSION_STATE_ONLINE;
1709 return CONNMAN_SESSION_STATE_DISCONNECTED;
1712 static void update_session_state(struct connman_session *session)
1714 enum connman_service_state service_state;
1715 enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1717 if (session->service) {
1718 service_state = connman_service_get_state(session->service);
1719 state = service_to_session_state(service_state);
1720 session->info->state = state;
1722 session->info->state = state;
1724 DBG("session %p state %s", session, state2string(state));
1726 update_firewall(session);
1727 del_nat_rules(session);
1728 update_routing_table(session);
1729 add_nat_rules(session);
1731 if (policy && policy->update_session_state)
1732 policy->update_session_state(session, state);
1734 session_notify(session);
1737 static bool session_match_service(struct connman_session *session,
1738 struct connman_service *service)
1740 enum connman_service_type bearer_type;
1741 enum connman_service_type service_type;
1742 enum connman_service_type current_service_type;
1746 if (policy && policy->allowed)
1747 return policy->allowed(session, service);
1749 current_service_type = connman_service_get_type(session->service);
1751 for (list = session->info->config.allowed_bearers; list; list = list->next) {
1752 bearer_type = GPOINTER_TO_INT(list->data);
1753 service_type = connman_service_get_type(service);
1754 ifname = connman_service_get_interface(service);
1756 if (bearer_type == current_service_type)
1759 if (bearer_type == service_type &&
1760 (session->info->config.allowed_interface == NULL ||
1761 !g_strcmp0(session->info->config.allowed_interface, "*") ||
1762 !g_strcmp0(session->info->config.allowed_interface, ifname))) {
1772 static bool is_session_connected(struct connman_session *session,
1773 enum connman_service_state state)
1777 case CONNMAN_SERVICE_STATE_UNKNOWN:
1778 case CONNMAN_SERVICE_STATE_IDLE:
1779 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1780 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1781 case CONNMAN_SERVICE_STATE_DISCONNECT:
1782 case CONNMAN_SERVICE_STATE_FAILURE:
1784 case CONNMAN_SERVICE_STATE_READY:
1785 if (session->info->config.type == CONNMAN_SESSION_TYPE_INTERNET)
1788 case CONNMAN_SERVICE_STATE_ONLINE:
1795 static void session_activate(struct connman_session *session)
1797 GHashTableIter iter;
1798 gpointer key, value;
1803 if (policy && policy->get_service_for_session) {
1804 struct connman_service *service;
1805 struct connman_service_info *info;
1806 GSList *service_list = NULL;
1807 enum connman_service_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1809 g_hash_table_iter_init(&iter, service_hash);
1811 while (g_hash_table_iter_next(&iter, &key, &value)) {
1812 struct connman_service_info *info = value;
1813 state = connman_service_get_state(info->service);
1815 if (is_session_connected(session, state))
1816 service_list = g_slist_prepend(service_list,
1820 service_list = g_slist_reverse(service_list);
1821 service = policy->get_service_for_session(session, service_list);
1824 info = g_hash_table_lookup(service_hash, service);
1825 DBG("session %p add service %p", session, info->service);
1827 info->sessions = g_slist_prepend(info->sessions,
1829 session->service = info->service;
1830 update_session_state(session);
1833 g_slist_free(service_list);
1837 g_hash_table_iter_init(&iter, service_hash);
1838 while (g_hash_table_iter_next(&iter, &key, &value)) {
1839 struct connman_service_info *info = value;
1840 enum connman_service_state state;
1842 state = connman_service_get_state(info->service);
1844 if (is_session_connected(session, state) &&
1845 session_match_service(session, info->service)) {
1846 DBG("session %p add service %p", session, info->service);
1848 info->sessions = g_slist_prepend(info->sessions,
1850 session->service = info->service;
1851 update_session_state(session);
1857 session_notify(session);
1860 static void session_deactivate(struct connman_session *session)
1862 struct connman_service_info *info;
1867 if (!session->service)
1870 info = g_hash_table_lookup(service_hash, session->service);
1874 info->sessions = g_slist_remove(info->sessions, session);
1875 session->service = NULL;
1877 session->info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1880 static void handle_service_state_online(struct connman_service *service,
1881 enum connman_service_state state,
1882 struct connman_service_info *info)
1884 GHashTableIter iter;
1885 gpointer key, value;
1887 g_hash_table_iter_init(&iter, session_hash);
1888 while (g_hash_table_iter_next(&iter, &key, &value)) {
1889 struct connman_session *session = value;
1892 connected = is_session_connected(session, state);
1894 if (session->service == service) {
1896 DBG("session %p remove service %p", session, service);
1897 info->sessions = g_slist_remove(info->sessions,
1899 session->service = NULL;
1900 update_session_state(session);
1902 } else if (connected && session_match_service(session, service)) {
1903 DBG("session %p add service %p", session, service);
1905 info->sessions = g_slist_prepend(info->sessions,
1907 session->service = service;
1908 update_session_state(session);
1913 static void handle_service_state_offline(struct connman_service *service,
1914 struct connman_service_info *info)
1918 for (list = info->sessions; list; list = list->next) {
1919 struct connman_session *session = list->data;
1921 if (session->service != service) {
1922 connman_warn("session %p should have session %p assigned",
1927 DBG("session %p remove service %p", session, service);
1929 session->service = NULL;
1930 update_session_state(session);
1931 session_activate(session);
1935 static void service_state_changed(struct connman_service *service,
1936 enum connman_service_state state)
1938 struct connman_service_info *info;
1940 DBG("service %p state %d", service, state);
1942 info = g_hash_table_lookup(service_hash, service);
1945 case CONNMAN_SERVICE_STATE_UNKNOWN:
1946 case CONNMAN_SERVICE_STATE_IDLE:
1947 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1948 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1949 case CONNMAN_SERVICE_STATE_FAILURE:
1950 case CONNMAN_SERVICE_STATE_DISCONNECT:
1954 handle_service_state_offline(service, info);
1956 g_hash_table_remove(service_hash, service);
1959 case CONNMAN_SERVICE_STATE_READY:
1960 case CONNMAN_SERVICE_STATE_ONLINE:
1962 info = g_new0(struct connman_service_info, 1);
1963 g_hash_table_replace(service_hash, service, info);
1966 info->service = service;
1967 handle_service_state_online(service, state, info);
1971 static void ipconfig_changed(struct connman_service *service,
1972 struct connman_ipconfig *ipconfig)
1974 GHashTableIter iter;
1975 gpointer key, value;
1976 struct connman_session *session;
1977 struct session_info *info;
1978 enum connman_ipconfig_type type;
1980 DBG("service %p ipconfig %p", service, ipconfig);
1982 type = __connman_ipconfig_get_config_type(ipconfig);
1984 g_hash_table_iter_init(&iter, session_hash);
1986 while (g_hash_table_iter_next(&iter, &key, &value)) {
1988 info = session->info;
1990 if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
1993 if (session->service && session->service == service) {
1994 update_session_state(session);
1996 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1997 ipconfig_ipv4_changed(session);
1998 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1999 ipconfig_ipv6_changed(session);
2004 static const struct connman_notifier session_notifier = {
2006 .service_state_changed = service_state_changed,
2007 .ipconfig_changed = ipconfig_changed,
2010 int __connman_session_init(void)
2016 connection = connman_dbus_get_connection();
2020 err = connman_notifier_register(&session_notifier);
2022 dbus_connection_unref(connection);
2026 session_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2027 NULL, cleanup_session);
2029 service_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2030 NULL, cleanup_service);
2034 void __connman_session_cleanup(void)
2041 connman_notifier_unregister(&session_notifier);
2043 g_hash_table_foreach(session_hash, release_session, NULL);
2044 g_hash_table_destroy(session_hash);
2045 session_hash = NULL;
2046 g_hash_table_destroy(service_hash);
2047 service_hash = NULL;
2049 dbus_connection_unref(connection);