-/*
- * @file nf-restriction.c
- *
- * @desc Implementation for set up/down restrictions.
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- */
-
-#include "stc-error.h"
-#include "stc-manager.h"
-#include "netlink-restriction.h"
-#include "helper-nfacct-rule.h"
-#include "helper-restriction.h"
-#include "stc-default-connection.h"
-#include "stc-monitor.h"
-#include "counter.h"
-
-static stc_error_e apply_net_restriction(struct nfacct_rule *rule,
- const int64_t send_limit,
- const int64_t rcv_limit)
-{
- nfacct_rule_jump jump;
-
- /* block immediately */
- if (!rcv_limit) { /* for dual nfacct entity for restriction add || !send_limit */
- return produce_net_rule(rule, 0, 0, NFACCT_ACTION_INSERT,
- NFACCT_JUMP_REJECT, NFACCT_COUNTER_OUT);
- }
-
- jump = ((rule->intend == NFACCT_WARN) ?
- NFACCT_JUMP_ACCEPT : NFACCT_JUMP_REJECT);
-
- return produce_net_rule(rule, send_limit, rcv_limit,
- NFACCT_ACTION_APPEND, jump,
- NFACCT_COUNTER_IN | NFACCT_COUNTER_OUT);
-}
-
-static stc_error_e revert_net_restriction(struct nfacct_rule *rule,
- const int64_t send_limit,
- const int64_t rcv_limit)
-{
- nfacct_rule_jump jump = ((rule->intend == NFACCT_WARN) ?
- NFACCT_JUMP_ACCEPT : NFACCT_JUMP_REJECT);
-
- return produce_net_rule(rule, send_limit, rcv_limit,
- NFACCT_ACTION_DELETE, jump,
- NFACCT_COUNTER_IN | NFACCT_COUNTER_OUT);
-
-}
-
-static stc_error_e exclude_net_restriction(struct nfacct_rule *rule)
-{
- /* Idea to remove old counter and insert new one at first position
- * iptables has following architecture: it gets all entries from kernel
- * modifies this list and returns it back, without iptables it could be
- * done for one step, but with iptables cmd 2 steps is necessary */
- rule->intend = NFACCT_COUNTER;
- stc_error_e ret = produce_net_rule(rule, 0, 0, NFACCT_ACTION_DELETE,
- NFACCT_JUMP_UNKNOWN,
- NFACCT_COUNTER_IN | NFACCT_COUNTER_OUT);
-
- ret_value_msg_if(ret != STC_ERROR_NONE, ret, "Failed to delete");
-
- return produce_net_rule(rule, 0, 0,
- NFACCT_ACTION_INSERT, NFACCT_JUMP_UNKNOWN,
- NFACCT_COUNTER_IN | NFACCT_COUNTER_OUT);
-}
-
-stc_error_e send_net_restriction(const enum traffic_restriction_type rst_type,
- const guint32 classid, const int quota_id,
- const stc_iface_type_e iftype,
- const int64_t send_limit,
- const int64_t rcv_limit,
- const int64_t snd_warning_threshold,
- const int64_t rcv_warning_threshold,
- const char *ifname)
-{
- int ret;
- stc_s *stc = stc_get_manager();
- struct counter_arg *carg;
- struct nfacct_rule rule = {
- .name = {0},
- .ifname = {0},
- .quota_id = quota_id,
- };
-
- rule.rst_state = convert_to_restriction_state(rst_type);
-
- ret_value_msg_if(stc == NULL, STC_ERROR_FAIL, "Can't get stc data");
- if (!stc->carg) {
- stc->carg = MALLOC0(counter_arg_s, 1);
- stc->carg->sock = stc_monitor_get_counter_socket();
- }
-
- carg = stc->carg;
- ret_value_msg_if(carg == NULL, STC_ERROR_FAIL, "Empty counter");
-
- rule.classid = classid;
- rule.iftype = iftype;
- rule.carg = carg;
- rule.roaming = stc_default_connection_get_roaming();
- STRING_SAVE_COPY(rule.ifname, ifname);
-
- if (rst_type == RST_SET) {
- /* snd_warning_threshold && */
- if (rcv_warning_threshold) {
- rule.intend = NFACCT_WARN;
- ret = apply_net_restriction(&rule,
- snd_warning_threshold,
- rcv_warning_threshold);
- ret_value_msg_if(ret != STC_ERROR_NONE, ret,
- "Can't apply network restriction");
- }
- rule.intend = NFACCT_BLOCK;
- ret = apply_net_restriction(&rule, send_limit, rcv_limit);
- ret_value_msg_if(ret != STC_ERROR_NONE, ret,
- "Can't apply network restriction");
- } else if (rst_type == RST_UNSET) {
- rule.intend = NFACCT_WARN;
- ret = revert_net_restriction(&rule,
- snd_warning_threshold,
- rcv_warning_threshold);
- ret_value_msg_if(ret != STC_ERROR_NONE, ret,
- "Can't revert network restriction");
- rule.intend = NFACCT_BLOCK;
- return revert_net_restriction(&rule, send_limit,
- rcv_limit);
- } else if (rst_type == RST_EXCLUDE)
- return exclude_net_restriction(&rule);
-
- return STC_ERROR_NONE;
-}