Modify to add/remove rule list by connection 86/237386/1 accepted/tizen/5.5/unified/20200630.160557 submit/tizen_5.5/20200630.071105
authorhyunuk.tak <hyunuk.tak@samsung.com>
Wed, 10 Jun 2020 06:50:51 +0000 (15:50 +0900)
committerCheoleun Moon <chleun.moon@samsung.com>
Tue, 30 Jun 2020 03:20:53 +0000 (12:20 +0900)
Change-Id: I97dd168f82a457968672e2a7dafa9b83444aaa5d
Signed-off-by: hyunuk.tak <hyunuk.tak@samsung.com>
plugin/monitor/include/stc-plugin-monitor-ipt.h
plugin/monitor/stc-plugin-monitor-app.c
plugin/monitor/stc-plugin-monitor-connection.c
plugin/monitor/stc-plugin-monitor-ipt.c
plugin/monitor/stc-plugin-monitor.c
src/helper/helper-iptables.c
src/helper/helper-iptables.h [changed mode: 0644->0755]
src/helper/helper-nfacct-rule.c
src/helper/helper-nfacct-rule.h

index a104c10..ab7286d 100755 (executable)
@@ -29,6 +29,9 @@ stc_error_e stc_monitor_ip6t_add_out(struct nfacct_rule *counter);
 stc_error_e stc_monitor_ip6t_del_in(struct nfacct_rule *counter);
 stc_error_e stc_monitor_ip6t_del_out(struct nfacct_rule *counter);
 
+stc_error_e stc_monitor_ipt_add_list(GSList *counter_list, nfacct_rule_iptype iptype);
+stc_error_e stc_monitor_ipt_del_list(GSList *counter_list, nfacct_rule_iptype iptype);
+
 stc_error_e stc_monitor_tether_add_in(struct nfacct_rule *counter,
                const gchar *ipaddr);
 stc_error_e stc_monitor_tether_add_out(struct nfacct_rule *counter,
index ca4a88f..a0c0224 100755 (executable)
@@ -556,15 +556,135 @@ void stc_monitor_app_add_monitor(gpointer key,
        }
 }
 
+typedef struct {
+       GSList *counter_v4_list;
+       GSList *counter_v6_list;
+       stc_connection_s *connection;
+       nfacct_rule_action action;
+       nfacct_rule_intend intend;
+} counter_list_data;
+
+static void __make_counter(stc_app_value_s *app_value,
+               nfacct_rule_direction iotype, nfacct_rule_iptype iptype,
+               counter_list_data *list_data)
+{
+       stc_s *stc = stc_get_manager();
+       struct nfacct_rule *counter;
+
+       if (!stc || !list_data->connection || !list_data->connection->ifname)
+               return;
+
+       if (!stc->carg) {
+               stc->carg = MALLOC0(counter_arg_s, 1);
+               if (stc->carg == NULL)
+                       return;
+
+               stc->carg->sock = stc_monitor_get_contr_sock();
+       }
+
+       counter = MALLOC0(struct nfacct_rule, 1);
+       if (counter == NULL)
+               return;
+
+       counter->carg = stc->carg;
+       counter->classid = app_value->classid;
+       counter->app_state = app_value->state;
+       counter->intend = list_data->intend;
+       counter->action = list_data->action;
+       counter->iotype = iotype;
+       counter->iftype = list_data->connection->type;
+       g_strlcpy(counter->ifname, list_data->connection->ifname, MAX_IFACE_LENGTH);
+       switch (counter->intend) {
+       case NFACCT_BLOCK:
+       case NFACCT_TETH_BLOCK:
+               counter->jump = NFACCT_JUMP_REJECT;
+               break;
+       case NFACCT_WARN:
+       case NFACCT_ALLOW:
+       case NFACCT_TETH_ALLOW:
+               counter->jump = NFACCT_JUMP_ACCEPT;
+               break;
+       default:
+               counter->jump = NFACCT_JUMP_UNKNOWN;
+       }
+       counter->send_limit = 0;
+       counter->rcv_limit = 0;
+
+       if (iptype == NFACCT_TYPE_IPV4)
+               list_data->counter_v4_list = g_slist_append(list_data->counter_v4_list, counter);
+       else if (iptype == NFACCT_TYPE_IPV6)
+               list_data->counter_v6_list = g_slist_append(list_data->counter_v6_list, counter);
+}
+
+static void __make_counter_list(stc_app_value_s *app_value, counter_list_data *list_data)
+{
+       switch (app_value->classid) {
+       case STC_TOTAL_IPV4_CLASSID:
+               __make_counter(app_value, NFACCT_COUNTER_IN, NFACCT_TYPE_IPV4, list_data);
+               __make_counter(app_value, NFACCT_COUNTER_OUT, NFACCT_TYPE_IPV4, list_data);
+               break;
+       case STC_TOTAL_IPV6_CLASSID:
+               __make_counter(app_value, NFACCT_COUNTER_IN, NFACCT_TYPE_IPV6, list_data);
+               __make_counter(app_value, NFACCT_COUNTER_OUT, NFACCT_TYPE_IPV6, list_data);
+               break;
+       default:
+               __make_counter(app_value, NFACCT_COUNTER_IN, NFACCT_TYPE_IPV4, list_data);
+               __make_counter(app_value, NFACCT_COUNTER_OUT, NFACCT_TYPE_IPV4, list_data);
+               __make_counter(app_value, NFACCT_COUNTER_IN, NFACCT_TYPE_IPV6, list_data);
+               __make_counter(app_value, NFACCT_COUNTER_OUT, NFACCT_TYPE_IPV6, list_data);
+       }
+}
+
+static void __foreach_app_table(gpointer key, gpointer value, gpointer data)
+{
+       stc_app_value_s *app_value = (stc_app_value_s *)value;
+       counter_list_data *list_data = (counter_list_data *)data;
+
+       if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
+           app_value->classid == STC_TOTAL_WIFI_CLASSID ||
+           app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
+               return;
+
+       list_data->intend = NFACCT_COUNTER;
+       __make_counter_list(app_value, list_data);
+
+       if (app_value->state == STC_APP_STATE_FOREGROUND) {
+               list_data->intend = NFACCT_ALLOW;
+               __make_counter_list(app_value, list_data);
+       }
+}
+
 void stc_monitor_app_add_by_connection(stc_connection_s *conn)
 {
        GHashTable *apps = stc_monitor_get_system_apps();
+       counter_list_data list_data = { 0, };
+       struct timespec start, end;
+       time_t sec;
+       long int nsec;
 
        if (!apps)
                return;
 
-       g_hash_table_foreach(apps, stc_monitor_app_add_monitor, conn);
-       g_hash_table_foreach(apps, stc_monitor_app_add_accept, conn);
+       list_data.connection = conn;
+       list_data.action = NFACCT_ACTION_INSERT;
+
+       g_hash_table_foreach(apps, __foreach_app_table, &list_data);
+
+       clock_gettime(CLOCK_MONOTONIC, &start);
+
+       stc_monitor_ipt_add_list(list_data.counter_v4_list, NFACCT_TYPE_IPV4);
+       stc_monitor_ipt_add_list(list_data.counter_v6_list, NFACCT_TYPE_IPV6);
+
+       g_slist_free_full(list_data.counter_v4_list, g_free);
+       g_slist_free_full(list_data.counter_v6_list, g_free);
+
+       clock_gettime(CLOCK_MONOTONIC, &end);
+
+       sec = end.tv_sec - start.tv_sec;
+       nsec = end.tv_nsec - start.tv_nsec;
+       if (nsec < 0)
+               nsec += 1000000000;
+       STC_LOGD("Added by [%s] connection [%3ld.%09ld]s", conn->ifname, sec, nsec);
 }
 
 void stc_monitor_app_add_accept(gpointer key,
@@ -677,12 +797,34 @@ void stc_monitor_app_remove_monitor(gpointer key,
 void stc_monitor_app_remove_by_connection(stc_connection_s *conn)
 {
        GHashTable *apps = stc_monitor_get_system_apps();
+       counter_list_data list_data = { 0, };
+       struct timespec start, end;
+       time_t sec;
+       long int nsec;
 
        if (!apps)
                return;
 
-       g_hash_table_foreach(apps, stc_monitor_app_remove_monitor, conn);
-       g_hash_table_foreach(apps, stc_monitor_app_remove_accept, conn);
+       list_data.connection = conn;
+       list_data.action = NFACCT_ACTION_DELETE;
+
+       g_hash_table_foreach(apps, __foreach_app_table, &list_data);
+
+       clock_gettime(CLOCK_MONOTONIC, &start);
+
+       stc_monitor_ipt_del_list(list_data.counter_v4_list, NFACCT_TYPE_IPV4);
+       stc_monitor_ipt_del_list(list_data.counter_v6_list, NFACCT_TYPE_IPV6);
+
+       g_slist_free_full(list_data.counter_v4_list, g_free);
+       g_slist_free_full(list_data.counter_v6_list, g_free);
+
+       clock_gettime(CLOCK_MONOTONIC, &end);
+
+       sec = end.tv_sec - start.tv_sec;
+       nsec = end.tv_nsec - start.tv_nsec;
+       if (nsec < 0)
+               nsec += 1000000000;
+       STC_LOGD("Removed by [%s] connection [%3ld.%09ld]s", conn->ifname, sec, nsec);
 }
 
 void stc_monitor_app_remove_accept(gpointer key,
index 02a12ac..1f03737 100755 (executable)
@@ -212,7 +212,7 @@ static void __telephony_update_default_modem_subscriber_id(GDBusConnection *conn
        return;
 }
 
-static void __print_connection_info(stc_connection_s *conn)
+static void __print_connection_info(stc_connection_s *conn, const char *state)
 {
        STC_LOGI("============= connection info ============");
        STC_LOGI("path    [%s]", conn->path);
@@ -221,6 +221,7 @@ static void __print_connection_info(stc_connection_s *conn)
        STC_LOGI("roaming [%u]", conn->roaming ? TRUE : FALSE);
        if (conn->type == STC_IFACE_DATACALL)
                STC_LOGI("sub_id  [%s]", conn->subscriber_id);
+       STC_LOGI("state   [%s]", state);
        STC_LOGI("==================================================");
 }
 
@@ -437,7 +438,7 @@ static stc_error_e __get_connected_profiles(GDBusConnection *connection)
                        }
 
                        __get_connection_info(connection, conn, conn->path);
-                       __print_connection_info(conn);
+                       __print_connection_info(conn, "connected");
 
                        if (default_conn == TRUE) {
                                g_default_connection = conn;
@@ -527,7 +528,7 @@ static void __append_connected_profile(GDBusConnection *connection,
        }
 
        __get_connection_info(connection, conn, conn->path);
-       __print_connection_info(conn);
+       __print_connection_info(conn, "connected");
 
        g_connection_list = g_slist_append(g_connection_list, conn);
 
@@ -540,7 +541,7 @@ static void __append_connected_profile(GDBusConnection *connection,
 static void __remove_disconnected_profile(GDBusConnection *connection,
                                stc_connection_s *conn)
 {
-       __print_connection_info(conn);
+       __print_connection_info(conn, "disconnected");
 
        stc_monitor_remove_by_connection(conn);
 
index c8fa882..f9df3fb 100755 (executable)
@@ -153,6 +153,22 @@ stc_error_e stc_monitor_ip6t_del_out(struct nfacct_rule *counter)
        return produce_net_rule(counter);
 }
 
+stc_error_e stc_monitor_ipt_add_list(GSList *counter_list, nfacct_rule_iptype iptype)
+{
+       if (counter_list == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       return produce_net_list(counter_list, iptype, NFACCT_ACTION_INSERT);
+}
+
+stc_error_e stc_monitor_ipt_del_list(GSList *counter_list, nfacct_rule_iptype iptype)
+{
+       if (counter_list == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       return produce_net_list(counter_list, iptype, NFACCT_ACTION_DELETE);
+}
+
 stc_error_e stc_monitor_tether_add_in(struct nfacct_rule *counter,
                const gchar *ipaddr)
 {
index 1143990..c7a491c 100755 (executable)
@@ -550,9 +550,6 @@ void stc_monitor_update_by_connection(void *data)
        stc_connection_s *connection = (stc_connection_s *)data;
 
        if (connection != NULL && connection->path != NULL) {
-               stc_monitor_app_remove_by_connection(connection);
-               stc_monitor_rstn_remove_by_connection(connection);
-
                iptables_flush_chains();
 
                stc_monitor_app_add_by_connection(connection);
index 519d898..ffffd21 100755 (executable)
 #define STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_RULE     "IptRemoveRule"
 #define STC_IPTABLES_DBUS_METHOD_IP6T_ADD_RULE       "Ip6tAddRule"
 #define STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_RULE    "Ip6tRemoveRule"
+#define STC_IPTABLES_DBUS_METHOD_IPT_ADD_LIST        "IptAddList"
+#define STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_LIST     "IptRemoveList"
+#define STC_IPTABLES_DBUS_METHOD_IP6T_ADD_LIST       "Ip6tAddList"
+#define STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_LIST    "Ip6tRemoveList"
 
 #define RULE_CHAIN      "chain"
 #define RULE_DIRECTION  "direction"
@@ -141,6 +145,43 @@ static void __remove_rule_reply(
        g_free(nfacct_name);
 }
 
+static void __add_list_info_to_builder(GVariantBuilder *builder,
+                               GSList *iptables_list)
+{
+       GSList *list;
+       GVariantBuilder sub_builder;
+
+       for (list = iptables_list; list; list = list->next) {
+               iptables_rule_s *rule = list->data;
+
+               g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
+
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_CHAIN,
+                             g_variant_new_string(rule->chain));
+
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_DIRECTION,
+                                     g_variant_new_uint16(rule->direction));
+
+               if (rule->ifname)
+                       g_variant_builder_add(&sub_builder, "{sv}", RULE_IFNAME,
+                                             g_variant_new_string(rule->ifname));
+
+               if (rule->classid > 0)
+                       g_variant_builder_add(&sub_builder, "{sv}", RULE_CGROUP,
+                                             g_variant_new_uint32(rule->classid));
+
+               if (rule->nfacct_name)
+                       g_variant_builder_add(&sub_builder, "{sv}", RULE_NFACCT,
+                                             g_variant_new_string(rule->nfacct_name));
+
+               if (rule->target)
+                       g_variant_builder_add(&sub_builder, "{sv}", RULE_TARGET,
+                                             g_variant_new_string(rule->target));
+
+               g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
+       }
+}
+
 static int __iptables_rule_add(GDBusConnection *connection,
                               iptables_rule_s *rule)
 {
@@ -269,6 +310,82 @@ static int __ip6tables_rule_remove(GDBusConnection *connection,
        return result;
 }
 
+static int __iptables_list_add(GDBusConnection *connection,
+                               GSList *iptables_list, iptables_ip_type_e iptype)
+{
+       stc_error_e result = STC_ERROR_NONE;
+       GVariantBuilder *builder = NULL;
+       GVariant *params = NULL;
+       GVariant *message = NULL;
+       const char *method = (iptype == IP_TYPE_IPV4) ?
+               STC_IPTABLES_DBUS_METHOD_IPT_ADD_LIST :
+               STC_IPTABLES_DBUS_METHOD_IP6T_ADD_LIST;
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
+       __add_list_info_to_builder(builder, iptables_list);
+       params = g_variant_new("(aa{sv})", builder);
+       g_variant_builder_unref(builder);
+
+       message = stc_manager_gdbus_call_sync(connection,
+                                             STC_IPTABLES_DBUS_SERVICE,
+                                             STC_IPTABLES_DBUS_RULE_PATH,
+                                             STC_IPTABLES_DBUS_RULE_INTERFACE,
+                                             method,
+                                             params);
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
+               return STC_ERROR_FAIL; //LCOV_EXCL_LINE
+       }
+
+       g_variant_get(message, "(i)", &result);
+
+       STC_LOGD("%s to add list [%s:%d]",
+               result == STC_ERROR_NONE ? "Successed" : "Failed",
+               iptype == IP_TYPE_IPV4 ? "IPv4" : "IPv6", result);
+
+       g_variant_unref(message);
+       return result;
+}
+
+static int __iptables_list_remove(GDBusConnection *connection,
+                               GSList *iptables_list, iptables_ip_type_e iptype)
+{
+       int result = 0;
+       GVariantBuilder *builder = NULL;
+       GVariant *params = NULL;
+       GVariant *message = NULL;
+       const char *method = (iptype == IP_TYPE_IPV4) ?
+               STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_LIST :
+               STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_LIST;
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
+       __add_list_info_to_builder(builder, iptables_list);
+       params = g_variant_new("(aa{sv})", builder);
+       g_variant_builder_unref(builder);
+
+       message = stc_manager_gdbus_call_sync(connection,
+                                             STC_IPTABLES_DBUS_SERVICE,
+                                             STC_IPTABLES_DBUS_RULE_PATH,
+                                             STC_IPTABLES_DBUS_RULE_INTERFACE,
+                                             method,
+                                             params);
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
+               return STC_ERROR_FAIL; //LCOV_EXCL_LINE
+       }
+
+       g_variant_get(message, "(i)", &result);
+
+       STC_LOGD("%s to add list [%s:%d]",
+               result == STC_ERROR_NONE ? "Successed" : "Failed",
+               iptype == IP_TYPE_IPV4 ? "IPv4" : "IPv6", result);
+
+       g_variant_unref(message);
+       return STC_ERROR_NONE;
+}
+
 static int __iptables_add_chain(GDBusConnection *connection,
                                const char *chain)
 {
@@ -931,6 +1048,26 @@ done:
        return ret;
 }
 
+stc_error_e iptables_add_list(GSList *iptables_list, iptables_ip_type_e iptype)
+{
+       stc_s *stc = stc_get_manager();
+
+       if (!stc || !stc->connection)
+               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       return __iptables_list_add(stc->connection, iptables_list, iptype);
+}
+
+stc_error_e iptables_remove_list(GSList *iptables_list, iptables_ip_type_e iptype)
+{
+       stc_s *stc = stc_get_manager();
+
+       if (!stc || !stc->connection)
+               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       return __iptables_list_remove(stc->connection, iptables_list, iptype);
+}
+
 API stc_error_e iptables_flush_chains(void)
 {
        stc_error_e ret = STC_ERROR_NONE;
old mode 100644 (file)
new mode 100755 (executable)
index 6fa7908..f9f069a
@@ -76,6 +76,8 @@ typedef struct {
 
 stc_error_e iptables_add(iptables_rule_s *rule, iptables_ip_type_e iptype);
 stc_error_e iptables_remove(iptables_rule_s *rule, iptables_ip_type_e iptype);
+stc_error_e iptables_add_list(GSList *iptables_list, iptables_ip_type_e iptype);
+stc_error_e iptables_remove_list(GSList *iptables_list, iptables_ip_type_e iptype);
 stc_error_e iptables_flush_chains(void);
 stc_error_e iptables_init(void);
 stc_error_e iptables_deinit(void);
index 070052b..ff703d3 100755 (executable)
@@ -850,6 +850,88 @@ API stc_error_e produce_net_rule(nfacct_rule_s *rule)
        return ret;
 }
 
+static stc_error_e append_iptables_cmd(GSList **iptables_list, nfacct_rule_s *rule)
+{
+       iptables_rule_s *iptables_rule = NULL;
+
+       iptables_rule = MALLOC0(iptables_rule_s, 1);
+       if (!iptables_rule)
+               return STC_ERROR_OUT_OF_MEMORY;
+
+       iptables_rule->nfacct_name = g_strdup(rule->name);
+       iptables_rule->ifname = g_strdup(rule->ifname);
+       iptables_rule->target = g_strdup(get_iptables_jump(rule->jump));
+       iptables_rule->chain = g_strdup(get_iptables_chain(rule->classid,
+                               rule->iotype, rule->app_state, rule->intend));
+       if (rule->classid < STC_RESERVED_CLASSID_MAX)
+               iptables_rule->classid = STC_UNKNOWN_CLASSID;
+       else
+               iptables_rule->classid = rule->classid;
+       iptables_rule->direction = (rule->iotype & NFACCT_COUNTER_IN) ?
+                                       IPTABLES_DIRECTION_IN : IPTABLES_DIRECTION_OUT;
+
+       *iptables_list = g_slist_append(*iptables_list, iptables_rule);
+
+       return STC_ERROR_NONE;
+}
+
+static void iptables_list_free(gpointer value)
+{
+       iptables_rule_s *iptables_rule = (iptables_rule_s *)value;
+
+       g_free(iptables_rule->chain);
+       g_free(iptables_rule->nfacct_name);
+       g_free(iptables_rule->ifname);
+       g_free(iptables_rule->target);
+       g_free(iptables_rule);
+}
+
+API stc_error_e produce_net_list(GSList *rule_list,
+               nfacct_rule_iptype iptype, nfacct_rule_action action)
+{
+       GSList *list = NULL;
+       GSList *iptables_list = NULL;
+       stc_error_e ret = STC_ERROR_NONE;
+
+       for (list = rule_list; list; list = list->next) {
+               nfacct_rule_s *rule = list->data;
+
+               if (rule->action == NFACCT_ACTION_APPEND &&
+                       rule->intend == NFACCT_WARN &&
+                       !rule->send_limit && !rule->rcv_limit)
+                       continue;
+
+               generate_counter_name(rule);
+               if (rule->action != NFACCT_ACTION_DELETE) {
+                       ret = nfacct_send_del(rule);
+                       if (ret != STC_ERROR_NONE)
+                               continue;
+
+                       ret = nfacct_send_new(rule);
+                       if (ret != STC_ERROR_NONE)
+                               continue;
+               }
+
+               append_iptables_cmd(&iptables_list, rule);
+       }
+
+       if (action == NFACCT_ACTION_INSERT ||
+               action == NFACCT_ACTION_APPEND)
+               ret = iptables_add_list(iptables_list, iptype);
+       else if (action == NFACCT_ACTION_DELETE)
+               ret = iptables_remove_list(iptables_list, iptype);
+
+       for (list = rule_list; list; list = list->next) {
+               nfacct_rule_s *rule = list->data;
+
+               if (rule->action == NFACCT_ACTION_DELETE)
+                       nfacct_send_del(rule);
+       }
+
+       g_slist_free_full(iptables_list, iptables_list_free);
+       return ret;
+}
+
 void generate_counter_name(nfacct_rule_s *counter)
 {
        char warn_symbol = 'c';
index 97c9b5e..e8923b8 100755 (executable)
@@ -134,6 +134,8 @@ bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *counter);
 
 stc_error_e nfacct_send_get_all(struct counter_arg *carg);
 stc_error_e produce_net_rule(nfacct_rule_s *rule);
+stc_error_e produce_net_list(GSList *rule_list,
+               nfacct_rule_iptype iptype, nfacct_rule_action action);
 
 netlink_serialization_command *
 netlink_create_command(struct netlink_serialization_params *params);