2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <sys/types.h>
25 #include <arpa/inet.h>
28 #include "helper-nfacct-rule.h"
29 #include "helper-iptables.h"
31 #include "configure_stub.h"
33 #define IPTABLES "/usr/sbin/iptables"
34 #define IP6TABLES "/usr/sbin/ip6tables"
35 #define IPTABLES_CHECK "-C"
40 #define NFACCT_NAME_MOD " -m nfacct --nfacct-name %s"
41 #define REJECT_RULE "REJECT"
42 #define ACCEPT_RULE "ACCEPT"
43 #define OUT_RULE "OUTPUT"
44 #define IN_RULE "INPUT"
45 #define FORWARD_RULE "FORWARD"
47 /* TODO idea to use the same rule both for BLOCK (REJECT) and WARNING (ACCEPT) */
48 #define RULE_APP_OUT "%s -w %s OUTPUT -o %s -m cgroup --cgroup %u %s %s"
49 #define RULE_APP_IN "%s -w %s INPUT -i %s -m cgroup --cgroup %u %s %s"
51 /* iptables -w [I/A/D] [OUTPUT/FORWARD/INPUT] -o/-i iface -m nfacct --nfacct-name name -j ACCEPT/REJECT */
53 #define RULE_IFACE_OUT "%s -w %s %s -o %s %s %s"
54 #define RULE_IFACE_IN "%s -w %s %s -i %s %s %s"
56 #define NFNL_SUBSYS_ACCT 7
57 #define BUF_SIZE_FOR_ERR 100
59 static void prepare_netlink_msg(struct genl *req, int type, int flag)
62 memset(req, 0, sizeof(struct genl));
63 req->n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
64 req->n.nlmsg_type = (NFNL_SUBSYS_ACCT << 8) | type;
65 req->n.nlmsg_flags = NLM_F_REQUEST | flag;
66 req->n.nlmsg_seq = seq;
69 static void add_value_attr(struct genl *req, const void *data, int len,
74 struct nlattr *na = (struct nlattr *)((char *)req +
75 NLMSG_ALIGN(req->n.nlmsg_len));
78 payload = len + NLA_HDRLEN;
79 na->nla_len = payload;
80 memcpy(NLA_DATA(na), data, len);
81 req->n.nlmsg_len += NLMSG_ALIGN(payload);
85 * following 2 function should be used in combination.
86 * start_nest_attr returns nlattr structure, which should be completed by
88 * before these invocations any number of netlink arguments could be inserted
90 static struct nlattr *start_nest_attr(struct genl *req, uint16_t type)
92 struct nlattr *start = (struct nlattr *)((char *)req +
93 NLMSG_ALIGN(req->n.nlmsg_len));
95 start->nla_type = NLA_F_NESTED | type;
96 req->n.nlmsg_len += NLMSG_ALIGN(sizeof(struct nlattr));
100 static void end_nest_attr(struct genl *req, struct nlattr *start)
102 start->nla_len = (__u16)((char *)req +
103 NLMSG_ALIGN(req->n.nlmsg_len) - (char *)start);
106 static void add_string_attr(struct genl *req, const char *str, int type)
108 add_value_attr(req, str, strlen(str) + 1, type);
111 static void add_uint64_attr(struct genl *req, const uint64_t v, int type)
113 add_value_attr(req, &v, sizeof(v), type);
116 /* macros or templare, due uint64 and uint32 is the same functions */
117 static void add_uint32_attr(struct genl *req, const uint32_t v, int type)
119 add_value_attr(req, &v, sizeof(v), type);
122 static stc_error_e send_nfacct_request(int sock, struct genl *req)
124 struct sockaddr_nl nladdr = {.nl_family = AF_NETLINK};
125 int ret = sendto(sock, (char *)(&req->n), req->n.nlmsg_len, 0,
126 (struct sockaddr *)&nladdr, sizeof(nladdr));
127 ret_value_msg_if(ret < 0, STC_ERROR_FAIL,
128 "Failed to send nfacct request, error [%d]", ret);
130 return STC_ERROR_NONE;
133 static stc_error_e nfacct_send_new(nfacct_rule_s *counter)
135 int ret = STC_ERROR_NONE;
136 struct genl *req = MALLOC0(struct genl, 1);
138 STC_LOGE("Failed allocate memory to genl request message"); //LCOV_EXCL_LINE
139 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
142 prepare_netlink_msg(req, NFNL_MSG_ACCT_NEW, NLM_F_CREATE | NLM_F_ACK);
143 add_string_attr(req, counter->name, NFACCT_NAME);
146 STC_LOGD("counter name %s", counter->name); //LCOV_EXCL_LINE
149 add_uint64_attr(req, 0, NFACCT_PKTS);
150 add_uint64_attr(req, 0, NFACCT_BYTES);
152 if (counter->quota) {
153 STC_LOGD("quota bytes %"PRId64, counter->quota);
155 add_uint32_attr(req, htobe32(NFACCT_F_QUOTA_BYTES),
157 add_uint64_attr(req, htobe64(counter->quota), NFACCT_QUOTA);
161 ret = send_nfacct_request(counter->carg->sock, req);
166 stc_error_e nfacct_send_del(nfacct_rule_s *counter)
168 int ret = STC_ERROR_NONE;
169 struct genl *req = MALLOC0(struct genl, 1);
171 STC_LOGE("Failed allocate memory to genl request message"); //LCOV_EXCL_LINE
172 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
176 STC_LOGD("send remove request for %s", counter->name); //LCOV_EXCL_LINE
178 prepare_netlink_msg(req, NFNL_MSG_ACCT_DEL, NLM_F_ACK);
179 add_string_attr(req, counter->name, NFACCT_NAME);
181 ret = send_nfacct_request(counter->carg->sock, req);
185 #define NFACCT_F_QUOTAS (NFACCT_F_QUOTA_BYTES | NFACCT_F_QUOTA_PKTS)
187 static stc_error_e internal_nfacct_send_get(struct counter_arg *carg,
188 enum nfnl_acct_msg_types get_type,
190 int mask, int filter)
192 int ret = STC_ERROR_NONE;
194 int flag = !name ? NLM_F_DUMP : 0;
195 struct genl *req = MALLOC0(struct genl, 1);
197 STC_LOGE("Failed allocate memory to genl request message"); //LCOV_EXCL_LINE
198 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
201 prepare_netlink_msg(req, get_type, flag);
202 /* due we don't get counter with quota any where else,
203 * here we will request just counters by default */
205 add_string_attr(req, name, NFACCT_NAME);
207 na = start_nest_attr(req, NFACCT_FILTER);
208 add_uint32_attr(req, htonl(mask), NFACCT_FILTER_ATTR_MASK);
209 add_uint32_attr(req, htonl(filter), NFACCT_FILTER_ATTR_VALUE);
210 end_nest_attr(req, na);
212 ret = send_nfacct_request(carg->sock, req);
217 stc_error_e nfacct_send_get_counters(struct counter_arg *carg, const char *name)
219 /* get and reset countes value */
220 return internal_nfacct_send_get(carg, NFNL_MSG_ACCT_GET_CTRZERO, name,
224 stc_error_e nfacct_send_get_quotas(struct counter_arg *carg, const char *name)
226 /* just get counters */
227 return internal_nfacct_send_get(carg, NFNL_MSG_ACCT_GET, name,
228 NFACCT_F_QUOTA_BYTES,
229 NFACCT_F_QUOTA_BYTES);
232 stc_error_e nfacct_send_get_all(struct counter_arg *carg)
234 /* get and reset everything, used when quiting */
235 return internal_nfacct_send_get(carg, NFNL_MSG_ACCT_GET_CTRZERO, NULL,
239 stc_error_e nfacct_send_get(nfacct_rule_s *rule)
241 if (rule->intend == NFACCT_BLOCK || rule->intend == NFACCT_WARN)
242 return nfacct_send_get_quotas(rule->carg, rule->name);
243 else if (rule->intend == NFACCT_COUNTER)
244 return nfacct_send_get_counters(rule->carg, rule->name);
246 return STC_ERROR_INVALID_PARAMETER;
249 static nfacct_rule_direction convert_to_iotype(int type)
251 return (type < NFACCT_COUNTER_LAST_ELEM &&
252 type > NFACCT_COUNTER_UNKNOWN) ? type : NFACCT_COUNTER_UNKNOWN;
255 static stc_iface_type_e convert_to_iftype(int type)
257 return (type < STC_IFACE_LAST_ELEM &&
258 type > STC_IFACE_UNKNOWN) ? type : STC_IFACE_UNKNOWN;
261 bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt)
267 char *save_ptr = NULL;
268 char name[NFACCT_NAME_MAX] = {0}; /* parse buffer to avoid cnt_name modification */
270 strncpy(name, cnt_name, sizeof(name) - 1);
274 cnt->intend = NFACCT_COUNTER;
277 cnt->intend = NFACCT_WARN;
280 cnt->intend = NFACCT_BLOCK;
283 cnt->intend = NFACCT_ALLOW;
286 cnt->intend = NFACCT_TETH_COUNTER; //LCOV_EXCL_LINE
287 break; //LCOV_EXCL_LINE
292 STRING_SAVE_COPY(cnt->name, cnt_name);
295 if (cnt->intend == NFACCT_TETH_COUNTER) {
296 char ifname_buf[MAX_IFACE_LENGTH];
298 stc_iface_type_e iface;
299 /* tbnep+:seth_w0; means comes by bt go away by mobile interface,
300 * it's outgoing traffic, due all tethering is mobile databased */
301 iftype_part = strchr(name, ':');
302 ret_value_msg_if(iftype_part == NULL,
303 false, "Invalid format of the tethering counter %s", name);
304 ifname_len = iftype_part - name - 1;
305 strncpy(ifname_buf, name + 1, ifname_len); /* skip first t */
306 ifname_buf[ifname_len] = '\0';
307 iface = get_iftype_by_name(ifname_buf);
308 /* check first part is it datacall */
309 if (iface == STC_IFACE_DATACALL) {
310 strncpy(cnt->ifname, ifname_buf, MAX_IFACE_LENGTH - 1);
311 cnt->iotype = NFACCT_COUNTER_IN;
313 /* +1, due : symbol and till the end of cnt_name */
314 strncpy(ifname_buf, iftype_part + 1, MAX_IFACE_LENGTH - 1);
315 iface = get_iftype_by_name(ifname_buf);
316 if (iface == STC_IFACE_DATACALL) {
317 cnt->iotype = NFACCT_COUNTER_OUT;
318 strncpy(cnt->ifname, ifname_buf, MAX_IFACE_LENGTH - 1);
322 if (cnt->iotype == NFACCT_COUNTER_UNKNOWN) {
323 STC_LOGE("can't determine tethering direction %s", name);
326 cnt->iftype = STC_IFACE_DATACALL;
327 cnt->classid = STC_TETHERING_APP_CLASSID;
332 io_part = strtok_r(name, "_", &save_ptr);
334 cnt->iotype = convert_to_iotype(atoi(io_part + 1));
338 iftype_part = strtok_r(NULL, "_", &save_ptr);
339 if (iftype_part != NULL)
340 cnt->iftype = convert_to_iftype(atoi(iftype_part));
344 classid_part = strtok_r(NULL, "_", &save_ptr);
345 if (classid_part != NULL)
346 cnt->classid = atoi(classid_part);
348 cnt->classid = STC_ALL_APP_CLASSID;
349 return cnt->intend == NFACCT_BLOCK ? true : false;
352 ifname_part = strtok_r(NULL, "\0", &save_ptr);
353 if (ifname_part != NULL)
354 STRING_SAVE_COPY(cnt->ifname, ifname_part);
361 static void _process_answer(struct netlink_serialization_params *params)
364 struct rtattr *attr_list[__NFACCT_MAX] = {0};
365 struct counter_arg *carg = params->carg;
366 struct genl *ans = params->ans;;
367 struct nlmsghdr *nlhdr = &ans->n;
368 int len = GENLMSG_PAYLOAD(nlhdr);
369 int ans_len = carg->ans_len;
374 /* parse reply message */
375 na = (struct rtattr *)GENLMSG_DATA(ans);
377 while (NLMSG_OK(nlhdr, ans_len)) {
378 fill_attribute_list(attr_list, NFACCT_MAX,
380 if (!attr_list[NFACCT_NAME] ||
381 !attr_list[NFACCT_BYTES])
383 params->eval_attr(attr_list, carg);
386 nlhdr = NLMSG_NEXT(nlhdr, ans_len);
389 na = (struct rtattr *)GENLMSG_DATA(nlhdr);
392 if (params->post_eval_attr)
393 params->post_eval_attr(carg);
396 netlink_serialization_command *
397 netlink_create_command(struct netlink_serialization_params *params)
399 static netlink_serialization_command command = {0,};
400 command.deserialize_answer = _process_answer;
401 command.params = *params;
405 static char *get_iptables_cmd(const nfacct_rule_action action)
407 if (action == NFACCT_ACTION_APPEND)
409 else if (action == NFACCT_ACTION_DELETE)
411 else if (action == NFACCT_ACTION_INSERT)
417 static char *get_iptables_chain(const nfacct_rule_direction iotype)
419 if (iotype == NFACCT_COUNTER_IN)
421 else if (iotype == NFACCT_COUNTER_OUT)
422 return STC_OUT_CHAIN;
423 else if (iotype == NFACCT_COUNTER_FORWARD) //LCOV_EXCL_LINE
424 return STC_FRWD_CHAIN; //LCOV_EXCL_LINE
429 static char *get_iptables_jump(const nfacct_rule_jump jump)
431 if (jump == NFACCT_JUMP_ACCEPT)
433 else if (jump == NFACCT_JUMP_REJECT)
440 static char *choose_iftype_name(nfacct_rule_s *rule)
442 return strlen(rule->ifname) != 0 ? rule->ifname :
443 get_iftype_name(rule->iftype);
447 static stc_error_e exec_iptables_cmd(nfacct_rule_s *rule)
449 stc_error_e ret = STC_ERROR_NONE;
450 iptables_ip_type_e iptype;
451 iptables_rule_s iptables_rule;
452 memset(&iptables_rule, 0, sizeof(iptables_rule_s));
454 iptables_rule.nfacct_name = g_strdup(rule->name);
455 iptables_rule.ifname = g_strdup(rule->ifname);
456 iptables_rule.target = g_strdup(get_iptables_jump(rule->jump));
457 iptables_rule.chain = g_strdup(get_iptables_chain(rule->iotype));
458 iptables_rule.classid = rule->classid;
459 iptables_rule.direction = (rule->iotype & NFACCT_COUNTER_IN) ?
460 IPTABLES_DIRECTION_IN : IPTABLES_DIRECTION_OUT;
461 iptype = (iptables_ip_type_e)rule->iptype;
463 if (rule->action == NFACCT_ACTION_DELETE) {
464 /* delete interface rule */
465 ret = iptables_remove(&iptables_rule, iptype);
467 /* add interface rule */
468 ret = iptables_add(&iptables_rule, iptype);
471 g_free(iptables_rule.nfacct_name);
472 g_free(iptables_rule.ifname);
473 g_free(iptables_rule.target);
474 g_free(iptables_rule.chain);
479 static stc_error_e produce_app_rule(nfacct_rule_s *rule)
482 return STC_ERROR_INVALID_PARAMETER;
484 char *set_cmd = get_iptables_cmd(rule->action);
485 char *jump_cmd = get_iptables_jump(rule->jump);
486 char nfacct_buf[sizeof(NFACCT_NAME_MOD) +
487 3*MAX_DEC_SIZE(int) + 4];
488 stc_error_e ret = STC_ERROR_NONE;
491 if (rule->iotype & NFACCT_COUNTER_IN) {
492 rule->quota = rule->rcv_limit;
493 rule->iotype = NFACCT_COUNTER_IN;
494 generate_counter_name(rule);
496 /* to support quated counter we need nfacct,
497 * don't use it in case of just block without a limit
498 * iow, send_limit = 0 and rcv_limit 0 */
499 if (rule->action != NFACCT_ACTION_DELETE) {
500 ret = nfacct_send_del(rule);
501 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
502 "can't del quota counter");
504 ret = nfacct_send_new(rule);
505 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
506 "can't set nfacct counter");
510 /* we have a counter, let's key in a rule, drop in case of
511 * send_limit/rcv_limit */
512 ret = snprintf(nfacct_buf, sizeof(nfacct_buf), NFACCT_NAME_MOD,
514 ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0,
515 STC_ERROR_FAIL, "Not enought buffer");
517 ret = exec_iptables_cmd(rule);
518 ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
519 "Can't set conditional block for ingress"
520 " traffic, for classid %u, cmd %s, j %s",
521 rule->classid, set_cmd, jump_cmd);
523 /* remove in any case */
524 if (rule->action == NFACCT_ACTION_DELETE) {
525 /* TODO here and everywhere should be not just a del,
526 * here should be get counted value and than
527 * set new counter with that value, but it's minor issue,
528 * due it's not clear when actual counters was stored,
529 * and based on which value settings made such decition */
530 rule->iptables_rule = nfacct_send_del;
531 set_finalize_flag(rule);
532 nfacct_send_get(rule);
533 ret = nfacct_send_del(rule);
534 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
535 "can't del quota counter");
539 if (rule->iotype & NFACCT_COUNTER_OUT) {
541 rule->iotype = NFACCT_COUNTER_OUT;
542 rule->quota = rule->send_limit;
543 generate_counter_name(rule);
544 if (rule->action != NFACCT_ACTION_DELETE) {
545 ret = nfacct_send_del(rule);
546 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
547 "can't del quota counter");
549 ret = nfacct_send_new(rule);
550 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
551 "can't set quota counter");
555 ret = snprintf(nfacct_buf, sizeof(nfacct_buf), NFACCT_NAME_MOD,
557 ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0,
558 STC_ERROR_FAIL, "Not enought buffer");
560 ret = exec_iptables_cmd(rule);
561 ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
562 "Can't set conditional block for engress"
563 " traffic, for classid %u, cmd %s, j %s",
564 rule->classid, set_cmd, jump_cmd);
566 if (rule->action == NFACCT_ACTION_DELETE) {
567 rule->iptables_rule = nfacct_send_del;
568 /* not effective, it's better to replace
569 * set_finalize_flag by set_property,
570 * due keep_counter it necessary only for
571 * setting iptables_rule */
572 set_finalize_flag(rule);
573 nfacct_send_get(rule);
574 ret = nfacct_send_del(rule);
575 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
576 "can't del quota counter");
579 return STC_ERROR_NONE;
582 static stc_error_e produce_iface_rule(nfacct_rule_s *rule)
585 return STC_ERROR_INVALID_PARAMETER;
587 char *set_cmd = get_iptables_cmd(rule->action);
588 char *jump_cmd = get_iptables_jump(rule->jump);
589 char nfacct_buf[sizeof(NFACCT_NAME_MOD) +
590 3*MAX_DEC_SIZE(int) + 4];
591 uint32_t classid = rule->classid;
594 if (rule->iotype & NFACCT_COUNTER_IN) {
596 rule->iotype = NFACCT_COUNTER_IN;
597 rule->quota = rule->rcv_limit;
598 generate_counter_name(rule);
600 if (rule->action != NFACCT_ACTION_DELETE) {
601 /* send delete comman in case of creation,
602 * because nfacct doesn't reset value for nfacct quota
603 * in case of quota existing */
604 ret = nfacct_send_del(rule);
605 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
606 "can't del quota counter");
608 ret = nfacct_send_new(rule);
609 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
610 "can't set quota counter");
614 ret = snprintf(nfacct_buf, sizeof(nfacct_buf),
615 NFACCT_NAME_MOD, rule->name);
616 ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0,
617 STC_ERROR_FAIL, "Not enought buffer");
619 classid = rule->classid;
622 ret = exec_iptables_cmd(rule);
623 ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
624 "Can't set conditional block for ingress"
625 " traffic, for iftype %d, cmd %s, j %s",
626 rule->iftype, set_cmd, jump_cmd);
630 if (rule->intend == NFACCT_WARN ||
631 rule->intend == NFACCT_BLOCK) {
632 /* RULE_IFACE_OUT is not a misprint here */
633 nfacct_rule_direction temp_iotype = rule->iotype;
635 rule->iotype = NFACCT_COUNTER_FORWARD;
636 ret = exec_iptables_cmd(rule);
637 rule->iotype = temp_iotype;
638 ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
639 "Can't set forward rule for ingress "
640 "traffic, for iftype %d, cmd %s, j %s",
641 rule->iftype, set_cmd, jump_cmd);
645 if (rule->action == NFACCT_ACTION_DELETE) {
646 rule->iptables_rule = nfacct_send_del;
647 set_finalize_flag(rule);
648 nfacct_send_get(rule);
649 ret = nfacct_send_del(rule);
650 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
651 "can't del quota counter");
656 rule->classid = classid;
658 if (rule->iotype & NFACCT_COUNTER_OUT) {
660 rule->iotype = NFACCT_COUNTER_OUT;
661 rule->quota = rule->send_limit;
662 generate_counter_name(rule);
664 if (rule->action != NFACCT_ACTION_DELETE) {
665 /* send delete comman in case of creation,
666 * because nfacct doesn't reset value for nfacct quota
667 * in case of quota existing */
668 ret = nfacct_send_del(rule);
669 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
670 "can't del quota counter");
672 ret = nfacct_send_new(rule);
673 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
674 "can't set quota counter");
678 ret = snprintf(nfacct_buf, sizeof(nfacct_buf),
679 NFACCT_NAME_MOD, rule->name);
680 ret_value_msg_if(ret > sizeof(nfacct_buf) || ret < 0,
681 STC_ERROR_FAIL, "Not enough buffer");
683 classid = rule->classid;
686 ret = exec_iptables_cmd(rule);
687 ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
688 "Can't set conditional block for "
689 "engress traffic, for iftype %d, cmd %s, j %s",
690 rule->iftype, set_cmd, jump_cmd);
694 if (rule->intend == NFACCT_WARN ||
695 rule->intend == NFACCT_BLOCK) {
696 nfacct_rule_direction temp_iotype = rule->iotype;
698 rule->iotype = NFACCT_COUNTER_OUT;
699 ret = exec_iptables_cmd(rule);
700 rule->iotype = temp_iotype;
701 ret_value_msg_if(ret != STC_ERROR_NONE, STC_ERROR_FAIL,
702 "Can't set forward rule for engress "
703 "traffic, for iftype %d, cmd %s, j %s",
704 rule->iftype, set_cmd, jump_cmd);
708 if (rule->action == NFACCT_ACTION_DELETE) {
709 rule->iptables_rule = nfacct_send_del;
710 set_finalize_flag(rule);
711 nfacct_send_get(rule);
712 ret = nfacct_send_del(rule);
713 ret_value_msg_if(ret != STC_ERROR_NONE, ret,
714 "can't del quota counter");
718 return STC_ERROR_NONE;
721 stc_error_e produce_net_rule(nfacct_rule_s *rule)
723 stc_error_e ret = STC_ERROR_NONE;
726 return STC_ERROR_INVALID_PARAMETER;
728 if (rule->action == NFACCT_ACTION_APPEND &&
729 rule->intend == NFACCT_WARN &&
730 !rule->send_limit && !rule->rcv_limit)
731 return STC_ERROR_NONE;
733 if (rule->classid != STC_ALL_APP_CLASSID &&
734 rule->classid != STC_TETHERING_APP_CLASSID &&
735 rule->classid != STC_TOTAL_DATACALL_CLASSID &&
736 rule->classid != STC_TOTAL_WIFI_CLASSID &&
737 rule->classid != STC_TOTAL_BLUETOOTH_CLASSID &&
738 rule->classid != STC_TOTAL_IPV4_CLASSID &&
739 rule->classid != STC_TOTAL_IPV6_CLASSID)
740 ret = produce_app_rule(rule);
742 ret = produce_iface_rule(rule);
747 void generate_counter_name(nfacct_rule_s *counter)
749 char warn_symbol = 'c';
750 if (!strlen(counter->ifname)) {
751 char *iftype_name = get_iftype_name(counter->iftype);
752 /* trace counter name, maybe name was already generated */
753 ret_msg_if(iftype_name == NULL,
754 "Can't get interface name for counter %s, iftype %d)!",
755 counter->name, counter->iftype);
756 STRING_SAVE_COPY(counter->ifname, iftype_name);
759 if (counter->intend == NFACCT_WARN)
761 else if (counter->intend == NFACCT_BLOCK)
763 else if (counter->intend == NFACCT_ALLOW)
765 snprintf(counter->name, NFACCT_NAME_MAX, "%c%d_%d_%d_%s",
766 warn_symbol, counter->iotype, counter->iftype,
767 counter->classid, counter->ifname);