Set STC_DEBUG_LOG flag
[platform/core/connectivity/stc-manager.git] / src / helper / helper-nfacct-rule.c
index 94ad5d1..a8474a1 100755 (executable)
 #define RULE_APP_OUT "%s -w %s OUTPUT -o %s -m cgroup --cgroup %u %s %s"
 #define RULE_APP_IN "%s -w %s INPUT -i %s -m cgroup --cgroup %u %s %s"
 
-
 /* iptables -w [I/A/D] [OUTPUT/FORWARD/INPUT] -o/-i iface -m nfacct --nfacct-name name -j ACCEPT/REJECT */
 
 #define RULE_IFACE_OUT "%s -w %s %s -o %s %s %s"
 #define RULE_IFACE_IN "%s -w %s %s -i %s %s  %s"
 
-
 #define NFNL_SUBSYS_ACCT                7
 #define BUF_SIZE_FOR_ERR 100
 
@@ -126,7 +124,7 @@ static stc_error_e send_nfacct_request(int sock, struct genl *req)
        int ret = sendto(sock, (char *)(&req->n), req->n.nlmsg_len, 0,
                         (struct sockaddr *)&nladdr, sizeof(nladdr));
        ret_value_msg_if(ret < 0, STC_ERROR_FAIL,
-                        "Failed to send command to get outgoing traffic");
+                        "Failed to send nfacct request, error [%d]", ret);
 
        return STC_ERROR_NONE;
 }
@@ -158,7 +156,9 @@ stc_error_e nfacct_send_del(nfacct_rule_s *counter)
 {
        struct genl req;
 
+#if STC_DEBUG_LOG
        STC_LOGD("send remove request for %s", counter->name);
+#endif
 
        prepare_netlink_msg(&req, NFNL_MSG_ACCT_DEL, NLM_F_ACK);
        add_string_attr(&req, counter->name, NFACCT_NAME);
@@ -286,7 +286,7 @@ bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt)
                        iface = get_iftype_by_name(ifname_buf);
                        if (iface == STC_IFACE_DATACALL) {
                                cnt->iotype = NFACCT_COUNTER_OUT;
-                               strcpy(cnt->ifname, ifname_buf);
+                               strncpy(cnt->ifname, ifname_buf, MAX_IFACE_LENGTH);
                        }
                }
 
@@ -388,16 +388,18 @@ static void wait_for_rule_cmd(pid_t pid)
 {
        int status;
        pid_t ret_pid;
-       char buf[BUF_SIZE_FOR_ERR] = { 0 };
 
-       if (!pid) {
+       if (!pid || pid == -1) {
                STC_LOGD("no need to wait");
                return;
        }
+
        ret_pid = waitpid(pid, &status, 0);
-       if (ret_pid < 0)
+       if (ret_pid < 0) {
+               char buf[BUF_SIZE_FOR_ERR] = { 0 };
                STC_LOGD("can't wait for a pid %d %d %s", pid, status,
                         strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+       }
 }
 
 static char* get_cmd_pos(const char *cmd_buf)
@@ -409,65 +411,95 @@ static char* get_cmd_pos(const char *cmd_buf)
        return cmd_pos;
 }
 
-static bool is_rule_exists(const char *cmd_buf)
+static bool is_rule_present(const char *cmd_buf)
 {
-       size_t buf_len;
-       char *exec_buf;
-       char *cmd_pos = get_cmd_pos(cmd_buf);
        bool ret = false;
-       if (!cmd_pos)
-               return false;
+       pid_t pid = fork();
 
-       buf_len = strlen(cmd_buf) + 1;
-       exec_buf = (char *)malloc(buf_len);
-       if (!exec_buf)
-               return false;
+       if (pid == 0) {
+               gchar **args = NULL;
+               size_t buf_len;
+               char *exec_buf;
+               char *cmd_pos = get_cmd_pos(cmd_buf);
+
+               if (!cmd_pos)
+                       exit(1);
 
-       strncpy(exec_buf, cmd_buf, buf_len);
-       strncpy(exec_buf + (cmd_pos - cmd_buf), IPTABLES_CHECK,
-               sizeof(IPTABLES_CHECK) - 1);
+               buf_len = strlen(cmd_buf) + 1;
+               exec_buf = (char *)malloc(buf_len);
+               if (!exec_buf)
+                       exit(1);
 
-       STC_LOGD("check rule %s", exec_buf);
+               strncpy(exec_buf, cmd_buf, buf_len);
+               strncpy(exec_buf + (cmd_pos - cmd_buf), IPTABLES_CHECK,
+                       sizeof(IPTABLES_CHECK) - 1);
+
+#if STC_DEBUG_LOG
+               STC_LOGD("check rule %s", exec_buf);
+#endif
+
+               args = g_strsplit_set(exec_buf, " ", -1);
+
+               ret = execv(args[0], args);
+               if (ret) {
+                       char buf[BUF_SIZE_FOR_ERR] = { 0 };
+                       STC_LOGE("Can't execute %s: %s",
+                                cmd_buf, strerror_r(errno, buf,
+                                                    BUF_SIZE_FOR_ERR));
+               }
+
+               free(exec_buf);
+               g_strfreev(args);
+               exit(ret);
+       }
 
-       ret = system(exec_buf) == 0;
-       free(exec_buf);
        return ret;
 }
 
 stc_error_e exec_iptables_cmd(const char *cmd_buf, pid_t *cmd_pid)
 {
+       const size_t args_number = get_args_number(cmd_buf);
+       *cmd_pid = 0;
+
+       ret_value_msg_if(args_number == 0, STC_ERROR_FAIL, "no arguments");
+
        pid_t pid = fork();
 
        if (pid == 0) {
                char *cmd;
                unsigned int i;
-               const size_t args_number = get_args_number(cmd_buf);
                char *args[args_number + 2];
                int ret;
                char *save_ptr = NULL;
-               char buf[BUF_SIZE_FOR_ERR] = { 0 };
-
-               STC_LOGD("executing iptables cmd %s in forked process",
-                        cmd_buf);
 
-               ret_value_msg_if(args_number == 0, STC_ERROR_FAIL, "no arguments");
+#if STC_DEBUG_LOG
+               STC_LOGD("executing iptables cmd %s in forked process", cmd_buf);
+#endif
 
-               if (is_rule_exists(cmd_buf)) {
-                       STC_LOGD("Rule %s already exists", cmd_buf);
+               if (is_rule_present(cmd_buf)) {
+                       STC_LOGD("Rule %s already present", cmd_buf);
                        exit(0);
                }
+
                args[0] = "iptables";
                cmd = strtok_r((char *)cmd_buf, " ", &save_ptr);
-               ret_value_msg_if(cmd == NULL, STC_ERROR_FAIL, "no arguments");
+               if (cmd == NULL) {
+                       STC_LOGE("no arguments");
+                       exit(-EINVAL);
+               }
+
                for (i = 1; i <= args_number; ++i)
                        args[i] = strtok_r(NULL, " ", &save_ptr);
 
                args[i] = NULL;
 
                ret = execv(cmd, args);
-               if (ret)
+               if (ret) {
+                       char buf[BUF_SIZE_FOR_ERR] = { 0 };
                        STC_LOGE("Can't execute %s: %s",
-                                cmd_buf, strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+                                cmd_buf, strerror_r(errno, buf,
+                                                    BUF_SIZE_FOR_ERR));
+               }
                exit(ret);
        }
 
@@ -477,38 +509,48 @@ stc_error_e exec_iptables_cmd(const char *cmd_buf, pid_t *cmd_pid)
 
 stc_error_e exec_ip6tables_cmd(const char *cmd_buf, pid_t *cmd_pid)
 {
+       const size_t args_number = get_args_number(cmd_buf);
+       *cmd_pid = 0;
+
+       ret_value_msg_if(args_number == 0, STC_ERROR_FAIL, "no arguments");
+
        pid_t pid = fork();
 
        if (pid == 0) {
                char *cmd;
                unsigned int i;
-               const size_t args_number = get_args_number(cmd_buf);
                char *args[args_number + 2];
                int ret;
                char *save_ptr = NULL;
-               char buf[BUF_SIZE_FOR_ERR] = { 0 };
-
-               STC_LOGD("executing ip6tables cmd %s in forked process",
-                        cmd_buf);
 
-               ret_value_msg_if(args_number == 0, STC_ERROR_FAIL, "no arguments");
+#if STC_DEBUG_LOG
+               STC_LOGD("executing ip6tables cmd %s in forked process", cmd_buf);
+#endif
 
-               if (is_rule_exists(cmd_buf)) {
-                       STC_LOGD("Rule %s already exists", cmd_buf);
+               if (is_rule_present(cmd_buf)) {
+                       STC_LOGD("Rule %s already present", cmd_buf);
                        exit(0);
                }
+
                args[0] = "ip6tables";
                cmd = strtok_r((char *)cmd_buf, " ", &save_ptr);
-               ret_value_msg_if(cmd == NULL, STC_ERROR_FAIL, "no arguments");
+               if (cmd == NULL) {
+                       STC_LOGE("no arguments");
+                       exit(-EINVAL);
+               }
+
                for (i = 1; i <= args_number; ++i)
                        args[i] = strtok_r(NULL, " ", &save_ptr);
 
                args[i] = NULL;
 
                ret = execv(cmd, args);
-               if (ret)
+               if (ret) {
+                       char buf[BUF_SIZE_FOR_ERR] = { 0 };
                        STC_LOGE("Can't execute %s: %s",
-                                cmd_buf, strerror_r(errno, buf, BUF_SIZE_FOR_ERR));
+                                cmd_buf, strerror_r(errno, buf,
+                                                    BUF_SIZE_FOR_ERR));
+               }
                exit(ret);
        }
 
@@ -525,52 +567,61 @@ static char *choose_iftype_name(nfacct_rule_s *rule)
 static stc_error_e exec_iface_cmd(const char *pattern, const char *cmd,
                                  const char *chain, const char *nfacct,
                                  const char *jump, char *iftype_name,
-                                 pid_t *pid)
+                                 pid_t *pid, nfacct_rule_iptype iptype)
 {
        char block_buf[MAX_PATH_LENGTH];
        int ret;
+       const char *iptables_type = IPTABLES;
 
        ret_value_msg_if(iftype_name == NULL, STC_ERROR_FAIL,
                         "Invalid network interface name argument");
 
-       /* iptables rule */
-       ret = snprintf(block_buf, sizeof(block_buf), pattern, IPTABLES, cmd, chain,
-                     iftype_name, nfacct, jump);
-       ret_value_msg_if(ret > sizeof(block_buf), STC_ERROR_FAIL,
-                        "Not enough buffer");
-       exec_iptables_cmd(block_buf, pid);
+       if (iptype == NFACCT_TYPE_IPV6)
+               iptables_type = IP6TABLES;
 
-       /* ip6tables rule */
-       ret = snprintf(block_buf, sizeof(block_buf), pattern, IP6TABLES, cmd, chain,
-                     iftype_name, nfacct, jump);
+       ret = snprintf(block_buf, sizeof(block_buf), pattern, iptables_type,
+                      cmd, chain, iftype_name, nfacct, jump);
        ret_value_msg_if(ret > sizeof(block_buf), STC_ERROR_FAIL,
                         "Not enough buffer");
-       return exec_ip6tables_cmd(block_buf, pid);
+
+       if (iptype == NFACCT_TYPE_IPV6)
+               exec_ip6tables_cmd(block_buf, pid);
+       else
+               exec_iptables_cmd(block_buf, pid);
+
+       wait_for_rule_cmd(*pid);
+
+       return STC_ERROR_NONE;
 }
 
 static stc_error_e exec_app_cmd(const char *pattern, const char *cmd,
                                const char *nfacct, const char *jump,
                                const uint32_t classid, char *iftype_name,
-                               pid_t *pid)
+                               pid_t *pid, nfacct_rule_iptype iptype)
 {
        char block_buf[MAX_PATH_LENGTH];
        int ret;
+       const char *iptables_type = IPTABLES;
+
        ret_value_msg_if(iftype_name == NULL, STC_ERROR_FAIL,
                         "Invalid network interface name argument");
 
-       /* iptables rules */
-       ret = snprintf(block_buf, sizeof(block_buf), pattern, IPTABLES, cmd,
-                     iftype_name, classid, nfacct, jump);
-       ret_value_msg_if(ret > sizeof(block_buf), STC_ERROR_FAIL,
-                        "Not enough buffer");
-       exec_iptables_cmd(block_buf, pid);
+       if (iptype == NFACCT_TYPE_IPV6)
+               iptables_type = IP6TABLES;
 
-       /* ip6tables rules */
-       ret = snprintf(block_buf, sizeof(block_buf), pattern, IP6TABLES, cmd,
-                     iftype_name, classid, nfacct, jump);
+       ret = snprintf(block_buf, sizeof(block_buf), pattern, iptables_type,
+                      cmd, iftype_name, classid, nfacct, jump);
        ret_value_msg_if(ret > sizeof(block_buf), STC_ERROR_FAIL,
                         "Not enough buffer");
-       return exec_ip6tables_cmd(block_buf, pid);
+
+       if (iptype == NFACCT_TYPE_IPV6)
+               exec_ip6tables_cmd(block_buf, pid);
+       else
+               exec_iptables_cmd(block_buf, pid);
+
+       wait_for_rule_cmd(*pid);
+
+       return STC_ERROR_NONE;
 }
 
 static char *get_iptables_cmd(const nfacct_rule_action action)
@@ -605,30 +656,28 @@ static char *get_iptables_jump(const nfacct_rule_jump jump)
        return "";
 }
 
-static stc_error_e produce_app_rule(nfacct_rule_s *rule,
-                                   const uint64_t send_limit,
-                                   const uint64_t rcv_limit,
-                                   const nfacct_rule_action action,
-                                   const nfacct_rule_jump jump,
-                                   const nfacct_rule_direction iotype)
+static stc_error_e produce_app_rule(nfacct_rule_s *rule)
 {
-       char *set_cmd = get_iptables_cmd(action);
-       char *jump_cmd = get_iptables_jump(jump);
+       if (rule == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       char *set_cmd = get_iptables_cmd(rule->action);
+       char *jump_cmd = get_iptables_jump(rule->jump);
        char nfacct_buf[sizeof(NFACCT_NAME_MOD) +
                3*MAX_DEC_SIZE(int) + 4];
        stc_error_e ret = STC_ERROR_NONE;
        pid_t pid = 0;
 
        /* income part */
-       if (iotype & NFACCT_COUNTER_IN) {
-               rule->quota = rcv_limit;
+       if (rule->iotype & NFACCT_COUNTER_IN) {
+               rule->quota = rule->rcv_limit;
                rule->iotype = NFACCT_COUNTER_IN;
                generate_counter_name(rule);
 
                /* to support quated counter we need nfacct,
                 *      don't use it in case of just block without a limit
                 *      iow, send_limit = 0 and rcv_limit 0 */
-               if (action != NFACCT_ACTION_DELETE) {
+               if (rule->action != NFACCT_ACTION_DELETE) {
                        ret = nfacct_send_del(rule);
                        ret_value_msg_if(ret != STC_ERROR_NONE, ret,
                                         "can't del quota counter");
@@ -648,20 +697,19 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule,
 
                ret = exec_app_cmd(RULE_APP_IN, set_cmd, nfacct_buf, jump_cmd,
                                   rule->classid, choose_iftype_name(rule),
-                                  &pid);
+                                  &pid, rule->iptype);
                ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
                                 "Can't set conditional block for ingress"
                                 " traffic, for classid %u, cmd %s, j %s",
                                 rule->classid, set_cmd, jump_cmd);
 
                /* remove in any case */
-               if (action == NFACCT_ACTION_DELETE) {
+               if (rule->action == NFACCT_ACTION_DELETE) {
                        /* TODO here and everywhere should be not just a del,
                         *      here should be get counted value and than
                         *      set new counter with that value, but it's minor issue,
                         *      due it's not clear when actual counters was stored,
                         *      and based on which value settings made such decition */
-                       wait_for_rule_cmd(pid);
                        rule->iptables_rule = nfacct_send_del;
                        set_finalize_flag(rule);
                        nfacct_send_get(rule);
@@ -671,12 +719,12 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule,
                }
        }
 
-       if (iotype & NFACCT_COUNTER_OUT) {
+       if (rule->iotype & NFACCT_COUNTER_OUT) {
                /* outcome part */
                rule->iotype = NFACCT_COUNTER_OUT;
-               rule->quota = send_limit;
+               rule->quota = rule->send_limit;
                generate_counter_name(rule);
-               if (action != NFACCT_ACTION_DELETE) {
+               if (rule->action != NFACCT_ACTION_DELETE) {
                        ret = nfacct_send_del(rule);
                        ret_value_msg_if(ret != STC_ERROR_NONE, ret,
                                         "can't del quota counter");
@@ -694,13 +742,12 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule,
 
                ret = exec_app_cmd(RULE_APP_OUT, set_cmd, nfacct_buf, jump_cmd,
                                   rule->classid, choose_iftype_name(rule),
-                                  &pid);
+                                  &pid, rule->iptype);
                ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
                                 "Can't set conditional block for engress"
                                 " traffic, for classid %u, cmd %s, j %s",
                                 rule->classid, set_cmd, jump_cmd);
-               if (action == NFACCT_ACTION_DELETE) {
-                       wait_for_rule_cmd(pid);
+               if (rule->action == NFACCT_ACTION_DELETE) {
                        rule->iptables_rule = nfacct_send_del;
                        /* not effective, it's better to replace
                         * set_finalize_flag by set_property,
@@ -716,27 +763,25 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule,
        return STC_ERROR_NONE;
 }
 
-static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
-                                     const uint64_t send_limit,
-                                     const uint64_t rcv_limit,
-                                     const nfacct_rule_action action,
-                                     const nfacct_rule_jump jump,
-                                     const nfacct_rule_direction iotype)
+static stc_error_e produce_iface_rule(nfacct_rule_s *rule)
 {
-       char *set_cmd = get_iptables_cmd(action);
-       char *jump_cmd = get_iptables_jump(jump);
+       if (rule == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       char *set_cmd = get_iptables_cmd(rule->action);
+       char *jump_cmd = get_iptables_jump(rule->jump);
        char nfacct_buf[sizeof(NFACCT_NAME_MOD) +
                3*MAX_DEC_SIZE(int) + 4];
        stc_error_e ret;
        pid_t pid = 0;
 
-       if (iotype & NFACCT_COUNTER_IN) {
+       if (rule->iotype & NFACCT_COUNTER_IN) {
                /* income part */
                rule->iotype = NFACCT_COUNTER_IN;
-               rule->quota = rcv_limit;
+               rule->quota = rule->rcv_limit;
                generate_counter_name(rule);
 
-               if (action != NFACCT_ACTION_DELETE) {
+               if (rule->action != NFACCT_ACTION_DELETE) {
                        /* send delete comman in case of creation,
                         * because nfacct doesn't reset value for nfacct quota
                         * in case of quota existing */
@@ -758,7 +803,8 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
                ret = exec_iface_cmd(RULE_IFACE_IN, set_cmd,
                                     get_iptables_chain(rule->iotype),
                                     nfacct_buf, jump_cmd,
-                                    choose_iftype_name(rule), &pid);
+                                    choose_iftype_name(rule), &pid,
+                                    rule->iptype);
                ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
                                 "Can't set conditional block for ingress"
                                 " traffic, for iftype %d, cmd %s, j %s",
@@ -768,10 +814,10 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
                if (rule->intend == NFACCT_WARN ||
                    rule->intend == NFACCT_BLOCK) {
                        /* RULE_IFACE_OUT is not a misprint here */
-                       wait_for_rule_cmd(pid);
                        ret = exec_iface_cmd(RULE_IFACE_IN, set_cmd,
                                             FORWARD_RULE, nfacct_buf, jump_cmd,
-                                            choose_iftype_name(rule), &pid);
+                                            choose_iftype_name(rule), &pid,
+                                            rule->iptype);
                        ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
                                         "Can't set forward rule for ingress "
                                         "traffic, for iftype %d, cmd %s, j %s",
@@ -779,8 +825,7 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
                }
                /* tethering */
 
-               if (action == NFACCT_ACTION_DELETE) {
-                       wait_for_rule_cmd(pid);
+               if (rule->action == NFACCT_ACTION_DELETE) {
                        rule->iptables_rule = nfacct_send_del;
                        set_finalize_flag(rule);
                        nfacct_send_get(rule);
@@ -790,13 +835,13 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
                }
        }
 
-       if (iotype & NFACCT_COUNTER_OUT) {
+       if (rule->iotype & NFACCT_COUNTER_OUT) {
                /* outcome part */
                rule->iotype = NFACCT_COUNTER_OUT;
-               rule->quota = send_limit;
+               rule->quota = rule->send_limit;
                generate_counter_name(rule);
 
-               if (action != NFACCT_ACTION_DELETE) {
+               if (rule->action != NFACCT_ACTION_DELETE) {
                        /* send delete comman in case of creation,
                         * because nfacct doesn't reset value for nfacct quota
                         * in case of quota existing */
@@ -815,10 +860,10 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
                ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0,
                                 STC_ERROR_FAIL, "Not enough buffer");
 
-               wait_for_rule_cmd(pid);
                ret = exec_iface_cmd(RULE_IFACE_OUT, set_cmd, OUT_RULE,
                                     nfacct_buf, jump_cmd,
-                                    choose_iftype_name(rule), &pid);
+                                    choose_iftype_name(rule), &pid,
+                                    rule->iptype);
                ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
                                 "Can't set conditional block for "
                                 "engress traffic, for iftype %d, cmd %s, j %s",
@@ -826,10 +871,10 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
                /* for tethering  */
                if (rule->intend == NFACCT_WARN ||
                    rule->intend == NFACCT_BLOCK) {
-                       wait_for_rule_cmd(pid);
                        ret = exec_iface_cmd(RULE_IFACE_OUT, set_cmd,
                                             FORWARD_RULE, nfacct_buf, jump_cmd,
-                                            choose_iftype_name(rule), &pid);
+                                            choose_iftype_name(rule), &pid,
+                                            rule->iptype);
                        ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
                                         "Can't set forward rule for engress "
                                         "traffic, for iftype %d, cmd %s, j %s",
@@ -837,8 +882,7 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
                }
                /* tethering  */
 
-               if (action == NFACCT_ACTION_DELETE) {
-                       wait_for_rule_cmd(pid);
+               if (rule->action == NFACCT_ACTION_DELETE) {
                        rule->iptables_rule = nfacct_send_del;
                        set_finalize_flag(rule);
                        nfacct_send_get(rule);
@@ -850,26 +894,28 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
        return STC_ERROR_NONE;
 }
 
-stc_error_e produce_net_rule(nfacct_rule_s *rule,
-                            const uint64_t send_limit,
-                            const uint64_t rcv_limit,
-                            const nfacct_rule_action action,
-                            const nfacct_rule_jump jump,
-                            const nfacct_rule_direction iotype)
+stc_error_e produce_net_rule(nfacct_rule_s *rule)
 {
        stc_error_e ret = STC_ERROR_NONE;
 
-       if (action == NFACCT_ACTION_APPEND && rule->intend == NFACCT_WARN
-           && !send_limit && !rcv_limit)
+       if (rule == NULL)
+               return STC_ERROR_INVALID_PARAMETER;
+
+       if (rule->action == NFACCT_ACTION_APPEND &&
+           rule->intend == NFACCT_WARN &&
+           !rule->send_limit && !rule->rcv_limit)
                return STC_ERROR_NONE;
 
        if (rule->classid != STC_ALL_APP_CLASSID &&
-           rule->classid != STC_TETHERING_APP_CLASSID)
-               ret = produce_app_rule(rule, send_limit,
-                                      rcv_limit, action, jump, iotype);
+           rule->classid != STC_TETHERING_APP_CLASSID &&
+           rule->classid != STC_TOTAL_DATACALL_CLASSID &&
+           rule->classid != STC_TOTAL_WIFI_CLASSID &&
+           rule->classid != STC_TOTAL_BLUETOOTH_CLASSID &&
+           rule->classid != STC_TOTAL_IPV4_CLASSID &&
+           rule->classid != STC_TOTAL_IPV6_CLASSID)
+               ret = produce_app_rule(rule);
        else
-               ret = produce_iface_rule(rule, send_limit, rcv_limit,
-                                        action, jump, iotype);
+               ret = produce_iface_rule(rule);
 
        return ret;
 }