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,
}
}
+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,
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,
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);
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("==================================================");
}
}
__get_connection_info(connection, conn, conn->path);
- __print_connection_info(conn);
+ __print_connection_info(conn, "connected");
if (default_conn == TRUE) {
g_default_connection = conn;
}
__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);
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);
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)
{
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);
#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"
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)
{
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)
{
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;
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);
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';
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);