#include "counter.h"
#include "helper-nfacct-rule.h"
+#include "helper-iptables.h"
#include "configure_stub.h"
#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"
#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
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)
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)
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)
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;
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;
- strncpy(cnt->ifname, ifname_buf, MAX_IFACE_LENGTH);
+ strncpy(cnt->ifname, ifname_buf, MAX_IFACE_LENGTH - 1);
}
}
cnt->classid = STC_TETHERING_APP_CLASSID;
return true;
}
+ //LCOV_EXCL_STOP
+#endif
io_part = strtok_r(name, "_", &save_ptr);
if (io_part != NULL)
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)
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 "";
}
return "";
}
-static stc_error_e produce_app_rule(nfacct_rule_s *rule,
- const int64_t send_limit,
- const int64_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");
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);
}
}
- 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");
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,
return STC_ERROR_NONE;
}
-static stc_error_e produce_iface_rule(nfacct_rule_s *rule,
- const int64_t send_limit,
- const int64_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 */
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",
}
/* 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);
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 */
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",
}
/* 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);
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 int64_t send_limit,
- const int64_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 &&
rule->classid != STC_TOTAL_DATACALL_CLASSID &&
rule->classid != STC_TOTAL_WIFI_CLASSID &&
- rule->classid != STC_TOTAL_BLUETOOTH_CLASSID)
- ret = produce_app_rule(rule, send_limit,
- rcv_limit, action, jump, iotype);
+ 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;
}
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);