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
31 #include <connman/session.h>
35 static DBusConnection *connection;
36 static GHashTable *session_hash;
37 static GHashTable *service_hash;
38 static struct connman_session *ecall_session;
39 static uint32_t session_mark = 256;
42 struct connman_session_config config;
43 enum connman_session_state state;
46 struct connman_session {
54 struct session_info *info;
55 struct session_info *info_last;
56 struct connman_service *service;
57 struct connman_service *service_last;
58 struct connman_session_config *policy_config;
59 GSList *user_allowed_bearers;
60 char *user_allowed_interface;
64 enum connman_session_id_type id_type;
65 struct firewall_context *fw;
73 struct connman_service_info {
74 struct connman_service *service;
82 struct firewall_context *fw;
87 static struct connman_session_policy *policy;
88 static void session_activate(struct connman_session *session);
89 static void session_deactivate(struct connman_session *session);
90 static void update_session_state(struct connman_session *session);
92 static void cleanup_service(gpointer data)
94 struct connman_service_info *info = data;
96 g_slist_free(info->sessions);
100 static const char *state2string(enum connman_session_state state)
103 case CONNMAN_SESSION_STATE_DISCONNECTED:
104 return "disconnected";
105 case CONNMAN_SESSION_STATE_CONNECTED:
107 case CONNMAN_SESSION_STATE_ONLINE:
114 static const char *type2string(enum connman_session_type type)
117 case CONNMAN_SESSION_TYPE_UNKNOWN:
119 case CONNMAN_SESSION_TYPE_ANY:
121 case CONNMAN_SESSION_TYPE_LOCAL:
123 case CONNMAN_SESSION_TYPE_INTERNET:
130 enum connman_session_roaming_policy connman_session_parse_roaming_policy(const char *policy)
132 if (g_strcmp0(policy, "default") == 0)
133 return CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
134 else if (g_strcmp0(policy, "always") == 0)
135 return CONNMAN_SESSION_ROAMING_POLICY_ALWAYS;
136 else if (g_strcmp0(policy, "forbidden") == 0)
137 return CONNMAN_SESSION_ROAMING_POLICY_FORBIDDEN;
138 else if (g_strcmp0(policy, "national") == 0)
139 return CONNMAN_SESSION_ROAMING_POLICY_NATIONAL;
140 else if (g_strcmp0(policy, "international") == 0)
141 return CONNMAN_SESSION_ROAMING_POLICY_INTERNATIONAL;
143 return CONNMAN_SESSION_ROAMING_POLICY_UNKNOWN;
146 enum connman_session_type connman_session_parse_connection_type(const char *type)
148 if (g_strcmp0(type, "any") == 0)
149 return CONNMAN_SESSION_TYPE_ANY;
150 if (g_strcmp0(type, "local") == 0)
151 return CONNMAN_SESSION_TYPE_LOCAL;
152 else if (g_strcmp0(type, "internet") == 0)
153 return CONNMAN_SESSION_TYPE_INTERNET;
155 return CONNMAN_SESSION_TYPE_UNKNOWN;
158 static int bearer2service(const char *bearer, enum connman_service_type *type)
160 if (g_strcmp0(bearer, "ethernet") == 0)
161 *type = CONNMAN_SERVICE_TYPE_ETHERNET;
162 else if (g_strcmp0(bearer, "wifi") == 0)
163 *type = CONNMAN_SERVICE_TYPE_WIFI;
164 else if (g_strcmp0(bearer, "gadget") == 0)
165 *type = CONNMAN_SERVICE_TYPE_GADGET;
166 else if (g_strcmp0(bearer, "bluetooth") == 0)
167 *type = CONNMAN_SERVICE_TYPE_BLUETOOTH;
168 else if (g_strcmp0(bearer, "cellular") == 0)
169 *type = CONNMAN_SERVICE_TYPE_CELLULAR;
170 else if (g_strcmp0(bearer, "vpn") == 0)
171 *type = CONNMAN_SERVICE_TYPE_VPN;
178 static char *service2bearer(enum connman_service_type type)
181 case CONNMAN_SERVICE_TYPE_ETHERNET:
183 case CONNMAN_SERVICE_TYPE_GADGET:
185 case CONNMAN_SERVICE_TYPE_WIFI:
187 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
189 case CONNMAN_SERVICE_TYPE_CELLULAR:
191 case CONNMAN_SERVICE_TYPE_VPN:
193 case CONNMAN_SERVICE_TYPE_SYSTEM:
194 case CONNMAN_SERVICE_TYPE_GPS:
195 case CONNMAN_SERVICE_TYPE_P2P:
196 case CONNMAN_SERVICE_TYPE_UNKNOWN:
197 #if defined TIZEN_EXT_WIFI_MESH
198 case CONNMAN_SERVICE_TYPE_MESH:
206 static struct fw_snat *fw_snat_lookup(int index)
208 struct fw_snat *fw_snat;
211 for (list = fw_snat_list; list; list = list->next) {
212 fw_snat = list->data;
214 if (fw_snat->index == index)
220 static int fw_snat_create(struct connman_session *session,
221 int index, const char *ifname, const char *addr)
223 struct fw_snat *fw_snat;
226 fw_snat = g_new0(struct fw_snat, 1);
228 fw_snat->fw = __connman_firewall_create();
229 fw_snat->index = index;
231 fw_snat->id = __connman_firewall_enable_snat(fw_snat->fw,
232 index, ifname, addr);
233 if (fw_snat->id < 0) {
238 fw_snat_list = g_slist_prepend(fw_snat_list, fw_snat);
239 fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
243 __connman_firewall_destroy(fw_snat->fw);
248 static void fw_snat_ref(struct connman_session *session,
249 struct fw_snat *fw_snat)
251 if (g_slist_find(fw_snat->sessions, session))
253 fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
256 static void fw_snat_unref(struct connman_session *session,
257 struct fw_snat *fw_snat)
259 fw_snat->sessions = g_slist_remove(fw_snat->sessions, session);
260 if (fw_snat->sessions)
263 fw_snat_list = g_slist_remove(fw_snat_list, fw_snat);
265 __connman_firewall_disable_snat(fw_snat->fw);
266 __connman_firewall_destroy(fw_snat->fw);
270 static int init_firewall_session(struct connman_session *session)
272 struct firewall_context *fw;
274 struct connman_ipconfig *ipconfig = NULL;
275 const char *addr = NULL;
277 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
278 !session->info->config.source_ip_rule)
283 if (session->info->config.source_ip_rule) {
284 ipconfig = __connman_service_get_ip4config(session->service);
285 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN && !ipconfig)
289 fw = __connman_firewall_create();
293 if (session->info->config.source_ip_rule && ipconfig) {
294 addr = __connman_ipconfig_get_local(ipconfig);
297 err =__connman_firewall_enable_marking(fw,
298 session->policy_config->id_type,
299 session->policy_config->id,
300 addr, session->mark);
302 __connman_firewall_destroy(fw);
305 session->id_type = session->policy_config->id_type;
311 static void cleanup_firewall_session(struct connman_session *session)
316 __connman_firewall_disable_marking(session->fw);
317 __connman_firewall_disable_snat(session->fw);
318 __connman_firewall_destroy(session->fw);
323 static int init_routing_table(struct connman_session *session)
327 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
328 !session->info->config.source_ip_rule)
331 if (!session->service)
336 err = __connman_inet_add_fwmark_rule(session->mark,
337 AF_INET, session->mark);
341 err = __connman_inet_add_fwmark_rule(session->mark,
342 AF_INET6, session->mark);
344 __connman_inet_del_fwmark_rule(session->mark,
345 AF_INET, session->mark);
346 session->policy_routing = true;
351 static void del_default_route(struct connman_session *session)
353 if (!session->gateway)
356 DBG("index %d routing table %d default gateway %s",
357 session->index, session->mark, session->gateway);
359 __connman_inet_del_default_from_table(session->mark,
360 session->index, session->gateway);
361 g_free(session->gateway);
362 session->gateway = NULL;
366 static void add_default_route(struct connman_session *session)
368 struct connman_ipconfig *ipconfig;
370 struct in_addr addr = { INADDR_ANY };
372 if (!session->service)
375 ipconfig = __connman_service_get_ip4config(session->service);
376 session->index = __connman_ipconfig_get_index(ipconfig);
377 session->gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig));
379 if (!session->gateway)
380 session->gateway = g_strdup(inet_ntoa(addr));
382 DBG("index %d routing table %d default gateway %s",
383 session->index, session->mark, session->gateway);
385 err = __connman_inet_add_default_to_table(session->mark,
386 session->index, session->gateway);
388 DBG("session %p %s", session, strerror(-err));
391 static void del_nat_rules(struct connman_session *session)
393 struct fw_snat *fw_snat;
395 if (!session->snat_enabled)
398 session->snat_enabled = false;
399 fw_snat = fw_snat_lookup(session->index);
404 fw_snat_unref(session, fw_snat);
407 static void add_nat_rules(struct connman_session *session)
409 struct connman_ipconfig *ipconfig;
410 struct fw_snat *fw_snat;
415 if (!session->service)
418 ipconfig = __connman_service_get_ip4config(session->service);
419 index = __connman_ipconfig_get_index(ipconfig);
420 ifname = connman_inet_ifname(index);
421 addr = __connman_ipconfig_get_local(ipconfig);
426 session->snat_enabled = true;
427 fw_snat = fw_snat_lookup(index);
429 fw_snat_ref(session, fw_snat);
433 err = fw_snat_create(session, index, ifname, addr);
435 DBG("failed to add SNAT rule");
436 session->snat_enabled = false;
442 uint32_t connman_session_firewall_get_fwmark(struct connman_session *session)
444 return session->mark;
447 static void cleanup_routing_table(struct connman_session *session)
451 if (session->policy_routing) {
452 __connman_inet_del_fwmark_rule(session->mark,
453 AF_INET6, session->mark);
455 __connman_inet_del_fwmark_rule(session->mark,
456 AF_INET, session->mark);
457 session->policy_routing = false;
460 del_default_route(session);
463 static void update_firewall(struct connman_session *session)
465 cleanup_firewall_session(session);
466 init_firewall_session(session);
469 static void update_routing_table(struct connman_session *session)
471 cleanup_routing_table(session);
472 init_routing_table(session);
473 add_default_route(session);
476 static void cleanup_nat_rules(struct connman_session *session)
478 del_nat_rules(session);
481 static void destroy_policy_config(struct connman_session *session)
484 g_free(session->policy_config);
488 policy->destroy(session);
491 static void free_session(struct connman_session *session)
496 if (session->notify_watch > 0)
497 g_dbus_remove_watch(connection, session->notify_watch);
499 destroy_policy_config(session);
500 g_slist_free(session->info->config.allowed_bearers);
501 g_free(session->info->config.allowed_interface);
502 g_free(session->owner);
503 g_free(session->session_path);
504 g_free(session->notify_path);
505 g_free(session->info);
506 g_free(session->info_last);
507 g_free(session->gateway);
512 static void set_active_session(struct connman_session *session, bool enable)
515 if (policy && policy->session_changed)
516 policy->session_changed(session, enable,
517 session->info->config.allowed_bearers);
519 __connman_service_set_active_session(enable,
520 session->info->config.allowed_bearers);
523 static void cleanup_session(gpointer user_data)
525 struct connman_session *session = user_data;
527 DBG("remove %s", session->session_path);
529 cleanup_nat_rules(session);
530 cleanup_routing_table(session);
531 cleanup_firewall_session(session);
534 set_active_session(session, false);
536 session_deactivate(session);
537 update_session_state(session);
539 g_slist_free(session->user_allowed_bearers);
540 g_free(session->user_allowed_interface);
542 free_session(session);
545 struct creation_data {
546 DBusMessage *pending;
547 struct connman_session *session;
550 enum connman_session_type type;
551 GSList *allowed_bearers;
552 char *allowed_interface;
556 static void cleanup_creation_data(struct creation_data *creation_data)
561 if (creation_data->pending)
562 dbus_message_unref(creation_data->pending);
564 g_slist_free(creation_data->allowed_bearers);
565 g_free(creation_data->allowed_interface);
566 g_free(creation_data);
569 static int create_policy_config(struct connman_session *session,
570 connman_session_config_func_t cb,
571 struct creation_data *creation_data)
573 struct connman_session_config *config;
576 config = connman_session_create_default_config();
578 free_session(session);
579 cleanup_creation_data(creation_data);
583 return cb(session, config, creation_data, 0);
586 return policy->create(session, cb, creation_data);
589 int connman_session_policy_register(struct connman_session_policy *plugin)
594 if (!plugin->create || !plugin->destroy)
597 DBG("name %s", plugin->name);
604 void connman_session_policy_unregister(struct connman_session_policy *plugin)
606 if (plugin != policy)
609 DBG("name %s", policy->name);
614 static int default_bearers[] = {
615 CONNMAN_SERVICE_TYPE_ETHERNET,
616 CONNMAN_SERVICE_TYPE_WIFI,
617 CONNMAN_SERVICE_TYPE_BLUETOOTH,
618 CONNMAN_SERVICE_TYPE_CELLULAR,
619 CONNMAN_SERVICE_TYPE_GADGET,
622 static void add_default_bearer_types(GSList **list)
626 for (i = 0; i < G_N_ELEMENTS(default_bearers); i++)
627 *list = g_slist_append(*list,
628 GINT_TO_POINTER(default_bearers[i]));
631 void connman_session_set_default_config(struct connman_session_config *config)
633 config->id_type = CONNMAN_SESSION_ID_TYPE_UNKNOWN;
637 config->priority = FALSE;
638 config->roaming_policy = CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
639 config->type = CONNMAN_SESSION_TYPE_ANY;
640 config->ecall = FALSE;
642 g_slist_free(config->allowed_bearers);
643 config->allowed_bearers = NULL;
644 add_default_bearer_types(&config->allowed_bearers);
647 struct connman_session_config *connman_session_create_default_config(void)
649 struct connman_session_config *config;
651 config = g_new0(struct connman_session_config, 1);
652 connman_session_set_default_config(config);
657 static enum connman_session_type apply_policy_on_type(
658 enum connman_session_type policy,
659 enum connman_session_type type)
661 if (type == CONNMAN_SESSION_TYPE_UNKNOWN)
662 return CONNMAN_SESSION_TYPE_UNKNOWN;
664 if (policy == CONNMAN_SESSION_TYPE_ANY)
667 if (policy == CONNMAN_SESSION_TYPE_LOCAL)
668 return CONNMAN_SESSION_TYPE_LOCAL;
670 return CONNMAN_SESSION_TYPE_INTERNET;
673 int connman_session_parse_bearers(const char *token, GSList **list)
675 enum connman_service_type bearer;
678 if (g_strcmp0(token, "") == 0)
681 if (g_strcmp0(token, "*") == 0) {
682 add_default_bearer_types(list);
686 err = bearer2service(token, &bearer);
690 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
695 static int parse_bearers(DBusMessageIter *iter, GSList **list)
697 DBusMessageIter array;
700 dbus_message_iter_recurse(iter, &array);
704 while ((type = dbus_message_iter_get_arg_type(&array)) !=
706 char *bearer_name = NULL;
708 if (type != DBUS_TYPE_STRING) {
714 dbus_message_iter_get_basic(&array, &bearer_name);
716 err = connman_session_parse_bearers(bearer_name, list);
723 dbus_message_iter_next(&array);
729 static void filter_bearer(GSList *bearers,
730 enum connman_service_type policy,
733 enum connman_service_type bearer;
739 for (it = bearers; it; it = it->next) {
740 bearer = GPOINTER_TO_INT(it->data);
742 if (policy != bearer)
745 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
750 static void apply_policy_on_bearers(GSList *policy_bearers, GSList *bearers,
753 enum connman_service_type policy_bearer;
758 for (it = policy_bearers; it; it = it->next) {
759 policy_bearer = GPOINTER_TO_INT(it->data);
761 filter_bearer(bearers, policy_bearer, list);
765 static char * apply_policy_on_interface(const char *policy_interface,
766 const char *user_interface)
768 if (policy_interface)
769 return g_strdup(policy_interface);
770 else if (user_interface)
771 return g_strdup(user_interface);
776 const char *connman_session_get_owner(struct connman_session *session)
778 return session->owner;
781 static void append_allowed_bearers(DBusMessageIter *iter, void *user_data)
783 struct session_info *info = user_data;
786 for (list = info->config.allowed_bearers;
787 list; list = list->next) {
788 enum connman_service_type bearer = GPOINTER_TO_INT(list->data);
789 const char *name = __connman_service_type2string(bearer);
794 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
799 static void append_ipconfig_ipv4(DBusMessageIter *iter, void *user_data)
801 struct connman_service *service = user_data;
802 struct connman_ipconfig *ipconfig_ipv4;
807 if (!__connman_service_is_connected_state(service,
808 CONNMAN_IPCONFIG_TYPE_IPV4))
811 ipconfig_ipv4 = __connman_service_get_ip4config(service);
815 __connman_ipconfig_append_ipv4(ipconfig_ipv4, iter);
818 static void append_ipconfig_ipv6(DBusMessageIter *iter, void *user_data)
820 struct connman_service *service = user_data;
821 struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
826 if (!__connman_service_is_connected_state(service,
827 CONNMAN_IPCONFIG_TYPE_IPV6))
830 ipconfig_ipv4 = __connman_service_get_ip4config(service);
831 ipconfig_ipv6 = __connman_service_get_ip6config(service);
835 __connman_ipconfig_append_ipv6(ipconfig_ipv6, iter, ipconfig_ipv4);
838 static void append_notify(DBusMessageIter *dict,
839 struct connman_session *session)
841 struct session_info *info = session->info;
842 struct session_info *info_last = session->info_last;
843 struct connman_service *service;
844 enum connman_service_type type;
845 const char *name, *bearer;
849 if (session->append_all || info->state != info_last->state) {
850 const char *state = state2string(info->state);
852 connman_dbus_dict_append_basic(dict, "State",
855 info_last->state = info->state;
858 if (session->append_all || session->service != session->service_last) {
859 if (session->service) {
860 service = session->service;
861 name = __connman_service_get_name(service);
862 idx = __connman_service_get_index(service);
864 ifname = connman_inet_ifname(idx);
866 ifname = g_strdup("");
868 type = connman_service_get_type(service);
869 bearer = service2bearer(type);
873 ifname = g_strdup("");
877 connman_dbus_dict_append_basic(dict, "Name",
881 connman_dbus_dict_append_dict(dict, "IPv4",
882 append_ipconfig_ipv4,
885 connman_dbus_dict_append_dict(dict, "IPv6",
886 append_ipconfig_ipv6,
889 connman_dbus_dict_append_basic(dict, "Interface",
893 connman_dbus_dict_append_basic(dict, "Bearer",
899 session->service_last = session->service;
902 if (session->append_all ||
903 info->config.type != info_last->config.type) {
904 const char *type = type2string(info->config.type);
906 connman_dbus_dict_append_basic(dict, "ConnectionType",
909 info_last->config.type = info->config.type;
912 if (session->append_all ||
913 info->config.allowed_bearers != info_last->config.allowed_bearers) {
914 connman_dbus_dict_append_array(dict, "AllowedBearers",
916 append_allowed_bearers,
918 info_last->config.allowed_bearers = info->config.allowed_bearers;
921 if (session->append_all ||
922 info->config.allowed_interface != info_last->config.allowed_interface) {
923 char *ifname = info->config.allowed_interface;
926 connman_dbus_dict_append_basic(dict, "AllowedInterface",
929 info_last->config.allowed_interface = info->config.allowed_interface;
932 if (session->append_all ||
933 info->config.source_ip_rule != info_last->config.source_ip_rule) {
934 dbus_bool_t source_ip_rule = FALSE;
935 if (info->config.source_ip_rule)
936 source_ip_rule = TRUE;
937 connman_dbus_dict_append_basic(dict, "SourceIPRule",
940 info_last->config.source_ip_rule = info->config.source_ip_rule;
943 session->append_all = false;
946 static bool compute_notifiable_changes(struct connman_session *session)
948 struct session_info *info_last = session->info_last;
949 struct session_info *info = session->info;
951 if (session->append_all)
954 if (info->state != info_last->state)
957 if (session->service != session->service_last &&
958 info->state >= CONNMAN_SESSION_STATE_CONNECTED)
961 if (info->config.allowed_bearers != info_last->config.allowed_bearers ||
962 info->config.type != info_last->config.type ||
963 info->config.allowed_interface != info_last->config.allowed_interface ||
964 info->config.source_ip_rule != info_last->config.source_ip_rule)
970 static gboolean session_notify(gpointer user_data)
972 struct connman_session *session = user_data;
974 DBusMessageIter array, dict;
976 if (!compute_notifiable_changes(session))
979 DBG("session %p owner %s notify_path %s", session,
980 session->owner, session->notify_path);
982 msg = dbus_message_new_method_call(session->owner, session->notify_path,
983 CONNMAN_NOTIFICATION_INTERFACE,
988 dbus_message_iter_init_append(msg, &array);
989 connman_dbus_dict_open(&array, &dict);
991 append_notify(&dict, session);
993 connman_dbus_dict_close(&array, &dict);
995 g_dbus_send_message(connection, msg);
1000 static void ipconfig_ipv4_changed(struct connman_session *session)
1002 connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1003 "IPv4", append_ipconfig_ipv4,
1007 static void ipconfig_ipv6_changed(struct connman_session *session)
1009 connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1010 "IPv6", append_ipconfig_ipv6,
1014 int connman_session_config_update(struct connman_session *session)
1016 struct session_info *info = session->info;
1017 GSList *allowed_bearers;
1018 char *allowed_interface;
1021 DBG("session %p", session);
1024 * We update all configuration even though only one entry
1025 * might have changed. We can still optimize this later.
1028 if (session->id_type != session->policy_config->id_type) {
1029 cleanup_firewall_session(session);
1030 err = init_firewall_session(session);
1032 connman_session_destroy(session);
1036 session->id_type = session->policy_config->id_type;
1039 apply_policy_on_bearers(
1040 session->policy_config->allowed_bearers,
1041 session->user_allowed_bearers,
1044 allowed_interface = apply_policy_on_interface(
1045 session->policy_config->allowed_interface,
1046 session->user_allowed_interface);
1048 if (session->active)
1049 set_active_session(session, false);
1051 session->active = false;
1052 session_deactivate(session);
1054 g_slist_free(info->config.allowed_bearers);
1055 info->config.allowed_bearers = allowed_bearers;
1057 g_free(info->config.allowed_interface);
1058 info->config.allowed_interface = allowed_interface;
1060 session_activate(session);
1062 info->config.type = apply_policy_on_type(
1063 session->policy_config->type,
1066 info->config.roaming_policy = session->policy_config->roaming_policy;
1068 info->config.ecall = session->policy_config->ecall;
1069 if (info->config.ecall)
1070 ecall_session = session;
1072 info->config.priority = session->policy_config->priority;
1074 session_notify(session);
1079 static DBusMessage *connect_session(DBusConnection *conn,
1080 DBusMessage *msg, void *user_data)
1082 struct connman_session *session = user_data;
1084 DBG("session %p", session);
1086 if (ecall_session) {
1087 if (ecall_session->ecall && ecall_session != session)
1088 return __connman_error_failed(msg, EBUSY);
1090 session->ecall = true;
1093 if (!session->active) {
1094 session->active = true;
1095 set_active_session(session, true);
1098 session_activate(session);
1100 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1102 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1105 static DBusMessage *disconnect_session(DBusConnection *conn,
1106 DBusMessage *msg, void *user_data)
1108 struct connman_session *session = user_data;
1110 DBG("session %p", session);
1112 if (ecall_session) {
1113 if (ecall_session->ecall && ecall_session != session)
1114 return __connman_error_failed(msg, EBUSY);
1116 session->ecall = false;
1119 if (session->active) {
1120 session->active = false;
1121 set_active_session(session, false);
1124 session_deactivate(session);
1125 update_session_state(session);
1127 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1130 static DBusMessage *change_session(DBusConnection *conn,
1131 DBusMessage *msg, void *user_data)
1133 struct connman_session *session = user_data;
1134 struct session_info *info = session->info;
1135 DBusMessageIter iter, value;
1138 GSList *allowed_bearers;
1141 DBG("session %p", session);
1142 if (!dbus_message_iter_init(msg, &iter))
1143 return __connman_error_invalid_arguments(msg);
1145 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1146 return __connman_error_invalid_arguments(msg);
1148 dbus_message_iter_get_basic(&iter, &name);
1149 dbus_message_iter_next(&iter);
1151 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1152 return __connman_error_invalid_arguments(msg);
1154 dbus_message_iter_recurse(&iter, &value);
1156 switch (dbus_message_iter_get_arg_type(&value)) {
1157 case DBUS_TYPE_ARRAY:
1158 if (g_str_equal(name, "AllowedBearers")) {
1159 err = parse_bearers(&value, &allowed_bearers);
1161 return __connman_error_failed(msg, -err);
1163 if (session->active)
1164 set_active_session(session, false);
1166 session->active = false;
1167 session_deactivate(session);
1168 update_session_state(session);
1170 g_slist_free(info->config.allowed_bearers);
1171 session->user_allowed_bearers = allowed_bearers;
1173 apply_policy_on_bearers(
1174 session->policy_config->allowed_bearers,
1175 session->user_allowed_bearers,
1176 &info->config.allowed_bearers);
1178 session_activate(session);
1183 case DBUS_TYPE_STRING:
1184 if (g_str_equal(name, "ConnectionType")) {
1185 dbus_message_iter_get_basic(&value, &val);
1186 info->config.type = apply_policy_on_type(
1187 session->policy_config->type,
1188 connman_session_parse_connection_type(val));
1189 } else if (g_str_equal(name, "AllowedInterface")) {
1190 dbus_message_iter_get_basic(&value, &val);
1191 if (session->active)
1192 set_active_session(session, false);
1194 session->active = false;
1195 session_deactivate(session);
1196 update_session_state(session);
1198 g_free(session->user_allowed_interface);
1199 /* empty string means allow any interface */
1200 if (!g_strcmp0(val, ""))
1201 session->user_allowed_interface = NULL;
1203 session->user_allowed_interface = g_strdup(val);
1205 info->config.allowed_interface = apply_policy_on_interface(
1206 session->policy_config->allowed_interface,
1207 session->user_allowed_interface);
1209 session_activate(session);
1214 case DBUS_TYPE_BOOLEAN:
1215 if (g_str_equal(name, "SourceIPRule")) {
1216 dbus_bool_t source_ip_rule;
1217 dbus_message_iter_get_basic(&value, &source_ip_rule);
1219 info->config.source_ip_rule = source_ip_rule;
1220 update_session_state(session);
1229 session_notify(session);
1231 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1234 return __connman_error_invalid_arguments(msg);
1237 static void release_session(gpointer key, gpointer value, gpointer user_data)
1239 struct connman_session *session = value;
1240 DBusMessage *message;
1242 DBG("owner %s path %s", session->owner, session->notify_path);
1244 if (session->notify_watch > 0)
1245 g_dbus_remove_watch(connection, session->notify_watch);
1247 g_dbus_unregister_interface(connection, session->session_path,
1248 CONNMAN_SESSION_INTERFACE);
1250 message = dbus_message_new_method_call(session->owner,
1251 session->notify_path,
1252 CONNMAN_NOTIFICATION_INTERFACE,
1257 dbus_message_set_no_reply(message, TRUE);
1259 g_dbus_send_message(connection, message);
1262 static int session_disconnect(struct connman_session *session)
1264 DBG("session %p, %s", session, session->owner);
1266 if (session->notify_watch > 0)
1267 g_dbus_remove_watch(connection, session->notify_watch);
1269 g_dbus_unregister_interface(connection, session->session_path,
1270 CONNMAN_SESSION_INTERFACE);
1272 g_hash_table_remove(session_hash, session->session_path);
1277 static void owner_disconnect(DBusConnection *conn, void *user_data)
1279 struct connman_session *session = user_data;
1281 DBG("session %p, %s died", session, session->owner);
1283 session_disconnect(session);
1286 static DBusMessage *destroy_session(DBusConnection *conn,
1287 DBusMessage *msg, void *user_data)
1289 struct connman_session *session = user_data;
1291 DBG("session %p", session);
1293 if (ecall_session && ecall_session != session)
1294 return __connman_error_failed(msg, EBUSY);
1296 session_disconnect(session);
1298 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1301 static const GDBusMethodTable session_methods[] = {
1302 { GDBUS_METHOD("Destroy", NULL, NULL, destroy_session) },
1303 { GDBUS_METHOD("Connect", NULL, NULL, connect_session) },
1304 { GDBUS_METHOD("Disconnect", NULL, NULL,
1305 disconnect_session ) },
1306 { GDBUS_METHOD("Change",
1307 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1308 NULL, change_session) },
1312 static int session_policy_config_cb(struct connman_session *session,
1313 struct connman_session_config *config,
1314 void *user_data, int err)
1316 struct creation_data *creation_data = user_data;
1317 struct session_info *info, *info_last;
1320 DBG("session %p config %p", session, config);
1325 session->policy_config = config;
1326 session->info->config.source_ip_rule = creation_data->source_ip_rule;
1328 session->mark = session_mark++;
1329 session->index = -1;
1331 err = init_firewall_session(session);
1335 err = init_routing_table(session);
1339 info = session->info;
1340 info_last = session->info_last;
1342 if (session->policy_config->ecall)
1343 ecall_session = session;
1345 info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1346 info->config.type = apply_policy_on_type(
1347 session->policy_config->type,
1348 creation_data->type);
1349 info->config.priority = session->policy_config->priority;
1350 info->config.roaming_policy = session->policy_config->roaming_policy;
1352 session->user_allowed_bearers = creation_data->allowed_bearers;
1353 creation_data->allowed_bearers = NULL;
1355 session->user_allowed_interface = creation_data->allowed_interface;
1356 creation_data->allowed_interface = NULL;
1358 apply_policy_on_bearers(
1359 session->policy_config->allowed_bearers,
1360 session->user_allowed_bearers,
1361 &info->config.allowed_bearers);
1363 info->config.allowed_interface = apply_policy_on_interface(
1364 session->policy_config->allowed_interface,
1365 session->user_allowed_interface);
1367 g_hash_table_replace(session_hash, session->session_path, session);
1369 DBG("add %s", session->session_path);
1371 if (!g_dbus_register_interface(connection, session->session_path,
1372 CONNMAN_SESSION_INTERFACE,
1373 session_methods, NULL, NULL,
1375 connman_error("Failed to register %s", session->session_path);
1376 g_hash_table_remove(session_hash, session->session_path);
1381 reply = g_dbus_create_reply(creation_data->pending,
1382 DBUS_TYPE_OBJECT_PATH, &session->session_path,
1384 g_dbus_send_message(connection, reply);
1385 creation_data->pending = NULL;
1387 info_last->state = info->state;
1388 info_last->config.priority = info->config.priority;
1389 info_last->config.roaming_policy = info->config.roaming_policy;
1390 info_last->config.allowed_bearers = info->config.allowed_bearers;
1391 info_last->config.allowed_interface = info->config.allowed_interface;
1392 info_last->config.source_ip_rule = info->config.source_ip_rule;
1394 session->append_all = true;
1396 cleanup_creation_data(creation_data);
1398 session_activate(session);
1403 reply = __connman_error_failed(creation_data->pending, -err);
1404 g_dbus_send_message(connection, reply);
1405 creation_data->pending = NULL;
1407 cleanup_session(session);
1408 cleanup_creation_data(creation_data);
1413 int __connman_session_create(DBusMessage *msg)
1415 const char *owner, *notify_path;
1416 char *session_path = NULL;
1417 DBusMessageIter iter, array;
1418 struct connman_session *session = NULL;
1419 struct creation_data *creation_data = NULL;
1420 bool user_allowed_bearers = false;
1421 bool user_connection_type = false;
1425 owner = dbus_message_get_sender(msg);
1427 DBG("owner %s", owner);
1429 if (ecall_session && ecall_session->ecall) {
1431 * If there is an emergency call already going on,
1432 * ignore session creation attempt
1438 creation_data = g_try_new0(struct creation_data, 1);
1439 if (!creation_data) {
1444 creation_data->pending = dbus_message_ref(msg);
1446 dbus_message_iter_init(msg, &iter);
1447 dbus_message_iter_recurse(&iter, &array);
1449 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1450 DBusMessageIter entry, value;
1451 const char *key, *val;
1453 dbus_message_iter_recurse(&array, &entry);
1454 dbus_message_iter_get_basic(&entry, &key);
1456 dbus_message_iter_next(&entry);
1457 dbus_message_iter_recurse(&entry, &value);
1459 switch (dbus_message_iter_get_arg_type(&value)) {
1460 case DBUS_TYPE_ARRAY:
1461 if (g_str_equal(key, "AllowedBearers")) {
1462 err = parse_bearers(&value,
1463 &creation_data->allowed_bearers);
1467 user_allowed_bearers = true;
1473 case DBUS_TYPE_STRING:
1474 if (g_str_equal(key, "ConnectionType")) {
1475 dbus_message_iter_get_basic(&value, &val);
1476 creation_data->type =
1477 connman_session_parse_connection_type(val);
1479 user_connection_type = true;
1480 } else if (g_str_equal(key, "AllowedInterface")) {
1481 dbus_message_iter_get_basic(&value, &val);
1482 creation_data->allowed_interface = g_strdup(val);
1488 case DBUS_TYPE_BOOLEAN:
1489 if (g_str_equal(key, "SourceIPRule")) {
1490 dbus_bool_t source_ip_rule;
1491 dbus_message_iter_get_basic(&value, &source_ip_rule);
1492 creation_data->source_ip_rule = source_ip_rule;
1503 dbus_message_iter_next(&array);
1507 * If the user hasn't provided a configuration, we set
1508 * the default configuration.
1510 * For AllowedBearers this is '*', ...
1512 if (!user_allowed_bearers) {
1513 add_default_bearer_types(&creation_data->allowed_bearers);
1514 if (!creation_data->allowed_bearers) {
1520 /* ... and for ConnectionType it is 'any'. */
1521 if (!user_connection_type)
1522 creation_data->type = CONNMAN_SESSION_TYPE_ANY;
1524 dbus_message_iter_next(&iter);
1525 dbus_message_iter_get_basic(&iter, ¬ify_path);
1532 str = g_strdup(owner);
1533 for (i = 0; str[i] != '\0'; i++)
1534 if (str[i] == ':' || str[i] == '.')
1536 session_path = g_strdup_printf("/sessions/%s%s", str, notify_path);
1539 if (!session_path) {
1544 session = g_hash_table_lookup(session_hash, session_path);
1546 g_free(session_path);
1552 session = g_try_new0(struct connman_session, 1);
1554 g_free(session_path);
1559 creation_data->session = session;
1560 session->session_path = session_path;
1562 session->info = g_try_new0(struct session_info, 1);
1563 if (!session->info) {
1568 session->info_last = g_try_new0(struct session_info, 1);
1569 if (!session->info_last) {
1574 session->owner = g_strdup(owner);
1575 session->notify_path = g_strdup(notify_path);
1576 session->notify_watch =
1577 g_dbus_add_disconnect_watch(connection, session->owner,
1578 owner_disconnect, session, NULL);
1580 err = create_policy_config(session, session_policy_config_cb,
1582 if (err < 0 && err != -EINPROGRESS)
1585 return -EINPROGRESS;
1588 connman_error("Failed to create session");
1590 free_session(session);
1592 cleanup_creation_data(creation_data);
1596 bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason)
1598 if (!policy || !policy->autoconnect)
1601 return policy->autoconnect(reason);
1604 void connman_session_destroy(struct connman_session *session)
1606 DBG("session %p", session);
1608 session_disconnect(session);
1611 int __connman_session_destroy(DBusMessage *msg)
1613 const char *owner, *session_path;
1614 struct connman_session *session;
1616 owner = dbus_message_get_sender(msg);
1618 DBG("owner %s", owner);
1620 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &session_path,
1625 session = g_hash_table_lookup(session_hash, session_path);
1629 if (g_strcmp0(owner, session->owner) != 0)
1632 connman_session_destroy(session);
1637 int connman_session_connect(struct connman_service *service)
1639 DBG("service %p name %s", service, __connman_service_get_name(service));
1641 return __connman_service_connect(service,
1642 CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1645 int connman_session_disconnect(struct connman_service *service)
1647 DBG("service %p", service);
1649 return __connman_service_disconnect(service);
1652 static enum connman_session_state service_to_session_state(
1653 enum connman_service_state state)
1656 case CONNMAN_SERVICE_STATE_UNKNOWN:
1657 case CONNMAN_SERVICE_STATE_IDLE:
1658 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1659 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1660 case CONNMAN_SERVICE_STATE_DISCONNECT:
1661 case CONNMAN_SERVICE_STATE_FAILURE:
1663 case CONNMAN_SERVICE_STATE_READY:
1664 return CONNMAN_SESSION_STATE_CONNECTED;
1665 case CONNMAN_SERVICE_STATE_ONLINE:
1666 return CONNMAN_SESSION_STATE_ONLINE;
1669 return CONNMAN_SESSION_STATE_DISCONNECTED;
1672 static void update_session_state(struct connman_session *session)
1674 enum connman_service_state service_state;
1675 enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1677 if (session->service) {
1678 service_state = __connman_service_get_state(session->service);
1679 state = service_to_session_state(service_state);
1680 session->info->state = state;
1682 session->info->state = state;
1684 DBG("session %p state %s", session, state2string(state));
1686 update_firewall(session);
1687 del_nat_rules(session);
1688 update_routing_table(session);
1689 add_nat_rules(session);
1691 if (policy && policy->update_session_state)
1692 policy->update_session_state(session, state);
1694 session_notify(session);
1697 static bool session_match_service(struct connman_session *session,
1698 struct connman_service *service)
1700 enum connman_service_type bearer_type;
1701 enum connman_service_type service_type;
1702 enum connman_service_type current_service_type;
1706 if (policy && policy->allowed)
1707 return policy->allowed(session, service);
1709 current_service_type = connman_service_get_type(session->service);
1711 for (list = session->info->config.allowed_bearers; list; list = list->next) {
1712 bearer_type = GPOINTER_TO_INT(list->data);
1713 service_type = connman_service_get_type(service);
1714 ifname = connman_service_get_interface(service);
1716 if (bearer_type == current_service_type)
1719 if (bearer_type == service_type &&
1720 (session->info->config.allowed_interface == NULL ||
1721 !g_strcmp0(session->info->config.allowed_interface, "*") ||
1722 !g_strcmp0(session->info->config.allowed_interface, ifname))) {
1732 static bool is_session_connected(struct connman_session *session,
1733 enum connman_service_state state)
1737 case CONNMAN_SERVICE_STATE_UNKNOWN:
1738 case CONNMAN_SERVICE_STATE_IDLE:
1739 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1740 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1741 case CONNMAN_SERVICE_STATE_DISCONNECT:
1742 case CONNMAN_SERVICE_STATE_FAILURE:
1744 case CONNMAN_SERVICE_STATE_READY:
1745 if (session->info->config.type == CONNMAN_SESSION_TYPE_INTERNET)
1748 case CONNMAN_SERVICE_STATE_ONLINE:
1755 static void session_activate(struct connman_session *session)
1757 GHashTableIter iter;
1758 gpointer key, value;
1763 if (policy && policy->get_service_for_session) {
1764 struct connman_service *service;
1765 struct connman_service_info *info;
1766 GSList *service_list = NULL;
1767 enum connman_service_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1769 g_hash_table_iter_init(&iter, service_hash);
1771 while (g_hash_table_iter_next(&iter, &key, &value)) {
1772 struct connman_service_info *info = value;
1773 state = __connman_service_get_state(info->service);
1775 if (is_session_connected(session, state))
1776 service_list = g_slist_prepend(service_list,
1780 service_list = g_slist_reverse(service_list);
1781 service = policy->get_service_for_session(session, service_list);
1784 info = g_hash_table_lookup(service_hash, service);
1785 DBG("session %p add service %p", session, info->service);
1787 info->sessions = g_slist_prepend(info->sessions,
1789 session->service = info->service;
1790 update_session_state(session);
1793 g_slist_free(service_list);
1797 g_hash_table_iter_init(&iter, service_hash);
1798 while (g_hash_table_iter_next(&iter, &key, &value)) {
1799 struct connman_service_info *info = value;
1800 enum connman_service_state state;
1802 state = __connman_service_get_state(info->service);
1804 if (is_session_connected(session, state) &&
1805 session_match_service(session, info->service)) {
1806 DBG("session %p add service %p", session, info->service);
1808 info->sessions = g_slist_prepend(info->sessions,
1810 session->service = info->service;
1811 update_session_state(session);
1817 session_notify(session);
1820 static void session_deactivate(struct connman_session *session)
1822 struct connman_service_info *info;
1827 if (!session->service)
1830 info = g_hash_table_lookup(service_hash, session->service);
1834 info->sessions = g_slist_remove(info->sessions, session);
1835 session->service = NULL;
1837 session->info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1840 static void handle_service_state_online(struct connman_service *service,
1841 enum connman_service_state state,
1842 struct connman_service_info *info)
1844 GHashTableIter iter;
1845 gpointer key, value;
1847 g_hash_table_iter_init(&iter, session_hash);
1848 while (g_hash_table_iter_next(&iter, &key, &value)) {
1849 struct connman_session *session = value;
1852 connected = is_session_connected(session, state);
1854 if (session->service == service) {
1856 DBG("session %p remove service %p", session, service);
1857 info->sessions = g_slist_remove(info->sessions,
1859 session->service = NULL;
1860 update_session_state(session);
1862 } else if (connected && session_match_service(session, service)) {
1863 DBG("session %p add service %p", session, service);
1865 info->sessions = g_slist_prepend(info->sessions,
1867 session->service = service;
1868 update_session_state(session);
1873 static void handle_service_state_offline(struct connman_service *service,
1874 struct connman_service_info *info)
1878 for (list = info->sessions; list; list = list->next) {
1879 struct connman_session *session = list->data;
1881 if (session->service != service) {
1882 connman_warn("session %p should have session %p assigned",
1887 DBG("session %p remove service %p", session, service);
1889 session->service = NULL;
1890 update_session_state(session);
1891 session_activate(session);
1895 static void service_state_changed(struct connman_service *service,
1896 enum connman_service_state state)
1898 struct connman_service_info *info;
1900 DBG("service %p state %d", service, state);
1902 info = g_hash_table_lookup(service_hash, service);
1905 case CONNMAN_SERVICE_STATE_UNKNOWN:
1906 case CONNMAN_SERVICE_STATE_IDLE:
1907 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1908 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1909 case CONNMAN_SERVICE_STATE_FAILURE:
1910 case CONNMAN_SERVICE_STATE_DISCONNECT:
1914 handle_service_state_offline(service, info);
1916 g_hash_table_remove(service_hash, service);
1919 case CONNMAN_SERVICE_STATE_READY:
1920 case CONNMAN_SERVICE_STATE_ONLINE:
1922 info = g_new0(struct connman_service_info, 1);
1923 g_hash_table_replace(service_hash, service, info);
1926 info->service = service;
1927 handle_service_state_online(service, state, info);
1931 static void ipconfig_changed(struct connman_service *service,
1932 struct connman_ipconfig *ipconfig)
1934 GHashTableIter iter;
1935 gpointer key, value;
1936 struct connman_session *session;
1937 struct session_info *info;
1938 enum connman_ipconfig_type type;
1940 DBG("service %p ipconfig %p", service, ipconfig);
1942 type = __connman_ipconfig_get_config_type(ipconfig);
1944 g_hash_table_iter_init(&iter, session_hash);
1946 while (g_hash_table_iter_next(&iter, &key, &value)) {
1948 info = session->info;
1950 if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
1953 if (session->service && session->service == service) {
1954 update_session_state(session);
1956 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1957 ipconfig_ipv4_changed(session);
1958 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1959 ipconfig_ipv6_changed(session);
1964 static struct connman_notifier session_notifier = {
1966 .service_state_changed = service_state_changed,
1967 .ipconfig_changed = ipconfig_changed,
1970 int __connman_session_init(void)
1976 connection = connman_dbus_get_connection();
1980 err = connman_notifier_register(&session_notifier);
1982 dbus_connection_unref(connection);
1986 session_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1987 NULL, cleanup_session);
1989 service_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1990 NULL, cleanup_service);
1994 void __connman_session_cleanup(void)
2001 connman_notifier_unregister(&session_notifier);
2003 g_hash_table_foreach(session_hash, release_session, NULL);
2004 g_hash_table_destroy(session_hash);
2005 session_hash = NULL;
2006 g_hash_table_destroy(service_hash);
2007 service_hash = NULL;
2009 dbus_connection_unref(connection);