ceeb0b455430b7ed07a4904fec9b821190b0795a
[platform/core/connectivity/stc-manager.git] / src / monitor / stc-monitor-app.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 "stc-db.h"
18 #include "counter.h"
19 #include "stc-manager.h"
20 #include "stc-monitor.h"
21 #include "stc-monitor-app.h"
22 #include "stc-monitor-rstn.h"
23 #include "stc-monitor-proc.h"
24 #include "stc-monitor-ipt.h"
25 #include "table-statistics.h"
26 #include "helper-net-cls.h"
27 #include "stc-manager-plugin-tether.h"
28
29 static void __print_app(gpointer key, gpointer value,
30                                           gpointer data)
31 {
32         stc_app_value_s *app_value = (stc_app_value_s *)value;
33
34         STC_LOGD("PkgID[%s] AppID[\033[0;32m%s\033[0;m] "
35                 "type[%d] state[%d] classid[\033[1;36m%d\033[0;m] "
36                 "counter[in(%lld) out(%lld)]",
37                  app_value->pkg_id, app_value->app_id,
38                  app_value->type, app_value->state,
39                  app_value->classid,
40                  app_value->data_usage.in_bytes,
41                  app_value->data_usage.out_bytes);
42 }
43
44 static void __app_update_statistics(gpointer key,
45                                         gpointer value, gpointer data)
46 {
47         stc_app_value_s *app_value = (stc_app_value_s *)value;
48         time_t *touch_time = (time_t *)data;
49         GSList *conn_list = stc_get_connection_list();
50
51         for (; conn_list != NULL; conn_list = conn_list->next) {
52                 stc_connection_s *conn = conn_list->data;
53                 stc_db_classid_iftype_key stat_key;
54                 stc_db_app_stats stat;
55
56                 memset(&stat_key, 0, sizeof(stc_db_classid_iftype_key));
57                 memset(&stat, 0 , sizeof(stc_db_app_stats));
58
59                 if (conn == NULL)
60                         return;
61
62                 /* Do not update statistics for Tethering
63                  * if tethering is in-active found */
64                 if (conn && conn->tether_state == FALSE &&
65                         !strcmp(app_value->app_id, STC_TOTAL_TETHERING))
66                         return;
67
68                 /* Do not update statistics for Wi-Fi
69                  * if tethering is active on wlan0 iface */
70                 if (conn && conn->tether_state &&
71                         conn->tether_iface.type == STC_IFACE_WIFI &&
72                         !strcmp(app_value->app_id, STC_TOTAL_WIFI))
73                         return;
74
75                 stat_key.classid = app_value->classid;
76
77                 if (app_value->classid == STC_TETHERING_APP_CLASSID &&
78                         conn->tether_state == TRUE)
79                         stat_key.iftype = conn->tether_iface.type;
80                 else if (g_str_has_suffix(app_value->app_id, STC_TETHERING_APP_SUFFIX))
81                         stat_key.iftype = conn->tether_iface.type;
82                 else
83                         stat_key.iftype = conn->type;
84
85                 if (STC_IFACE_DATACALL == stat_key.iftype)
86                         stat_key.subscriber_id = g_strdup(conn->subscriber_id);
87                 else
88                         stat_key.subscriber_id = g_strdup(SUBSCRIBERID_NONE);
89
90                 if (app_value->classid == STC_TETHERING_APP_CLASSID &&
91                         conn->tether_state == TRUE)
92                         g_strlcpy(stat_key.ifname, conn->tether_iface.ifname,
93                                   MAX_IFACE_LENGTH);
94                 else if (g_str_has_suffix(app_value->app_id, STC_TETHERING_APP_SUFFIX))
95                         g_strlcpy(stat_key.ifname, conn->tether_iface.ifname,
96                                   MAX_IFACE_LENGTH);
97                 else
98                         g_strlcpy(stat_key.ifname, conn->ifname,
99                                   MAX_IFACE_LENGTH);
100
101                 stat.app_id = g_strdup(app_value->app_id);
102                 stat.snd_count = app_value->counter.out_bytes;
103                 stat.rcv_count = app_value->counter.in_bytes;
104                 stat.is_roaming = conn->roaming;
105
106                 if (strstr(stat.app_id, "_BACKGROUND")) {
107                         stat.ground = STC_APP_STATE_BACKGROUND;
108                 } else {
109                         if (strstr(stat.app_id, "TOTAL_"))
110                                 stat.ground = STC_APP_STATE_UNKNOWN;
111                         else
112                                 stat.ground = STC_APP_STATE_FOREGROUND;
113                 }
114
115                 table_statistics_insert(&stat_key, &stat, *touch_time);
116
117                 app_value->counter.out_bytes = 0;
118                 app_value->counter.in_bytes = 0;
119
120                 FREE(stat.app_id);
121                 FREE(stat_key.subscriber_id);
122         }
123
124         return;
125 }
126
127 static gboolean __add_app_monitor_for_tethering(gpointer key,
128                                     gpointer value, gpointer data)
129 {
130         stc_app_value_s *app_value = (stc_app_value_s *)value;
131         stc_connection_s *connection = (stc_connection_s *)data;
132         stc_s *stc = stc_get_manager();
133         struct nfacct_rule counter;
134         char *ipaddr = NULL;
135         int ret;
136
137         STC_LOGI("Add appid(%s) classid(%d)", app_value->app_id,
138                         app_value->classid);
139
140         if (stc == NULL || connection == NULL)
141                 return FALSE;
142
143         if (!stc->carg) {
144                 stc->carg = MALLOC0(counter_arg_s, 1);
145                 if (stc->carg == NULL)
146                         return FALSE;
147
148                 stc->carg->sock = stc_monitor_get_contr_sock();
149         }
150
151         memset(&counter, 0, sizeof(struct nfacct_rule));
152
153         counter.carg = stc->carg;
154         counter.classid = app_value->classid;
155         counter.intend = NFACCT_TETH_COUNTER;
156
157         if (connection->tether_state != TRUE ||
158                         connection->tether_iface.ifname == NULL)
159                 return FALSE;
160
161         counter.iftype = connection->tether_iface.type;
162         g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
163
164         /* get the ip address of the station based on its mac address */
165         ret = stc_plugin_tether_get_station_ip(app_value->mac, &ipaddr);
166         if (ret != STC_ERROR_NONE)
167                 return FALSE;
168
169         /* tethering iptables rule */
170         stc_monitor_tether_add_in(&counter, ipaddr);
171         stc_monitor_tether_add_out(&counter, ipaddr);
172
173         g_free(ipaddr);
174         return FALSE;
175 }
176
177 static gboolean __remove_app_monitor_for_tethering(gpointer key,
178                                 gpointer value, gpointer data)
179 {
180         stc_app_value_s *app_value = (stc_app_value_s *)value;
181         stc_connection_s *connection = (stc_connection_s *)data;
182         stc_s *stc = stc_get_manager();
183         struct nfacct_rule counter;
184         char *ipaddr = NULL;
185         int ret;
186
187         STC_LOGI("Remove appid(%s) classid(%d)", app_value->app_id,
188                         app_value->classid);
189
190         if (stc == NULL || connection == NULL)
191                 return FALSE;
192
193         if (!stc->carg) {
194                 stc->carg = MALLOC0(counter_arg_s, 1);
195                 if (stc->carg == NULL)
196                         return FALSE;
197
198                 stc->carg->sock = stc_monitor_get_contr_sock();
199         }
200
201         memset(&counter, 0, sizeof(struct nfacct_rule));
202
203         counter.carg = stc->carg;
204         counter.classid = app_value->classid;
205         counter.intend = NFACCT_TETH_COUNTER;
206
207         if (connection->tether_state != TRUE ||
208                         connection->tether_iface.ifname == NULL)
209                 return FALSE;
210
211         counter.iftype = connection->tether_iface.type;
212         g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
213
214         /* get the ip address of the station based on its mac address */
215         ret = stc_plugin_tether_get_station_ip(app_value->mac, &ipaddr);
216         if (ret != STC_ERROR_NONE)
217                 return FALSE;
218
219         stc_monitor_tether_del_in(&counter, ipaddr);
220         stc_monitor_tether_del_out(&counter, ipaddr);
221
222         g_free(ipaddr);
223         return FALSE;
224 }
225
226 static void __app_value_destroy(gpointer data)
227 {
228         stc_app_value_s *app_value = (stc_app_value_s *)data;
229
230         FREE(app_value->pkg_id);
231         FREE(app_value->app_id);
232         g_hash_table_destroy(app_value->processes);
233         app_value->processes = NULL;
234
235         FREE(app_value);
236 }
237
238 static void __check_rstn_limit_exceeded(gpointer data,
239                                 gpointer user_data)
240 {
241         stc_rstn_data_s *rstn_data = (stc_rstn_data_s *)data;
242         int32_t *limit_exceeded = (int32_t *)user_data;
243
244         if (rstn_data->limit_exceeded != 0)
245                 *limit_exceeded = rstn_data->limit_exceeded;
246 }
247
248 static void __app_update_counter(classid_bytes_context_s *context,
249                                 uint32_t classid)
250 {
251         stc_app_value_s *lookup_app;
252         stc_rstn_value_s *lookup_rstn;
253         GHashTable *apps = stc_monitor_get_system_apps();
254         GHashTable *rstns = stc_monitor_get_system_rstns();
255
256         if (!apps)
257                 return;
258
259         lookup_app = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
260         if (lookup_app)
261                 stc_monitor_app_update_counter(lookup_app, context);
262
263         if (!rstns)
264                 return;
265
266         lookup_rstn = g_hash_table_lookup(rstns, GUINT_TO_POINTER(classid));
267         if (lookup_rstn) {
268                 int32_t limit_exceeded = 0;
269                 g_slist_foreach(lookup_rstn->rules,
270                         __check_rstn_limit_exceeded, &limit_exceeded);
271
272                 if (limit_exceeded != 0)
273                         return;
274         }
275 }
276
277 void stc_monitor_app_update_counter(stc_app_value_s *value,
278                                  classid_bytes_context_s *context)
279 {
280         switch (context->counter->iotype) {
281         case NFACCT_COUNTER_IN:
282                 value->data_usage.in_bytes += context->bytes;
283                 value->counter.in_bytes = context->bytes;
284                 stc_monitor_set_apps_updated(TRUE);
285
286                 break;
287         case NFACCT_COUNTER_OUT:
288                 value->data_usage.out_bytes += context->bytes;
289                 value->counter.out_bytes = context->bytes;
290                 stc_monitor_set_apps_updated(TRUE);
291
292                 break;
293         default:
294                 STC_LOGE("Unknown iotype");
295         }
296 }
297
298 void stc_monitor_app_update_iface_counter(classid_bytes_context_s *context)
299 {
300         switch (context->counter->iftype) {
301         case STC_IFACE_DATACALL:
302                 __app_update_counter(context, STC_TOTAL_DATACALL_CLASSID);
303                 break;
304         case STC_IFACE_WIFI:
305                 __app_update_counter(context, STC_TOTAL_WIFI_CLASSID);
306                 __app_update_counter(context, STC_TETHERING_APP_CLASSID);
307                 break;
308         case STC_IFACE_BLUETOOTH:
309                 __app_update_counter(context, STC_TOTAL_BLUETOOTH_CLASSID);
310                 __app_update_counter(context, STC_TETHERING_APP_CLASSID);
311                 break;
312         case STC_IFACE_USB:
313                 __app_update_counter(context, STC_TETHERING_APP_CLASSID);
314                 break;
315         case STC_IFACE_P2P:
316                 __app_update_counter(context, STC_TETHERING_APP_CLASSID);
317                 break;
318         default:
319                 break;
320         }
321 }
322
323 gboolean stc_monitor_app_flush_stats_to_db(gpointer user_data)
324 {
325         time_t current_time = 0;
326         stc_s *stc = stc_get_manager();
327         GHashTable *apps = stc_monitor_get_system_apps();
328         gboolean apps_updated = stc_monitor_get_apps_updated();
329
330         if (stc && stc->carg)
331                 current_time = stc->carg->last_run_time;
332
333         if (apps_updated == FALSE)
334                 return G_SOURCE_REMOVE;
335
336         stc_monitor_set_apps_updated(FALSE);
337
338         if (apps)
339                 g_hash_table_foreach(apps,
340                                         __app_update_statistics,
341                                         &current_time);
342
343         STC_LOGI("Flushed app stats to database");
344         return G_SOURCE_REMOVE;
345 }
346
347 API stc_error_e stc_monitor_app_add(uint32_t classid,
348                                 const char *app_id,
349                                 const char *pkg_id,
350                                 const stc_app_value_s value)
351 {
352         stc_app_value_s *app_value;
353         stc_app_value_s *lookup_value;
354
355         GHashTable *apps = stc_monitor_get_system_apps();
356         GSList *conn_list = stc_get_connection_list();
357
358         if (!apps)
359                 return STC_ERROR_NO_DATA;
360
361         if (classid == STC_UNKNOWN_CLASSID)
362                 classid = get_classid_by_app_id(app_id, TRUE);
363
364         lookup_value = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
365         if (lookup_value) {
366                 if (STC_DEBUG_LOG && STC_STAT_LOG)
367                         STC_LOGE("Already exists [\033[1;36m%d\033[0;m:"
368                                                 "\033[0;32m%s\033[0;m]", classid, app_id);
369                 return STC_ERROR_NONE;
370         }
371
372         app_value = MALLOC0(stc_app_value_s, 1);
373         if (!app_value) {
374                 if (STC_DEBUG_LOG && STC_STAT_LOG)
375                         STC_LOGE("Value allocation failed");
376                 return STC_ERROR_OUT_OF_MEMORY;
377         }
378
379         /* create cgroup and update classid */
380         app_value->classid = classid;
381
382         app_value->app_id = g_strdup(app_id);
383         app_value->pkg_id = g_strdup(pkg_id);
384
385         app_value->type = value.type;
386         app_value->state = value.state;
387         app_value->data_usage.in_bytes = value.data_usage.in_bytes;
388         app_value->data_usage.out_bytes = value.data_usage.out_bytes;
389         g_strlcpy(app_value->mac, value.mac, MAC_ADDRESS_LEN);
390
391         app_value->processes = g_hash_table_new_full(g_direct_hash,
392                                                                 g_direct_equal, NULL, NULL);
393
394         /* update classid for tethering station based on its mac address */
395         if (g_str_has_suffix(app_id, STC_TETHERING_APP_SUFFIX) &&
396                                 classid != STC_TETHERING_APP_CLASSID)
397                 stc_plugin_tether_set_station_classid(app_value->mac, classid);
398
399         g_hash_table_insert(apps, GUINT_TO_POINTER(classid), app_value);
400
401         for (; conn_list != NULL; conn_list = conn_list->next) {
402                 stc_connection_s *conn = conn_list->data;
403                 /* add nfacct rule for this classid */
404                 stc_monitor_app_add_monitor(GUINT_TO_POINTER(classid),
405                                         app_value, conn);
406
407                 if (app_value->state == STC_APP_STATE_FOREGROUND)
408                         stc_monitor_app_add_accept(GUINT_TO_POINTER(classid),
409                                         app_value, conn);
410         }
411
412         stc_monitor_rstn_add_for_app(classid);
413
414         if (STC_DEBUG_LOG && STC_STAT_LOG) {
415                 __print_app(GUINT_TO_POINTER(classid), app_value, NULL);
416                 STC_LOGD("\033[1;32mApplication added\033[0;m "
417                         "[\033[1;36m%d\033[0;m]", classid);
418         }
419
420         return STC_ERROR_NONE;
421 }
422
423 void stc_monitor_app_add_by_iface(const char *ifname)
424 {
425         stc_app_value_s app_value;
426
427         if (ifname == NULL)
428                 return;
429
430         memset(&app_value, 0, sizeof(stc_app_value_s));
431
432         app_value.type = STC_APP_TYPE_NONE;
433         app_value.processes = NULL;
434         app_value.counter.in_bytes = 0;
435         app_value.counter.out_bytes = 0;
436
437         stc_monitor_app_add(STC_UNKNOWN_CLASSID, ifname, ifname, app_value);
438 }
439
440 void stc_monitor_app_add_monitor(gpointer key,
441                                 gpointer value, gpointer data)
442 {
443         stc_app_value_s *app_value = (stc_app_value_s *)value;
444         stc_connection_s *connection = (stc_connection_s *)data;
445         stc_s *stc = stc_get_manager();
446
447         if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
448             app_value->classid == STC_TOTAL_WIFI_CLASSID ||
449             app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
450                 return;
451
452         if (stc && connection && connection->ifname) {
453                 struct nfacct_rule counter;
454
455                 if (!stc->carg) {
456                         stc->carg = MALLOC0(counter_arg_s, 1);
457                         if (stc->carg == NULL)
458                                 return;
459
460                         stc->carg->sock = stc_monitor_get_contr_sock();
461                 }
462
463                 memset(&counter, 0, sizeof(struct nfacct_rule));
464
465                 counter.carg = stc->carg;
466                 counter.classid = app_value->classid;
467                 counter.app_state = app_value->state;
468                 counter.intend = NFACCT_COUNTER;
469
470                 if (connection->tether_state == TRUE &&
471                         connection->tether_iface.ifname != NULL &&
472                         app_value->classid == STC_TETHERING_APP_CLASSID) {
473                         counter.iftype = connection->tether_iface.type;
474                         g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
475                 } else {
476                         counter.iftype = connection->type;
477                         g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
478                 }
479
480                 if (g_str_has_suffix(app_value->app_id, STC_TETHERING_APP_SUFFIX) &&
481                                 app_value->classid != STC_TETHERING_APP_CLASSID) {
482                         __add_app_monitor_for_tethering(key, value, data);
483                 } else if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
484                         stc_monitor_ipt_add_in(&counter);
485                         stc_monitor_ipt_add_out(&counter);
486                 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
487                         stc_monitor_ip6t_add_in(&counter);
488                         stc_monitor_ip6t_add_out(&counter);
489                 } else {
490                         stc_monitor_ipt_add_in(&counter);
491                         stc_monitor_ipt_add_out(&counter);
492                         stc_monitor_ip6t_add_in(&counter);
493                         stc_monitor_ip6t_add_out(&counter);
494                 }
495         }
496 }
497
498 void stc_monitor_app_add_by_connection(stc_connection_s *conn)
499 {
500         GHashTable *apps = stc_monitor_get_system_apps();
501
502         if (!apps)
503                 return;
504
505         g_hash_table_foreach(apps, stc_monitor_app_add_monitor, conn);
506         g_hash_table_foreach(apps, stc_monitor_app_add_accept, conn);
507 }
508
509 void stc_monitor_app_add_accept(gpointer key,
510                                 gpointer value, gpointer data)
511 {
512         stc_app_value_s *app_value = (stc_app_value_s *)value;
513         stc_connection_s *connection = (stc_connection_s *)data;
514         stc_s *stc = stc_get_manager();
515
516         if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
517             app_value->classid == STC_TOTAL_WIFI_CLASSID ||
518             app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
519                 return;
520
521         if (app_value->state != STC_APP_STATE_FOREGROUND)
522                 return;
523
524         if (stc && connection && connection->ifname) {
525                 struct nfacct_rule counter;
526
527                 if (!stc->carg) {
528                         stc->carg = MALLOC0(counter_arg_s, 1);
529                         if (stc->carg == NULL)
530                                 return;
531
532                         stc->carg->sock = stc_monitor_get_contr_sock();
533                 }
534
535                 memset(&counter, 0, sizeof(struct nfacct_rule));
536
537                 counter.carg = stc->carg;
538                 counter.classid = app_value->classid;
539                 counter.app_state = app_value->state;
540                 counter.intend = NFACCT_ALLOW;
541
542                 counter.iftype = connection->type;
543                 g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
544
545                 if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
546                         stc_monitor_ipt_add_in(&counter);
547                         stc_monitor_ipt_add_out(&counter);
548                 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
549                         stc_monitor_ip6t_add_in(&counter);
550                         stc_monitor_ip6t_add_out(&counter);
551                 } else {
552                         stc_monitor_ipt_add_in(&counter);
553                         stc_monitor_ipt_add_out(&counter);
554                         stc_monitor_ip6t_add_in(&counter);
555                         stc_monitor_ip6t_add_out(&counter);
556                 }
557         }
558 }
559
560 API stc_error_e stc_monitor_app_remove(uint32_t classid, const char *app_id)
561 {
562         stc_app_value_s *app_lookup;
563         GHashTable *apps = stc_monitor_get_system_apps();
564         GSList *conn_list = stc_get_connection_list();
565
566         if (!apps)
567                 return STC_ERROR_NO_DATA;
568
569         classid = get_classid_by_app_id(app_id, FALSE);
570
571         app_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
572         if (!app_lookup) {
573                 if (STC_DEBUG_LOG && STC_STAT_LOG)
574                         STC_LOGD("Application not found [\033[1;36m%d\033[0;m]", classid);
575                 return STC_ERROR_FAIL;
576         }
577
578         for (; conn_list != NULL; conn_list = conn_list->next) {
579                 stc_connection_s *conn = conn_list->data;
580                 /* remove nfacct rule for this classid */
581                 stc_monitor_app_remove_monitor(GUINT_TO_POINTER(classid),
582                                         app_lookup, conn);
583
584                 if (app_lookup->state == STC_APP_STATE_FOREGROUND)
585                         stc_monitor_app_remove_accept(GUINT_TO_POINTER(classid),
586                                                 app_lookup, conn);
587         }
588
589         /* remove ristrictions if any */
590         stc_monitor_rstn_remove_for_app(classid);
591
592         if (STC_DEBUG_LOG && STC_STAT_LOG)
593                 __print_app(GUINT_TO_POINTER(classid), app_lookup, NULL);
594
595         /* remove app_key from the stc-manager */
596         g_hash_table_remove(apps, GUINT_TO_POINTER(classid));
597
598         return STC_ERROR_NONE;
599 }
600
601 void stc_monitor_app_remove_monitor(gpointer key,
602                                 gpointer value, gpointer data)
603 {
604         stc_app_value_s *app_value = (stc_app_value_s *)value;
605         stc_connection_s *connection = (stc_connection_s *)data;
606         stc_s *stc = stc_get_manager();
607
608         if (stc && connection && connection->ifname) {
609                 struct nfacct_rule counter;
610
611                 if (!stc->carg) {
612                         stc->carg = MALLOC0(counter_arg_s, 1);
613                         if (stc->carg == NULL)
614                                 return;
615
616                         stc->carg->sock = stc_monitor_get_contr_sock();
617                 }
618
619                 memset(&counter, 0, sizeof(struct nfacct_rule));
620
621                 counter.carg = stc->carg;
622                 counter.classid = app_value->classid;
623                 counter.app_state = app_value->state;
624                 counter.intend = NFACCT_COUNTER;
625
626                 if (g_str_has_suffix(app_value->app_id, STC_TETHERING_APP_SUFFIX) &&
627                                 app_value->classid != STC_TETHERING_APP_CLASSID) {
628                         __remove_app_monitor_for_tethering(key, value, data);
629                         return;
630                 } else if (connection->tether_state == FALSE &&
631                         connection->tether_iface.ifname != NULL &&
632                         app_value->classid == STC_TETHERING_APP_CLASSID) {
633                         counter.iftype = connection->tether_iface.type;
634                         g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
635                 } else {
636                         counter.iftype = connection->type;
637                         g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
638                 }
639
640                 if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
641                         stc_monitor_ipt_del_in(&counter);
642                         stc_monitor_ipt_del_out(&counter);
643                 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
644                         stc_monitor_ip6t_del_in(&counter);
645                         stc_monitor_ip6t_del_out(&counter);
646                 } else {
647                         stc_monitor_ipt_del_in(&counter);
648                         stc_monitor_ipt_del_out(&counter);
649                         stc_monitor_ip6t_del_in(&counter);
650                         stc_monitor_ip6t_del_out(&counter);
651                 }
652         }
653
654         return;
655 }
656
657 void stc_monitor_app_remove_by_connection(stc_connection_s *conn)
658 {
659         GHashTable *apps = stc_monitor_get_system_apps();
660
661         if (!apps)
662                 return;
663
664         g_hash_table_foreach(apps, stc_monitor_app_remove_monitor, conn);
665         g_hash_table_foreach(apps, stc_monitor_app_remove_accept, conn);
666 }
667
668 void stc_monitor_app_remove_accept(gpointer key,
669                                 gpointer value, gpointer data)
670 {
671         stc_app_value_s *app_value = (stc_app_value_s *)value;
672         stc_connection_s *connection = (stc_connection_s *)data;
673         stc_s *stc = stc_get_manager();
674
675         if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
676             app_value->classid == STC_TOTAL_WIFI_CLASSID ||
677             app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
678                 return;
679
680         if (app_value->state != STC_APP_STATE_FOREGROUND)
681                 return;
682
683         if (stc && connection && connection->ifname) {
684                 struct nfacct_rule counter;
685
686                 if (!stc->carg) {
687                         stc->carg = MALLOC0(counter_arg_s, 1);
688                         if (stc->carg == NULL)
689                                 return;
690
691                         stc->carg->sock = stc_monitor_get_contr_sock();
692                 }
693
694                 memset(&counter, 0, sizeof(struct nfacct_rule));
695
696                 counter.carg = stc->carg;
697                 counter.classid = app_value->classid;
698                 counter.app_state = app_value->state;
699                 counter.intend = NFACCT_ALLOW;
700
701                 counter.iftype = connection->type;
702                 g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
703
704                 if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
705                         stc_monitor_ipt_del_in(&counter);
706                         stc_monitor_ipt_del_out(&counter);
707                 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
708                         stc_monitor_ip6t_del_in(&counter);
709                         stc_monitor_ip6t_del_out(&counter);
710                 } else {
711                         stc_monitor_ipt_del_in(&counter);
712                         stc_monitor_ipt_del_out(&counter);
713                         stc_monitor_ip6t_del_in(&counter);
714                         stc_monitor_ip6t_del_out(&counter);
715                 }
716         }
717
718         return;
719 }
720
721 API gboolean stc_monitor_app_lookup(uint32_t classid)
722 {
723         stc_app_value_s *lookup_value;
724
725         GHashTable *apps = stc_monitor_get_system_apps();
726
727         if (!apps)
728                 return FALSE;
729
730         if (classid == STC_UNKNOWN_CLASSID)
731                 return FALSE;
732
733         lookup_value = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
734         if (lookup_value)
735                 return TRUE;
736
737         return FALSE;
738 }
739
740 GHashTable *stc_monitor_apps_init(void)
741 {
742         return g_hash_table_new_full(g_direct_hash, g_direct_equal,
743                                         NULL, __app_value_destroy);
744 }