Merge "Initialize memory for nfacct rule" into tizen
[platform/core/connectivity/stc-manager.git] / src / monitor / stc-monitor.c
index ebf15a5..ca7f6bf 100755 (executable)
@@ -31,6 +31,7 @@
 #include "stc-time.h"
 #include "stc-manager-plugin-appstatus.h"
 #include "stc-manager-plugin-exception.h"
+#include "stc-manager-plugin-tether.h"
 
 #define GRANULARITY 10
 #define MAX_INT_LENGTH 128
@@ -101,6 +102,10 @@ static nfacct_rule_jump __get_jump_by_intend(struct nfacct_rule *counter)
                return NFACCT_JUMP_REJECT;
        else if (counter->intend == NFACCT_ALLOW)
                return NFACCT_JUMP_ACCEPT;
+       else if (counter->intend == NFACCT_TETH_BLOCK)
+               return NFACCT_JUMP_REJECT;
+       else if (counter->intend == NFACCT_TETH_ALLOW)
+               return NFACCT_JUMP_ACCEPT;
 
        return NFACCT_JUMP_UNKNOWN;
 }
@@ -124,7 +129,7 @@ static stc_error_e __add_iptables_tether_in(struct nfacct_rule *counter,
 
        ret = produce_net_rule(counter);
 
-       g_free(counter->src_ip1);
+       FREE(counter->src_ip1);
        counter->src_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
        return ret;
 }
@@ -148,7 +153,7 @@ static stc_error_e __add_iptables_tether_out(struct nfacct_rule *counter,
 
        ret = produce_net_rule(counter);
 
-       g_free(counter->dst_ip1);
+       FREE(counter->dst_ip1);
        counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
        return ret;
 }
@@ -172,7 +177,7 @@ static stc_error_e __del_iptables_tether_in(struct nfacct_rule *counter,
 
        ret = produce_net_rule(counter);
 
-       g_free(counter->src_ip1);
+       FREE(counter->src_ip1);
        counter->src_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
        return ret;
 }
@@ -196,7 +201,7 @@ static stc_error_e __del_iptables_tether_out(struct nfacct_rule *counter,
 
        ret = produce_net_rule(counter);
 
-       g_free(counter->dst_ip1);
+       FREE(counter->dst_ip1);
        counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
        return ret;
 }
@@ -515,16 +520,19 @@ static gboolean __processes_tree_check_empty(gpointer key, gpointer value,
 }
 //LCOV_EXCL_STOP
 
-static gboolean __add_application_monitor_for_tethering(gpointer key, gpointer value,
-                                   gpointer data)
+static gboolean __add_application_monitor_for_tethering(gpointer key,
+                                   gpointer value, gpointer data)
 {
        stc_app_value_s *app_value = (stc_app_value_s *)value;
        stc_app_key_s *app_key = (stc_app_key_s *)key;
        default_connection_s *connection = (default_connection_s *)data;
        stc_s *stc = stc_get_manager();
        struct nfacct_rule counter;
+       char *ipaddr = NULL;
+       int ret;
 
-       STC_LOGI("add tether app (%s)", app_key->app_id);
+       STC_LOGI("add appid(%s) classid(%d)", app_key->app_id,
+                       app_value->classid);
 
        if (stc == NULL || connection == NULL)
                return FALSE;
@@ -550,9 +558,16 @@ static gboolean __add_application_monitor_for_tethering(gpointer key, gpointer v
        counter.iftype = connection->tether_iface.type;
        g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
 
-       __add_iptables_tether_in(&counter, app_value->ipaddr);
-       __add_iptables_tether_out(&counter, app_value->ipaddr);
+       /* get the ip address of the station based on its mac address */
+       ret = stc_plugin_tether_get_station_ip(app_value->mac, &ipaddr);
+       if (ret != STC_ERROR_NONE)
+               return FALSE;
+
+       /* tethering iptables rule */
+       __add_iptables_tether_in(&counter, ipaddr);
+       __add_iptables_tether_out(&counter, ipaddr);
 
+       g_free(ipaddr);
        return FALSE;
 }
 
@@ -564,8 +579,11 @@ static gboolean __remove_application_monitor_for_tethering(gpointer key, gpointe
        default_connection_s *connection = (default_connection_s *)data;
        stc_s *stc = stc_get_manager();
        struct nfacct_rule counter;
+       char *ipaddr = NULL;
+       int ret;
 
-       STC_LOGI("remove tether app (%s)", app_key->app_id);
+       STC_LOGI("remove appid(%s) classid(%d)", app_key->app_id,
+                       app_value->classid);
 
        if (stc == NULL || connection == NULL)
                return FALSE;
@@ -591,9 +609,15 @@ static gboolean __remove_application_monitor_for_tethering(gpointer key, gpointe
        counter.iftype = connection->tether_iface.type;
        g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
 
-       __del_iptables_tether_in(&counter, app_value->ipaddr);
-       __del_iptables_tether_out(&counter, app_value->ipaddr);
+       /* get the ip address of the station based on its mac address */
+       ret = stc_plugin_tether_get_station_ip(app_value->mac, &ipaddr);
+       if (ret != STC_ERROR_NONE)
+               return FALSE;
 
+       __del_iptables_tether_in(&counter, ipaddr);
+       __del_iptables_tether_out(&counter, ipaddr);
+
+       g_free(ipaddr);
        return FALSE;
 }
 
@@ -786,6 +810,96 @@ static void __add_iptables_rule(int64_t classid, nfacct_rule_intend intend,
        __add_ip6tables_out(&counter);
 }
 
+static void __add_tethering_iptables_rule(int64_t classid, gchar *mac,
+               nfacct_rule_intend intend, stc_iface_type_e iftype)
+{
+       default_connection_s *connection = stc_get_default_connection();
+       struct nfacct_rule counter;
+       stc_s *stc = stc_get_manager();
+       char *ipaddr = NULL;
+       int ret;
+
+       if (!stc || !mac)
+               return;
+
+       if (!stc->carg) {
+               stc->carg = MALLOC0(counter_arg_s, 1);
+               if (stc->carg == NULL)
+                       return;
+
+               stc->carg->sock = stc_monitor_get_counter_socket();
+       }
+
+       memset(&counter, 0, sizeof(struct nfacct_rule));
+
+       counter.carg = stc->carg;
+       counter.classid = classid;
+       counter.intend = intend;
+
+       if (connection->tether_state != TRUE ||
+               connection->tether_iface.ifname == NULL)
+       return;
+
+       counter.iftype = connection->tether_iface.type;
+       g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
+
+       /* get connected station ip based on its mac */
+       ret = stc_plugin_tether_get_station_ip(mac, &ipaddr);
+       if (ret != STC_ERROR_NONE)
+               return;
+
+       /* tethering iptables rule */
+       __add_iptables_tether_in(&counter, ipaddr);
+       __add_iptables_tether_out(&counter, ipaddr);
+       g_free(ipaddr);
+}
+
+static void __del_tethering_iptables_rule(int64_t classid, gchar *mac,
+               nfacct_rule_intend intend, stc_iface_type_e iftype)
+{
+       default_connection_s *connection = stc_get_default_connection();
+       struct nfacct_rule counter;
+       stc_s *stc = stc_get_manager();
+       char *ipaddr = NULL;
+       int ret;
+
+       if (!stc || !mac)
+               return;
+
+       if (!stc->carg) {
+               stc->carg = MALLOC0(counter_arg_s, 1);
+               if (stc->carg == NULL)
+                       return;
+
+               stc->carg->sock = stc_monitor_get_counter_socket();
+       }
+
+       memset(&counter, 0, sizeof(struct nfacct_rule));
+
+       counter.carg = stc->carg;
+       counter.classid = classid;
+       counter.intend = intend;
+
+       if (connection->tether_state != TRUE ||
+               connection->tether_iface.ifname == NULL)
+       return;
+
+       counter.iftype = connection->tether_iface.type;
+       g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
+
+       /* get connected station ip based on its mac */
+       ret = stc_plugin_tether_get_station_ip(mac, &ipaddr);
+       if (ret != STC_ERROR_NONE) {
+               STC_LOGE("Error: no IP found for station mac(%s)", mac);
+               return;
+       }
+
+       /* tethering iptables rule */
+       __del_iptables_tether_in(&counter, ipaddr);
+       __del_iptables_tether_out(&counter, ipaddr);
+       g_free(ipaddr);
+}
+
 static void __del_iptables_rule(int64_t classid, nfacct_rule_intend intend,
                                stc_iface_type_e iftype)
 {
@@ -876,6 +990,142 @@ static stc_cb_ret_e __statistics_info_cb(const table_statistics_info *info,
        return STC_CONTINUE;
 }
 
+static void __process_tethering_restriction(enum traffic_restriction_type rstn_type,
+               stc_rstn_key_s *rstn_key, stc_rstn_value_s *rstn_value, void *data)
+{
+       default_connection_s *old_connection = (default_connection_s *)data;
+       default_connection_s *connection = NULL;
+       char *mac_str = NULL;
+
+       if (old_connection != NULL)
+               connection = old_connection;
+       else
+               connection = stc_get_default_connection();
+
+       /* in case tethering is not active */
+       if (connection->tether_state == FALSE)
+               return;
+
+       /* rstn not applicable for this interface */
+       if (rstn_key->ifname != NULL && g_strcmp0("", rstn_key->ifname) != 0 &&
+                       (g_strcmp0(connection->tether_iface.ifname, rstn_key->ifname) != 0))
+               return;
+
+       /* in case appid not a tethering app */
+       if (!g_str_has_suffix(rstn_key->app_id, STC_TETHERING_APP_SUFFIX))
+               return;
+
+       /* Ignore TOTAL_TETHERING,
+        * Process only station appids */
+       if (rstn_value->classid == STC_TETHERING_APP_CLASSID)
+               return;
+
+       /* get the station mac based on classid */
+       stc_plugin_tether_get_station_by_classid(rstn_value->classid, &mac_str);
+       if (!mac_str) {
+               STC_LOGE("station not found for classid(%d)", rstn_value->classid);
+               return;
+       }
+
+       switch (rstn_type) {
+       case RST_SET:
+       {
+               int i;
+               table_counters_info info;
+               int64_t effective_limit[STC_RSTN_LIMIT_TYPE_MAX] = { 0, };
+
+                       memset(&info, 0, sizeof(table_counters_info));
+                       rstn_value->limit_exceeded = 0;
+
+                       if ((rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 &&
+                                               rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) ||
+                                       (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 &&
+                                        rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) ||
+                                       (rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 &&
+                                        rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) ||
+                                       (rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 &&
+                                        rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) ||
+                                       (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 &&
+                                        rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) {
+                               table_counters_get(rstn_value->restriction_id, &info);
+
+                               time_t current_time = 0;
+                               cumulative_data_s stat;
+                               table_statistics_select_rule rule;
+
+                               memset(&stat, 0, sizeof(cumulative_data_s));
+                               stat.month_start_ts = rstn_value->month_start_ts;
+                               stat.week_start_ts = g_system->last_week_ts;
+                               stat.day_start_ts = g_system->last_day_ts;
+
+                               memset(&rule, 0, sizeof(table_statistics_select_rule));
+                               rule.from = rstn_value->month_start_ts;
+                               time(&current_time);
+                               rule.to = current_time;
+                               rule.iftype = rstn_key->iftype;
+                               rule.granularity = GRANULARITY;
+
+                               table_statistics_per_app(rstn_key->app_id, &rule, __statistics_info_cb, &stat);
+
+                               rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter;
+                               rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter;
+                               rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter + stat.monthly_stat;
+                               rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter + stat.weekly_stat;
+                               rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter + stat.daily_stat;
+                       }
+
+                       for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
+                               if (rstn_value->limit[i] >= 0) {
+                                       effective_limit[i] = rstn_value->limit[i] - rstn_value->counter[i];
+
+                                       if (effective_limit[i] < 0)
+                                               rstn_value->limit_exceeded |= (1 << i);
+                               }
+                       }
+
+                       STC_LOGD("rstn_id [%llu], datausage [%llu] bytes",
+                                       rstn_value->restriction_id, info.data_counter);
+
+                       if (rstn_value->limit_exceeded != 0 &&
+                                       rstn_value->limit_exceeded != (1 << STC_RSTN_LIMIT_TYPE_DATA_WARN)) {
+                               __add_tethering_iptables_rule(rstn_value->classid, mac_str,
+                                               NFACCT_TETH_BLOCK, rstn_key->iftype);
+                       }
+
+                       rstn_value->rstn_state = STC_RSTN_STATE_ACTIVATED;
+       }
+       break;
+       case RST_EXCLUDE:
+       {
+               __add_tethering_iptables_rule(rstn_value->classid, mac_str,
+                                       NFACCT_TETH_ALLOW, rstn_key->iftype);
+
+                       rstn_value->rstn_state = STC_RSTN_STATE_ACTIVATED;
+                       rstn_value->limit_exceeded = 0;
+                       rstn_value->limit_notified = 0;
+       }
+       break;
+       case RST_UNSET:
+       {
+                       int i;
+                       __del_tethering_iptables_rule(rstn_value->classid, mac_str,
+                                       NFACCT_TETH_BLOCK, rstn_key->iftype);
+
+                       rstn_value->rstn_state = STC_RSTN_STATE_DEACTIVATED;
+                       rstn_value->limit_exceeded = 0;
+                       rstn_value->limit_notified = 0;
+
+                       for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++)
+                               if (rstn_value->limit[i] >= 0)
+                                       rstn_value->counter[i] = 0;
+       }
+       break;
+       default:
+                       ;//Do Nothing
+       }
+       FREE(mac_str);
+}
+
 static void __process_restriction(enum traffic_restriction_type rstn_type,
                                  stc_rstn_key_s *rstn_key,
                                  stc_rstn_value_s *rstn_value, void *data)
@@ -902,6 +1152,13 @@ static void __process_restriction(enum traffic_restriction_type rstn_type,
        if (rstn_value->classid <= STC_UNKNOWN_CLASSID)
                return;
 
+       /* Do not proceed for tethering station appid if found here,
+        * for tethering station apps __process_tethering_restriction() call
+        * will handle it */
+       if (g_str_has_suffix(rstn_key->app_id, STC_TETHERING_APP_SUFFIX) &&
+                       rstn_value->classid != STC_TETHERING_APP_CLASSID)
+               return;
+
        switch (rstn_type) {
        case RST_SET:
        {
@@ -1028,6 +1285,9 @@ static gboolean __remove_rstns_foreach_application(gpointer key,
        /* remove restriction from system */
        __process_restriction(RST_UNSET, rstn_key, rstn_value, NULL);
 
+       /* remove tethering restriction from system*/
+       __process_tethering_restriction(RST_UNSET, rstn_key, rstn_value, NULL);
+
        __print_rstn(rstn_key, rstn_value);
 out:
        return FALSE;
@@ -1129,6 +1389,36 @@ static stc_error_e __close_and_reopen_contr_sock(stc_system_s *system)
        return STC_ERROR_NONE;
 }
 
+static void __action_when_rstn_limit_exceeded_tethering(stc_rstn_key_s *rstn_key,
+               stc_rstn_value_s *rstn_value, classid_bytes_context_s *context)
+{
+       char *mac_str = NULL;
+       struct nfacct_rule *counter = context->counter;
+
+       /* get the station mac based on classid */
+       stc_plugin_tether_get_station_by_classid(counter->classid, &mac_str);
+       if (!mac_str) {
+               STC_LOGE("station not found for classid(%d)", counter->classid);
+               return;
+       }
+
+       STC_LOGI("station mac %s, classid %u, iftype %u, iotype %d, \
+                       intend %d, ifname %s, bytes %lld", mac_str,
+                       counter->classid, counter->iftype, counter->iotype,
+                       counter->intend, counter->ifname, context->bytes);
+
+       /* Block tethering station immediately */
+       counter->intend = NFACCT_TETH_BLOCK;
+       __del_tethering_iptables_rule(counter->classid, mac_str,
+                       NFACCT_TETH_BLOCK, rstn_key->iftype);
+
+       __add_tethering_iptables_rule(counter->classid, mac_str,
+                       NFACCT_TETH_BLOCK, rstn_key->iftype);
+       counter->intend = NFACCT_TETH_COUNTER;
+
+       g_free(mac_str);
+}
+
 static void __action_when_rstn_limit_exceeded(stc_rstn_limit_type_e limit_type,
                                                stc_rstn_key_s *rstn_key,
                                                stc_rstn_value_s *rstn_value,
@@ -1164,18 +1454,30 @@ static void __action_when_rstn_limit_exceeded(stc_rstn_limit_type_e limit_type,
                net_popup_content = "restriction threshold crossed";
                net_popup_type = "restriction_noti";
 
-               /* block immediately */
-               context->counter->intend = NFACCT_BLOCK;
-               __del_iptables_in(context->counter);
-               __del_iptables_out(context->counter);
-               __add_iptables_in(context->counter);
-               __add_iptables_out(context->counter);
+               /* Apply restriction for tethering apps if app_id is of tethering client
+                * otherwise do the normal iptables rule */
+               if (context->counter->intend == NFACCT_TETH_COUNTER) {
 
-               __del_ip6tables_in(context->counter);
-               __del_ip6tables_out(context->counter);
-               __add_ip6tables_in(context->counter);
-               __add_ip6tables_out(context->counter);
-               context->counter->intend = NFACCT_COUNTER;
+                       if (g_str_has_suffix(rstn_key->app_id, STC_TETHERING_APP_SUFFIX) &&
+                                       rstn_value->classid != STC_TETHERING_APP_CLASSID) {
+                               __action_when_rstn_limit_exceeded_tethering(rstn_key, rstn_value,
+                                               context);
+                       }
+
+               } else {
+                       /* block immediately */
+                       context->counter->intend = NFACCT_BLOCK;
+                       __del_iptables_in(context->counter);
+                       __del_iptables_out(context->counter);
+                       __add_iptables_in(context->counter);
+                       __add_iptables_out(context->counter);
+
+                       __del_ip6tables_in(context->counter);
+                       __del_ip6tables_out(context->counter);
+                       __add_ip6tables_in(context->counter);
+                       __add_ip6tables_out(context->counter);
+                       context->counter->intend = NFACCT_COUNTER;
+               }
 
                rstn_value->limit_exceeded |= (1 << limit_type);
 
@@ -1883,6 +2185,7 @@ static gboolean __remove_restriction(gpointer key, gpointer value,
        stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
 
        __process_restriction(RST_UNSET, rstn_key, rstn_value, data);
+       __process_tethering_restriction(RST_UNSET, rstn_key, rstn_value, data);
        __print_rstn(rstn_key, rstn_value);
        return FALSE;
 }
@@ -1897,10 +2200,13 @@ static gboolean __add_restriction_debug(gpointer key, gpointer value,
        if (rstn_value->rstn_state == STC_RSTN_STATE_ACTIVATED)
                return FALSE;
 
-       if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
+       if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT) {
                __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, data);
-       else
+               __process_tethering_restriction(RST_EXCLUDE, rstn_key, rstn_value, data);
+       } else {
                __process_restriction(RST_SET, rstn_key, rstn_value, data);
+               __process_tethering_restriction(RST_SET, rstn_key, rstn_value, data);
+       }
 
        __print_rstn(rstn_key, rstn_value);
 
@@ -1917,10 +2223,13 @@ static gboolean __add_restriction(gpointer key, gpointer value, gpointer data)
        if (rstn_value->rstn_state == STC_RSTN_STATE_ACTIVATED)
                return FALSE;
 
-       if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
+       if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT) {
                __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, data);
-       else
+               __process_tethering_restriction(RST_EXCLUDE, rstn_key, rstn_value, data);
+       } else {
                __process_restriction(RST_SET, rstn_key, rstn_value, data);
+               __process_tethering_restriction(RST_SET, rstn_key, rstn_value, data);
+       }
 
        return FALSE;
 }
@@ -1977,6 +2286,7 @@ static stc_error_e __rstn_tree_add(stc_rstn_key_s *key,
 
        rstn_key->app_id = g_strdup(key->app_id);
        rstn_key->ifname = g_strdup(key->ifname);
+       rstn_key->mac = g_strdup(key->mac);
        rstn_key->subscriber_id = g_strdup(key->subscriber_id);
        rstn_key->iftype = key->iftype;
        rstn_key->roaming = key->roaming;
@@ -2077,10 +2387,13 @@ static gboolean __add_rstn_foreach_application(gpointer key,
                goto out;
 
        /* add restriction to system */
-       if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
+       if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT) {
                __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, NULL);
-       else
+               __process_tethering_restriction(RST_EXCLUDE, rstn_key, rstn_value, NULL);
+       } else {
                __process_restriction(RST_SET, rstn_key, rstn_value, NULL);
+               __process_tethering_restriction(RST_SET, rstn_key, rstn_value, NULL);
+       }
 
        __print_rstn(rstn_key, rstn_value);
 out:
@@ -2299,7 +2612,7 @@ API stc_error_e stc_monitor_application_add(const stc_app_key_s app_key,
        value->type = app_value.type;
        value->data_usage.in_bytes = app_value.data_usage.in_bytes;
        value->data_usage.out_bytes = app_value.data_usage.out_bytes;
-       g_strlcpy(value->ipaddr, app_value.ipaddr, IPV4_IPADDRESS_LEN);
+       g_strlcpy(value->mac, app_value.mac, MAC_ADDRESS_LEN);
 
        value->processes = g_tree_new_full(__processes_tree_key_compare, NULL,
                                           __processes_tree_key_free,
@@ -2308,6 +2621,11 @@ API stc_error_e stc_monitor_application_add(const stc_app_key_s app_key,
        /* create cgroup and update classid */
        value->classid = get_classid_by_app_id(app_key.app_id, TRUE);
 
+       /* update classid for tethering station based on its mac address */
+       if (g_str_has_suffix(app_key.app_id, STC_TETHERING_APP_SUFFIX) &&
+                               value->classid != STC_TETHERING_APP_CLASSID)
+               stc_plugin_tether_set_station_classid(value->mac, value->classid);
+
        g_tree_insert(g_system->apps, key, value);
 
        /* add nfacct rule for this classid */
@@ -2523,6 +2841,7 @@ stc_error_e stc_monitor_rstns_tree_add(const table_restrictions_info *info)
 
        key.app_id = g_strdup(info->app_id);
        key.ifname = g_strdup(info->ifname);
+       key.mac = g_strdup(info->mac);
        key.subscriber_id = g_strdup(info->subscriber_id);
        key.iftype = info->iftype;
        key.roaming = info->roaming;
@@ -2555,6 +2874,7 @@ stc_error_e stc_monitor_rstns_tree_add(const table_restrictions_info *info)
 
        FREE(key.app_id);
        FREE(key.ifname);
+       FREE(key.mac);
        FREE(key.subscriber_id);
        return ret;
 }