Added firewall feature 28/174928/2
authorhyunuktak <hyunuk.tak@samsung.com>
Thu, 5 Apr 2018 06:25:28 +0000 (15:25 +0900)
committerhyunuktak <hyunuk.tak@samsung.com>
Thu, 5 Apr 2018 07:37:36 +0000 (16:37 +0900)
Change-Id: I9c71bc7af199d145509cbe0c7e935d16e85dfd8d
Signed-off-by: hyunuktak <hyunuk.tak@samsung.com>
24 files changed:
data/firewall_db.sql [new file with mode: 0644]
include/stc-error.h
include/stc-firewall.h [new file with mode: 0755]
include/stc-manager-gdbus.h
include/stc-manager.h
interfaces/CMakeLists.txt
interfaces/stcmanager-iface-firewall.xml [new file with mode: 0644]
packaging/stc-manager.spec
src/CMakeLists.txt
src/database/db-common.c
src/database/include/table-firewall.h [new file with mode: 0755]
src/database/tables/table-firewall.c [new file with mode: 0755]
src/database/tables/table-statistics.c
src/helper/helper-firewall.c [new file with mode: 0755]
src/helper/helper-firewall.h [new file with mode: 0755]
src/helper/helper-iptables.c
src/helper/helper-iptables.h
src/helper/helper-nfacct-rule.c
src/monitor/stc-default-connection.c
src/stc-firewall.c [new file with mode: 0755]
src/stc-manager-gdbus.c
src/stc-manager.c
src/stc-restriction.c
src/stc-statistics.c

diff --git a/data/firewall_db.sql b/data/firewall_db.sql
new file mode 100644 (file)
index 0000000..9a0bfdb
--- /dev/null
@@ -0,0 +1,35 @@
+CREATE TABLE IF NOT EXISTS fw_lock (
+  name TEXT PRIMARY KEY,
+  state INT
+);
+
+CREATE TABLE IF NOT EXISTS fw_chains (
+  chain TEXT PRIMARY KEY,
+  target INT,
+  priority INT
+);
+
+CREATE TABLE IF NOT EXISTS fw_rules (
+  key BIGINT PRIMARY KEY,
+  chain TEXT NOT NULL,
+  direction INT,
+  s_ip_type INT,
+  d_ip_type INT,
+  s_port_type INT,
+  d_port_type INT,
+  protocol INT,
+  family INT,
+  s_ip1 TEXT NOT NULL,
+  s_ip2 TEXT NOT NULL,
+  d_ip1 TEXT NOT NULL,
+  d_ip2 TEXT NOT NULL,
+  s_port1 INT,
+  s_port2 INT,
+  d_port1 INT,
+  d_port2 INT,
+  ifname TEXT NOT NULL,
+  target INT,
+  identifier TEXT NOT NULL
+);
+
+CREATE INDEX IF NOT EXISTS rules_index ON fw_rules (chain, target);
index ecb4e68..6bf1c40 100755 (executable)
 #define __STC_ERROR_H__
 
 typedef enum {
-       STC_ERROR_NOTIMPL = -7,            /**< Not implemented yet error */
-       STC_ERROR_UNINITIALIZED = -6,      /**< Cgroup doen't mounted or daemon not started */
+       STC_ERROR_NOTIMPL = -9,            /**< Not implemented yet error */
+       STC_ERROR_PERMISSION_DENIED = -8,  /**< Permission denied */
+       STC_ERROR_UNINITIALIZED = -7,      /**< Not initialized */
+       STC_ERROR_ALREADY_DATA = -6,       /**< Success, but already data */
        STC_ERROR_NO_DATA = -5,            /**< Success, but no data */
        STC_ERROR_INVALID_PARAMETER = -4,  /**< Invalid parameter */
        STC_ERROR_OUT_OF_MEMORY = -3,      /**< Out of memory */
diff --git a/include/stc-firewall.h b/include/stc-firewall.h
new file mode 100755 (executable)
index 0000000..c857f9b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __STC_FIREWALL_H__
+#define __STC_FIREWALL_H__
+
+#include <glib.h>
+#include "stc-manager.h"
+#include "stc-manager-gdbus.h"
+#include "table-firewall.h"
+
+/*****************************************************************************
+ * Macros and Typedefs
+ *****************************************************************************/
+
+typedef struct {
+       stc_fw_chain_target_e target;
+       uint64_t priority;
+       GSList *rules;
+} stc_fw_data_s;
+
+/*****************************************************************************
+ * Functions Declaration
+ *****************************************************************************/
+
+void stc_firewall_init(void);
+void stc_firewall_update(void);
+void stc_firewall_deinit(void);
+
+gboolean handle_firewall_lock(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       void *user_data);
+
+gboolean handle_firewall_unlock(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       void *user_data);
+
+gboolean handle_firewall_get_lock(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       void *user_data);
+
+gboolean handle_firewall_add_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       void *user_data);
+
+gboolean handle_firewall_remove_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       void *user_data);
+
+gboolean handle_firewall_flush_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       void *user_data);
+
+gboolean handle_firewall_get_all_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       void *user_data);
+
+gboolean handle_firewall_set_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       unsigned int target,
+                                       void *user_data);
+
+gboolean handle_firewall_unset_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       void *user_data);
+
+gboolean handle_firewall_add_rule(StcFirewall *object,
+                                  GDBusMethodInvocation *invocation,
+                                  GVariant *parameters,
+                                  void *user_data);
+
+gboolean handle_firewall_remove_rule(StcFirewall *object,
+                                  GDBusMethodInvocation *invocation,
+                                  GVariant *parameters,
+                                  void *user_data);
+
+gboolean handle_firewall_update_rule(StcFirewall *object,
+                                  GDBusMethodInvocation *invocation,
+                                  GVariant *parameters,
+                                  void *user_data);
+
+gboolean handle_firewall_get_all_rule(StcFirewall *object,
+                                  GDBusMethodInvocation *invocation,
+                                  void *user_data);
+
+#endif /* __STC_FIREWALL_H__ */
index 7803c6b..4b6a50f 100755 (executable)
@@ -25,6 +25,7 @@
 #define STC_DBUS_SERVICE_PATH              "/net/stc"
 #define STC_DBUS_SERVICE_STATISTICS_PATH   "/net/stc/statistics"
 #define STC_DBUS_SERVICE_RESTRICTION_PATH  "/net/stc/restriction"
+#define STC_DBUS_SERVICE_FIREWALL_PATH     "/net/stc/firewall"
 #define STC_DBUS_SERVICE_MANAGER_PATH      "/net/stc/manager"
 
 #define STC_DBUS_REPLY_ERROR_NONE(invocation) \
index 1a84f69..c6a8f8e 100755 (executable)
@@ -48,6 +48,56 @@ typedef enum {
        STC_CMD_MAX_ELEM
 } stc_cmd_type_e;
 
+typedef enum {
+       STC_FW_DIRECTION_NONE,
+       STC_FW_DIRECTION_IN,
+       STC_FW_DIRECTION_OUT
+} stc_fw_direction_e;
+
+typedef enum {
+       STC_FW_FAMILY_NONE,
+       STC_FW_FAMILY_V4,
+       STC_FW_FAMILY_V6
+} stc_fw_family_type_e;
+
+typedef enum {
+       STC_FW_IP_NONE,
+       STC_FW_IP_SINGLE,
+       STC_FW_IP_MASK,
+       STC_FW_IP_RANGE
+} stc_fw_ip_type_e;
+
+typedef enum {
+       STC_FW_PORT_NONE,
+       STC_FW_PORT_SINGLE,
+       STC_FW_PORT_RANGE
+} stc_fw_port_type_e;
+
+typedef enum {
+       STC_FW_PROTOCOL_NONE,
+       STC_FW_PROTOCOL_TCP,
+       STC_FW_PROTOCOL_UDP,
+       STC_FW_PROTOCOL_ICMP,
+       STC_FW_PROTOCOL_ESP,
+       STC_FW_PROTOCOL_AH,
+       STC_FW_PROTOCOL_SCTP,
+       STC_FW_PROTOCOL_MH,
+       STC_FW_PROTOCOL_ALL,
+} stc_fw_protocol_type_e;
+
+typedef enum {
+       STC_FW_CHAIN_TARGET_NONE,
+       STC_FW_CHAIN_TARGET_INPUT,
+       STC_FW_CHAIN_TARGET_OUTPUT
+} stc_fw_chain_target_e;
+
+typedef enum {
+       STC_FW_RULE_TARGET_NONE,
+       STC_FW_RULE_TARGET_ACCEPT,
+       STC_FW_RULE_TARGET_DROP,
+       STC_FW_RULE_TARGET_LOG,
+} stc_fw_rule_target_e;
+
 /**
  * @brief Monitored application types
  */
@@ -121,7 +171,7 @@ typedef enum {
  * @brief Hardware network protocol types
  */
 typedef enum {
-       STC_PROTOCOL_NONE,                /**< Network unknown */
+       STC_PROTOCOL_UNKNOWN,             /**< Network unknown */
        STC_PROTOCOL_DATACALL_NOSVC,      /**< Network no service */
        STC_PROTOCOL_DATACALL_EMERGENCY,  /**< Network emergency */
        STC_PROTOCOL_DATACALL_SEARCH,     /**< Network search 1900 */
@@ -173,6 +223,7 @@ typedef struct {
 
        gpointer statistics_obj;
        gpointer restriction_obj;
+       gpointer firewall_obj;
        gpointer manager_obj;
 
        GDBusObjectManagerServer *obj_mgr;
index 2e61a9e..8f03ebf 100644 (file)
@@ -9,6 +9,7 @@ ADD_CUSTOM_COMMAND(
                        ${INTERFACES}/stcmanager-iface-manager.xml
                        ${INTERFACES}/stcmanager-iface-restriction.xml
                        ${INTERFACES}/stcmanager-iface-statistics.xml
+                       ${INTERFACES}/stcmanager-iface-firewall.xml
                        COMMENT "Generating GDBus .c/.h")
 
 ADD_CUSTOM_TARGET(GENERATED_DBUS_CODE DEPENDS dbus)
diff --git a/interfaces/stcmanager-iface-firewall.xml b/interfaces/stcmanager-iface-firewall.xml
new file mode 100644 (file)
index 0000000..d5817cf
--- /dev/null
@@ -0,0 +1,53 @@
+<node>
+       <interface name="net.stc.firewall">
+               <method name='Lock'>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='Unlock'>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='GetLock'>
+                       <arg type='i' name='state' direction='out'/>
+               </method>
+               <method name='AddChain'>
+                       <arg type='s' name='chain' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='RemoveChain'>
+                       <arg type='s' name='chain' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='FlushChain'>
+                       <arg type='s' name='chain' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='GetAllChain'>
+                       <arg type='aa{sv}' name='parameters' direction='out'/>
+               </method>
+               <method name='SetChain'>
+                       <arg type='s' name='chain' direction='in'/>
+                       <arg type='u' name='target' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='UnsetChain'>
+                       <arg type='s' name='chain' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+
+               <method name='AddRule'>
+                       <arg type='a{sv}' name='parameters' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='RemoveRule'>
+                       <arg type='a{sv}' name='parameters' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='UpdateRule'>
+                       <arg type='a{sv}' name='parameters' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='GetAllRule'>
+                       <arg type='aa{sv}' name='parameters' direction='out'/>
+               </method>
+       </interface>
+</node>
index 7b9b87e..6dca357 100644 (file)
@@ -1,6 +1,6 @@
 Name:       stc-manager
 Summary:    STC(Smart Traffic Control) manager
-Version:    0.0.54
+Version:    0.0.55
 Release:    0
 Group:      Network & Connectivity/Other
 License:    Apache-2.0
@@ -88,7 +88,9 @@ rm -rf %{buildroot}
 %if %{?enable_database} == YES
        mkdir -p %{buildroot}/opt/usr/dbspace
        sqlite3 %{buildroot}%{database_full_path} < %{buildroot}/usr/share/traffic_db.sql
+       sqlite3 %{buildroot}%{database_full_path} < %{buildroot}/usr/share/firewall_db.sql
        rm %{buildroot}/usr/share/traffic_db.sql
+       rm %{buildroot}/usr/share/firewall_db.sql
 %endif
 
 #Exceptions file
index f01f292..809897a 100644 (file)
@@ -69,6 +69,7 @@ IF("${ENABLE_DATABASE}" STREQUAL "YES")
        SET(SRCS ${SRCS} ${DATABASE_SRCS} ${DATABASE_TABLES_SRCS})
 
        INSTALL(FILES ${DATA_DIR}/traffic_db.sql DESTINATION /usr/share)
+       INSTALL(FILES ${DATA_DIR}/firewall_db.sql DESTINATION /usr/share)
 ENDIF()
 
 IF(BUILD_GTESTS)
index f5f1770..a4c2a3d 100755 (executable)
@@ -19,6 +19,7 @@
 #include "table-statistics.h"
 #include "table-restrictions.h"
 #include "table-counters.h"
+#include "table-firewall.h"
 
 #ifndef DATABASE_FULL_PATH
 #define DATABASE_FULL_PATH "/opt/usr/dbspace/.stc-manager-datausage.db"
@@ -111,6 +112,7 @@ stc_error_e stc_db_initialize(void)
        EXEC(STC_ERROR_NONE, table_statistics_prepare(database));
        EXEC(STC_ERROR_NONE, table_restrictions_prepare(database));
        EXEC(STC_ERROR_NONE, table_counters_prepare(database));
+       EXEC(STC_ERROR_NONE, table_firewall_prepare(database));
        EXEC(STC_ERROR_NONE, stc_init_db_guard());
 
        __STC_LOG_FUNC_EXIT__;
@@ -133,6 +135,7 @@ gboolean stc_db_deinitialize(void)
        table_statistics_finalize();
        table_restrictions_finalize();
        table_counters_finalize();
+       table_firewall_finalize();
        sqlite3_close(database);
 
        __STC_LOG_FUNC_EXIT__;
diff --git a/src/database/include/table-firewall.h b/src/database/include/table-firewall.h
new file mode 100755 (executable)
index 0000000..e15668f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TABLE_FIREWALL_H__
+#define __TABLE_FIREWALL_H__
+
+#include <arpa/inet.h>
+#include "helper-firewall.h"
+
+typedef stc_cb_ret_e
+(*firewall_chain_cb)(const firewall_chain_s *info, void *user_data);
+
+typedef stc_cb_ret_e
+(*firewall_rule_cb)(const firewall_rule_s *info, void *user_data);
+
+stc_error_e table_firewall_insert_lock(char *name, int state);
+stc_error_e table_firewall_update_lock(char *name, int state);
+stc_error_e table_firewall_get_lock(char *name, int *state);
+
+stc_error_e table_firewall_insert_chain(firewall_chain_s *info);
+stc_error_e table_firewall_delete_chain(firewall_chain_s *info);
+stc_error_e table_firewall_flush_chain(firewall_chain_s *info);
+stc_error_e table_firewall_update_chain(firewall_chain_s *info);
+stc_error_e table_firewall_foreach_chain(firewall_chain_cb info_cb,
+                                      void *user_data);
+
+stc_error_e table_firewall_insert_rule(firewall_rule_s *info);
+stc_error_e table_firewall_delete_rule(firewall_rule_s *info);
+stc_error_e table_firewall_update_rule(firewall_rule_s *info);
+stc_error_e table_firewall_foreach_rule(firewall_rule_cb info_cb,
+                                      void *user_data);
+
+stc_error_e table_firewall_prepare(sqlite3 *db);
+void table_firewall_finalize(void);
+
+#endif /*__TABLE_FIREWALL_H__ */
diff --git a/src/database/tables/table-firewall.c b/src/database/tables/table-firewall.c
new file mode 100755 (executable)
index 0000000..3c811c7
--- /dev/null
@@ -0,0 +1,843 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This file implements restrictions entity handler methods.
+ *
+ * @file        table-restrictions.c
+ */
+
+#include "stc-db.h"
+#include "db-internal.h"
+#include "table-firewall.h"
+
+#define BUF_SIZE_FOR_IP   64
+
+/* DELETE statements */
+#define DELETE_FIREWALL_CHAIN "DELETE FROM fw_chains " \
+       "WHERE chain = ?"
+
+#define DELETE_FIREWALL_RULE "DELETE FROM fw_rules " \
+       "WHERE key = ?"
+
+#define DELETE_FIREWALL_RULE_PER_CHAIN "DELETE FROM fw_rules " \
+       "WHERE chain = ?"
+
+/* SELECT statements */
+#define SELECT_FIREWALL_LOCK "SELECT state FROM fw_lock " \
+       "WHERE name = ?"
+
+#define SELECT_FIREWALL_CHAIN "SELECT chain, " \
+       "target, priority FROM fw_chains"
+
+#define SELECT_FIREWALL_RULE "SELECT key, " \
+       "chain, direction, s_ip_type, d_ip_type, s_port_type, " \
+       "d_port_type, protocol, family, s_ip1, s_ip2, d_ip1, d_ip2, " \
+       "s_port1, s_port2, d_port1, d_port2, ifname, target, identifier " \
+       "FROM fw_rules"
+
+#define SELECT_FIREWALL_RULE_PER_CHAIN "SELECT key, " \
+       "chain, direction, s_ip_type, d_ip_type, s_port_type, " \
+       "d_port_type, protocol, family, s_ip1, s_ip2, d_ip1, d_ip2, " \
+       "s_port1, s_port2, d_port1, d_port2, ifname, target, identifier " \
+       "FROM fw_rules INDEXED BY rules_index " \
+       "WHERE chain = ?"
+
+/* UPDATE statement */
+#define UPDATE_FIREWALL_LOCK "UPDATE fw_lock " \
+       "SET state = ? WHERE name = ?"
+
+#define UPDATE_FIREWALL_CHAIN "UPDATE fw_chains " \
+       "SET target = ?, priority = ? " \
+       "WHERE chain = ?"
+
+#define UPDATE_FIREWALL_RULE "UPDATE fw_rules " \
+       "SET chain = ?, direction = ?, s_ip_type = ?, d_ip_type = ?, " \
+       "s_port_type = ?, d_port_type = ?, protocol = ?, family = ?, " \
+       "s_ip1 = ?, s_ip2 = ?, d_ip1 = ?, d_ip2 = ?, s_port1 = ?, " \
+       "s_port2 = ?, d_port1 = ?, d_port2 = ?, ifname = ?, " \
+       "target = ?, identifier = ? " \
+       "WHERE key = ?"
+
+/* INSERT statement */
+#define INSERT_FIREWALL_LOCK "INSERT INTO fw_lock " \
+       "(name, state) VALUES (?, ?)"
+
+#define INSERT_FIREWALL_CHAIN "INSERT INTO fw_chains " \
+       "(chain, target, priority) " \
+       "VALUES (?, ?, ?)"
+
+#define INSERT_FIREWALL_RULE "INSERT INTO fw_rules " \
+       "(key, chain, direction, s_ip_type, d_ip_type, s_port_type, " \
+       "d_port_type, protocol, family, s_ip1, s_ip2, d_ip1, d_ip2, " \
+       "s_port1, s_port2, d_port1, d_port2, ifname, target, identifier) " \
+       "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+
+static void __finalize_delete(void);
+
+#define PREPARE_DELETE(stm, query) do { \
+       rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL); \
+       if (rc != SQLITE_OK) { \
+               stm = NULL; \
+               __finalize_delete(); \
+               STC_LOGE("Failed to prepare \"%s\" query" \
+                        , query); \
+               return rc; \
+       } \
+} while (0)
+
+static void __finalize_select(void);
+
+#define PREPARE_SELECT(stm, query) do { \
+       rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL); \
+       if (rc != SQLITE_OK) { \
+               stm = NULL; \
+               __finalize_select(); \
+               STC_LOGE("Failed to prepare \"%s\" query" \
+                        , query); \
+               return rc; \
+       } \
+} while (0)
+
+static void __finalize_update(void);
+
+#define PREPARE_UPDATE(stm, query) do { \
+       rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL); \
+       if (rc != SQLITE_OK) { \
+               stm = NULL; \
+               __finalize_update(); \
+               STC_LOGE("Failed to prepare \"%s\" query" \
+                        , query); \
+               return rc; \
+       } \
+} while (0)
+
+static void __finalize_insert(void);
+
+#define PREPARE_INSERT(stm, query) do { \
+       rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL); \
+       if (rc != SQLITE_OK) { \
+               stm = NULL; \
+               __finalize_insert(); \
+               STC_LOGE("Failed to prepare \"%s\" query" \
+                        , query); \
+               return rc; \
+       } \
+} while (0)
+
+#define FINALIZE(stm) do { \
+       if (stm) { \
+               sqlite3_finalize(stm); \
+               stm = NULL; \
+       } \
+} while (0)
+
+/* DELETE statements */
+static sqlite3_stmt *delete_fw_chain;
+static sqlite3_stmt *delete_fw_rule;
+static sqlite3_stmt *delete_fw_rule_per_chain;
+
+/* SELECT statements */
+static sqlite3_stmt *select_fw_lock;
+static sqlite3_stmt *select_fw_chain;
+static sqlite3_stmt *select_fw_rule;
+static sqlite3_stmt *select_fw_rule_per_chain;
+
+/* UPDATE statements */
+static sqlite3_stmt *update_fw_lock;
+static sqlite3_stmt *update_fw_chain;
+static sqlite3_stmt *update_fw_rule;
+
+/* INSERT statements */
+static sqlite3_stmt *insert_fw_lock;
+static sqlite3_stmt *insert_fw_chain;
+static sqlite3_stmt *insert_fw_rule;
+
+static int __prepare_delete(sqlite3 *db)
+{
+       __STC_LOG_FUNC_ENTER__;
+       int rc;
+       static int initialized;
+
+       if (initialized) {
+               __STC_LOG_FUNC_EXIT__;
+               return SQLITE_OK;
+       }
+
+       PREPARE_DELETE(delete_fw_chain, DELETE_FIREWALL_CHAIN);
+       PREPARE_DELETE(delete_fw_rule, DELETE_FIREWALL_RULE);
+       PREPARE_DELETE(delete_fw_rule_per_chain, DELETE_FIREWALL_RULE_PER_CHAIN);
+
+       initialized = 1;
+       __STC_LOG_FUNC_EXIT__;
+       return rc;
+}
+
+static void __finalize_delete(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       FINALIZE(delete_fw_chain);
+       FINALIZE(delete_fw_rule);
+       FINALIZE(delete_fw_rule_per_chain);
+
+       __STC_LOG_FUNC_EXIT__;
+}
+
+static int __prepare_select(sqlite3 *db)
+{
+       __STC_LOG_FUNC_ENTER__;
+       int rc;
+       static int initialized;
+
+       if (initialized) {
+               __STC_LOG_FUNC_EXIT__;
+               return SQLITE_OK;
+       }
+
+       PREPARE_SELECT(select_fw_lock, SELECT_FIREWALL_LOCK);
+       PREPARE_SELECT(select_fw_chain, SELECT_FIREWALL_CHAIN);
+       PREPARE_SELECT(select_fw_rule, SELECT_FIREWALL_RULE);
+       PREPARE_SELECT(select_fw_rule_per_chain, SELECT_FIREWALL_RULE_PER_CHAIN);
+
+       initialized = 1;
+       __STC_LOG_FUNC_EXIT__;
+       return rc;
+}
+
+static void __finalize_select(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       FINALIZE(select_fw_lock);
+       FINALIZE(select_fw_chain);
+       FINALIZE(select_fw_rule);
+       FINALIZE(select_fw_rule_per_chain);
+
+       __STC_LOG_FUNC_EXIT__;
+}
+
+static int __prepare_update(sqlite3 *db)
+{
+       __STC_LOG_FUNC_ENTER__;
+       int rc;
+       static int initialized;
+
+       if (initialized) {
+               __STC_LOG_FUNC_EXIT__;
+               return SQLITE_OK;
+       }
+
+       PREPARE_UPDATE(update_fw_lock, UPDATE_FIREWALL_LOCK);
+       PREPARE_UPDATE(update_fw_chain, UPDATE_FIREWALL_CHAIN);
+       PREPARE_UPDATE(update_fw_rule, UPDATE_FIREWALL_RULE);
+
+       initialized = 1;
+       __STC_LOG_FUNC_EXIT__;
+       return rc;
+}
+
+static void __finalize_update(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       FINALIZE(update_fw_lock);
+       FINALIZE(update_fw_chain);
+       FINALIZE(update_fw_rule);
+
+       __STC_LOG_FUNC_EXIT__;
+}
+
+static int __prepare_insert(sqlite3 *db)
+{
+       __STC_LOG_FUNC_ENTER__;
+       int rc;
+       static int initialized;
+
+       if (initialized) {
+               __STC_LOG_FUNC_EXIT__;
+               return SQLITE_OK;
+       }
+
+       PREPARE_INSERT(insert_fw_lock, INSERT_FIREWALL_LOCK);
+       PREPARE_INSERT(insert_fw_chain, INSERT_FIREWALL_CHAIN);
+       PREPARE_INSERT(insert_fw_rule, INSERT_FIREWALL_RULE);
+
+       initialized = 1;
+       __STC_LOG_FUNC_EXIT__;
+       return rc;
+}
+
+static void __finalize_insert(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       FINALIZE(insert_fw_lock);
+       FINALIZE(insert_fw_chain);
+       FINALIZE(insert_fw_rule);
+
+       __STC_LOG_FUNC_EXIT__;
+}
+
+stc_error_e table_firewall_insert_lock(char *name, int state)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = insert_fw_lock;
+
+       DB_ACTION(sqlite3_bind_text(stmt, 1, name ? name : "",
+                                       -1, SQLITE_TRANSIENT));
+       DB_ACTION(sqlite3_bind_int(stmt, 2, state));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to insert firewall lock state: %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall lock state inserted [%d]", state);
+
+handle_error:
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_update_lock(char *name, int state)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = update_fw_lock;
+
+       DB_ACTION(sqlite3_bind_int(stmt, 1, state));
+       DB_ACTION(sqlite3_bind_text(stmt, 2, name ? name : "",
+                                       -1, SQLITE_TRANSIENT));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to update firewall lock state: %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall lock state updated [%d]", state);
+
+handle_error:
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_get_lock(char *name, int *state)
+{
+       int rc;
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = select_fw_lock;
+
+       if (!name)
+               return STC_ERROR_DB_FAILED;
+
+       DB_ACTION(sqlite3_bind_text(stmt, 1, name,
+                                       -1, SQLITE_TRANSIENT));
+
+       rc = sqlite3_step(stmt);
+
+       switch (rc) {
+       case SQLITE_DONE:
+               break;
+       case SQLITE_ROW:
+               *state = sqlite3_column_int(stmt, 0);
+               break;
+       case SQLITE_ERROR:
+       default:
+               STC_LOGE("Failed to get firewall lock state: %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall lock state [%d]", *state);
+
+handle_error:
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_insert_chain(firewall_chain_s *info)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = insert_fw_chain;
+
+       if (!info) {
+               error_code = STC_ERROR_INVALID_PARAMETER;
+               goto handle_error;
+       }
+
+       DB_ACTION(sqlite3_bind_text(stmt, 1, info->chain ? info->chain : "",
+                                       -1, SQLITE_TRANSIENT));
+       DB_ACTION(sqlite3_bind_int(stmt, 2, info->target));
+       DB_ACTION(sqlite3_bind_int(stmt, 3, info->priority));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to insert firewall chain: %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall chain inserted [%s]", info->chain);
+
+handle_error:
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_delete_chain(firewall_chain_s *info)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = delete_fw_chain;
+
+       if (!info) {
+               error_code = STC_ERROR_INVALID_PARAMETER;
+               goto handle_error;
+       }
+
+       DB_ACTION(sqlite3_bind_text(stmt, 1, info->chain ? info->chain : "",
+                                   -1, SQLITE_TRANSIENT));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to delete firewall chain %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall chain deleted [%s]", info->chain);
+
+handle_error:
+
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_flush_chain(firewall_chain_s *info)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = delete_fw_rule_per_chain;
+
+       if (!info) {
+               error_code = STC_ERROR_INVALID_PARAMETER;
+               goto handle_error;
+       }
+
+       DB_ACTION(sqlite3_bind_text(stmt, 1, info->chain ? info->chain : "",
+                                   -1, SQLITE_TRANSIENT));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to flush firewall chain %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall chain flushed [%s]", info->chain);
+
+handle_error:
+
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_update_chain(firewall_chain_s *info)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = update_fw_chain;
+
+       if (!info) {
+               error_code = STC_ERROR_INVALID_PARAMETER;
+               goto handle_error;
+       }
+
+       DB_ACTION(sqlite3_bind_int(stmt, 1, info->target));
+       DB_ACTION(sqlite3_bind_int(stmt, 2, info->priority));
+       DB_ACTION(sqlite3_bind_text(stmt, 3, info->chain ? info->chain : "",
+                                       -1, SQLITE_TRANSIENT));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to update firewall chain: %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall chain updated [%s]", info->chain);
+
+handle_error:
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_foreach_chain(firewall_chain_cb info_cb,
+                                      void *user_data)
+{
+       firewall_chain_s info;
+       int rc;
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = select_fw_chain;
+
+       do {
+               rc = sqlite3_step(stmt);
+
+               memset(&info, 0, sizeof(info));
+
+               switch (rc) {
+               case SQLITE_DONE:
+                       break;
+               case SQLITE_ROW:
+                       info.chain = (char *)sqlite3_column_text(stmt, 0);
+                       info.target = sqlite3_column_int(stmt, 1);
+                       info.priority = sqlite3_column_int(stmt, 2);
+
+                       if (info_cb(&info, user_data) == STC_CANCEL)
+                               rc = SQLITE_DONE;
+                       break;
+               case SQLITE_ERROR:
+               default:
+                       STC_LOGE("Failed to enumerate firewall chains: %s\n",
+                                sqlite3_errmsg(stc_db_get_database()));
+
+                       error_code = STC_ERROR_DB_FAILED;
+               }
+       } while (rc == SQLITE_ROW);
+
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_insert_rule(firewall_rule_s *info)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       char buf[BUF_SIZE_FOR_IP];
+       sqlite3_stmt *stmt = insert_fw_rule;
+
+       if (!info) {
+               error_code = STC_ERROR_INVALID_PARAMETER;
+               goto handle_error;
+       }
+
+       DB_ACTION(sqlite3_bind_int64(stmt, 1, info->key));
+       DB_ACTION(sqlite3_bind_text(stmt, 2, info->chain ? info->chain : "",
+                                       -1, SQLITE_TRANSIENT));
+       DB_ACTION(sqlite3_bind_int(stmt, 3, info->direction));
+       DB_ACTION(sqlite3_bind_int(stmt, 4, info->s_ip_type));
+       DB_ACTION(sqlite3_bind_int(stmt, 5, info->d_ip_type));
+       DB_ACTION(sqlite3_bind_int(stmt, 6, info->s_port_type));
+       DB_ACTION(sqlite3_bind_int(stmt, 7, info->d_port_type));
+       DB_ACTION(sqlite3_bind_int(stmt, 8, info->protocol));
+       DB_ACTION(sqlite3_bind_int(stmt, 9, info->family));
+       if (info->family == STC_FW_FAMILY_V4) {
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x", info->s_ip1.Ipv4.s_addr);
+               DB_ACTION(sqlite3_bind_text(stmt, 10, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x", info->s_ip2.Ipv4.s_addr);
+               DB_ACTION(sqlite3_bind_text(stmt, 11, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x", info->d_ip1.Ipv4.s_addr);
+               DB_ACTION(sqlite3_bind_text(stmt, 12, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x", info->d_ip2.Ipv4.s_addr);
+               DB_ACTION(sqlite3_bind_text(stmt, 13, buf, -1, SQLITE_TRANSIENT));
+       } else if (info->family == STC_FW_FAMILY_V6) {
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                       info->s_ip1.Ipv6.s6_addr32[0], info->s_ip1.Ipv6.s6_addr32[1],
+                       info->s_ip1.Ipv6.s6_addr32[2], info->s_ip1.Ipv6.s6_addr32[3]);
+               DB_ACTION(sqlite3_bind_text(stmt, 10, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                       info->s_ip2.Ipv6.s6_addr32[0], info->s_ip2.Ipv6.s6_addr32[1],
+                       info->s_ip2.Ipv6.s6_addr32[2], info->s_ip2.Ipv6.s6_addr32[3]);
+               DB_ACTION(sqlite3_bind_text(stmt, 11, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                       info->d_ip1.Ipv6.s6_addr32[0], info->d_ip1.Ipv6.s6_addr32[1],
+                       info->d_ip1.Ipv6.s6_addr32[2], info->d_ip1.Ipv6.s6_addr32[3]);
+               DB_ACTION(sqlite3_bind_text(stmt, 12, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                       info->d_ip2.Ipv6.s6_addr32[0], info->d_ip2.Ipv6.s6_addr32[1],
+                       info->d_ip2.Ipv6.s6_addr32[2], info->d_ip2.Ipv6.s6_addr32[3]);
+               DB_ACTION(sqlite3_bind_text(stmt, 13, buf, -1, SQLITE_TRANSIENT));
+       } else {
+               DB_ACTION(sqlite3_bind_text(stmt, 10, "", -1, SQLITE_TRANSIENT));
+               DB_ACTION(sqlite3_bind_text(stmt, 11, "", -1, SQLITE_TRANSIENT));
+               DB_ACTION(sqlite3_bind_text(stmt, 12, "", -1, SQLITE_TRANSIENT));
+               DB_ACTION(sqlite3_bind_text(stmt, 13, "", -1, SQLITE_TRANSIENT));
+       }
+       DB_ACTION(sqlite3_bind_int(stmt, 14, info->s_port1));
+       DB_ACTION(sqlite3_bind_int(stmt, 15, info->s_port2));
+       DB_ACTION(sqlite3_bind_int(stmt, 16, info->d_port1));
+       DB_ACTION(sqlite3_bind_int(stmt, 17, info->d_port2));
+       DB_ACTION(sqlite3_bind_text(stmt, 18, info->ifname ? info->ifname : "",
+                                       -1, SQLITE_TRANSIENT));
+       DB_ACTION(sqlite3_bind_int(stmt, 19, info->target));
+       DB_ACTION(sqlite3_bind_text(stmt, 20, info->identifier ? info->identifier : "",
+                                       -1, SQLITE_TRANSIENT));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to insert firewall rule: %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall rule inserted [%s]", info->chain);
+
+handle_error:
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_delete_rule(firewall_rule_s *info)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = delete_fw_rule;
+
+       if (!info) {
+               error_code = STC_ERROR_INVALID_PARAMETER;
+               goto handle_error;
+       }
+
+       DB_ACTION(sqlite3_bind_int64(stmt, 1, info->key));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to delete firewall rule %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall rule deleted [%s]", info->chain);
+
+handle_error:
+
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_update_rule(firewall_rule_s *info)
+{
+       stc_error_e error_code = STC_ERROR_NONE;
+       char buf[BUF_SIZE_FOR_IP];
+       sqlite3_stmt *stmt = update_fw_rule;
+
+       if (!info) {
+               error_code = STC_ERROR_INVALID_PARAMETER;
+               goto handle_error;
+       }
+
+       DB_ACTION(sqlite3_bind_text(stmt, 1, info->chain ? info->chain : "",
+                                       -1, SQLITE_TRANSIENT));
+       DB_ACTION(sqlite3_bind_int(stmt, 2, info->direction));
+       DB_ACTION(sqlite3_bind_int(stmt, 3, info->s_ip_type));
+       DB_ACTION(sqlite3_bind_int(stmt, 4, info->d_ip_type));
+       DB_ACTION(sqlite3_bind_int(stmt, 5, info->s_port_type));
+       DB_ACTION(sqlite3_bind_int(stmt, 6, info->d_port_type));
+       DB_ACTION(sqlite3_bind_int(stmt, 7, info->protocol));
+       DB_ACTION(sqlite3_bind_int(stmt, 8, info->family));
+       if (info->family == STC_FW_FAMILY_V4) {
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x", info->s_ip1.Ipv4.s_addr);
+               DB_ACTION(sqlite3_bind_text(stmt, 9, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x", info->s_ip2.Ipv4.s_addr);
+               DB_ACTION(sqlite3_bind_text(stmt, 10, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x", info->d_ip1.Ipv4.s_addr);
+               DB_ACTION(sqlite3_bind_text(stmt, 11, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x", info->d_ip2.Ipv4.s_addr);
+               DB_ACTION(sqlite3_bind_text(stmt, 12, buf, -1, SQLITE_TRANSIENT));
+       } else if (info->family == STC_FW_FAMILY_V6) {
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                       info->s_ip1.Ipv6.s6_addr32[0], info->s_ip1.Ipv6.s6_addr32[1],
+                       info->s_ip1.Ipv6.s6_addr32[2], info->s_ip1.Ipv6.s6_addr32[3]);
+               DB_ACTION(sqlite3_bind_text(stmt, 9, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                       info->s_ip2.Ipv6.s6_addr32[0], info->s_ip2.Ipv6.s6_addr32[1],
+                       info->s_ip2.Ipv6.s6_addr32[2], info->s_ip2.Ipv6.s6_addr32[3]);
+               DB_ACTION(sqlite3_bind_text(stmt, 10, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                       info->d_ip1.Ipv6.s6_addr32[0], info->d_ip1.Ipv6.s6_addr32[1],
+                       info->d_ip1.Ipv6.s6_addr32[2], info->d_ip1.Ipv6.s6_addr32[3]);
+               DB_ACTION(sqlite3_bind_text(stmt, 11, buf, -1, SQLITE_TRANSIENT));
+
+               memset(buf, 0, sizeof(buf));
+               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                       info->d_ip2.Ipv6.s6_addr32[0], info->d_ip2.Ipv6.s6_addr32[1],
+                       info->d_ip2.Ipv6.s6_addr32[2], info->d_ip2.Ipv6.s6_addr32[3]);
+               DB_ACTION(sqlite3_bind_text(stmt, 12, buf, -1, SQLITE_TRANSIENT));
+       } else {
+               DB_ACTION(sqlite3_bind_text(stmt, 9, "", -1, SQLITE_TRANSIENT));
+               DB_ACTION(sqlite3_bind_text(stmt, 10, "", -1, SQLITE_TRANSIENT));
+               DB_ACTION(sqlite3_bind_text(stmt, 11, "", -1, SQLITE_TRANSIENT));
+               DB_ACTION(sqlite3_bind_text(stmt, 12, "", -1, SQLITE_TRANSIENT));
+       }
+       DB_ACTION(sqlite3_bind_int(stmt, 13, info->s_port1));
+       DB_ACTION(sqlite3_bind_int(stmt, 14, info->s_port2));
+       DB_ACTION(sqlite3_bind_int(stmt, 15, info->d_port1));
+       DB_ACTION(sqlite3_bind_int(stmt, 16, info->d_port2));
+       DB_ACTION(sqlite3_bind_text(stmt, 17, info->ifname ? info->ifname : "",
+                                       -1, SQLITE_TRANSIENT));
+       DB_ACTION(sqlite3_bind_int(stmt, 18, info->target));
+       DB_ACTION(sqlite3_bind_text(stmt, 19, info->identifier ? info->identifier : "",
+                                       -1, SQLITE_TRANSIENT));
+       DB_ACTION(sqlite3_bind_int64(stmt, 20, info->key));
+
+       if (sqlite3_step(stmt) != SQLITE_DONE) {
+               STC_LOGE("Failed to update firewall rule %s\n",
+                        sqlite3_errmsg(stc_db_get_database()));
+               error_code = STC_ERROR_DB_FAILED;
+               goto handle_error;
+       }
+
+       STC_LOGD("Firewall rule updated [%s]", info->chain);
+
+handle_error:
+
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_foreach_rule(firewall_rule_cb info_cb,
+                                      void *user_data)
+{
+       firewall_rule_s info;
+       int rc;
+       stc_error_e error_code = STC_ERROR_NONE;
+       sqlite3_stmt *stmt = select_fw_rule;
+
+       do {
+               rc = sqlite3_step(stmt);
+
+               memset(&info, 0, sizeof(info));
+
+               switch (rc) {
+               case SQLITE_DONE:
+                       break;
+               case SQLITE_ROW:
+                       info.key = sqlite3_column_int64(stmt, 0);
+                       info.chain = (char *)sqlite3_column_text(stmt, 1);
+                       info.direction = sqlite3_column_int(stmt, 2);
+                       info.s_ip_type = sqlite3_column_int(stmt, 3);
+                       info.d_ip_type = sqlite3_column_int(stmt, 4);
+                       info.s_port_type = sqlite3_column_int(stmt, 5);
+                       info.d_port_type = sqlite3_column_int(stmt, 6);
+                       info.protocol = sqlite3_column_int(stmt, 7);
+                       info.family = sqlite3_column_int(stmt, 8);
+                       if (info.family == STC_FW_FAMILY_V4) {
+                               sscanf((char *)sqlite3_column_text(stmt, 9), "%08x",
+                                                               &(info.s_ip1.Ipv4.s_addr));
+                               sscanf((char *)sqlite3_column_text(stmt, 10), "%08x",
+                                                               &(info.s_ip2.Ipv4.s_addr));
+                               sscanf((char *)sqlite3_column_text(stmt, 11), "%08x",
+                                                               &(info.d_ip1.Ipv4.s_addr));
+                               sscanf((char *)sqlite3_column_text(stmt, 12), "%08x",
+                                                               &(info.d_ip2.Ipv4.s_addr));
+                       } else if (info.family == STC_FW_FAMILY_V6) {
+                               sscanf((char *)sqlite3_column_text(stmt, 9), "%08x:%08x:%08x:%08x",
+                                       &(info.s_ip1.Ipv6.s6_addr32[0]), &(info.s_ip1.Ipv6.s6_addr32[1]),
+                                       &(info.s_ip1.Ipv6.s6_addr32[2]), &(info.s_ip1.Ipv6.s6_addr32[3]));
+                               sscanf((char *)sqlite3_column_text(stmt, 10), "%08x:%08x:%08x:%08x",
+                                       &(info.s_ip2.Ipv6.s6_addr32[0]), &(info.s_ip2.Ipv6.s6_addr32[1]),
+                                       &(info.s_ip2.Ipv6.s6_addr32[2]), &(info.s_ip2.Ipv6.s6_addr32[3]));
+                               sscanf((char *)sqlite3_column_text(stmt, 11), "%08x:%08x:%08x:%08x",
+                                       &(info.d_ip1.Ipv6.s6_addr32[0]), &(info.d_ip1.Ipv6.s6_addr32[1]),
+                                       &(info.d_ip1.Ipv6.s6_addr32[2]), &(info.d_ip1.Ipv6.s6_addr32[3]));
+                               sscanf((char *)sqlite3_column_text(stmt, 12), "%08x:%08x:%08x:%08x",
+                                       &(info.d_ip2.Ipv6.s6_addr32[0]), &(info.d_ip2.Ipv6.s6_addr32[1]),
+                                       &(info.d_ip2.Ipv6.s6_addr32[2]), &(info.d_ip2.Ipv6.s6_addr32[3]));
+                       }
+                       info.s_port1 = sqlite3_column_int(stmt, 13);
+                       info.s_port2 = sqlite3_column_int(stmt, 14);
+                       info.d_port1 = sqlite3_column_int(stmt, 15);
+                       info.d_port2 = sqlite3_column_int(stmt, 16);
+                       info.ifname = (char *)sqlite3_column_text(stmt, 17);
+                       info.target = sqlite3_column_int(stmt, 18);
+                       info.identifier = (char *)sqlite3_column_text(stmt, 19);
+
+                       if (info_cb(&info, user_data) == STC_CANCEL)
+                               rc = SQLITE_DONE;
+                       break;
+               case SQLITE_ERROR:
+               default:
+                       STC_LOGE("Failed to enumerate firewall rules: %s\n",
+                                sqlite3_errmsg(stc_db_get_database()));
+
+                       error_code = STC_ERROR_DB_FAILED;
+               }
+       } while (rc == SQLITE_ROW);
+
+       sqlite3_reset(stmt);
+       return error_code;
+}
+
+stc_error_e table_firewall_prepare(sqlite3 *db)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       stc_error_e error_code = STC_ERROR_NONE;
+
+       if (db == NULL) {
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_FAIL;
+       }
+
+       DB_ACTION(__prepare_delete(db));
+       DB_ACTION(__prepare_select(db));
+       DB_ACTION(__prepare_update(db));
+       DB_ACTION(__prepare_insert(db));
+
+handle_error:
+
+       __STC_LOG_FUNC_EXIT__;
+       return error_code;
+}
+
+void table_firewall_finalize(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+       __finalize_delete();
+       __finalize_select();
+       __finalize_update();
+       __finalize_insert();
+       __STC_LOG_FUNC_EXIT__;
+}
index 49856b4..6f2fe03 100755 (executable)
@@ -594,7 +594,7 @@ stc_error_e table_statistics_insert(stc_db_classid_iftype_key *stat_key,
 {
        stc_error_e error_code = STC_ERROR_NONE;
        sqlite3_stmt *stmt = update_statistics_query;
-       stc_hw_net_protocol_type_e hw_net_protocol_type = STC_PROTOCOL_NONE;
+       stc_hw_net_protocol_type_e hw_net_protocol_type = STC_PROTOCOL_UNKNOWN;
 
        if (!stat->rcv_count && !stat->snd_count) {
                error_code = STC_ERROR_INVALID_PARAMETER;
diff --git a/src/helper/helper-firewall.c b/src/helper/helper-firewall.c
new file mode 100755 (executable)
index 0000000..aab377f
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stc-manager-gdbus.h"
+#include "helper-firewall.h"
+
+#define STC_FIREWALL_DBUS_SERVICE                    "net.stc.iptables"
+#define STC_FIREWALL_DBUS_RULE_INTERFACE             STC_FIREWALL_DBUS_SERVICE ".rule"
+#define STC_FIREWALL_DBUS_CHAIN_INTERFACE            STC_FIREWALL_DBUS_SERVICE ".chain"
+#define STC_FIREWALL_DBUS_RULE_PATH                  "/net/stc/iptables/rule"
+#define STC_FIREWALL_DBUS_CHAIN_PATH                 "/net/stc/iptables/chain"
+
+#define STC_FIREWALL_DBUS_METHOD_ADD_CHAIN           "IptAddChain"
+#define STC_FIREWALL_DBUS_METHOD_REMOVE_CHAIN        "IptRemoveChain"
+#define STC_FIREWALL_DBUS_METHOD_FLUSH_CHAIN         "IptFlushChain"
+#define STC_FIREWALL6_DBUS_METHOD_ADD_CHAIN          "Ip6tAddChain"
+#define STC_FIREWALL6_DBUS_METHOD_REMOVE_CHAIN       "Ip6tRemoveChain"
+#define STC_FIREWALL6_DBUS_METHOD_FLUSH_CHAIN        "Ip6tFlushChain"
+
+#define STC_FIREWALL_DBUS_METHOD_ADD_RULE            "IptAddRule"
+#define STC_FIREWALL_DBUS_METHOD_REMOVE_RULE         "IptRemoveRule"
+#define STC_FIREWALL6_DBUS_METHOD_ADD_RULE           "Ip6tAddRule"
+#define STC_FIREWALL6_DBUS_METHOD_REMOVE_RULE        "Ip6tRemoveRule"
+
+#define BUF_SIZE_FOR_IP 64
+
+#define RULE_CHAIN      "chain"
+#define RULE_DIRECTION  "type"
+#define RULE_IFNAME     "ifname"
+#define RULE_PROTOCOL   "protocol"
+#define RULE_TARGET     "target"
+
+#define RULE_FAMILY     "family"
+#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"
+#define RULE_SPORTTYPE  "s_port_type"
+#define RULE_SPORT1     "s_port1"
+#define RULE_SPORT2     "s_port2"
+#define RULE_DPORTTYPE  "d_port_type"
+#define RULE_DPORT1     "d_port1"
+#define RULE_DPORT2     "d_port2"
+
+static void __fw_add_rule_info_to_builder(GVariantBuilder *builder,
+                                      firewall_rule_s *rule)
+{
+       if (builder == NULL || rule == NULL)
+               return;
+
+       g_variant_builder_add(builder, "{sv}", RULE_CHAIN,
+                       g_variant_new_string(rule->chain));
+
+       if (rule->direction != STC_FW_DIRECTION_NONE)
+               g_variant_builder_add(builder, "{sv}", RULE_DIRECTION,
+                               g_variant_new_uint16(rule->direction));
+
+       if (rule->s_ip_type != STC_FW_IP_NONE)
+               g_variant_builder_add(builder, "{sv}", RULE_SIPTYPE,
+                               g_variant_new_uint16(rule->s_ip_type));
+
+       if (rule->d_ip_type != STC_FW_IP_NONE)
+               g_variant_builder_add(builder, "{sv}", RULE_DIPTYPE,
+                               g_variant_new_uint16(rule->d_ip_type));
+
+       if (rule->s_port_type != STC_FW_PORT_NONE)
+               g_variant_builder_add(builder, "{sv}", RULE_SPORTTYPE,
+                               g_variant_new_uint16(rule->s_port_type));
+
+       if (rule->d_port_type != STC_FW_PORT_NONE)
+               g_variant_builder_add(builder, "{sv}", RULE_DPORTTYPE,
+                               g_variant_new_uint16(rule->d_port_type));
+
+       if (rule->protocol != STC_FW_PROTOCOL_NONE)
+               g_variant_builder_add(builder, "{sv}", RULE_PROTOCOL,
+                               g_variant_new_uint16(rule->protocol));
+
+       switch (rule->family) {
+       case STC_FW_FAMILY_V4:
+               if (rule->s_ip1.Ipv4.s_addr)
+                       g_variant_builder_add(builder, "{sv}", RULE_SIP1,
+                                       g_variant_new_uint32(rule->s_ip1.Ipv4.s_addr));
+
+               if (rule->s_ip2.Ipv4.s_addr)
+                       g_variant_builder_add(builder, "{sv}", RULE_SIP2,
+                                       g_variant_new_uint32(rule->s_ip2.Ipv4.s_addr));
+
+               if (rule->d_ip1.Ipv4.s_addr)
+                       g_variant_builder_add(builder, "{sv}", RULE_DIP1,
+                                       g_variant_new_uint32(rule->d_ip1.Ipv4.s_addr));
+
+               if (rule->d_ip2.Ipv4.s_addr)
+                       g_variant_builder_add(builder, "{sv}", RULE_DIP2,
+                                       g_variant_new_uint32(rule->d_ip2.Ipv4.s_addr));
+
+               break;
+       case STC_FW_FAMILY_V6:
+               {
+                       char buf[BUF_SIZE_FOR_IP];
+
+                       if (rule->s_ip1.Ipv6.s6_addr32[0] || rule->s_ip1.Ipv6.s6_addr32[1] ||
+                               rule->s_ip1.Ipv6.s6_addr32[2] || rule->s_ip1.Ipv6.s6_addr32[3]) {
+                               memset(buf, 0, sizeof(buf));
+                               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                                       rule->s_ip1.Ipv6.s6_addr32[0], rule->s_ip1.Ipv6.s6_addr32[1],
+                                       rule->s_ip1.Ipv6.s6_addr32[2], rule->s_ip1.Ipv6.s6_addr32[3]);
+                               g_variant_builder_add(builder, "{sv}", RULE_SIP1,
+                                                       g_variant_new_string(buf));
+                       }
+
+                       if (rule->s_ip2.Ipv6.s6_addr32[0] || rule->s_ip2.Ipv6.s6_addr32[1] ||
+                               rule->s_ip2.Ipv6.s6_addr32[2] || rule->s_ip2.Ipv6.s6_addr32[3]) {
+                               memset(buf, 0, sizeof(buf));
+                               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                                       rule->s_ip2.Ipv6.s6_addr32[0], rule->s_ip2.Ipv6.s6_addr32[1],
+                                       rule->s_ip2.Ipv6.s6_addr32[2], rule->s_ip2.Ipv6.s6_addr32[3]);
+                               g_variant_builder_add(builder, "{sv}", RULE_SIP2,
+                                                       g_variant_new_string(buf));
+                       }
+
+                       if (rule->d_ip1.Ipv6.s6_addr32[0] || rule->d_ip1.Ipv6.s6_addr32[1] ||
+                               rule->d_ip1.Ipv6.s6_addr32[2] || rule->d_ip1.Ipv6.s6_addr32[3]) {
+                               memset(buf, 0, sizeof(buf));
+                               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                                       rule->d_ip1.Ipv6.s6_addr32[0], rule->d_ip1.Ipv6.s6_addr32[1],
+                                       rule->d_ip1.Ipv6.s6_addr32[2], rule->d_ip1.Ipv6.s6_addr32[3]);
+                               g_variant_builder_add(builder, "{sv}", RULE_DIP1,
+                                                       g_variant_new_string(buf));
+                       }
+
+                       if (rule->d_ip2.Ipv6.s6_addr32[0] || rule->d_ip2.Ipv6.s6_addr32[1] ||
+                               rule->d_ip2.Ipv6.s6_addr32[2] || rule->d_ip2.Ipv6.s6_addr32[3]) {
+                               memset(buf, 0, sizeof(buf));
+                               snprintf(buf, sizeof(buf), "%08x:%08x:%08x:%08x",
+                                       rule->d_ip2.Ipv6.s6_addr32[0], rule->d_ip2.Ipv6.s6_addr32[1],
+                                       rule->d_ip2.Ipv6.s6_addr32[2], rule->d_ip2.Ipv6.s6_addr32[3]);
+                               g_variant_builder_add(builder, "{sv}", RULE_DIP2,
+                                                       g_variant_new_string(buf));
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+
+       if (rule->s_port1)
+               g_variant_builder_add(builder, "{sv}", RULE_SPORT1,
+                               g_variant_new_uint32(rule->s_port1));
+
+       if (rule->s_port2)
+               g_variant_builder_add(builder, "{sv}", RULE_SPORT2,
+                               g_variant_new_uint32(rule->s_port2));
+
+       if (rule->d_port1)
+               g_variant_builder_add(builder, "{sv}", RULE_DPORT1,
+                               g_variant_new_uint32(rule->d_port1));
+
+       if (rule->d_port2)
+               g_variant_builder_add(builder, "{sv}", RULE_DPORT2,
+                               g_variant_new_uint32(rule->d_port2));
+
+       if (rule->ifname)
+               g_variant_builder_add(builder, "{sv}", RULE_IFNAME,
+                               g_variant_new_string(rule->ifname));
+
+       if (rule->target_str)
+               g_variant_builder_add(builder, "{sv}", RULE_TARGET,
+                               g_variant_new_string(rule->target_str));
+}
+
+static int __fw_add_chain(GDBusConnection *connection,
+                               const char *chain)
+{
+       int result = 0;
+       GVariant *message = NULL;
+
+       message = stc_manager_gdbus_call_sync(connection,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_CHAIN_PATH,
+                                             STC_FIREWALL_DBUS_CHAIN_INTERFACE,
+                                             STC_FIREWALL_DBUS_METHOD_ADD_CHAIN,
+                                             g_variant_new("(s)", chain));
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully added firewall chain [%d:%s]", result, chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw6_add_chain(GDBusConnection *connection,
+                                const char *chain)
+{
+       int result = 0;
+       GVariant *message = NULL;
+
+       message = stc_manager_gdbus_call_sync(connection,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_CHAIN_PATH,
+                                             STC_FIREWALL_DBUS_CHAIN_INTERFACE,
+                                             STC_FIREWALL6_DBUS_METHOD_ADD_CHAIN,
+                                             g_variant_new("(s)", chain));
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully added firewall6 chain [%d:%s]", result, chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw_remove_chain(GDBusConnection *connection,
+                                  const char *chain)
+{
+       int result = 0;
+       GVariant *message = NULL;
+
+       message = stc_manager_gdbus_call_sync(connection,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_CHAIN_PATH,
+                                             STC_FIREWALL_DBUS_CHAIN_INTERFACE,
+                                             STC_FIREWALL_DBUS_METHOD_REMOVE_CHAIN,
+                                             g_variant_new("(s)", chain));
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully removed firewall chain [%d:%s]", result, chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw6_remove_chain(GDBusConnection *connection,
+                                   const char *chain)
+{
+       int result = 0;
+       GVariant *message = NULL;
+
+       message = stc_manager_gdbus_call_sync(connection,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_CHAIN_PATH,
+                                             STC_FIREWALL_DBUS_CHAIN_INTERFACE,
+                                             STC_FIREWALL6_DBUS_METHOD_REMOVE_CHAIN,
+                                             g_variant_new("(s)", chain));
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully removed firewall6 chain [%d:%s]", result, chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw_flush_chain(GDBusConnection *connection,
+                                 const char *chain)
+{
+       int result = 0;
+       GVariant *message = NULL;
+
+       message = stc_manager_gdbus_call_sync(connection,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_CHAIN_PATH,
+                                             STC_FIREWALL_DBUS_CHAIN_INTERFACE,
+                                             STC_FIREWALL_DBUS_METHOD_FLUSH_CHAIN,
+                                             g_variant_new("(s)", chain));
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully flushed firewall chain [%d:%s]", result, chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw6_flush_chain(GDBusConnection *connection,
+                                  const char *chain)
+{
+       int result = 0;
+       GVariant *message = NULL;
+
+       message = stc_manager_gdbus_call_sync(connection,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_CHAIN_PATH,
+                                             STC_FIREWALL_DBUS_CHAIN_INTERFACE,
+                                             STC_FIREWALL6_DBUS_METHOD_FLUSH_CHAIN,
+                                             g_variant_new("(s)", chain));
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully flushed firewall6 chain [%d:%s]", result, chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw_set_chain(firewall_chain_s *chain)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+       firewall_rule_s rule;
+       memset(&rule, 0, sizeof(firewall_rule_s));
+
+       switch (chain->target) {
+       case STC_FW_CHAIN_TARGET_INPUT:
+               rule.chain = g_strdup(FIREWALL_CHAIN_TARGET_IN);
+               break;
+       case STC_FW_CHAIN_TARGET_OUTPUT:
+               rule.chain = g_strdup(FIREWALL_CHAIN_TARGET_OUT);
+               break;
+       default:
+               return STC_ERROR_INVALID_PARAMETER;
+       }
+
+       rule.target_str = g_strdup(chain->chain);
+       ret = firewall_rule_add(&rule);
+
+       g_free(rule.chain);
+       g_free(rule.target_str);
+
+       return ret;
+}
+
+static int __fw_unset_chain(firewall_chain_s *chain)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+       firewall_rule_s rule;
+       memset(&rule, 0, sizeof(firewall_rule_s));
+
+       switch (chain->target) {
+       case STC_FW_CHAIN_TARGET_INPUT:
+               rule.chain = g_strdup(FIREWALL_CHAIN_TARGET_IN);
+               break;
+       case STC_FW_CHAIN_TARGET_OUTPUT:
+               rule.chain = g_strdup(FIREWALL_CHAIN_TARGET_OUT);
+               break;
+       default:
+               return STC_ERROR_INVALID_PARAMETER;
+       }
+
+       rule.target_str = g_strdup(chain->chain);
+       ret = firewall_rule_remove(&rule);
+
+       g_free(rule.chain);
+       g_free(rule.target_str);
+
+       return ret;
+}
+
+static int __fw_add_rule(GDBusConnection *connection,
+                              firewall_rule_s *rule)
+{
+       int result = 0;
+       GVariantBuilder *builder = NULL;
+       GVariant *params = NULL;
+       GVariant *message = NULL;
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       __fw_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,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_RULE_PATH,
+                                             STC_FIREWALL_DBUS_RULE_INTERFACE,
+                                             STC_FIREWALL_DBUS_METHOD_ADD_RULE,
+                                             params);
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully added firewall rule [%d:%s]",
+                               result, rule->chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw6_add_rule(GDBusConnection *connection,
+                               firewall_rule_s *rule)
+{
+       int result = 0;
+       GVariantBuilder *builder = NULL;
+       GVariant *params = NULL;
+       GVariant *message = NULL;
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       __fw_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,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_RULE_PATH,
+                                             STC_FIREWALL_DBUS_RULE_INTERFACE,
+                                             STC_FIREWALL6_DBUS_METHOD_ADD_RULE,
+                                             params);
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully added firewall6 rule [%d:%s]",
+                               result, rule->chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw_remove_rule(GDBusConnection *connection,
+                                 firewall_rule_s *rule)
+{
+       int result = 0;
+       GVariantBuilder *builder = NULL;
+       GVariant *params = NULL;
+       GVariant *message = NULL;
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       __fw_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,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_RULE_PATH,
+                                             STC_FIREWALL_DBUS_RULE_INTERFACE,
+                                             STC_FIREWALL_DBUS_METHOD_REMOVE_RULE,
+                                             params);
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully removed firewall rule [%d:%s]",
+                               result, rule->chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+static int __fw6_remove_rule(GDBusConnection *connection,
+                                  firewall_rule_s *rule)
+{
+       int result = 0;
+       GVariantBuilder *builder = NULL;
+       GVariant *params = NULL;
+       GVariant *message = NULL;
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       __fw_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,
+                                             STC_FIREWALL_DBUS_SERVICE,
+                                             STC_FIREWALL_DBUS_RULE_PATH,
+                                             STC_FIREWALL_DBUS_RULE_INTERFACE,
+                                             STC_FIREWALL6_DBUS_METHOD_REMOVE_RULE,
+                                             params);
+
+       if (message == NULL) {
+               STC_LOGE("Failed to invoke dbus method");
+               return STC_ERROR_FAIL;
+       }
+
+       g_variant_get(message, "(i)", &result);
+       STC_LOGD("Successfully removed firewall6 rule [%d:%s]",
+                               result, rule->chain);
+       g_variant_unref(message);
+
+       return STC_ERROR_NONE;
+}
+
+stc_error_e firewall_chain_add(firewall_chain_s *chain)
+{
+       __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__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       ret = __fw_add_chain(stc->connection, chain->chain);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__;
+               return ret;
+       }
+
+       ret = __fw6_add_chain(stc->connection, chain->chain);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__;
+               return ret;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
+
+stc_error_e firewall_chain_remove(firewall_chain_s *chain)
+{
+       __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__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       ret = __fw_remove_chain(stc->connection, chain->chain);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__;
+               return ret;
+       }
+
+       ret = __fw6_remove_chain(stc->connection, chain->chain);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__;
+               return ret;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
+
+stc_error_e firewall_chain_flush(firewall_chain_s *chain)
+{
+       __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__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       ret = __fw_flush_chain(stc->connection, chain->chain);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__;
+               return ret;
+       }
+
+       ret = __fw6_flush_chain(stc->connection, chain->chain);
+       if (ret != STC_ERROR_NONE) {
+               __STC_LOG_FUNC_EXIT__;
+               return ret;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
+
+stc_error_e firewall_chain_set(firewall_chain_s *chain)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       stc_error_e ret = STC_ERROR_NONE;
+       ret = __fw_set_chain(chain);
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
+
+stc_error_e firewall_chain_unset(firewall_chain_s *chain)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       stc_error_e ret = STC_ERROR_NONE;
+       ret = __fw_unset_chain(chain);
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
+
+stc_error_e firewall_rule_add(firewall_rule_s *rule)
+{
+       __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__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       switch (rule->family) {
+       case STC_FW_FAMILY_V4:
+               ret = __fw_add_rule(stc->connection, rule);
+               if (ret != STC_ERROR_NONE) {
+                       __STC_LOG_FUNC_EXIT__;
+                       return ret;
+               }
+               break;
+       case STC_FW_FAMILY_V6:
+               ret = __fw6_add_rule(stc->connection, rule);
+               if (ret != STC_ERROR_NONE) {
+                       __STC_LOG_FUNC_EXIT__;
+                       return ret;
+               }
+               break;
+       default:
+               ret = __fw_add_rule(stc->connection, rule);
+               if (ret != STC_ERROR_NONE) {
+                       __STC_LOG_FUNC_EXIT__;
+                       return ret;
+               }
+
+               ret = __fw6_add_rule(stc->connection, rule);
+               if (ret != STC_ERROR_NONE) {
+                       __STC_LOG_FUNC_EXIT__;
+                       return ret;
+               }
+               break;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
+
+stc_error_e firewall_rule_remove(firewall_rule_s *rule)
+{
+       __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__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       switch (rule->family) {
+       case STC_FW_FAMILY_V4:
+               ret = __fw_remove_rule(stc->connection, rule);
+               if (ret != STC_ERROR_NONE) {
+                       __STC_LOG_FUNC_EXIT__;
+                       return ret;
+               }
+               break;
+       case STC_FW_FAMILY_V6:
+               ret = __fw6_remove_rule(stc->connection, rule);
+               if (ret != STC_ERROR_NONE) {
+                       __STC_LOG_FUNC_EXIT__;
+                       return ret;
+               }
+               break;
+       default:
+               ret = __fw_remove_rule(stc->connection, rule);
+               if (ret != STC_ERROR_NONE) {
+                       __STC_LOG_FUNC_EXIT__;
+                       return ret;
+               }
+
+               ret = __fw6_remove_rule(stc->connection, rule);
+               if (ret != STC_ERROR_NONE) {
+                       __STC_LOG_FUNC_EXIT__;
+                       return ret;
+               }
+               break;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
diff --git a/src/helper/helper-firewall.h b/src/helper/helper-firewall.h
new file mode 100755 (executable)
index 0000000..8a1dbea
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __STC_HELPER_FIREWALL_H__
+#define __STC_HELPER_FIREWALL_H__
+
+#include <arpa/inet.h>
+
+#include "stc-manager.h"
+#include "stc-error.h"
+
+#define FIREWALL_CHAIN_TARGET_IN     "STC_IN"
+#define FIREWALL_CHAIN_TARGET_OUT    "STC_OUT"
+
+#define FIREWALL_RULE_TARGET_ACCEPT  "ACCEPT"
+#define FIREWALL_RULE_TARGET_DROP    "DROP"
+#define FIREWALL_RULE_TARGET_LOG     "LOG"
+
+typedef enum {
+       FIREWALL_UNKONWN,
+       FIREWALL_UNLOCKED,
+       FIREWALL_LOCKED
+} firewall_lock_e;
+
+typedef union {
+       struct in_addr Ipv4;
+       struct in6_addr Ipv6;
+} ip_addr_u;
+
+typedef struct {
+       char *chain;
+       stc_fw_chain_target_e target;
+       guint priority;
+} firewall_chain_s;
+
+typedef struct {
+       guint key;
+       char *chain;
+       stc_fw_direction_e direction;
+       stc_fw_ip_type_e s_ip_type;
+       stc_fw_ip_type_e d_ip_type;
+       stc_fw_port_type_e s_port_type;
+       stc_fw_port_type_e d_port_type;
+       stc_fw_protocol_type_e protocol;
+       stc_fw_family_type_e family;
+       ip_addr_u s_ip1;
+       ip_addr_u s_ip2;
+       ip_addr_u d_ip1;
+       ip_addr_u d_ip2;
+       guint s_port1;
+       guint s_port2;
+       guint d_port1;
+       guint d_port2;
+       char *ifname;
+       stc_fw_rule_target_e target;
+       char *target_str;
+       char *identifier;
+} firewall_rule_s;
+
+stc_error_e firewall_chain_add(firewall_chain_s *chain);
+stc_error_e firewall_chain_remove(firewall_chain_s *chain);
+stc_error_e firewall_chain_flush(firewall_chain_s *chain);
+stc_error_e firewall_chain_set(firewall_chain_s *chain);
+stc_error_e firewall_chain_unset(firewall_chain_s *chain);
+
+stc_error_e firewall_rule_add(firewall_rule_s *rule);
+stc_error_e firewall_rule_remove(firewall_rule_s *rule);
+
+#endif /*__STC_HELPER_FIREWALL_H__*/
index 81cab4a..cfd8aaf 100755 (executable)
@@ -50,7 +50,7 @@ static void __add_rule_info_to_builder(GVariantBuilder *builder,
                              g_variant_new_string(rule->chain));
 
        g_variant_builder_add(builder, "{sv}", RULE_TYPE,
-                             g_variant_new_uint32(rule->direction));
+                             g_variant_new_uint16(rule->direction));
 
        if (rule->ifname)
                g_variant_builder_add(builder, "{sv}", RULE_IFNAME,
index b73e29f..13db25b 100755 (executable)
@@ -25,6 +25,7 @@
 #define STC_FRWD_CHAIN    "STC_FRWD"
 
 typedef enum {
+       IPTABLES_DIRECTION_NONE,
        IPTABLES_DIRECTION_IN,
        IPTABLES_DIRECTION_OUT
 } iptables_rule_direction_e;
index 4c12965..3923daf 100755 (executable)
@@ -456,7 +456,8 @@ static stc_error_e exec_iptables_cmd(nfacct_rule_s *rule)
        iptables_rule.target = g_strdup(get_iptables_jump(rule->jump));
        iptables_rule.chain = g_strdup(get_iptables_chain(rule->iotype));
        iptables_rule.classid = rule->classid;
-       iptables_rule.direction = (rule->iotype & NFACCT_COUNTER_IN) ? 0 : 1;
+       iptables_rule.direction = (rule->iotype & NFACCT_COUNTER_IN) ?
+                                       IPTABLES_DIRECTION_IN : IPTABLES_DIRECTION_OUT;
        iptype = (iptables_ip_type_e)rule->iptype;
 
        if (rule->action == NFACCT_ACTION_DELETE) {
index 6128e02..9a359d4 100755 (executable)
@@ -18,6 +18,7 @@
 #include <openssl/sha.h>
 
 #include "stc-monitor.h"
+#include "stc-firewall.h"
 #include "stc-manager-gdbus.h"
 #include "stc-default-connection.h"
 
@@ -414,6 +415,7 @@ static stc_error_e __get_default_profile(GDBusConnection *connection)
        __print_default_connection_info();
 
        stc_monitor_update_rstn_by_default_connection(&g_default_connection);
+       stc_firewall_update();
 
        return STC_ERROR_NONE;
 }
diff --git a/src/stc-firewall.c b/src/stc-firewall.c
new file mode 100755 (executable)
index 0000000..b0a66bb
--- /dev/null
@@ -0,0 +1,1551 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stc-db.h"
+#include "table-firewall.h"
+#include "helper-firewall.h"
+#include "stc-firewall.h"
+#include "stc-manager-gdbus.h"
+
+#define IDENTIFIER_LEN     512
+
+#define LOCK_NAME          "admin"
+
+#define CHAIN_NAME         "chain"
+#define CHAIN_TARGET       "target"
+#define CHAIN_PRIORITY     "priority"
+
+#define RULE_CHAIN         "chain"
+#define RULE_DIRECTION     "direction"
+#define RULE_SIPTYPE       "s_ip_type"
+#define RULE_DIPTYPE       "d_ip_type"
+#define RULE_SPORTTYPE     "s_port_type"
+#define RULE_DPORTTYPE     "d_port_type"
+#define RULE_PROTOCOL      "protocol"
+#define RULE_FAMILY        "family"
+#define RULE_SIP1          "s_ip1"
+#define RULE_SIP2          "s_ip2"
+#define RULE_DIP1          "d_ip1"
+#define RULE_DIP2          "d_ip2"
+#define RULE_SPORT1        "s_port1"
+#define RULE_SPORT2        "s_port2"
+#define RULE_DPORT1        "d_port1"
+#define RULE_DPORT2        "d_port2"
+#define RULE_IFNAME        "ifname"
+#define RULE_TARGET        "target"
+#define RULE_IDENTIFIER    "identifier"
+#define RULE_KEY           "key"
+
+#define RULE_TARGET_ACCEPT "ACCEPT"
+#define RULE_TARGET_DROP   "DROP"
+#define RULE_TARGET_LOG    "LOG"
+
+#define FIREWALL_DBUS_ERROR_NAME "net.stc.firewall.Error.Failed"
+
+#define STC_FIREWALL_DBUS_REPLY_ERROR(invocation, err_num) \
+       g_dbus_method_invocation_return_dbus_error((invocation), \
+                                                  FIREWALL_DBUS_ERROR_NAME, \
+                                                  stc_err_strs[-(err_num)])
+
+#define STC_FIREWALL_CHECK_LOCK_STATE(invocation) do { \
+       if (g_lock_state == FIREWALL_LOCKED) { \
+               STC_LOGD("Firewall is locked");  \
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, \
+                                               STC_ERROR_PERMISSION_DENIED); \
+               __STC_LOG_FUNC_EXIT__; \
+               return TRUE; \
+       } \
+} while (0)
+
+static const gchar *stc_err_strs[] = {
+       "ERROR_NONE",
+       "FAIL",
+       "DB_FAILED",
+       "OUT_OF_MEMORY",
+       "INVALID_PARAMETER",
+       "NO_DATA",
+       "ALREADY_DATA",
+       "UNINITIALIZED",
+       "PERMISSION_DENIED",
+       "NOTIMPL"
+};
+
+static GHashTable *g_firewalls = NULL;
+static int g_lock_state = FIREWALL_UNKONWN;
+static uint g_chain_priority = 0;
+
+static void __fw_rule_copy(firewall_rule_s *rule,
+                               const firewall_rule_s *info)
+{
+       if (info->chain) {
+               FREE(rule->chain);
+               rule->chain = g_strdup(info->chain);
+       }
+
+       rule->direction = info->direction;
+       rule->s_ip_type = info->s_ip_type;
+       rule->d_ip_type = info->d_ip_type;
+       rule->s_port_type = info->s_port_type;
+       rule->d_port_type = info->d_port_type;
+       rule->protocol = info->protocol;
+       rule->family = info->family;
+
+       rule->s_ip1 = info->s_ip1;
+       rule->s_ip2 = info->s_ip2;
+       rule->d_ip1 = info->d_ip1;
+       rule->d_ip2 = info->d_ip2;
+
+       rule->s_port1 = info->s_port1;
+       rule->s_port2 = info->s_port2;
+       rule->d_port1 = info->d_port1;
+       rule->d_port2 = info->d_port2;
+
+       if (info->ifname) {
+               FREE(rule->ifname);
+               rule->ifname = g_strdup(info->ifname);
+       }
+
+       rule->target = info->target;
+
+       if (info->target_str) {
+               FREE(rule->target_str);
+               rule->target_str = g_strdup(info->target_str);
+       }
+
+       if (info->identifier) {
+               FREE(rule->identifier);
+               rule->identifier = g_strdup(info->identifier);
+       }
+
+       rule->key = info->key;
+}
+
+static void __fw_rule_make_key(firewall_rule_s *rule,
+                               firewall_rule_s *info)
+{
+       GString *str;
+
+       if (!rule->chain)
+               return;
+
+       str = g_string_sized_new(IDENTIFIER_LEN);
+       if (!str)
+               return;
+
+       g_string_append_printf(str, "%s", rule->chain);
+
+       g_string_append_printf(str, "_%u%u%u%u%u%u%u", rule->direction,
+               rule->s_ip_type, rule->d_ip_type, rule->s_port_type,
+               rule->d_port_type, rule->protocol, rule->family);
+
+       if (rule->family == STC_FW_FAMILY_V4) {
+               g_string_append_printf(str, "_");
+               g_string_append_printf(str, "%08x", rule->s_ip1.Ipv4.s_addr);
+               g_string_append_printf(str, "%08x", rule->s_ip2.Ipv4.s_addr);
+
+               g_string_append_printf(str, "_");
+               g_string_append_printf(str, "%08x", rule->d_ip1.Ipv4.s_addr);
+               g_string_append_printf(str, "%08x", rule->d_ip2.Ipv4.s_addr);
+       } else if (rule->family == STC_FW_FAMILY_V6) {
+               g_string_append_printf(str, "_");
+               g_string_append_printf(str, "%08x", rule->s_ip1.Ipv6.s6_addr32[0]);
+               g_string_append_printf(str, "%08x", rule->s_ip1.Ipv6.s6_addr32[1]);
+               g_string_append_printf(str, "%08x", rule->s_ip1.Ipv6.s6_addr32[2]);
+               g_string_append_printf(str, "%08x", rule->s_ip1.Ipv6.s6_addr32[3]);
+               g_string_append_printf(str, "%08x", rule->s_ip2.Ipv6.s6_addr32[0]);
+               g_string_append_printf(str, "%08x", rule->s_ip2.Ipv6.s6_addr32[1]);
+               g_string_append_printf(str, "%08x", rule->s_ip2.Ipv6.s6_addr32[2]);
+               g_string_append_printf(str, "%08x", rule->s_ip2.Ipv6.s6_addr32[3]);
+
+               g_string_append_printf(str, "_");
+               g_string_append_printf(str, "%08x", rule->d_ip1.Ipv6.s6_addr32[0]);
+               g_string_append_printf(str, "%08x", rule->d_ip1.Ipv6.s6_addr32[1]);
+               g_string_append_printf(str, "%08x", rule->d_ip1.Ipv6.s6_addr32[2]);
+               g_string_append_printf(str, "%08x", rule->d_ip1.Ipv6.s6_addr32[3]);
+               g_string_append_printf(str, "%08x", rule->d_ip2.Ipv6.s6_addr32[0]);
+               g_string_append_printf(str, "%08x", rule->d_ip2.Ipv6.s6_addr32[1]);
+               g_string_append_printf(str, "%08x", rule->d_ip2.Ipv6.s6_addr32[2]);
+               g_string_append_printf(str, "%08x", rule->d_ip2.Ipv6.s6_addr32[3]);
+       }
+
+       g_string_append_printf(str, "_%04x", rule->s_port1);
+       g_string_append_printf(str, "%04x", rule->s_port2);
+
+       g_string_append_printf(str, "_%04x", rule->d_port1);
+       g_string_append_printf(str, "%04x", rule->d_port2);
+
+       g_string_append_printf(str, "_%s", (rule->ifname) ? rule->ifname : "");
+       g_string_append_printf(str, "_%u", rule->target);
+
+       rule->identifier = g_string_free(str, FALSE);
+       rule->key = g_str_hash(rule->identifier);
+
+       info->identifier = g_strdup(rule->identifier);
+       info->key = rule->key;
+
+       STC_LOGD("Identifier [%s]", rule->identifier);
+       STC_LOGD("Key [%u]", rule->key);
+}
+
+static void __fw_rule_free(void *data)
+{
+       firewall_rule_s *rule = (firewall_rule_s *)data;
+
+       FREE(rule->chain);
+       FREE(rule->ifname);
+       FREE(rule->identifier);
+       FREE(rule);
+}
+
+static void __fw_data_free(gpointer value)
+{
+       stc_fw_data_s *data = (stc_fw_data_s *)value;
+
+       g_slist_free_full(data->rules, __fw_rule_free);
+       data->rules = NULL;
+
+       FREE(data);
+}
+
+static gint __fw_rule_comp(gconstpointer a, gconstpointer b)
+{
+       firewall_rule_s *data = (firewall_rule_s *)a;
+       firewall_rule_s *rule = (firewall_rule_s *)b;
+
+       if ((data->key == rule->key) &&
+               (g_strcmp0(data->identifier, rule->identifier) == 0))
+               return 0;
+
+       return -1;
+}
+
+static stc_error_e __fw_chain_add(const char *chain)
+{
+       stc_fw_data_s *data;
+       stc_fw_data_s *lookup;
+
+       ret_value_msg_if(g_firewalls == NULL,
+               STC_ERROR_FAIL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, chain);
+       if (lookup) {
+               STC_LOGD("chain already present");
+               return STC_ERROR_ALREADY_DATA;
+       }
+
+       data = MALLOC0(stc_fw_data_s, 1);
+       if (!data) {
+               STC_LOGE("data allocation failed");
+               return STC_ERROR_OUT_OF_MEMORY;
+       }
+
+       data->target = STC_FW_CHAIN_TARGET_NONE;
+       data->priority = 0;
+       data->rules = NULL;
+
+       g_hash_table_insert(g_firewalls, g_strdup(chain), data);
+
+       return STC_ERROR_NONE;
+}
+
+static stc_error_e __fw_chain_remove(const char *chain)
+{
+       stc_fw_data_s *lookup;
+
+       ret_value_msg_if(g_firewalls == NULL,
+               STC_ERROR_FAIL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
+               STC_LOGE("can't be applied bcz chain is set");
+               return STC_ERROR_INVALID_PARAMETER;
+       }
+
+       g_slist_free_full(lookup->rules, __fw_rule_free);
+       lookup->rules = NULL;
+
+       g_hash_table_remove(g_firewalls, chain);
+
+       return STC_ERROR_NONE;
+}
+
+static stc_error_e __fw_chain_flush(const char *chain)
+{
+       stc_fw_data_s *lookup;
+
+       ret_value_msg_if(g_firewalls == NULL,
+               STC_ERROR_FAIL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
+               STC_LOGE("can't be applied bcz chain is set");
+               return STC_ERROR_INVALID_PARAMETER;
+       }
+
+       g_slist_free_full(lookup->rules, __fw_rule_free);
+       lookup->rules = NULL;
+
+       return STC_ERROR_NONE;
+}
+
+static stc_error_e __fw_chain_set(const char *chain, stc_fw_data_s value)
+{
+       stc_fw_data_s *lookup;
+
+       ret_value_msg_if(g_firewalls == NULL,
+               STC_ERROR_FAIL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       lookup->target = value.target;
+       lookup->priority = value.priority;
+
+       return STC_ERROR_NONE;
+}
+
+static stc_fw_data_s *__fw_chain_get(const char *chain)
+{
+       stc_fw_data_s *lookup;
+
+       ret_value_msg_if(g_firewalls == NULL, NULL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return NULL;
+       }
+
+       return lookup;
+}
+
+static stc_error_e __fw_chain_unset(const char *chain)
+{
+       stc_error_e ret = STC_ERROR_NONE;
+       stc_fw_data_s *lookup;
+
+       ret_value_msg_if(g_firewalls == NULL,
+               STC_ERROR_FAIL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       lookup->target = STC_FW_CHAIN_TARGET_NONE;
+       lookup->priority = 0;
+
+       return ret;
+}
+
+static void __fw_chain_make_params(gpointer key, gpointer value,
+                               gpointer user_data)
+{
+       char *chain = (char *)key;
+       stc_fw_data_s *data = (stc_fw_data_s *)value;
+       GVariantBuilder *builder = (GVariantBuilder *)user_data;
+       GVariantBuilder sub_builder;
+
+       g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
+
+       g_variant_builder_add(&sub_builder, "{sv}", CHAIN_NAME,
+                                       g_variant_new_string(chain));
+
+       g_variant_builder_add(&sub_builder, "{sv}", CHAIN_PRIORITY,
+                               g_variant_new_uint32(data->priority));
+
+       g_variant_builder_add(&sub_builder, "{sv}", CHAIN_TARGET,
+                               g_variant_new_uint16(data->target));
+
+       g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
+}
+
+static void __fw_rule_make_params(gpointer data, gpointer user_data)
+{
+       firewall_rule_s *rule = (firewall_rule_s *)data;
+       GVariantBuilder *builder = (GVariantBuilder *)user_data;
+       GVariantBuilder sub_builder;
+
+       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));
+
+       if (rule->direction != STC_FW_DIRECTION_NONE)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_DIRECTION,
+                                       g_variant_new_uint16(rule->direction));
+
+       if (rule->s_ip_type != STC_FW_IP_NONE)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_SIPTYPE,
+                                       g_variant_new_uint16(rule->s_ip_type));
+
+       if (rule->d_ip_type != STC_FW_IP_NONE)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_DIPTYPE,
+                                       g_variant_new_uint16(rule->d_ip_type));
+
+       if (rule->s_port_type != STC_FW_PORT_NONE)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_SPORTTYPE,
+                                       g_variant_new_uint16(rule->s_port_type));
+
+       if (rule->d_port_type != STC_FW_PORT_NONE)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_DPORTTYPE,
+                                       g_variant_new_uint16(rule->d_port_type));
+
+       if (rule->protocol != STC_FW_PROTOCOL_NONE)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_PROTOCOL,
+                                       g_variant_new_uint16(rule->protocol));
+
+       if (rule->family != STC_FW_FAMILY_NONE)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_FAMILY,
+                                       g_variant_new_uint16(rule->family));
+
+       if (rule->family == STC_FW_FAMILY_V4) {
+               char *addr = NULL;
+
+               switch (rule->s_ip_type) {
+               case STC_FW_IP_RANGE:
+               case STC_FW_IP_MASK:
+                       addr = g_try_malloc0(INET_ADDRSTRLEN);
+                       if (addr) {
+                               inet_ntop(AF_INET, &(rule->s_ip2.Ipv4), addr, INET_ADDRSTRLEN);
+                               g_variant_builder_add(&sub_builder, "{sv}", RULE_SIP2,
+                                                       g_variant_new_string(addr));
+                               FREE(addr);
+                       }
+               case STC_FW_IP_SINGLE:
+                       addr = g_try_malloc0(INET_ADDRSTRLEN);
+                       if (addr) {
+                               inet_ntop(AF_INET, &(rule->s_ip1.Ipv4), addr, INET_ADDRSTRLEN);
+                               g_variant_builder_add(&sub_builder, "{sv}", RULE_SIP1,
+                                                       g_variant_new_string(addr));
+                               FREE(addr);
+                       }
+                       break;
+               default:
+                       break;
+               }
+
+               switch (rule->d_ip_type) {
+               case STC_FW_IP_RANGE:
+               case STC_FW_IP_MASK:
+                       addr = g_try_malloc0(INET_ADDRSTRLEN);
+                       if (addr) {
+                               inet_ntop(AF_INET, &(rule->d_ip2.Ipv4), addr, INET_ADDRSTRLEN);
+                               g_variant_builder_add(&sub_builder, "{sv}", RULE_DIP2,
+                                                       g_variant_new_string(addr));
+                               FREE(addr);
+                       }
+               case STC_FW_IP_SINGLE:
+                       addr = g_try_malloc0(INET_ADDRSTRLEN);
+                       if (addr) {
+                               inet_ntop(AF_INET, &(rule->d_ip1.Ipv4), addr, INET_ADDRSTRLEN);
+                               g_variant_builder_add(&sub_builder, "{sv}", RULE_DIP1,
+                                                       g_variant_new_string(addr));
+                               FREE(addr);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       } else if (rule->family == STC_FW_FAMILY_V6) {
+               char *addr = NULL;
+
+               switch (rule->s_ip_type) {
+               case STC_FW_IP_RANGE:
+               case STC_FW_IP_MASK:
+                       addr = g_try_malloc0(INET6_ADDRSTRLEN);
+                       if (addr) {
+                               inet_ntop(AF_INET6, &(rule->s_ip2.Ipv6), addr, INET6_ADDRSTRLEN);
+                               g_variant_builder_add(&sub_builder, "{sv}", RULE_SIP2,
+                                                       g_variant_new_string(addr));
+                               FREE(addr);
+                       }
+               case STC_FW_IP_SINGLE:
+                       addr = g_try_malloc0(INET6_ADDRSTRLEN);
+                       if (addr) {
+                               inet_ntop(AF_INET6, &(rule->s_ip1.Ipv6), addr, INET6_ADDRSTRLEN);
+                               g_variant_builder_add(&sub_builder, "{sv}", RULE_SIP1,
+                                                       g_variant_new_string(addr));
+                               FREE(addr);
+                       }
+                       break;
+               default:
+                       break;
+               }
+
+               switch (rule->d_ip_type) {
+               case STC_FW_IP_RANGE:
+               case STC_FW_IP_MASK:
+                       addr = g_try_malloc0(INET6_ADDRSTRLEN);
+                       if (addr) {
+                               inet_ntop(AF_INET6, &(rule->d_ip2.Ipv6), addr, INET6_ADDRSTRLEN);
+                               g_variant_builder_add(&sub_builder, "{sv}", RULE_DIP2,
+                                                       g_variant_new_string(addr));
+                               FREE(addr);
+                       }
+               case STC_FW_IP_SINGLE:
+                       addr = g_try_malloc0(INET6_ADDRSTRLEN);
+                       if (addr) {
+                               inet_ntop(AF_INET6, &(rule->d_ip1.Ipv6), addr, INET6_ADDRSTRLEN);
+                               g_variant_builder_add(&sub_builder, "{sv}", RULE_DIP1,
+                                                       g_variant_new_string(addr));
+                               FREE(addr);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       g_variant_builder_add(&sub_builder, "{sv}", RULE_SPORT1,
+                               g_variant_new_uint32(rule->s_port1));
+
+       g_variant_builder_add(&sub_builder, "{sv}", RULE_SPORT2,
+                               g_variant_new_uint32(rule->s_port2));
+
+       g_variant_builder_add(&sub_builder, "{sv}", RULE_DPORT1,
+                               g_variant_new_uint32(rule->d_port1));
+
+       g_variant_builder_add(&sub_builder, "{sv}", RULE_DPORT2,
+                               g_variant_new_uint32(rule->d_port2));
+
+       if (rule->ifname)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_IFNAME,
+                                       g_variant_new_string(rule->ifname));
+
+       if (rule->target != STC_FW_RULE_TARGET_NONE)
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_TARGET,
+                                       g_variant_new_uint16(rule->target));
+
+       g_variant_builder_add(&sub_builder, "{sv}", RULE_IDENTIFIER,
+                               g_variant_new_string(rule->identifier));
+
+       g_variant_builder_add(&sub_builder, "{sv}", RULE_KEY,
+                               g_variant_new_uint32(rule->key));
+
+       g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
+}
+
+static void __fw_rule_set_to_chain(gpointer data, gpointer user_data)
+{
+       firewall_rule_s *info = (firewall_rule_s *)data;
+       char *chain = (char *)user_data;
+       firewall_rule_s rule;
+
+       if (chain && (g_strcmp0(info->chain, chain) != 0))
+               return;
+
+       memset(&rule, 0, sizeof(firewall_rule_s));
+       memcpy(&rule, info, sizeof(firewall_rule_s));
+       rule.chain = g_strdup(info->chain);
+       rule.ifname = g_strdup(info->ifname);
+       switch (rule.target) {
+       case STC_FW_RULE_TARGET_ACCEPT:
+               rule.target_str = g_strdup(FIREWALL_RULE_TARGET_ACCEPT);
+               break;
+       case STC_FW_RULE_TARGET_DROP:
+               rule.target_str = g_strdup(FIREWALL_RULE_TARGET_DROP);
+               break;
+       case STC_FW_RULE_TARGET_LOG:
+               rule.target_str = g_strdup(FIREWALL_RULE_TARGET_LOG);
+               break;
+       default:
+               break;
+       }
+
+       firewall_rule_add(&rule);
+
+       FREE(rule.chain);
+       FREE(rule.ifname);
+       FREE(rule.target_str);
+}
+
+static void __fw_foreach_to_make_rule_param(gpointer key, gpointer value,
+                               gpointer user_data)
+{
+       stc_fw_data_s *data = (stc_fw_data_s *)value;
+
+       g_slist_foreach(data->rules, __fw_rule_make_params, user_data);
+}
+
+static void __fw_foreach_to_set_rule_to_chain(gpointer key, gpointer value,
+                               gpointer user_data)
+{
+       stc_fw_data_s *data = (stc_fw_data_s *)value;
+       char *chain = (char *)user_data;
+
+       if (chain || (data->target != STC_FW_CHAIN_TARGET_NONE))
+               g_slist_foreach(data->rules, __fw_rule_set_to_chain, user_data);
+}
+
+static void __fw_foreach_to_set_chain(gpointer key, gpointer value,
+                               gpointer user_data)
+{
+       char *chain = (char *)key;
+       stc_fw_data_s *data = (stc_fw_data_s *)value;
+
+       if (data->target != STC_FW_CHAIN_TARGET_NONE) {
+               firewall_chain_s info;
+               memset(&info, 0, sizeof(firewall_chain_s));
+               info.chain = chain;
+               info.target = data->target;
+               info.priority = data->priority;
+               firewall_chain_set(&info);
+       }
+}
+
+static void __fw_foreach_to_add_chain(gpointer key, gpointer value,
+                               gpointer user_data)
+{
+       char *chain = (char *)key;
+       stc_fw_data_s *data = (stc_fw_data_s *)value;
+
+       if (data->target != STC_FW_CHAIN_TARGET_NONE) {
+               firewall_chain_s info;
+               memset(&info, 0, sizeof(firewall_chain_s));
+               info.chain = chain;
+               info.target = data->target;
+               info.priority = data->priority;
+               firewall_chain_add(&info);
+       }
+}
+
+static void __fw_chain_foreach(GHFunc func, void *user_data)
+{
+       g_hash_table_foreach(g_firewalls, func, user_data);
+}
+
+stc_cb_ret_e __fw_table_chain_info_cb(const firewall_chain_s *info,
+                               void *user_data)
+{
+       stc_fw_data_s *data;
+
+       data = MALLOC0(stc_fw_data_s, 1);
+       if (!data) {
+               STC_LOGE("data allocation failed");
+               return STC_CONTINUE;
+       }
+
+       data->target = info->target;
+       data->priority = info->priority;
+       data->rules = NULL;
+
+       g_hash_table_insert(g_firewalls, g_strdup(info->chain), data);
+
+       return STC_CONTINUE;
+}
+
+stc_cb_ret_e __fw_table_rule_info_cb(const firewall_rule_s *info,
+                               void *user_data)
+{
+       stc_fw_data_s *lookup;
+       firewall_rule_s *rule;
+
+       lookup = g_hash_table_lookup(g_firewalls, info->chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return STC_CONTINUE;
+       }
+
+       rule = MALLOC0(firewall_rule_s, 1);
+       if (!rule) {
+               STC_LOGE("rule allocation failed");
+               return STC_CONTINUE;
+       }
+
+       memset(rule, 0, sizeof(firewall_rule_s));
+       __fw_rule_copy(rule, info);
+
+       lookup->rules = g_slist_append(lookup->rules, rule);
+
+       return STC_CONTINUE;
+}
+
+static stc_error_e __fw_rule_add(firewall_rule_s *info)
+{
+       stc_fw_data_s *lookup;
+       firewall_rule_s *rule;
+       GSList *comp;
+
+       ret_value_msg_if(g_firewalls == NULL,
+               STC_ERROR_FAIL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, info->chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
+               STC_LOGE("can't be applied bcz chain is set");
+               return STC_ERROR_INVALID_PARAMETER;
+       }
+
+       rule = MALLOC0(firewall_rule_s, 1);
+       if (!rule) {
+               STC_LOGE("rule allocation failed");
+               return STC_ERROR_OUT_OF_MEMORY;
+       }
+
+       memset(rule, 0, sizeof(firewall_rule_s));
+       __fw_rule_copy(rule, info);
+       __fw_rule_make_key(rule, info);
+
+       comp = g_slist_find_custom(lookup->rules, rule, __fw_rule_comp);
+       if (comp) {
+               STC_LOGD("rule already present");
+               return STC_ERROR_ALREADY_DATA;
+       }
+
+       lookup->rules = g_slist_append(lookup->rules, rule);
+
+       return STC_ERROR_NONE;
+}
+
+static stc_error_e __fw_rule_remove(const firewall_rule_s *info)
+{
+       stc_fw_data_s *lookup;
+       GSList *rule_list;
+       GSList *comp;
+       firewall_rule_s *rule;
+
+       ret_value_msg_if(g_firewalls == NULL,
+               STC_ERROR_FAIL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, info->chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
+               STC_LOGE("can't be applied bcz chain is set");
+               return STC_ERROR_INVALID_PARAMETER;
+       }
+
+       rule_list = lookup->rules;
+       comp = g_slist_find_custom(rule_list, info, __fw_rule_comp);
+       if (!comp) {
+               STC_LOGD("rule not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       rule = comp->data;
+       lookup->rules = g_slist_remove(lookup->rules, rule);
+       __fw_rule_free(rule);
+
+       return STC_ERROR_NONE;
+}
+
+static stc_error_e __fw_rule_update(const firewall_rule_s *info)
+{
+       stc_fw_data_s *lookup;
+       GSList *rule_list;
+       GSList *comp;
+       firewall_rule_s *rule;
+
+       ret_value_msg_if(g_firewalls == NULL,
+               STC_ERROR_FAIL,
+               "firewall is not initialized!");
+
+       lookup = g_hash_table_lookup(g_firewalls, info->chain);
+       if (!lookup) {
+               STC_LOGE("chain not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
+               STC_LOGE("can't be applied bcz chain is set");
+               return STC_ERROR_INVALID_PARAMETER;
+       }
+
+       rule_list = lookup->rules;
+       comp = g_slist_find_custom(rule_list, info, __fw_rule_comp);
+       if (!comp) {
+               STC_LOGD("rule not found");
+               return STC_ERROR_NO_DATA;
+       }
+
+       rule = comp->data;
+       __fw_rule_copy(rule, info);
+
+       return STC_ERROR_NONE;
+}
+
+static void __fw_rule_extract(const char *key, GVariant *value,
+                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       firewall_rule_s *rule = (firewall_rule_s *)user_data;
+       if (rule == NULL) {
+               __STC_LOG_FUNC_EXIT__;
+               return;
+       }
+
+       if (g_strcmp0(key, RULE_CHAIN) == 0) {
+               guint str_length;
+               const gchar *str = g_variant_get_string(value, &str_length);
+               rule->chain = g_strdup(str);
+               STC_LOGD("%s: [%s]", RULE_CHAIN, rule->chain);
+
+       } else if (g_strcmp0(key, RULE_DIRECTION) == 0) {
+               rule->direction = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DIRECTION, rule->direction);
+
+       } else if (g_strcmp0(key, RULE_SIPTYPE) == 0) {
+               rule->s_ip_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_SIPTYPE, rule->s_ip_type);
+
+       } else if (g_strcmp0(key, RULE_DIPTYPE) == 0) {
+               rule->d_ip_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DIPTYPE, rule->d_ip_type);
+
+       } else if (g_strcmp0(key, RULE_SPORTTYPE) == 0) {
+               rule->s_port_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_SPORTTYPE, rule->s_port_type);
+
+       } else if (g_strcmp0(key, RULE_DPORTTYPE) == 0) {
+               rule->d_port_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DPORTTYPE, rule->d_port_type);
+
+       } else if (g_strcmp0(key, RULE_PROTOCOL) == 0) {
+               rule->protocol = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_PROTOCOL, rule->protocol);
+
+       } else if (g_strcmp0(key, RULE_FAMILY) == 0) {
+               rule->family = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_FAMILY, rule->family);
+
+       } else if (g_strcmp0(key, RULE_SIP1) == 0) {
+               guint str_length;
+               const gchar *str = g_variant_get_string(value, &str_length);
+               if (rule->family == STC_FW_FAMILY_V4) {
+                       inet_pton(AF_INET, str, &(rule->s_ip1.Ipv4));
+                       STC_LOGD("%s: [%08x]", RULE_SIP1, rule->s_ip1.Ipv4.s_addr);
+               } else if (rule->family == STC_FW_FAMILY_V6) {
+                       inet_pton(AF_INET6, str, &(rule->s_ip1.Ipv6));
+                       STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_SIP1,
+                               rule->s_ip1.Ipv6.s6_addr32[0], rule->s_ip1.Ipv6.s6_addr32[1],
+                               rule->s_ip1.Ipv6.s6_addr32[2], rule->s_ip1.Ipv6.s6_addr32[3]);
+               }
+
+       } else if (g_strcmp0(key, RULE_SIP2) == 0) {
+               guint str_length;
+               const gchar *str = g_variant_get_string(value, &str_length);
+               if (rule->family == STC_FW_FAMILY_V4) {
+                       inet_pton(AF_INET, str, &(rule->s_ip2.Ipv4));
+                       STC_LOGD("%s: [%08x]", RULE_SIP2, rule->s_ip2.Ipv4.s_addr);
+               } else if (rule->family == STC_FW_FAMILY_V6) {
+                       inet_pton(AF_INET6, str, &(rule->s_ip2.Ipv6));
+                       STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_SIP2,
+                               rule->s_ip2.Ipv6.s6_addr32[0], rule->s_ip2.Ipv6.s6_addr32[1],
+                               rule->s_ip2.Ipv6.s6_addr32[2], rule->s_ip2.Ipv6.s6_addr32[3]);
+               }
+
+       } else if (g_strcmp0(key, RULE_DIP1) == 0) {
+               guint str_length;
+               const gchar *str = g_variant_get_string(value, &str_length);
+               if (rule->family == STC_FW_FAMILY_V4) {
+                       inet_pton(AF_INET, str, &(rule->d_ip1.Ipv4));
+                       STC_LOGD("%s: [%08x]", RULE_DIP1, rule->d_ip1.Ipv4.s_addr);
+               } else if (rule->family == STC_FW_FAMILY_V6) {
+                       inet_pton(AF_INET6, str, &(rule->d_ip1.Ipv6));
+                       STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_DIP1,
+                               rule->d_ip1.Ipv6.s6_addr32[0], rule->d_ip1.Ipv6.s6_addr32[1],
+                               rule->d_ip1.Ipv6.s6_addr32[2], rule->d_ip1.Ipv6.s6_addr32[3]);
+               }
+
+       } else if (g_strcmp0(key, RULE_DIP2) == 0) {
+               guint str_length;
+               const gchar *str = g_variant_get_string(value, &str_length);
+               if (rule->family == STC_FW_FAMILY_V4) {
+                       inet_pton(AF_INET, str, &(rule->d_ip2.Ipv4));
+                       STC_LOGD("%s: [%08x]", RULE_DIP2, rule->d_ip2.Ipv4.s_addr);
+               } else if (rule->family == STC_FW_FAMILY_V6) {
+                       inet_pton(AF_INET6, str, &(rule->d_ip2.Ipv6));
+                       STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_DIP2,
+                               rule->d_ip2.Ipv6.s6_addr32[0], rule->d_ip2.Ipv6.s6_addr32[1],
+                               rule->d_ip2.Ipv6.s6_addr32[2], rule->d_ip2.Ipv6.s6_addr32[3]);
+               }
+
+       } else if (g_strcmp0(key, RULE_SPORT1) == 0) {
+               rule->s_port1 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_SPORT1, rule->s_port1);
+
+       } else if (g_strcmp0(key, RULE_SPORT2) == 0) {
+               rule->s_port2 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_SPORT2, rule->s_port2);
+
+       } else if (g_strcmp0(key, RULE_DPORT1) == 0) {
+               rule->d_port1 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_DPORT1, rule->d_port1);
+
+       } else if (g_strcmp0(key, RULE_DPORT2) == 0) {
+               rule->d_port2 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_DPORT2, rule->d_port2);
+
+       } else if (g_strcmp0(key, RULE_IFNAME) == 0) {
+               guint str_length;
+               const gchar *str = g_variant_get_string(value, &str_length);
+               rule->ifname = g_strdup(str);
+               STC_LOGD("%s: [%s]", RULE_IFNAME, rule->ifname);
+
+       } else if (g_strcmp0(key, RULE_TARGET) == 0) {
+               rule->target = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_TARGET, rule->target);
+
+       } else if (g_strcmp0(key, RULE_IDENTIFIER) == 0) {
+               guint str_length;
+               const gchar *str = g_variant_get_string(value, &str_length);
+               rule->identifier = g_strdup(str);
+               STC_LOGD("%s: [%s]", RULE_IDENTIFIER, rule->identifier);
+
+       } else if (g_strcmp0(key, RULE_KEY) == 0) {
+               rule->key = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%u]", RULE_KEY, rule->key);
+
+       } else {
+               STC_LOGD("Unknown rule [%s]", key);
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+}
+
+gboolean __validate_fw_rule(firewall_rule_s *rule)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (rule == NULL) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->chain == NULL) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->direction > STC_FW_DIRECTION_OUT) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->s_ip_type > STC_FW_IP_RANGE) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->d_ip_type > STC_FW_IP_RANGE) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->s_port_type > STC_FW_PORT_RANGE) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->d_port_type > STC_FW_PORT_RANGE) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->protocol > STC_FW_PROTOCOL_ALL) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->family > STC_FW_FAMILY_V6) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+void stc_firewall_init(void)
+{
+       int ret = STC_ERROR_NONE;
+
+       g_firewalls = g_hash_table_new_full(g_str_hash,
+                                       g_str_equal, g_free, __fw_data_free);
+
+       ret = table_firewall_get_lock(LOCK_NAME, &g_lock_state);
+       if (ret != STC_ERROR_NONE)
+               table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
+
+       if (g_lock_state == FIREWALL_UNKONWN)
+               g_lock_state = FIREWALL_UNLOCKED;
+
+       table_firewall_foreach_chain(__fw_table_chain_info_cb, NULL);
+       table_firewall_foreach_rule(__fw_table_rule_info_cb, NULL);
+}
+
+void stc_firewall_update(void)
+{
+       __fw_chain_foreach(__fw_foreach_to_add_chain, NULL);
+       __fw_chain_foreach(__fw_foreach_to_set_rule_to_chain, NULL);
+       __fw_chain_foreach(__fw_foreach_to_set_chain, NULL);
+}
+
+void stc_firewall_deinit(void)
+{
+       if (g_firewalls) {
+               g_hash_table_destroy(g_firewalls);
+               g_firewalls = NULL;
+       }
+}
+
+gboolean handle_firewall_lock(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       int ret = STC_ERROR_NONE;
+
+       ret = table_firewall_update_lock(LOCK_NAME, FIREWALL_LOCKED);
+       if (ret != STC_ERROR_NONE)
+               table_firewall_insert_lock(LOCK_NAME, FIREWALL_LOCKED);
+
+       g_lock_state = FIREWALL_LOCKED;
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_unlock(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       int ret = STC_ERROR_NONE;
+
+       ret = table_firewall_update_lock(LOCK_NAME, FIREWALL_UNLOCKED);
+       if (ret != STC_ERROR_NONE)
+               table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
+
+       g_lock_state = FIREWALL_UNLOCKED;
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_get_lock(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       int ret = STC_ERROR_NONE;
+       GVariant *return_parameters = NULL;
+
+       if (g_lock_state == FIREWALL_UNKONWN) {
+               ret = table_firewall_get_lock(LOCK_NAME, &g_lock_state);
+               if (ret != STC_ERROR_NONE)
+                       table_firewall_insert_lock(LOCK_NAME, FIREWALL_UNLOCKED);
+
+               if (g_lock_state == FIREWALL_UNKONWN)
+                       g_lock_state = FIREWALL_UNLOCKED;
+       }
+
+       return_parameters = g_variant_new("(i)", g_lock_state);
+       STC_DBUS_REPLY(invocation, return_parameters);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_add_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       firewall_chain_s info;
+       int ret = STC_ERROR_NONE;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       if (chain == NULL) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       ret = __fw_chain_add(chain);
+       if (ret == STC_ERROR_NONE) {
+               memset(&info, 0, sizeof(firewall_chain_s));
+               info.chain = chain;
+               info.priority = 0;
+               info.target = STC_FW_CHAIN_TARGET_NONE;
+               table_firewall_insert_chain(&info);
+       } else {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_remove_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       firewall_chain_s info;
+       int ret = STC_ERROR_NONE;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       if (chain == NULL) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       ret = __fw_chain_remove(chain);
+       if (ret == STC_ERROR_NONE) {
+               memset(&info, 0, sizeof(firewall_chain_s));
+               info.chain = chain;
+               table_firewall_flush_chain(&info);
+               table_firewall_delete_chain(&info);
+       } else {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_flush_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       firewall_chain_s info;
+       int ret = STC_ERROR_NONE;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       if (chain == NULL) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       ret = __fw_chain_flush(chain);
+       if (ret == STC_ERROR_NONE) {
+               memset(&info, 0, sizeof(firewall_chain_s));
+               info.chain = chain;
+               table_firewall_flush_chain(&info);
+       } else {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_get_all_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       GVariantBuilder *builder = NULL;
+       GVariant *return_parameters = NULL;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
+
+       __fw_chain_foreach(__fw_chain_make_params, builder);
+
+       return_parameters = g_variant_new("(aa{sv})", builder);
+       g_variant_builder_unref(builder);
+
+       DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
+       STC_DBUS_REPLY(invocation, return_parameters);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_set_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       unsigned int target,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       stc_fw_data_s *lookup = NULL;
+       stc_fw_data_s data;
+       firewall_chain_s info;
+       uint priority;
+       int ret = STC_ERROR_NONE;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       if (chain == NULL ||
+               target > STC_FW_CHAIN_TARGET_OUTPUT) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       lookup = __fw_chain_get(chain);
+       if (lookup == NULL) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_NO_DATA);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       if (lookup->target != STC_FW_CHAIN_TARGET_NONE) {
+               STC_LOGE("chain is already set");
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       /* stc-iptables */
+       memset(&info, 0, sizeof(firewall_chain_s));
+       info.chain = chain;
+       info.target = target;
+
+       ret = firewall_chain_add(&info);
+       if (ret != STC_ERROR_NONE) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       __fw_chain_foreach(__fw_foreach_to_set_rule_to_chain, chain);
+
+       ret = firewall_chain_set(&info);
+       if (ret != STC_ERROR_NONE) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+       /* stc-iptables */
+
+       priority = g_chain_priority + 1;
+
+       memset(&data, 0, sizeof(stc_fw_data_s));
+       data.target = target;
+       data.priority = priority;
+
+       ret = __fw_chain_set(chain, data);
+       if (ret == STC_ERROR_NONE) {
+               info.priority = priority;
+               table_firewall_update_chain(&info);
+               g_chain_priority = priority;
+       } else {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_unset_chain(StcFirewall *object,
+                                       GDBusMethodInvocation *invocation,
+                                       gchar *chain,
+                                       void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       stc_fw_data_s *lookup = NULL;
+       firewall_chain_s info;
+       int ret = STC_ERROR_NONE;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       if (chain == NULL) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       lookup = __fw_chain_get(chain);
+       if (lookup == NULL) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_NO_DATA);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       if (lookup->target == STC_FW_CHAIN_TARGET_NONE) {
+               STC_LOGE("chain is not set");
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                               STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       /* stc-iptables */
+       memset(&info, 0, sizeof(firewall_chain_s));
+       info.chain = chain;
+       info.target = lookup->target;
+
+       ret = firewall_chain_unset(&info);
+       if (ret != STC_ERROR_NONE) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       ret = firewall_chain_remove(&info);
+       if (ret != STC_ERROR_NONE) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+       /* stc-iptables */
+
+       ret = __fw_chain_unset(chain);
+       if (ret == STC_ERROR_NONE) {
+               info.target = STC_FW_CHAIN_TARGET_NONE;
+               info.priority = 0;
+               table_firewall_update_chain(&info);
+       } else {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_add_rule(StcFirewall *object,
+                                  GDBusMethodInvocation *invocation,
+                                  GVariant *parameters,
+                                  void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       GVariantIter *iter = NULL;
+       firewall_rule_s *rule;
+       int ret = STC_ERROR_NONE;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       rule = MALLOC0(firewall_rule_s, 1);
+       if (!rule) {
+               STC_LOGE("rule allocation failed");
+               return STC_ERROR_OUT_OF_MEMORY;
+       }
+
+       memset(rule, 0, sizeof(firewall_rule_s));
+
+       g_variant_get(parameters, "a{sv}", &iter);
+       if (iter != NULL) {
+               stc_manager_gdbus_dict_foreach(iter,
+                                              __fw_rule_extract,
+                                              rule);
+               g_variant_iter_free(iter);
+       }
+
+       if (__validate_fw_rule(rule) == FALSE) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                                STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       ret = __fw_rule_add(rule);
+       if (ret == STC_ERROR_NONE) {
+               table_firewall_insert_rule(rule);
+       } else {
+               __fw_rule_free(rule);
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       __fw_rule_free(rule);
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_remove_rule(StcFirewall *object,
+                                  GDBusMethodInvocation *invocation,
+                                  GVariant *parameters,
+                                  void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       GVariantIter *iter = NULL;
+       firewall_rule_s *rule;
+       int ret = STC_ERROR_NONE;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       rule = MALLOC0(firewall_rule_s, 1);
+       if (!rule) {
+               STC_LOGE("rule allocation failed");
+               return STC_ERROR_OUT_OF_MEMORY;
+       }
+
+       memset(rule, 0, sizeof(firewall_rule_s));
+
+       g_variant_get(parameters, "a{sv}", &iter);
+       if (iter != NULL) {
+               stc_manager_gdbus_dict_foreach(iter,
+                                              __fw_rule_extract,
+                                              rule);
+               g_variant_iter_free(iter);
+       }
+
+       if (__validate_fw_rule(rule) == FALSE) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                                STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       ret = __fw_rule_remove(rule);
+       if (ret == STC_ERROR_NONE) {
+               table_firewall_delete_rule(rule);
+       } else {
+               __fw_rule_free(rule);
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       __fw_rule_free(rule);
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_update_rule(StcFirewall *object,
+                                  GDBusMethodInvocation *invocation,
+                                  GVariant *parameters,
+                                  void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       GVariantIter *iter = NULL;
+       firewall_rule_s *rule;
+       int ret = STC_ERROR_NONE;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       rule = MALLOC0(firewall_rule_s, 1);
+       if (!rule) {
+               STC_LOGE("rule allocation failed");
+               return STC_ERROR_OUT_OF_MEMORY;
+       }
+
+       memset(rule, 0, sizeof(firewall_rule_s));
+
+       g_variant_get(parameters, "a{sv}", &iter);
+       if (iter != NULL) {
+               stc_manager_gdbus_dict_foreach(iter,
+                                              __fw_rule_extract,
+                                              rule);
+               g_variant_iter_free(iter);
+       }
+
+       if (__validate_fw_rule(rule) == FALSE) {
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
+                                                STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       ret = __fw_rule_update(rule);
+       if (ret == STC_ERROR_NONE) {
+               table_firewall_update_rule(rule);
+       } else {
+               __fw_rule_free(rule);
+               STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
+               __STC_LOG_FUNC_EXIT__;
+               return TRUE;
+       }
+
+       __fw_rule_free(rule);
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_firewall_get_all_rule(StcFirewall *object,
+                                  GDBusMethodInvocation *invocation,
+                                  void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       GVariantBuilder *builder = NULL;
+       GVariant *return_parameters = NULL;
+
+       STC_FIREWALL_CHECK_LOCK_STATE(invocation);
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
+
+       __fw_chain_foreach(__fw_foreach_to_make_rule_param, builder);
+
+       return_parameters = g_variant_new("(aa{sv})", builder);
+       g_variant_builder_unref(builder);
+
+       DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
+       STC_DBUS_REPLY(invocation, return_parameters);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
index a321a4c..75b93b1 100755 (executable)
@@ -18,6 +18,7 @@
 #include "stc-manager.h"
 #include "stc-statistics.h"
 #include "stc-restriction.h"
+#include "stc-firewall.h"
 #include "stc-default-connection.h"
 #include "stc-manager-plugin-appstatus.h"
 #include "stc-manager-plugin-procfs.h"
@@ -130,6 +131,89 @@ static gboolean __stc_manager_gdbus_restriction_init(stc_s *stc)
        return ret;
 }
 
+static gboolean __stc_manager_gdbus_firewall_init(stc_s *stc)
+{
+       __STC_LOG_FUNC_ENTER__;
+       gboolean ret = TRUE;
+       gchar *s = NULL;
+
+       StcObjectSkeleton *object = NULL;
+       StcFirewall *firewall = NULL;
+       s = g_strdup_printf(STC_DBUS_SERVICE_FIREWALL_PATH);
+
+       /* Add interface to default object path */
+       object = stc_object_skeleton_new(s);
+       g_free(s);
+
+       firewall = stc_firewall_skeleton_new();
+       stc_object_skeleton_set_firewall(object, firewall);
+       g_object_unref(firewall);
+
+       /* Register for method callbacks as signal callbacks */
+
+       g_signal_connect(firewall, "handle-lock",
+                        G_CALLBACK(handle_firewall_lock),
+                        stc);
+
+       g_signal_connect(firewall, "handle-unlock",
+                        G_CALLBACK(handle_firewall_unlock),
+                        stc);
+
+       g_signal_connect(firewall, "handle-get-lock",
+                        G_CALLBACK(handle_firewall_get_lock),
+                        stc);
+
+       g_signal_connect(firewall, "handle-add-chain",
+                        G_CALLBACK(handle_firewall_add_chain),
+                        stc);
+
+       g_signal_connect(firewall, "handle-remove-chain",
+                        G_CALLBACK(handle_firewall_remove_chain),
+                        stc);
+
+       g_signal_connect(firewall, "handle-flush-chain",
+                        G_CALLBACK(handle_firewall_flush_chain),
+                        stc);
+
+       g_signal_connect(firewall, "handle-get-all-chain",
+                        G_CALLBACK(handle_firewall_get_all_chain),
+                        stc);
+
+       g_signal_connect(firewall, "handle-set-chain",
+                        G_CALLBACK(handle_firewall_set_chain),
+                        stc);
+
+       g_signal_connect(firewall, "handle-unset-chain",
+                        G_CALLBACK(handle_firewall_unset_chain),
+                        stc);
+
+       g_signal_connect(firewall, "handle-add-rule",
+                        G_CALLBACK(handle_firewall_add_rule),
+                        stc);
+
+       g_signal_connect(firewall, "handle-remove-rule",
+                        G_CALLBACK(handle_firewall_remove_rule),
+                        stc);
+
+       g_signal_connect(firewall, "handle-update-rule",
+                        G_CALLBACK(handle_firewall_update_rule),
+                        stc);
+
+       g_signal_connect(firewall, "handle-get-all-rule",
+                        G_CALLBACK(handle_firewall_get_all_rule),
+                        stc);
+
+       /* Export the object (@manager takes its own reference to @object) */
+       g_dbus_object_manager_server_export(stc->obj_mgr,
+                                           G_DBUS_OBJECT_SKELETON(object));
+       g_object_unref(object);
+
+       stc->firewall_obj = (gpointer)firewall;
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
+
 static gboolean __stc_manager_gdbus_manager_init(stc_s *stc)
 {
        __STC_LOG_FUNC_ENTER__;
@@ -184,6 +268,11 @@ static void __stc_manager_gdbus_on_bus_acquired(GDBusConnection *connection,
                /* Deinitialize and quit manager */
        }
 
+       if (__stc_manager_gdbus_firewall_init(stc) == FALSE) {
+               STC_LOGE("Cannot signal connect to firewall"); //LCOV_EXCL_LINE
+               /* Deinitialize and quit manager */
+       }
+
        if (__stc_manager_gdbus_manager_init(stc) == FALSE) {
                STC_LOGE("Cannot signal connect to manager"); //LCOV_EXCL_LINE
                /* Deinitialize and quit manager */
@@ -246,6 +335,7 @@ void stc_manager_gdbus_deinit(gpointer stc_data)
 
        stc->statistics_obj = NULL;
        stc->restriction_obj = NULL;
+       stc->firewall_obj = NULL;
        stc->manager_obj = NULL;
        __STC_LOG_FUNC_EXIT__;
 }
index 8317d4f..0da9bf4 100755 (executable)
@@ -25,6 +25,7 @@
 #include "helper-nfacct-rule.h"
 #include "helper-iptables.h"
 #include "stc-monitor.h"
+#include "stc-firewall.h"
 #include "stc-manager-plugin-appstatus.h"
 #include "stc-manager-plugin-exception.h"
 #include "stc-manager-plugin-procfs.h"
@@ -65,6 +66,8 @@ static void __stc_manager_deinit(void)
 
        stc_manager_gdbus_deinit((gpointer)g_stc);
 
+       stc_firewall_deinit();
+
        stc_plugin_appstatus_deinit();
        stc_plugin_exception_deinit();
        stc_plugin_procfs_deinit();
@@ -97,6 +100,8 @@ static stc_s *__stc_manager_init(void)
        stc_plugin_exception_init();
        stc_plugin_procfs_init();
 
+       stc_firewall_init();
+
        err = stc_monitor_init();
        if (err != STC_ERROR_NONE)
                goto handle_error;
index cb3a382..e39575a 100755 (executable)
@@ -34,7 +34,9 @@ static const gchar *stc_err_strs[] = {
        "OUT_OF_MEMORY",
        "INVALID_PARAMETER",
        "NO_DATA",
+       "ALREADY_DATA",
        "UNINITIALIZED",
+       "PERMISSION_DENIED",
        "NOTIMPL"
 };
 
index 70cf48c..f2ff8e9 100755 (executable)
@@ -21,9 +21,6 @@
 
 #define STATISTICS_DBUS_ERROR_NAME "net.stc.statistics.Error.Failed"
 
-#define STC_DBUS_REPLY(invocation, parameters) \
-       g_dbus_method_invocation_return_value((invocation), parameters);
-
 #define STC_STATISTICS_DBUS_REPLY_ERROR(invocation, err_num) \
        g_dbus_method_invocation_return_dbus_error((invocation), \
                                                   STATISTICS_DBUS_ERROR_NAME, \
@@ -36,7 +33,9 @@ static const gchar *stc_err_strs[] = {
        "OUT_OF_MEMORY",
        "INVALID_PARAMETER",
        "NO_DATA",
+       "ALREADY_DATA",
        "UNINITIALIZED",
+       "PERMISSION_DENIED",
        "NOTIMPL"
 };