Merge "Return errors to caller" into tizen_5.5
[platform/core/connectivity/stc-manager.git] / src / helper / helper-iptables.c
old mode 100644 (file)
new mode 100755 (executable)
index 445b627..ffffd21
 #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"
@@ -97,90 +101,236 @@ static void __add_rule_info_to_builder(GVariantBuilder *builder,
                                      g_variant_new_uint32(rule->d_ip2.s_addr));
 }
 
+static void __add_rule_reply(
+                       GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+       GDBusConnection *conn = NULL;
+       GVariant *dbus_data = NULL;
+       GError *dbus_error = NULL;
+       int result = 0;
+       char *nfacct_name = user_data;
+
+       conn = G_DBUS_CONNECTION(source_object);
+       dbus_data = g_dbus_connection_call_finish(conn, res, &dbus_error);
+       if (dbus_error != NULL) {
+               STC_LOGE("Dbus reply error [%s]", dbus_error->message);
+               g_error_free(dbus_error);
+       } else {
+               g_variant_get(dbus_data, "(i)", &result);
+               STC_LOGI("Added rule [%d:%s]", result, nfacct_name);
+       }
+
+       g_free(nfacct_name);
+}
+
+static void __remove_rule_reply(
+                       GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+       GDBusConnection *conn = NULL;
+       GVariant *dbus_data = NULL;
+       GError *dbus_error = NULL;
+       int result = 0;
+       char *nfacct_name = user_data;
+
+       conn = G_DBUS_CONNECTION(source_object);
+       dbus_data = g_dbus_connection_call_finish(conn, res, &dbus_error);
+       if (dbus_error != NULL) {
+               STC_LOGE("Dbus reply error [%s]", dbus_error->message);
+               g_error_free(dbus_error);
+       } else {
+               g_variant_get(dbus_data, "(i)", &result);
+               STC_LOGI("Removed rule [%d:%s]", result, nfacct_name);
+       }
+
+       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)
 {
-       int result = 0;
+       int result = STC_ERROR_NONE;
        GVariantBuilder *builder = NULL;
        GVariant *params = NULL;
-       GVariant *message = NULL;
+       char *nfacct_name = NULL;
 
        builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
        __add_rule_info_to_builder(builder, rule);
        params = g_variant_new("(a{sv})", builder);
        g_variant_builder_unref(builder);
 
-       message = stc_manager_gdbus_call_sync(connection,
+       nfacct_name = g_strdup_printf("4:%s", rule->nfacct_name);
+
+       result = stc_manager_gdbus_call_async(connection,
                                              STC_IPTABLES_DBUS_SERVICE,
                                              STC_IPTABLES_DBUS_RULE_PATH,
                                              STC_IPTABLES_DBUS_RULE_INTERFACE,
                                              STC_IPTABLES_DBUS_METHOD_IPT_ADD_RULE,
-                                             params);
+                                             params,
+                                             __add_rule_reply,
+                                             nfacct_name);
 
-       if (message == NULL) {
-               STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
-               return STC_ERROR_FAIL; //LCOV_EXCL_LINE
+       if (result != STC_ERROR_NONE) {
+               STC_LOGE("Failed to invoke dbus method async");
+               g_free(nfacct_name);
        }
 
-       g_variant_get(message, "(i)", &result);
-       if (STC_DEBUG_LOG)
-               STC_LOGD("Successfully Add Rule [%d:%s]", result, rule->nfacct_name);
-       g_variant_unref(message);
-
-       return STC_ERROR_NONE;
+       return result;
 }
 
 static int __iptables_rule_remove(GDBusConnection *connection,
                                  iptables_rule_s *rule)
 {
-       int result = 0;
+       int result = STC_ERROR_NONE;
        GVariantBuilder *builder = NULL;
        GVariant *params = NULL;
-       GVariant *message = NULL;
+       char *nfacct_name = NULL;
 
        builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
        __add_rule_info_to_builder(builder, rule);
        params = g_variant_new("(a{sv})", builder);
        g_variant_builder_unref(builder);
 
-       message = stc_manager_gdbus_call_sync(connection,
+       nfacct_name = g_strdup_printf("4:%s", rule->nfacct_name);
+
+       result = stc_manager_gdbus_call_async(connection,
                                              STC_IPTABLES_DBUS_SERVICE,
                                              STC_IPTABLES_DBUS_RULE_PATH,
                                              STC_IPTABLES_DBUS_RULE_INTERFACE,
                                              STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_RULE,
-                                             params);
+                                             params,
+                                             __remove_rule_reply,
+                                             nfacct_name);
 
-       if (message == NULL) {
-               STC_LOGE("Failed to invoke dbus method"); //LCOV_EXCL_LINE
-               return STC_ERROR_FAIL; //LCOV_EXCL_LINE
+       if (result != STC_ERROR_NONE) {
+               STC_LOGE("Failed to invoke dbus method async");
+               g_free(nfacct_name);
        }
 
-       g_variant_get(message, "(i)", &result);
-       if (STC_DEBUG_LOG)
-               STC_LOGD("Successfully Remove Rule [%d:%s]", result, rule->nfacct_name);
-       g_variant_unref(message);
-
-       return STC_ERROR_NONE;
+       return result;
 }
 
 static int __ip6tables_rule_add(GDBusConnection *connection,
                                iptables_rule_s *rule)
 {
-       int result = 0;
+       int result = STC_ERROR_NONE;
        GVariantBuilder *builder = NULL;
        GVariant *params = NULL;
-       GVariant *message = NULL;
+       char *nfacct_name = NULL;
 
        builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
        __add_rule_info_to_builder(builder, rule);
        params = g_variant_new("(a{sv})", builder);
        g_variant_builder_unref(builder);
 
-       message = stc_manager_gdbus_call_sync(connection,
+       nfacct_name = g_strdup_printf("6:%s", rule->nfacct_name);
+
+       result = stc_manager_gdbus_call_async(connection,
                                              STC_IPTABLES_DBUS_SERVICE,
                                              STC_IPTABLES_DBUS_RULE_PATH,
                                              STC_IPTABLES_DBUS_RULE_INTERFACE,
                                              STC_IPTABLES_DBUS_METHOD_IP6T_ADD_RULE,
+                                             params,
+                                             __add_rule_reply,
+                                             nfacct_name);
+
+       if (result != STC_ERROR_NONE) {
+               STC_LOGE("Failed to invoke dbus method async");
+               g_free(nfacct_name);
+       }
+
+       return result;
+}
+
+static int __ip6tables_rule_remove(GDBusConnection *connection,
+                                  iptables_rule_s *rule)
+{
+       int result = STC_ERROR_NONE;
+       GVariantBuilder *builder = NULL;
+       GVariant *params = NULL;
+       char *nfacct_name = NULL;
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       __add_rule_info_to_builder(builder, rule);
+       params = g_variant_new("(a{sv})", builder);
+       g_variant_builder_unref(builder);
+
+       nfacct_name = g_strdup_printf("6:%s", rule->nfacct_name);
+
+       result = stc_manager_gdbus_call_async(connection,
+                                             STC_IPTABLES_DBUS_SERVICE,
+                                             STC_IPTABLES_DBUS_RULE_PATH,
+                                             STC_IPTABLES_DBUS_RULE_INTERFACE,
+                                             STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_RULE,
+                                             params,
+                                             __remove_rule_reply,
+                                             nfacct_name);
+
+       if (result != STC_ERROR_NONE) {
+               STC_LOGE("Failed to invoke dbus method async");
+               g_free(nfacct_name);
+       }
+
+       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) {
@@ -189,31 +339,36 @@ static int __ip6tables_rule_add(GDBusConnection *connection,
        }
 
        g_variant_get(message, "(i)", &result);
-       if (STC_DEBUG_LOG)
-               STC_LOGD("Successfully Add 6 Rule [%d:%s]", result, rule->nfacct_name);
-       g_variant_unref(message);
 
-       return STC_ERROR_NONE;
+       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 __ip6tables_rule_remove(GDBusConnection *connection,
-                                  iptables_rule_s *rule)
+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("a{sv}"));
-       __add_rule_info_to_builder(builder, rule);
-       params = g_variant_new("(a{sv})", builder);
+       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,
-                                             STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_RULE,
+                                             method,
                                              params);
 
        if (message == NULL) {
@@ -222,10 +377,12 @@ static int __ip6tables_rule_remove(GDBusConnection *connection,
        }
 
        g_variant_get(message, "(i)", &result);
-       if (STC_DEBUG_LOG)
-               STC_LOGD("Successfully Remove 6 Rule [%d:%s]", result, rule->nfacct_name);
-       g_variant_unref(message);
 
+       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;
 }
 
@@ -397,6 +554,454 @@ static int __iptables_add_chain_jump_rule(const char *chain,
        return ret;
 }
 
+static stc_error_e _iptables_add_in_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __iptables_add_chain(stc->connection, STC_IN_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_IN_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_IN_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_IN_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_IN_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_IN_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _iptables_add_out_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __iptables_add_chain(stc->connection, STC_OUT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_OUT_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_OUT_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_OUT_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_OUT_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain(stc->connection, STC_OUT_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _ip6tables_add_in_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _ip6tables_add_out_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __ip6tables_add_chain(stc->connection, STC_OUT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_OUT_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_OUT_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_OUT_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_OUT_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_add_chain(stc->connection, STC_OUT_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _iptables_add_in_chain_jump_rule(void)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _iptables_add_out_chain_jump_rule(void)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _iptables_remove_in_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __iptables_remove_chain(stc->connection, STC_IN_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_IN_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_IN_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_IN_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_IN_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_IN_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _iptables_remove_out_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __iptables_remove_chain(stc->connection, STC_OUT_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_OUT_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_OUT_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_OUT_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_OUT_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_remove_chain(stc->connection, STC_OUT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _ip6tables_remove_in_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_IN_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_IN_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_IN_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_IN_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_IN_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_IN_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _ip6tables_remove_out_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_OUT_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_OUT_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_OUT_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_OUT_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_OUT_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_remove_chain(stc->connection, STC_OUT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _iptables_flush_in_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __iptables_flush_chain(stc->connection, STC_IN_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_IN_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_IN_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_IN_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_IN_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_IN_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _iptables_flush_out_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __iptables_flush_chain(stc->connection, STC_OUT_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_OUT_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_OUT_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_OUT_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_OUT_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_OUT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
+static stc_error_e _ip6tables_flush_in_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_IN_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_IN_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_IN_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_IN_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_IN_BG_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
+
+done:
+       return ret;
+}
+
+static stc_error_e _ip6tables_flush_out_chain(stc_s *stc)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_OUT_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_OUT_FG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_OUT_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_OUT_BG_DROP_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_OUT_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_OUT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+done:
+       return ret;
+}
+
 stc_error_e iptables_add(iptables_rule_s *rule, iptables_ip_type_e iptype)
 {
        stc_error_e ret = STC_ERROR_NONE;
@@ -443,7 +1048,27 @@ done:
        return ret;
 }
 
-stc_error_e iptables_flush_chains(void)
+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_s *stc = stc_get_manager();
@@ -451,11 +1076,11 @@ stc_error_e iptables_flush_chains(void)
        if (!stc || !stc->connection)
                return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
 
-       ret = __iptables_flush_chain(stc->connection, STC_IN_CHAIN);
+       ret = _iptables_flush_in_chain(stc);
        if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
 
-       ret = __iptables_flush_chain(stc->connection, STC_OUT_CHAIN);
+       ret = _iptables_flush_out_chain(stc);
        if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
 
@@ -467,11 +1092,11 @@ stc_error_e iptables_flush_chains(void)
        if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
 
-       ret = __ip6tables_flush_chain(stc->connection, STC_IN_CHAIN);
+       ret = _ip6tables_flush_in_chain(stc);
        if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
 
-       ret = __ip6tables_flush_chain(stc->connection, STC_OUT_CHAIN);
+       ret = _ip6tables_flush_out_chain(stc);
        if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
 
@@ -492,13 +1117,13 @@ stc_error_e iptables_init(void)
                return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
        }
 
-       ret = __iptables_add_chain(stc->connection, STC_IN_CHAIN);
+       ret = _iptables_add_in_chain(stc);
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
        }
 
-       ret = __iptables_add_chain(stc->connection, STC_OUT_CHAIN);
+       ret = _iptables_add_out_chain(stc);
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
@@ -516,13 +1141,13 @@ stc_error_e iptables_init(void)
                goto done; //LCOV_EXCL_LINE
        }
 
-       ret = __ip6tables_add_chain(stc->connection, STC_IN_CHAIN);
+       ret = _ip6tables_add_in_chain(stc);
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
        }
 
-       ret = __ip6tables_add_chain(stc->connection, STC_OUT_CHAIN);
+       ret = _ip6tables_add_out_chain(stc);
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
@@ -534,13 +1159,19 @@ stc_error_e iptables_init(void)
                goto done; //LCOV_EXCL_LINE
        }
 
-       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_CHAIN);
+       ret = __ip6tables_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 = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_CHAIN);
+       ret = _iptables_add_in_chain_jump_rule();
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               goto done; //LCOV_EXCL_LINE
+       }
+
+       ret = _iptables_add_out_chain_jump_rule();
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
@@ -557,7 +1188,9 @@ stc_error_e iptables_init(void)
                __STC_LOG_FUNC_EXIT__;
                goto done;
        }
+
 done:
+       __STC_LOG_FUNC_ENTER__;
        return ret;
 }
 
@@ -573,13 +1206,13 @@ stc_error_e iptables_deinit(void)
                return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
        }
 
-       ret = __iptables_remove_chain(stc->connection, STC_IN_CHAIN);
+       ret = _iptables_remove_in_chain(stc);
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
        }
 
-       ret = __iptables_remove_chain(stc->connection, STC_OUT_CHAIN);
+       ret = _iptables_remove_out_chain(stc);
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
@@ -597,19 +1230,25 @@ stc_error_e iptables_deinit(void)
                goto done; //LCOV_EXCL_LINE
        }
 
-       ret = __ip6tables_remove_chain(stc->connection, STC_IN_CHAIN);
+       ret = _ip6tables_remove_in_chain(stc);
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
        }
 
-       ret = __ip6tables_remove_chain(stc->connection, STC_OUT_CHAIN);
+       ret = _ip6tables_remove_out_chain(stc);
        if (ret != STC_ERROR_NONE) {
                __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
                goto done; //LCOV_EXCL_LINE
        }
 
        ret = __ip6tables_remove_chain(stc->connection, STC_FRWD_CHAIN);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               goto done; //LCOV_EXCL_LINE
+       }
+
 done:
+       __STC_LOG_FUNC_ENTER__;
        return ret;
 }