2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <linux/netlink.h>
19 #include <vconf-keys.h>
21 #include "stc-default-connection.h"
22 #include "helper-nl.h"
23 #include "helper-nfacct-rule.h"
24 #include "helper-net-cls.h"
25 #include "helper-cgroup.h"
26 #include "helper-iptables.h"
28 #include "table-statistics.h"
29 #include "table-counters.h"
30 #include "stc-monitor.h"
32 #include "stc-manager-plugin-appstatus.h"
33 #include "stc-manager-plugin-exception.h"
35 #define GRANULARITY 10
36 #define MAX_INT_LENGTH 128
38 #ifndef VCONFKEY_STC_BACKGROUND_STATE
39 #define VCONFKEY_STC_BACKGROUND_STATE "db/stc/background_state"
42 #ifndef VCONFKEY_SETAPPL_DATA_RESTRICTION_INT
43 #define VCONFKEY_SETAPPL_DATA_RESTRICTION_INT "db/setting/data_restriction"
48 time_t month_start_ts;
52 } reset_time_limits_context_s;
55 stc_app_key_s *app_key;
56 stc_process_key_s *proc_key;
57 gboolean entry_removed;
58 } remove_pid_context_s;
61 struct nfacct_rule *counter;
63 gboolean data_limit_exceeded;
64 } classid_bytes_context_s;
66 static stc_system_s *g_system = NULL;
69 static int __vconf_get_int(const char *key, int *value)
73 ret = vconf_get_int(key, value);
74 if (ret != VCONF_OK) {
75 STC_LOGE("Failed to get vconfkey [%s] value", key); //LCOV_EXCL_LINE
76 return -1; //LCOV_EXCL_LINE
82 static int __vconf_set_int(const char *key, int value)
86 ret = vconf_set_int(key, value);
87 if (ret != VCONF_OK) {
88 STC_LOGE("Failed to set vconfkey [%s] value", key); //LCOV_EXCL_LINE
89 return -1; //LCOV_EXCL_LINE
96 static nfacct_rule_jump __get_jump_by_intend(struct nfacct_rule *counter)
98 if (counter->intend == NFACCT_WARN)
99 return NFACCT_JUMP_ACCEPT;
100 else if (counter->intend == NFACCT_BLOCK)
101 return NFACCT_JUMP_REJECT;
102 else if (counter->intend == NFACCT_ALLOW)
103 return NFACCT_JUMP_ACCEPT;
105 return NFACCT_JUMP_UNKNOWN;
108 static stc_error_e __add_iptables_tether_in(struct nfacct_rule *counter,
113 if (counter == NULL || ipaddr == NULL)
114 return STC_ERROR_INVALID_PARAMETER;
116 counter->action = NFACCT_ACTION_INSERT;
117 counter->iotype = NFACCT_COUNTER_IN;
118 counter->jump = __get_jump_by_intend(counter);
119 counter->iptype = NFACCT_TYPE_IPV4;
120 counter->send_limit = 0;
121 counter->rcv_limit = 0;
122 counter->src_iprange_type = NFACCT_IPRANGE_TYPE_SINGLE;
123 counter->src_ip1 = g_strdup(ipaddr);
125 ret = produce_net_rule(counter);
127 g_free(counter->src_ip1);
128 counter->src_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
132 static stc_error_e __add_iptables_tether_out(struct nfacct_rule *counter,
137 if (counter == NULL || ipaddr == NULL)
138 return STC_ERROR_INVALID_PARAMETER;
140 counter->action = NFACCT_ACTION_INSERT;
141 counter->iotype = NFACCT_COUNTER_OUT;
142 counter->jump = __get_jump_by_intend(counter);
143 counter->iptype = NFACCT_TYPE_IPV4;
144 counter->send_limit = 0;
145 counter->rcv_limit = 0;
146 counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_SINGLE;
147 counter->dst_ip1 = g_strdup(ipaddr);
149 ret = produce_net_rule(counter);
151 g_free(counter->dst_ip1);
152 counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
156 static stc_error_e __del_iptables_tether_in(struct nfacct_rule *counter,
161 if (counter == NULL || ipaddr == NULL)
162 return STC_ERROR_INVALID_PARAMETER;
164 counter->action = NFACCT_ACTION_DELETE;
165 counter->iotype = NFACCT_COUNTER_IN;
166 counter->jump = __get_jump_by_intend(counter);
167 counter->iptype = NFACCT_TYPE_IPV4;
168 counter->send_limit = 0;
169 counter->rcv_limit = 0;
170 counter->src_iprange_type = NFACCT_IPRANGE_TYPE_SINGLE;
171 counter->src_ip1 = g_strdup(ipaddr);
173 ret = produce_net_rule(counter);
175 g_free(counter->src_ip1);
176 counter->src_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
180 static stc_error_e __del_iptables_tether_out(struct nfacct_rule *counter,
185 if (counter == NULL || ipaddr == NULL)
186 return STC_ERROR_INVALID_PARAMETER;
188 counter->action = NFACCT_ACTION_DELETE;
189 counter->iotype = NFACCT_COUNTER_OUT;
190 counter->jump = __get_jump_by_intend(counter);
191 counter->iptype = NFACCT_TYPE_IPV4;
192 counter->send_limit = 0;
193 counter->rcv_limit = 0;
194 counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_SINGLE;
195 counter->dst_ip1 = g_strdup(ipaddr);
197 ret = produce_net_rule(counter);
199 g_free(counter->dst_ip1);
200 counter->dst_iprange_type = NFACCT_IPRANGE_TYPE_NONE;
204 static stc_error_e __add_iptables_in(struct nfacct_rule *counter)
207 return STC_ERROR_INVALID_PARAMETER;
209 counter->action = NFACCT_ACTION_INSERT;
210 counter->iotype = NFACCT_COUNTER_IN;
211 counter->jump = __get_jump_by_intend(counter);
212 counter->iptype = NFACCT_TYPE_IPV4;
213 counter->send_limit = 0;
214 counter->rcv_limit = 0;
216 return produce_net_rule(counter);
219 static stc_error_e __add_iptables_out(struct nfacct_rule *counter)
222 return STC_ERROR_INVALID_PARAMETER;
224 counter->action = NFACCT_ACTION_INSERT;
225 counter->iotype = NFACCT_COUNTER_OUT;
226 counter->jump = __get_jump_by_intend(counter);
227 counter->iptype = NFACCT_TYPE_IPV4;
228 counter->send_limit = 0;
229 counter->rcv_limit = 0;
231 return produce_net_rule(counter);
234 static stc_error_e __del_iptables_in(struct nfacct_rule *counter)
237 return STC_ERROR_INVALID_PARAMETER;
239 counter->action = NFACCT_ACTION_DELETE;
240 counter->iotype = NFACCT_COUNTER_IN;
241 counter->jump = __get_jump_by_intend(counter);
242 counter->iptype = NFACCT_TYPE_IPV4;
243 counter->send_limit = 0;
244 counter->rcv_limit = 0;
246 return produce_net_rule(counter);
249 static stc_error_e __del_iptables_out(struct nfacct_rule *counter)
252 return STC_ERROR_INVALID_PARAMETER;
254 counter->action = NFACCT_ACTION_DELETE;
255 counter->iotype = NFACCT_COUNTER_OUT;
256 counter->jump = __get_jump_by_intend(counter);
257 counter->iptype = NFACCT_TYPE_IPV4;
258 counter->send_limit = 0;
259 counter->rcv_limit = 0;
261 return produce_net_rule(counter);
264 static stc_error_e __add_ip6tables_in(struct nfacct_rule *counter)
267 return STC_ERROR_INVALID_PARAMETER;
269 counter->action = NFACCT_ACTION_INSERT;
270 counter->iotype = NFACCT_COUNTER_IN;
271 counter->jump = __get_jump_by_intend(counter);
272 counter->iptype = NFACCT_TYPE_IPV6;
273 counter->send_limit = 0;
274 counter->rcv_limit = 0;
276 return produce_net_rule(counter);
279 static stc_error_e __add_ip6tables_out(struct nfacct_rule *counter)
282 return STC_ERROR_INVALID_PARAMETER;
284 counter->action = NFACCT_ACTION_INSERT;
285 counter->iotype = NFACCT_COUNTER_OUT;
286 counter->jump = __get_jump_by_intend(counter);
287 counter->iptype = NFACCT_TYPE_IPV6;
288 counter->send_limit = 0;
289 counter->rcv_limit = 0;
291 return produce_net_rule(counter);
294 static stc_error_e __del_ip6tables_in(struct nfacct_rule *counter)
297 return STC_ERROR_INVALID_PARAMETER;
299 counter->action = NFACCT_ACTION_DELETE;
300 counter->iotype = NFACCT_COUNTER_IN;
301 counter->jump = __get_jump_by_intend(counter);
302 counter->iptype = NFACCT_TYPE_IPV6;
303 counter->send_limit = 0;
304 counter->rcv_limit = 0;
306 return produce_net_rule(counter);
309 static stc_error_e __del_ip6tables_out(struct nfacct_rule *counter)
312 return STC_ERROR_INVALID_PARAMETER;
314 counter->action = NFACCT_ACTION_DELETE;
315 counter->iotype = NFACCT_COUNTER_OUT;
316 counter->jump = __get_jump_by_intend(counter);
317 counter->iptype = NFACCT_TYPE_IPV6;
318 counter->send_limit = 0;
319 counter->rcv_limit = 0;
321 return produce_net_rule(counter);
324 static int __processes_tree_key_compare(gconstpointer a, gconstpointer b,
325 gpointer UNUSED user_data)
327 stc_process_key_s *key_a = (stc_process_key_s *)a;
328 stc_process_key_s *key_b = (stc_process_key_s *)b;
330 return key_a->pid - key_b->pid;
333 static void __processes_tree_value_free(gpointer data)
335 stc_process_value_s *value = (stc_process_value_s *)data;
340 static void __processes_tree_key_free(gpointer data)
342 stc_process_key_s *key = (stc_process_key_s *)data;
347 static int __apps_tree_key_compare(gconstpointer a, gconstpointer b,
348 gpointer UNUSED user_data)
350 stc_app_key_s *key_a = (stc_app_key_s *)a;
351 stc_app_key_s *key_b = (stc_app_key_s *)b;
354 ret = g_strcmp0(key_a->pkg_id, key_b->pkg_id);
358 return g_strcmp0(key_a->app_id, key_b->app_id);
361 static void __apps_tree_value_free(gpointer data)
363 stc_app_value_s *value = (stc_app_value_s *)data;
365 g_tree_destroy(value->processes);
366 value->processes = NULL;
371 static void __apps_tree_key_free(gpointer data)
373 stc_app_key_s *key = (stc_app_key_s *)data;
380 static int __rstns_tree_key_compare(gconstpointer a, gconstpointer b,
381 gpointer UNUSED user_data)
383 stc_rstn_key_s *key_a = (stc_rstn_key_s *)a;
384 stc_rstn_key_s *key_b = (stc_rstn_key_s *)b;
387 ret = g_strcmp0(key_a->app_id, key_b->app_id);
391 ret = g_strcmp0(key_a->ifname, key_b->ifname);
395 ret = g_strcmp0(key_a->subscriber_id, key_b->subscriber_id);
399 ret = key_a->iftype - key_b->iftype;
403 ret = key_a->roaming - key_b->roaming;
410 static void __rstns_tree_value_free(gpointer data)
412 stc_rstn_value_s *value = (stc_rstn_value_s *)data;
417 static void __rstns_tree_key_free(gpointer data)
419 stc_rstn_key_s *key = (stc_rstn_key_s *)data;
423 FREE(key->subscriber_id);
429 static gboolean __processes_tree_foreach_print(gpointer key, gpointer value,
432 stc_process_key_s *proc_key = (stc_process_key_s *)key;
433 stc_process_value_s *proc_value = (stc_process_value_s *)value;
435 STC_LOGD("Process entry => PID [\033[1;33m%d\033[0;m], Ground state [%d]",
436 proc_key->pid, proc_value->ground);
440 static void __processes_tree_printall(GTree *processes)
442 g_tree_foreach(processes, __processes_tree_foreach_print, NULL);
445 static gboolean __apps_tree_foreach_print(gpointer key, gpointer value,
448 stc_app_key_s *app_key = (stc_app_key_s *)key;
449 stc_app_value_s *app_value = (stc_app_value_s *)value;
451 STC_LOGD("Application info => Pkg ID [\033[0;34m%s\033[0;m], "
452 "App ID [\033[0;32m%s\033[0;m], Type [%d], classid [%d],"
453 " counter [ in (%lld), out (%lld)]",
454 app_key->pkg_id, app_key->app_id,
455 app_value->type, app_value->classid,
456 app_value->data_usage.in_bytes, app_value->data_usage.out_bytes);
458 __processes_tree_printall(app_value->processes);
462 static void __apps_tree_printall(void)
464 g_tree_foreach(g_system->apps, __apps_tree_foreach_print, NULL);
469 static gboolean __apps_tree_foreach_remove_pid(gpointer key, gpointer value,
472 remove_pid_context_s *context = (remove_pid_context_s *)data;
473 stc_app_value_s *app_value = (stc_app_value_s *)value;
475 if (!g_tree_remove(app_value->processes, context->proc_key))
478 context->entry_removed = TRUE;
479 context->app_key = (stc_app_key_s *)key;
484 static stc_app_value_s * __application_lookup(GTree *apps,
485 const stc_app_key_s *key)
487 stc_app_value_s *lookup;
489 ret_value_msg_if(apps == NULL, NULL, "apps is null!");
491 lookup = g_tree_lookup(apps, key);
496 static stc_process_value_s * __process_lookup(GTree *processes,
497 const stc_process_key_s *key)
499 stc_process_value_s *lookup;
501 ret_value_msg_if(processes == NULL, NULL, "processes is null!");
503 lookup = g_tree_lookup(processes, key);
509 static gboolean __processes_tree_check_empty(gpointer key, gpointer value,
512 guint *pid_count = (guint *)data;
518 static gboolean __add_application_monitor_for_tethering(gpointer key, gpointer value,
521 stc_app_value_s *app_value = (stc_app_value_s *)value;
522 stc_app_key_s *app_key = (stc_app_key_s *)key;
523 default_connection_s *connection = (default_connection_s *)data;
524 stc_s *stc = stc_get_manager();
525 struct nfacct_rule counter;
527 STC_LOGI("add tether app (%s)", app_key->app_id);
529 if (stc == NULL || connection == NULL)
533 stc->carg = MALLOC0(counter_arg_s, 1);
534 if (stc->carg == NULL)
537 stc->carg->sock = stc_monitor_get_counter_socket();
540 memset(&counter, 0, sizeof(struct nfacct_rule));
542 counter.carg = stc->carg;
543 counter.classid = app_value->classid;
544 counter.intend = NFACCT_TETH_COUNTER;
546 if (connection->tether_state != TRUE ||
547 connection->tether_iface.ifname == NULL)
550 counter.iftype = connection->tether_iface.type;
551 g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
553 __add_iptables_tether_in(&counter, app_value->ipaddr);
554 __add_iptables_tether_out(&counter, app_value->ipaddr);
559 static gboolean __remove_application_monitor_for_tethering(gpointer key, gpointer value,
562 stc_app_value_s *app_value = (stc_app_value_s *)value;
563 stc_app_key_s *app_key = (stc_app_key_s *)key;
564 default_connection_s *connection = (default_connection_s *)data;
565 stc_s *stc = stc_get_manager();
566 struct nfacct_rule counter;
568 STC_LOGI("remove tether app (%s)", app_key->app_id);
570 if (stc == NULL || connection == NULL)
574 stc->carg = MALLOC0(counter_arg_s, 1);
575 if (stc->carg == NULL)
578 stc->carg->sock = stc_monitor_get_counter_socket();
581 memset(&counter, 0, sizeof(struct nfacct_rule));
583 counter.carg = stc->carg;
584 counter.classid = app_value->classid;
585 counter.intend = NFACCT_TETH_COUNTER;
587 if (connection->tether_state != TRUE ||
588 connection->tether_iface.ifname == NULL)
591 counter.iftype = connection->tether_iface.type;
592 g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
594 __del_iptables_tether_in(&counter, app_value->ipaddr);
595 __del_iptables_tether_out(&counter, app_value->ipaddr);
600 static gboolean __add_application_monitor(gpointer key, gpointer value,
603 stc_app_value_s *app_value = (stc_app_value_s *)value;
604 stc_app_key_s *app_key = (stc_app_key_s *)key;
605 default_connection_s *connection = (default_connection_s *)data;
606 stc_s *stc = stc_get_manager();
608 if (app_value->classid == STC_TOTAL_DATACALL_CLASSID ||
609 app_value->classid == STC_TOTAL_WIFI_CLASSID ||
610 app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID)
613 if (stc && connection && connection->ifname) {
614 struct nfacct_rule counter;
617 stc->carg = MALLOC0(counter_arg_s, 1); //LCOV_EXCL_LINE
618 if (stc->carg == NULL) //LCOV_EXCL_LINE
619 return FALSE; //LCOV_EXCL_LINE
621 stc->carg->sock = stc_monitor_get_counter_socket(); //LCOV_EXCL_LINE
624 memset(&counter, 0, sizeof(struct nfacct_rule));
626 counter.carg = stc->carg;
627 counter.classid = app_value->classid;
628 counter.intend = NFACCT_COUNTER;
630 if (connection->tether_state == TRUE &&
631 connection->tether_iface.ifname != NULL &&
632 app_value->classid == STC_TETHERING_APP_CLASSID) {
633 counter.iftype = connection->tether_iface.type;
634 g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
636 counter.iftype = connection->type;
637 g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
640 if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX) &&
641 app_value->classid != STC_TETHERING_APP_CLASSID) {
642 __add_application_monitor_for_tethering(key, value, data);
643 } else if (app_value->classid == STC_TOTAL_IPV4_CLASSID) {
644 __add_iptables_in(&counter);
645 __add_iptables_out(&counter);
646 } else if (app_value->classid == STC_TOTAL_IPV6_CLASSID) {
647 __add_ip6tables_in(&counter);
648 __add_ip6tables_out(&counter);
650 __add_iptables_in(&counter);
651 __add_iptables_out(&counter);
652 __add_ip6tables_in(&counter);
653 __add_ip6tables_out(&counter);
660 static gboolean __remove_application_monitor(gpointer key, gpointer value,
663 stc_app_value_s *app_value = (stc_app_value_s *)value;
664 stc_app_key_s *app_key = (stc_app_key_s *)key;
665 default_connection_s *connection = (default_connection_s *)data;
666 stc_s *stc = stc_get_manager();
668 if (stc && connection && connection->ifname) {
669 struct nfacct_rule counter;
672 stc->carg = MALLOC0(counter_arg_s, 1); //LCOV_EXCL_LINE
673 if (stc->carg == NULL) //LCOV_EXCL_LINE
674 return FALSE; //LCOV_EXCL_LINE
676 stc->carg->sock = stc_monitor_get_counter_socket(); //LCOV_EXCL_LINE
679 memset(&counter, 0, sizeof(struct nfacct_rule));
681 counter.carg = stc->carg;
682 counter.classid = app_value->classid;
683 counter.intend = NFACCT_COUNTER;
685 if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX) &&
686 app_value->classid != STC_TETHERING_APP_CLASSID) {
687 __remove_application_monitor_for_tethering(key, value, data);
689 } else if (connection->tether_state == FALSE &&
690 connection->tether_iface.ifname != NULL &&
691 app_value->classid == STC_TETHERING_APP_CLASSID) {
692 counter.iftype = connection->tether_iface.type;
693 g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
695 counter.iftype = connection->type;
696 g_strlcpy(counter.ifname, connection->ifname, MAX_IFACE_LENGTH);
699 __del_iptables_in(&counter);
700 __del_iptables_out(&counter);
701 __del_ip6tables_in(&counter);
702 __del_ip6tables_out(&counter);
708 static void __print_rstn(stc_rstn_key_s *rstn_key, stc_rstn_value_s *rstn_value)
710 STC_LOGI("rstn info => rstn_id [%llu], "
711 "app_id [%s], classid [%u], ifname [%s], "
712 "iftype [%d], rstn_state [%d], rstn_type [%d], "
713 "month_start_date [%d], limit [ (%lld) bytes], "
714 "warn_limit [ (%lld) bytes], "
715 "monthly_limit [ (%lld) bytes], "
716 "weekly_limit [ (%lld) bytes], "
717 "daily_limit [ (%lld) bytes], "
718 "data_counter [ (%lld) bytes], "
719 "warn_counter [ (%lld) bytes], "
720 "monthly_counter [ (%lld) bytes], "
721 "weekly_counter [ (%lld) bytes], "
722 "daily_counter [ (%lld) bytes], "
723 "roaming [%d], subscriber_id [%s]",
724 rstn_value->restriction_id,
725 rstn_key->app_id, rstn_value->classid , rstn_key->ifname,
726 rstn_key->iftype, rstn_value->rstn_state, rstn_value->rstn_type,
727 rstn_value->month_start_date,
728 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA],
729 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN],
730 rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY],
731 rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY],
732 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY],
733 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA],
734 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN],
735 rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY],
736 rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY],
737 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY],
738 rstn_key->roaming, rstn_key->subscriber_id);
741 static void __add_iptables_rule(int64_t classid, nfacct_rule_intend intend,
742 stc_iface_type_e iftype)
744 char *default_ifname = stc_default_connection_get_ifname();
745 default_connection_s *connection = stc_get_default_connection();
746 struct nfacct_rule counter;
747 stc_s *stc = stc_get_manager();
749 g_free(default_ifname); //LCOV_EXCL_LINE
750 return; //LCOV_EXCL_LINE
754 stc->carg = MALLOC0(counter_arg_s, 1); //LCOV_EXCL_LINE
755 if (stc->carg == NULL) { //LCOV_EXCL_LINE
756 g_free(default_ifname); //LCOV_EXCL_LINE
757 return; //LCOV_EXCL_LINE
760 stc->carg->sock = stc_monitor_get_counter_socket(); //LCOV_EXCL_LINE
763 counter.carg = stc->carg;
764 counter.classid = classid;
765 counter.intend = intend;
767 if (connection && connection->tether_iface.ifname != NULL &&
768 classid == STC_TETHERING_APP_CLASSID) {
769 counter.iftype = connection->tether_iface.type;
770 g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
772 counter.iftype = iftype;
773 g_strlcpy(counter.ifname, default_ifname, MAX_IFACE_LENGTH);
776 g_free(default_ifname);
779 __add_iptables_in(&counter);
780 __add_iptables_out(&counter);
783 __add_ip6tables_in(&counter);
784 __add_ip6tables_out(&counter);
787 static void __del_iptables_rule(int64_t classid, nfacct_rule_intend intend,
788 stc_iface_type_e iftype)
790 char *default_ifname = stc_default_connection_get_ifname();
791 default_connection_s *connection = stc_get_default_connection();
792 struct nfacct_rule counter;
793 stc_s *stc = stc_get_manager();
795 g_free(default_ifname); //LCOV_EXCL_LINE
796 return; //LCOV_EXCL_LINE
800 stc->carg = MALLOC0(counter_arg_s, 1); //LCOV_EXCL_LINE
801 if (stc->carg == NULL) { //LCOV_EXCL_LINE
802 g_free(default_ifname); //LCOV_EXCL_LINE
803 return; //LCOV_EXCL_LINE
806 stc->carg->sock = stc_monitor_get_counter_socket(); //LCOV_EXCL_LINE
809 counter.carg = stc->carg;
810 counter.classid = classid;
811 counter.intend = intend;
813 if (connection && connection->tether_iface.ifname != NULL &&
814 classid == STC_TETHERING_APP_CLASSID) {
815 counter.iftype = connection->tether_iface.type;
816 g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
818 counter.iftype = iftype;
819 g_strlcpy(counter.ifname, default_ifname, MAX_IFACE_LENGTH);
822 g_free(default_ifname);
825 __del_iptables_in(&counter);
826 __del_iptables_out(&counter);
829 __del_ip6tables_in(&counter);
830 __del_ip6tables_out(&counter);
833 static void __set_rstn_noti_state(int value)
835 int state = STC_RSTN_STATE_INIT;
837 if (__vconf_get_int(VCONFKEY_SETAPPL_DATA_RESTRICTION_INT, &state))
840 if (state == value) {
841 STC_LOGI("No need to change a restriction status: %d", state);
845 vconf_set_int(VCONFKEY_SETAPPL_DATA_RESTRICTION_INT, value);
850 time_t month_start_ts;
851 time_t week_start_ts;
853 int64_t monthly_stat;
858 static stc_cb_ret_e __statistics_info_cb(const table_statistics_info *info,
861 cumulative_data_s *stat = (cumulative_data_s *)user_data;
862 int64_t counters = 0;
864 counters = info->cnt.in_bytes + info->cnt.out_bytes;
866 stat->monthly_stat += counters;
867 if (stat->week_start_ts <= info->interval->from)
868 stat->weekly_stat += counters;
869 if (stat->day_start_ts <= info->interval->from)
870 stat->daily_stat += counters;
875 static void __process_restriction(enum traffic_restriction_type rstn_type,
876 stc_rstn_key_s *rstn_key,
877 stc_rstn_value_s *rstn_value, void *data)
879 default_connection_s *old_connection = (default_connection_s *)data;
880 default_connection_s *connection = NULL;
882 if (old_connection != NULL)
883 connection = old_connection;
885 connection = stc_get_default_connection();
887 /* no default ifname */
888 if (connection->ifname == NULL)
891 /* rstn not applicable for this interface */
892 if (rstn_key->ifname != NULL && g_strcmp0("", rstn_key->ifname) != 0 &&
893 (g_strcmp0(connection->ifname, rstn_key->ifname) != 0) &&
894 (g_strcmp0(connection->tether_iface.ifname, rstn_key->ifname) != 0))
897 /* classid is invalid */
898 if (rstn_value->classid <= STC_UNKNOWN_CLASSID)
905 table_counters_info info;
906 int64_t effective_limit[STC_RSTN_LIMIT_TYPE_MAX] = { 0, };
908 memset(&info, 0, sizeof(table_counters_info));
909 rstn_value->limit_exceeded = 0;
911 if ((rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 &&
912 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) ||
913 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 &&
914 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) ||
915 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 &&
916 rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) ||
917 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 &&
918 rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) ||
919 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 &&
920 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) {
921 table_counters_get(rstn_value->restriction_id, &info);
923 time_t current_time = 0;
924 cumulative_data_s stat;
925 table_statistics_select_rule rule;
927 memset(&stat, 0, sizeof(cumulative_data_s));
928 stat.month_start_ts = rstn_value->month_start_ts;
929 stat.week_start_ts = g_system->last_week_ts;
930 stat.day_start_ts = g_system->last_day_ts;
932 memset(&rule, 0, sizeof(table_statistics_select_rule));
933 rule.from = rstn_value->month_start_ts;
935 rule.to = current_time;
936 rule.iftype = rstn_key->iftype;
937 rule.granularity = GRANULARITY;
939 table_statistics_per_app(rstn_key->app_id, &rule, __statistics_info_cb, &stat);
941 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter;
942 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter;
943 rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter + stat.monthly_stat;
944 rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter + stat.weekly_stat;
945 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter + stat.daily_stat;
948 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
949 if (rstn_value->limit[i] >= 0) {
950 effective_limit[i] = rstn_value->limit[i] - rstn_value->counter[i];
952 if (effective_limit[i] < 0)
953 rstn_value->limit_exceeded |= (1 << i);
957 STC_LOGD("rstn_id [%llu], datausage [%llu] bytes",
958 rstn_value->restriction_id, info.data_counter);
960 if (rstn_value->limit_exceeded != 0 &&
961 rstn_value->limit_exceeded != (1 << STC_RSTN_LIMIT_TYPE_DATA_WARN)) {
962 __add_iptables_rule(rstn_value->classid, NFACCT_BLOCK, rstn_key->iftype);
965 rstn_value->rstn_state = STC_RSTN_STATE_ACTIVATED;
969 __add_iptables_rule(rstn_value->classid, NFACCT_ALLOW,
972 rstn_value->rstn_state = STC_RSTN_STATE_ACTIVATED;
973 rstn_value->limit_exceeded = 0;
974 rstn_value->limit_notified = 0;
980 if (rstn_value->classid == STC_TETHERING_APP_CLASSID)
981 __del_iptables_rule(rstn_value->classid, NFACCT_BLOCK,
984 __del_iptables_rule(rstn_value->classid, rstn_value->rstn_type,
987 rstn_value->rstn_state = STC_RSTN_STATE_DEACTIVATED;
988 rstn_value->limit_exceeded = 0;
989 rstn_value->limit_notified = 0;
991 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++)
992 if (rstn_value->limit[i] >= 0)
993 rstn_value->counter[i] = 0;
995 __set_rstn_noti_state(STC_RSTN_STATE_UNSET);
1004 static gboolean __remove_rstns_foreach_application(gpointer key,
1008 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1009 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1010 gchar *app_id = (gchar *)data;
1012 /* rstn rule is not for applications */
1013 if (rstn_key->app_id == NULL)
1016 /* rstn rule is not for this application */
1017 if (g_strcmp0(rstn_key->app_id, app_id) != 0)
1020 /* rstn rule is already removed */
1021 if (rstn_value->rstn_state == STC_RSTN_STATE_DEACTIVATED)
1024 /* remove restriction from system */
1025 __process_restriction(RST_UNSET, rstn_key, rstn_value, NULL);
1027 __print_rstn(rstn_key, rstn_value);
1033 static void __remove_rstns_for_application(gchar *app_id)
1035 g_tree_foreach(g_system->rstns, __remove_rstns_foreach_application,
1039 static stc_error_e __application_remove_if_empty(const stc_app_key_s *app_key)
1041 stc_error_e ret = STC_ERROR_NONE;
1042 guint pid_count = 0;
1043 stc_app_value_s *lookup;
1045 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
1047 lookup = __application_lookup(g_system->apps, app_key);
1049 STC_LOGE("app_key not found"); //LCOV_EXCL_LINE
1050 return STC_ERROR_NO_DATA; //LCOV_EXCL_LINE
1053 g_tree_foreach(lookup->processes, __processes_tree_check_empty,
1057 /* remove nfacct rule for this classid */
1058 __remove_application_monitor((gpointer) app_key, lookup,
1059 stc_get_default_connection());
1060 __remove_rstns_for_application(app_key->app_id);
1063 if (!g_tree_remove(g_system->apps, app_key)) {
1064 ret = STC_ERROR_NO_DATA; //LCOV_EXCL_LINE
1065 STC_LOGE("key not found"); //LCOV_EXCL_LINE
1071 static stc_error_e __close_contr_sock(stc_system_s *system)
1073 ret_value_msg_if(system == NULL, STC_ERROR_INVALID_PARAMETER, "invalid parameter");
1075 /* close netlink socket for updating kernel counters */
1076 if (system->contr_sock != -1) {
1077 close(system->contr_sock);
1078 system->contr_sock = -1;
1081 if (system->contr_gsource_id != 0) {
1082 g_source_remove(system->contr_gsource_id);
1083 system->contr_gsource_id = 0;
1086 return STC_ERROR_NONE;
1089 static gboolean __process_contr_reply(GIOChannel *source,
1090 GIOCondition condition,
1091 gpointer user_data);
1094 static stc_error_e __close_and_reopen_contr_sock(stc_system_s *system)
1096 GIOChannel *gio = NULL;
1097 ret_value_msg_if(system == NULL, STC_ERROR_INVALID_PARAMETER, "invalid parameter");
1099 /* close netlink socket for updating kernel counters */
1100 if (system->contr_sock != -1) {
1101 close(system->contr_sock);
1102 system->contr_sock = -1;
1105 if (system->contr_gsource_id != 0) {
1106 g_source_remove(system->contr_gsource_id);
1107 system->contr_gsource_id = 0;
1110 /* create netlink socket for updating kernel counters */
1111 system->contr_sock = create_netlink(NETLINK_NETFILTER, 0);
1112 if (system->contr_sock < 0) {
1113 STC_LOGE("failed to open socket");
1115 return STC_ERROR_FAIL;
1118 gio = g_io_channel_unix_new(system->contr_sock);
1119 system->contr_gsource_id =
1120 g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP,
1121 (GIOFunc) __process_contr_reply,
1123 g_io_channel_unref(gio);
1125 return STC_ERROR_NONE;
1128 static void __action_when_rstn_limit_exceeded(stc_rstn_limit_type_e limit_type,
1129 stc_rstn_key_s *rstn_key,
1130 stc_rstn_value_s *rstn_value,
1131 classid_bytes_context_s *context)
1134 char iftype[MAX_INT_LENGTH] = { 0, };
1135 char byte[MAX_INT_LENGTH] = { 0, };
1136 const char *signal_name = NULL;
1137 const char *net_popup_content = NULL;
1138 const char *net_popup_type = NULL;
1139 stc_s *stc = (stc_s *)stc_get_manager();
1142 STC_LOGE("Failed to get stc data");
1146 switch (limit_type) {
1147 case STC_RSTN_LIMIT_TYPE_DATA_WARN:
1149 signal_name = "WarnThresholdCrossed";
1150 net_popup_content = "warn threshold crossed";
1151 net_popup_type = "warning_noti";
1154 case STC_RSTN_LIMIT_TYPE_DATA:
1155 case STC_RSTN_LIMIT_TYPE_MONTHLY:
1156 case STC_RSTN_LIMIT_TYPE_WEEKLY:
1157 case STC_RSTN_LIMIT_TYPE_DAILY:
1159 signal_name = "RestrictionThresholdCrossed";
1160 net_popup_content = "restriction threshold crossed";
1161 net_popup_type = "restriction_noti";
1163 /* block immediately */
1164 context->counter->intend = NFACCT_BLOCK;
1165 __del_iptables_in(context->counter);
1166 __del_iptables_out(context->counter);
1167 __add_iptables_in(context->counter);
1168 __add_iptables_out(context->counter);
1170 __del_ip6tables_in(context->counter);
1171 __del_ip6tables_out(context->counter);
1172 __add_ip6tables_in(context->counter);
1173 __add_ip6tables_out(context->counter);
1174 context->counter->intend = NFACCT_COUNTER;
1176 rstn_value->limit_exceeded |= (1 << limit_type);
1178 __set_rstn_noti_state(STC_RSTN_STATE_SET);
1185 if (signal_name == NULL) {
1186 STC_LOGE("Invalid parameter: limit_type");
1191 rv = stc_manager_dbus_emit_signal(stc->connection,
1192 STC_DBUS_SERVICE_RESTRICTION_PATH,
1193 STC_DBUS_INTERFACE_RESTRICTION,
1195 g_variant_new("(si)",
1200 rstn_value->limit_notified |= (1 << limit_type);
1202 snprintf(iftype, MAX_INT_LENGTH, "%d", rstn_key->iftype);
1203 snprintf(byte, MAX_INT_LENGTH, "%lld", rstn_value->limit[limit_type]);
1204 stc_plugin_appstatus_send_message(net_popup_content,
1205 net_popup_type, rstn_key->app_id, iftype, byte);
1208 static gboolean __rstn_counter_update(stc_rstn_key_s *rstn_key,
1209 stc_rstn_value_s *rstn_value,
1210 classid_bytes_context_s *context)
1213 switch (context->counter->iotype) {
1214 case NFACCT_COUNTER_IN:
1215 case NFACCT_COUNTER_OUT:
1216 if ((rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 &&
1217 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) ||
1218 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 &&
1219 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) ||
1220 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 &&
1221 rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) ||
1222 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 &&
1223 rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) ||
1224 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 &&
1225 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) {
1226 table_counters_info info;
1227 memset(&info, 0, sizeof(table_counters_info));
1228 table_counters_get(rstn_value->restriction_id, &info);
1230 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter;
1231 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter;
1232 rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter;
1233 rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter;
1234 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter;
1237 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
1238 if (rstn_value->limit[i] >= 0 &&
1239 !(rstn_value->limit_notified & (1 << i))) {
1240 rstn_value->counter[i] += context->bytes;
1241 if (rstn_value->limit[i] <= rstn_value->counter[i])
1242 __action_when_rstn_limit_exceeded(i,
1249 g_system->rstns_tree_updated = TRUE;
1250 __print_rstn(rstn_key, rstn_value);
1253 STC_LOGE("unknown iotype");
1259 static gboolean __interface_rstn_counter_update(stc_rstn_key_s *rstn_key,
1260 stc_rstn_value_s *rstn_value,
1261 classid_bytes_context_s *context)
1263 if ((rstn_value->classid == STC_TOTAL_DATACALL_CLASSID &&
1264 context->counter->iftype == STC_IFACE_DATACALL) ||
1265 (rstn_value->classid == STC_TOTAL_WIFI_CLASSID &&
1266 context->counter->iftype == STC_IFACE_WIFI) ||
1267 (rstn_value->classid == STC_TOTAL_BLUETOOTH_CLASSID &&
1268 context->counter->iftype == STC_IFACE_BLUETOOTH) ||
1269 (rstn_value->classid == STC_TETHERING_APP_CLASSID &&
1270 context->counter->iftype == STC_IFACE_WIFI) ||
1271 (rstn_value->classid == STC_TETHERING_APP_CLASSID &&
1272 context->counter->iftype == STC_IFACE_BLUETOOTH) ||
1273 (rstn_value->classid == STC_TETHERING_APP_CLASSID &&
1274 context->counter->iftype == STC_IFACE_USB) ||
1275 (rstn_value->classid == STC_TETHERING_APP_CLASSID &&
1276 context->counter->iftype == STC_IFACE_P2P)) {
1277 context->counter->classid = rstn_value->classid;
1278 return __rstn_counter_update(rstn_key, rstn_value, context);
1284 static gboolean __rstn_counter_update_foreach_classid(gpointer key,
1288 gboolean rv = FALSE;
1289 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1290 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1291 classid_bytes_context_s *context = (classid_bytes_context_s *)data;
1294 if (context->counter->intend != NFACCT_COUNTER &&
1295 context->counter->intend != NFACCT_TETH_COUNTER)
1296 goto try_next_callback;
1298 if (rstn_value->limit_exceeded == TRUE) {
1299 context->data_limit_exceeded = TRUE; //LCOV_EXCL_LINE
1300 goto try_next_callback; //LCOV_EXCL_LINE
1303 classid = context->counter->classid;
1304 rv = __interface_rstn_counter_update(rstn_key, rstn_value, context);
1306 context->counter->classid = classid;
1307 if (rstn_value->classid != context->counter->classid)
1308 goto try_next_callback;
1310 rv = __rstn_counter_update(rstn_key, rstn_value, context);
1317 static gboolean __update_app_statistics(gpointer key, gpointer value,
1320 stc_app_key_s *app_key = (stc_app_key_s *)key;
1321 stc_app_value_s *app_value = (stc_app_value_s *)value;
1322 time_t *touch_time = (time_t *)data;
1323 stc_db_classid_iftype_key stat_key;
1324 stc_db_app_stats stat;
1325 default_connection_s *default_connection = stc_get_default_connection();
1327 memset(&stat_key, 0, sizeof(stc_db_classid_iftype_key));
1328 memset(&stat, 0 , sizeof(stc_db_app_stats));
1330 /* Do not update statistics for Tethering
1331 * if tethering is in-active found */
1332 if (default_connection &&
1333 default_connection->tether_state == FALSE &&
1334 !strcmp(app_key->app_id, STC_TOTAL_TETHERING))
1337 /* Do not update statistics for Wi-Fi
1338 * if tethering is active on wlan0 iface */
1339 if (default_connection && default_connection->tether_state &&
1340 default_connection->tether_iface.type == STC_IFACE_WIFI &&
1341 !strcmp(app_key->app_id, STC_TOTAL_WIFI))
1344 stat_key.classid = app_value->classid;
1346 if (app_value->classid == STC_TETHERING_APP_CLASSID &&
1347 default_connection->tether_state == TRUE)
1348 stat_key.iftype = default_connection->tether_iface.type;
1349 else if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX))
1350 stat_key.iftype = default_connection->tether_iface.type;
1352 stat_key.iftype = default_connection->type;
1354 if (STC_IFACE_DATACALL == stat_key.iftype)
1355 stat_key.subscriber_id = g_strdup(default_connection->subscriber_id);
1357 stat_key.subscriber_id = g_strdup("none_subid"); //LCOV_EXCL_LINE
1359 if (app_value->classid == STC_TETHERING_APP_CLASSID &&
1360 default_connection->tether_state == TRUE)
1361 g_strlcpy(stat_key.ifname, default_connection->tether_iface.ifname,
1363 else if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX))
1364 g_strlcpy(stat_key.ifname, default_connection->tether_iface.ifname,
1367 g_strlcpy(stat_key.ifname, default_connection->ifname,
1370 stat.app_id = g_strdup(app_key->app_id);
1371 stat.snd_count = app_value->counter.out_bytes;
1372 stat.rcv_count = app_value->counter.in_bytes;
1373 stat.is_roaming = default_connection->roaming;
1375 if (strstr(stat.app_id, "_BACKGROUND")) {
1376 stat.ground = STC_APP_STATE_BACKGROUND;
1378 if (strstr(stat.app_id, "TOTAL_"))
1379 stat.ground = STC_APP_STATE_UNKNOWN;
1381 stat.ground = STC_APP_STATE_FOREGROUND;
1384 table_statistics_insert(&stat_key, &stat, *touch_time);
1386 app_value->counter.out_bytes = 0;
1387 app_value->counter.in_bytes = 0;
1390 FREE(stat_key.subscriber_id);
1395 static gboolean __flush_apps_stats_to_database(gpointer user_data)
1397 time_t current_time = 0;
1398 stc_s *stc = stc_get_manager();
1400 if (stc && stc->carg)
1401 current_time = stc->carg->last_run_time;
1403 if (g_system->apps_tree_updated == FALSE)
1404 return G_SOURCE_REMOVE;
1406 g_system->apps_tree_updated = FALSE;
1409 g_tree_foreach(g_system->apps,
1410 __update_app_statistics,
1413 STC_LOGI("Flushed app stats to database");
1414 return G_SOURCE_REMOVE;
1418 static gboolean __update_counter_statistics(gpointer key, gpointer value,
1421 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1422 table_counters_info info = {
1423 .restriction_id = rstn_value->restriction_id,
1424 .data_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA],
1425 .warn_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN],
1426 .monthly_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY],
1427 .weekly_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY],
1428 .daily_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY]
1431 table_counters_update_counters(&info);
1436 static gboolean __flush_rstns_counter_to_database(gpointer user_data)
1438 time_t current_time = 0;
1439 stc_s *stc = stc_get_manager();
1441 if (stc && stc->carg)
1442 current_time = stc->carg->last_run_time;
1444 if (g_system->rstns_tree_updated == FALSE)
1445 return G_SOURCE_REMOVE;
1447 g_system->rstns_tree_updated = FALSE;
1449 if (g_system->rstns)
1450 g_tree_foreach(g_system->rstns,
1451 __update_counter_statistics,
1454 STC_LOGI("Flushed rstns counters to database");
1455 return G_SOURCE_REMOVE;
1459 static void __app_counter_update(stc_app_key_s *app_key,
1460 stc_app_value_s *app_value,
1461 classid_bytes_context_s *context)
1463 switch (context->counter->iotype) {
1464 case NFACCT_COUNTER_IN:
1465 app_value->data_usage.in_bytes += context->bytes;
1466 app_value->counter.in_bytes = context->bytes;
1467 g_system->apps_tree_updated = TRUE;
1470 __apps_tree_foreach_print(app_key, app_value, NULL); //LCOV_EXCL_LINE
1473 case NFACCT_COUNTER_OUT:
1474 app_value->data_usage.out_bytes += context->bytes;
1475 app_value->counter.out_bytes = context->bytes;
1476 g_system->apps_tree_updated = TRUE;
1479 __apps_tree_foreach_print(app_key, app_value, NULL); //LCOV_EXCL_LINE
1483 STC_LOGE("unknown iotype"); //LCOV_EXCL_LINE
1487 static void __interface_counter_update(stc_app_key_s *app_key,
1488 stc_app_value_s *app_value,
1489 classid_bytes_context_s *context)
1491 if ((app_value->classid == STC_TOTAL_DATACALL_CLASSID &&
1492 context->counter->iftype == STC_IFACE_DATACALL) ||
1493 (app_value->classid == STC_TOTAL_WIFI_CLASSID &&
1494 context->counter->iftype == STC_IFACE_WIFI) ||
1495 (app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID &&
1496 context->counter->iftype == STC_IFACE_BLUETOOTH) ||
1497 (app_value->classid == STC_TETHERING_APP_CLASSID &&
1498 context->counter->iftype == STC_IFACE_WIFI) ||
1499 (app_value->classid == STC_TETHERING_APP_CLASSID &&
1500 context->counter->iftype == STC_IFACE_BLUETOOTH) ||
1501 (app_value->classid == STC_TETHERING_APP_CLASSID &&
1502 context->counter->iftype == STC_IFACE_USB) ||
1503 (app_value->classid == STC_TETHERING_APP_CLASSID &&
1504 context->counter->iftype == STC_IFACE_P2P))
1505 __app_counter_update(app_key, app_value, context);
1509 static gboolean __apps_counter_update_foreach_classid(gpointer key,
1513 stc_app_key_s *app_key = (stc_app_key_s *)key;
1514 stc_app_value_s *app_value = (stc_app_value_s *)value;
1515 classid_bytes_context_s *context = (classid_bytes_context_s *)data;
1517 if (context->counter->intend != NFACCT_COUNTER &&
1518 context->counter->intend != NFACCT_TETH_COUNTER)
1519 goto try_next_callback;
1521 __interface_counter_update(app_key, app_value, context);
1523 if (app_value->classid != context->counter->classid)
1524 goto try_next_callback;
1526 __app_counter_update(app_key, app_value, context);
1532 static gboolean __reset_time_counter_foreach_rstn(gpointer key,
1536 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1537 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1538 reset_time_limits_context_s *context = (reset_time_limits_context_s *)data;
1540 time_t now_month_start_ts;
1542 if (rstn_value->month_start_date == 0) {
1543 table_counters_info info;
1544 memset(&info, 0, sizeof(table_counters_info));
1545 table_counters_get_timestamps(rstn_value->restriction_id, &info);
1547 if (info.month_start_date == 0)
1548 rstn_value->month_start_date = 1;
1550 rstn_value->month_start_date = info.month_start_date;
1551 rstn_value->month_start_ts = info.month_start_ts;
1554 now_month_start_ts =
1555 stc_time_get_month_start(context->now,
1556 rstn_value->month_start_date);
1558 if (rstn_value->month_start_ts != now_month_start_ts) {
1559 rstn_value->month_start_ts = now_month_start_ts;
1560 context->month_start_ts = now_month_start_ts;
1561 context->is_updated |= (1 << STC_RSTN_LIMIT_TYPE_MONTHLY);
1564 if (context->is_updated) {
1565 table_counters_info info;
1566 memset(&info, 0, sizeof(table_counters_info));
1568 info.restriction_id = rstn_value->restriction_id;
1569 info.month_start_date = rstn_value->month_start_date;
1570 info.month_start_ts = rstn_value->month_start_ts;
1571 info.week_start_ts = context->week_start_ts;
1572 info.day_start_ts = context->day_start_ts;
1574 table_counters_update_timestamps(&info);
1577 for (i = STC_RSTN_LIMIT_TYPE_MONTHLY; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
1579 if ((context->is_updated) & (1 << i)) {
1581 rstn_value->counter[i] = 0;
1583 if (rstn_value->limit_exceeded & (1 << i)) {
1584 /* remove iptables rule */
1585 char *default_ifname = stc_default_connection_get_ifname();
1586 struct nfacct_rule counter;
1587 stc_s *stc = stc_get_manager();
1589 STC_LOGE("Can't get stc data");
1590 g_free(default_ifname);
1591 goto try_next_callback;
1595 stc->carg = MALLOC0(counter_arg_s, 1);
1596 if (stc->carg == NULL) {
1597 g_free(default_ifname);
1598 goto try_next_callback;
1602 stc_monitor_get_counter_socket();
1605 counter.carg = stc->carg;
1606 counter.classid = rstn_value->classid;
1607 counter.intend = NFACCT_BLOCK;
1608 counter.iftype = rstn_key->iftype;
1609 g_strlcpy(counter.ifname, default_ifname,
1612 g_free(default_ifname);
1615 __del_iptables_in(&counter);
1616 __del_iptables_out(&counter);
1618 /* ip6tables rule */
1619 __del_ip6tables_in(&counter);
1620 __del_ip6tables_out(&counter);
1622 rstn_value->rstn_state = STC_RSTN_STATE_DEACTIVATED;
1623 rstn_value->limit_exceeded &= ~(1 << i);
1624 rstn_value->limit_notified &= ~(1 << i);
1633 static void __reset_time_counters_if_required(void)
1635 reset_time_limits_context_s context;
1637 if (g_system == NULL) {
1638 STC_LOGE("stc monitor not initialized!");
1642 context.now = time(NULL);
1643 context.week_start_ts = stc_time_get_week_start(context.now);
1644 context.day_start_ts = stc_time_get_day_start(context.now);
1645 context.is_updated = 0;
1647 if (g_system->last_week_ts != context.week_start_ts) {
1648 g_system->last_week_ts = context.week_start_ts;
1649 context.is_updated |= (1 << STC_RSTN_LIMIT_TYPE_WEEKLY);
1652 if (g_system->last_day_ts != context.day_start_ts) {
1653 g_system->last_day_ts = context.day_start_ts;
1654 context.is_updated |= (1 << STC_RSTN_LIMIT_TYPE_DAILY);
1657 if (g_system->rstns) {
1658 g_tree_foreach(g_system->rstns,
1659 __reset_time_counter_foreach_rstn,
1661 if (context.is_updated)
1662 STC_LOGD("Counter reset completed month_start [%ld], week_start [%ld], day_start [%ld]",
1663 context.month_start_ts, g_system->last_week_ts, g_system->last_day_ts);
1667 static void __fill_nfacct_result(char *cnt_name, int64_t bytes,
1668 struct counter_arg *carg)
1670 __reset_time_counters_if_required();
1672 struct nfacct_rule counter = {
1679 classid_bytes_context_s context = {
1680 .counter = &counter,
1682 .data_limit_exceeded = FALSE,
1685 if (!recreate_counter_by_name(cnt_name, &counter)) {
1686 STC_LOGE("Can't parse counter name %s", cnt_name); //LCOV_EXCL_LINE
1687 return; //LCOV_EXCL_LINE
1691 STC_LOGI("classid %u, iftype %u, iotype %d, intend %d, ifname %s, bytes %lld",
1692 context.counter->classid, context.counter->iftype,
1693 context.counter->iotype, context.counter->intend,
1694 context.counter->ifname, context.bytes);
1696 if (g_system->rstns)
1697 g_tree_foreach(g_system->rstns,
1698 __rstn_counter_update_foreach_classid,
1702 g_tree_foreach(g_system->apps,
1703 __apps_counter_update_foreach_classid,
1707 static int __fill_counters(struct rtattr *attr_list[__NFACCT_MAX],
1710 struct counter_arg *carg = user_data;
1711 char *cnt_name = (char *)RTA_DATA(attr_list[NFACCT_NAME]);
1712 if (carg->initiate) {
1714 * TODO: this will be used when daemon starts to update existing
1715 * counter data if present.
1717 populate_counters(cnt_name, carg);
1721 (int64_t *)RTA_DATA(attr_list[NFACCT_BYTES]);
1722 int bytes = be64toh(*bytes_p);
1724 ++carg->serialized_counters;
1725 __fill_nfacct_result(cnt_name, bytes, carg);
1732 static int __post_fill_counters(void *user_data)
1734 struct counter_arg *carg = user_data;
1742 static void __process_network_counter(struct genl *ans,
1743 struct counter_arg *carg)
1745 struct netlink_serialization_params ser_params = {
1748 .eval_attr = __fill_counters,
1749 .post_eval_attr = __post_fill_counters,
1752 netlink_serialization_command *netlink =
1753 netlink_create_command(&ser_params);
1755 STC_LOGE("Can not create command"); //LCOV_EXCL_LINE
1756 return; //LCOV_EXCL_LINE
1759 netlink->deserialize_answer(&(netlink->params));
1762 static gboolean __process_contr_reply(GIOChannel *source,
1763 GIOCondition condition,
1766 int sock = g_io_channel_unix_get_fd(source);
1769 stc_s *stc = stc_get_manager();
1772 void __gcov_flush(void);
1776 if ((condition & G_IO_ERR) || (condition & G_IO_HUP) ||
1777 (condition & G_IO_NVAL)) {
1778 /* G_IO_ERR/G_IO_HUP/G_IO_NVAL received */
1780 STC_LOGE("Counter socket received G_IO event, closing socket." //LCOV_EXCL_LINE
1781 "G_IO_ERR [%u], G_IO_HUP [%u], G_IO_NVAL [%u]",
1782 (condition & G_IO_ERR), (condition & G_IO_HUP),
1783 (condition & G_IO_NVAL));
1784 __close_and_reopen_contr_sock(g_system); //LCOV_EXCL_LINE
1785 return FALSE; //LCOV_EXCL_LINE
1788 ans = MALLOC0(struct genl, 1);
1790 STC_LOGE("Failed allocate memory to genl reply message"); //LCOV_EXCL_LINE
1791 return TRUE; //LCOV_EXCL_LINE
1795 STC_LOGE("Can't get stc data"); //LCOV_EXCL_LINE
1796 goto out; //LCOV_EXCL_LINE
1799 ret = read_netlink(sock, ans, sizeof(struct genl));
1800 /* STC_LOGD("Counter data received ret [%d]", ret); */
1804 stc->carg->ans_len = ret;
1805 stc->carg->last_run_time = time(NULL);
1807 __process_network_counter(ans, stc->carg);
1809 g_idle_add(__flush_apps_stats_to_database, NULL);
1810 g_idle_add(__flush_rstns_counter_to_database, NULL);
1817 static gboolean __update_contr_cb(void *user_data)
1819 /* Here we just sent command, answer we receive in another callback */
1820 stc_s *stc = stc_get_manager();
1821 ret_value_msg_if(stc == NULL, STC_ERROR_FAIL, "Can't get stc data");
1823 stc->carg = MALLOC0(counter_arg_s, 1);
1824 if (stc->carg == NULL)
1825 return TRUE; /* we need to continue the timer */
1827 stc->carg->sock = stc_monitor_get_counter_socket();
1831 void __gcov_flush(void);
1835 /* STC_LOGD("Get all counters"); */
1836 nfacct_send_get_all(stc->carg);
1838 /* we need to continue the timer */
1844 static gboolean __rstn_tree_foreach_print(gpointer key, gpointer value,
1847 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1848 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1850 __print_rstn(rstn_key, rstn_value);
1854 static void __rstn_tree_printall(void)
1856 g_tree_foreach(g_system->rstns, __rstn_tree_foreach_print, NULL);
1861 static stc_rstn_value_s * __rstn_lookup(GTree *rstns_tree,
1862 const stc_rstn_key_s *key)
1864 stc_rstn_value_s *lookup;
1866 ret_value_msg_if(rstns_tree == NULL, NULL, "rstns_tree is null!");
1868 lookup = g_tree_lookup(rstns_tree, key);
1873 static gboolean __remove_restriction(gpointer key, gpointer value,
1876 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1877 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1879 __process_restriction(RST_UNSET, rstn_key, rstn_value, data);
1880 __print_rstn(rstn_key, rstn_value);
1884 static gboolean __add_restriction_debug(gpointer key, gpointer value,
1887 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1888 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1890 /* rstn rule is activated */
1891 if (rstn_value->rstn_state == STC_RSTN_STATE_ACTIVATED)
1894 if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
1895 __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, data);
1897 __process_restriction(RST_SET, rstn_key, rstn_value, data);
1899 __print_rstn(rstn_key, rstn_value);
1905 static gboolean __add_restriction(gpointer key, gpointer value, gpointer data)
1907 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1908 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1910 /* rstn rule is activated */
1911 if (rstn_value->rstn_state == STC_RSTN_STATE_ACTIVATED)
1914 if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
1915 __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, data);
1917 __process_restriction(RST_SET, rstn_key, rstn_value, data);
1923 static stc_error_e __rstn_tree_remove(stc_rstn_key_s *key)
1925 stc_rstn_value_s *lookup_value;
1927 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
1929 lookup_value = __rstn_lookup(g_system->rstns, key);
1930 if (!lookup_value) {
1931 STC_LOGE("key not found"); //LCOV_EXCL_LINE
1932 return STC_ERROR_NO_DATA; //LCOV_EXCL_LINE
1935 /* remove counter also */
1936 table_counters_delete(lookup_value->restriction_id);
1937 __remove_restriction(key, lookup_value, NULL);
1939 if (!g_tree_remove(g_system->rstns, key)) {
1940 STC_LOGD("key not found"); //LCOV_EXCL_LINE
1941 return STC_ERROR_NO_DATA; //LCOV_EXCL_LINE
1944 return STC_ERROR_NONE;
1947 static stc_error_e __rstn_tree_add(stc_rstn_key_s *key,
1948 stc_rstn_value_s *value, gboolean debug)
1950 stc_rstn_key_s *rstn_key;
1951 stc_rstn_value_s *rstn_value;
1953 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
1955 rstn_value = __rstn_lookup(g_system->rstns, key);
1957 __rstn_tree_remove(key);
1959 rstn_key = MALLOC0(stc_rstn_key_s, 1);
1961 STC_LOGE("rstn_key allocation failed"); //LCOV_EXCL_LINE
1962 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
1965 rstn_value = MALLOC0(stc_rstn_value_s, 1);
1967 STC_LOGE("rstn_value allocation failed"); //LCOV_EXCL_LINE
1968 FREE(rstn_key); //LCOV_EXCL_LINE
1969 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
1972 rstn_key->app_id = g_strdup(key->app_id);
1973 rstn_key->ifname = g_strdup(key->ifname);
1974 rstn_key->subscriber_id = g_strdup(key->subscriber_id);
1975 rstn_key->iftype = key->iftype;
1976 rstn_key->roaming = key->roaming;
1978 g_tree_insert(g_system->rstns, rstn_key, rstn_value);
1980 rstn_value->restriction_id = value->restriction_id;
1981 rstn_value->rstn_state = value->rstn_state;
1982 rstn_value->rstn_type = value->rstn_type;
1983 rstn_value->classid = value->classid;
1986 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
1987 rstn_value->limit[i] = value->limit[i];
1988 rstn_value->counter[i] = 0;
1991 rstn_value->limit_exceeded = 0;
1992 rstn_value->limit_notified = 0;
1993 rstn_value->month_start_date = value->month_start_date;
1994 rstn_value->month_start_ts = value->month_start_ts;
1997 __add_restriction_debug(key, rstn_value, NULL);
1999 __add_restriction(key, rstn_value, NULL);
2001 return STC_ERROR_NONE;
2005 static stc_cb_ret_e __insert_restriction_cb(const table_restrictions_info *info,
2008 stc_cb_ret_e ret = STC_CONTINUE;
2011 stc_rstn_value_s value;
2013 memset(&key, 0, sizeof(stc_rstn_key_s));
2014 memset(&value, 0, sizeof(stc_rstn_value_s));
2016 key.app_id = g_strdup(info->app_id);
2017 key.ifname = g_strdup(info->ifname);
2018 key.subscriber_id = g_strdup(info->subscriber_id);
2019 key.iftype = info->iftype;
2020 key.roaming = info->roaming;
2022 value.rstn_type = info->rstn_type;
2023 value.rstn_state = STC_RSTN_STATE_UNKNOWN;
2024 value.restriction_id = info->restriction_id;
2027 value.classid = get_classid_by_app_id(info->app_id, TRUE);
2029 value.classid = STC_UNKNOWN_CLASSID;
2031 value.limit[STC_RSTN_LIMIT_TYPE_DATA] = info->data_limit;
2032 value.limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info->data_warn_limit;
2033 value.limit[STC_RSTN_LIMIT_TYPE_MONTHLY] = info->monthly_limit;
2034 value.limit[STC_RSTN_LIMIT_TYPE_WEEKLY] = info->weekly_limit;
2035 value.limit[STC_RSTN_LIMIT_TYPE_DAILY] = info->daily_limit;
2037 if (__rstn_tree_add(&key, &value, FALSE) != STC_ERROR_NONE)
2042 FREE(key.subscriber_id);
2046 static void __fill_restritions_list(void)
2048 table_restrictions_foreach(__insert_restriction_cb, NULL);
2050 /* __rstn_tree_printall(); */
2053 static gboolean __add_rstn_foreach_application(gpointer key,
2057 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
2058 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
2059 gchar *app_id = (gchar *)data;
2061 /* rstn rule is not for applications */
2062 if (rstn_key->app_id == NULL)
2065 /* rstn rule is not for this application */
2066 if (g_strcmp0(rstn_key->app_id, app_id) != 0)
2069 /* rstn rule is already applied */
2070 if (rstn_value->rstn_state == STC_RSTN_STATE_ACTIVATED)
2073 /* add restriction to system */
2074 if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
2075 __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, NULL);
2077 __process_restriction(RST_SET, rstn_key, rstn_value, NULL);
2079 __print_rstn(rstn_key, rstn_value);
2085 static void __add_rstns_for_application(gchar *app_id)
2087 g_tree_foreach(g_system->rstns, __add_rstn_foreach_application,
2091 static void __add_application_by_interface(const char *app_id)
2093 stc_app_key_s app_key;
2094 stc_app_value_s app_value;
2097 return; //LCOV_EXCL_LINE
2099 memset(&app_key, 0, sizeof(stc_app_key_s));
2100 memset(&app_value, 0, sizeof(stc_app_value_s));
2102 app_key.pkg_id = g_strdup(app_id);
2103 app_key.app_id = g_strdup(app_id);
2105 app_value.type = STC_APP_TYPE_NONE;
2106 app_value.processes = NULL;
2107 app_value.counter.in_bytes = 0;
2108 app_value.counter.out_bytes = 0;
2110 stc_monitor_application_add(app_key, app_value);
2112 FREE(app_key.pkg_id);
2113 FREE(app_key.app_id);
2116 static guint __get_background_state(void)
2118 return g_system->background_state;;
2121 static void __set_background_state(guint state)
2123 g_system->background_state = state;
2126 static gboolean __processes_tree_foreach_background(gpointer key,
2130 stc_process_key_s *proc_key = (stc_process_key_s *)key;
2131 stc_app_key_s *app_key = (stc_app_key_s *)data;
2133 if (g_system->background_state)
2134 place_pids_to_net_cgroup(proc_key->pid, STC_BACKGROUND_APP_ID);
2136 place_pids_to_net_cgroup(proc_key->pid, app_key->app_id);
2141 static gboolean __apps_tree_foreach_background(gpointer key, gpointer value,
2144 stc_app_key_s *app_key = (stc_app_key_s *)key;
2145 stc_app_value_s *app_value = (stc_app_value_s *)value;
2147 if (strstr(app_key->app_id, STC_BACKGROUND_APP_SUFFIX))
2148 g_tree_foreach(app_value->processes,
2149 __processes_tree_foreach_background, app_key);
2154 static stc_error_e __process_update_background(void)
2156 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2158 g_tree_foreach(g_system->apps, __apps_tree_foreach_background, NULL);
2160 return STC_ERROR_NONE;
2164 static void __fill_exceptions_list(void)
2166 stc_plugin_fill_exception_list();
2169 stc_error_e stc_monitor_init(void)
2171 stc_system_s *system = MALLOC0(stc_system_s, 1);
2172 GIOChannel *gio = NULL;
2174 ret_value_msg_if(system == NULL, STC_ERROR_OUT_OF_MEMORY, "stc_system_s malloc fail!");
2176 /* initializing current classid */
2177 init_current_classid();
2179 /* initializing cgroups */
2182 /* creating monitored application tree */
2183 system->apps = g_tree_new_full(__apps_tree_key_compare, NULL,
2184 __apps_tree_key_free,
2185 __apps_tree_value_free);
2187 system->rstns = g_tree_new_full(__rstns_tree_key_compare, NULL,
2188 __rstns_tree_key_free,
2189 __rstns_tree_value_free);
2191 /* create netlink socket for updating kernel counters */
2192 system->contr_sock = create_netlink(NETLINK_NETFILTER, 0);
2193 if (system->contr_sock < 0) {
2194 STC_LOGE("failed to open socket"); //LCOV_EXCL_LINE
2195 FREE(system); //LCOV_EXCL_LINE
2196 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
2199 gio = g_io_channel_unix_new(system->contr_sock);
2200 system->contr_gsource_id =
2201 g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP,
2202 (GIOFunc) __process_contr_reply,
2204 g_io_channel_unref(gio);
2208 __add_application_by_interface(STC_TOTAL_DATACALL);
2209 __add_application_by_interface(STC_TOTAL_WIFI);
2210 __add_application_by_interface(STC_TOTAL_BLUETOOTH);
2211 __add_application_by_interface(STC_TOTAL_IPV4);
2212 __add_application_by_interface(STC_TOTAL_IPV6);
2213 __add_application_by_interface(STC_TOTAL_TETHERING);
2215 /* creating restriction rules tree */
2216 __update_contr_cb(NULL);
2218 /* registering periodic kernel counters update callback */
2219 g_system->contr_timer_id = g_timeout_add_seconds(CONTR_TIMER_INTERVAL,
2222 if (g_system->contr_timer_id == 0) {
2223 STC_LOGE("Failed to register kernel counters update timer"); //LCOV_EXCL_LINE
2224 __close_contr_sock(g_system); //LCOV_EXCL_LINE
2225 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
2228 __vconf_get_int(VCONFKEY_STC_BACKGROUND_STATE,
2229 (int *)&g_system->background_state);
2231 __fill_exceptions_list();
2232 __fill_restritions_list();
2234 return STC_ERROR_NONE;
2237 stc_error_e stc_monitor_deinit(void)
2239 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2241 /* close netlink socket for updating kernel counters */
2242 __close_contr_sock(g_system);
2244 /* remove kernel counters update timer */
2245 if (g_system->contr_timer_id > 0) {
2246 g_source_remove(g_system->contr_timer_id);
2247 g_system->contr_timer_id = 0;
2250 /* destroy monitored application tree */
2251 g_tree_destroy(g_system->apps);
2252 g_system->apps = NULL;
2254 /* destroy restriction rules tree */
2255 g_tree_destroy(g_system->rstns);
2256 g_system->rstns = NULL;
2260 return STC_ERROR_NONE;
2263 API stc_error_e stc_monitor_application_add(const stc_app_key_s app_key,
2264 const stc_app_value_s app_value)
2266 stc_error_e ret = STC_ERROR_NONE;
2268 stc_app_value_s *value;
2269 stc_app_value_s *lookup;
2271 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2273 lookup = __application_lookup(g_system->apps, &app_key);
2275 return STC_ERROR_NONE; //LCOV_EXCL_LINE
2277 key = MALLOC0(stc_app_key_s, 1);
2279 STC_LOGE("key allocation failed"); //LCOV_EXCL_LINE
2280 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
2283 value = MALLOC0(stc_app_value_s, 1);
2285 STC_LOGE("value allocation failed"); //LCOV_EXCL_LINE
2286 FREE(key); //LCOV_EXCL_LINE
2287 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
2290 key->app_id = g_strdup(app_key.app_id);
2291 key->pkg_id = g_strdup(app_key.pkg_id);
2293 value->type = app_value.type;
2294 value->data_usage.in_bytes = app_value.data_usage.in_bytes;
2295 value->data_usage.out_bytes = app_value.data_usage.out_bytes;
2296 g_strlcpy(value->ipaddr, app_value.ipaddr, IPV4_IPADDRESS_LEN);
2298 value->processes = g_tree_new_full(__processes_tree_key_compare, NULL,
2299 __processes_tree_key_free,
2300 __processes_tree_value_free);
2302 /* create cgroup and update classid */
2303 value->classid = get_classid_by_app_id(app_key.app_id, TRUE);
2305 g_tree_insert(g_system->apps, key, value);
2307 /* add nfacct rule for this classid */
2308 __add_application_monitor(key, value, stc_get_default_connection());
2309 __add_rstns_for_application(app_key.app_id);
2314 API stc_error_e stc_monitor_application_remove(const stc_app_key_s app_key)
2316 stc_error_e ret = STC_ERROR_NONE;
2317 stc_app_value_s *app_lookup;
2319 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2321 app_lookup = __application_lookup(g_system->apps, &app_key);
2324 STC_LOGD("app_key not found"); //LCOV_EXCL_LINE
2325 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
2328 /* remove nfacct rule for this classid */
2329 __remove_application_monitor((gpointer) &app_key, app_lookup,
2330 stc_get_default_connection());
2332 /* remove ristrictions if any */
2333 __remove_rstns_for_application(app_key.app_id);
2335 /* remove app_key from the stc-manager */
2336 if (!g_tree_remove(g_system->apps, &app_key)) {
2337 ret = STC_ERROR_NO_DATA;
2338 STC_LOGE("key not found");
2344 API stc_error_e stc_monitor_process_add(const stc_app_key_s app_key,
2345 const stc_process_key_s proc_key,
2346 const stc_process_value_s proc_value)
2348 stc_error_e ret = STC_ERROR_NONE;
2349 stc_app_value_s *app_lookup;
2350 stc_process_key_s *key;
2351 stc_process_value_s *value;
2352 stc_process_value_s *proc_lookup;
2354 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2356 app_lookup = __application_lookup(g_system->apps, &app_key);
2359 STC_LOGD("app_key not found"); //LCOV_EXCL_LINE
2360 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
2363 proc_lookup = __process_lookup(app_lookup->processes, &proc_key);
2365 return STC_ERROR_NONE; //LCOV_EXCL_LINE
2367 key = MALLOC0(stc_process_key_s, 1);
2369 STC_LOGE("key allocation failed"); //LCOV_EXCL_LINE
2370 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
2373 value = MALLOC0(stc_process_value_s, 1);
2375 STC_LOGE("value allocation failed"); //LCOV_EXCL_LINE
2376 FREE(key); //LCOV_EXCL_LINE
2377 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
2380 key->pid = proc_key.pid;
2382 value->ground = proc_value.ground;
2384 g_tree_insert(app_lookup->processes, key, value);
2386 /* add pid to application cgroup */
2387 place_pids_to_net_cgroup(proc_key.pid, app_key.app_id);
2390 __apps_tree_printall(); //LCOV_EXCL_LINE
2396 API stc_error_e stc_monitor_process_remove(pid_t pid)
2398 stc_error_e ret = STC_ERROR_NONE;
2399 stc_process_key_s proc_key = {
2403 remove_pid_context_s context = {
2405 .proc_key = &proc_key,
2406 .entry_removed = FALSE,
2409 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2411 g_tree_foreach(g_system->apps, __apps_tree_foreach_remove_pid,
2414 if (context.entry_removed)
2415 __application_remove_if_empty(context.app_key);
2418 __apps_tree_printall(); //LCOV_EXCL_LINE
2425 API stc_error_e stc_monitor_process_update_ground(const stc_app_key_s app_key,
2426 const stc_process_key_s proc_key,
2427 stc_app_state_e ground)
2429 stc_error_e ret = STC_ERROR_NONE;
2430 stc_app_value_s *app_lookup;
2431 stc_process_value_s *proc_lookup;
2433 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2435 app_lookup = __application_lookup(g_system->apps, &app_key);
2437 STC_LOGD("app_key not found");
2438 return STC_ERROR_FAIL;
2441 proc_lookup = __process_lookup(app_lookup->processes, &proc_key);
2443 STC_LOGD("proc_key not found");
2444 return STC_ERROR_FAIL;
2447 if (proc_lookup->ground != ground)
2448 proc_lookup->ground = ground;
2450 if (ground == STC_APP_STATE_BACKGROUND && __get_background_state())
2451 place_pids_to_net_cgroup(proc_key.pid, STC_BACKGROUND_APP_ID);
2453 place_pids_to_net_cgroup(proc_key.pid, app_key.app_id);
2459 void stc_monitor_update_rstn_by_default_connection(void *data)
2461 static default_connection_s old_connection;
2462 default_connection_s *new_connection = (default_connection_s *)data;
2464 if (old_connection.path != NULL) {
2467 g_tree_foreach(g_system->apps,
2468 __remove_application_monitor,
2469 (gpointer)&old_connection);
2471 if (g_system->rstns)
2472 g_tree_foreach(g_system->rstns,
2473 __remove_restriction,
2474 (gpointer)&old_connection);
2476 iptables_flush_chains();
2480 FREE(old_connection.path);
2481 FREE(old_connection.ifname);
2482 FREE(old_connection.tether_iface.ifname);
2483 old_connection.type = 0;
2484 old_connection.roaming = 0;
2485 old_connection.tether_state = FALSE;
2486 old_connection.tether_iface.type = 0;
2488 if (new_connection != NULL && new_connection->path != NULL) {
2490 g_tree_foreach(g_system->apps,
2491 __add_application_monitor,
2492 (gpointer)new_connection);
2494 if (g_system->rstns)
2495 g_tree_foreach(g_system->rstns, __add_restriction,
2498 old_connection.path = g_strdup(new_connection->path);
2499 old_connection.ifname = g_strdup(new_connection->ifname);
2500 old_connection.tether_iface.ifname = g_strdup(new_connection->tether_iface.ifname);
2501 old_connection.type = new_connection->type;
2502 old_connection.roaming = new_connection->roaming;
2503 old_connection.tether_state = new_connection->tether_state;
2504 old_connection.tether_iface.type = new_connection->tether_iface.type;
2508 stc_error_e stc_monitor_rstns_tree_add(const table_restrictions_info *info)
2513 stc_rstn_value_s value;
2515 memset(&key, 0, sizeof(stc_rstn_key_s));
2516 memset(&value, 0, sizeof(stc_rstn_value_s));
2518 key.app_id = g_strdup(info->app_id);
2519 key.ifname = g_strdup(info->ifname);
2520 key.subscriber_id = g_strdup(info->subscriber_id);
2521 key.iftype = info->iftype;
2522 key.roaming = info->roaming;
2524 value.rstn_type = info->rstn_type;
2525 value.rstn_state = STC_RSTN_STATE_UNKNOWN;
2526 value.restriction_id = info->restriction_id;
2529 value.classid = get_classid_by_app_id(info->app_id, TRUE);
2531 value.classid = STC_UNKNOWN_CLASSID;
2533 if (value.classid == STC_BACKGROUND_APP_CLASSID) {
2534 __set_background_state(TRUE); //LCOV_EXCL_LINE
2535 __vconf_set_int(VCONFKEY_STC_BACKGROUND_STATE, g_system->background_state); //LCOV_EXCL_LINE
2536 __process_update_background(); //LCOV_EXCL_LINE
2539 value.limit[STC_RSTN_LIMIT_TYPE_DATA] = info->data_limit;
2540 value.limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info->data_warn_limit;
2541 value.limit[STC_RSTN_LIMIT_TYPE_MONTHLY] = info->monthly_limit;
2542 value.limit[STC_RSTN_LIMIT_TYPE_WEEKLY] = info->weekly_limit;
2543 value.limit[STC_RSTN_LIMIT_TYPE_DAILY] = info->daily_limit;
2544 value.month_start_date = info->month_start_date;
2545 value.month_start_ts = stc_time_get_month_start(time(NULL),
2546 info->month_start_date);
2548 ret = __rstn_tree_add(&key, &value, TRUE);
2552 FREE(key.subscriber_id);
2556 stc_error_e stc_monitor_rstns_tree_remove(const table_restrictions_info *info)
2560 stc_rstn_key_s key = {
2561 .app_id = g_strdup(info->app_id),
2562 .ifname = g_strdup(info->ifname),
2563 .subscriber_id = g_strdup(info->subscriber_id),
2564 .iftype = info->iftype,
2565 .roaming = info->roaming,
2568 if (!strcmp(key.app_id, STC_BACKGROUND_APP_ID)) {
2569 __set_background_state(FALSE); //LCOV_EXCL_LINE
2570 __vconf_set_int(VCONFKEY_STC_BACKGROUND_STATE, g_system->background_state); //LCOV_EXCL_LINE
2571 __process_update_background(); //LCOV_EXCL_LINE
2574 ret = __rstn_tree_remove(&key);
2578 FREE(key.subscriber_id);
2582 API stc_error_e stc_monitor_check_excn_by_cmdline(char *cmdline)
2584 return stc_plugin_check_exception_by_cmdline(cmdline);
2587 int stc_monitor_get_counter_socket(void)
2589 return g_system->contr_sock;