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