Fix derefrencing of NULL pointer
[platform/upstream/connman.git] / src / session.c
index 9e3c559..6000b6d 100644 (file)
@@ -28,8 +28,6 @@
 
 #include <gdbus.h>
 
-#include <connman/session.h>
-
 #include "connman.h"
 
 static DBusConnection *connection;
@@ -65,7 +63,9 @@ struct connman_session {
        struct firewall_context *fw;
        uint32_t mark;
        int index;
+       char *addr;
        char *gateway;
+       unsigned char prefixlen;
        bool policy_routing;
        bool snat_enabled;
 };
@@ -79,6 +79,7 @@ struct fw_snat {
        GSList *sessions;
        int id;
        int index;
+       char *addr;
        struct firewall_context *fw;
 };
 
@@ -194,13 +195,16 @@ static char *service2bearer(enum connman_service_type type)
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
        case CONNMAN_SERVICE_TYPE_UNKNOWN:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                return "";
        }
 
        return "";
 }
 
-static struct fw_snat *fw_snat_lookup(int index)
+static struct fw_snat *fw_snat_lookup(int index, const char *addr)
 {
        struct fw_snat *fw_snat;
        GSList *list;
@@ -208,8 +212,11 @@ static struct fw_snat *fw_snat_lookup(int index)
        for (list = fw_snat_list; list; list = list->next) {
                fw_snat = list->data;
 
-               if (fw_snat->index == index)
+               if (fw_snat->index == index) {
+                       if (g_strcmp0(addr, fw_snat->addr) != 0)
+                               continue;
                        return fw_snat;
+               }
        }
        return NULL;
 }
@@ -224,6 +231,7 @@ static int fw_snat_create(struct connman_session *session,
 
        fw_snat->fw = __connman_firewall_create();
        fw_snat->index = index;
+       fw_snat->addr = g_strdup(addr);
 
        fw_snat->id = __connman_firewall_enable_snat(fw_snat->fw,
                                                index, ifname, addr);
@@ -238,6 +246,7 @@ static int fw_snat_create(struct connman_session *session,
        return 0;
 err:
        __connman_firewall_destroy(fw_snat->fw);
+       g_free(fw_snat->addr);
        g_free(fw_snat);
        return err;
 }
@@ -350,13 +359,17 @@ static void del_default_route(struct connman_session *session)
        if (!session->gateway)
                return;
 
-       DBG("index %d routing table %d default gateway %s",
-               session->index, session->mark, session->gateway);
+       DBG("index %d routing table %d default gateway %s/%u",
+               session->index, session->mark, session->gateway, session->prefixlen);
+
+       __connman_inet_del_subnet_from_table(session->mark,
+               session->index, session->gateway, session->prefixlen);
 
        __connman_inet_del_default_from_table(session->mark,
                                        session->index, session->gateway);
        g_free(session->gateway);
        session->gateway = NULL;
+       session->prefixlen = 0;
        session->index = -1;
 }
 
@@ -376,13 +389,20 @@ static void add_default_route(struct connman_session *session)
        if (!session->gateway)
                session->gateway = g_strdup(inet_ntoa(addr));
 
-       DBG("index %d routing table %d default gateway %s",
-               session->index, session->mark, session->gateway);
+       session->prefixlen = __connman_ipconfig_get_prefixlen(ipconfig);
+
+       DBG("index %d routing table %d default gateway %s/%u",
+               session->index, session->mark, session->gateway, session->prefixlen);
 
        err = __connman_inet_add_default_to_table(session->mark,
                                        session->index, session->gateway);
        if (err < 0)
                DBG("session %p %s", session, strerror(-err));
+
+       err = __connman_inet_add_subnet_to_table(session->mark,
+                                       session->index, session->gateway, session->prefixlen);
+       if (err < 0)
+               DBG("session add subnet route %p %s", session, strerror(-err));
 }
 
 static void del_nat_rules(struct connman_session *session)
@@ -393,7 +413,7 @@ static void del_nat_rules(struct connman_session *session)
                return;
 
        session->snat_enabled = false;
-       fw_snat = fw_snat_lookup(session->index);
+       fw_snat = fw_snat_lookup(session->index, session->addr);
 
        if (!fw_snat)
                return;
@@ -420,8 +440,11 @@ static void add_nat_rules(struct connman_session *session)
        if (!addr)
                return;
 
+       g_free(session->addr);
+       session->addr = g_strdup(addr);
+
        session->snat_enabled = true;
-       fw_snat = fw_snat_lookup(index);
+       fw_snat = fw_snat_lookup(index, session->addr);
        if (fw_snat) {
                fw_snat_ref(session, fw_snat);
                return;
@@ -493,6 +516,9 @@ static void free_session(struct connman_session *session)
        if (session->notify_watch > 0)
                g_dbus_remove_watch(connection, session->notify_watch);
 
+       g_dbus_unregister_interface(connection, session->session_path,
+                                   CONNMAN_SESSION_INTERFACE);
+
        destroy_policy_config(session);
        g_slist_free(session->info->config.allowed_bearers);
        g_free(session->info->config.allowed_interface);
@@ -502,6 +528,7 @@ static void free_session(struct connman_session *session)
        g_free(session->info);
        g_free(session->info_last);
        g_free(session->gateway);
+       g_free(session->addr);
 
        g_free(session);
 }
@@ -548,6 +575,7 @@ struct creation_data {
        GSList *allowed_bearers;
        char *allowed_interface;
        bool source_ip_rule;
+       char *context_identifier;
 };
 
 static void cleanup_creation_data(struct creation_data *creation_data)
@@ -557,6 +585,8 @@ static void cleanup_creation_data(struct creation_data *creation_data)
 
        if (creation_data->pending)
                dbus_message_unref(creation_data->pending);
+       if (creation_data->context_identifier)
+               g_free(creation_data->context_identifier);
 
        g_slist_free(creation_data->allowed_bearers);
        g_free(creation_data->allowed_interface);
@@ -927,6 +957,17 @@ static void append_notify(DBusMessageIter *dict,
        }
 
        if (session->append_all ||
+                       info->config.context_identifier != info_last->config.context_identifier) {
+               char *ifname = info->config.context_identifier;
+               if (!ifname)
+                       ifname = "";
+               connman_dbus_dict_append_basic(dict, "ContextIdentifier",
+                                               DBUS_TYPE_STRING,
+                                               &ifname);
+               info_last->config.context_identifier = info->config.context_identifier;
+       }
+
+       if (session->append_all ||
                        info->config.source_ip_rule != info_last->config.source_ip_rule) {
                dbus_bool_t source_ip_rule = FALSE;
                if (info->config.source_ip_rule)
@@ -1372,7 +1413,7 @@ static int session_policy_config_cb(struct connman_session *session,
                connman_error("Failed to register %s", session->session_path);
                g_hash_table_remove(session_hash, session->session_path);
                err = -EINVAL;
-               goto err;
+               goto err_notify;
        }
 
        reply = g_dbus_create_reply(creation_data->pending,
@@ -1397,11 +1438,13 @@ static int session_policy_config_cb(struct connman_session *session,
        return 0;
 
 err:
+       cleanup_session(session);
+
+err_notify:
        reply = __connman_error_failed(creation_data->pending, -err);
        g_dbus_send_message(connection, reply);
        creation_data->pending = NULL;
 
-       cleanup_session(session);
        cleanup_creation_data(creation_data);
 
        return err;
@@ -1474,6 +1517,9 @@ int __connman_session_create(DBusMessage *msg)
                                        connman_session_parse_connection_type(val);
 
                                user_connection_type = true;
+                       } else if (g_str_equal(key, "ContextIdentifier")) {
+                               dbus_message_iter_get_basic(&value, &val);
+                               creation_data->context_identifier = g_strdup(val);
                        } else if (g_str_equal(key, "AllowedInterface")) {
                                dbus_message_iter_get_basic(&value, &val);
                                creation_data->allowed_interface = g_strdup(val);
@@ -1672,7 +1718,7 @@ static void update_session_state(struct connman_session *session)
        enum connman_session_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
 
        if (session->service) {
-               service_state = __connman_service_get_state(session->service);
+               service_state = connman_service_get_state(session->service);
                state = service_to_session_state(service_state);
                session->info->state = state;
        }
@@ -1710,8 +1756,16 @@ static bool session_match_service(struct connman_session *session,
                service_type = connman_service_get_type(service);
                ifname = connman_service_get_interface(service);
 
+
+#if defined TIZEN_EXT
+               if (bearer_type == current_service_type) {
+                       g_free(ifname);
+                       return false;
+               }
+#else
                if (bearer_type == current_service_type)
                        return false;
+#endif
 
                if (bearer_type == service_type &&
                        (session->info->config.allowed_interface == NULL ||
@@ -1767,7 +1821,7 @@ static void session_activate(struct connman_session *session)
 
                while (g_hash_table_iter_next(&iter, &key, &value)) {
                        struct connman_service_info *info = value;
-                       state = __connman_service_get_state(info->service);
+                       state = connman_service_get_state(info->service);
 
                        if (is_session_connected(session, state))
                                service_list = g_slist_prepend(service_list,
@@ -1796,7 +1850,7 @@ static void session_activate(struct connman_session *session)
                struct connman_service_info *info = value;
                enum connman_service_state state;
 
-               state = __connman_service_get_state(info->service);
+               state = connman_service_get_state(info->service);
 
                if (is_session_connected(session, state) &&
                                session_match_service(session, info->service)) {
@@ -1958,7 +2012,7 @@ static void ipconfig_changed(struct connman_service *service,
        }
 }
 
-static struct connman_notifier session_notifier = {
+static const struct connman_notifier session_notifier = {
        .name                   = "session",
        .service_state_changed  = service_state_changed,
        .ipconfig_changed       = ipconfig_changed,