From: Milind Murhekar Date: Mon, 20 Aug 2018 11:45:05 +0000 (+0530) Subject: [Add] tethering client monitoring X-Git-Tag: accepted/tizen/unified/20180829.143000~1^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fconnectivity%2Fstc-manager.git;a=commitdiff_plain;h=754bc0adb95b0efb54f2c7dd8e3105ff41ccc14d [Add] tethering client monitoring This change adds the feature to monitor the data usage of connected tethering clients and saves the stats to the table counters. Change-Id: I50df631b27ad9fe483f6790877e92308b8ea760a Signed-off-by: Milind Murhekar --- diff --git a/include/stc-manager.h b/include/stc-manager.h index 898e7ae..94c57a1 100644 --- a/include/stc-manager.h +++ b/include/stc-manager.h @@ -24,6 +24,7 @@ #define NET_CLS_SUBSYS "net_cls" #define STC_BACKGROUND_APP_SUFFIX "_BACKGROUND" +#define STC_TETHERING_APP_SUFFIX "_TETHERING" #define STC_BACKGROUND_APP_ID "BACKGROUND" #define STC_TOTAL_DATACALL "TOTAL_DATACALL" #define STC_TOTAL_WIFI "TOTAL_WIFI" @@ -118,6 +119,7 @@ typedef enum { STC_APP_TYPE_GROUP, STC_APP_TYPE_WATCH, STC_APP_TYPE_WIDGET, + STC_APP_TYPE_TETHERING, STC_APP_TYPE_MAX, } stc_app_type_e; diff --git a/packaging/stc-manager.spec b/packaging/stc-manager.spec index 6b0b965..81d341a 100644 --- a/packaging/stc-manager.spec +++ b/packaging/stc-manager.spec @@ -1,6 +1,6 @@ Name: stc-manager Summary: STC(Smart Traffic Control) manager -Version: 0.0.74 +Version: 0.0.75 Release: 0 Group: Network & Connectivity/Other License: Apache-2.0 diff --git a/plugin/tether/stc-plugin-tether.c b/plugin/tether/stc-plugin-tether.c index ed3ccd4..629abbf 100644 --- a/plugin/tether/stc-plugin-tether.c +++ b/plugin/tether/stc-plugin-tether.c @@ -31,6 +31,51 @@ static GDBusConnection *connection = NULL; static GCancellable *cancellable = NULL; static int g_mobileap_signal_sub_id = 0; +static stc_error_e add_station_monitor(gchar *pkg_id, gchar *app_id, const char *ip) +{ + int ret; + stc_app_key_s app_key; + stc_app_value_s app_value; + + if (pkg_id == NULL || app_id == NULL || ip == NULL) { + STC_LOGE("invalid station station info"); + return STC_ERROR_INVALID_PARAMETER; + } + + memset(&app_key, 0, sizeof(stc_app_key_s)); + memset(&app_value, 0, sizeof(stc_app_value_s)); + app_key.pkg_id = g_strdup(pkg_id); + app_key.app_id = g_strconcat(app_id, STC_TETHERING_APP_SUFFIX, NULL); + app_value.type = STC_APP_TYPE_TETHERING; + app_value.processes = NULL; + g_strlcpy(app_value.ipaddr, ip, IPV4_IPADDRESS_LEN); + + ret = stc_monitor_application_add(app_key, app_value); + FREE(app_key.pkg_id); + FREE(app_key.app_id); + return ret; +} + +static stc_error_e remove_station_monitor(gchar *pkg_id, gchar *app_id) +{ + int ret; + stc_app_key_s app_key; + + if (pkg_id == NULL || app_id == NULL) { + STC_LOGE("invalid station station info"); + return STC_ERROR_INVALID_PARAMETER; + } + + memset(&app_key, 0, sizeof(stc_app_key_s)); + app_key.pkg_id = g_strdup(pkg_id); + app_key.app_id = g_strconcat(app_id, STC_TETHERING_APP_SUFFIX, NULL); + + ret = stc_monitor_application_remove(app_key); + FREE(app_key.pkg_id); + FREE(app_key.app_id); + return ret; +} + static int _compare_sta_by_mac_func(gconstpointer a, gconstpointer b) { @@ -75,6 +120,10 @@ static void _remove_station_info(gconstpointer data, GCompareFunc func) info = (tether_sta_info_s *)list->data; STC_LOGI("STA-REMOVED: (%s) (%s) (%s)", info->ip, info->mac, info->name); + + /* remove tethering client from monitoring */ + remove_station_monitor(info->mac, info->station_id); + g_free(info->station_id); g_free(info); @@ -99,7 +148,10 @@ static void _add_station_info(tether_sta_info_s *info) station_list = g_slist_prepend(station_list, info); STC_LOGI("STA-ADDED: (%s) (%s) (%s)", info->ip, info->mac, info->name); + + /* add tethering client for monitoring data usage */ info->station_id = g_strdup_printf("%s_%s", info->mac, info->name); + add_station_monitor(info->mac, info->station_id, info->ip); } static void _mobileap_signal_cb(GDBusConnection *conn, @@ -189,7 +241,6 @@ void tether_plugin_deinit(void) STC_LOGI("tether plugin deinitialised"); } -/* Tether Plugin APIs */ API stc_plugin_tether_s tether_plugin = { .init = tether_plugin_init, .deinit = tether_plugin_deinit, diff --git a/src/helper/helper-cgroup.c b/src/helper/helper-cgroup.c index 1f195ba..fa54c12 100644 --- a/src/helper/helper-cgroup.c +++ b/src/helper/helper-cgroup.c @@ -237,4 +237,8 @@ void cgroup_init(void) /* create foreground cgroup directory */ cgroup_make_subdir(STC_CGROUP_NETWORK, STC_FOREGROUND_CGROUP_NAME, NULL); + + /* create tethering cgroup directory */ + cgroup_make_subdir(STC_CGROUP_NETWORK, STC_TETHERING_CGROUP_NAME, + NULL); } diff --git a/src/helper/helper-cgroup.h b/src/helper/helper-cgroup.h index 725cad4..73abd40 100644 --- a/src/helper/helper-cgroup.h +++ b/src/helper/helper-cgroup.h @@ -33,10 +33,12 @@ #define STC_CGROUP_NETWORK CGROUP_NETWORK "/stc" #define BACKGROUND_CGROUP_NETWORK STC_CGROUP_NETWORK "/BACKGROUND" #define FOREGROUND_CGROUP_NETWORK STC_CGROUP_NETWORK "/FOREGROUND" +#define TETHERING_CGROUP_NETWORK STC_CGROUP_NETWORK "/TETHERING" #define PROC_TASK_CHILDREN "/proc/%d/task/%d/children" #define STC_CGROUP_NAME "stc" #define STC_BACKGROUND_CGROUP_NAME "BACKGROUND" #define STC_FOREGROUND_CGROUP_NAME "FOREGROUND" +#define STC_TETHERING_CGROUP_NAME "TETHERING" /** * @desc Get one unsigned int32 value from cgroup diff --git a/src/helper/helper-iptables.c b/src/helper/helper-iptables.c index 6ca96af..0914100 100644 --- a/src/helper/helper-iptables.c +++ b/src/helper/helper-iptables.c @@ -39,6 +39,13 @@ #define RULE_CGROUP "cgroup" #define RULE_NFACCT "nfacct" #define RULE_TARGET "target" +#define RULE_PROTOCOL "protocol" +#define RULE_SIPTYPE "s_ip_type" +#define RULE_SIP1 "s_ip1" +#define RULE_SIP2 "s_ip2" +#define RULE_DIPTYPE "d_ip_type" +#define RULE_DIP1 "d_ip1" +#define RULE_DIP2 "d_ip2" static void __add_rule_info_to_builder(GVariantBuilder *builder, iptables_rule_s *rule) @@ -68,6 +75,27 @@ static void __add_rule_info_to_builder(GVariantBuilder *builder, g_variant_builder_add(builder, "{sv}", RULE_TARGET, g_variant_new_string(rule->target)); + g_variant_builder_add(builder, "{sv}", RULE_SIPTYPE, + g_variant_new_uint16(rule->s_iprange_type)); + + g_variant_builder_add(builder, "{sv}", RULE_DIPTYPE, + g_variant_new_uint16(rule->d_iprange_type)); + + if (rule->s_ip1.s_addr) + g_variant_builder_add(builder, "{sv}", RULE_SIP1, + g_variant_new_uint32(rule->s_ip1.s_addr)); + + if (rule->s_ip2.s_addr) + g_variant_builder_add(builder, "{sv}", RULE_SIP2, + g_variant_new_uint32(rule->s_ip2.s_addr)); + + if (rule->d_ip1.s_addr) + g_variant_builder_add(builder, "{sv}", RULE_DIP1, + g_variant_new_uint32(rule->d_ip1.s_addr)); + + if (rule->d_ip2.s_addr) + g_variant_builder_add(builder, "{sv}", RULE_DIP2, + g_variant_new_uint32(rule->d_ip2.s_addr)); } static int __iptables_rule_add(GDBusConnection *connection, @@ -436,6 +464,10 @@ stc_error_e iptables_flush_chains(void) if (ret != STC_ERROR_NONE) goto done; //LCOV_EXCL_LINE + ret = __iptables_flush_chain(stc->connection, STC_TETHER_CHAIN); + if (ret != STC_ERROR_NONE) + goto done; //LCOV_EXCL_LINE + ret = __ip6tables_flush_chain(stc->connection, STC_IN_CHAIN); if (ret != STC_ERROR_NONE) goto done; //LCOV_EXCL_LINE @@ -479,6 +511,12 @@ stc_error_e iptables_init(void) goto done; //LCOV_EXCL_LINE } + ret = __iptables_add_chain(stc->connection, STC_TETHER_CHAIN); + if (ret != STC_ERROR_NONE) { + __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE + goto done; //LCOV_EXCL_LINE + } + ret = __ip6tables_add_chain(stc->connection, STC_IN_CHAIN); if (ret != STC_ERROR_NONE) { __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE @@ -510,6 +548,16 @@ stc_error_e iptables_init(void) } ret = __iptables_add_chain_jump_rule("FORWARD", STC_FRWD_CHAIN); + if (ret != STC_ERROR_NONE) { + __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE + goto done; //LCOV_EXCL_LINE + } + + ret = __iptables_add_chain_jump_rule("FORWARD", STC_TETHER_CHAIN); + if (ret != STC_ERROR_NONE) { + __STC_LOG_FUNC_EXIT__; + goto done; + } done: return ret; } @@ -538,6 +586,12 @@ stc_error_e iptables_deinit(void) goto done; //LCOV_EXCL_LINE } + ret = __iptables_remove_chain(stc->connection, STC_TETHER_CHAIN); + if (ret != STC_ERROR_NONE) { + __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE + goto done; //LCOV_EXCL_LINE + } + ret = __iptables_remove_chain(stc->connection, STC_FRWD_CHAIN); if (ret != STC_ERROR_NONE) { __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE diff --git a/src/helper/helper-iptables.h b/src/helper/helper-iptables.h index 13db25b..71b057b 100644 --- a/src/helper/helper-iptables.h +++ b/src/helper/helper-iptables.h @@ -17,12 +17,14 @@ #ifndef __STC_HELPER_IPTABLES_H__ #define __STC_HELPER_IPTABLES_H__ +#include #include "stc-manager.h" #include "stc-error.h" #define STC_IN_CHAIN "STC_IN" #define STC_OUT_CHAIN "STC_OUT" #define STC_FRWD_CHAIN "STC_FRWD" +#define STC_TETHER_CHAIN "STC_TETHER" typedef enum { IPTABLES_DIRECTION_NONE, @@ -38,11 +40,24 @@ typedef enum { IP_TYPE_LAST_ELEM } iptables_ip_type_e; +typedef enum { + IPTABLES_IP_NONE, + IPTABLES_IP_SINGLE, + IPTABLES_IP_MASK, + IPTABLES_IP_RANGE +} iptables_iprange_type_e; + typedef struct { char *chain; char *ifname; char *nfacct_name; char *target; + iptables_iprange_type_e s_iprange_type; + iptables_iprange_type_e d_iprange_type; + struct in_addr s_ip1; + struct in_addr s_ip2; + struct in_addr d_ip1; + struct in_addr d_ip2; iptables_rule_direction_e direction; uint32_t classid; } iptables_rule_s; diff --git a/src/helper/helper-net-cls.c b/src/helper/helper-net-cls.c index 748f95f..238b7de 100644 --- a/src/helper/helper-net-cls.c +++ b/src/helper/helper-net-cls.c @@ -137,6 +137,8 @@ uint32_t get_classid_by_app_id(const char *app_id, int create) if (strstr(app_id, STC_BACKGROUND_APP_SUFFIX)) path_to_net_cgroup_dir = BACKGROUND_CGROUP_NETWORK; + else if (strstr(app_id, STC_TETHERING_APP_SUFFIX)) + path_to_net_cgroup_dir = TETHERING_CGROUP_NETWORK; else path_to_net_cgroup_dir = FOREGROUND_CGROUP_NETWORK; @@ -186,6 +188,8 @@ stc_error_e place_pids_to_net_cgroup(const int pid, const char *app_id) path_to_net_cgroup_dir = STC_CGROUP_NETWORK; else if (strstr(app_id, STC_BACKGROUND_APP_SUFFIX)) path_to_net_cgroup_dir = BACKGROUND_CGROUP_NETWORK; + else if (strstr(app_id, STC_TETHERING_APP_SUFFIX)) + path_to_net_cgroup_dir = TETHERING_CGROUP_NETWORK; else path_to_net_cgroup_dir = FOREGROUND_CGROUP_NETWORK; //LCOV_EXCL_LINE diff --git a/src/helper/helper-nfacct-rule.c b/src/helper/helper-nfacct-rule.c index 90364d3..70b29a5 100644 --- a/src/helper/helper-nfacct-rule.c +++ b/src/helper/helper-nfacct-rule.c @@ -448,12 +448,32 @@ static stc_error_e exec_iptables_cmd(nfacct_rule_s *rule) 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->iotype)); + + /* In case of tehering use chain 'STC_TETHER' */ + if (rule->intend == NFACCT_TETH_COUNTER) + iptables_rule.chain = g_strdup(STC_TETHER_CHAIN); + else + iptables_rule.chain = g_strdup(get_iptables_chain(rule->iotype)); + iptables_rule.classid = rule->classid; iptables_rule.direction = (rule->iotype & NFACCT_COUNTER_IN) ? IPTABLES_DIRECTION_IN : IPTABLES_DIRECTION_OUT; iptype = (iptables_ip_type_e)rule->iptype; + /* specify the ip range type for source and destination */ + iptables_rule.s_iprange_type = rule->src_iprange_type; + iptables_rule.d_iprange_type = rule->dst_iprange_type; + + /* specify source and destination ip address if any */ + if (rule->src_ip1) + inet_aton(rule->src_ip1, &iptables_rule.s_ip1); + if (rule->src_ip2) + inet_aton(rule->src_ip2, &iptables_rule.s_ip2); + if (rule->dst_ip1) + inet_aton(rule->dst_ip1, &iptables_rule.d_ip1); + if (rule->dst_ip2) + inet_aton(rule->dst_ip2, &iptables_rule.d_ip2); + if (rule->action == NFACCT_ACTION_DELETE) { /* delete interface rule */ ret = iptables_remove(&iptables_rule, iptype); @@ -480,6 +500,7 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule) char nfacct_buf[sizeof(NFACCT_NAME_MOD) + 3*MAX_DEC_SIZE(int) + 4 + 1]; stc_error_e ret = STC_ERROR_NONE; + uint32_t classid = rule->classid; /* income part */ if (rule->iotype & NFACCT_COUNTER_IN) { @@ -508,7 +529,19 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule) ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0, STC_ERROR_FAIL, "Not enought buffer"); + /* cgroup extention on FORWARD chain are not allowed + * remove classid info in case of tethering rules */ + if (rule->intend == NFACCT_TETH_COUNTER) { + classid = rule->classid; + rule->classid = 0; + } + ret = exec_iptables_cmd(rule); + + /* restore the classid info in case of tethering rule */ + if (rule->intend == NFACCT_TETH_COUNTER) + rule->classid = classid; + ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL, "Can't set conditional block for ingress" " traffic, for classid %u, cmd %s, j %s", @@ -551,7 +584,19 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule) ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0, STC_ERROR_FAIL, "Not enought buffer"); + /* cgroup extention on FORWARD chain are not allowed + * remove classid info in case of tethering rules */ + if (rule->intend == NFACCT_TETH_COUNTER) { + classid = rule->classid; + rule->classid = 0; + } + ret = exec_iptables_cmd(rule); + + /* restore the classid info in case of tethering rule */ + if (rule->intend == NFACCT_TETH_COUNTER) + rule->classid = classid; + ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL, "Can't set conditional block for engress" " traffic, for classid %u, cmd %s, j %s", diff --git a/src/helper/helper-nfacct-rule.h b/src/helper/helper-nfacct-rule.h index 9d80afb..52ef8f4 100644 --- a/src/helper/helper-nfacct-rule.h +++ b/src/helper/helper-nfacct-rule.h @@ -67,6 +67,13 @@ typedef enum { NFACCT_TYPE_LAST_ELEM } nfacct_rule_iptype; +typedef enum { + NFACCT_IPRANGE_TYPE_NONE, + NFACCT_IPRANGE_TYPE_SINGLE, + NFACCT_IPRANGE_TYPE_MASK, + NFACCT_IPRANGE_TYPE_RANGE, +} nfacct_rule_iprange_type; + enum nfnl_acct_flags { NFACCT_F_QUOTA_PKTS = (1 << 0), NFACCT_F_QUOTA_BYTES = (1 << 1), @@ -97,6 +104,12 @@ struct nfacct_rule { nfacct_rule_jump jump; /* in most cases jump is evalutation based on intend, but not always */ stc_rstn_state_e rstn_state; nfacct_rule_iptype iptype; + nfacct_rule_iprange_type src_iprange_type; + nfacct_rule_iprange_type dst_iprange_type; + char *src_ip1; + char *src_ip2; + char *dst_ip1; + char *dst_ip2; struct counter_arg *carg; stc_error_e(*iptables_rule)(struct nfacct_rule *counter); diff --git a/src/monitor/include/stc-monitor.h b/src/monitor/include/stc-monitor.h index 3414c06..4b5375c 100644 --- a/src/monitor/include/stc-monitor.h +++ b/src/monitor/include/stc-monitor.h @@ -27,6 +27,7 @@ /* 1 seconds */ #define CONTR_TIMER_INTERVAL 1 +#define IPV4_IPADDRESS_LEN 16 /** * @brief enumeration for data limit types @@ -72,6 +73,7 @@ typedef struct { stc_data_counter_s data_usage; stc_data_counter_s counter; GTree *processes; /**< applications instances */ + char ipaddr[IPV4_IPADDRESS_LEN+1]; /**< application ip address */ } stc_app_value_s; /** @@ -139,6 +141,11 @@ stc_error_e stc_monitor_application_add(const stc_app_key_s app_key, const stc_app_value_s app_value); /** + * @brief deletes an application entry + */ +stc_error_e stc_monitor_application_remove(const stc_app_key_s app_key); + +/** * @brief associates process to an application */ stc_error_e stc_monitor_process_add(const stc_app_key_s app_key, diff --git a/src/monitor/stc-monitor.c b/src/monitor/stc-monitor.c index 2a42682..fbed5e3 100644 --- a/src/monitor/stc-monitor.c +++ b/src/monitor/stc-monitor.c @@ -70,6 +70,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) @@ -384,10 +480,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(); @@ -423,7 +602,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) { @@ -444,6 +626,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(); @@ -464,7 +647,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; @@ -1049,7 +1236,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) { @@ -1103,6 +1291,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; @@ -1115,6 +1305,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); @@ -1266,7 +1459,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); @@ -2071,6 +2265,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, @@ -2088,6 +2283,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)