Merge "[Add] tethering client monitoring" into tizen
[platform/core/connectivity/stc-manager.git] / src / monitor / stc-monitor.c
index 694bf5c..7f28d9c 100755 (executable)
@@ -105,6 +105,102 @@ static nfacct_rule_jump __get_jump_by_intend(struct nfacct_rule *counter)
        return NFACCT_JUMP_UNKNOWN;
 }
 
+static stc_error_e __add_iptables_tether_in(struct nfacct_rule *counter,
+               const gchar *ipaddr)
+{
+       int ret;
+
+       if (counter == NULL || ipaddr == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       counter->action = NFACCT_ACTION_INSERT;
+       counter->iotype = NFACCT_COUNTER_IN;
+       counter->jump = __get_jump_by_intend(counter);
+       counter->iptype = NFACCT_TYPE_IPV4;
+       counter->send_limit = 0;
+       counter->rcv_limit = 0;
+       counter->src_iprange_type = NFACCT_IPRANGE_TYPE_SINGLE;
+       counter->src_ip1 = g_strdup(ipaddr);
+
+       ret = produce_net_rule(counter);
+
+       g_free(counter->src_ip1);
+       counter->src_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
+       return ret;
+}
+
+static stc_error_e __add_iptables_tether_out(struct nfacct_rule *counter,
+               const gchar *ipaddr)
+{
+       int ret;
+
+       if (counter == NULL || ipaddr == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       counter->action = NFACCT_ACTION_INSERT;
+       counter->iotype = NFACCT_COUNTER_OUT;
+       counter->jump = __get_jump_by_intend(counter);
+       counter->iptype = NFACCT_TYPE_IPV4;
+       counter->send_limit = 0;
+       counter->rcv_limit = 0;
+       counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_SINGLE;
+       counter->dst_ip1 = g_strdup(ipaddr);
+
+       ret = produce_net_rule(counter);
+
+       g_free(counter->dst_ip1);
+       counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
+       return ret;
+}
+
+static stc_error_e __del_iptables_tether_in(struct nfacct_rule *counter,
+               const gchar *ipaddr)
+{
+       int ret;
+
+       if (counter == NULL || ipaddr == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       counter->action = NFACCT_ACTION_DELETE;
+       counter->iotype = NFACCT_COUNTER_IN;
+       counter->jump = __get_jump_by_intend(counter);
+       counter->iptype = NFACCT_TYPE_IPV4;
+       counter->send_limit = 0;
+       counter->rcv_limit = 0;
+       counter->src_iprange_type = NFACCT_IPRANGE_TYPE_SINGLE;
+       counter->src_ip1 = g_strdup(ipaddr);
+
+       ret = produce_net_rule(counter);
+
+       g_free(counter->src_ip1);
+       counter->src_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
+       return ret;
+}
+
+static stc_error_e __del_iptables_tether_out(struct nfacct_rule *counter,
+               const gchar *ipaddr)
+{
+       int ret;
+
+       if (counter == NULL || ipaddr == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       counter->action = NFACCT_ACTION_DELETE;
+       counter->iotype = NFACCT_COUNTER_OUT;
+       counter->jump = __get_jump_by_intend(counter);
+       counter->iptype = NFACCT_TYPE_IPV4;
+       counter->send_limit = 0;
+       counter->rcv_limit = 0;
+       counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_SINGLE;
+       counter->dst_ip1 = g_strdup(ipaddr);
+
+       ret = produce_net_rule(counter);
+
+       g_free(counter->dst_ip1);
+       counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
+       return ret;
+}
+
 static stc_error_e __add_iptables_in(struct nfacct_rule *counter)
 {
        if (counter == NULL)
@@ -419,10 +515,93 @@ static gboolean __processes_tree_check_empty(gpointer key, gpointer value,
 }
 //LCOV_EXCL_STOP
 
+static gboolean __add_application_monitor_for_tethering(gpointer key, gpointer value,
+                                   gpointer data)
+{
+       stc_app_value_s *app_value = (stc_app_value_s *)value;
+       stc_app_key_s *app_key = (stc_app_key_s *)key;
+       default_connection_s *connection = (default_connection_s *)data;
+       stc_s *stc = stc_get_manager();
+       struct nfacct_rule counter;
+
+       STC_LOGI("add tether app (%s)", app_key->app_id);
+
+       if (stc == NULL || connection == NULL)
+               return FALSE;
+
+       if (!stc->carg) {
+               stc->carg = MALLOC0(counter_arg_s, 1);
+               if (stc->carg == NULL)
+                       return FALSE;
+
+               stc->carg->sock = stc_monitor_get_counter_socket();
+       }
+
+       memset(&counter, 0, sizeof(struct nfacct_rule));
+
+       counter.carg = stc->carg;
+       counter.classid = app_value->classid;
+       counter.intend = NFACCT_TETH_COUNTER;
+
+       if (connection->tether_state != TRUE ||
+                       connection->tether_iface.ifname == NULL)
+               return FALSE;
+
+       counter.iftype = connection->tether_iface.type;
+       g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
+
+       __add_iptables_tether_in(&counter, app_value->ipaddr);
+       __add_iptables_tether_out(&counter, app_value->ipaddr);
+
+       return FALSE;
+}
+
+static gboolean __remove_application_monitor_for_tethering(gpointer key, gpointer value,
+                                   gpointer data)
+{
+       stc_app_value_s *app_value = (stc_app_value_s *)value;
+       stc_app_key_s *app_key = (stc_app_key_s *)key;
+       default_connection_s *connection = (default_connection_s *)data;
+       stc_s *stc = stc_get_manager();
+       struct nfacct_rule counter;
+
+       STC_LOGI("remove tether app (%s)", app_key->app_id);
+
+       if (stc == NULL || connection == NULL)
+               return FALSE;
+
+       if (!stc->carg) {
+               stc->carg = MALLOC0(counter_arg_s, 1);
+               if (stc->carg == NULL)
+                       return FALSE;
+
+               stc->carg->sock = stc_monitor_get_counter_socket();
+       }
+
+       memset(&counter, 0, sizeof(struct nfacct_rule));
+
+       counter.carg = stc->carg;
+       counter.classid = app_value->classid;
+       counter.intend = NFACCT_TETH_COUNTER;
+
+       if (connection->tether_state != TRUE ||
+                       connection->tether_iface.ifname == NULL)
+               return FALSE;
+
+       counter.iftype = connection->tether_iface.type;
+       g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
+
+       __del_iptables_tether_in(&counter, app_value->ipaddr);
+       __del_iptables_tether_out(&counter, app_value->ipaddr);
+
+       return FALSE;
+}
+
 static gboolean __add_application_monitor(gpointer key, gpointer value,
                                          gpointer data)
 {
        stc_app_value_s *app_value = (stc_app_value_s *)value;
+       stc_app_key_s *app_key = (stc_app_key_s *)key;
        default_connection_s *connection = (default_connection_s *)data;
        stc_s *stc = stc_get_manager();
 
@@ -458,7 +637,10 @@ static gboolean __add_application_monitor(gpointer key, gpointer value,
                        g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
                }
 
-               if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
+               if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX) &&
+                               app_value->classid != STC_TETHERING_APP_CLASSID) {
+                       __add_application_monitor_for_tethering(key, value, data);
+               } else if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
                        __add_iptables_in(&counter);
                        __add_iptables_out(&counter);
                } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
@@ -479,6 +661,7 @@ static gboolean __remove_application_monitor(gpointer key, gpointer value,
                                             gpointer data)
 {
        stc_app_value_s *app_value = (stc_app_value_s *)value;
+       stc_app_key_s *app_key = (stc_app_key_s *)key;
        default_connection_s *connection = (default_connection_s *)data;
        stc_s *stc = stc_get_manager();
 
@@ -499,7 +682,11 @@ static gboolean __remove_application_monitor(gpointer key, gpointer value,
                counter.classid = app_value->classid;
                counter.intend = NFACCT_COUNTER;
 
-               if (connection->tether_state == FALSE &&
+               if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX) &&
+                               app_value->classid != STC_TETHERING_APP_CLASSID) {
+                       __remove_application_monitor_for_tethering(key, value, data);
+                       return FALSE;
+               } else if (connection->tether_state == FALSE &&
                        connection->tether_iface.ifname != NULL &&
                        app_value->classid == STC_TETHERING_APP_CLASSID) {
                        counter.iftype = connection->tether_iface.type;
@@ -1104,7 +1291,8 @@ static gboolean __rstn_counter_update_foreach_classid(gpointer key,
        classid_bytes_context_s *context = (classid_bytes_context_s *)data;
        uint32_t classid;
 
-       if (context->counter->intend != NFACCT_COUNTER)
+       if (context->counter->intend != NFACCT_COUNTER &&
+                       context->counter->intend != NFACCT_TETH_COUNTER)
                goto try_next_callback;
 
        if (rstn_value->limit_exceeded == TRUE) {
@@ -1158,6 +1346,8 @@ static gboolean __update_app_statistics(gpointer key, gpointer value,
        if (app_value->classid == STC_TETHERING_APP_CLASSID &&
                default_connection->tether_state == TRUE)
                stat_key.iftype = default_connection->tether_iface.type;
+       else if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX))
+               stat_key.iftype = default_connection->tether_iface.type;
        else
                stat_key.iftype = default_connection->type;
 
@@ -1170,6 +1360,9 @@ static gboolean __update_app_statistics(gpointer key, gpointer value,
                default_connection->tether_state == TRUE)
                g_strlcpy(stat_key.ifname, default_connection->tether_iface.ifname,
                          MAX_IFACE_LENGTH);
+       else if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX))
+               g_strlcpy(stat_key.ifname, default_connection->tether_iface.ifname,
+                         MAX_IFACE_LENGTH);
        else
                g_strlcpy(stat_key.ifname, default_connection->ifname,
                          MAX_IFACE_LENGTH);
@@ -1321,7 +1514,8 @@ static gboolean __apps_counter_update_foreach_classid(gpointer key,
        stc_app_value_s *app_value = (stc_app_value_s *)value;
        classid_bytes_context_s *context = (classid_bytes_context_s *)data;
 
-       if (context->counter->intend != NFACCT_COUNTER)
+       if (context->counter->intend != NFACCT_COUNTER &&
+                       context->counter->intend != NFACCT_TETH_COUNTER)
                goto try_next_callback;
 
        __interface_counter_update(app_key, app_value, context);
@@ -2099,6 +2293,7 @@ API stc_error_e stc_monitor_application_add(const stc_app_key_s app_key,
        value->type = app_value.type;
        value->data_usage.in_bytes = app_value.data_usage.in_bytes;
        value->data_usage.out_bytes = app_value.data_usage.out_bytes;
+       g_strlcpy(value->ipaddr, app_value.ipaddr, IPV4_IPADDRESS_LEN);
 
        value->processes = g_tree_new_full(__processes_tree_key_compare, NULL,
                                           __processes_tree_key_free,
@@ -2116,6 +2311,36 @@ API stc_error_e stc_monitor_application_add(const stc_app_key_s app_key,
        return ret;
 }
 
+API stc_error_e stc_monitor_application_remove(const stc_app_key_s app_key)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+       stc_app_value_s *app_lookup;
+
+       ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
+
+       app_lookup = __application_lookup(g_system->apps, &app_key);
+       if (!app_lookup) {
+               if (STC_DEBUG_LOG)
+                       STC_LOGD("app_key not found"); //LCOV_EXCL_LINE
+               return STC_ERROR_FAIL; //LCOV_EXCL_LINE
+       }
+
+       /* remove nfacct rule for this classid */
+       __remove_application_monitor((gpointer) &app_key, app_lookup,
+                                    stc_get_default_connection());
+
+       /* remove ristrictions if any */
+       __remove_rstns_for_application(app_key.app_id);
+
+       /* remove app_key from the stc-manager */
+       if (!g_tree_remove(g_system->apps, &app_key)) {
+               ret = STC_ERROR_NO_DATA;
+               STC_LOGE("key not found");
+       }
+
+       return ret;
+}
+
 API stc_error_e stc_monitor_process_add(const stc_app_key_s app_key,
                                    const stc_process_key_s proc_key,
                                    const stc_process_value_s proc_value)