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:
203 static struct fw_snat *fw_snat_lookup(int index)
205 struct fw_snat *fw_snat;
208 for (list = fw_snat_list; list; list = list->next) {
209 fw_snat = list->data;
211 if (fw_snat->index == index)
217 static int fw_snat_create(struct connman_session *session,
218 int index, const char *ifname, const char *addr)
220 struct fw_snat *fw_snat;
223 fw_snat = g_new0(struct fw_snat, 1);
225 fw_snat->fw = __connman_firewall_create();
226 fw_snat->index = index;
228 fw_snat->id = __connman_firewall_enable_snat(fw_snat->fw,
229 index, ifname, addr);
230 if (fw_snat->id < 0) {
235 fw_snat_list = g_slist_prepend(fw_snat_list, fw_snat);
236 fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
240 __connman_firewall_destroy(fw_snat->fw);
245 static void fw_snat_ref(struct connman_session *session,
246 struct fw_snat *fw_snat)
248 if (g_slist_find(fw_snat->sessions, session))
250 fw_snat->sessions = g_slist_prepend(fw_snat->sessions, session);
253 static void fw_snat_unref(struct connman_session *session,
254 struct fw_snat *fw_snat)
256 fw_snat->sessions = g_slist_remove(fw_snat->sessions, session);
257 if (fw_snat->sessions)
260 fw_snat_list = g_slist_remove(fw_snat_list, fw_snat);
262 __connman_firewall_disable_snat(fw_snat->fw);
263 __connman_firewall_destroy(fw_snat->fw);
267 static int init_firewall_session(struct connman_session *session)
269 struct firewall_context *fw;
271 struct connman_ipconfig *ipconfig = NULL;
272 const char *addr = NULL;
274 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
275 !session->info->config.source_ip_rule)
280 if (session->info->config.source_ip_rule) {
281 ipconfig = __connman_service_get_ip4config(session->service);
282 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN && !ipconfig)
286 fw = __connman_firewall_create();
290 if (session->info->config.source_ip_rule && ipconfig) {
291 addr = __connman_ipconfig_get_local(ipconfig);
294 err =__connman_firewall_enable_marking(fw,
295 session->policy_config->id_type,
296 session->policy_config->id,
297 addr, session->mark);
299 __connman_firewall_destroy(fw);
302 session->id_type = session->policy_config->id_type;
308 static void cleanup_firewall_session(struct connman_session *session)
313 __connman_firewall_disable_marking(session->fw);
314 __connman_firewall_disable_snat(session->fw);
315 __connman_firewall_destroy(session->fw);
320 static int init_routing_table(struct connman_session *session)
324 if (session->policy_config->id_type == CONNMAN_SESSION_ID_TYPE_UNKNOWN &&
325 !session->info->config.source_ip_rule)
328 if (!session->service)
333 err = __connman_inet_add_fwmark_rule(session->mark,
334 AF_INET, session->mark);
338 err = __connman_inet_add_fwmark_rule(session->mark,
339 AF_INET6, session->mark);
341 __connman_inet_del_fwmark_rule(session->mark,
342 AF_INET, session->mark);
343 session->policy_routing = true;
348 static void del_default_route(struct connman_session *session)
350 if (!session->gateway)
353 DBG("index %d routing table %d default gateway %s",
354 session->index, session->mark, session->gateway);
356 __connman_inet_del_default_from_table(session->mark,
357 session->index, session->gateway);
358 g_free(session->gateway);
359 session->gateway = NULL;
363 static void add_default_route(struct connman_session *session)
365 struct connman_ipconfig *ipconfig;
367 struct in_addr addr = { INADDR_ANY };
369 if (!session->service)
372 ipconfig = __connman_service_get_ip4config(session->service);
373 session->index = __connman_ipconfig_get_index(ipconfig);
374 session->gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig));
376 if (!session->gateway)
377 session->gateway = g_strdup(inet_ntoa(addr));
379 DBG("index %d routing table %d default gateway %s",
380 session->index, session->mark, session->gateway);
382 err = __connman_inet_add_default_to_table(session->mark,
383 session->index, session->gateway);
385 DBG("session %p %s", session, strerror(-err));
388 static void del_nat_rules(struct connman_session *session)
390 struct fw_snat *fw_snat;
392 if (!session->snat_enabled)
395 session->snat_enabled = false;
396 fw_snat = fw_snat_lookup(session->index);
401 fw_snat_unref(session, fw_snat);
404 static void add_nat_rules(struct connman_session *session)
406 struct connman_ipconfig *ipconfig;
407 struct fw_snat *fw_snat;
412 if (!session->service)
415 ipconfig = __connman_service_get_ip4config(session->service);
416 index = __connman_ipconfig_get_index(ipconfig);
417 ifname = connman_inet_ifname(index);
418 addr = __connman_ipconfig_get_local(ipconfig);
423 session->snat_enabled = true;
424 fw_snat = fw_snat_lookup(index);
426 fw_snat_ref(session, fw_snat);
430 err = fw_snat_create(session, index, ifname, addr);
432 DBG("failed to add SNAT rule");
433 session->snat_enabled = false;
439 uint32_t connman_session_firewall_get_fwmark(struct connman_session *session)
441 return session->mark;
444 static void cleanup_routing_table(struct connman_session *session)
448 if (session->policy_routing) {
449 __connman_inet_del_fwmark_rule(session->mark,
450 AF_INET6, session->mark);
452 __connman_inet_del_fwmark_rule(session->mark,
453 AF_INET, session->mark);
454 session->policy_routing = false;
457 del_default_route(session);
460 static void update_firewall(struct connman_session *session)
462 cleanup_firewall_session(session);
463 init_firewall_session(session);
466 static void update_routing_table(struct connman_session *session)
468 cleanup_routing_table(session);
469 init_routing_table(session);
470 add_default_route(session);
473 static void cleanup_nat_rules(struct connman_session *session)
475 del_nat_rules(session);
478 static void destroy_policy_config(struct connman_session *session)
481 g_free(session->policy_config);
485 policy->destroy(session);
488 static void free_session(struct connman_session *session)
493 if (session->notify_watch > 0)
494 g_dbus_remove_watch(connection, session->notify_watch);
496 destroy_policy_config(session);
497 g_slist_free(session->info->config.allowed_bearers);
498 g_free(session->info->config.allowed_interface);
499 g_free(session->owner);
500 g_free(session->session_path);
501 g_free(session->notify_path);
502 g_free(session->info);
503 g_free(session->info_last);
504 g_free(session->gateway);
509 static void set_active_session(struct connman_session *session, bool enable)
512 if (policy && policy->session_changed)
513 policy->session_changed(session, enable,
514 session->info->config.allowed_bearers);
516 __connman_service_set_active_session(enable,
517 session->info->config.allowed_bearers);
520 static void cleanup_session(gpointer user_data)
522 struct connman_session *session = user_data;
524 DBG("remove %s", session->session_path);
526 cleanup_nat_rules(session);
527 cleanup_routing_table(session);
528 cleanup_firewall_session(session);
531 set_active_session(session, false);
533 session_deactivate(session);
534 update_session_state(session);
536 g_slist_free(session->user_allowed_bearers);
537 g_free(session->user_allowed_interface);
539 free_session(session);
542 struct creation_data {
543 DBusMessage *pending;
544 struct connman_session *session;
547 enum connman_session_type type;
548 GSList *allowed_bearers;
549 char *allowed_interface;
553 static void cleanup_creation_data(struct creation_data *creation_data)
558 if (creation_data->pending)
559 dbus_message_unref(creation_data->pending);
561 g_slist_free(creation_data->allowed_bearers);
562 g_free(creation_data->allowed_interface);
563 g_free(creation_data);
566 static int create_policy_config(struct connman_session *session,
567 connman_session_config_func_t cb,
568 struct creation_data *creation_data)
570 struct connman_session_config *config;
573 config = connman_session_create_default_config();
575 free_session(session);
576 cleanup_creation_data(creation_data);
580 return cb(session, config, creation_data, 0);
583 return policy->create(session, cb, creation_data);
586 int connman_session_policy_register(struct connman_session_policy *plugin)
591 if (!plugin->create || !plugin->destroy)
594 DBG("name %s", plugin->name);
601 void connman_session_policy_unregister(struct connman_session_policy *plugin)
603 if (plugin != policy)
606 DBG("name %s", policy->name);
611 static int default_bearers[] = {
612 CONNMAN_SERVICE_TYPE_ETHERNET,
613 CONNMAN_SERVICE_TYPE_WIFI,
614 CONNMAN_SERVICE_TYPE_BLUETOOTH,
615 CONNMAN_SERVICE_TYPE_CELLULAR,
616 CONNMAN_SERVICE_TYPE_GADGET,
619 static void add_default_bearer_types(GSList **list)
623 for (i = 0; i < G_N_ELEMENTS(default_bearers); i++)
624 *list = g_slist_append(*list,
625 GINT_TO_POINTER(default_bearers[i]));
628 void connman_session_set_default_config(struct connman_session_config *config)
630 config->id_type = CONNMAN_SESSION_ID_TYPE_UNKNOWN;
634 config->priority = FALSE;
635 config->roaming_policy = CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
636 config->type = CONNMAN_SESSION_TYPE_ANY;
637 config->ecall = FALSE;
639 g_slist_free(config->allowed_bearers);
640 config->allowed_bearers = NULL;
641 add_default_bearer_types(&config->allowed_bearers);
644 struct connman_session_config *connman_session_create_default_config(void)
646 struct connman_session_config *config;
648 config = g_new0(struct connman_session_config, 1);
649 connman_session_set_default_config(config);
654 static enum connman_session_type apply_policy_on_type(
655 enum connman_session_type policy,
656 enum connman_session_type type)
658 if (type == CONNMAN_SESSION_TYPE_UNKNOWN)
659 return CONNMAN_SESSION_TYPE_UNKNOWN;
661 if (policy == CONNMAN_SESSION_TYPE_ANY)
664 if (policy == CONNMAN_SESSION_TYPE_LOCAL)
665 return CONNMAN_SESSION_TYPE_LOCAL;
667 return CONNMAN_SESSION_TYPE_INTERNET;
670 int connman_session_parse_bearers(const char *token, GSList **list)
672 enum connman_service_type bearer;
675 if (g_strcmp0(token, "") == 0)
678 if (g_strcmp0(token, "*") == 0) {
679 add_default_bearer_types(list);
683 err = bearer2service(token, &bearer);
687 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
692 static int parse_bearers(DBusMessageIter *iter, GSList **list)
694 DBusMessageIter array;
697 dbus_message_iter_recurse(iter, &array);
701 while ((type = dbus_message_iter_get_arg_type(&array)) !=
703 char *bearer_name = NULL;
705 if (type != DBUS_TYPE_STRING) {
711 dbus_message_iter_get_basic(&array, &bearer_name);
713 err = connman_session_parse_bearers(bearer_name, list);
720 dbus_message_iter_next(&array);
726 static void filter_bearer(GSList *bearers,
727 enum connman_service_type policy,
730 enum connman_service_type bearer;
736 for (it = bearers; it; it = it->next) {
737 bearer = GPOINTER_TO_INT(it->data);
739 if (policy != bearer)
742 *list = g_slist_append(*list, GINT_TO_POINTER(bearer));
747 static void apply_policy_on_bearers(GSList *policy_bearers, GSList *bearers,
750 enum connman_service_type policy_bearer;
755 for (it = policy_bearers; it; it = it->next) {
756 policy_bearer = GPOINTER_TO_INT(it->data);
758 filter_bearer(bearers, policy_bearer, list);
762 static char * apply_policy_on_interface(const char *policy_interface,
763 const char *user_interface)
765 if (policy_interface)
766 return g_strdup(policy_interface);
767 else if (user_interface)
768 return g_strdup(user_interface);
773 const char *connman_session_get_owner(struct connman_session *session)
775 return session->owner;
778 static void append_allowed_bearers(DBusMessageIter *iter, void *user_data)
780 struct session_info *info = user_data;
783 for (list = info->config.allowed_bearers;
784 list; list = list->next) {
785 enum connman_service_type bearer = GPOINTER_TO_INT(list->data);
786 const char *name = __connman_service_type2string(bearer);
791 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
796 static void append_ipconfig_ipv4(DBusMessageIter *iter, void *user_data)
798 struct connman_service *service = user_data;
799 struct connman_ipconfig *ipconfig_ipv4;
804 if (!__connman_service_is_connected_state(service,
805 CONNMAN_IPCONFIG_TYPE_IPV4))
808 ipconfig_ipv4 = __connman_service_get_ip4config(service);
812 __connman_ipconfig_append_ipv4(ipconfig_ipv4, iter);
815 static void append_ipconfig_ipv6(DBusMessageIter *iter, void *user_data)
817 struct connman_service *service = user_data;
818 struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
823 if (!__connman_service_is_connected_state(service,
824 CONNMAN_IPCONFIG_TYPE_IPV6))
827 ipconfig_ipv4 = __connman_service_get_ip4config(service);
828 ipconfig_ipv6 = __connman_service_get_ip6config(service);
832 __connman_ipconfig_append_ipv6(ipconfig_ipv6, iter, ipconfig_ipv4);
835 static void append_notify(DBusMessageIter *dict,
836 struct connman_session *session)
838 struct session_info *info = session->info;
839 struct session_info *info_last = session->info_last;
840 struct connman_service *service;
841 enum connman_service_type type;
842 const char *name, *bearer;
846 if (session->append_all || info->state != info_last->state) {
847 const char *state = state2string(info->state);
849 connman_dbus_dict_append_basic(dict, "State",
852 info_last->state = info->state;
855 if (session->append_all || session->service != session->service_last) {
856 if (session->service) {
857 service = session->service;
858 name = __connman_service_get_name(service);
859 idx = __connman_service_get_index(service);
861 ifname = connman_inet_ifname(idx);
863 ifname = g_strdup("");
865 type = connman_service_get_type(service);
866 bearer = service2bearer(type);
870 ifname = g_strdup("");
874 connman_dbus_dict_append_basic(dict, "Name",
878 connman_dbus_dict_append_dict(dict, "IPv4",
879 append_ipconfig_ipv4,
882 connman_dbus_dict_append_dict(dict, "IPv6",
883 append_ipconfig_ipv6,
886 connman_dbus_dict_append_basic(dict, "Interface",
890 connman_dbus_dict_append_basic(dict, "Bearer",
896 session->service_last = session->service;
899 if (session->append_all ||
900 info->config.type != info_last->config.type) {
901 const char *type = type2string(info->config.type);
903 connman_dbus_dict_append_basic(dict, "ConnectionType",
906 info_last->config.type = info->config.type;
909 if (session->append_all ||
910 info->config.allowed_bearers != info_last->config.allowed_bearers) {
911 connman_dbus_dict_append_array(dict, "AllowedBearers",
913 append_allowed_bearers,
915 info_last->config.allowed_bearers = info->config.allowed_bearers;
918 if (session->append_all ||
919 info->config.allowed_interface != info_last->config.allowed_interface) {
920 char *ifname = info->config.allowed_interface;
923 connman_dbus_dict_append_basic(dict, "AllowedInterface",
926 info_last->config.allowed_interface = info->config.allowed_interface;
929 if (session->append_all ||
930 info->config.source_ip_rule != info_last->config.source_ip_rule) {
931 dbus_bool_t source_ip_rule = FALSE;
932 if (info->config.source_ip_rule)
933 source_ip_rule = TRUE;
934 connman_dbus_dict_append_basic(dict, "SourceIPRule",
937 info_last->config.source_ip_rule = info->config.source_ip_rule;
940 session->append_all = false;
943 static bool compute_notifiable_changes(struct connman_session *session)
945 struct session_info *info_last = session->info_last;
946 struct session_info *info = session->info;
948 if (session->append_all)
951 if (info->state != info_last->state)
954 if (session->service != session->service_last &&
955 info->state >= CONNMAN_SESSION_STATE_CONNECTED)
958 if (info->config.allowed_bearers != info_last->config.allowed_bearers ||
959 info->config.type != info_last->config.type ||
960 info->config.allowed_interface != info_last->config.allowed_interface ||
961 info->config.source_ip_rule != info_last->config.source_ip_rule)
967 static gboolean session_notify(gpointer user_data)
969 struct connman_session *session = user_data;
971 DBusMessageIter array, dict;
973 if (!compute_notifiable_changes(session))
976 DBG("session %p owner %s notify_path %s", session,
977 session->owner, session->notify_path);
979 msg = dbus_message_new_method_call(session->owner, session->notify_path,
980 CONNMAN_NOTIFICATION_INTERFACE,
985 dbus_message_iter_init_append(msg, &array);
986 connman_dbus_dict_open(&array, &dict);
988 append_notify(&dict, session);
990 connman_dbus_dict_close(&array, &dict);
992 g_dbus_send_message(connection, msg);
997 static void ipconfig_ipv4_changed(struct connman_session *session)
999 connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1000 "IPv4", append_ipconfig_ipv4,
1004 static void ipconfig_ipv6_changed(struct connman_session *session)
1006 connman_dbus_setting_changed_dict(session->owner, session->notify_path,
1007 "IPv6", append_ipconfig_ipv6,
1011 int connman_session_config_update(struct connman_session *session)
1013 struct session_info *info = session->info;
1014 GSList *allowed_bearers;
1015 char *allowed_interface;
1018 DBG("session %p", session);
1021 * We update all configuration even though only one entry
1022 * might have changed. We can still optimize this later.
1025 if (session->id_type != session->policy_config->id_type) {
1026 cleanup_firewall_session(session);
1027 err = init_firewall_session(session);
1029 connman_session_destroy(session);
1033 session->id_type = session->policy_config->id_type;
1036 apply_policy_on_bearers(
1037 session->policy_config->allowed_bearers,
1038 session->user_allowed_bearers,
1041 allowed_interface = apply_policy_on_interface(
1042 session->policy_config->allowed_interface,
1043 session->user_allowed_interface);
1045 if (session->active)
1046 set_active_session(session, false);
1048 session->active = false;
1049 session_deactivate(session);
1051 g_slist_free(info->config.allowed_bearers);
1052 info->config.allowed_bearers = allowed_bearers;
1054 g_free(info->config.allowed_interface);
1055 info->config.allowed_interface = allowed_interface;
1057 session_activate(session);
1059 info->config.type = apply_policy_on_type(
1060 session->policy_config->type,
1063 info->config.roaming_policy = session->policy_config->roaming_policy;
1065 info->config.ecall = session->policy_config->ecall;
1066 if (info->config.ecall)
1067 ecall_session = session;
1069 info->config.priority = session->policy_config->priority;
1071 session_notify(session);
1076 static DBusMessage *connect_session(DBusConnection *conn,
1077 DBusMessage *msg, void *user_data)
1079 struct connman_session *session = user_data;
1081 DBG("session %p", session);
1083 if (ecall_session) {
1084 if (ecall_session->ecall && ecall_session != session)
1085 return __connman_error_failed(msg, EBUSY);
1087 session->ecall = true;
1090 if (!session->active) {
1091 session->active = true;
1092 set_active_session(session, true);
1095 session_activate(session);
1097 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1099 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1102 static DBusMessage *disconnect_session(DBusConnection *conn,
1103 DBusMessage *msg, void *user_data)
1105 struct connman_session *session = user_data;
1107 DBG("session %p", session);
1109 if (ecall_session) {
1110 if (ecall_session->ecall && ecall_session != session)
1111 return __connman_error_failed(msg, EBUSY);
1113 session->ecall = false;
1116 if (session->active) {
1117 session->active = false;
1118 set_active_session(session, false);
1121 session_deactivate(session);
1122 update_session_state(session);
1124 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1127 static DBusMessage *change_session(DBusConnection *conn,
1128 DBusMessage *msg, void *user_data)
1130 struct connman_session *session = user_data;
1131 struct session_info *info = session->info;
1132 DBusMessageIter iter, value;
1135 GSList *allowed_bearers;
1138 DBG("session %p", session);
1139 if (!dbus_message_iter_init(msg, &iter))
1140 return __connman_error_invalid_arguments(msg);
1142 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1143 return __connman_error_invalid_arguments(msg);
1145 dbus_message_iter_get_basic(&iter, &name);
1146 dbus_message_iter_next(&iter);
1148 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1149 return __connman_error_invalid_arguments(msg);
1151 dbus_message_iter_recurse(&iter, &value);
1153 switch (dbus_message_iter_get_arg_type(&value)) {
1154 case DBUS_TYPE_ARRAY:
1155 if (g_str_equal(name, "AllowedBearers")) {
1156 err = parse_bearers(&value, &allowed_bearers);
1158 return __connman_error_failed(msg, -err);
1160 if (session->active)
1161 set_active_session(session, false);
1163 session->active = false;
1164 session_deactivate(session);
1165 update_session_state(session);
1167 g_slist_free(info->config.allowed_bearers);
1168 session->user_allowed_bearers = allowed_bearers;
1170 apply_policy_on_bearers(
1171 session->policy_config->allowed_bearers,
1172 session->user_allowed_bearers,
1173 &info->config.allowed_bearers);
1175 session_activate(session);
1180 case DBUS_TYPE_STRING:
1181 if (g_str_equal(name, "ConnectionType")) {
1182 dbus_message_iter_get_basic(&value, &val);
1183 info->config.type = apply_policy_on_type(
1184 session->policy_config->type,
1185 connman_session_parse_connection_type(val));
1186 } else if (g_str_equal(name, "AllowedInterface")) {
1187 dbus_message_iter_get_basic(&value, &val);
1188 if (session->active)
1189 set_active_session(session, false);
1191 session->active = false;
1192 session_deactivate(session);
1193 update_session_state(session);
1195 g_free(session->user_allowed_interface);
1196 /* empty string means allow any interface */
1197 if (!g_strcmp0(val, ""))
1198 session->user_allowed_interface = NULL;
1200 session->user_allowed_interface = g_strdup(val);
1202 info->config.allowed_interface = apply_policy_on_interface(
1203 session->policy_config->allowed_interface,
1204 session->user_allowed_interface);
1206 session_activate(session);
1211 case DBUS_TYPE_BOOLEAN:
1212 if (g_str_equal(name, "SourceIPRule")) {
1213 dbus_bool_t source_ip_rule;
1214 dbus_message_iter_get_basic(&value, &source_ip_rule);
1216 info->config.source_ip_rule = source_ip_rule;
1217 update_session_state(session);
1226 session_notify(session);
1228 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1231 return __connman_error_invalid_arguments(msg);
1234 static void release_session(gpointer key, gpointer value, gpointer user_data)
1236 struct connman_session *session = value;
1237 DBusMessage *message;
1239 DBG("owner %s path %s", session->owner, session->notify_path);
1241 if (session->notify_watch > 0)
1242 g_dbus_remove_watch(connection, session->notify_watch);
1244 g_dbus_unregister_interface(connection, session->session_path,
1245 CONNMAN_SESSION_INTERFACE);
1247 message = dbus_message_new_method_call(session->owner,
1248 session->notify_path,
1249 CONNMAN_NOTIFICATION_INTERFACE,
1254 dbus_message_set_no_reply(message, TRUE);
1256 g_dbus_send_message(connection, message);
1259 static int session_disconnect(struct connman_session *session)
1261 DBG("session %p, %s", session, session->owner);
1263 if (session->notify_watch > 0)
1264 g_dbus_remove_watch(connection, session->notify_watch);
1266 g_dbus_unregister_interface(connection, session->session_path,
1267 CONNMAN_SESSION_INTERFACE);
1269 g_hash_table_remove(session_hash, session->session_path);
1274 static void owner_disconnect(DBusConnection *conn, void *user_data)
1276 struct connman_session *session = user_data;
1278 DBG("session %p, %s died", session, session->owner);
1280 session_disconnect(session);
1283 static DBusMessage *destroy_session(DBusConnection *conn,
1284 DBusMessage *msg, void *user_data)
1286 struct connman_session *session = user_data;
1288 DBG("session %p", session);
1290 if (ecall_session && ecall_session != session)
1291 return __connman_error_failed(msg, EBUSY);
1293 session_disconnect(session);
1295 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
1298 static const GDBusMethodTable session_methods[] = {
1299 { GDBUS_METHOD("Destroy", NULL, NULL, destroy_session) },
1300 { GDBUS_METHOD("Connect", NULL, NULL, connect_session) },
1301 { GDBUS_METHOD("Disconnect", NULL, NULL,
1302 disconnect_session ) },
1303 { GDBUS_METHOD("Change",
1304 GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1305 NULL, change_session) },
1309 static int session_policy_config_cb(struct connman_session *session,
1310 struct connman_session_config *config,
1311 void *user_data, int err)
1313 struct creation_data *creation_data = user_data;
1314 struct session_info *info, *info_last;
1317 DBG("session %p config %p", session, config);
1322 session->policy_config = config;
1323 session->info->config.source_ip_rule = creation_data->source_ip_rule;
1325 session->mark = session_mark++;
1326 session->index = -1;
1328 err = init_firewall_session(session);
1332 err = init_routing_table(session);
1336 info = session->info;
1337 info_last = session->info_last;
1339 if (session->policy_config->ecall)
1340 ecall_session = session;
1342 info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1343 info->config.type = apply_policy_on_type(
1344 session->policy_config->type,
1345 creation_data->type);
1346 info->config.priority = session->policy_config->priority;
1347 info->config.roaming_policy = session->policy_config->roaming_policy;
1349 session->user_allowed_bearers = creation_data->allowed_bearers;
1350 creation_data->allowed_bearers = NULL;
1352 session->user_allowed_interface = creation_data->allowed_interface;
1353 creation_data->allowed_interface = NULL;
1355 apply_policy_on_bearers(
1356 session->policy_config->allowed_bearers,
1357 session->user_allowed_bearers,
1358 &info->config.allowed_bearers);
1360 info->config.allowed_interface = apply_policy_on_interface(
1361 session->policy_config->allowed_interface,
1362 session->user_allowed_interface);
1364 g_hash_table_replace(session_hash, session->session_path, session);
1366 DBG("add %s", session->session_path);
1368 if (!g_dbus_register_interface(connection, session->session_path,
1369 CONNMAN_SESSION_INTERFACE,
1370 session_methods, NULL, NULL,
1372 connman_error("Failed to register %s", session->session_path);
1373 g_hash_table_remove(session_hash, session->session_path);
1378 reply = g_dbus_create_reply(creation_data->pending,
1379 DBUS_TYPE_OBJECT_PATH, &session->session_path,
1381 g_dbus_send_message(connection, reply);
1382 creation_data->pending = NULL;
1384 info_last->state = info->state;
1385 info_last->config.priority = info->config.priority;
1386 info_last->config.roaming_policy = info->config.roaming_policy;
1387 info_last->config.allowed_bearers = info->config.allowed_bearers;
1388 info_last->config.allowed_interface = info->config.allowed_interface;
1389 info_last->config.source_ip_rule = info->config.source_ip_rule;
1391 session->append_all = true;
1393 cleanup_creation_data(creation_data);
1395 session_activate(session);
1400 reply = __connman_error_failed(creation_data->pending, -err);
1401 g_dbus_send_message(connection, reply);
1402 creation_data->pending = NULL;
1404 cleanup_session(session);
1405 cleanup_creation_data(creation_data);
1410 int __connman_session_create(DBusMessage *msg)
1412 const char *owner, *notify_path;
1413 char *session_path = NULL;
1414 DBusMessageIter iter, array;
1415 struct connman_session *session = NULL;
1416 struct creation_data *creation_data = NULL;
1417 bool user_allowed_bearers = false;
1418 bool user_connection_type = false;
1422 owner = dbus_message_get_sender(msg);
1424 DBG("owner %s", owner);
1426 if (ecall_session && ecall_session->ecall) {
1428 * If there is an emergency call already going on,
1429 * ignore session creation attempt
1435 creation_data = g_try_new0(struct creation_data, 1);
1436 if (!creation_data) {
1441 creation_data->pending = dbus_message_ref(msg);
1443 dbus_message_iter_init(msg, &iter);
1444 dbus_message_iter_recurse(&iter, &array);
1446 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
1447 DBusMessageIter entry, value;
1448 const char *key, *val;
1450 dbus_message_iter_recurse(&array, &entry);
1451 dbus_message_iter_get_basic(&entry, &key);
1453 dbus_message_iter_next(&entry);
1454 dbus_message_iter_recurse(&entry, &value);
1456 switch (dbus_message_iter_get_arg_type(&value)) {
1457 case DBUS_TYPE_ARRAY:
1458 if (g_str_equal(key, "AllowedBearers")) {
1459 err = parse_bearers(&value,
1460 &creation_data->allowed_bearers);
1464 user_allowed_bearers = true;
1470 case DBUS_TYPE_STRING:
1471 if (g_str_equal(key, "ConnectionType")) {
1472 dbus_message_iter_get_basic(&value, &val);
1473 creation_data->type =
1474 connman_session_parse_connection_type(val);
1476 user_connection_type = true;
1477 } else if (g_str_equal(key, "AllowedInterface")) {
1478 dbus_message_iter_get_basic(&value, &val);
1479 creation_data->allowed_interface = g_strdup(val);
1485 case DBUS_TYPE_BOOLEAN:
1486 if (g_str_equal(key, "SourceIPRule")) {
1487 dbus_bool_t source_ip_rule;
1488 dbus_message_iter_get_basic(&value, &source_ip_rule);
1489 creation_data->source_ip_rule = source_ip_rule;
1500 dbus_message_iter_next(&array);
1504 * If the user hasn't provided a configuration, we set
1505 * the default configuration.
1507 * For AllowedBearers this is '*', ...
1509 if (!user_allowed_bearers) {
1510 add_default_bearer_types(&creation_data->allowed_bearers);
1511 if (!creation_data->allowed_bearers) {
1517 /* ... and for ConnectionType it is 'any'. */
1518 if (!user_connection_type)
1519 creation_data->type = CONNMAN_SESSION_TYPE_ANY;
1521 dbus_message_iter_next(&iter);
1522 dbus_message_iter_get_basic(&iter, ¬ify_path);
1529 str = g_strdup(owner);
1530 for (i = 0; str[i] != '\0'; i++)
1531 if (str[i] == ':' || str[i] == '.')
1533 session_path = g_strdup_printf("/sessions/%s%s", str, notify_path);
1536 if (!session_path) {
1541 session = g_hash_table_lookup(session_hash, session_path);
1543 g_free(session_path);
1549 session = g_try_new0(struct connman_session, 1);
1551 g_free(session_path);
1556 creation_data->session = session;
1557 session->session_path = session_path;
1559 session->info = g_try_new0(struct session_info, 1);
1560 if (!session->info) {
1565 session->info_last = g_try_new0(struct session_info, 1);
1566 if (!session->info_last) {
1571 session->owner = g_strdup(owner);
1572 session->notify_path = g_strdup(notify_path);
1573 session->notify_watch =
1574 g_dbus_add_disconnect_watch(connection, session->owner,
1575 owner_disconnect, session, NULL);
1577 err = create_policy_config(session, session_policy_config_cb,
1579 if (err < 0 && err != -EINPROGRESS)
1582 return -EINPROGRESS;
1585 connman_error("Failed to create session");
1587 free_session(session);
1589 cleanup_creation_data(creation_data);
1593 bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason)
1595 if (!policy || !policy->autoconnect)
1598 return policy->autoconnect(reason);
1601 void connman_session_destroy(struct connman_session *session)
1603 DBG("session %p", session);
1605 session_disconnect(session);
1608 int __connman_session_destroy(DBusMessage *msg)
1610 const char *owner, *session_path;
1611 struct connman_session *session;
1613 owner = dbus_message_get_sender(msg);
1615 DBG("owner %s", owner);
1617 dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &session_path,
1622 session = g_hash_table_lookup(session_hash, session_path);
1626 if (g_strcmp0(owner, session->owner) != 0)
1629 connman_session_destroy(session);
1634 int connman_session_connect(struct connman_service *service)
1636 DBG("service %p name %s", service, __connman_service_get_name(service));
1638 return __connman_service_connect(service,
1639 CONNMAN_SERVICE_CONNECT_REASON_SESSION);
1642 int connman_session_disconnect(struct connman_service *service)
1644 DBG("service %p", service);
1646 return __connman_service_disconnect(service);
1649 static enum connman_session_state service_to_session_state(
1650 enum connman_service_state state)
1653 case CONNMAN_SERVICE_STATE_UNKNOWN:
1654 case CONNMAN_SERVICE_STATE_IDLE:
1655 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1656 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1657 case CONNMAN_SERVICE_STATE_DISCONNECT:
1658 case CONNMAN_SERVICE_STATE_FAILURE:
1660 case CONNMAN_SERVICE_STATE_READY:
1661 return CONNMAN_SESSION_STATE_CONNECTED;
1662 case CONNMAN_SERVICE_STATE_ONLINE:
1663 return CONNMAN_SESSION_STATE_ONLINE;
1666 return CONNMAN_SESSION_STATE_DISCONNECTED;
1669 static void update_session_state(struct connman_session *session)
1671 enum connman_service_state service_state;
1672 enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1674 if (session->service) {
1675 service_state = __connman_service_get_state(session->service);
1676 state = service_to_session_state(service_state);
1677 session->info->state = state;
1679 session->info->state = state;
1681 DBG("session %p state %s", session, state2string(state));
1683 update_firewall(session);
1684 del_nat_rules(session);
1685 update_routing_table(session);
1686 add_nat_rules(session);
1688 if (policy && policy->update_session_state)
1689 policy->update_session_state(session, state);
1691 session_notify(session);
1694 static bool session_match_service(struct connman_session *session,
1695 struct connman_service *service)
1697 enum connman_service_type bearer_type;
1698 enum connman_service_type service_type;
1699 enum connman_service_type current_service_type;
1703 if (policy && policy->allowed)
1704 return policy->allowed(session, service);
1706 current_service_type = connman_service_get_type(session->service);
1708 for (list = session->info->config.allowed_bearers; list; list = list->next) {
1709 bearer_type = GPOINTER_TO_INT(list->data);
1710 service_type = connman_service_get_type(service);
1711 ifname = connman_service_get_interface(service);
1713 if (bearer_type == current_service_type)
1716 if (bearer_type == service_type &&
1717 (session->info->config.allowed_interface == NULL ||
1718 !g_strcmp0(session->info->config.allowed_interface, "*") ||
1719 !g_strcmp0(session->info->config.allowed_interface, ifname))) {
1729 static bool is_session_connected(struct connman_session *session,
1730 enum connman_service_state state)
1734 case CONNMAN_SERVICE_STATE_UNKNOWN:
1735 case CONNMAN_SERVICE_STATE_IDLE:
1736 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1737 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1738 case CONNMAN_SERVICE_STATE_DISCONNECT:
1739 case CONNMAN_SERVICE_STATE_FAILURE:
1741 case CONNMAN_SERVICE_STATE_READY:
1742 if (session->info->config.type == CONNMAN_SESSION_TYPE_INTERNET)
1745 case CONNMAN_SERVICE_STATE_ONLINE:
1752 static void session_activate(struct connman_session *session)
1754 GHashTableIter iter;
1755 gpointer key, value;
1760 if (policy && policy->get_service_for_session) {
1761 struct connman_service *service;
1762 struct connman_service_info *info;
1763 GSList *service_list = NULL;
1764 enum connman_service_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
1766 g_hash_table_iter_init(&iter, service_hash);
1768 while (g_hash_table_iter_next(&iter, &key, &value)) {
1769 struct connman_service_info *info = value;
1770 state = __connman_service_get_state(info->service);
1772 if (is_session_connected(session, state))
1773 service_list = g_slist_prepend(service_list,
1777 service_list = g_slist_reverse(service_list);
1778 service = policy->get_service_for_session(session, service_list);
1781 info = g_hash_table_lookup(service_hash, service);
1782 DBG("session %p add service %p", session, info->service);
1784 info->sessions = g_slist_prepend(info->sessions,
1786 session->service = info->service;
1787 update_session_state(session);
1790 g_slist_free(service_list);
1794 g_hash_table_iter_init(&iter, service_hash);
1795 while (g_hash_table_iter_next(&iter, &key, &value)) {
1796 struct connman_service_info *info = value;
1797 enum connman_service_state state;
1799 state = __connman_service_get_state(info->service);
1801 if (is_session_connected(session, state) &&
1802 session_match_service(session, info->service)) {
1803 DBG("session %p add service %p", session, info->service);
1805 info->sessions = g_slist_prepend(info->sessions,
1807 session->service = info->service;
1808 update_session_state(session);
1814 session_notify(session);
1817 static void session_deactivate(struct connman_session *session)
1819 struct connman_service_info *info;
1824 if (!session->service)
1827 info = g_hash_table_lookup(service_hash, session->service);
1831 info->sessions = g_slist_remove(info->sessions, session);
1832 session->service = NULL;
1834 session->info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
1837 static void handle_service_state_online(struct connman_service *service,
1838 enum connman_service_state state,
1839 struct connman_service_info *info)
1841 GHashTableIter iter;
1842 gpointer key, value;
1844 g_hash_table_iter_init(&iter, session_hash);
1845 while (g_hash_table_iter_next(&iter, &key, &value)) {
1846 struct connman_session *session = value;
1849 connected = is_session_connected(session, state);
1851 if (session->service == service) {
1853 DBG("session %p remove service %p", session, service);
1854 info->sessions = g_slist_remove(info->sessions,
1856 session->service = NULL;
1857 update_session_state(session);
1859 } else if (connected && session_match_service(session, service)) {
1860 DBG("session %p add service %p", session, service);
1862 info->sessions = g_slist_prepend(info->sessions,
1864 session->service = service;
1865 update_session_state(session);
1870 static void handle_service_state_offline(struct connman_service *service,
1871 struct connman_service_info *info)
1875 for (list = info->sessions; list; list = list->next) {
1876 struct connman_session *session = list->data;
1878 if (session->service != service) {
1879 connman_warn("session %p should have session %p assigned",
1884 DBG("session %p remove service %p", session, service);
1886 session->service = NULL;
1887 update_session_state(session);
1888 session_activate(session);
1892 static void service_state_changed(struct connman_service *service,
1893 enum connman_service_state state)
1895 struct connman_service_info *info;
1897 DBG("service %p state %d", service, state);
1899 info = g_hash_table_lookup(service_hash, service);
1902 case CONNMAN_SERVICE_STATE_UNKNOWN:
1903 case CONNMAN_SERVICE_STATE_IDLE:
1904 case CONNMAN_SERVICE_STATE_ASSOCIATION:
1905 case CONNMAN_SERVICE_STATE_CONFIGURATION:
1906 case CONNMAN_SERVICE_STATE_FAILURE:
1907 case CONNMAN_SERVICE_STATE_DISCONNECT:
1911 handle_service_state_offline(service, info);
1913 g_hash_table_remove(service_hash, service);
1916 case CONNMAN_SERVICE_STATE_READY:
1917 case CONNMAN_SERVICE_STATE_ONLINE:
1919 info = g_new0(struct connman_service_info, 1);
1920 g_hash_table_replace(service_hash, service, info);
1923 info->service = service;
1924 handle_service_state_online(service, state, info);
1928 static void ipconfig_changed(struct connman_service *service,
1929 struct connman_ipconfig *ipconfig)
1931 GHashTableIter iter;
1932 gpointer key, value;
1933 struct connman_session *session;
1934 struct session_info *info;
1935 enum connman_ipconfig_type type;
1937 DBG("service %p ipconfig %p", service, ipconfig);
1939 type = __connman_ipconfig_get_config_type(ipconfig);
1941 g_hash_table_iter_init(&iter, session_hash);
1943 while (g_hash_table_iter_next(&iter, &key, &value)) {
1945 info = session->info;
1947 if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED)
1950 if (session->service && session->service == service) {
1951 update_session_state(session);
1953 if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1954 ipconfig_ipv4_changed(session);
1955 else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1956 ipconfig_ipv6_changed(session);
1961 static struct connman_notifier session_notifier = {
1963 .service_state_changed = service_state_changed,
1964 .ipconfig_changed = ipconfig_changed,
1967 int __connman_session_init(void)
1973 connection = connman_dbus_get_connection();
1977 err = connman_notifier_register(&session_notifier);
1979 dbus_connection_unref(connection);
1983 session_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
1984 NULL, cleanup_session);
1986 service_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1987 NULL, cleanup_service);
1991 void __connman_session_cleanup(void)
1998 connman_notifier_unregister(&session_notifier);
2000 g_hash_table_foreach(session_hash, release_session, NULL);
2001 g_hash_table_destroy(session_hash);
2002 session_hash = NULL;
2003 g_hash_table_destroy(service_hash);
2004 service_hash = NULL;
2006 dbus_connection_unref(connection);