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