Merge "Return errors to caller" into tizen_5.5
[platform/core/connectivity/stc-manager.git] / src / helper / helper-nfacct-rule.c
old mode 100644 (file)
new mode 100755 (executable)
index 70b29a5..ff703d3
@@ -108,7 +108,7 @@ static void add_string_attr(struct genl *req, const char *str, int type)
        add_value_attr(req, str, strlen(str) + 1, type);
 }
 
-static void add_uint64_attr(struct genl *req, const uint64_t v, int type)
+static void add_uint64_attr(struct genl *req, const long long unsigned int v, int type)
 {
        add_value_attr(req, &v, sizeof(v), type);
 }
@@ -147,7 +147,7 @@ static stc_error_e nfacct_send_new(nfacct_rule_s *counter)
        add_uint64_attr(req, 0, NFACCT_BYTES);
        //LCOV_EXCL_START
        if (counter->quota) {
-               STC_LOGD("quota bytes %"PRId64, counter->quota);
+               STC_LOGD("quota bytes %lld", counter->quota);
 
                add_uint32_attr(req, htobe32(NFACCT_F_QUOTA_BYTES),
                                NFACCT_FLAGS);
@@ -223,7 +223,7 @@ stc_error_e nfacct_send_get_quotas(struct counter_arg *carg, const char *name)
                                        NFACCT_F_QUOTA_BYTES);
 }
 
-stc_error_e nfacct_send_get_all(struct counter_arg *carg)
+API stc_error_e nfacct_send_get_all(struct counter_arg *carg)
 {
        /* get and reset everything, used when quiting */
        return internal_nfacct_send_get(carg, NFNL_MSG_ACCT_GET_CTRZERO, NULL,
@@ -252,7 +252,7 @@ static stc_iface_type_e convert_to_iftype(int type)
                        type > STC_IFACE_UNKNOWN) ? type : STC_IFACE_UNKNOWN;
 }
 
-bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt)
+API bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt)
 {
        char *iftype_part;
        char *classid_part;
@@ -285,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];
@@ -322,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)
@@ -387,7 +396,7 @@ next:
                params->post_eval_attr(carg);
 }
 
-netlink_serialization_command *
+API netlink_serialization_command *
 netlink_create_command(struct netlink_serialization_params *params)
 {
        static netlink_serialization_command command = {0,};
@@ -408,14 +417,45 @@ 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)
+                               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)
+                               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 "";
 }
@@ -449,13 +489,19 @@ static stc_error_e exec_iptables_cmd(nfacct_rule_s *rule)
        iptables_rule.ifname = g_strdup(rule->ifname);
        iptables_rule.target = g_strdup(get_iptables_jump(rule->jump));
 
-       /* In case of tehering use chain 'STC_TETHER' */
-       if (rule->intend == NFACCT_TETH_COUNTER)
+       /* 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.chain = g_strdup(get_iptables_chain(rule->classid,
+                                                               rule->iotype, rule->app_state, rule->intend));
 
-       iptables_rule.classid = rule->classid;
+       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;
@@ -465,14 +511,33 @@ static stc_error_e exec_iptables_cmd(nfacct_rule_s *rule)
        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->src_ip1) {
+               if (!inet_aton(rule->src_ip1, &iptables_rule.s_ip1)) {
+                       ret = STC_ERROR_INVALID_PARAMETER;
+                       goto free;
+               }
+       }
+
+       if (rule->src_ip2) {
+               if (!inet_aton(rule->src_ip2, &iptables_rule.s_ip2)) {
+                       ret = STC_ERROR_INVALID_PARAMETER;
+                       goto free;
+               }
+       }
+
+       if (rule->dst_ip1) {
+               if (!inet_aton(rule->dst_ip1, &iptables_rule.d_ip1)) {
+                       ret = STC_ERROR_INVALID_PARAMETER;
+                       goto free;
+               }
+       }
+
+       if (rule->dst_ip2) {
+               if (!inet_aton(rule->dst_ip2, &iptables_rule.d_ip2)) {
+                       ret = STC_ERROR_INVALID_PARAMETER;
+                       goto free;
+               }
+       }
 
        if (rule->action == NFACCT_ACTION_DELETE) {
                /* delete interface rule */
@@ -482,6 +547,7 @@ static stc_error_e exec_iptables_cmd(nfacct_rule_s *rule)
                ret = iptables_add(&iptables_rule, iptype);
        }
 
+free:
        g_free(iptables_rule.nfacct_name);
        g_free(iptables_rule.ifname);
        g_free(iptables_rule.target);
@@ -531,7 +597,9 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule)
 
                /* cgroup extention on FORWARD chain are not allowed
                 * remove classid info in case of tethering rules */
-               if (rule->intend == NFACCT_TETH_COUNTER) {
+               if (rule->intend == NFACCT_TETH_COUNTER ||
+                               rule->intend == NFACCT_TETH_ALLOW ||
+                               rule->intend == NFACCT_TETH_BLOCK) {
                        classid = rule->classid;
                        rule->classid = 0;
                }
@@ -539,7 +607,9 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule)
                ret = exec_iptables_cmd(rule);
 
                /* restore the classid info in case of tethering rule */
-               if (rule->intend == NFACCT_TETH_COUNTER)
+               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,
@@ -586,7 +656,9 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule)
 
                /* cgroup extention on FORWARD chain are not allowed
                 * remove classid info in case of tethering rules */
-               if (rule->intend == NFACCT_TETH_COUNTER) {
+               if (rule->intend == NFACCT_TETH_COUNTER ||
+                               rule->intend == NFACCT_TETH_ALLOW ||
+                               rule->intend == NFACCT_TETH_BLOCK) {
                        classid = rule->classid;
                        rule->classid = 0;
                }
@@ -594,7 +666,9 @@ static stc_error_e produce_app_rule(nfacct_rule_s *rule)
                ret = exec_iptables_cmd(rule);
 
                /* restore the classid info in case of tethering rule */
-               if (rule->intend == NFACCT_TETH_COUNTER)
+               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,
@@ -627,7 +701,6 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule)
        char *jump_cmd = get_iptables_jump(rule->jump);
        char nfacct_buf[sizeof(NFACCT_NAME_MOD) +
                3*MAX_DEC_SIZE(int) + 4 + 1];
-       uint32_t classid = rule->classid;
        stc_error_e ret;
 
        if (rule->iotype & NFACCT_COUNTER_IN) {
@@ -655,9 +728,6 @@ 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");
 
-               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"
@@ -692,8 +762,6 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule)
                //LCOV_EXCL_STOP
        }
 
-       rule->classid = classid;
-
        if (rule->iotype & NFACCT_COUNTER_OUT) {
                /* outcome part */
                rule->iotype = NFACCT_COUNTER_OUT;
@@ -719,9 +787,6 @@ 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");
 
-               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 "
@@ -754,10 +819,11 @@ static stc_error_e produce_iface_rule(nfacct_rule_s *rule)
                }
                //LCOV_EXCL_STOP
        }
+
        return STC_ERROR_NONE;
 }
 
-stc_error_e produce_net_rule(nfacct_rule_s *rule)
+API stc_error_e produce_net_rule(nfacct_rule_s *rule)
 {
        stc_error_e ret = STC_ERROR_NONE;
 
@@ -771,6 +837,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 &&
@@ -783,6 +850,88 @@ stc_error_e produce_net_rule(nfacct_rule_s *rule)
        return ret;
 }
 
+static stc_error_e append_iptables_cmd(GSList **iptables_list, nfacct_rule_s *rule)
+{
+       iptables_rule_s *iptables_rule = NULL;
+
+       iptables_rule = MALLOC0(iptables_rule_s, 1);
+       if (!iptables_rule)
+               return STC_ERROR_OUT_OF_MEMORY;
+
+       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->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;
+
+       *iptables_list = g_slist_append(*iptables_list, iptables_rule);
+
+       return STC_ERROR_NONE;
+}
+
+static void iptables_list_free(gpointer value)
+{
+       iptables_rule_s *iptables_rule = (iptables_rule_s *)value;
+
+       g_free(iptables_rule->chain);
+       g_free(iptables_rule->nfacct_name);
+       g_free(iptables_rule->ifname);
+       g_free(iptables_rule->target);
+       g_free(iptables_rule);
+}
+
+API stc_error_e produce_net_list(GSList *rule_list,
+               nfacct_rule_iptype iptype, nfacct_rule_action action)
+{
+       GSList *list = NULL;
+       GSList *iptables_list = NULL;
+       stc_error_e ret = STC_ERROR_NONE;
+
+       for (list = rule_list; list; list = list->next) {
+               nfacct_rule_s *rule = list->data;
+
+               if (rule->action == NFACCT_ACTION_APPEND &&
+                       rule->intend == NFACCT_WARN &&
+                       !rule->send_limit && !rule->rcv_limit)
+                       continue;
+
+               generate_counter_name(rule);
+               if (rule->action != NFACCT_ACTION_DELETE) {
+                       ret = nfacct_send_del(rule);
+                       if (ret != STC_ERROR_NONE)
+                               continue;
+
+                       ret = nfacct_send_new(rule);
+                       if (ret != STC_ERROR_NONE)
+                               continue;
+               }
+
+               append_iptables_cmd(&iptables_list, rule);
+       }
+
+       if (action == NFACCT_ACTION_INSERT ||
+               action == NFACCT_ACTION_APPEND)
+               ret = iptables_add_list(iptables_list, iptype);
+       else if (action == NFACCT_ACTION_DELETE)
+               ret = iptables_remove_list(iptables_list, iptype);
+
+       for (list = rule_list; list; list = list->next) {
+               nfacct_rule_s *rule = list->data;
+
+               if (rule->action == NFACCT_ACTION_DELETE)
+                       nfacct_send_del(rule);
+       }
+
+       g_slist_free_full(iptables_list, iptables_list_free);
+       return ret;
+}
+
 void generate_counter_name(nfacct_rule_s *counter)
 {
        char warn_symbol = 'c';
@@ -795,12 +944,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)
+       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);