Separate monitoring function plugin
[platform/core/connectivity/stc-manager.git] / src / stc-firewall.c
index 236169b..64e7abb 100755 (executable)
 #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) \
@@ -125,6 +103,22 @@ static void __fw_rule_copy(firewall_rule_s *rule,
                rule->target_str = g_strdup(info->target_str);
        }
 
+       rule->log_level = info->log_level;
+
+       if (info->log_prefix) {
+               FREE(rule->log_prefix);
+               rule->log_prefix = g_strdup(info->log_prefix);
+       }
+
+       rule->nflog_group = info->nflog_group;
+       rule->nflog_range = info->nflog_range;
+       rule->nflog_threshold = info->nflog_threshold;
+
+       if (info->nflog_prefix) {
+               FREE(rule->nflog_prefix);
+               rule->nflog_prefix = g_strdup(info->nflog_prefix);
+       }
+
        if (info->identifier) {
                FREE(rule->identifier);
                rule->identifier = g_strdup(info->identifier);
@@ -190,14 +184,33 @@ static void __fw_rule_make_key(firewall_rule_s *rule,
        g_string_append_printf(str, "_%s", (rule->ifname) ? rule->ifname : "");
        g_string_append_printf(str, "_%u", rule->target);
 
+       switch (rule->target) {
+       case STC_FW_RULE_TARGET_LOG:
+               g_string_append_printf(str, "_%u", rule->log_level);
+               g_string_append_printf(str, "_%s", rule->log_prefix);
+               break;
+       case STC_FW_RULE_TARGET_NFLOG:
+               g_string_append_printf(str, "_%u", rule->nflog_group);
+               g_string_append_printf(str, "_%s", rule->nflog_prefix);
+               g_string_append_printf(str, "_%u", rule->nflog_range);
+               g_string_append_printf(str, "_%u", rule->nflog_threshold);
+               break;
+       default:
+               break;
+       }
+
+       FREE(rule->identifier);
        rule->identifier = g_string_free(str, FALSE);
        rule->key = g_str_hash(rule->identifier);
 
+       FREE(info->identifier);
        info->identifier = g_strdup(rule->identifier);
        info->key = rule->key;
 
-       STC_LOGD("Identifier [%s]", rule->identifier);
-       STC_LOGD("Key [%u]", rule->key);
+       if (STC_DEBUG_LOG && STC_FW_LOG) {
+               STC_LOGD("Identifier [%s]", rule->identifier);
+               STC_LOGD("Key [%u]", rule->key);
+       }
 }
 
 static void __fw_rule_free(void *data)
@@ -206,6 +219,9 @@ static void __fw_rule_free(void *data)
 
        FREE(rule->chain);
        FREE(rule->ifname);
+       FREE(rule->target_str);
+       FREE(rule->log_prefix);
+       FREE(rule->nflog_prefix);
        FREE(rule->identifier);
        FREE(rule);
 }
@@ -243,13 +259,15 @@ static stc_error_e __fw_chain_add(const char *chain)
 
        lookup = g_hash_table_lookup(g_firewalls, chain);
        if (lookup) {
-               STC_LOGD("chain already present");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGD("chain already present");
                return STC_ERROR_ALREADY_DATA;
        }
 
        data = MALLOC0(stc_fw_data_s, 1);
        if (!data) {
-               STC_LOGE("data allocation failed");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("data allocation failed");
                return STC_ERROR_OUT_OF_MEMORY;
        }
 
@@ -272,12 +290,14 @@ static stc_error_e __fw_chain_remove(const char *chain)
 
        lookup = g_hash_table_lookup(g_firewalls, chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       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");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("can't be applied bcz chain is set");
                return STC_ERROR_INVALID_PARAMETER;
        }
 
@@ -299,12 +319,14 @@ static stc_error_e __fw_chain_flush(const char *chain)
 
        lookup = g_hash_table_lookup(g_firewalls, chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       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");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("can't be applied bcz chain is set");
                return STC_ERROR_INVALID_PARAMETER;
        }
 
@@ -324,7 +346,8 @@ static stc_error_e __fw_chain_set(const char *chain, stc_fw_data_s value)
 
        lookup = g_hash_table_lookup(g_firewalls, chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("chain not found");
                return STC_ERROR_NO_DATA;
        }
 
@@ -343,7 +366,8 @@ static stc_fw_data_s *__fw_chain_get(const char *chain)
 
        lookup = g_hash_table_lookup(g_firewalls, chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("chain not found");
                return NULL;
        }
 
@@ -361,7 +385,8 @@ static stc_error_e __fw_chain_unset(const char *chain)
 
        lookup = g_hash_table_lookup(g_firewalls, chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("chain not found");
                return STC_ERROR_NO_DATA;
        }
 
@@ -437,6 +462,7 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
 
                switch (rule->s_ip_type) {
                case STC_FW_IP_RANGE:
+                       /* fall through */
                case STC_FW_IP_MASK:
                        addr = g_try_malloc0(INET_ADDRSTRLEN);
                        if (addr) {
@@ -445,6 +471,7 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
                                                        g_variant_new_string(addr));
                                FREE(addr);
                        }
+                       /* fall through */
                case STC_FW_IP_SINGLE:
                        addr = g_try_malloc0(INET_ADDRSTRLEN);
                        if (addr) {
@@ -460,6 +487,7 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
 
                switch (rule->d_ip_type) {
                case STC_FW_IP_RANGE:
+                       /* fall through */
                case STC_FW_IP_MASK:
                        addr = g_try_malloc0(INET_ADDRSTRLEN);
                        if (addr) {
@@ -468,6 +496,7 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
                                                        g_variant_new_string(addr));
                                FREE(addr);
                        }
+                       /* fall through */
                case STC_FW_IP_SINGLE:
                        addr = g_try_malloc0(INET_ADDRSTRLEN);
                        if (addr) {
@@ -485,6 +514,7 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
 
                switch (rule->s_ip_type) {
                case STC_FW_IP_RANGE:
+                       /* fall through */
                case STC_FW_IP_MASK:
                        addr = g_try_malloc0(INET6_ADDRSTRLEN);
                        if (addr) {
@@ -493,6 +523,7 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
                                                        g_variant_new_string(addr));
                                FREE(addr);
                        }
+                       /* fall through */
                case STC_FW_IP_SINGLE:
                        addr = g_try_malloc0(INET6_ADDRSTRLEN);
                        if (addr) {
@@ -508,6 +539,7 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
 
                switch (rule->d_ip_type) {
                case STC_FW_IP_RANGE:
+                       /* fall through */
                case STC_FW_IP_MASK:
                        addr = g_try_malloc0(INET6_ADDRSTRLEN);
                        if (addr) {
@@ -516,6 +548,7 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
                                                        g_variant_new_string(addr));
                                FREE(addr);
                        }
+                       /* fall through */
                case STC_FW_IP_SINGLE:
                        addr = g_try_malloc0(INET6_ADDRSTRLEN);
                        if (addr) {
@@ -550,6 +583,33 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
                g_variant_builder_add(&sub_builder, "{sv}", RULE_TARGET,
                                        g_variant_new_uint16(rule->target));
 
+       switch (rule->target) {
+       case STC_FW_RULE_TARGET_LOG:
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_LOG_LEVEL,
+                               g_variant_new_uint16(rule->log_level));
+
+               if (rule->log_prefix)
+                       g_variant_builder_add(&sub_builder, "{sv}", RULE_LOG_PREFIX,
+                                               g_variant_new_string(rule->log_prefix));
+               break;
+       case STC_FW_RULE_TARGET_NFLOG:
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_NFLOG_GROUP,
+                               g_variant_new_uint16(rule->nflog_group));
+
+               if (rule->nflog_prefix)
+                       g_variant_builder_add(&sub_builder, "{sv}", RULE_NFLOG_PREFIX,
+                                               g_variant_new_string(rule->nflog_prefix));
+
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_NFLOG_RANGE,
+                                       g_variant_new_uint16(rule->nflog_range));
+
+               g_variant_builder_add(&sub_builder, "{sv}", RULE_NFLOG_THRESHOLD,
+                                       g_variant_new_uint16(rule->nflog_threshold));
+               break;
+       default:
+               break;
+       }
+
        g_variant_builder_add(&sub_builder, "{sv}", RULE_IDENTIFIER,
                                g_variant_new_string(rule->identifier));
 
@@ -561,36 +621,79 @@ static void __fw_rule_make_params(gpointer data, gpointer user_data)
 
 static void __fw_rule_set_to_chain(gpointer data, gpointer user_data)
 {
-       firewall_rule_s *info = (firewall_rule_s *)data;
+       firewall_rule_s *rule = (firewall_rule_s *)data;
        char *chain = (char *)user_data;
-       firewall_rule_s rule;
 
-       if (chain && (g_strcmp0(info->chain, chain) != 0))
+       if (chain && (g_strcmp0(rule->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) {
+       switch (rule->target) {
        case STC_FW_RULE_TARGET_ACCEPT:
-               rule.target_str = g_strdup(FIREWALL_RULE_TARGET_ACCEPT);
+               FREE(rule->target_str);
+               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);
+               FREE(rule->target_str);
+               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);
+               FREE(rule->target_str);
+               rule->target_str = g_strdup(FIREWALL_RULE_TARGET_LOG);
+               break;
+       case STC_FW_RULE_TARGET_NFLOG:
+               FREE(rule->target_str);
+               rule->target_str = g_strdup(FIREWALL_RULE_TARGET_NFLOG);
                break;
        default:
                break;
        }
 
-       firewall_rule_add(&rule);
+       firewall_rule_append(rule);
+}
+
+static void __fw_rule_print_rules(gpointer data, gpointer user_data)
+{
+       firewall_rule_s *rule = (firewall_rule_s *)data;
+
+       STC_LOGD("[%s][%d][%s][%d][%d][%04x][%04x]"
+               "[%d][%04x][%04x][%d][%s][%d][%s][%d][%d]",
+               rule->chain, rule->direction, rule->ifname,
+               rule->protocol,
+               rule->s_port_type, rule->s_port1, rule->s_port2,
+               rule->d_port_type, rule->d_port1, rule->d_port2,
+               rule->target, rule->target_str,
+               rule->nflog_group, rule->nflog_prefix,
+               rule->nflog_range, rule->nflog_threshold);
+
+       switch (rule->family) {
+       case STC_FW_FAMILY_V4:
+               STC_LOGD("[%d][%d][%08x][%08x][%d][%08x][%08x]",
+                       rule->family,
+                       rule->s_ip_type, rule->s_ip1.Ipv4.s_addr, rule->s_ip2.Ipv4.s_addr,
+                       rule->d_ip_type, rule->d_ip1.Ipv4.s_addr, rule->d_ip2.Ipv4.s_addr);
+               break;
+       case STC_FW_FAMILY_V6:
+               STC_LOGD("[%d][%d][%08x:%08x:%08x:%08x]"
+                       "[%d][%08x:%08x:%08x:%08x]",
+                       rule->family,
+                       rule->s_ip_type,
+                       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],
+                       rule->d_ip_type,
+                       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]);
+               break;
+       default:
+               break;
+       }
+}
+
+static void __fw_foreach_to_print_rule(gpointer key, gpointer value,
+                               gpointer user_data)
+{
+       stc_fw_data_s *data = (stc_fw_data_s *)value;
 
-       FREE(rule.chain);
-       FREE(rule.ifname);
-       FREE(rule.target_str);
+       g_slist_foreach(data->rules, __fw_rule_print_rules, user_data);
 }
 
 static void __fw_foreach_to_make_rule_param(gpointer key, gpointer value,
@@ -655,7 +758,8 @@ stc_cb_ret_e __fw_table_chain_info_cb(const firewall_chain_s *info,
 
        data = MALLOC0(stc_fw_data_s, 1);
        if (!data) {
-               STC_LOGE("data allocation failed");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("data allocation failed");
                return STC_CONTINUE;
        }
 
@@ -676,13 +780,15 @@ stc_cb_ret_e __fw_table_rule_info_cb(const firewall_rule_s *info,
 
        lookup = g_hash_table_lookup(g_firewalls, info->chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("chain not found");
                return STC_CONTINUE;
        }
 
        rule = MALLOC0(firewall_rule_s, 1);
        if (!rule) {
-               STC_LOGE("rule allocation failed");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("rule allocation failed");
                return STC_CONTINUE;
        }
 
@@ -706,18 +812,21 @@ static stc_error_e __fw_rule_add(firewall_rule_s *info)
 
        lookup = g_hash_table_lookup(g_firewalls, info->chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       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");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       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");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("rule allocation failed");
                return STC_ERROR_OUT_OF_MEMORY;
        }
 
@@ -727,7 +836,9 @@ static stc_error_e __fw_rule_add(firewall_rule_s *info)
 
        comp = g_slist_find_custom(lookup->rules, rule, __fw_rule_comp);
        if (comp) {
-               STC_LOGD("rule already present");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGD("rule already present");
+               __fw_rule_free(rule);
                return STC_ERROR_ALREADY_DATA;
        }
 
@@ -749,19 +860,22 @@ static stc_error_e __fw_rule_remove(const firewall_rule_s *info)
 
        lookup = g_hash_table_lookup(g_firewalls, info->chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       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");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       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");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGD("rule not found");
                return STC_ERROR_NO_DATA;
        }
 
@@ -772,12 +886,13 @@ static stc_error_e __fw_rule_remove(const firewall_rule_s *info)
        return STC_ERROR_NONE;
 }
 
-static stc_error_e __fw_rule_update(const firewall_rule_s *info)
+static stc_error_e __fw_rule_update(firewall_rule_s *info)
 {
        stc_fw_data_s *lookup;
        GSList *rule_list;
        GSList *comp;
-       firewall_rule_s *rule;
+       firewall_rule_s *origin_rule;
+       firewall_rule_s *update_rule;
 
        ret_value_msg_if(g_firewalls == NULL,
                STC_ERROR_FAIL,
@@ -785,24 +900,50 @@ static stc_error_e __fw_rule_update(const firewall_rule_s *info)
 
        lookup = g_hash_table_lookup(g_firewalls, info->chain);
        if (!lookup) {
-               STC_LOGE("chain not found");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       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");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       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");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGD("rule not found");
                return STC_ERROR_NO_DATA;
        }
 
-       rule = comp->data;
-       __fw_rule_copy(rule, info);
+       origin_rule = comp->data;
+
+       update_rule = MALLOC0(firewall_rule_s, 1);
+       if (!update_rule) {
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("rule allocation failed");
+               return STC_ERROR_OUT_OF_MEMORY;
+       }
+
+       memset(update_rule, 0, sizeof(firewall_rule_s));
+       __fw_rule_copy(update_rule, info);
+       __fw_rule_make_key(update_rule, info);
+
+       comp = g_slist_find_custom(lookup->rules, update_rule, __fw_rule_comp);
+       if (comp) {
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGD("rule already present");
+               __fw_rule_free(update_rule);
+               return STC_ERROR_ALREADY_DATA;
+       }
+
+       lookup->rules = g_slist_remove(lookup->rules, origin_rule);
+       __fw_rule_free(origin_rule);
+
+       lookup->rules = g_slist_append(lookup->rules, update_rule);
 
        return STC_ERROR_NONE;
 }
@@ -810,8 +951,6 @@ static stc_error_e __fw_rule_update(const firewall_rule_s *info)
 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__;
@@ -853,83 +992,141 @@ static void __fw_rule_extract(const char *key, GVariant *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]);
+               if (rule->s_ip_type != STC_FW_IP_NONE) {
+                       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]);
+               if (rule->s_ip_type != STC_FW_IP_NONE) {
+                       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]);
+               if (rule->d_ip_type != STC_FW_IP_NONE) {
+                       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]);
+               if (rule->d_ip_type != STC_FW_IP_NONE) {
+                       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);
+               if (rule->s_port_type != STC_FW_PORT_NONE) {
+                       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);
+               if (rule->s_port_type != STC_FW_PORT_NONE) {
+                       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);
+               if (rule->d_port_type != STC_FW_PORT_NONE) {
+                       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);
+               if (rule->d_port_type != STC_FW_PORT_NONE) {
+                       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);
+               if (rule->direction != STC_FW_DIRECTION_NONE) {
+                       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_LOG_LEVEL) == 0) {
+               if (rule->target == STC_FW_RULE_TARGET_LOG) {
+                       rule->log_level = g_variant_get_uint16(value);
+                       STC_LOGD("%s: [%u]", RULE_LOG_LEVEL, rule->log_level);
+               }
+
+       } else if (g_strcmp0(key, RULE_LOG_PREFIX) == 0) {
+               if (rule->target == STC_FW_RULE_TARGET_LOG) {
+                       guint str_length;
+                       const gchar *str = g_variant_get_string(value, &str_length);
+                       rule->log_prefix = g_strdup(str);
+                       STC_LOGD("%s: [%s]", RULE_LOG_PREFIX, rule->log_prefix);
+               }
+
+       } else if (g_strcmp0(key, RULE_NFLOG_GROUP) == 0) {
+               if (rule->target == STC_FW_RULE_TARGET_NFLOG) {
+                       rule->nflog_group = g_variant_get_uint16(value);
+                       STC_LOGD("%s: [%u]", RULE_NFLOG_GROUP, rule->nflog_group);
+               }
+
+       } else if (g_strcmp0(key, RULE_NFLOG_PREFIX) == 0) {
+               if (rule->target == STC_FW_RULE_TARGET_NFLOG) {
+                       guint str_length;
+                       const gchar *str = g_variant_get_string(value, &str_length);
+                       rule->nflog_prefix = g_strdup(str);
+                       STC_LOGD("%s: [%s]", RULE_NFLOG_PREFIX, rule->nflog_prefix);
+               }
+
+       } else if (g_strcmp0(key, RULE_NFLOG_RANGE) == 0) {
+               if (rule->target == STC_FW_RULE_TARGET_NFLOG) {
+                       rule->nflog_range = g_variant_get_uint16(value);
+                       STC_LOGD("%s: [%u]", RULE_NFLOG_RANGE, rule->nflog_range);
+               }
+
+       } else if (g_strcmp0(key, RULE_NFLOG_THRESHOLD) == 0) {
+               if (rule->target == STC_FW_RULE_TARGET_NFLOG) {
+                       rule->nflog_threshold = g_variant_get_uint16(value);
+                       STC_LOGD("%s: [%u]", RULE_NFLOG_THRESHOLD, rule->nflog_threshold);
+               }
+
        } else if (g_strcmp0(key, RULE_IDENTIFIER) == 0) {
                guint str_length;
                const gchar *str = g_variant_get_string(value, &str_length);
@@ -943,8 +1140,6 @@ static void __fw_rule_extract(const char *key, GVariant *value,
        } else {
                STC_LOGD("Unknown rule [%s]", key);
        }
-
-       __STC_LOG_FUNC_EXIT__;
 }
 
 gboolean __validate_fw_rule(firewall_rule_s *rule)
@@ -996,12 +1191,33 @@ gboolean __validate_fw_rule(firewall_rule_s *rule)
                return FALSE;
        }
 
+       if (rule->target >= STC_FW_RULE_TARGET_MAX) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->target == STC_FW_RULE_TARGET_LOG &&
+               (rule->log_prefix == NULL ||
+               rule->log_prefix[0] == '\0')) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (rule->target == STC_FW_RULE_TARGET_NFLOG &&
+               (rule->nflog_prefix == NULL ||
+               rule->nflog_prefix[0] == '\0')) {
+               __STC_LOG_FUNC_EXIT__;
+               return FALSE;
+       }
+
        __STC_LOG_FUNC_EXIT__;
        return TRUE;
 }
 
 void stc_firewall_init(void)
 {
+       __STC_LOG_FUNC_ENTER__;
+
        int ret = STC_ERROR_NONE;
 
        g_firewalls = g_hash_table_new_full(g_str_hash,
@@ -1016,21 +1232,31 @@ void stc_firewall_init(void)
 
        table_firewall_foreach_chain(__fw_table_chain_info_cb, NULL);
        table_firewall_foreach_rule(__fw_table_rule_info_cb, NULL);
+
+       __STC_LOG_FUNC_EXIT__;
 }
 
-void stc_firewall_update(void)
+API void stc_firewall_update(void)
 {
+       __STC_LOG_FUNC_ENTER__;
+
        __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);
+
+       __STC_LOG_FUNC_EXIT__;
 }
 
 void stc_firewall_deinit(void)
 {
+       __STC_LOG_FUNC_ENTER__;
+
        if (g_firewalls) {
                g_hash_table_destroy(g_firewalls);
                g_firewalls = NULL;
        }
+
+       __STC_LOG_FUNC_EXIT__;
 }
 
 gboolean handle_firewall_lock(StcFirewall *object,
@@ -1236,7 +1462,7 @@ gboolean handle_firewall_set_chain(StcFirewall *object,
        STC_FIREWALL_CHECK_LOCK_STATE(invocation);
 
        if (chain == NULL ||
-               target > STC_FW_CHAIN_TARGET_OUTPUT) {
+               target >= STC_FW_CHAIN_TARGET_MAX) {
                STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
                                                STC_ERROR_INVALID_PARAMETER);
                __STC_LOG_FUNC_EXIT__;
@@ -1272,7 +1498,6 @@ gboolean handle_firewall_set_chain(StcFirewall *object,
        }
 
        __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);
@@ -1331,7 +1556,8 @@ gboolean handle_firewall_unset_chain(StcFirewall *object,
        }
 
        if (lookup->target == STC_FW_CHAIN_TARGET_NONE) {
-               STC_LOGE("chain is not set");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("chain is not set");
                STC_FIREWALL_DBUS_REPLY_ERROR(invocation,
                                                STC_ERROR_INVALID_PARAMETER);
                __STC_LOG_FUNC_EXIT__;
@@ -1388,7 +1614,8 @@ gboolean handle_firewall_add_rule(StcFirewall *object,
 
        rule = MALLOC0(firewall_rule_s, 1);
        if (!rule) {
-               STC_LOGE("rule allocation failed");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("rule allocation failed");
                return STC_ERROR_OUT_OF_MEMORY;
        }
 
@@ -1440,7 +1667,8 @@ gboolean handle_firewall_remove_rule(StcFirewall *object,
 
        rule = MALLOC0(firewall_rule_s, 1);
        if (!rule) {
-               STC_LOGE("rule allocation failed");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("rule allocation failed");
                return STC_ERROR_OUT_OF_MEMORY;
        }
 
@@ -1486,13 +1714,15 @@ gboolean handle_firewall_update_rule(StcFirewall *object,
        __STC_LOG_FUNC_ENTER__;
        GVariantIter *iter = NULL;
        firewall_rule_s *rule;
+       guint key;
        int ret = STC_ERROR_NONE;
 
        STC_FIREWALL_CHECK_LOCK_STATE(invocation);
 
        rule = MALLOC0(firewall_rule_s, 1);
        if (!rule) {
-               STC_LOGE("rule allocation failed");
+               if (STC_DEBUG_LOG && STC_FW_LOG)
+                       STC_LOGE("rule allocation failed");
                return STC_ERROR_OUT_OF_MEMORY;
        }
 
@@ -1514,9 +1744,10 @@ gboolean handle_firewall_update_rule(StcFirewall *object,
                return TRUE;
        }
 
+       key = rule->key;
        ret = __fw_rule_update(rule);
        if (ret == STC_ERROR_NONE) {
-               table_firewall_update_rule(rule);
+               table_firewall_update_rule(rule, key);
        } else {
                __fw_rule_free(rule);
                STC_FIREWALL_DBUS_REPLY_ERROR(invocation, ret);
@@ -1543,6 +1774,7 @@ gboolean handle_firewall_get_all_rule(StcFirewall *object,
        builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
 
        __fw_chain_foreach(__fw_foreach_to_make_rule_param, builder);
+       __fw_chain_foreach(__fw_foreach_to_print_rule, NULL);
 
        return_parameters = g_variant_new("(aa{sv})", builder);
        g_variant_builder_unref(builder);