Add some chains to separate monitoring and restriction
[platform/core/connectivity/stc-manager.git] / src / helper / helper-nfacct-rule.c
old mode 100755 (executable)
new mode 100644 (file)
index 8f5dfee..4a80fca
@@ -142,9 +142,6 @@ static stc_error_e nfacct_send_new(nfacct_rule_s *counter)
        prepare_netlink_msg(req, NFNL_MSG_ACCT_NEW, NLM_F_CREATE | NLM_F_ACK);
        add_string_attr(req, counter->name, NFACCT_NAME);
 
-       if (STC_DEBUG_LOG)
-               STC_LOGD("counter name %s", counter->name); //LCOV_EXCL_LINE
-
        /* padding */
        add_uint64_attr(req, 0, NFACCT_PKTS);
        add_uint64_attr(req, 0, NFACCT_BYTES);
@@ -172,9 +169,6 @@ stc_error_e nfacct_send_del(nfacct_rule_s *counter)
                return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
        }
 
-       if (STC_DEBUG_LOG)
-               STC_LOGD("send remove request for %s", counter->name); //LCOV_EXCL_LINE
-
        prepare_netlink_msg(req, NFNL_MSG_ACCT_DEL, NLM_F_ACK);
        add_string_attr(req, counter->name, NFACCT_NAME);
 
@@ -255,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)
@@ -279,6 +273,9 @@ bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt)
        case 'r':
                cnt->intend  = NFACCT_BLOCK;
                break;
+       case 'a':
+               cnt->intend  = NFACCT_ALLOW;
+               break;
        case 't':
                cnt->intend  = NFACCT_TETH_COUNTER; //LCOV_EXCL_LINE
                break; //LCOV_EXCL_LINE
@@ -288,6 +285,14 @@ bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt)
 
        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];
@@ -325,6 +330,7 @@ bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt)
                return true;
        }
        //LCOV_EXCL_STOP
+#endif
 
        io_part = strtok_r(name, "_", &save_ptr);
        if (io_part != NULL)
@@ -411,14 +417,51 @@ static char *get_iptables_cmd(const nfacct_rule_action action)
        return "";
 }
 
-static char *get_iptables_chain(const nfacct_rule_direction iotype)
+static char *get_iptables_chain(uint32_t classid,
+                               const nfacct_rule_direction iotype,
+                               const stc_app_state_e app_state,
+                               const nfacct_rule_intend intend)
 {
-       if (iotype == NFACCT_COUNTER_IN)
-               return STC_IN_CHAIN;
-       else if (iotype == NFACCT_COUNTER_OUT)
-               return STC_OUT_CHAIN;
-       else if (iotype == NFACCT_COUNTER_FORWARD) //LCOV_EXCL_LINE
-               return STC_FRWD_CHAIN; //LCOV_EXCL_LINE
+       if (iotype == NFACCT_COUNTER_IN) {
+               if (intend == NFACCT_COUNTER ||
+                       intend == NFACCT_TETH_COUNTER) {
+                       if (app_state == STC_APP_STATE_FOREGROUND) {
+                               if (intend == NFACCT_ALLOW)
+                                       return STC_IN_ACCEPT_CHAIN;
+                               else
+                                       return STC_IN_FG_CHAIN;
+                       } else
+                               return STC_IN_BG_CHAIN;
+               } else if (intend == NFACCT_ALLOW ||
+                               intend == NFACCT_TETH_ALLOW) {
+                       return STC_IN_ACCEPT_CHAIN;
+               } else {
+                       if (classid == STC_BACKGROUND_APP_CLASSID)
+                               return STC_IN_BG_DROP_CHAIN;
+                       else
+                               return STC_IN_DROP_CHAIN;
+               }
+       } else if (iotype == NFACCT_COUNTER_OUT) {
+               if (intend == NFACCT_COUNTER ||
+                       intend == NFACCT_TETH_COUNTER) {
+                       if (app_state == STC_APP_STATE_FOREGROUND) {
+                               if (intend == NFACCT_ALLOW)
+                                       return STC_OUT_ACCEPT_CHAIN;
+                               else
+                                       return STC_OUT_FG_CHAIN;
+                       } else
+                               return STC_OUT_BG_CHAIN;
+               } else if (intend == NFACCT_ALLOW ||
+                               intend == NFACCT_TETH_ALLOW) {
+                       return STC_OUT_ACCEPT_CHAIN;
+               } else {
+                       if (classid == STC_BACKGROUND_APP_CLASSID)
+                               return STC_OUT_BG_DROP_CHAIN;
+                       else
+                               return STC_OUT_DROP_CHAIN;
+               }
+       } else if (iotype == NFACCT_COUNTER_FORWARD)
+               return STC_FRWD_CHAIN;
 
        return "";
 }
@@ -444,22 +487,51 @@ static char *choose_iftype_name(nfacct_rule_s *rule)
 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));
-       iptables_rule.chain = g_strdup(get_iptables_chain(rule->iotype));
-       iptables_rule.classid = rule->classid;
-       iptables_rule.direction = (rule->iotype & NFACCT_COUNTER_IN) ? 0 : 1;
+
+       /* 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->classid,
+                                                               rule->iotype, rule->app_state, rule->intend));
+
+       if (rule->classid < STC_RESERVED_CLASSID_MAX)
+               iptables_rule.classid = STC_UNKNOWN_CLASSID;
+       else
+               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)
+               inet_aton(rule->src_ip1, &iptables_rule.s_ip1);
+       if (rule->src_ip2)
+               inet_aton(rule->src_ip2, &iptables_rule.s_ip2);
+       if (rule->dst_ip1)
+               inet_aton(rule->dst_ip1, &iptables_rule.d_ip1);
+       if (rule->dst_ip2)
+               inet_aton(rule->dst_ip2, &iptables_rule.d_ip2);
 
        if (rule->action == NFACCT_ACTION_DELETE) {
                /* delete interface rule */
-               ret = iptables_remove(&iptables_rule);
+               ret = iptables_remove(&iptables_rule, iptype);
        } else {
                /* add interface rule */
-               ret = iptables_add(&iptables_rule);
+               ret = iptables_add(&iptables_rule, iptype);
        }
 
        g_free(iptables_rule.nfacct_name);
@@ -478,8 +550,9 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule)
        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;
+       uint32_t classid = rule->classid;
 
        /* income part */
        if (rule->iotype & NFACCT_COUNTER_IN) {
@@ -508,7 +581,23 @@ 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");
 
+               /* 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",
@@ -551,7 +640,23 @@ 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");
 
+               /* 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",
@@ -581,11 +686,9 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule)
        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;
 
-       rule->classid = 0;
-
        if (rule->iotype & NFACCT_COUNTER_IN) {
                /* income part */
                rule->iotype = NFACCT_COUNTER_IN;
@@ -702,6 +805,7 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule)
                }
                //LCOV_EXCL_STOP
        }
+
        return STC_ERROR_NONE;
 }
 
@@ -719,6 +823,7 @@ stc_error_e produce_net_rule(nfacct_rule_s *rule)
 
        if (rule->classid != STC_ALL_APP_CLASSID &&
            rule->classid != STC_TETHERING_APP_CLASSID &&
+           rule->classid != STC_BACKGROUND_APP_CLASSID &&
            rule->classid != STC_TOTAL_DATACALL_CLASSID &&
            rule->classid != STC_TOTAL_WIFI_CLASSID &&
            rule->classid != STC_TOTAL_BLUETOOTH_CLASSID &&
@@ -743,10 +848,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);