X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fhelper%2Fhelper-nfacct-rule.c;h=a3e4647b287d4837e591420b18dd3082b591ab43;hb=4ba9fee21db5a1911529822b5928c3f41c4e9946;hp=94ad5d14dfd28879a007b56d585889c66aaccd44;hpb=8cf8059a714d925d9f8ccdd56eedb2648f0c7c90;p=platform%2Fcore%2Fconnectivity%2Fstc-manager.git diff --git a/src/helper/helper-nfacct-rule.c b/src/helper/helper-nfacct-rule.c old mode 100755 new mode 100644 index 94ad5d1..a3e4647 --- a/src/helper/helper-nfacct-rule.c +++ b/src/helper/helper-nfacct-rule.c @@ -26,6 +26,7 @@ #include "counter.h" #include "helper-nfacct-rule.h" +#include "helper-iptables.h" #include "configure_stub.h" @@ -37,8 +38,8 @@ #define INSERT "-I" #define NFACCT_NAME_MOD " -m nfacct --nfacct-name %s" -#define REJECT_RULE " -j REJECT" -#define ACCEPT_RULE " -j ACCEPT" +#define REJECT_RULE "REJECT" +#define ACCEPT_RULE "ACCEPT" #define OUT_RULE "OUTPUT" #define IN_RULE "INPUT" #define FORWARD_RULE "FORWARD" @@ -47,13 +48,11 @@ #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,43 +125,56 @@ 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; } static stc_error_e nfacct_send_new(nfacct_rule_s *counter) { - struct genl req; - - prepare_netlink_msg(&req, NFNL_MSG_ACCT_NEW, NLM_F_CREATE | NLM_F_ACK); - add_string_attr(&req, counter->name, NFACCT_NAME); + int ret = STC_ERROR_NONE; + struct genl *req = MALLOC0(struct genl, 1); + if (req == NULL) { + STC_LOGE("Failed allocate memory to genl request message"); //LCOV_EXCL_LINE + return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE + } - STC_LOGD("counter name %s", counter->name); + prepare_netlink_msg(req, NFNL_MSG_ACCT_NEW, NLM_F_CREATE | NLM_F_ACK); + add_string_attr(req, counter->name, NFACCT_NAME); /* padding */ - add_uint64_attr(&req, 0, NFACCT_PKTS); - add_uint64_attr(&req, 0, NFACCT_BYTES); + add_uint64_attr(req, 0, NFACCT_PKTS); + add_uint64_attr(req, 0, NFACCT_BYTES); + //LCOV_EXCL_START if (counter->quota) { STC_LOGD("quota bytes %"PRId64, counter->quota); - add_uint32_attr(&req, htobe32(NFACCT_F_QUOTA_BYTES), + add_uint32_attr(req, htobe32(NFACCT_F_QUOTA_BYTES), NFACCT_FLAGS); - add_uint64_attr(&req, htobe64(counter->quota), NFACCT_QUOTA); + add_uint64_attr(req, htobe64(counter->quota), NFACCT_QUOTA); } + //LCOV_EXCL_STOP - return send_nfacct_request(counter->carg->sock, &req); + ret = send_nfacct_request(counter->carg->sock, req); + FREE(req); + return ret; } stc_error_e nfacct_send_del(nfacct_rule_s *counter) { - struct genl req; + int ret = STC_ERROR_NONE; + struct genl *req = MALLOC0(struct genl, 1); + if (req == NULL) { + STC_LOGE("Failed allocate memory to genl request message"); //LCOV_EXCL_LINE + return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE + } - STC_LOGD("send remove request for %s", counter->name); + prepare_netlink_msg(req, NFNL_MSG_ACCT_DEL, NLM_F_ACK); + add_string_attr(req, counter->name, NFACCT_NAME); - prepare_netlink_msg(&req, NFNL_MSG_ACCT_DEL, NLM_F_ACK); - add_string_attr(&req, counter->name, NFACCT_NAME); - return send_nfacct_request(counter->carg->sock, &req); + ret = send_nfacct_request(counter->carg->sock, req); + FREE(req); + return ret; } #define NFACCT_F_QUOTAS (NFACCT_F_QUOTA_BYTES | NFACCT_F_QUOTA_PKTS) @@ -171,22 +183,29 @@ static stc_error_e internal_nfacct_send_get(struct counter_arg *carg, const char *name, int mask, int filter) { - struct genl req; + int ret = STC_ERROR_NONE; struct nlattr *na; int flag = !name ? NLM_F_DUMP : 0; - prepare_netlink_msg(&req, get_type, - flag); + struct genl *req = MALLOC0(struct genl, 1); + if (req == NULL) { + STC_LOGE("Failed allocate memory to genl request message"); //LCOV_EXCL_LINE + return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE + } + + prepare_netlink_msg(req, get_type, flag); /* due we don't get counter with quota any where else, * here we will request just counters by default */ if (name) - add_string_attr(&req, name, NFACCT_NAME); - - na = start_nest_attr(&req, NFACCT_FILTER); - add_uint32_attr(&req, htonl(mask), - NFACCT_FILTER_ATTR_MASK); - add_uint32_attr(&req, htonl(filter), NFACCT_FILTER_ATTR_VALUE); - end_nest_attr(&req, na); - return send_nfacct_request(carg->sock, &req); + add_string_attr(req, name, NFACCT_NAME); + + na = start_nest_attr(req, NFACCT_FILTER); + add_uint32_attr(req, htonl(mask), NFACCT_FILTER_ATTR_MASK); + add_uint32_attr(req, htonl(filter), NFACCT_FILTER_ATTR_VALUE); + end_nest_attr(req, na); + + ret = send_nfacct_request(carg->sock, req); + FREE(req); + return ret; } stc_error_e nfacct_send_get_counters(struct counter_arg *carg, const char *name) @@ -230,7 +249,7 @@ static nfacct_rule_direction convert_to_iotype(int type) static stc_iface_type_e convert_to_iftype(int type) { return (type < STC_IFACE_LAST_ELEM && - type > STC_IFACE_UNKNOWN) ? type : STC_IFACE_UNKNOWN; + type > STC_IFACE_UNKNOWN) ? type : STC_IFACE_UNKNOWN; } bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt) @@ -254,15 +273,27 @@ bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt) case 'r': cnt->intend = NFACCT_BLOCK; break; - case 't': - cnt->intend = NFACCT_TETH_COUNTER; + case 'a': + cnt->intend = NFACCT_ALLOW; break; + case 't': + cnt->intend = NFACCT_TETH_COUNTER; //LCOV_EXCL_LINE + break; //LCOV_EXCL_LINE default: return false; } STRING_SAVE_COPY(cnt->name, cnt_name); +#if 0 + /* ======================================================== + * NOTE:- + * Below parsing for tethering case is not in use + * stc-manager needs to ignore this for NFACCT_TETH_COUNTER + * this is disbaled for future use. + * =======================================================*/ + + //LCOV_EXCL_START if (cnt->intend == NFACCT_TETH_COUNTER) { char ifname_buf[MAX_IFACE_LENGTH]; int ifname_len; @@ -278,15 +309,15 @@ bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt) iface = get_iftype_by_name(ifname_buf); /* check first part is it datacall */ if (iface == STC_IFACE_DATACALL) { - strncpy(cnt->ifname, ifname_buf, MAX_IFACE_LENGTH); + strncpy(cnt->ifname, ifname_buf, MAX_IFACE_LENGTH - 1); cnt->iotype = NFACCT_COUNTER_IN; } else { /* +1, due : symbol and till the end of cnt_name */ - strncpy(ifname_buf, iftype_part + 1, MAX_IFACE_LENGTH); + strncpy(ifname_buf, iftype_part + 1, MAX_IFACE_LENGTH - 1); 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 - 1); } } @@ -298,6 +329,8 @@ bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt) cnt->classid = STC_TETHERING_APP_CLASSID; return true; } + //LCOV_EXCL_STOP +#endif io_part = strtok_r(name, "_", &save_ptr); if (io_part != NULL) @@ -372,207 +405,6 @@ netlink_create_command(struct netlink_serialization_params *params) return &command; } -static unsigned int get_args_number(const char *cmd_buf) -{ - char *str; - unsigned int count = 0; - - for (str = (char *)cmd_buf; *str != '\0'; ++str) { - if (*str == ' ') - ++count; - } - return count; -} - -static void wait_for_rule_cmd(pid_t pid) -{ - int status; - pid_t ret_pid; - char buf[BUF_SIZE_FOR_ERR] = { 0 }; - - if (!pid) { - STC_LOGD("no need to wait"); - return; - } - ret_pid = waitpid(pid, &status, 0); - if (ret_pid < 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) -{ - char *cmd_pos = strstr(cmd_buf, APPEND); - if (!cmd_pos) - cmd_pos = strstr(cmd_buf, INSERT); - - return cmd_pos; -} - -static bool is_rule_exists(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; - - buf_len = strlen(cmd_buf) + 1; - exec_buf = (char *)malloc(buf_len); - if (!exec_buf) - return false; - - strncpy(exec_buf, cmd_buf, buf_len); - strncpy(exec_buf + (cmd_pos - cmd_buf), IPTABLES_CHECK, - sizeof(IPTABLES_CHECK) - 1); - - STC_LOGD("check rule %s", exec_buf); - - ret = system(exec_buf) == 0; - free(exec_buf); - return ret; -} - -stc_error_e exec_iptables_cmd(const char *cmd_buf, pid_t *cmd_pid) -{ - 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 (is_rule_exists(cmd_buf)) { - STC_LOGD("Rule %s already exists", 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"); - for (i = 1; i <= args_number; ++i) - args[i] = strtok_r(NULL, " ", &save_ptr); - - args[i] = NULL; - - ret = execv(cmd, args); - if (ret) - STC_LOGE("Can't execute %s: %s", - cmd_buf, strerror_r(errno, buf, BUF_SIZE_FOR_ERR)); - exit(ret); - } - - *cmd_pid = pid; - return STC_ERROR_NONE; -} - -stc_error_e exec_ip6tables_cmd(const char *cmd_buf, pid_t *cmd_pid) -{ - 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 (is_rule_exists(cmd_buf)) { - STC_LOGD("Rule %s already exists", 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"); - for (i = 1; i <= args_number; ++i) - args[i] = strtok_r(NULL, " ", &save_ptr); - - args[i] = NULL; - - ret = execv(cmd, args); - if (ret) - STC_LOGE("Can't execute %s: %s", - cmd_buf, strerror_r(errno, buf, BUF_SIZE_FOR_ERR)); - exit(ret); - } - - *cmd_pid = pid; - return STC_ERROR_NONE; -} - -static char *choose_iftype_name(nfacct_rule_s *rule) -{ - return strlen(rule->ifname) != 0 ? rule->ifname : - get_iftype_name(rule->iftype); -} - -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) -{ - char block_buf[MAX_PATH_LENGTH]; - int ret; - - 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); - - /* ip6tables rule */ - ret = snprintf(block_buf, sizeof(block_buf), pattern, IP6TABLES, 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); -} - -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) -{ - char block_buf[MAX_PATH_LENGTH]; - int ret; - 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); - - /* ip6tables rules */ - ret = snprintf(block_buf, sizeof(block_buf), pattern, IP6TABLES, 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); -} - static char *get_iptables_cmd(const nfacct_rule_action action) { if (action == NFACCT_ACTION_APPEND) @@ -588,9 +420,11 @@ static char *get_iptables_cmd(const nfacct_rule_action action) static char *get_iptables_chain(const nfacct_rule_direction iotype) { if (iotype == NFACCT_COUNTER_IN) - return IN_RULE; + return STC_IN_CHAIN; else if (iotype == NFACCT_COUNTER_OUT) - return OUT_RULE; + return STC_OUT_CHAIN; + else if (iotype == NFACCT_COUNTER_FORWARD) //LCOV_EXCL_LINE + return STC_FRWD_CHAIN; //LCOV_EXCL_LINE return ""; } @@ -605,30 +439,98 @@ 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 char *choose_iftype_name(nfacct_rule_s *rule) +{ + return strlen(rule->ifname) != 0 ? rule->ifname : + get_iftype_name(rule->iftype); +} +*/ + +static stc_error_e exec_iptables_cmd(nfacct_rule_s *rule) +{ + stc_error_e ret = STC_ERROR_NONE; + iptables_ip_type_e iptype; + iptables_rule_s iptables_rule; + memset(&iptables_rule, 0, sizeof(iptables_rule_s)); + + iptables_rule.nfacct_name = g_strdup(rule->name); + iptables_rule.ifname = g_strdup(rule->ifname); + iptables_rule.target = g_strdup(get_iptables_jump(rule->jump)); + + /* In case of tehering rules use chain 'STC_TETHER' */ + if (rule->intend == NFACCT_TETH_COUNTER || + rule->intend == NFACCT_TETH_ALLOW || + rule->intend == NFACCT_TETH_BLOCK) + iptables_rule.chain = g_strdup(STC_TETHER_CHAIN); + else + iptables_rule.chain = g_strdup(get_iptables_chain(rule->iotype)); + + iptables_rule.classid = rule->classid; + iptables_rule.direction = (rule->iotype & NFACCT_COUNTER_IN) ? + IPTABLES_DIRECTION_IN : IPTABLES_DIRECTION_OUT; + iptype = (iptables_ip_type_e)rule->iptype; + + /* specify the ip range type for source and destination */ + iptables_rule.s_iprange_type = rule->src_iprange_type; + iptables_rule.d_iprange_type = rule->dst_iprange_type; + + /* specify source and destination ip address if any */ + if (rule->src_ip1) { + if (!inet_aton(rule->src_ip1, &iptables_rule.s_ip1)) + STC_LOGE("Failed to inet aton [%s]", rule->src_ip1); + } + if (rule->src_ip2) { + if (!inet_aton(rule->src_ip2, &iptables_rule.s_ip2)) + STC_LOGE("Failed to inet aton [%s]", rule->src_ip2); + } + if (rule->dst_ip1) { + if (!inet_aton(rule->dst_ip1, &iptables_rule.d_ip1)) + STC_LOGE("Failed to inet aton [%s]", rule->dst_ip1); + } + if (rule->dst_ip2) { + if (!inet_aton(rule->dst_ip2, &iptables_rule.d_ip2)) + STC_LOGE("Failed to inet aton [%s]", rule->dst_ip2); + } + + if (rule->action == NFACCT_ACTION_DELETE) { + /* delete interface rule */ + ret = iptables_remove(&iptables_rule, iptype); + } else { + /* add interface rule */ + ret = iptables_add(&iptables_rule, iptype); + } + + g_free(iptables_rule.nfacct_name); + g_free(iptables_rule.ifname); + g_free(iptables_rule.target); + g_free(iptables_rule.chain); + + return ret; +} + +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]; + 3*MAX_DEC_SIZE(int) + 4 + 1]; stc_error_e ret = STC_ERROR_NONE; - pid_t pid = 0; + uint32_t classid = rule->classid; /* 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"); @@ -646,22 +548,35 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule, ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0, STC_ERROR_FAIL, "Not enought buffer"); - ret = exec_app_cmd(RULE_APP_IN, set_cmd, nfacct_buf, jump_cmd, - rule->classid, choose_iftype_name(rule), - &pid); + /* cgroup extention on FORWARD chain are not allowed + * remove classid info in case of tethering rules */ + if (rule->intend == NFACCT_TETH_COUNTER || + rule->intend == NFACCT_TETH_ALLOW || + rule->intend == NFACCT_TETH_BLOCK) { + classid = rule->classid; + rule->classid = 0; + } + + ret = exec_iptables_cmd(rule); + + /* restore the classid info in case of tethering rule */ + if (rule->intend == NFACCT_TETH_COUNTER || + rule->intend == NFACCT_TETH_ALLOW || + rule->intend == NFACCT_TETH_BLOCK) + rule->classid = classid; + 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 +586,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"); @@ -692,15 +607,29 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule, ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0, STC_ERROR_FAIL, "Not enought buffer"); - ret = exec_app_cmd(RULE_APP_OUT, set_cmd, nfacct_buf, jump_cmd, - rule->classid, choose_iftype_name(rule), - &pid); + /* cgroup extention on FORWARD chain are not allowed + * remove classid info in case of tethering rules */ + if (rule->intend == NFACCT_TETH_COUNTER || + rule->intend == NFACCT_TETH_ALLOW || + rule->intend == NFACCT_TETH_BLOCK) { + classid = rule->classid; + rule->classid = 0; + } + + ret = exec_iptables_cmd(rule); + + /* restore the classid info in case of tethering rule */ + if (rule->intend == NFACCT_TETH_COUNTER || + rule->intend == NFACCT_TETH_ALLOW || + rule->intend == NFACCT_TETH_BLOCK) + rule->classid = classid; + 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 +645,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]; + 3*MAX_DEC_SIZE(int) + 4 + 1]; + uint32_t classid = rule->classid; 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 */ @@ -755,23 +682,25 @@ 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 enought buffer"); - ret = exec_iface_cmd(RULE_IFACE_IN, set_cmd, - get_iptables_chain(rule->iotype), - nfacct_buf, jump_cmd, - choose_iftype_name(rule), &pid); + classid = rule->classid; + rule->classid = 0; + + ret = exec_iptables_cmd(rule); 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", rule->iftype, set_cmd, jump_cmd); + //LCOV_EXCL_START /* for tethering */ 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); + nfacct_rule_direction temp_iotype = rule->iotype; + + rule->iotype = NFACCT_COUNTER_FORWARD; + ret = exec_iptables_cmd(rule); + rule->iotype = temp_iotype; 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 +708,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); @@ -788,15 +716,18 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule, ret_value_msg_if(ret != STC_ERROR_NONE, ret, "can't del quota counter"); } + //LCOV_EXCL_STOP } - if (iotype & NFACCT_COUNTER_OUT) { + rule->classid = classid; + + 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,21 +746,24 @@ 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); + classid = rule->classid; + rule->classid = 0; + + ret = exec_iptables_cmd(rule); 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", rule->iftype, set_cmd, jump_cmd); + + //LCOV_EXCL_START /* 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); + nfacct_rule_direction temp_iotype = rule->iotype; + + rule->iotype = NFACCT_COUNTER_OUT; + ret = exec_iptables_cmd(rule); + rule->iotype = temp_iotype; 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 +771,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); @@ -846,30 +779,33 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule, ret_value_msg_if(ret != STC_ERROR_NONE, ret, "can't del quota counter"); } + //LCOV_EXCL_STOP } 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; } @@ -886,10 +822,17 @@ void generate_counter_name(nfacct_rule_s *counter) STRING_SAVE_COPY(counter->ifname, iftype_name); } - if (counter->intend == NFACCT_WARN) + if (counter->intend == NFACCT_WARN || + counter->intend == NFACCT_TETH_WARN) warn_symbol = 'w'; - else if (counter->intend == NFACCT_BLOCK) + else if (counter->intend == NFACCT_BLOCK || + counter->intend == NFACCT_TETH_BLOCK) warn_symbol = 'r'; + else if (counter->intend == NFACCT_ALLOW || + counter->intend == NFACCT_TETH_ALLOW) + warn_symbol = 'a'; + else if (counter->intend == NFACCT_TETH_COUNTER) + warn_symbol = 't'; snprintf(counter->name, NFACCT_NAME_MAX, "%c%d_%d_%d_%s", warn_symbol, counter->iotype, counter->iftype, counter->classid, counter->ifname);