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:
198 #if defined TIZEN_EXT_WIFI_MESH
199 case CONNMAN_SERVICE_TYPE_MESH:
207 static struct fw_snat *fw_snat_lookup(int index, const char *addr)
209 struct fw_snat *fw_snat;
212 for (list = fw_snat_list; list; list = list->next) {
213 fw_snat = list->data;
215 if (fw_snat->index == index) {
216 if (g_strcmp0(addr, fw_snat->addr) != 0)
224 static int fw_snat_create(struct connman_session *session,
225 int index, const char *ifname, const char *addr)
227 struct fw_snat *fw_snat;
230 fw_snat = g_new0(struct fw_snat, 1);
232 fw_snat->fw = __connman_firewall_create();
233 fw_snat->index = index;
234 fw_snat->addr = g_strdup(addr);
236 fw_snat->id = __connman_firewall_enable_snat(fw_snat->fw,
237 index, ifname, addr);
238 if (fw_snat->id < 0) {
243 fw_snat_list = g_slist_prepend(fw_snat_list, fw_snat);
244 fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
248 __connman_firewall_destroy(fw_snat->fw);
249 g_free(fw_snat->addr);
254 static void fw_snat_ref(struct connman_session *session,
255 struct fw_snat *fw_snat)
257 if (g_slist_find(fw_snat->sessions, session))
259 fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
262 static void fw_snat_unref(struct connman_session *session,
263 struct fw_snat *fw_snat)
265 fw_snat->sessions = g_slist_remove(fw_snat->sessions, session);
266 if (fw_snat->sessions)
269 fw_snat_list = g_slist_remove(fw_snat_list, fw_snat);
271 __connman_firewall_disable_snat(fw_snat->fw);
272 __connman_firewall_destroy(fw_snat->fw);
276 static int init_firewall_session(struct connman_session *session)
278 struct firewall_context *fw;
280 struct connman_ipconfig *ipconfig = NULL;
281 const char *addr = NULL;
283 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
284 !session->info->config.source_ip_rule)
289 if (session->info->config.source_ip_rule) {
290 ipconfig = __connman_service_get_ip4config(session->service);
291 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN && !ipconfig)
295 fw = __connman_firewall_create();
299 if (session->info->config.source_ip_rule && ipconfig) {
300 addr = __connman_ipconfig_get_local(ipconfig);
303 err =__connman_firewall_enable_marking(fw,
304 session->policy_config->id_type,
305 session->policy_config->id,
306 addr, session->mark);
308 __connman_firewall_destroy(fw);
311 session->id_type = session->policy_config->id_type;
317 static void cleanup_firewall_session(struct connman_session *session)
322 __connman_firewall_disable_marking(session->fw);
323 __connman_firewall_disable_snat(session->fw);
324 __connman_firewall_destroy(session->fw);
329 static int init_routing_table(struct connman_session *session)
333 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
334 !session->info->config.source_ip_rule)
337 if (!session->service)
342 err = __connman_inet_add_fwmark_rule(session->mark,
343 AF_INET, session->mark);
347 err = __connman_inet_add_fwmark_rule(session->mark,
348 AF_INET6, session->mark);
350 __connman_inet_del_fwmark_rule(session->mark,
351 AF_INET, session->mark);
352 session->policy_routing = true;
357 static void del_default_route(struct connman_session *session)
359 if (!session->gateway)
362 DBG("index %d routing table %d default gateway %s/%u",
363 session->index, session->mark, session->gateway, session->prefixlen);
365 __connman_inet_del_subnet_from_table(session->mark,
366 session->index, session->gateway, session->prefixlen);
368 __connman_inet_del_default_from_table(session->mark,
369 session->index, session->gateway);
370 g_free(session->gateway);
371 session->gateway = NULL;
372 session->prefixlen = 0;
376 static void add_default_route(struct connman_session *session)
378 struct connman_ipconfig *ipconfig;
380 struct in_addr addr = { INADDR_ANY };
382 if (!session->service)
385 ipconfig = __connman_service_get_ip4config(session->service);
386 session->index = __connman_ipconfig_get_index(ipconfig);
387 session->gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig));
389 if (!session->gateway)
390 session->gateway = g_strdup(inet_ntoa(addr));
392 session->prefixlen = __connman_ipconfig_get_prefixlen(ipconfig);
394 DBG("index %d routing table %d default gateway %s/%u",
395 session->index, session->mark, session->gateway, session->prefixlen);
397 err = __connman_inet_add_default_to_table(session->mark,
398 session->index, session->gateway);
400 DBG("session %p %s", session, strerror(-err));
402 err = __connman_inet_add_subnet_to_table(session->mark,
403 session->index, session->gateway, session->prefixlen);
405 DBG("session add subnet route %p %s", session, strerror(-err));
408 static void del_nat_rules(struct connman_session *session)
410 struct fw_snat *fw_snat;
412 if (!session->snat_enabled)
415 session->snat_enabled = false;
416 fw_snat = fw_snat_lookup(session->index, session->addr);
421 fw_snat_unref(session, fw_snat);
424 static void add_nat_rules(struct connman_session *session)
426 struct connman_ipconfig *ipconfig;
427 struct fw_snat *fw_snat;
432 if (!session->service)
435 ipconfig = __connman_service_get_ip4config(session->service);
436 index = __connman_ipconfig_get_index(ipconfig);
437 ifname = connman_inet_ifname(index);
438 addr = __connman_ipconfig_get_local(ipconfig);
443 g_free(session->addr);
444 session->addr = g_strdup(addr);
446 session->snat_enabled = true;
447 fw_snat = fw_snat_lookup(index, session->addr);
449 fw_snat_ref(session, fw_snat);
453 err = fw_snat_create(session, index, ifname, addr);
455 DBG("failed to add SNAT rule");
456 session->snat_enabled = false;
462 uint32_t connman_session_firewall_get_fwmark(struct connman_session *session)
464 return session->mark;
467 static void cleanup_routing_table(struct connman_session *session)
471 if (session->policy_routing) {
472 __connman_inet_del_fwmark_rule(session->mark,
473 AF_INET6, session->mark);
475 __connman_inet_del_fwmark_rule(session->mark,
476 AF_INET, session->mark);
477 session->policy_routing = false;
480 del_default_route(session);
483 static void update_firewall(struct connman_session *session)
485 cleanup_firewall_session(session);
486 init_firewall_session(session);
489 static void update_routing_table(struct connman_session *session)
491 cleanup_routing_table(session);
492 init_routing_table(session);
493 add_default_route(session);
496 static void cleanup_nat_rules(struct connman_session *session)
498 del_nat_rules(session);
501 static void destroy_policy_config(struct connman_session *session)
504 g_free(session->policy_config);
508 policy->destroy(session);
511 static void free_session(struct connman_session *session)
516 if (session->notify_watch > 0)
517 g_dbus_remove_watch(connection, session->notify_watch);
519 g_dbus_unregister_interface(connection, session->session_path,
520 CONNMAN_SESSION_INTERFACE);
522 destroy_policy_config(session);
523 g_slist_free(session->info->config.allowed_bearers);
524 g_free(session->info->config.allowed_interface);
525 g_free(session->owner);
526 g_free(session->session_path);
527 g_free(session->notify_path);
528 g_free(session->info);
529 g_free(session->info_last);
530 g_free(session->gateway);
531 g_free(session->addr);
536 static void set_active_session(struct connman_session *session, bool enable)
539 if (policy && policy->session_changed)
540 policy->session_changed(session, enable,
541 session->info->config.allowed_bearers);
543 __connman_service_set_active_session(enable,
544 session->info->config.allowed_bearers);
547 static void cleanup_session(gpointer user_data)
549 struct connman_session *session = user_data;
551 DBG("remove %s", session->session_path);
553 cleanup_nat_rules(session);
554 cleanup_routing_table(session);
555 cleanup_firewall_session(session);
558 set_active_session(session, false);
560 session_deactivate(session);
561 update_session_state(session);
563 g_slist_free(session->user_allowed_bearers);
564 g_free(session->user_allowed_interface);
566 free_session(session);
569 struct creation_data {
570 DBusMessage *pending;
571 struct connman_session *session;
574 enum connman_session_type type;
575 GSList *allowed_bearers;
576 char *allowed_interface;
578 char *context_identifier;
581 static void cleanup_creation_data(struct creation_data *creation_data)
586 if (creation_data->pending)
587 dbus_message_unref(creation_data->pending);
588 if (creation_data->context_identifier)
589 g_free(creation_data->context_identifier);
591 g_slist_free(creation_data->allowed_bearers);
592 g_free(creation_data->allowed_interface);
593 g_free(creation_data);
596 static int create_policy_config(struct connman_session *session,
597 connman_session_config_func_t cb,
598 struct creation_data *creation_data)
600 struct connman_session_config *config;
603 config = connman_session_create_default_config();
605 free_session(session);
606 cleanup_creation_data(creation_data);
610 return cb(session, config, creation_data, 0);
613 return policy->create(session, cb, creation_data);
616 int connman_session_policy_register(struct connman_session_policy *plugin)
621 if (!plugin->create || !plugin->destroy)
624 DBG("name %s", plugin->name);
631 void connman_session_policy_unregister(struct connman_session_policy *plugin)
633 if (plugin != policy)
636 DBG("name %s", policy->name);
641 static int default_bearers[] = {
642 CONNMAN_SERVICE_TYPE_ETHERNET,
643 CONNMAN_SERVICE_TYPE_WIFI,
644 CONNMAN_SERVICE_TYPE_BLUETOOTH,
645 CONNMAN_SERVICE_TYPE_CELLULAR,
646 CONNMAN_SERVICE_TYPE_GADGET,
649 static void add_default_bearer_types(GSList **list)
653 for (i = 0; i < G_N_ELEMENTS(default_bearers); i++)
654 *list = g_slist_append(*list,
655 GINT_TO_POINTER(default_bearers[i]));
658 void connman_session_set_default_config(struct connman_session_config *config)
660 config->id_type = CONNMAN_SESSION_ID_TYPE_UNKNOWN;
664 config->priority = FALSE;
665 config->roaming_policy = CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
666 config->type = CONNMAN_SESSION_TYPE_ANY;
667 config->ecall = FALSE;
669 g_slist_free(config->allowed_bearers);
670 config->allowed_bearers = NULL;
671 add_default_bearer_types(&config->allowed_bearers);
674 struct connman_session_config *connman_session_create_default_config(void)
676 struct connman_session_config *config;
678 config = g_new0(struct connman_session_config, 1);
679 connman_session_set_default_config(config);
684 static enum connman_session_type apply_policy_on_type(
685 enum connman_session_type policy,
686 enum connman_session_type type)
688 if (type == CONNMAN_SESSION_TYPE_UNKNOWN)
689 return CONNMAN_SESSION_TYPE_UNKNOWN;
691 if (policy == CONNMAN_SESSION_TYPE_ANY)
694 if (policy == CONNMAN_SESSION_TYPE_LOCAL)
695 return CONNMAN_SESSION_TYPE_LOCAL;
697 return CONNMAN_SESSION_TYPE_INTERNET;
700 int connman_session_parse_bearers(const char *token, GSList **list)
702 enum connman_service_type bearer;
705 if (g_strcmp0(token, "") == 0)
708 if (g_strcmp0(token, "*") == 0) {
709 add_default_bearer_types(list);
713 err = bearer2service(token, &bearer);
717 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
722 static int parse_bearers(DBusMessageIter *iter, GSList **list)
724 DBusMessageIter array;
727 dbus_message_iter_recurse(iter, &array);
731 while ((type = dbus_message_iter_get_arg_type(&array)) !=
733 char *bearer_name = NULL;
735 if (type != DBUS_TYPE_STRING) {
741 dbus_message_iter_get_basic(&array, &bearer_name);
743 err = connman_session_parse_bearers(bearer_name, list);
750 dbus_message_iter_next(&array);
756 static void filter_bearer(GSList *bearers,
757 enum connman_service_type policy,
760 enum connman_service_type bearer;
766 for (it = bearers; it; it = it->next) {
767 bearer = GPOINTER_TO_INT(it->data);
769 if (policy != bearer)
772 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
777 static void apply_policy_on_bearers(GSList *policy_bearers, GSList *bearers,
780 enum connman_service_type policy_bearer;
785 for (it = policy_bearers; it; it = it->next) {
786 policy_bearer = GPOINTER_TO_INT(it->data);
788 filter_bearer(bearers, policy_bearer, list);
792 static char * apply_policy_on_interface(const char *policy_interface,
793 const char *user_interface)
795 if (policy_interface)
796 return g_strdup(policy_interface);
797 else if (user_interface)
798 return g_strdup(user_interface);
803 const char *connman_session_get_owner(struct connman_session *session)
805 return session->owner;
808 static void append_allowed_bearers(DBusMessageIter *iter, void *user_data)
810 struct session_info *info = user_data;
813 for (list = info->config.allowed_bearers;
814 list; list = list->next) {
815 enum connman_service_type bearer = GPOINTER_TO_INT(list->data);
816 const char *name = __connman_service_type2string(bearer);
821 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
826 static void append_ipconfig_ipv4(DBusMessageIter *iter, void *user_data)
828 struct connman_service *service = user_data;
829 struct connman_ipconfig *ipconfig_ipv4;
834 if (!__connman_service_is_connected_state(service,
835 CONNMAN_IPCONFIG_TYPE_IPV4))
838 ipconfig_ipv4 = __connman_service_get_ip4config(service);
842 __connman_ipconfig_append_ipv4(ipconfig_ipv4, iter);
845 static void append_ipconfig_ipv6(DBusMessageIter *iter, void *user_data)
847 struct connman_service *service = user_data;
848 struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
853 if (!__connman_service_is_connected_state(service,
854 CONNMAN_IPCONFIG_TYPE_IPV6))
857 ipconfig_ipv4 = __connman_service_get_ip4config(service);
858 ipconfig_ipv6 = __connman_service_get_ip6config(service);
862 __connman_ipconfig_append_ipv6(ipconfig_ipv6, iter, ipconfig_ipv4);
865 static void append_notify(DBusMessageIter *dict,
866 struct connman_session *session)
868 struct session_info *info = session->info;
869 struct session_info *info_last = session->info_last;
870 struct connman_service *service;
871 enum connman_service_type type;
872 const char *name, *bearer;
876 if (session->append_all || info->state != info_last->state) {
877 const char *state = state2string(info->state);
879 connman_dbus_dict_append_basic(dict, "State",
882 info_last->state = info->state;
885 if (session->append_all || session->service != session->service_last) {
886 if (session->service) {
887 service = session->service;
888 name = __connman_service_get_name(service);
889 idx = __connman_service_get_index(service);
891 ifname = connman_inet_ifname(idx);
893 ifname = g_strdup("");
895 type = connman_service_get_type(service);
896 bearer = service2bearer(type);
900 ifname = g_strdup("");
904 connman_dbus_dict_append_basic(dict, "Name",
908 connman_dbus_dict_append_dict(dict, "IPv4",
909 append_ipconfig_ipv4,
912 connman_dbus_dict_append_dict(dict, "IPv6",
913 append_ipconfig_ipv6,
916 connman_dbus_dict_append_basic(dict, "Interface",
920 connman_dbus_dict_append_basic(dict, "Bearer",
926 session->service_last = session->service;
929 if (session->append_all ||
930 info->config.type != info_last->config.type) {
931 const char *type = type2string(info->config.type);
933 connman_dbus_dict_append_basic(dict, "ConnectionType",
936 info_last->config.type = info->config.type;
939 if (session->append_all ||
940 info->config.allowed_bearers != info_last->config.allowed_bearers) {
941 connman_dbus_dict_append_array(dict, "AllowedBearers",
943 append_allowed_bearers,
945 info_last->config.allowed_bearers = info->config.allowed_bearers;
948 if (session->append_all ||
949 info->config.allowed_interface != info_last->config.allowed_interface) {
950 char *ifname = info->config.allowed_interface;
953 connman_dbus_dict_append_basic(dict, "AllowedInterface",
956 info_last->config.allowed_interface = info->config.allowed_interface;
959 if (session->append_all ||
960 info->config.context_identifier != info_last->config.context_identifier) {
961 char *ifname = info->config.context_identifier;
964 connman_dbus_dict_append_basic(dict, "ContextIdentifier",
967 info_last->config.context_identifier = info->config.context_identifier;
970 if (session->append_all ||
971 info->config.source_ip_rule != info_last->config.source_ip_rule) {
972 dbus_bool_t source_ip_rule = FALSE;
973 if (info->config.source_ip_rule)
974 source_ip_rule = TRUE;
975 connman_dbus_dict_append_basic(dict, "SourceIPRule",
978 info_last->config.source_ip_rule = info->config.source_ip_rule;
981 session->append_all = false;
984 static bool compute_notifiable_changes(struct connman_session *session)
986 struct session_info *info_last = session->info_last;
987 struct session_info *info = session->info;
989 if (session->append_all)
992 if (info->state != info_last->state)
995 if (session->service != session->service_last &&
996 info->state >= CONNMAN_SESSION_STATE_CONNECTED)
999 if (info->config.allowed_bearers != info_last->config.allowed_bearers ||
1000 info->config.type != info_last->config.type ||
1001 info->config.allowed_interface != info_last->config.allowed_interface ||
1002 info->config.source_ip_rule != info_last->config.source_ip_rule)
1008 static gboolean session_notify(gpointer user_data)
1010 struct connman_session *session = user_data;
1012 DBusMessageIter array, dict;
1014 if (!compute_notifiable_changes(session))
1017 DBG("session %p owner %s notify_path %s", session,
1018 session->owner, session->notify_path);
1020 msg = dbus_message_new_method_call(session->owner, session->notify_path,
1021 CONNMAN_NOTIFICATION_INTERFACE,
1026 dbus_message_iter_init_append(msg, &array);
1027 connman_dbus_dict_open(&array, &dict);
1029 append_notify(&dict, session);
1031 connman_dbus_dict_close(&array, &dict);
1033 g_dbus_send_message(connection, msg);
1038 static void ipconfig_ipv4_changed(struct connman_session *session)
1040 connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1041 "IPv4", append_ipconfig_ipv4,
1045 static void ipconfig_ipv6_changed(struct connman_session *session)
1047 connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1048 "IPv6", append_ipconfig_ipv6,
1052 int connman_session_config_update(struct connman_session *session)
1054 struct session_info *info = session->info;
1055 GSList *allowed_bearers;
1056 char *allowed_interface;
1059 DBG("session %p", session);
1062 * We update all configuration even though only one entry
1063 * might have changed. We can still optimize this later.
1066 if (session->id_type != session->policy_config->id_type) {
1067 cleanup_firewall_session(session);
1068 err = init_firewall_session(session);
1070 connman_session_destroy(session);
1074 session->id_type = session->policy_config->id_type;
1077 apply_policy_on_bearers(
1078 session->policy_config->allowed_bearers,
1079 session->user_allowed_bearers,
1082 allowed_interface = apply_policy_on_interface(
1083 session->policy_config->allowed_interface,
1084 session->user_allowed_interface);
1086 if (session->active)
1087 set_active_session(session, false);
1089 session->active = false;
1090 session_deactivate(session);
1092 g_slist_free(info->config.allowed_bearers);
1093 info->config.allowed_bearers = allowed_bearers;
1095 g_free(info->config.allowed_interface);
1096 info->config.allowed_interface = allowed_interface;
1098 session_activate(session);
1100 info->config.type = apply_policy_on_type(
1101 session->policy_config->type,
1104 info->config.roaming_policy = session->policy_config->roaming_policy;
1106 info->config.ecall = session->policy_config->ecall;
1107 if (info->config.ecall)
1108 ecall_session = session;
1110 info->config.priority = session->policy_config->priority;
1112 session_notify(session);
1117 static DBusMessage *connect_session(DBusConnection *conn,
1118 DBusMessage *msg, void *user_data)
1120 struct connman_session *session = user_data;
1122 DBG("session %p", session);
1124 if (ecall_session) {
1125 if (ecall_session->ecall && ecall_session != session)
1126 return __connman_error_failed(msg, EBUSY);
1128 session->ecall = true;
1131 if (!session->active) {
1132 session->active = true;
1133 set_active_session(session, true);
1136 session_activate(session);
1138 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1140 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1143 static DBusMessage *disconnect_session(DBusConnection *conn,
1144 DBusMessage *msg, void *user_data)
1146 struct connman_session *session = user_data;
1148 DBG("session %p", session);
1150 if (ecall_session) {
1151 if (ecall_session->ecall && ecall_session != session)
1152 return __connman_error_failed(msg, EBUSY);
1154 session->ecall = false;
1157 if (session->active) {
1158 session->active = false;
1159 set_active_session(session, false);
1162 session_deactivate(session);
1163 update_session_state(session);
1165 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1168 static DBusMessage *change_session(DBusConnection *conn,
1169 DBusMessage *msg, void *user_data)
1171 struct connman_session *session = user_data;
1172 struct session_info *info = session->info;
1173 DBusMessageIter iter, value;
1176 GSList *allowed_bearers;
1179 DBG("session %p", session);
1180 if (!dbus_message_iter_init(msg, &iter))
1181 return __connman_error_invalid_arguments(msg);
1183 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1184 return __connman_error_invalid_arguments(msg);
1186 dbus_message_iter_get_basic(&iter, &name);
1187 dbus_message_iter_next(&iter);
1189 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1190 return __connman_error_invalid_arguments(msg);
1192 dbus_message_iter_recurse(&iter, &value);
1194 switch (dbus_message_iter_get_arg_type(&value)) {
1195 case DBUS_TYPE_ARRAY:
1196 if (g_str_equal(name, "AllowedBearers")) {
1197 err = parse_bearers(&value, &allowed_bearers);
1199 return __connman_error_failed(msg, -err);
1201 if (session->active)
1202 set_active_session(session, false);
1204 session->active = false;
1205 session_deactivate(session);
1206 update_session_state(session);
1208 g_slist_free(info->config.allowed_bearers);
1209 session->user_allowed_bearers = allowed_bearers;
1211 apply_policy_on_bearers(
1212 session->policy_config->allowed_bearers,
1213 session->user_allowed_bearers,
1214 &info->config.allowed_bearers);
1216 session_activate(session);
1221 case DBUS_TYPE_STRING:
1222 if (g_str_equal(name, "ConnectionType")) {
1223 dbus_message_iter_get_basic(&value, &val);
1224 info->config.type = apply_policy_on_type(
1225 session->policy_config->type,
1226 connman_session_parse_connection_type(val));
1227 } else if (g_str_equal(name, "AllowedInterface")) {
1228 dbus_message_iter_get_basic(&value, &val);
1229 if (session->active)
1230 set_active_session(session, false);
1232 session->active = false;
1233 session_deactivate(session);
1234 update_session_state(session);
1236 g_free(session->user_allowed_interface);
1237 /* empty string means allow any interface */
1238 if (!g_strcmp0(val, ""))
1239 session->user_allowed_interface = NULL;
1241 session->user_allowed_interface = g_strdup(val);
1243 info->config.allowed_interface = apply_policy_on_interface(
1244 session->policy_config->allowed_interface,
1245 session->user_allowed_interface);
1247 session_activate(session);
1252 case DBUS_TYPE_BOOLEAN:
1253 if (g_str_equal(name, "SourceIPRule")) {
1254 dbus_bool_t source_ip_rule;
1255 dbus_message_iter_get_basic(&value, &source_ip_rule);
1257 info->config.source_ip_rule = source_ip_rule;
1258 update_session_state(session);
1267 session_notify(session);
1269 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1272 return __connman_error_invalid_arguments(msg);
1275 static void release_session(gpointer key, gpointer value, gpointer user_data)
1277 struct connman_session *session = value;
1278 DBusMessage *message;
1280 DBG("owner %s path %s", session->owner, session->notify_path);
1282 if (session->notify_watch > 0)
1283 g_dbus_remove_watch(connection, session->notify_watch);
1285 g_dbus_unregister_interface(connection, session->session_path,
1286 CONNMAN_SESSION_INTERFACE);
1288 message = dbus_message_new_method_call(session->owner,
1289 session->notify_path,
1290 CONNMAN_NOTIFICATION_INTERFACE,
1295 dbus_message_set_no_reply(message, TRUE);
1297 g_dbus_send_message(connection, message);
1300 static int session_disconnect(struct connman_session *session)
1302 DBG("session %p, %s", session, session->owner);
1304 if (session->notify_watch > 0)
1305 g_dbus_remove_watch(connection, session->notify_watch);
1307 g_dbus_unregister_interface(connection, session->session_path,
1308 CONNMAN_SESSION_INTERFACE);
1310 g_hash_table_remove(session_hash, session->session_path);
1315 static void owner_disconnect(DBusConnection *conn, void *user_data)
1317 struct connman_session *session = user_data;
1319 DBG("session %p, %s died", session, session->owner);
1321 session_disconnect(session);
1324 static DBusMessage *destroy_session(DBusConnection *conn,
1325 DBusMessage *msg, void *user_data)
1327 struct connman_session *session = user_data;
1329 DBG("session %p", session);
1331 if (ecall_session && ecall_session != session)
1332 return __connman_error_failed(msg, EBUSY);
1334 session_disconnect(session);
1336 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1339 static const GDBusMethodTable session_methods[] = {
1340 { GDBUS_METHOD("Destroy", NULL, NULL, destroy_session) },
1341 { GDBUS_METHOD("Connect", NULL, NULL, connect_session) },
1342 { GDBUS_METHOD("Disconnect", NULL, NULL,
1343 disconnect_session ) },
1344 { GDBUS_METHOD("Change",
1345 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1346 NULL, change_session) },
1350 static int session_policy_config_cb(struct connman_session *session,
1351 struct connman_session_config *config,
1352 void *user_data, int err)
1354 struct creation_data *creation_data = user_data;
1355 struct session_info *info, *info_last;
1358 DBG("session %p config %p", session, config);
1363 session->policy_config = config;
1364 session->info->config.source_ip_rule = creation_data->source_ip_rule;
1366 session->mark = session_mark++;
1367 session->index = -1;
1369 err = init_firewall_session(session);
1373 err = init_routing_table(session);
1377 info = session->info;
1378 info_last = session->info_last;
1380 if (session->policy_config->ecall)
1381 ecall_session = session;
1383 info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1384 info->config.type = apply_policy_on_type(
1385 session->policy_config->type,
1386 creation_data->type);
1387 info->config.priority = session->policy_config->priority;
1388 info->config.roaming_policy = session->policy_config->roaming_policy;
1390 session->user_allowed_bearers = creation_data->allowed_bearers;
1391 creation_data->allowed_bearers = NULL;
1393 session->user_allowed_interface = creation_data->allowed_interface;
1394 creation_data->allowed_interface = NULL;
1396 apply_policy_on_bearers(
1397 session->policy_config->allowed_bearers,
1398 session->user_allowed_bearers,
1399 &info->config.allowed_bearers);
1401 info->config.allowed_interface = apply_policy_on_interface(
1402 session->policy_config->allowed_interface,
1403 session->user_allowed_interface);
1405 g_hash_table_replace(session_hash, session->session_path, session);
1407 DBG("add %s", session->session_path);
1409 if (!g_dbus_register_interface(connection, session->session_path,
1410 CONNMAN_SESSION_INTERFACE,
1411 session_methods, NULL, NULL,
1413 connman_error("Failed to register %s", session->session_path);
1414 g_hash_table_remove(session_hash, session->session_path);
1419 reply = g_dbus_create_reply(creation_data->pending,
1420 DBUS_TYPE_OBJECT_PATH, &session->session_path,
1422 g_dbus_send_message(connection, reply);
1423 creation_data->pending = NULL;
1425 info_last->state = info->state;
1426 info_last->config.priority = info->config.priority;
1427 info_last->config.roaming_policy = info->config.roaming_policy;
1428 info_last->config.allowed_bearers = info->config.allowed_bearers;
1429 info_last->config.allowed_interface = info->config.allowed_interface;
1430 info_last->config.source_ip_rule = info->config.source_ip_rule;
1432 session->append_all = true;
1434 cleanup_creation_data(creation_data);
1436 session_activate(session);
1441 cleanup_session(session);
1444 reply = __connman_error_failed(creation_data->pending, -err);
1445 g_dbus_send_message(connection, reply);
1446 creation_data->pending = NULL;
1448 cleanup_creation_data(creation_data);
1453 int __connman_session_create(DBusMessage *msg)
1455 const char *owner, *notify_path;
1456 char *session_path = NULL;
1457 DBusMessageIter iter, array;
1458 struct connman_session *session = NULL;
1459 struct creation_data *creation_data = NULL;
1460 bool user_allowed_bearers = false;
1461 bool user_connection_type = false;
1465 owner = dbus_message_get_sender(msg);
1467 DBG("owner %s", owner);
1469 if (ecall_session && ecall_session->ecall) {
1471 * If there is an emergency call already going on,
1472 * ignore session creation attempt
1478 creation_data = g_try_new0(struct creation_data, 1);
1479 if (!creation_data) {
1484 creation_data->pending = dbus_message_ref(msg);
1486 dbus_message_iter_init(msg, &iter);
1487 dbus_message_iter_recurse(&iter, &array);
1489 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1490 DBusMessageIter entry, value;
1491 const char *key, *val;
1493 dbus_message_iter_recurse(&array, &entry);
1494 dbus_message_iter_get_basic(&entry, &key);
1496 dbus_message_iter_next(&entry);
1497 dbus_message_iter_recurse(&entry, &value);
1499 switch (dbus_message_iter_get_arg_type(&value)) {
1500 case DBUS_TYPE_ARRAY:
1501 if (g_str_equal(key, "AllowedBearers")) {
1502 err = parse_bearers(&value,
1503 &creation_data->allowed_bearers);
1507 user_allowed_bearers = true;
1513 case DBUS_TYPE_STRING:
1514 if (g_str_equal(key, "ConnectionType")) {
1515 dbus_message_iter_get_basic(&value, &val);
1516 creation_data->type =
1517 connman_session_parse_connection_type(val);
1519 user_connection_type = true;
1520 } else if (g_str_equal(key, "ContextIdentifier")) {
1521 dbus_message_iter_get_basic(&value, &val);
1522 creation_data->context_identifier = g_strdup(val);
1523 } else if (g_str_equal(key, "AllowedInterface")) {
1524 dbus_message_iter_get_basic(&value, &val);
1525 creation_data->allowed_interface = g_strdup(val);
1531 case DBUS_TYPE_BOOLEAN:
1532 if (g_str_equal(key, "SourceIPRule")) {
1533 dbus_bool_t source_ip_rule;
1534 dbus_message_iter_get_basic(&value, &source_ip_rule);
1535 creation_data->source_ip_rule = source_ip_rule;
1546 dbus_message_iter_next(&array);
1550 * If the user hasn't provided a configuration, we set
1551 * the default configuration.
1553 * For AllowedBearers this is '*', ...
1555 if (!user_allowed_bearers) {
1556 add_default_bearer_types(&creation_data->allowed_bearers);
1557 if (!creation_data->allowed_bearers) {
1563 /* ... and for ConnectionType it is 'any'. */
1564 if (!user_connection_type)
1565 creation_data->type = CONNMAN_SESSION_TYPE_ANY;
1567 dbus_message_iter_next(&iter);
1568 dbus_message_iter_get_basic(&iter, ¬ify_path);
1575 str = g_strdup(owner);
1576 for (i = 0; str[i] != '\0'; i++)
1577 if (str[i] == ':' || str[i] == '.')
1579 session_path = g_strdup_printf("/sessions/%s%s", str, notify_path);
1582 if (!session_path) {
1587 session = g_hash_table_lookup(session_hash, session_path);
1589 g_free(session_path);
1595 session = g_try_new0(struct connman_session, 1);
1597 g_free(session_path);
1602 creation_data->session = session;
1603 session->session_path = session_path;
1605 session->info = g_try_new0(struct session_info, 1);
1606 if (!session->info) {
1611 session->info_last = g_try_new0(struct session_info, 1);
1612 if (!session->info_last) {
1617 session->owner = g_strdup(owner);
1618 session->notify_path = g_strdup(notify_path);
1619 session->notify_watch =
1620 g_dbus_add_disconnect_watch(connection, session->owner,
1621 owner_disconnect, session, NULL);
1623 err = create_policy_config(session, session_policy_config_cb,
1625 if (err < 0 && err != -EINPROGRESS)
1628 return -EINPROGRESS;
1631 connman_error("Failed to create session");
1633 free_session(session);
1635 cleanup_creation_data(creation_data);
1639 bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason)
1641 if (!policy || !policy->autoconnect)
1644 return policy->autoconnect(reason);
1647 void connman_session_destroy(struct connman_session *session)
1649 DBG("session %p", session);
1651 session_disconnect(session);
1654 int __connman_session_destroy(DBusMessage *msg)
1656 const char *owner, *session_path;
1657 struct connman_session *session;
1659 owner = dbus_message_get_sender(msg);
1661 DBG("owner %s", owner);
1663 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &session_path,
1668 session = g_hash_table_lookup(session_hash, session_path);
1672 if (g_strcmp0(owner, session->owner) != 0)
1675 connman_session_destroy(session);
1680 int connman_session_connect(struct connman_service *service)
1682 DBG("service %p name %s", service, __connman_service_get_name(service));
1684 return __connman_service_connect(service,
1685 CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1688 int connman_session_disconnect(struct connman_service *service)
1690 DBG("service %p", service);
1692 return __connman_service_disconnect(service);
1695 static enum connman_session_state service_to_session_state(
1696 enum connman_service_state state)
1699 case CONNMAN_SERVICE_STATE_UNKNOWN:
1700 case CONNMAN_SERVICE_STATE_IDLE:
1701 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1702 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1703 case CONNMAN_SERVICE_STATE_DISCONNECT:
1704 case CONNMAN_SERVICE_STATE_FAILURE:
1706 case CONNMAN_SERVICE_STATE_READY:
1707 return CONNMAN_SESSION_STATE_CONNECTED;
1708 case CONNMAN_SERVICE_STATE_ONLINE:
1709 return CONNMAN_SESSION_STATE_ONLINE;
1712 return CONNMAN_SESSION_STATE_DISCONNECTED;
1715 static void update_session_state(struct connman_session *session)
1717 enum connman_service_state service_state;
1718 enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1720 if (session->service) {
1721 service_state = connman_service_get_state(session->service);
1722 state = service_to_session_state(service_state);
1723 session->info->state = state;
1725 session->info->state = state;
1727 DBG("session %p state %s", session, state2string(state));
1729 update_firewall(session);
1730 del_nat_rules(session);
1731 update_routing_table(session);
1732 add_nat_rules(session);
1734 if (policy && policy->update_session_state)
1735 policy->update_session_state(session, state);
1737 session_notify(session);
1740 static bool session_match_service(struct connman_session *session,
1741 struct connman_service *service)
1743 enum connman_service_type bearer_type;
1744 enum connman_service_type service_type;
1745 enum connman_service_type current_service_type;
1749 if (policy && policy->allowed)
1750 return policy->allowed(session, service);
1752 current_service_type = connman_service_get_type(session->service);
1754 for (list = session->info->config.allowed_bearers; list; list = list->next) {
1755 bearer_type = GPOINTER_TO_INT(list->data);
1756 service_type = connman_service_get_type(service);
1757 ifname = connman_service_get_interface(service);
1760 #if defined TIZEN_EXT
1761 if (bearer_type == current_service_type) {
1766 if (bearer_type == current_service_type)
1770 if (bearer_type == service_type &&
1771 (session->info->config.allowed_interface == NULL ||
1772 !g_strcmp0(session->info->config.allowed_interface, "*") ||
1773 !g_strcmp0(session->info->config.allowed_interface, ifname))) {
1783 static bool is_session_connected(struct connman_session *session,
1784 enum connman_service_state state)
1788 case CONNMAN_SERVICE_STATE_UNKNOWN:
1789 case CONNMAN_SERVICE_STATE_IDLE:
1790 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1791 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1792 case CONNMAN_SERVICE_STATE_DISCONNECT:
1793 case CONNMAN_SERVICE_STATE_FAILURE:
1795 case CONNMAN_SERVICE_STATE_READY:
1796 if (session->info->config.type == CONNMAN_SESSION_TYPE_INTERNET)
1799 case CONNMAN_SERVICE_STATE_ONLINE:
1806 static void session_activate(struct connman_session *session)
1808 GHashTableIter iter;
1809 gpointer key, value;
1814 if (policy && policy->get_service_for_session) {
1815 struct connman_service *service;
1816 struct connman_service_info *info;
1817 GSList *service_list = NULL;
1818 enum connman_service_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1820 g_hash_table_iter_init(&iter, service_hash);
1822 while (g_hash_table_iter_next(&iter, &key, &value)) {
1823 struct connman_service_info *info = value;
1824 state = connman_service_get_state(info->service);
1826 if (is_session_connected(session, state))
1827 service_list = g_slist_prepend(service_list,
1831 service_list = g_slist_reverse(service_list);
1832 service = policy->get_service_for_session(session, service_list);
1835 info = g_hash_table_lookup(service_hash, service);
1836 DBG("session %p add service %p", session, info->service);
1838 info->sessions = g_slist_prepend(info->sessions,
1840 session->service = info->service;
1841 update_session_state(session);
1844 g_slist_free(service_list);
1848 g_hash_table_iter_init(&iter, service_hash);
1849 while (g_hash_table_iter_next(&iter, &key, &value)) {
1850 struct connman_service_info *info = value;
1851 enum connman_service_state state;
1853 state = connman_service_get_state(info->service);
1855 if (is_session_connected(session, state) &&
1856 session_match_service(session, info->service)) {
1857 DBG("session %p add service %p", session, info->service);
1859 info->sessions = g_slist_prepend(info->sessions,
1861 session->service = info->service;
1862 update_session_state(session);
1868 session_notify(session);
1871 static void session_deactivate(struct connman_session *session)
1873 struct connman_service_info *info;
1878 if (!session->service)
1881 info = g_hash_table_lookup(service_hash, session->service);
1885 info->sessions = g_slist_remove(info->sessions, session);
1886 session->service = NULL;
1888 session->info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1891 static void handle_service_state_online(struct connman_service *service,
1892 enum connman_service_state state,
1893 struct connman_service_info *info)
1895 GHashTableIter iter;
1896 gpointer key, value;
1898 g_hash_table_iter_init(&iter, session_hash);
1899 while (g_hash_table_iter_next(&iter, &key, &value)) {
1900 struct connman_session *session = value;
1903 connected = is_session_connected(session, state);
1905 if (session->service == service) {
1907 DBG("session %p remove service %p", session, service);
1908 info->sessions = g_slist_remove(info->sessions,
1910 session->service = NULL;
1911 update_session_state(session);
1913 } else if (connected && session_match_service(session, service)) {
1914 DBG("session %p add service %p", session, service);
1916 info->sessions = g_slist_prepend(info->sessions,
1918 session->service = service;
1919 update_session_state(session);
1924 static void handle_service_state_offline(struct connman_service *service,
1925 struct connman_service_info *info)
1929 for (list = info->sessions; list; list = list->next) {
1930 struct connman_session *session = list->data;
1932 if (session->service != service) {
1933 connman_warn("session %p should have session %p assigned",
1938 DBG("session %p remove service %p", session, service);
1940 session->service = NULL;
1941 update_session_state(session);
1942 session_activate(session);
1946 static void service_state_changed(struct connman_service *service,
1947 enum connman_service_state state)
1949 struct connman_service_info *info;
1951 DBG("service %p state %d", service, state);
1953 info = g_hash_table_lookup(service_hash, service);
1956 case CONNMAN_SERVICE_STATE_UNKNOWN:
1957 case CONNMAN_SERVICE_STATE_IDLE:
1958 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1959 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1960 case CONNMAN_SERVICE_STATE_FAILURE:
1961 case CONNMAN_SERVICE_STATE_DISCONNECT:
1965 handle_service_state_offline(service, info);
1967 g_hash_table_remove(service_hash, service);
1970 case CONNMAN_SERVICE_STATE_READY:
1971 case CONNMAN_SERVICE_STATE_ONLINE:
1973 info = g_new0(struct connman_service_info, 1);
1974 g_hash_table_replace(service_hash, service, info);
1977 info->service = service;
1978 handle_service_state_online(service, state, info);
1982 static void ipconfig_changed(struct connman_service *service,
1983 struct connman_ipconfig *ipconfig)
1985 GHashTableIter iter;
1986 gpointer key, value;
1987 struct connman_session *session;
1988 struct session_info *info;
1989 enum connman_ipconfig_type type;
1991 DBG("service %p ipconfig %p", service, ipconfig);
1993 type = __connman_ipconfig_get_config_type(ipconfig);
1995 g_hash_table_iter_init(&iter, session_hash);
1997 while (g_hash_table_iter_next(&iter, &key, &value)) {
1999 info = session->info;
2001 if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
2004 if (session->service && session->service == service) {
2005 update_session_state(session);
2007 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
2008 ipconfig_ipv4_changed(session);
2009 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
2010 ipconfig_ipv6_changed(session);
2015 static const struct connman_notifier session_notifier = {
2017 .service_state_changed = service_state_changed,
2018 .ipconfig_changed = ipconfig_changed,
2021 int __connman_session_init(void)
2027 connection = connman_dbus_get_connection();
2031 err = connman_notifier_register(&session_notifier);
2033 dbus_connection_unref(connection);
2037 session_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2038 NULL, cleanup_session);
2040 service_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
2041 NULL, cleanup_service);
2045 void __connman_session_cleanup(void)
2052 connman_notifier_unregister(&session_notifier);
2054 g_hash_table_foreach(session_hash, release_session, NULL);
2055 g_hash_table_destroy(session_hash);
2056 session_hash = NULL;
2057 g_hash_table_destroy(service_hash);
2058 service_hash = NULL;
2060 dbus_connection_unref(connection);