+ return 0;
+}
+
+static void owner_disconnect(DBusConnection *conn, void *user_data)
+{
+ struct connman_session *session = user_data;
+
+ DBG("session %p, %s died", session, session->owner);
+
+ session_disconnect(session);
+}
+
+static DBusMessage *destroy_session(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_session *session = user_data;
+
+ DBG("session %p", session);
+
+ if (ecall_session && ecall_session != session)
+ return __connman_error_failed(msg, EBUSY);
+
+ session_disconnect(session);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static const GDBusMethodTable session_methods[] = {
+ { GDBUS_METHOD("Destroy", NULL, NULL, destroy_session) },
+ { GDBUS_METHOD("Connect", NULL, NULL, connect_session) },
+ { GDBUS_METHOD("Disconnect", NULL, NULL,
+ disconnect_session ) },
+ { GDBUS_METHOD("Change",
+ GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
+ NULL, change_session) },
+ { },
+};
+
+static int session_policy_config_cb(struct connman_session *session,
+ struct connman_session_config *config,
+ void *user_data, int err)
+{
+ struct creation_data *creation_data = user_data;
+ struct session_info *info, *info_last;
+ DBusMessage *reply;
+
+ DBG("session %p config %p", session, config);
+
+ if (err < 0)
+ goto err;
+
+ session->policy_config = config;
+ session->info->config.source_ip_rule = creation_data->source_ip_rule;
+
+ session->mark = session_mark++;
+ session->index = -1;
+
+ err = init_firewall_session(session);
+ if (err < 0)
+ goto err;
+
+ err = init_routing_table(session);
+ if (err < 0)
+ goto err;
+
+ info = session->info;
+ info_last = session->info_last;
+
+ if (session->policy_config->ecall)
+ ecall_session = session;
+
+ info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
+ info->config.type = apply_policy_on_type(
+ session->policy_config->type,
+ creation_data->type);
+ info->config.priority = session->policy_config->priority;
+ info->config.roaming_policy = session->policy_config->roaming_policy;
+
+ session->user_allowed_bearers = creation_data->allowed_bearers;
+ creation_data->allowed_bearers = NULL;
+
+ session->user_allowed_interface = creation_data->allowed_interface;
+ creation_data->allowed_interface = NULL;
+
+ apply_policy_on_bearers(
+ session->policy_config->allowed_bearers,
+ session->user_allowed_bearers,
+ &info->config.allowed_bearers);
+
+ info->config.allowed_interface = apply_policy_on_interface(
+ session->policy_config->allowed_interface,
+ session->user_allowed_interface);
+
+ g_hash_table_replace(session_hash, session->session_path, session);
+
+ DBG("add %s", session->session_path);
+
+ if (!g_dbus_register_interface(connection, session->session_path,
+ CONNMAN_SESSION_INTERFACE,
+ session_methods, NULL, NULL,
+ session, NULL)) {
+ connman_error("Failed to register %s", session->session_path);
+ g_hash_table_remove(session_hash, session->session_path);
+ err = -EINVAL;
+ goto err;
+ }
+
+ reply = g_dbus_create_reply(creation_data->pending,
+ DBUS_TYPE_OBJECT_PATH, &session->session_path,
+ DBUS_TYPE_INVALID);
+ g_dbus_send_message(connection, reply);
+ creation_data->pending = NULL;