From 318757d777bb08f64a1a45ff5729c8a4bb3ffe0c Mon Sep 17 00:00:00 2001 From: "hyunuk.tak" Date: Wed, 10 Jun 2020 15:50:51 +0900 Subject: [PATCH] Modify to add/remove rule list by connection Change-Id: I97dd168f82a457968672e2a7dafa9b83444aaa5d Signed-off-by: hyunuk.tak --- plugin/monitor/include/stc-plugin-monitor-ipt.h | 3 + plugin/monitor/stc-plugin-monitor-app.c | 150 +++++++++++++++++++++++- plugin/monitor/stc-plugin-monitor-connection.c | 9 +- plugin/monitor/stc-plugin-monitor-ipt.c | 16 +++ plugin/monitor/stc-plugin-monitor.c | 3 - src/helper/helper-iptables.c | 137 ++++++++++++++++++++++ src/helper/helper-iptables.h | 2 + src/helper/helper-nfacct-rule.c | 82 +++++++++++++ src/helper/helper-nfacct-rule.h | 2 + 9 files changed, 393 insertions(+), 11 deletions(-) mode change 100644 => 100755 src/helper/helper-iptables.h diff --git a/plugin/monitor/include/stc-plugin-monitor-ipt.h b/plugin/monitor/include/stc-plugin-monitor-ipt.h index a104c10..ab7286d 100755 --- a/plugin/monitor/include/stc-plugin-monitor-ipt.h +++ b/plugin/monitor/include/stc-plugin-monitor-ipt.h @@ -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, diff --git a/plugin/monitor/stc-plugin-monitor-app.c b/plugin/monitor/stc-plugin-monitor-app.c index ca4a88f..a0c0224 100755 --- a/plugin/monitor/stc-plugin-monitor-app.c +++ b/plugin/monitor/stc-plugin-monitor-app.c @@ -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, diff --git a/plugin/monitor/stc-plugin-monitor-connection.c b/plugin/monitor/stc-plugin-monitor-connection.c index 02a12ac..1f03737 100755 --- a/plugin/monitor/stc-plugin-monitor-connection.c +++ b/plugin/monitor/stc-plugin-monitor-connection.c @@ -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); diff --git a/plugin/monitor/stc-plugin-monitor-ipt.c b/plugin/monitor/stc-plugin-monitor-ipt.c index c8fa882..f9df3fb 100755 --- a/plugin/monitor/stc-plugin-monitor-ipt.c +++ b/plugin/monitor/stc-plugin-monitor-ipt.c @@ -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) { diff --git a/plugin/monitor/stc-plugin-monitor.c b/plugin/monitor/stc-plugin-monitor.c index 1143990..c7a491c 100755 --- a/plugin/monitor/stc-plugin-monitor.c +++ b/plugin/monitor/stc-plugin-monitor.c @@ -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); diff --git a/src/helper/helper-iptables.c b/src/helper/helper-iptables.c index 519d898..ffffd21 100755 --- a/src/helper/helper-iptables.c +++ b/src/helper/helper-iptables.c @@ -32,6 +32,10 @@ #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; diff --git a/src/helper/helper-iptables.h b/src/helper/helper-iptables.h old mode 100644 new mode 100755 index 6fa7908..f9f069a --- a/src/helper/helper-iptables.h +++ b/src/helper/helper-iptables.h @@ -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); diff --git a/src/helper/helper-nfacct-rule.c b/src/helper/helper-nfacct-rule.c index 070052b..ff703d3 100755 --- a/src/helper/helper-nfacct-rule.c +++ b/src/helper/helper-nfacct-rule.c @@ -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'; diff --git a/src/helper/helper-nfacct-rule.h b/src/helper/helper-nfacct-rule.h index 97c9b5e..e8923b8 100755 --- a/src/helper/helper-nfacct-rule.h +++ b/src/helper/helper-nfacct-rule.h @@ -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); -- 2.7.4