Support to multi connection
[platform/core/connectivity/stc-manager.git] / src / monitor / stc-monitor-rstn.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <vconf.h>
18 #include <vconf-keys.h>
19
20 #include "counter.h"
21 #include "stc-monitor.h"
22 #include "stc-monitor-rstn.h"
23 #include "stc-monitor-ipt.h"
24 #include "stc-time.h"
25 #include "table-counters.h"
26 #include "table-restrictions.h"
27 #include "table-statistics.h"
28 #include "helper-net-cls.h"
29 #include "stc-manager-plugin-appstatus.h"
30 #include "stc-manager-plugin-tether.h"
31
32 static void __print_rstn(stc_rstn_data_s *rstn_data)
33 {
34         STC_LOGI("RstnID[%llu] AppID[%s] classid[%u] "
35                 "iftype[%d] ifname[%s] rstn_state[%d] "
36                 "rstn_type[%d] roaming[%d] subscriber_id[%s]",
37                  rstn_data->restriction_id,
38                  rstn_data->app_id, rstn_data->classid,
39                  rstn_data->iftype, rstn_data->ifname,
40                  rstn_data->rstn_state, rstn_data->rstn_type,
41                  rstn_data->roaming, rstn_data->subscriber_id);
42         STC_LOGI("month_start_date[%d] limit[%lld] "
43                 "warn_limit[%lld] monthly_limit[%lld] "
44                 "weekly_limit[%lld] daily_limit[%lld] ",
45                 rstn_data->month_start_date,
46                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA],
47                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN],
48                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_MONTHLY],
49                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_WEEKLY],
50                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_DAILY]);
51         STC_LOGI("data_counter[%lld] warn_counter[%lld] "
52                 "monthly_counter[%lld] weekly_counter[%lld] "
53                 "daily_counter[%lld]",
54                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA],
55                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN],
56                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY],
57                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY],
58                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY]);
59 }
60
61 static int __vconf_get_int(const char *key, int *value)
62 {
63         int ret = 0;
64
65         ret = vconf_get_int(key, value);
66         if (ret != VCONF_OK) {
67                 STC_LOGE("Failed to get vconfkey [%s] value", key);
68                 return -1;
69         }
70
71         return 0;
72 }
73
74 static int __vconf_set_int(const char *key, int value)
75 {
76         int ret = 0;
77
78         ret = vconf_set_int(key, value);
79         if (ret != VCONF_OK) {
80                 STC_LOGE("Failed to set vconfkey [%s] value", key);
81                 return -1;
82         }
83
84         return 0;
85 }
86
87 static stc_cb_ret_e __statistics_info_cb(const table_statistics_info *info,
88                                         void *user_data)
89 {
90         stc_rstn_cumulative_data_s *stat = (stc_rstn_cumulative_data_s *)user_data;
91         int64_t counters = 0;
92
93         counters = info->cnt.in_bytes + info->cnt.out_bytes;
94
95         stat->monthly_stat += counters;
96         if (stat->week_start_ts <= info->interval->from)
97                 stat->weekly_stat += counters;
98         if (stat->day_start_ts <= info->interval->from)
99                 stat->daily_stat += counters;
100
101         return STC_CONTINUE;
102 }
103
104 static void __rstn_add_tether_rule(int64_t classid, gchar *mac,
105                 nfacct_rule_intend intend, stc_iface_type_e iftype)
106 {
107         GSList *conn_list = stc_get_connection_list();
108         struct nfacct_rule counter;
109         stc_s *stc = stc_get_manager();
110         char *ipaddr = NULL;
111         int ret;
112
113         if (!stc || !mac)
114                 return;
115
116         for (; conn_list != NULL; conn_list = conn_list->next) {
117                 stc_connection_s *conn = conn_list->data;
118
119                 if (!stc->carg) {
120                         stc->carg = MALLOC0(counter_arg_s, 1);
121                         if (stc->carg == NULL)
122                                 return;
123
124                         stc->carg->sock = stc_monitor_get_contr_sock();
125                 }
126
127                 memset(&counter, 0, sizeof(struct nfacct_rule));
128
129                 counter.carg = stc->carg;
130                 counter.classid = classid;
131                 counter.intend = intend;
132
133                 if (conn->tether_state != TRUE ||
134                         conn->tether_iface.ifname == NULL)
135                         return;
136
137                 counter.iftype = conn->tether_iface.type;
138                 g_strlcpy(counter.ifname, conn->tether_iface.ifname, MAX_IFACE_LENGTH);
139
140                 /* get connected station ip based on its mac */
141                 ret = stc_plugin_tether_get_station_ip(mac, &ipaddr);
142                 if (ret != STC_ERROR_NONE)
143                         return;
144
145                 /* tethering iptables rule */
146                 stc_monitor_tether_add_in(&counter, ipaddr);
147                 stc_monitor_tether_add_out(&counter, ipaddr);
148                 g_free(ipaddr);
149         }
150 }
151
152 static void __rstn_del_tether_rule(int64_t classid, gchar *mac,
153                 nfacct_rule_intend intend, stc_iface_type_e iftype)
154 {
155         GSList *conn_list = stc_get_connection_list();
156         struct nfacct_rule counter;
157         stc_s *stc = stc_get_manager();
158         char *ipaddr = NULL;
159         int ret;
160
161         if (!stc || !mac)
162                 return;
163
164         for (; conn_list != NULL; conn_list = conn_list->next) {
165                 stc_connection_s *conn = conn_list->data;
166
167                 if (!stc->carg) {
168                         stc->carg = MALLOC0(counter_arg_s, 1);
169                         if (stc->carg == NULL)
170                                 return;
171
172                         stc->carg->sock = stc_monitor_get_contr_sock();
173                 }
174
175                 memset(&counter, 0, sizeof(struct nfacct_rule));
176
177                 counter.carg = stc->carg;
178                 counter.classid = classid;
179                 counter.intend = intend;
180
181                 if (conn->tether_state != TRUE ||
182                         conn->tether_iface.ifname == NULL)
183                         return;
184
185                 counter.iftype = conn->tether_iface.type;
186                 g_strlcpy(counter.ifname, conn->tether_iface.ifname, MAX_IFACE_LENGTH);
187
188                 /* get connected station ip based on its mac */
189                 ret = stc_plugin_tether_get_station_ip(mac, &ipaddr);
190                 if (ret != STC_ERROR_NONE) {
191                         STC_LOGE("Error: no IP found for station mac(%s)", mac);
192                         return;
193                 }
194
195                 /* tethering iptables rule */
196                 stc_monitor_tether_del_in(&counter, ipaddr);
197                 stc_monitor_tether_del_out(&counter, ipaddr);
198                 g_free(ipaddr);
199         }
200 }
201
202 static void __rstn_add_ipt_rule(int64_t classid, nfacct_rule_intend intend,
203                                 stc_iface_type_e iftype)
204 {
205         GSList *conn_list = stc_get_connection_list();
206         struct nfacct_rule counter;
207         stc_s *stc = stc_get_manager();
208
209         if (!stc)
210                 return;
211
212         for (; conn_list != NULL; conn_list = conn_list->next) {
213                 stc_connection_s *conn = conn_list->data;
214
215                 if (!stc->carg) {
216                         stc->carg = MALLOC0(counter_arg_s, 1);
217                         if (stc->carg == NULL)
218                                 return;
219
220                         stc->carg->sock = stc_monitor_get_contr_sock();
221                 }
222
223                 memset(&counter, 0, sizeof(struct nfacct_rule));
224
225                 counter.carg = stc->carg;
226                 counter.classid = classid;
227                 counter.intend = intend;
228
229                 if (conn && conn->tether_iface.ifname != NULL &&
230                         classid == STC_TETHERING_APP_CLASSID) {
231                         counter.iftype = conn->tether_iface.type;
232                         g_strlcpy(counter.ifname, conn->tether_iface.ifname, MAX_IFACE_LENGTH);
233                 } else {
234                         counter.iftype = iftype;
235                         g_strlcpy(counter.ifname, conn->ifname, MAX_IFACE_LENGTH);
236                 }
237
238                 /* iptables rule */
239                 stc_monitor_ipt_add_in(&counter);
240                 stc_monitor_ipt_add_out(&counter);
241
242                 /* ip6tables rule */
243                 stc_monitor_ip6t_add_in(&counter);
244                 stc_monitor_ip6t_add_out(&counter);
245         }
246 }
247
248 static void __rstn_del_ipt_rule(int64_t classid, nfacct_rule_intend intend,
249                                 stc_iface_type_e iftype)
250 {
251         GSList *conn_list = stc_get_connection_list();
252         struct nfacct_rule counter;
253         stc_s *stc = stc_get_manager();
254
255         if (!stc)
256                 return;
257
258         for (; conn_list != NULL; conn_list = conn_list->next) {
259                 stc_connection_s *conn = conn_list->data;
260
261                 if (!stc->carg) {
262                         stc->carg = MALLOC0(counter_arg_s, 1);
263                         if (stc->carg == NULL)
264                                 return;
265
266                         stc->carg->sock = stc_monitor_get_contr_sock();
267                 }
268
269                 memset(&counter, 0, sizeof(struct nfacct_rule));
270
271                 counter.carg = stc->carg;
272                 counter.classid = classid;
273                 counter.intend = intend;
274
275                 if (conn && conn->tether_iface.ifname != NULL &&
276                         classid == STC_TETHERING_APP_CLASSID) {
277                         counter.iftype = conn->tether_iface.type;
278                         g_strlcpy(counter.ifname, conn->tether_iface.ifname, MAX_IFACE_LENGTH);
279                 } else {
280                         counter.iftype = iftype;
281                         g_strlcpy(counter.ifname, conn->ifname, MAX_IFACE_LENGTH);
282                 }
283
284                 /* iptables rule */
285                 stc_monitor_ipt_del_in(&counter);
286                 stc_monitor_ipt_del_out(&counter);
287
288                 /* ip6tables rule */
289                 stc_monitor_ip6t_del_in(&counter);
290                 stc_monitor_ip6t_del_out(&counter);
291         }
292 }
293
294 static void __rstn_set_noti_state(int value)
295 {
296         int state = STC_RSTN_STATE_INIT;
297
298         if (__vconf_get_int(VCONFKEY_SETAPPL_DATA_RESTRICTION_INT, &state))
299                 return;
300
301         if (state == value) {
302                 STC_LOGI("No need to change a restriction status: %d", state);
303                 return;
304         }
305
306         __vconf_set_int(VCONFKEY_SETAPPL_DATA_RESTRICTION_INT, value);
307 }
308
309 static void __rstn_tethering_process(enum traffic_restriction_type rstn_type,
310                                 char *app_id, stc_rstn_data_s *rstn_data, void *data)
311 {
312         stc_connection_s *old_connection = (stc_connection_s *)data;
313         stc_connection_s *connection = NULL;
314         char *mac_str = NULL;
315
316         if (old_connection != NULL) {
317                 connection = old_connection;
318                 if (connection->tether_state == FALSE)
319                         return;
320
321                 /* rstn not applicable for this interface */
322                 if (rstn_data->ifname != NULL &&
323                         g_strcmp0("", rstn_data->ifname) != 0 &&
324                         g_strcmp0(connection->tether_iface.ifname, rstn_data->ifname) != 0)
325                         return;
326         } else {
327                 GSList *conn_list = stc_get_connection_list();
328                 for (; conn_list != NULL; conn_list = conn_list->next) {
329                         stc_connection_s *conn = conn_list->data;
330                         if (conn->tether_state == FALSE)
331                                 continue;
332
333                         if (rstn_data->ifname != NULL &&
334                                 g_strcmp0(rstn_data->ifname, "") != 0 &&
335                                 g_strcmp0(conn->tether_iface.ifname, rstn_data->ifname) == 0)
336                                 connection = conn;
337                 }
338
339                 if (connection == NULL)
340                         return;
341         }
342
343         /* in case appid not a tethering app */
344         if (!g_str_has_suffix(app_id, STC_TETHERING_APP_SUFFIX))
345                 return;
346
347         /* Ignore TOTAL_TETHERING,
348          * Process only station appids */
349         if (rstn_data->classid == STC_TETHERING_APP_CLASSID)
350                 return;
351
352         /* get the station mac based on classid */
353         stc_plugin_tether_get_station_by_classid(rstn_data->classid, &mac_str);
354         if (!mac_str) {
355                 STC_LOGE("Station not found for classid(%d)", rstn_data->classid);
356                 return;
357         }
358
359         switch (rstn_type) {
360         case RST_SET:
361         {
362                 int i;
363                 table_counters_info info;
364                 int64_t effective_limit[STC_RSTN_LIMIT_TYPE_MAX] = { 0, };
365
366                         memset(&info, 0, sizeof(table_counters_info));
367                         rstn_data->limit_exceeded = 0;
368
369                         if ((rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 &&
370                                                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) ||
371                                         (rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 &&
372                                          rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) ||
373                                         (rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 &&
374                                          rstn_data->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) ||
375                                         (rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 &&
376                                          rstn_data->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) ||
377                                         (rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 &&
378                                          rstn_data->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) {
379                                 table_counters_get(rstn_data->restriction_id, &info);
380
381                                 time_t current_time = 0;
382                                 stc_rstn_cumulative_data_s stat;
383                                 table_statistics_select_rule rule;
384                                 time_t last_week_ts = stc_monitor_get_last_week_ts();
385                                 time_t last_day_ts = stc_monitor_get_last_day_ts();
386
387                                 memset(&stat, 0, sizeof(stc_rstn_cumulative_data_s));
388                                 stat.month_start_ts = rstn_data->month_start_ts;
389                                 stat.week_start_ts = last_week_ts;
390                                 stat.day_start_ts = last_day_ts;
391
392                                 memset(&rule, 0, sizeof(table_statistics_select_rule));
393                                 rule.from = rstn_data->month_start_ts;
394                                 time(&current_time);
395                                 rule.to = current_time;
396                                 rule.iftype = rstn_data->iftype;
397                                 rule.granularity = GRANULARITY;
398
399                                 table_statistics_per_app(app_id, &rule, __statistics_info_cb, &stat);
400
401                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter;
402                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter;
403                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter + stat.monthly_stat;
404                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter + stat.weekly_stat;
405                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter + stat.daily_stat;
406                         }
407
408                         for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
409                                 if (rstn_data->limit[i] >= 0) {
410                                         effective_limit[i] = rstn_data->limit[i] - rstn_data->counter[i];
411
412                                         if (effective_limit[i] < 0)
413                                                 rstn_data->limit_exceeded |= (1 << i);
414                                 }
415                         }
416
417                         STC_LOGD("Rstn_id[%llu] datausage[%lld]bytes",
418                                         rstn_data->restriction_id, info.data_counter);
419
420                         if (rstn_data->limit_exceeded != 0 &&
421                                         rstn_data->limit_exceeded != (1 << STC_RSTN_LIMIT_TYPE_DATA_WARN)) {
422                                 __rstn_add_tether_rule(rstn_data->classid, mac_str,
423                                                 NFACCT_TETH_BLOCK, rstn_data->iftype);
424                         }
425
426                         rstn_data->rstn_state = STC_RSTN_STATE_ACTIVATED;
427         }
428         break;
429         case RST_EXCLUDE:
430         {
431                 __rstn_add_tether_rule(rstn_data->classid, mac_str,
432                                         NFACCT_TETH_ALLOW, rstn_data->iftype);
433
434                         rstn_data->rstn_state = STC_RSTN_STATE_ACTIVATED;
435                         rstn_data->limit_exceeded = 0;
436                         rstn_data->limit_notified = 0;
437         }
438         break;
439         case RST_UNSET:
440         {
441                         int i;
442                         __rstn_del_tether_rule(rstn_data->classid, mac_str,
443                                         NFACCT_TETH_BLOCK, rstn_data->iftype);
444
445                         rstn_data->rstn_state = STC_RSTN_STATE_DEACTIVATED;
446                         rstn_data->limit_exceeded = 0;
447                         rstn_data->limit_notified = 0;
448
449                         for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++)
450                                 if (rstn_data->limit[i] >= 0)
451                                         rstn_data->counter[i] = 0;
452         }
453         break;
454         default:
455                 break;
456         }
457         FREE(mac_str);
458 }
459
460 static void __rstn_process(enum traffic_restriction_type rstn_type,
461                                   char *app_id, stc_rstn_data_s *rstn_data, void *data)
462 {
463         stc_connection_s *old_connection = (stc_connection_s *)data;
464         stc_connection_s *connection = NULL;
465
466         if (old_connection != NULL) {
467                 connection = old_connection;
468                 if (connection->ifname == NULL)
469                         return;
470
471                 /* rstn not applicable for this interface */
472                 if (rstn_data->ifname != NULL &&
473                         g_strcmp0(rstn_data->ifname, "") != 0 &&
474                     g_strcmp0(connection->ifname, rstn_data->ifname) != 0 &&
475                     g_strcmp0(connection->tether_iface.ifname, rstn_data->ifname) != 0)
476                     return;
477         } else {
478                 GSList *conn_list = stc_get_connection_list();
479                 for (; conn_list != NULL; conn_list = conn_list->next) {
480                         stc_connection_s *conn = conn_list->data;
481                         if (conn == NULL || conn->ifname == NULL)
482                                 continue;
483
484                         if (rstn_data->ifname != NULL &&
485                                 g_strcmp0(rstn_data->ifname, "") != 0 &&
486                                 g_strcmp0(conn->ifname, rstn_data->ifname) == 0 &&
487                                 g_strcmp0(conn->tether_iface.ifname, rstn_data->ifname) == 0)
488                                 connection = conn;
489                 }
490
491                 if (connection == NULL)
492                         return;
493         }
494
495         /* classid is invalid */
496         if (rstn_data->classid <= STC_UNKNOWN_CLASSID)
497                 return;
498
499         /* Do not proceed for tethering station appid if found here,
500          * for tethering station apps __rstn_tethering_process() call
501          * will handle it */
502         if (g_str_has_suffix(app_id, STC_TETHERING_APP_SUFFIX) &&
503                         rstn_data->classid != STC_TETHERING_APP_CLASSID)
504                 return;
505
506         switch (rstn_type) {
507         case RST_SET:
508         {
509                 int i;
510                 table_counters_info info;
511                 int64_t effective_limit[STC_RSTN_LIMIT_TYPE_MAX] = { 0, };
512
513                 memset(&info, 0, sizeof(table_counters_info));
514                 rstn_data->limit_exceeded = 0;
515
516                 if ((rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 &&
517                         rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) ||
518                         (rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 &&
519                         rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) ||
520                         (rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 &&
521                         rstn_data->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) ||
522                         (rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 &&
523                         rstn_data->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) ||
524                         (rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 &&
525                         rstn_data->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) {
526                         table_counters_get(rstn_data->restriction_id, &info);
527
528                         time_t current_time = 0;
529                         stc_rstn_cumulative_data_s stat;
530                         table_statistics_select_rule rule;
531                         time_t last_week_ts = stc_monitor_get_last_week_ts();
532                         time_t last_day_ts = stc_monitor_get_last_day_ts();
533
534                         memset(&stat, 0, sizeof(stc_rstn_cumulative_data_s));
535                         stat.month_start_ts = rstn_data->month_start_ts;
536                         stat.week_start_ts = last_week_ts;
537                         stat.day_start_ts = last_day_ts;
538
539                         memset(&rule, 0, sizeof(table_statistics_select_rule));
540                         rule.from = rstn_data->month_start_ts;
541                         time(&current_time);
542                         rule.to = current_time;
543                         rule.iftype = rstn_data->iftype;
544                         rule.granularity = GRANULARITY;
545
546                         table_statistics_per_app(rstn_data->app_id, &rule, __statistics_info_cb, &stat);
547
548                         rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter;
549                         rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter;
550                         rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter + stat.monthly_stat;
551                         rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter + stat.weekly_stat;
552                         rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter + stat.daily_stat;
553
554                         if (STC_DEBUG_LOG)
555                                 STC_LOGD("Rstn counter data[%lld] warn[%lld] "
556                                 "monthly[%lld] weekly[%lld] daily[%lld]",
557                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA],
558                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN],
559                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY],
560                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY],
561                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY]);
562                 }
563
564                 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
565                         if (rstn_data->limit[i] >= 0) {
566                                 effective_limit[i] = rstn_data->limit[i] - rstn_data->counter[i];
567
568                                 if (effective_limit[i] < 0)
569                                         rstn_data->limit_exceeded |= (1 << i);
570                         }
571                 }
572
573                 STC_LOGD("Rstn_id[%llu] limit[%lld] datausage[%lld]",
574                                         rstn_data->restriction_id,
575                                         rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA],
576                                         info.data_counter);
577
578                 if (rstn_data->limit_exceeded != 0 &&
579                         rstn_data->limit_exceeded != (1 << STC_RSTN_LIMIT_TYPE_DATA_WARN)) {
580                         __rstn_add_ipt_rule(rstn_data->classid, NFACCT_BLOCK, rstn_data->iftype);
581                 }
582
583                 if (rstn_data->classid == STC_BACKGROUND_APP_CLASSID)
584                         __rstn_add_ipt_rule(rstn_data->classid, NFACCT_BLOCK, rstn_data->iftype);
585
586                 rstn_data->rstn_state = STC_RSTN_STATE_ACTIVATED;
587
588                 if (STC_DEBUG_LOG) {
589                         STC_LOGD("Restriction activated "
590                                 "[\033[1;36m%d\033[0;m:\033[1;35m%d\033[0;m]",
591                                 rstn_data->classid, rstn_data->restriction_id);
592                 }
593         }
594         break;
595         case RST_EXCLUDE:
596                 __rstn_add_ipt_rule(rstn_data->classid, NFACCT_ALLOW,
597                                     rstn_data->iftype);
598
599                 rstn_data->rstn_state = STC_RSTN_STATE_ACTIVATED;
600                 rstn_data->limit_exceeded = 0;
601                 rstn_data->limit_notified = 0;
602
603                 if (STC_DEBUG_LOG) {
604                         STC_LOGD("Restriction activated "
605                                 "[\033[1;36m%d\033[0;m:\033[1;35m%d\033[0;m]",
606                                 rstn_data->classid, rstn_data->restriction_id);
607                 }
608                 break;
609         case RST_UNSET:
610         {
611                 int i;
612
613                 if (rstn_data->classid == STC_TETHERING_APP_CLASSID)
614                         __rstn_del_ipt_rule(rstn_data->classid, NFACCT_BLOCK,
615                                             rstn_data->iftype);
616                 else
617                         __rstn_del_ipt_rule(rstn_data->classid, rstn_data->rstn_type,
618                                             rstn_data->iftype);
619
620                 rstn_data->rstn_state = STC_RSTN_STATE_DEACTIVATED;
621                 rstn_data->limit_exceeded = 0;
622                 rstn_data->limit_notified = 0;
623
624                 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++)
625                         if (rstn_data->limit[i] >= 0)
626                                 rstn_data->counter[i] = 0;
627
628                 __rstn_set_noti_state(STC_RSTN_STATE_UNSET);
629
630                 if (STC_DEBUG_LOG) {
631                         STC_LOGD("Restriction deactivated "
632                                 "[\033[1;36m%d\033[0;m:\033[1;35m%d\033[0;m]",
633                                 rstn_data->classid, rstn_data->restriction_id);
634                 }
635         }
636         break;
637         default:
638                 break;
639         }
640 }
641
642 static void __rstn_add(gpointer data, gpointer user_data)
643 {
644         stc_rstn_data_s *rstn_data = (stc_rstn_data_s *)data;
645
646         /* rstn rule is activated */
647         if (rstn_data->rstn_state == STC_RSTN_STATE_ACTIVATED) {
648                 if (STC_DEBUG_LOG) {
649                         STC_LOGD("Restriction already activated "
650                                 "[\033[1;36m%d\033[0;m:\033[1;35m%d\033[0;m]",
651                                 rstn_data->classid, rstn_data->restriction_id);
652                 }
653                 return;
654         }
655
656         if (rstn_data->rstn_type == STC_RSTN_TYPE_ACCEPT) {
657                 __rstn_process(RST_EXCLUDE,
658                         rstn_data->app_id, rstn_data, user_data);
659                 __rstn_tethering_process(RST_EXCLUDE,
660                         rstn_data->app_id, rstn_data, user_data);
661         } else {
662                 __rstn_process(RST_SET,
663                         rstn_data->app_id, rstn_data, user_data);
664                 __rstn_tethering_process(RST_SET,
665                         rstn_data->app_id, rstn_data, user_data);
666         }
667
668         if (STC_DEBUG_LOG) {
669                 __print_rstn(rstn_data);
670                 STC_LOGD("\033[1;32mRestriction added\033[0;m "
671                         "[\033[1;36m%d\033[0;m:\033[1;35m%d\033[0;m]",
672                         rstn_data->classid, rstn_data->restriction_id);
673         }
674 }
675
676 static void __rstn_add_by_connection(gpointer key,
677                                         gpointer value, gpointer data)
678 {
679         stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
680
681         g_slist_foreach(rstn_value->rules, __rstn_add, data);
682 }
683
684 static void __rstn_remove(gpointer data, gpointer user_data)
685 {
686         stc_rstn_data_s *rstn_data = (stc_rstn_data_s *)data;
687
688         if (rstn_data->rstn_state == STC_RSTN_STATE_DEACTIVATED) {
689                 STC_LOGD("\033[1;31mRestriction already deactivated\033[0;m "
690                         "[\033[1;36m%d\033[0;m:\033[1;35m%d\033[0;m]",
691                         rstn_data->classid, rstn_data->restriction_id);
692                 return;
693         }
694
695         __rstn_process(RST_UNSET,
696                 rstn_data->app_id, rstn_data, user_data);
697         __rstn_tethering_process(RST_UNSET,
698                 rstn_data->app_id, rstn_data, user_data);
699
700         if (STC_DEBUG_LOG) {
701                 __print_rstn(rstn_data);
702                 STC_LOGD("\033[1;31mRestriction removed\033[0;m "
703                         "[\033[1;36m%d\033[0;m:\033[1;35m%d\033[0;m]",
704                         rstn_data->classid, rstn_data->restriction_id);
705         }
706 }
707
708 static void __rstn_remove_by_connection(gpointer key,
709                                         gpointer value, gpointer data)
710 {
711         stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
712
713         g_slist_foreach(rstn_value->rules, __rstn_remove, data);
714 }
715
716 static void __rstn_update_counter_data(gpointer data,
717                                                 gpointer user_data)
718 {
719         stc_rstn_data_s *rstn_data = (stc_rstn_data_s *)data;
720
721         table_counters_info info = {
722                 .restriction_id = rstn_data->restriction_id,
723                 .data_counter = rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA],
724                 .warn_counter = rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN],
725                 .monthly_counter = rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY],
726                 .weekly_counter = rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY],
727                 .daily_counter = rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY]
728         };
729
730         table_counters_update_counters(&info);
731 }
732
733 static void __rstn_update_counter_value(gpointer key,
734                                                 gpointer value, gpointer data)
735 {
736         stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
737
738         g_slist_foreach(rstn_value->rules, __rstn_update_counter_data, NULL);
739 }
740
741 static void __rstn_data_destroy(gpointer data)
742 {
743         stc_rstn_data_s *rstn_data = (stc_rstn_data_s *)data;
744
745         FREE(rstn_data->app_id);
746         FREE(rstn_data->ifname);
747         FREE(rstn_data->subscriber_id);
748         FREE(rstn_data->mac);
749
750         FREE(rstn_data);
751 }
752
753 static gint __rstn_data_comp(gconstpointer a, gconstpointer b)
754 {
755         stc_rstn_data_s *da = (stc_rstn_data_s *)a;
756         stc_rstn_data_s *db = (stc_rstn_data_s *)b;
757
758         if ((da->iftype == db->iftype) &&
759                 (g_strcmp0(da->ifname, db->ifname) == 0) &&
760                 (g_strcmp0(da->subscriber_id, db->subscriber_id) == 0) &&
761                 (da->roaming == db->roaming))
762                 return 0;
763
764         return -1;
765 }
766
767 static stc_error_e __rstn_data_remove(stc_rstn_data_s *data)
768 {
769         stc_rstn_value_s *lookup_value;
770         GSList *lookup_list;
771         stc_rstn_data_s *lookup_data;
772         GHashTable *rstns = stc_monitor_get_system_rstns();
773
774         if (!rstns)
775                 return STC_ERROR_NO_DATA;
776
777         lookup_value = g_hash_table_lookup(rstns, GUINT_TO_POINTER(data->classid));
778         if (!lookup_value) {
779                 if (STC_DEBUG_LOG)
780                         STC_LOGE("Restriction not found [\033[1;36m%d\033[0;m]",
781                                                 data->classid);
782                 return STC_ERROR_NO_DATA;
783         }
784
785         lookup_list = g_slist_find_custom(lookup_value->rules,
786                                         data, __rstn_data_comp);
787         if (!lookup_list) {
788                 if (STC_DEBUG_LOG)
789                         STC_LOGE("Restriction not found [%d:%s:%s:%d]",
790                                 data->iftype, data->ifname,
791                                 data->subscriber_id, data->roaming);
792                 return STC_ERROR_NO_DATA;
793         }
794
795         lookup_data = lookup_list->data;
796
797         /* remove counter also */
798         table_counters_delete(lookup_data->restriction_id);
799         __rstn_remove(lookup_data, NULL);
800
801         lookup_value->rules = g_slist_remove(lookup_value->rules,
802                                                         lookup_data);
803         __rstn_data_destroy(lookup_data);
804
805         if (!lookup_value->rules)
806                 g_hash_table_remove(rstns, GUINT_TO_POINTER(data->classid));
807
808         return STC_ERROR_NONE;
809 }
810
811 static stc_error_e __rstn_data_add(stc_rstn_data_s *data)
812 {
813         int i;
814         stc_rstn_value_s *lookup_value;
815         stc_rstn_value_s *rstn_value;
816         stc_rstn_data_s *rstn_data;
817         GHashTable *rstns = stc_monitor_get_system_rstns();
818
819         if (!rstns)
820                 return STC_ERROR_NO_DATA;
821
822         rstn_data = MALLOC0(stc_rstn_data_s, 1);
823         if (!rstn_data) {
824                 if (STC_DEBUG_LOG)
825                         STC_LOGE("Rstn_data allocation failed");
826                 return STC_ERROR_OUT_OF_MEMORY;
827         }
828
829         lookup_value = g_hash_table_lookup(rstns, GUINT_TO_POINTER(data->classid));
830         if (!lookup_value) {
831                 rstn_value = MALLOC0(stc_rstn_value_s, 1);
832                 if (!rstn_value) {
833                         if (STC_DEBUG_LOG)
834                                 STC_LOGE("Rstn_value allocation failed");
835                         FREE(rstn_data);
836                         return STC_ERROR_OUT_OF_MEMORY;
837                 }
838
839                 g_hash_table_insert(rstns, GUINT_TO_POINTER(data->classid),
840                         rstn_value);
841         } else {
842                 rstn_value = lookup_value;
843         }
844
845         rstn_data->classid = data->classid;
846         rstn_data->app_id = g_strdup(data->app_id);
847         rstn_data->iftype = data->iftype;
848         rstn_data->ifname = g_strdup(data->ifname);
849         rstn_data->subscriber_id = g_strdup(data->subscriber_id);
850         rstn_data->roaming = data->roaming;
851         rstn_data->mac = g_strdup(data->mac);
852
853         rstn_data->restriction_id = data->restriction_id;
854         rstn_data->rstn_state = data->rstn_state;
855         rstn_data->rstn_type = data->rstn_type;
856
857         for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
858                 rstn_data->limit[i] = data->limit[i];
859                 rstn_data->counter[i] = 0;
860         }
861
862         rstn_data->limit_exceeded = 0;
863         rstn_data->limit_notified = 0;
864         rstn_data->month_start_date = data->month_start_date;
865         rstn_data->month_start_ts = data->month_start_ts;
866
867         __rstn_data_remove(rstn_data);
868         rstn_value->rules = g_slist_append(rstn_value->rules, rstn_data);
869
870         __rstn_add(rstn_data, NULL);
871
872         return STC_ERROR_NONE;
873 }
874
875 static void __rstn_value_destroy(gpointer data)
876 {
877         stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)data;
878
879         g_slist_free_full(rstn_value->rules, __rstn_data_destroy);
880
881         FREE(rstn_value);
882 }
883
884 static stc_cb_ret_e __rstn_insert_cb(const table_restrictions_info *info,
885                                             void *user_data)
886 {
887         stc_cb_ret_e ret = STC_CONTINUE;
888         stc_rstn_data_s data;
889
890         memset(&data, 0, sizeof(stc_rstn_data_s));
891
892         if (info->app_id) {
893                 data.classid = get_classid_by_app_id(info->app_id, TRUE);
894                 data.app_id = info->app_id;
895         } else
896                 data.classid = STC_UNKNOWN_CLASSID;
897
898         data.iftype = info->iftype;
899         data.ifname = info->ifname;
900         data.subscriber_id = info->subscriber_id;
901         data.roaming = info->roaming;
902
903         data.rstn_type = info->rstn_type;
904         data.rstn_state = STC_RSTN_STATE_UNKNOWN;
905         data.restriction_id = info->restriction_id;
906
907         data.limit[STC_RSTN_LIMIT_TYPE_DATA] = info->data_limit;
908         data.limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info->data_warn_limit;
909         data.limit[STC_RSTN_LIMIT_TYPE_MONTHLY] = info->monthly_limit;
910         data.limit[STC_RSTN_LIMIT_TYPE_WEEKLY] = info->weekly_limit;
911         data.limit[STC_RSTN_LIMIT_TYPE_DAILY] = info->daily_limit;
912
913         if (__rstn_data_add(&data) != STC_ERROR_NONE)
914                 ret = STC_CANCEL;
915
916         return ret;
917 }
918
919 static void __rstn_update_counter(classid_bytes_context_s *context,
920                                 uint32_t classid)
921 {
922         stc_rstn_value_s *lookup;
923         GHashTable *rstns = stc_monitor_get_system_rstns();
924
925         if (!rstns)
926                 return;
927
928         lookup = g_hash_table_lookup(rstns, GUINT_TO_POINTER(classid));
929         if (lookup) {
930                 context->counter->classid = classid;
931                 g_slist_foreach(lookup->rules,
932                         stc_monitor_rstn_update_counter,
933                         context);
934         }
935 }
936
937 static void __rstn_action_when_limit_exceeded_tethering(stc_rstn_data_s *rstn_data,
938                                         classid_bytes_context_s *context)
939 {
940         char *mac_str = NULL;
941         struct nfacct_rule *counter = context->counter;
942
943         /* get the station mac based on classid */
944         stc_plugin_tether_get_station_by_classid(counter->classid, &mac_str);
945         if (!mac_str) {
946                 STC_LOGE("Station not found for classid(%d)", counter->classid);
947                 return;
948         }
949
950         STC_LOGI("Station mac[%s] classid[%u] iftype[%u] iotype[%d] "
951                         "intend[%d] ifname[%s] bytes[%lld]", mac_str,
952                         counter->classid, counter->iftype, counter->iotype,
953                         counter->intend, counter->ifname, context->bytes);
954
955         /* Block tethering station immediately */
956         counter->intend = NFACCT_TETH_BLOCK;
957         __rstn_del_tether_rule(counter->classid, mac_str,
958                         NFACCT_TETH_BLOCK, rstn_data->iftype);
959
960         __rstn_add_tether_rule(counter->classid, mac_str,
961                         NFACCT_TETH_BLOCK, rstn_data->iftype);
962         counter->intend = NFACCT_TETH_COUNTER;
963
964         g_free(mac_str);
965 }
966
967 static void __reset_time_counter_foreach_rstn_data(gpointer data,
968                                                   gpointer user_data)
969 {
970         stc_rstn_data_s *rstn_data = (stc_rstn_data_s *)data;
971         reset_time_limits_context_s *context =
972                 (reset_time_limits_context_s *)user_data;
973         int i;
974         time_t now_month_start_ts;
975
976         if (rstn_data->month_start_date == 0) {
977                 table_counters_info info;
978                 memset(&info, 0, sizeof(table_counters_info));
979                 table_counters_get_timestamps(rstn_data->restriction_id, &info);
980
981                 if (info.month_start_date == 0)
982                         rstn_data->month_start_date = 1;
983                 else
984                         rstn_data->month_start_date = info.month_start_date;
985                 rstn_data->month_start_ts = info.month_start_ts;
986         }
987
988         now_month_start_ts =
989                 stc_time_get_month_start(context->now,
990                                          rstn_data->month_start_date);
991
992         if (rstn_data->month_start_ts != now_month_start_ts) {
993                 rstn_data->month_start_ts = now_month_start_ts;
994                 context->month_start_ts = now_month_start_ts;
995                 context->is_updated |= (1 << STC_RSTN_LIMIT_TYPE_MONTHLY);
996         }
997
998         if (context->is_updated) {
999                 table_counters_info info;
1000                 memset(&info, 0, sizeof(table_counters_info));
1001
1002                 info.restriction_id = rstn_data->restriction_id;
1003                 info.month_start_date = rstn_data->month_start_date;
1004                 info.month_start_ts = rstn_data->month_start_ts;
1005                 info.week_start_ts = context->week_start_ts;
1006                 info.day_start_ts = context->day_start_ts;
1007
1008                 table_counters_update_timestamps(&info);
1009         }
1010
1011         for (i = STC_RSTN_LIMIT_TYPE_MONTHLY; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
1012
1013                 if ((context->is_updated) & (1 << i)) {
1014                         /* reset limit */
1015                         rstn_data->counter[i] = 0;
1016
1017                         if (rstn_data->limit_exceeded & (1 << i)) {
1018                                 /* remove iptables rule */
1019                                 GSList *conn_list = stc_get_connection_list();
1020                                 struct nfacct_rule counter;
1021                                 stc_s *stc = stc_get_manager();
1022                                 if (stc == NULL) {
1023                                         STC_LOGE("Can't get stc data");
1024                                         goto try_next_callback;
1025                                 }
1026
1027                                 if (!stc->carg) {
1028                                         stc->carg = MALLOC0(counter_arg_s, 1);
1029                                         if (stc->carg == NULL) {
1030                                                 goto try_next_callback;
1031                                         }
1032
1033                                         stc->carg->sock = stc_monitor_get_contr_sock();
1034                                 }
1035
1036                                 for (; conn_list != NULL; conn_list = conn_list->next) {
1037                                         stc_connection_s *conn = conn_list->data;
1038
1039                                         memset(&counter, 0, sizeof(struct nfacct_rule));
1040
1041                                         counter.carg = stc->carg;
1042                                         counter.classid = rstn_data->classid;
1043                                         counter.intend = NFACCT_BLOCK;
1044                                         counter.iftype = rstn_data->iftype;
1045                                         g_strlcpy(counter.ifname, conn->ifname, MAX_IFACE_LENGTH);
1046
1047                                         /* iptables rule */
1048                                         stc_monitor_ipt_del_in(&counter);
1049                                         stc_monitor_ipt_del_out(&counter);
1050
1051                                         /* ip6tables rule */
1052                                         stc_monitor_ip6t_del_in(&counter);
1053                                         stc_monitor_ip6t_del_out(&counter);
1054
1055                                         rstn_data->rstn_state = STC_RSTN_STATE_DEACTIVATED;
1056                                         rstn_data->limit_exceeded &= ~(1 << i);
1057                                         rstn_data->limit_notified &= ~(1 << i);
1058                                 }
1059                         }
1060                 }
1061         }
1062
1063 try_next_callback:
1064         return;
1065 }
1066
1067 static void __reset_time_counter_foreach_rstn_value(gpointer key,
1068                                                   gpointer value,
1069                                                   gpointer data)
1070 {
1071         stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1072         g_slist_foreach(rstn_value->rules,
1073                 __reset_time_counter_foreach_rstn_data, data);
1074 }
1075
1076 void stc_monitor_rstn_reset_time_counters_if_required(void)
1077 {
1078         reset_time_limits_context_s context;
1079         GHashTable *rstns = stc_monitor_get_system_rstns();
1080         time_t last_week_ts = stc_monitor_get_last_week_ts();
1081         time_t last_day_ts = stc_monitor_get_last_day_ts();
1082
1083         context.now = time(NULL);
1084         context.week_start_ts = stc_time_get_week_start(context.now);
1085         context.day_start_ts = stc_time_get_day_start(context.now);
1086         context.is_updated = 0;
1087
1088         if (last_week_ts != context.week_start_ts) {
1089                 stc_monitor_set_last_week_ts(context.week_start_ts);
1090                 context.is_updated |= (1 << STC_RSTN_LIMIT_TYPE_WEEKLY);
1091         }
1092
1093         if (last_day_ts != context.day_start_ts) {
1094                 stc_monitor_set_last_day_ts(context.day_start_ts);
1095                 context.is_updated |= (1 << STC_RSTN_LIMIT_TYPE_DAILY);
1096         }
1097
1098         if (rstns) {
1099                 g_hash_table_foreach(rstns,
1100                                __reset_time_counter_foreach_rstn_value,
1101                                &context);
1102
1103                 if (context.is_updated)
1104                         STC_LOGD("Counter reset completed month_start[%ld] "
1105                                 "week_start[%ld] day_start[%ld]",
1106                                 context.month_start_ts, last_week_ts, last_day_ts);
1107         }
1108 }
1109
1110 void stc_monitor_rstn_update_counter(gpointer data,
1111                                         gpointer user_data)
1112 {
1113         int i;
1114         stc_rstn_data_s *rstn_data = (stc_rstn_data_s *)data;
1115         classid_bytes_context_s *context = (classid_bytes_context_s *)user_data;
1116         GSList *conn_list = stc_get_connection_list();
1117
1118         for (; conn_list != NULL; conn_list = conn_list->next) {
1119                 stc_connection_s *conn = conn_list->data;
1120
1121                 if (rstn_data->iftype != context->counter->iftype)
1122                         return;
1123
1124                 if (rstn_data->ifname != NULL &&
1125                         g_strcmp0(rstn_data->ifname, "") &&
1126                         g_strcmp0(rstn_data->ifname, context->counter->ifname) != 0)
1127                         return;
1128
1129                 if (rstn_data->subscriber_id != NULL &&
1130                         g_strcmp0(rstn_data->subscriber_id, "") &&
1131                         g_strcmp0(rstn_data->subscriber_id, conn->subscriber_id) != 0)
1132                         return;
1133
1134                 if (rstn_data->roaming != conn->roaming)
1135                         return;
1136
1137                 if (rstn_data->limit_exceeded != 0) {
1138                         context->data_limit_exceeded = TRUE;
1139                         return;
1140                 }
1141
1142                 switch (context->counter->iotype) {
1143                 case NFACCT_COUNTER_IN:
1144                 case NFACCT_COUNTER_OUT:
1145                         if ((rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 &&
1146                                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) ||
1147                                 (rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 &&
1148                                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) ||
1149                                 (rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 &&
1150                                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) ||
1151                                 (rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 &&
1152                                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) ||
1153                                 (rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 &&
1154                                 rstn_data->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) {
1155                                 table_counters_info info;
1156                                 memset(&info, 0, sizeof(table_counters_info));
1157                                 table_counters_get(rstn_data->restriction_id, &info);
1158
1159                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter;
1160                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter;
1161                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter;
1162                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter;
1163                                 rstn_data->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter;
1164                         }
1165
1166                         for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
1167                                 if (rstn_data->limit[i] >= 0 &&
1168                                         !(rstn_data->limit_notified & (1 << i))) {
1169                                         rstn_data->counter[i] += context->bytes;
1170                                         if (rstn_data->limit[i] <= rstn_data->counter[i])
1171                                                 stc_monitor_rstn_action_when_limit_exceeded(i,
1172                                                                                         rstn_data,
1173                                                                                         context);
1174                                 }
1175                         }
1176
1177                         stc_monitor_set_rstns_updated(TRUE);
1178                         __print_rstn(rstn_data);
1179                         break;
1180                 default:
1181                         STC_LOGE("Unknown iotype");
1182                 }
1183         }
1184 }
1185
1186 void stc_monitor_rstn_update_iface_counter(classid_bytes_context_s *context)
1187 {
1188         switch (context->counter->iftype) {
1189         case STC_IFACE_DATACALL:
1190                 __rstn_update_counter(context, STC_TOTAL_DATACALL_CLASSID);
1191                 break;
1192         case STC_IFACE_WIFI:
1193                 __rstn_update_counter(context, STC_TOTAL_WIFI_CLASSID);
1194                 __rstn_update_counter(context, STC_TETHERING_APP_CLASSID);
1195                 break;
1196         case STC_IFACE_BLUETOOTH:
1197                 __rstn_update_counter(context, STC_TOTAL_BLUETOOTH_CLASSID);
1198                 __rstn_update_counter(context, STC_TETHERING_APP_CLASSID);
1199                 break;
1200         case STC_IFACE_USB:
1201                 __rstn_update_counter(context, STC_TETHERING_APP_CLASSID);
1202                 break;
1203         case STC_IFACE_P2P:
1204                 __rstn_update_counter(context, STC_TETHERING_APP_CLASSID);
1205                 break;
1206         default:
1207                 break;
1208         }
1209 }
1210
1211 void stc_monitor_rstn_action_when_limit_exceeded(stc_rstn_limit_type_e limit_type,
1212                                                 stc_rstn_data_s *rstn_data,
1213                                                 classid_bytes_context_s *context)
1214 {
1215         gboolean rv;
1216         char iftype[MAX_INT_LENGTH] = { 0, };
1217         char byte[MAX_INT_LENGTH] = { 0, };
1218         const char *signal_name = NULL;
1219         const char *net_popup_content = NULL;
1220         const char *net_popup_type = NULL;
1221         stc_s *stc = (stc_s *)stc_get_manager();
1222
1223         if (stc == NULL) {
1224                 STC_LOGE("Failed to get stc data");
1225                 return;
1226         }
1227
1228         switch (limit_type) {
1229         case STC_RSTN_LIMIT_TYPE_DATA_WARN:
1230         {
1231                 signal_name = "WarnThresholdCrossed";
1232                 net_popup_content = "warn threshold crossed";
1233                 net_popup_type = "warning_noti";
1234         }
1235         break;
1236         case STC_RSTN_LIMIT_TYPE_DATA:
1237         case STC_RSTN_LIMIT_TYPE_MONTHLY:
1238         case STC_RSTN_LIMIT_TYPE_WEEKLY:
1239         case STC_RSTN_LIMIT_TYPE_DAILY:
1240         {
1241                 signal_name = "RestrictionThresholdCrossed";
1242                 net_popup_content = "restriction threshold crossed";
1243                 net_popup_type = "restriction_noti";
1244
1245                 /* Apply restriction for tethering apps if app_id is of tethering client
1246                  * otherwise do the normal iptables rule */
1247                 if (context->counter->intend == NFACCT_TETH_COUNTER) {
1248
1249                         if (g_str_has_suffix(rstn_data->app_id, STC_TETHERING_APP_SUFFIX) &&
1250                                         rstn_data->classid != STC_TETHERING_APP_CLASSID) {
1251                                 __rstn_action_when_limit_exceeded_tethering(rstn_data,
1252                                                 context);
1253                         }
1254
1255                 } else {
1256                         /* block immediately */
1257                         context->counter->intend = NFACCT_BLOCK;
1258                         stc_monitor_ipt_del_in(context->counter);
1259                         stc_monitor_ipt_del_out(context->counter);
1260                         stc_monitor_ipt_add_in(context->counter);
1261                         stc_monitor_ipt_add_out(context->counter);
1262
1263                         stc_monitor_ip6t_del_in(context->counter);
1264                         stc_monitor_ip6t_del_out(context->counter);
1265                         stc_monitor_ip6t_add_in(context->counter);
1266                         stc_monitor_ip6t_add_out(context->counter);
1267                         context->counter->intend = NFACCT_COUNTER;
1268                 }
1269
1270                 rstn_data->limit_exceeded |= (1 << limit_type);
1271                 __rstn_set_noti_state(STC_RSTN_STATE_SET);
1272         }
1273         break;
1274         default:
1275                 break;
1276         }
1277
1278         if (signal_name == NULL) {
1279                 STC_LOGE("Invalid parameter: limit_type");
1280                 return;
1281         }
1282
1283         /* emit signal */
1284         rv = stc_manager_dbus_emit_signal(stc->connection,
1285                                                   STC_DBUS_SERVICE_RESTRICTION_PATH,
1286                                                   STC_DBUS_INTERFACE_RESTRICTION,
1287                                                   signal_name,
1288                                                   g_variant_new("(si)",
1289                                                   rstn_data->app_id,
1290                                                   rstn_data->iftype));
1291
1292         if (rv == TRUE)
1293                 rstn_data->limit_notified |= (1 << limit_type);
1294
1295         snprintf(iftype, MAX_INT_LENGTH, "%d", rstn_data->iftype);
1296         snprintf(byte, MAX_INT_LENGTH, "%lld", rstn_data->limit[limit_type]);
1297         stc_plugin_appstatus_send_message(net_popup_content,
1298                         net_popup_type, rstn_data->app_id, iftype, byte);
1299
1300         if (STC_DEBUG_LOG)
1301                 STC_LOGD("Limit exceeded [\033[0;31m%s\033[0;m:%d]",
1302                                         net_popup_content, limit_type);
1303 }
1304
1305 gboolean stc_monitor_rstn_flush_contr_to_db(gpointer user_data)
1306 {
1307         time_t current_time = 0;
1308         stc_s *stc = stc_get_manager();
1309         GHashTable *rstns = stc_monitor_get_system_rstns();
1310         gboolean rstns_updated = stc_monitor_get_rstns_updated();
1311
1312         if (stc && stc->carg)
1313                 current_time = stc->carg->last_run_time;
1314
1315         if (rstns_updated == FALSE)
1316                 return G_SOURCE_REMOVE;
1317
1318         stc_monitor_set_rstns_updated(FALSE);
1319
1320         if (rstns)
1321                 g_hash_table_foreach(rstns,
1322                                __rstn_update_counter_value,
1323                                &current_time);
1324
1325         STC_LOGI("Flushed rstns counters to database");
1326         return G_SOURCE_REMOVE;
1327 }
1328
1329 stc_error_e stc_monitor_rstn_add(const table_restrictions_info *info)
1330 {
1331         stc_rstn_data_s data;
1332
1333         memset(&data, 0, sizeof(stc_rstn_data_s));
1334
1335         if (info->app_id) {
1336                 data.classid = get_classid_by_app_id(info->app_id, TRUE);
1337                 data.app_id = info->app_id;
1338         } else
1339                 data.classid = STC_UNKNOWN_CLASSID;
1340
1341         if (data.classid == STC_BACKGROUND_APP_CLASSID) {
1342                 stc_monitor_set_background_state(TRUE);
1343                 __vconf_set_int(VCONFKEY_STC_BACKGROUND_STATE, TRUE);
1344         }
1345
1346         data.iftype = info->iftype;
1347         data.ifname = info->ifname;
1348         data.subscriber_id = info->subscriber_id;
1349         data.roaming = info->roaming;
1350         data.mac = info->mac;
1351
1352         data.rstn_type = info->rstn_type;
1353         data.rstn_state = STC_RSTN_STATE_UNKNOWN;
1354         data.restriction_id = info->restriction_id;
1355
1356         data.limit[STC_RSTN_LIMIT_TYPE_DATA] = info->data_limit;
1357         data.limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info->data_warn_limit;
1358         data.limit[STC_RSTN_LIMIT_TYPE_MONTHLY] = info->monthly_limit;
1359         data.limit[STC_RSTN_LIMIT_TYPE_WEEKLY] = info->weekly_limit;
1360         data.limit[STC_RSTN_LIMIT_TYPE_DAILY] = info->daily_limit;
1361         data.month_start_date = info->month_start_date;
1362         data.month_start_ts = stc_time_get_month_start(time(NULL),
1363                                                                                 info->month_start_date);
1364
1365         return __rstn_data_add(&data);
1366 }
1367
1368 void stc_monitor_rstn_add_for_app(uint32_t classid)
1369 {
1370         stc_rstn_value_s *lookup_value;
1371         GHashTable *rstns = stc_monitor_get_system_rstns();
1372
1373         if (!rstns)
1374                 return;
1375
1376         lookup_value = g_hash_table_lookup(rstns, GUINT_TO_POINTER(classid));
1377         if (!lookup_value) {
1378                 if (STC_DEBUG_LOG)
1379                         STC_LOGD("Restriction not found [\033[1;36m%d\033[0;m]",
1380                                                 classid);
1381                 return;
1382         }
1383
1384         g_slist_foreach(lookup_value->rules, __rstn_add, NULL);
1385 }
1386
1387 void stc_monitor_rstn_add_by_connection(stc_connection_s *conn)
1388 {
1389         GHashTable *rstns = stc_monitor_get_system_rstns();
1390
1391         if (!rstns)
1392                 return;
1393
1394         g_hash_table_foreach(rstns, __rstn_add_by_connection, conn);
1395 }
1396
1397 stc_error_e stc_monitor_rstn_remove(const table_restrictions_info *info)
1398 {
1399         stc_rstn_data_s data;
1400
1401         memset(&data, 0, sizeof(stc_rstn_data_s));
1402
1403         data.classid = get_classid_by_app_id(info->app_id, TRUE);
1404         data.app_id = info->app_id;
1405
1406         data.iftype = info->iftype;
1407         data.ifname = info->ifname;
1408         data.subscriber_id = info->subscriber_id;
1409         data.roaming = info->roaming;
1410
1411         if (g_strcmp0(info->app_id, STC_TOTAL_BACKGROUND) == 0) {
1412                 stc_monitor_set_background_state(FALSE);
1413                 __vconf_set_int(VCONFKEY_STC_BACKGROUND_STATE, FALSE);
1414         }
1415
1416         return __rstn_data_remove(&data);
1417 }
1418
1419 void stc_monitor_rstn_remove_for_app(uint32_t classid)
1420 {
1421         stc_rstn_value_s *lookup_value;
1422         GHashTable *rstns = stc_monitor_get_system_rstns();
1423
1424         if (!rstns)
1425                 return;
1426
1427         lookup_value = g_hash_table_lookup(rstns, GUINT_TO_POINTER(classid));
1428         if (!lookup_value) {
1429                 if (STC_DEBUG_LOG)
1430                         STC_LOGD("Restriction not found [\033[1;36m%d\033[0;m]",
1431                                                 classid);
1432                 return;
1433         }
1434
1435         g_slist_foreach(lookup_value->rules, __rstn_remove, NULL);
1436 }
1437
1438 void stc_monitor_rstn_remove_by_connection(stc_connection_s *conn)
1439 {
1440         GHashTable *rstns = stc_monitor_get_system_rstns();
1441
1442         if (!rstns)
1443                 return;
1444
1445         g_hash_table_foreach(rstns, __rstn_remove_by_connection, conn);
1446 }
1447
1448 void stc_monitor_rstns_load(void)
1449 {
1450         table_restrictions_foreach(__rstn_insert_cb, NULL);
1451
1452         /* __rstn_tree_printall(); */
1453 }
1454
1455 GHashTable *stc_monitor_rstns_init(void)
1456 {
1457         return g_hash_table_new_full(g_direct_hash, g_direct_equal,
1458                                         NULL, __rstn_value_destroy);
1459 }