Fix a coverity for 1142644
[platform/core/connectivity/stc-manager.git] / plugin / monitor / stc-plugin-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-plugin-monitor.h"
21 #include "stc-plugin-monitor-app.h"
22 #include "stc-plugin-monitor-rstn.h"
23 #include "stc-plugin-monitor-proc.h"
24 #include "stc-plugin-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 == TRUE) ? STC_ROAMING_ENABLE : STC_ROAMING_DISABLE;
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 API stc_error_e stc_plugin_monitor_app_add(uint32_t classid,
278                                 const char *app_id,
279                                 const char *pkg_id,
280                                 const stc_app_value_s value)
281 {
282         stc_app_value_s *app_value;
283         stc_app_value_s *lookup_value;
284
285         GHashTable *apps = stc_monitor_get_system_apps();
286         GSList *conn_list = stc_get_connection_list();
287
288         if (!apps)
289                 return STC_ERROR_NO_DATA;
290
291         if (classid == STC_UNKNOWN_CLASSID)
292                 classid = get_classid_by_app_id(app_id, TRUE);
293
294         lookup_value = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
295         if (lookup_value) {
296                 if (STC_STAT_LOG)
297                         STC_LOGE("Already exists [\033[1;36m%d\033[0;m:"
298                                                 "\033[0;32m%s\033[0;m]", classid, app_id);
299                 return STC_ERROR_NONE;
300         }
301
302         app_value = MALLOC0(stc_app_value_s, 1);
303         if (!app_value) {
304                 if (STC_STAT_LOG)
305                         STC_LOGE("Value allocation failed");
306                 return STC_ERROR_OUT_OF_MEMORY;
307         }
308
309         /* create cgroup and update classid */
310         app_value->classid = classid;
311
312         app_value->app_id = g_strdup(app_id);
313         app_value->pkg_id = g_strdup(pkg_id);
314
315         app_value->type = value.type;
316         app_value->state = value.state;
317         app_value->data_usage.in_bytes = value.data_usage.in_bytes;
318         app_value->data_usage.out_bytes = value.data_usage.out_bytes;
319         g_strlcpy(app_value->mac, value.mac, MAC_ADDRESS_LEN);
320
321         app_value->processes = g_hash_table_new_full(g_direct_hash,
322                                                                 g_direct_equal, NULL, NULL);
323
324         /* update classid for tethering station based on its mac address */
325         if (g_str_has_suffix(app_id, STC_TETHERING_APP_SUFFIX) &&
326                                 classid != STC_TETHERING_APP_CLASSID)
327                 stc_plugin_tether_set_station_classid(app_value->mac, classid);
328
329         g_hash_table_insert(apps, GUINT_TO_POINTER(classid), app_value);
330
331         for (; conn_list != NULL; conn_list = conn_list->next) {
332                 stc_connection_s *conn = conn_list->data;
333                 /* add nfacct rule for this classid */
334                 stc_monitor_app_add_monitor(GUINT_TO_POINTER(classid),
335                                         app_value, conn);
336
337                 if (app_value->state == STC_APP_STATE_FOREGROUND)
338                         stc_monitor_app_add_accept(GUINT_TO_POINTER(classid),
339                                         app_value, conn);
340         }
341
342         stc_monitor_rstn_add_for_app(classid);
343
344         if (STC_STAT_LOG) {
345                 __print_app(GUINT_TO_POINTER(classid), app_value, NULL);
346                 STC_LOGD("\033[1;32mApplication added\033[0;m "
347                         "[\033[1;36m%d\033[0;m]", classid);
348         }
349
350         return STC_ERROR_NONE;
351 }
352
353 API stc_error_e stc_plugin_monitor_app_remove(uint32_t classid,
354                                 const char *app_id)
355 {
356         stc_app_value_s *app_lookup;
357         GHashTable *apps = stc_monitor_get_system_apps();
358         GSList *conn_list = stc_get_connection_list();
359
360         if (!apps)
361                 return STC_ERROR_NO_DATA;
362
363         classid = get_classid_by_app_id(app_id, FALSE);
364
365         app_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
366         if (!app_lookup) {
367                 if (STC_STAT_LOG)
368                         STC_LOGD("Application not found [\033[1;36m%d\033[0;m]", classid);
369                 return STC_ERROR_FAIL;
370         }
371
372         for (; conn_list != NULL; conn_list = conn_list->next) {
373                 stc_connection_s *conn = conn_list->data;
374                 /* remove nfacct rule for this classid */
375                 stc_monitor_app_remove_monitor(GUINT_TO_POINTER(classid),
376                                         app_lookup, conn);
377
378                 if (app_lookup->state == STC_APP_STATE_FOREGROUND)
379                         stc_monitor_app_remove_accept(GUINT_TO_POINTER(classid),
380                                                 app_lookup, conn);
381         }
382
383         /* remove ristrictions if any */
384         stc_monitor_rstn_remove_for_app(classid);
385
386         if (STC_STAT_LOG)
387                 __print_app(GUINT_TO_POINTER(classid), app_lookup, NULL);
388
389         /* remove app_key from the stc-manager */
390         g_hash_table_remove(apps, GUINT_TO_POINTER(classid));
391
392         return STC_ERROR_NONE;
393 }
394
395 API gboolean stc_plugin_monitor_app_lookup(uint32_t classid)
396 {
397         stc_app_value_s *lookup_value;
398
399         GHashTable *apps = stc_monitor_get_system_apps();
400
401         if (!apps)
402                 return FALSE;
403
404         if (classid == STC_UNKNOWN_CLASSID)
405                 return FALSE;
406
407         lookup_value = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
408         if (lookup_value)
409                 return TRUE;
410
411         return FALSE;
412 }
413
414 void stc_monitor_app_update_counter(stc_app_value_s *value,
415                                  classid_bytes_context_s *context)
416 {
417         switch (context->counter->iotype) {
418         case NFACCT_COUNTER_IN:
419                 value->data_usage.in_bytes += context->bytes;
420                 value->counter.in_bytes = context->bytes;
421                 stc_monitor_set_apps_updated(TRUE);
422
423                 break;
424         case NFACCT_COUNTER_OUT:
425                 value->data_usage.out_bytes += context->bytes;
426                 value->counter.out_bytes = context->bytes;
427                 stc_monitor_set_apps_updated(TRUE);
428
429                 break;
430         default:
431                 STC_LOGE("Unknown iotype");
432         }
433 }
434
435 void stc_monitor_app_update_iface_counter(classid_bytes_context_s *context)
436 {
437         switch (context->counter->iftype) {
438         case STC_IFACE_DATACALL:
439                 __app_update_counter(context, STC_TOTAL_DATACALL_CLASSID);
440                 break;
441         case STC_IFACE_WIFI:
442                 __app_update_counter(context, STC_TOTAL_WIFI_CLASSID);
443                 __app_update_counter(context, STC_TETHERING_APP_CLASSID);
444                 break;
445         case STC_IFACE_BLUETOOTH:
446                 __app_update_counter(context, STC_TOTAL_BLUETOOTH_CLASSID);
447                 __app_update_counter(context, STC_TETHERING_APP_CLASSID);
448                 break;
449         case STC_IFACE_USB:
450                 __app_update_counter(context, STC_TETHERING_APP_CLASSID);
451                 break;
452         case STC_IFACE_P2P:
453                 __app_update_counter(context, STC_TETHERING_APP_CLASSID);
454                 break;
455         default:
456                 break;
457         }
458 }
459
460 gboolean stc_monitor_app_flush_stats_to_db(gpointer user_data)
461 {
462         time_t current_time = 0;
463         stc_s *stc = stc_get_manager();
464         GHashTable *apps = stc_monitor_get_system_apps();
465         gboolean apps_updated = stc_monitor_get_apps_updated();
466
467         if (stc && stc->carg)
468                 current_time = stc->carg->last_run_time;
469
470         if (apps_updated == FALSE)
471                 return G_SOURCE_REMOVE;
472
473         stc_monitor_set_apps_updated(FALSE);
474
475         if (apps)
476                 g_hash_table_foreach(apps,
477                                         __app_update_statistics,
478                                         &current_time);
479
480         STC_LOGI("Flushed app stats to database");
481         return G_SOURCE_REMOVE;
482 }
483
484 void stc_monitor_app_add_by_iface(const char *ifname)
485 {
486         stc_app_value_s app_value;
487
488         if (ifname == NULL)
489                 return;
490
491         memset(&app_value, 0, sizeof(stc_app_value_s));
492
493         app_value.type = STC_APP_TYPE_NONE;
494         app_value.processes = NULL;
495         app_value.counter.in_bytes = 0;
496         app_value.counter.out_bytes = 0;
497
498         stc_plugin_monitor_app_add(STC_UNKNOWN_CLASSID, ifname, ifname, app_value);
499 }
500
501 void stc_monitor_app_add_monitor(gpointer key,
502                                 gpointer value, gpointer data)
503 {
504         stc_app_value_s *app_value = (stc_app_value_s *)value;
505         stc_connection_s *connection = (stc_connection_s *)data;
506         stc_s *stc = stc_get_manager();
507
508         if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
509             app_value->classid == STC_TOTAL_WIFI_CLASSID ||
510             app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
511                 return;
512
513         if (stc && connection && connection->ifname) {
514                 struct nfacct_rule counter;
515
516                 if (!stc->carg) {
517                         stc->carg = MALLOC0(counter_arg_s, 1);
518                         if (stc->carg == NULL)
519                                 return;
520
521                         stc->carg->sock = stc_monitor_get_contr_sock();
522                 }
523
524                 memset(&counter, 0, sizeof(struct nfacct_rule));
525
526                 counter.carg = stc->carg;
527                 counter.classid = app_value->classid;
528                 counter.app_state = app_value->state;
529                 counter.intend = NFACCT_COUNTER;
530
531                 if (connection->tether_state == TRUE &&
532                         connection->tether_iface.ifname != NULL &&
533                         app_value->classid == STC_TETHERING_APP_CLASSID) {
534                         counter.iftype = connection->tether_iface.type;
535                         g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
536                 } else {
537                         counter.iftype = connection->type;
538                         g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
539                 }
540
541                 if (g_str_has_suffix(app_value->app_id, STC_TETHERING_APP_SUFFIX) &&
542                                 app_value->classid != STC_TETHERING_APP_CLASSID) {
543                         __add_app_monitor_for_tethering(key, value, data);
544                 } else if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
545                         stc_monitor_ipt_add_in(&counter);
546                         stc_monitor_ipt_add_out(&counter);
547                 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
548                         stc_monitor_ip6t_add_in(&counter);
549                         stc_monitor_ip6t_add_out(&counter);
550                 } else {
551                         stc_monitor_ipt_add_in(&counter);
552                         stc_monitor_ipt_add_out(&counter);
553                         stc_monitor_ip6t_add_in(&counter);
554                         stc_monitor_ip6t_add_out(&counter);
555                 }
556         }
557 }
558
559 typedef struct {
560         GSList *counter_v4_list;
561         GSList *counter_v6_list;
562         stc_connection_s *connection;
563         nfacct_rule_action action;
564         nfacct_rule_intend intend;
565 } counter_list_data;
566
567 static void __make_counter(stc_app_value_s *app_value,
568                 nfacct_rule_direction iotype, nfacct_rule_iptype iptype,
569                 counter_list_data *list_data)
570 {
571         stc_s *stc = stc_get_manager();
572         struct nfacct_rule *counter;
573
574         if (!stc || !list_data->connection || !list_data->connection->ifname)
575                 return;
576
577         if (!stc->carg) {
578                 stc->carg = MALLOC0(counter_arg_s, 1);
579                 if (stc->carg == NULL)
580                         return;
581
582                 stc->carg->sock = stc_monitor_get_contr_sock();
583         }
584
585         counter = MALLOC0(struct nfacct_rule, 1);
586         if (counter == NULL)
587                 return;
588
589         counter->carg = stc->carg;
590         counter->classid = app_value->classid;
591         counter->app_state = app_value->state;
592         counter->intend = list_data->intend;
593         counter->action = list_data->action;
594         counter->iotype = iotype;
595         counter->iftype = list_data->connection->type;
596         g_strlcpy(counter->ifname, list_data->connection->ifname, MAX_IFACE_LENGTH);
597         switch (counter->intend) {
598         case NFACCT_BLOCK:
599         case NFACCT_TETH_BLOCK:
600                 counter->jump = NFACCT_JUMP_REJECT;
601                 break;
602         case NFACCT_WARN:
603         case NFACCT_ALLOW:
604         case NFACCT_TETH_ALLOW:
605                 counter->jump = NFACCT_JUMP_ACCEPT;
606                 break;
607         default:
608                 counter->jump = NFACCT_JUMP_UNKNOWN;
609         }
610         counter->send_limit = 0;
611         counter->rcv_limit = 0;
612
613         if (iptype == NFACCT_TYPE_IPV4)
614                 list_data->counter_v4_list = g_slist_append(list_data->counter_v4_list, counter);
615         else
616                 list_data->counter_v6_list = g_slist_append(list_data->counter_v6_list, counter);
617 }
618
619 static void __make_counter_list(stc_app_value_s *app_value, counter_list_data *list_data)
620 {
621         switch (app_value->classid) {
622         case STC_TOTAL_IPV4_CLASSID:
623                 __make_counter(app_value, NFACCT_COUNTER_IN, NFACCT_TYPE_IPV4, list_data);
624                 __make_counter(app_value, NFACCT_COUNTER_OUT, NFACCT_TYPE_IPV4, list_data);
625                 break;
626         case STC_TOTAL_IPV6_CLASSID:
627                 __make_counter(app_value, NFACCT_COUNTER_IN, NFACCT_TYPE_IPV6, list_data);
628                 __make_counter(app_value, NFACCT_COUNTER_OUT, NFACCT_TYPE_IPV6, list_data);
629                 break;
630         default:
631                 __make_counter(app_value, NFACCT_COUNTER_IN, NFACCT_TYPE_IPV4, list_data);
632                 __make_counter(app_value, NFACCT_COUNTER_OUT, NFACCT_TYPE_IPV4, list_data);
633                 __make_counter(app_value, NFACCT_COUNTER_IN, NFACCT_TYPE_IPV6, list_data);
634                 __make_counter(app_value, NFACCT_COUNTER_OUT, NFACCT_TYPE_IPV6, list_data);
635         }
636 }
637
638 static void __foreach_app_table(gpointer key, gpointer value, gpointer data)
639 {
640         stc_app_value_s *app_value = (stc_app_value_s *)value;
641         counter_list_data *list_data = (counter_list_data *)data;
642
643         if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
644             app_value->classid == STC_TOTAL_WIFI_CLASSID ||
645             app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
646                 return;
647
648         list_data->intend = NFACCT_COUNTER;
649         __make_counter_list(app_value, list_data);
650
651         if (app_value->state == STC_APP_STATE_FOREGROUND) {
652                 list_data->intend = NFACCT_ALLOW;
653                 __make_counter_list(app_value, list_data);
654         }
655 }
656
657 void stc_monitor_app_add_by_connection(stc_connection_s *conn)
658 {
659         GHashTable *apps = stc_monitor_get_system_apps();
660         counter_list_data list_data = { 0, };
661         struct timespec start, end;
662         time_t sec;
663         long int nsec;
664
665         if (!apps)
666                 return;
667
668         list_data.connection = conn;
669         list_data.action = NFACCT_ACTION_INSERT;
670
671         g_hash_table_foreach(apps, __foreach_app_table, &list_data);
672
673         clock_gettime(CLOCK_MONOTONIC, &start);
674
675         stc_monitor_ipt_add_list(list_data.counter_v4_list, NFACCT_TYPE_IPV4);
676         stc_monitor_ipt_add_list(list_data.counter_v6_list, NFACCT_TYPE_IPV6);
677
678         g_slist_free_full(list_data.counter_v4_list, g_free);
679         g_slist_free_full(list_data.counter_v6_list, g_free);
680
681         clock_gettime(CLOCK_MONOTONIC, &end);
682
683         sec = end.tv_sec - start.tv_sec;
684         nsec = end.tv_nsec - start.tv_nsec;
685         if (nsec < 0)
686                 nsec += 1000000000;
687         STC_LOGD("Added by [%s] connection [%3ld.%09ld]s", conn->ifname, sec, nsec);
688 }
689
690 void stc_monitor_app_add_accept(gpointer key,
691                                 gpointer value, gpointer data)
692 {
693         stc_app_value_s *app_value = (stc_app_value_s *)value;
694         stc_connection_s *connection = (stc_connection_s *)data;
695         stc_s *stc = stc_get_manager();
696
697         if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
698             app_value->classid == STC_TOTAL_WIFI_CLASSID ||
699             app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
700                 return;
701
702         if (app_value->state != STC_APP_STATE_FOREGROUND)
703                 return;
704
705         if (stc && connection && connection->ifname) {
706                 struct nfacct_rule counter;
707
708                 if (!stc->carg) {
709                         stc->carg = MALLOC0(counter_arg_s, 1);
710                         if (stc->carg == NULL)
711                                 return;
712
713                         stc->carg->sock = stc_monitor_get_contr_sock();
714                 }
715
716                 memset(&counter, 0, sizeof(struct nfacct_rule));
717
718                 counter.carg = stc->carg;
719                 counter.classid = app_value->classid;
720                 counter.app_state = app_value->state;
721                 counter.intend = NFACCT_ALLOW;
722
723                 counter.iftype = connection->type;
724                 g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
725
726                 if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
727                         stc_monitor_ipt_add_in(&counter);
728                         stc_monitor_ipt_add_out(&counter);
729                 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
730                         stc_monitor_ip6t_add_in(&counter);
731                         stc_monitor_ip6t_add_out(&counter);
732                 } else {
733                         stc_monitor_ipt_add_in(&counter);
734                         stc_monitor_ipt_add_out(&counter);
735                         stc_monitor_ip6t_add_in(&counter);
736                         stc_monitor_ip6t_add_out(&counter);
737                 }
738         }
739 }
740
741 void stc_monitor_app_remove_monitor(gpointer key,
742                                 gpointer value, gpointer data)
743 {
744         stc_app_value_s *app_value = (stc_app_value_s *)value;
745         stc_connection_s *connection = (stc_connection_s *)data;
746         stc_s *stc = stc_get_manager();
747
748         if (stc && connection && connection->ifname) {
749                 struct nfacct_rule counter;
750
751                 if (!stc->carg) {
752                         stc->carg = MALLOC0(counter_arg_s, 1);
753                         if (stc->carg == NULL)
754                                 return;
755
756                         stc->carg->sock = stc_monitor_get_contr_sock();
757                 }
758
759                 memset(&counter, 0, sizeof(struct nfacct_rule));
760
761                 counter.carg = stc->carg;
762                 counter.classid = app_value->classid;
763                 counter.app_state = app_value->state;
764                 counter.intend = NFACCT_COUNTER;
765
766                 if (g_str_has_suffix(app_value->app_id, STC_TETHERING_APP_SUFFIX) &&
767                                 app_value->classid != STC_TETHERING_APP_CLASSID) {
768                         __remove_app_monitor_for_tethering(key, value, data);
769                         return;
770                 } else if (connection->tether_state == FALSE &&
771                         connection->tether_iface.ifname != NULL &&
772                         app_value->classid == STC_TETHERING_APP_CLASSID) {
773                         counter.iftype = connection->tether_iface.type;
774                         g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
775                 } else {
776                         counter.iftype = connection->type;
777                         g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
778                 }
779
780                 if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
781                         stc_monitor_ipt_del_in(&counter);
782                         stc_monitor_ipt_del_out(&counter);
783                 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
784                         stc_monitor_ip6t_del_in(&counter);
785                         stc_monitor_ip6t_del_out(&counter);
786                 } else {
787                         stc_monitor_ipt_del_in(&counter);
788                         stc_monitor_ipt_del_out(&counter);
789                         stc_monitor_ip6t_del_in(&counter);
790                         stc_monitor_ip6t_del_out(&counter);
791                 }
792         }
793
794         return;
795 }
796
797 void stc_monitor_app_remove_by_connection(stc_connection_s *conn)
798 {
799         GHashTable *apps = stc_monitor_get_system_apps();
800         counter_list_data list_data = { 0, };
801         struct timespec start, end;
802         time_t sec;
803         long int nsec;
804
805         if (!apps)
806                 return;
807
808         list_data.connection = conn;
809         list_data.action = NFACCT_ACTION_DELETE;
810
811         g_hash_table_foreach(apps, __foreach_app_table, &list_data);
812
813         clock_gettime(CLOCK_MONOTONIC, &start);
814
815         stc_monitor_ipt_del_list(list_data.counter_v4_list, NFACCT_TYPE_IPV4);
816         stc_monitor_ipt_del_list(list_data.counter_v6_list, NFACCT_TYPE_IPV6);
817
818         g_slist_free_full(list_data.counter_v4_list, g_free);
819         g_slist_free_full(list_data.counter_v6_list, g_free);
820
821         clock_gettime(CLOCK_MONOTONIC, &end);
822
823         sec = end.tv_sec - start.tv_sec;
824         nsec = end.tv_nsec - start.tv_nsec;
825         if (nsec < 0)
826                 nsec += 1000000000;
827         STC_LOGD("Removed by [%s] connection [%3ld.%09ld]s", conn->ifname, sec, nsec);
828 }
829
830 void stc_monitor_app_remove_accept(gpointer key,
831                                 gpointer value, gpointer data)
832 {
833         stc_app_value_s *app_value = (stc_app_value_s *)value;
834         stc_connection_s *connection = (stc_connection_s *)data;
835         stc_s *stc = stc_get_manager();
836
837         if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
838             app_value->classid == STC_TOTAL_WIFI_CLASSID ||
839             app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
840                 return;
841
842         if (app_value->state != STC_APP_STATE_FOREGROUND)
843                 return;
844
845         if (stc && connection && connection->ifname) {
846                 struct nfacct_rule counter;
847
848                 if (!stc->carg) {
849                         stc->carg = MALLOC0(counter_arg_s, 1);
850                         if (stc->carg == NULL)
851                                 return;
852
853                         stc->carg->sock = stc_monitor_get_contr_sock();
854                 }
855
856                 memset(&counter, 0, sizeof(struct nfacct_rule));
857
858                 counter.carg = stc->carg;
859                 counter.classid = app_value->classid;
860                 counter.app_state = app_value->state;
861                 counter.intend = NFACCT_ALLOW;
862
863                 counter.iftype = connection->type;
864                 g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
865
866                 if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
867                         stc_monitor_ipt_del_in(&counter);
868                         stc_monitor_ipt_del_out(&counter);
869                 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
870                         stc_monitor_ip6t_del_in(&counter);
871                         stc_monitor_ip6t_del_out(&counter);
872                 } else {
873                         stc_monitor_ipt_del_in(&counter);
874                         stc_monitor_ipt_del_out(&counter);
875                         stc_monitor_ip6t_del_in(&counter);
876                         stc_monitor_ip6t_del_out(&counter);
877                 }
878         }
879
880         return;
881 }
882
883 GHashTable *stc_monitor_apps_init(void)
884 {
885         return g_hash_table_new_full(g_direct_hash, g_direct_equal,
886                                         NULL, __app_value_destroy);
887 }