ipconfig: Add function to clear ipaddress information
[platform/upstream/connman.git] / src / session.c
index cc9d549..3d497b8 100644 (file)
@@ -59,21 +59,6 @@ enum connman_session_state {
        CONNMAN_SESSION_STATE_ONLINE         = 2,
 };
 
-enum connman_session_type {
-       CONNMAN_SESSION_TYPE_ANY      = 0,
-       CONNMAN_SESSION_TYPE_LOCAL    = 1,
-       CONNMAN_SESSION_TYPE_INTERNET = 2,
-};
-
-enum connman_session_roaming_policy {
-       CONNMAN_SESSION_ROAMING_POLICY_UNKNOWN          = 0,
-       CONNMAN_SESSION_ROAMING_POLICY_DEFAULT          = 1,
-       CONNMAN_SESSION_ROAMING_POLICY_ALWAYS           = 2,
-       CONNMAN_SESSION_ROAMING_POLICY_FORBIDDEN        = 3,
-       CONNMAN_SESSION_ROAMING_POLICY_NATIONAL         = 4,
-       CONNMAN_SESSION_ROAMING_POLICY_INTERNATIONAL    = 5,
-};
-
 struct service_entry {
        /* track why this service was selected */
        enum connman_session_reason reason;
@@ -86,12 +71,8 @@ struct service_entry {
 };
 
 struct session_info {
+       struct connman_session_config config;
        enum connman_session_state state;
-       enum connman_session_type type;
-       connman_bool_t priority;
-       GSList *allowed_bearers;
-       enum connman_session_roaming_policy roaming_policy;
-
        struct service_entry *entry;
        enum connman_session_reason reason;
 };
@@ -107,6 +88,7 @@ struct connman_session {
        connman_bool_t append_all;
        struct session_info *info;
        struct session_info *info_last;
+       struct connman_session_config *policy_config;
 
        connman_bool_t ecall;
 
@@ -114,12 +96,6 @@ struct connman_session {
        GHashTable *service_hash;
 };
 
-struct bearer_info {
-       char *name;
-       connman_bool_t match_all;
-       enum connman_service_type service_type;
-};
-
 static const char *trigger2string(enum connman_session_trigger trigger)
 {
        switch (trigger) {
@@ -171,8 +147,10 @@ static const char *state2string(enum connman_session_state state)
 static const char *type2string(enum connman_session_type type)
 {
        switch (type) {
-       case CONNMAN_SESSION_TYPE_ANY:
+       case CONNMAN_SESSION_TYPE_UNKNOWN:
                return "";
+       case CONNMAN_SESSION_TYPE_ANY:
+               return "any";
        case CONNMAN_SESSION_TYPE_LOCAL:
                return "local";
        case CONNMAN_SESSION_TYPE_INTERNET:
@@ -184,28 +162,14 @@ static const char *type2string(enum connman_session_type type)
 
 static enum connman_session_type string2type(const char *type)
 {
+       if (g_strcmp0(type, "any") == 0)
+               return CONNMAN_SESSION_TYPE_ANY;
        if (g_strcmp0(type, "local") == 0)
                return CONNMAN_SESSION_TYPE_LOCAL;
        else if (g_strcmp0(type, "internet") == 0)
                return CONNMAN_SESSION_TYPE_INTERNET;
 
-       return CONNMAN_SESSION_TYPE_ANY;
-}
-
-static enum connman_session_roaming_policy string2roamingpolicy(const char *policy)
-{
-       if (g_strcmp0(policy, "default") == 0)
-               return CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
-       else if (g_strcmp0(policy, "always") == 0)
-               return CONNMAN_SESSION_ROAMING_POLICY_ALWAYS;
-       else if (g_strcmp0(policy, "forbidden") == 0)
-               return CONNMAN_SESSION_ROAMING_POLICY_FORBIDDEN;
-       else if (g_strcmp0(policy, "national") == 0)
-               return CONNMAN_SESSION_ROAMING_POLICY_NATIONAL;
-       else if (g_strcmp0(policy, "international") == 0)
-               return CONNMAN_SESSION_ROAMING_POLICY_INTERNATIONAL;
-       else
-               return CONNMAN_SESSION_ROAMING_POLICY_UNKNOWN;
+       return CONNMAN_SESSION_TYPE_UNKNOWN;
 }
 
 static enum connman_service_type bearer2service(const char *bearer)
@@ -254,28 +218,6 @@ static char *service2bearer(enum connman_service_type type)
        return "";
 }
 
-static int policy_get_bool(struct connman_session *session, const char *id,
-                               const char *key, connman_bool_t *val)
-{
-       if (session->policy == NULL) {
-               *val = FALSE;
-               return -EINVAL;
-       }
-
-       return (*session->policy->get_bool)(id, key, val);
-}
-
-static int policy_get_string(struct connman_session *session, const char *id,
-                               const char *key, char **val)
-{
-       if (session->policy == NULL) {
-               *val = NULL;
-               return -EINVAL;
-       }
-
-       return (*session->policy->get_string)(id, key, val);
-}
-
 static int assign_policy_plugin(struct connman_session *session)
 {
        GSList *list;
@@ -294,6 +236,34 @@ static int assign_policy_plugin(struct connman_session *session)
        return 0;
 }
 
+static int create_policy_config(struct connman_session *session)
+{
+       struct connman_session_config *config;
+
+       if (session->policy == NULL)
+               config = connman_session_create_default_config();
+       else
+               config = (*session->policy->create)(session);
+
+       if (config == NULL)
+               return -ENOMEM;
+
+       session->policy_config = config;
+
+       return 0;
+}
+
+static void destroy_policy_config(struct connman_session *session)
+{
+       if (session->policy == NULL) {
+               connman_session_free_bearers(
+                       session->policy_config->allowed_bearers);
+               g_free(session->policy_config);
+       } else {
+               (*session->policy->destroy)(session);
+       }
+}
+
 static void probe_policy(struct connman_session_policy *policy)
 {
 
@@ -344,150 +314,215 @@ static gint compare_priority(gconstpointer a, gconstpointer b)
        return policy2->priority - policy1->priority;
 }
 
-static struct connman_session *session_lookup_by_id(const char *id)
-{
-       struct connman_session *session;
-       GHashTableIter iter;
-       gpointer key, value;
-
-       DBG("id %s", id);
-
-       g_hash_table_iter_init(&iter, session_hash);
-
-       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
-               session = value;
 
-               if (g_strcmp0(session->owner, id) == FALSE)
-                       continue;
+int connman_session_policy_register(struct connman_session_policy *policy)
+{
+       DBG("name %s", policy->name);
 
-               return session;
-       }
+       policy_list = g_slist_insert_sorted(policy_list, policy,
+                                               compare_priority);
 
-       DBG("No session found by id %s", id);
+       probe_policy(policy);
 
-       return NULL;
+       return 0;
 }
 
-int connman_session_update_bool(const char *id, const char *key,
-                                       connman_bool_t val)
+void connman_session_policy_unregister(struct connman_session_policy *policy)
 {
-       struct connman_session *session;
-       struct session_info *info;
-
-       session = session_lookup_by_id(id);
-       if (session == NULL)
-               return -EINVAL;
-
-       info = session->info;
-       if (info == NULL)
-               return 0;
+       DBG("name %s", policy->name);
 
-       DBG("%s %d", key, val);
+       policy_list = g_slist_remove(policy_list, policy);
 
-       return -EINVAL;
+       remove_policy(policy);
 }
 
-int connman_session_update_string(const char *id, const char *key,
-                                       const char *val)
+struct connman_session_config *connman_session_create_default_config(void)
 {
-       struct connman_session *session;
-       struct session_info *info;
+       struct connman_session_config *config;
 
-       session = session_lookup_by_id(id);
-       if (session == NULL)
-               return -EINVAL;
-
-       info = session->info;
-       if (info == NULL)
-               return 0;
+       config = g_try_new0(struct connman_session_config, 1);
+       if (config == NULL)
+               return NULL;
 
-       DBG("%s %s", key, val);
+       config->priority = FALSE;
+       config->roaming_policy = CONNMAN_SESSION_ROAMING_POLICY_DEFAULT;
+       config->type = CONNMAN_SESSION_TYPE_ANY;
+       config->ecall = FALSE;
+       config->allowed_bearers = connman_session_allowed_bearers_any();
+       if (config->allowed_bearers == NULL) {
+               g_free(config);
+               return NULL;
+       }
 
-       return -EINVAL;
+       return config;
 }
 
-int connman_session_policy_register(struct connman_session_policy *policy)
+static enum connman_session_type apply_policy_on_type(
+                       enum connman_session_type policy,
+                       enum connman_session_type type)
 {
-       DBG("name %s", policy->name);
+       if (type == CONNMAN_SESSION_TYPE_UNKNOWN)
+               return CONNMAN_SESSION_TYPE_UNKNOWN;
 
-       policy_list = g_slist_insert_sorted(policy_list, policy,
-                                               compare_priority);
+       if (policy == CONNMAN_SESSION_TYPE_ANY)
+               return type;
 
-       probe_policy(policy);
+       if (policy == CONNMAN_SESSION_TYPE_LOCAL)
+               return CONNMAN_SESSION_TYPE_LOCAL;
 
-       return 0;
+       return CONNMAN_SESSION_TYPE_INTERNET;
 }
 
-void connman_session_policy_unregister(struct connman_session_policy *policy)
+static void cleanup_bearer(gpointer data)
 {
-       DBG("name %s", policy->name);
+       struct connman_session_bearer *bearer = data;
 
-       policy_list = g_slist_remove(policy_list, policy);
-
-       remove_policy(policy);
+       g_free(bearer->name);
+       g_free(bearer);
 }
 
-static void cleanup_bearer_info(gpointer data, gpointer user_data)
+void connman_session_free_bearers(GSList *bearers)
 {
-       struct bearer_info *info = data;
-
-       g_free(info->name);
-       g_free(info);
+       g_slist_free_full(bearers, cleanup_bearer);
 }
 
-static GSList *session_parse_allowed_bearers(DBusMessageIter *iter)
+static int session_parse_allowed_bearers(DBusMessageIter *iter, GSList **list)
 {
-       struct bearer_info *info;
+       struct connman_session_bearer *bearer;
        DBusMessageIter array;
-       GSList *list = NULL;
 
        dbus_message_iter_recurse(iter, &array);
 
-       while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
-               char *bearer = NULL;
+       *list = NULL;
 
-               dbus_message_iter_get_basic(&array, &bearer);
+       while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
+               char *bearer_name = NULL;
 
-               info = g_try_new0(struct bearer_info, 1);
-               if (info == NULL) {
-                       g_slist_foreach(list, cleanup_bearer_info, NULL);
-                       g_slist_free(list);
+               dbus_message_iter_get_basic(&array, &bearer_name);
 
-                       return NULL;
+               bearer = g_try_new0(struct connman_session_bearer, 1);
+               if (bearer == NULL) {
+                       connman_session_free_bearers(*list);
+                       *list = NULL;
+                       return -ENOMEM;
                }
 
-               info->name = g_strdup(bearer);
-               info->service_type = bearer2service(info->name);
+               bearer->name = g_strdup(bearer_name);
+               bearer->service_type = bearer2service(bearer->name);
 
-               if (info->service_type == CONNMAN_SERVICE_TYPE_UNKNOWN &&
-                               g_strcmp0(info->name, "*") == 0) {
-                       info->match_all = TRUE;
+               if (bearer->service_type == CONNMAN_SERVICE_TYPE_UNKNOWN &&
+                               g_strcmp0(bearer->name, "*") == 0) {
+                       bearer->match_all = TRUE;
                } else {
-                       info->match_all = FALSE;
+                       bearer->match_all = FALSE;
                }
 
-               list = g_slist_append(list, info);
+               *list = g_slist_append(*list, bearer);
 
                dbus_message_iter_next(&array);
        }
 
-       return list;
+       return 0;
 }
 
-static GSList *session_allowed_bearers_any(void)
+static struct connman_session_bearer *clone_bearer(
+                                       struct connman_session_bearer *orig)
 {
-       struct bearer_info *info;
+       struct connman_session_bearer *bearer;
+
+       bearer = g_try_new0(struct connman_session_bearer, 1);
+       if (bearer == NULL)
+               return NULL;
+
+       bearer->name = g_strdup(orig->name);
+       bearer->match_all = orig->match_all;
+       bearer->service_type = orig->service_type;
+
+       return bearer;
+}
+
+static int filter_bearer(GSList *policy_bearers,
+                               struct connman_session_bearer *bearer,
+                               GSList **list)
+{
+       struct connman_session_bearer *policy, *tmp;
+       GSList *it;
+
+       if (policy_bearers == NULL)
+               goto clone;
+
+       for (it = policy_bearers; it != NULL; it = it->next) {
+               policy = it->data;
+
+               if (policy->match_all == FALSE &&
+                               bearer->service_type != policy->service_type)
+                       continue;
+
+               goto clone;
+       }
+
+       *list = NULL;
+
+       return 0;
+
+clone:
+       tmp = clone_bearer(bearer);
+       if (tmp == NULL) {
+               connman_session_free_bearers(*list);
+               *list = NULL;
+               return -ENOMEM;
+       }
+       *list = g_slist_append(*list, tmp);
+
+       return 0;
+}
+
+static connman_bool_t is_bearer_valid(struct connman_session_bearer *bearer)
+{
+       if (bearer->match_all == FALSE &&
+                       bearer->service_type == CONNMAN_SERVICE_TYPE_UNKNOWN)
+               return FALSE;
+
+       return TRUE;
+}
+
+static int apply_policy_on_bearers(GSList *policy_bearers, GSList *bearers,
+                               GSList **list)
+{
+       struct connman_session_bearer *bearer;
+       GSList *it;
+       int err;
+
+       *list = NULL;
+
+       for (it = bearers; it != NULL; it = it->next) {
+               bearer = it->data;
+
+               if (is_bearer_valid(bearer) == FALSE)
+                       continue;
+
+               err = filter_bearer(policy_bearers, bearer, list);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+GSList *connman_session_allowed_bearers_any(void)
+{
+       struct connman_session_bearer *bearer;
        GSList *list = NULL;
 
-       info = g_try_new0(struct bearer_info, 1);
-       if (info == NULL)
+       bearer = g_try_new0(struct connman_session_bearer, 1);
+       if (bearer == NULL)
                return NULL;
 
-       info->name = g_strdup("");
-       info->match_all = TRUE;
-       info->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
+       bearer->name = g_strdup("");
+       bearer->match_all = TRUE;
+       bearer->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
 
-       list = g_slist_append(list, info);
+       list = g_slist_append(list, bearer);
 
        return list;
 }
@@ -497,12 +532,12 @@ static void append_allowed_bearers(DBusMessageIter *iter, void *user_data)
        struct session_info *info = user_data;
        GSList *list;
 
-       for (list = info->allowed_bearers;
+       for (list = info->config.allowed_bearers;
                        list != NULL; list = list->next) {
-               struct bearer_info *bearer_info = list->data;
+               struct connman_session_bearer *bearer = list->data;
 
                dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
-                                               &bearer_info->name);
+                                               &bearer->name);
        }
 }
 
@@ -602,22 +637,23 @@ static void append_notify(DBusMessageIter *dict,
                info_last->entry = info->entry;
        }
 
-       if (session->append_all == TRUE || info->type != info_last->type) {
-               const char *type = type2string(info->type);
+       if (session->append_all == TRUE ||
+                       info->config.type != info_last->config.type) {
+               const char *type = type2string(info->config.type);
 
                connman_dbus_dict_append_basic(dict, "ConnectionType",
                                                DBUS_TYPE_STRING,
                                                &type);
-               info_last->type = info->type;
+               info_last->config.type = info->config.type;
        }
 
        if (session->append_all == TRUE ||
-                       info->allowed_bearers != info_last->allowed_bearers) {
+                       info->config.allowed_bearers != info_last->config.allowed_bearers) {
                connman_dbus_dict_append_array(dict, "AllowedBearers",
                                                DBUS_TYPE_STRING,
                                                append_allowed_bearers,
                                                info);
-               info_last->allowed_bearers = info->allowed_bearers;
+               info_last->config.allowed_bearers = info->config.allowed_bearers;
        }
 
        session->append_all = FALSE;
@@ -627,6 +663,8 @@ static connman_bool_t is_type_matching_state(enum connman_session_state *state,
                                                enum connman_session_type type)
 {
        switch (type) {
+       case CONNMAN_SESSION_TYPE_UNKNOWN:
+               return FALSE;
        case CONNMAN_SESSION_TYPE_ANY:
                return TRUE;
        case CONNMAN_SESSION_TYPE_LOCAL:
@@ -660,8 +698,8 @@ static connman_bool_t compute_notifiable_changes(struct connman_session *session
                        info->state >= CONNMAN_SESSION_STATE_CONNECTED)
                return TRUE;
 
-       if (info->allowed_bearers != info_last->allowed_bearers ||
-                       info->type != info_last->type)
+       if (info->config.allowed_bearers != info_last->config.allowed_bearers ||
+                       info->config.type != info_last->config.type)
                return TRUE;
 
        return FALSE;
@@ -721,16 +759,16 @@ static connman_bool_t service_type_match(struct connman_session *session,
        struct session_info *info = session->info;
        GSList *list;
 
-       for (list = info->allowed_bearers;
+       for (list = info->config.allowed_bearers;
                        list != NULL; list = list->next) {
-               struct bearer_info *bearer_info = list->data;
+               struct connman_session_bearer *bearer = list->data;
                enum connman_service_type service_type;
 
-               if (bearer_info->match_all == TRUE)
+               if (bearer->match_all == TRUE)
                        return TRUE;
 
                service_type = connman_service_get_type(service);
-               if (bearer_info->service_type == service_type)
+               if (bearer->service_type == service_type)
                        return TRUE;
        }
 
@@ -792,11 +830,11 @@ static gint sort_allowed_bearers(struct connman_service *service_a,
        type_a = connman_service_get_type(service_a);
        type_b = connman_service_get_type(service_b);
 
-       for (list = info->allowed_bearers;
+       for (list = info->config.allowed_bearers;
                        list != NULL; list = list->next) {
-               struct bearer_info *bearer_info = list->data;
+               struct connman_session_bearer *bearer = list->data;
 
-               if (bearer_info->match_all == TRUE) {
+               if (bearer->match_all == TRUE) {
                        if (type_a != type_b) {
                                weight_a = service_type_weight(type_a);
                                weight_b = service_type_weight(type_b);
@@ -811,18 +849,18 @@ static gint sort_allowed_bearers(struct connman_service *service_a,
                        }
                }
 
-               if (type_a == bearer_info->service_type &&
-                               type_b == bearer_info->service_type) {
+               if (type_a == bearer->service_type &&
+                               type_b == bearer->service_type) {
                        return 0;
                }
 
-               if (type_a == bearer_info->service_type &&
-                               type_b != bearer_info->service_type) {
+               if (type_a == bearer->service_type &&
+                               type_b != bearer->service_type) {
                        return -1;
                }
 
-               if (type_a != bearer_info->service_type &&
-                               type_b == bearer_info->service_type) {
+               if (type_a != bearer->service_type &&
+                               type_b == bearer->service_type) {
                        return 1;
                }
        }
@@ -855,9 +893,8 @@ static void cleanup_session(gpointer user_data)
                __connman_service_disconnect(info->entry->service);
        }
 
-       g_slist_foreach(info->allowed_bearers, cleanup_bearer_info, NULL);
-       g_slist_free(info->allowed_bearers);
-
+       destroy_policy_config(session);
+       connman_session_free_bearers(session->info->config.allowed_bearers);
        g_free(session->owner);
        g_free(session->session_path);
        g_free(session->notify_path);
@@ -1092,7 +1129,7 @@ static void select_connected_service(struct session_info *info,
        enum connman_session_state state;
 
        state = service_to_session_state(entry->state);
-       if (is_type_matching_state(&state, info->type) == FALSE)
+       if (is_type_matching_state(&state, info->config.type) == FALSE)
                return;
 
        info->state = state;
@@ -1260,7 +1297,7 @@ static void session_changed(struct connman_session *session,
 
                state = service_to_session_state(info->entry->state);
 
-               if (is_type_matching_state(&state, info->type) == TRUE)
+               if (is_type_matching_state(&state, info->config.type) == TRUE)
                        info->state = state;
        }
 
@@ -1269,7 +1306,7 @@ static void session_changed(struct connman_session *session,
                DBG("ignore session changed event");
                return;
        case CONNMAN_SESSION_TRIGGER_SETTING:
-               if (info->allowed_bearers != info_last->allowed_bearers) {
+               if (info->config.allowed_bearers != info_last->config.allowed_bearers) {
 
                        service_hash_last = session->service_hash;
                        service_list_last = session->service_list;
@@ -1297,10 +1334,10 @@ static void session_changed(struct connman_session *session,
                        g_sequence_free(service_list_last);
                }
 
-               if (info->type != info_last->type) {
+               if (info->config.type != info_last->config.type) {
                        if (info->state >= CONNMAN_SESSION_STATE_CONNECTED &&
                                        is_type_matching_state(&info->state,
-                                                       info->type) == FALSE)
+                                                       info->config.type) == FALSE)
                                deselect_and_disconnect(session);
                }
 
@@ -1403,6 +1440,7 @@ static DBusMessage *change_session(DBusConnection *conn,
        const char *name;
        const char *val;
        GSList *allowed_bearers;
+       int err;
 
        DBG("session %p", session);
        if (dbus_message_iter_init(msg, &iter) == FALSE)
@@ -1422,20 +1460,20 @@ static DBusMessage *change_session(DBusConnection *conn,
        switch (dbus_message_iter_get_arg_type(&value)) {
        case DBUS_TYPE_ARRAY:
                if (g_str_equal(name, "AllowedBearers") == TRUE) {
-                       allowed_bearers = session_parse_allowed_bearers(&value);
-
-                       g_slist_foreach(info->allowed_bearers,
-                                       cleanup_bearer_info, NULL);
-                       g_slist_free(info->allowed_bearers);
-
-                       if (allowed_bearers == NULL) {
-                               allowed_bearers = session_allowed_bearers_any();
-
-                               if (allowed_bearers == NULL)
-                                       return __connman_error_failed(msg, ENOMEM);
-                       }
-
-                       info->allowed_bearers = allowed_bearers;
+                       err = session_parse_allowed_bearers(&value,
+                                                       &allowed_bearers);
+                       if (err < 0)
+                               return __connman_error_failed(msg, err);
+
+                       connman_session_free_bearers(info->config.allowed_bearers);
+                       err = apply_policy_on_bearers(
+                                       session->policy_config->allowed_bearers,
+                                       allowed_bearers,
+                                       &info->config.allowed_bearers);
+
+                       connman_session_free_bearers(allowed_bearers);
+                       if (err < 0)
+                               return __connman_error_failed(msg, err);
                } else {
                        goto err;
                }
@@ -1443,7 +1481,9 @@ static DBusMessage *change_session(DBusConnection *conn,
        case DBUS_TYPE_STRING:
                if (g_str_equal(name, "ConnectionType") == TRUE) {
                        dbus_message_iter_get_basic(&value, &val);
-                       info->type = string2type(val);
+                       info->config.type = apply_policy_on_type(
+                               session->policy_config->type,
+                               string2type(val));
                } else {
                        goto err;
                }
@@ -1544,13 +1584,10 @@ int __connman_session_create(DBusMessage *msg)
        DBusMessageIter iter, array;
        struct connman_session *session = NULL;
        struct session_info *info, *info_last;
-
        enum connman_session_type type = CONNMAN_SESSION_TYPE_ANY;
-       connman_bool_t priority;
-       connman_bool_t ecall_app;
-       enum connman_session_roaming_policy roaming_policy;
-       char *roaming_policy_str;
        GSList *allowed_bearers = NULL;
+       connman_bool_t allowed_bearers_valid = FALSE;
+       connman_bool_t type_valid = FALSE;
        int err;
 
        owner = dbus_message_get_sender(msg);
@@ -1582,8 +1619,12 @@ int __connman_session_create(DBusMessage *msg)
                switch (dbus_message_iter_get_arg_type(&value)) {
                case DBUS_TYPE_ARRAY:
                        if (g_str_equal(key, "AllowedBearers") == TRUE) {
-                               allowed_bearers =
-                                       session_parse_allowed_bearers(&value);
+                               err = session_parse_allowed_bearers(&value,
+                                                       &allowed_bearers);
+                               if (err < 0)
+                                       goto err;
+
+                               allowed_bearers_valid = TRUE;
                        } else {
                                return -EINVAL;
                        }
@@ -1592,6 +1633,7 @@ int __connman_session_create(DBusMessage *msg)
                        if (g_str_equal(key, "ConnectionType") == TRUE) {
                                dbus_message_iter_get_basic(&value, &val);
                                type = string2type(val);
+                               type_valid = TRUE;
                        } else {
                                return -EINVAL;
                        }
@@ -1648,34 +1690,41 @@ int __connman_session_create(DBusMessage *msg)
                g_dbus_add_disconnect_watch(connection, session->owner,
                                        owner_disconnect, session, NULL);
 
-       assign_policy_plugin(session);
-
-       policy_get_bool(session, owner, "Priority", &priority);
-       policy_get_bool(session, owner, "EmergencyCall", &ecall_app);
-       policy_get_string(session, owner, "RoamingPolicy", &roaming_policy_str);
-       roaming_policy = string2roamingpolicy(roaming_policy_str);
+       err = assign_policy_plugin(session);
+       if (err < 0)
+               goto err;
+       err = create_policy_config(session);
+       if (err < 0)
+               goto err;
 
-       if (ecall_app == TRUE)
+       if (session->policy_config->ecall == TRUE)
                ecall_session = session;
 
        info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
-       info->type = type;
-       info->priority = priority;
-       info->roaming_policy = roaming_policy;
+       if (type_valid == FALSE)
+               type = CONNMAN_SESSION_TYPE_ANY;
+       info->config.type = apply_policy_on_type(
+                               session->policy_config->type,
+                               type);
+       info->config.priority = session->policy_config->priority;
+       info->config.roaming_policy = session->policy_config->roaming_policy;
        info->entry = NULL;
 
-       if (allowed_bearers == NULL) {
-               info->allowed_bearers =
-                               session_allowed_bearers_any();
-
-               if (info->allowed_bearers == NULL) {
+       if (allowed_bearers_valid == FALSE) {
+               allowed_bearers = connman_session_allowed_bearers_any();
+               if (allowed_bearers == NULL) {
                        err = -ENOMEM;
                        goto err;
                }
-       } else {
-               info->allowed_bearers = allowed_bearers;
        }
 
+       err = apply_policy_on_bearers(
+                       session->policy_config->allowed_bearers,
+                       allowed_bearers,
+                       &info->config.allowed_bearers);
+       if (err < 0)
+               goto err;
+
        g_hash_table_replace(session_hash, session->session_path, session);
 
        DBG("add %s", session->session_path);
@@ -1700,10 +1749,10 @@ int __connman_session_create(DBusMessage *msg)
        populate_service_list(session);
 
        info_last->state = info->state;
-       info_last->priority = info->priority;
-       info_last->roaming_policy = info->roaming_policy;
+       info_last->config.priority = info->config.priority;
+       info_last->config.roaming_policy = info->config.roaming_policy;
        info_last->entry = info->entry;
-       info_last->allowed_bearers = info->allowed_bearers;
+       info_last->config.allowed_bearers = info->config.allowed_bearers;
 
        session->append_all = TRUE;
 
@@ -1724,8 +1773,7 @@ err:
 
        g_free(session_path);
 
-       g_slist_foreach(allowed_bearers, cleanup_bearer_info, NULL);
-       g_slist_free(allowed_bearers);
+       connman_session_free_bearers(allowed_bearers);
 
        return err;
 }