Merge "Return errors to caller" into tizen_5.5
[platform/core/connectivity/stc-manager.git] / src / helper / helper-iptables.c
index cfd8aaf..ffffd21 100755 (executable)
 #define STC_IPTABLES_DBUS_METHOD_IPT_REMOVE_RULE     "IptRemoveRule"
 #define STC_IPTABLES_DBUS_METHOD_IP6T_ADD_RULE       "Ip6tAddRule"
 #define STC_IPTABLES_DBUS_METHOD_IP6T_REMOVE_RULE    "Ip6tRemoveRule"
-
-#define RULE_CHAIN   "chain"
-#define RULE_TYPE    "type"
-#define RULE_IFNAME  "ifname"
-#define RULE_CGROUP  "cgroup"
-#define RULE_NFACCT  "nfacct"
-#define RULE_TARGET  "target"
+#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"
+#define RULE_IFNAME     "ifname"
+#define RULE_CGROUP     "cgroup"
+#define RULE_NFACCT     "nfacct"
+#define RULE_TARGET     "target"
+#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)
@@ -49,7 +59,7 @@ static void __add_rule_info_to_builder(GVariantBuilder *builder,
        g_variant_builder_add(builder, "{sv}", RULE_CHAIN,
                              g_variant_new_string(rule->chain));
 
-       g_variant_builder_add(builder, "{sv}", RULE_TYPE,
+       g_variant_builder_add(builder, "{sv}", RULE_DIRECTION,
                              g_variant_new_uint16(rule->direction));
 
        if (rule->ifname)
@@ -68,90 +78,259 @@ 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 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);
-       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);
-       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) {
@@ -160,30 +339,36 @@ static int __ip6tables_rule_add(GDBusConnection *connection,
        }
 
        g_variant_get(message, "(i)", &result);
-       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) {
@@ -192,9 +377,12 @@ static int __ip6tables_rule_remove(GDBusConnection *connection,
        }
 
        g_variant_get(message, "(i)", &result);
-       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;
 }
 
@@ -366,193 +554,701 @@ static int __iptables_add_chain_jump_rule(const char *chain,
        return ret;
 }
 
-stc_error_e iptables_add(iptables_rule_s *rule, iptables_ip_type_e iptype)
+static stc_error_e _iptables_add_in_chain(stc_s *stc)
 {
        stc_error_e ret = STC_ERROR_NONE;
-       stc_s *stc = stc_get_manager();
 
-       if (!stc || !stc->connection)
-               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+       ret = __iptables_add_chain(stc->connection, STC_IN_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
 
-       if (iptype == IP_TYPE_IPV4 ||
-               iptype == IP_TYPE_IPV4_IPV6) {
-               ret = __iptables_rule_add(stc->connection, rule);
-               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
 
-       if (iptype == IP_TYPE_IPV6 ||
-               iptype == IP_TYPE_IPV4_IPV6)
-               ret = __ip6tables_rule_add(stc->connection, rule);
+       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;
 }
 
-stc_error_e iptables_remove(iptables_rule_s *rule, iptables_ip_type_e iptype)
+static stc_error_e _iptables_add_out_chain(stc_s *stc)
 {
        stc_error_e ret = STC_ERROR_NONE;
-       stc_s *stc = stc_get_manager();
 
-       if (!stc || !stc->connection)
-               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+       ret = __iptables_add_chain(stc->connection, STC_OUT_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
 
-       if (iptype == IP_TYPE_IPV4 ||
-               iptype == IP_TYPE_IPV4_IPV6) {
-               ret = __iptables_rule_remove(stc->connection, rule);
-               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
 
-       if (iptype == IP_TYPE_IPV6 ||
-               iptype == IP_TYPE_IPV4_IPV6)
-               ret = __ip6tables_rule_remove(stc->connection, rule);
+       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;
 }
 
-stc_error_e iptables_flush_chains(void)
+static stc_error_e _ip6tables_add_in_chain(stc_s *stc)
 {
        stc_error_e ret = STC_ERROR_NONE;
-       stc_s *stc = stc_get_manager();
 
-       if (!stc || !stc->connection)
-               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_CHAIN);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
 
-       ret = __iptables_flush_chain(stc->connection, STC_IN_CHAIN);
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_DROP_CHAIN);
        if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
 
-       ret = __iptables_flush_chain(stc->connection, STC_OUT_CHAIN);
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_FG_CHAIN);
        if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
 
-       ret = __iptables_flush_chain(stc->connection, STC_FRWD_CHAIN);
+       ret = __ip6tables_add_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_CHAIN);
+       ret = __ip6tables_add_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_OUT_CHAIN);
+       ret = __ip6tables_add_chain(stc->connection, STC_IN_BG_CHAIN);
        if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
 
-       ret = __ip6tables_flush_chain(stc->connection, STC_FRWD_CHAIN);
 done:
        return ret;
 }
 
-stc_error_e iptables_init(void)
+static stc_error_e _ip6tables_add_out_chain(stc_s *stc)
 {
-       __STC_LOG_FUNC_ENTER__;
-
        stc_error_e ret = STC_ERROR_NONE;
-       stc_s *stc = stc_get_manager();
-
-       if (!stc || !stc->connection) {
-               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
-               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
-       }
-
-       ret = __iptables_add_chain(stc->connection, STC_IN_CHAIN);
-       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);
-       if (ret != STC_ERROR_NONE) {
-               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
-               goto done; //LCOV_EXCL_LINE
-       }
 
-       ret = __iptables_add_chain(stc->connection, STC_FRWD_CHAIN);
-       if (ret != STC_ERROR_NONE) {
-               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+       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_IN_CHAIN);
-       if (ret != STC_ERROR_NONE) {
-               __STC_LOG_FUNC_EXIT__; //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_CHAIN);
-       if (ret != STC_ERROR_NONE) {
-               __STC_LOG_FUNC_EXIT__; //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_FRWD_CHAIN);
-       if (ret != STC_ERROR_NONE) {
-               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+       ret = __ip6tables_add_chain(stc->connection, STC_OUT_ACCEPT_CHAIN);
+       if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
-       }
 
-       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_CHAIN);
-       if (ret != STC_ERROR_NONE) {
-               __STC_LOG_FUNC_EXIT__; //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 = __iptables_add_chain_jump_rule("OUTPUT", STC_OUT_CHAIN);
-       if (ret != STC_ERROR_NONE) {
-               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+       ret = __ip6tables_add_chain(stc->connection, STC_OUT_BG_CHAIN);
+       if (ret != STC_ERROR_NONE)
                goto done; //LCOV_EXCL_LINE
-       }
 
-       ret = __iptables_add_chain_jump_rule("FORWARD", STC_FRWD_CHAIN);
 done:
        return ret;
 }
 
-stc_error_e iptables_deinit(void)
+static stc_error_e _iptables_add_in_chain_jump_rule(void)
 {
-       __STC_LOG_FUNC_ENTER__;
-
        stc_error_e ret = STC_ERROR_NONE;
-       stc_s *stc = stc_get_manager();
 
-       if (!stc || !stc->connection) {
-               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
-               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
-       }
+       ret = __iptables_add_chain_jump_rule("INPUT", STC_IN_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) {
-               __STC_LOG_FUNC_EXIT__; //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_remove_chain(stc->connection, STC_OUT_CHAIN);
-       if (ret != STC_ERROR_NONE) {
-               __STC_LOG_FUNC_EXIT__; //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_remove_chain(stc->connection, STC_FRWD_CHAIN);
-       if (ret != STC_ERROR_NONE) {
+       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;
+       stc_s *stc = stc_get_manager();
+
+       if (!stc || !stc->connection)
+               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       if (iptype == IP_TYPE_IPV4 ||
+               iptype == IP_TYPE_IPV4_IPV6) {
+               ret = __iptables_rule_add(stc->connection, rule);
+               if (ret != STC_ERROR_NONE)
+                       goto done; //LCOV_EXCL_LINE
+       }
+
+       if (iptype == IP_TYPE_IPV6 ||
+               iptype == IP_TYPE_IPV4_IPV6)
+               ret = __ip6tables_rule_add(stc->connection, rule);
+
+done:
+       return ret;
+}
+
+stc_error_e iptables_remove(iptables_rule_s *rule, iptables_ip_type_e iptype)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+       stc_s *stc = stc_get_manager();
+
+       if (!stc || !stc->connection)
+               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       if (iptype == IP_TYPE_IPV4 ||
+               iptype == IP_TYPE_IPV4_IPV6) {
+               ret = __iptables_rule_remove(stc->connection, rule);
+               if (ret != STC_ERROR_NONE)
+                       goto done; //LCOV_EXCL_LINE
+       }
+
+       if (iptype == IP_TYPE_IPV6 ||
+               iptype == IP_TYPE_IPV4_IPV6)
+               ret = __ip6tables_rule_remove(stc->connection, rule);
+
+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;
+       stc_s *stc = stc_get_manager();
+
+       if (!stc || !stc->connection)
+               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+
+       ret = _iptables_flush_in_chain(stc);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = _iptables_flush_out_chain(stc);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __iptables_flush_chain(stc->connection, STC_FRWD_CHAIN);
+       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_in_chain(stc);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = _ip6tables_flush_out_chain(stc);
+       if (ret != STC_ERROR_NONE)
+               goto done; //LCOV_EXCL_LINE
+
+       ret = __ip6tables_flush_chain(stc->connection, STC_FRWD_CHAIN);
+done:
+       return ret;
+}
+
+stc_error_e iptables_init(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       stc_error_e ret = STC_ERROR_NONE;
+       stc_s *stc = stc_get_manager();
+
+       if (!stc || !stc->connection) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+       }
+
+       ret = _iptables_add_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_IN_CHAIN);
+       ret = _iptables_add_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_OUT_CHAIN);
+       ret = __iptables_add_chain(stc->connection, STC_FRWD_CHAIN);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               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_in_chain(stc);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               goto done; //LCOV_EXCL_LINE
+       }
+
+       ret = _ip6tables_add_out_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_FRWD_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_TETHER_CHAIN);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               goto done; //LCOV_EXCL_LINE
+       }
+
+       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
+       }
+
+       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:
+       __STC_LOG_FUNC_ENTER__;
+       return ret;
+}
+
+stc_error_e iptables_deinit(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       stc_error_e ret = STC_ERROR_NONE;
+       stc_s *stc = stc_get_manager();
+
+       if (!stc || !stc->connection) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+       }
+
+       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_out_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_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
+               goto done; //LCOV_EXCL_LINE
+       }
+
+       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_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;
 }