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 memset(&counter, 0, sizeof(struct nfacct_rule));
765 counter.carg = stc->carg;
766 counter.classid = classid;
767 counter.intend = intend;
769 if (connection && connection->tether_iface.ifname != NULL &&
770 classid == STC_TETHERING_APP_CLASSID) {
771 counter.iftype = connection->tether_iface.type;
772 g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
774 counter.iftype = iftype;
775 g_strlcpy(counter.ifname, default_ifname, MAX_IFACE_LENGTH);
778 g_free(default_ifname);
781 __add_iptables_in(&counter);
782 __add_iptables_out(&counter);
785 __add_ip6tables_in(&counter);
786 __add_ip6tables_out(&counter);
789 static void __del_iptables_rule(int64_t classid, nfacct_rule_intend intend,
790 stc_iface_type_e iftype)
792 char *default_ifname = stc_default_connection_get_ifname();
793 default_connection_s *connection = stc_get_default_connection();
794 struct nfacct_rule counter;
795 stc_s *stc = stc_get_manager();
797 g_free(default_ifname); //LCOV_EXCL_LINE
798 return; //LCOV_EXCL_LINE
802 stc->carg = MALLOC0(counter_arg_s, 1); //LCOV_EXCL_LINE
803 if (stc->carg == NULL) { //LCOV_EXCL_LINE
804 g_free(default_ifname); //LCOV_EXCL_LINE
805 return; //LCOV_EXCL_LINE
808 stc->carg->sock = stc_monitor_get_counter_socket(); //LCOV_EXCL_LINE
811 memset(&counter, 0, sizeof(struct nfacct_rule));
813 counter.carg = stc->carg;
814 counter.classid = classid;
815 counter.intend = intend;
817 if (connection && connection->tether_iface.ifname != NULL &&
818 classid == STC_TETHERING_APP_CLASSID) {
819 counter.iftype = connection->tether_iface.type;
820 g_strlcpy(counter.ifname, connection->tether_iface.ifname, MAX_IFACE_LENGTH);
822 counter.iftype = iftype;
823 g_strlcpy(counter.ifname, default_ifname, MAX_IFACE_LENGTH);
826 g_free(default_ifname);
829 __del_iptables_in(&counter);
830 __del_iptables_out(&counter);
833 __del_ip6tables_in(&counter);
834 __del_ip6tables_out(&counter);
837 static void __set_rstn_noti_state(int value)
839 int state = STC_RSTN_STATE_INIT;
841 if (__vconf_get_int(VCONFKEY_SETAPPL_DATA_RESTRICTION_INT, &state))
844 if (state == value) {
845 STC_LOGI("No need to change a restriction status: %d", state);
849 vconf_set_int(VCONFKEY_SETAPPL_DATA_RESTRICTION_INT, value);
854 time_t month_start_ts;
855 time_t week_start_ts;
857 int64_t monthly_stat;
862 static stc_cb_ret_e __statistics_info_cb(const table_statistics_info *info,
865 cumulative_data_s *stat = (cumulative_data_s *)user_data;
866 int64_t counters = 0;
868 counters = info->cnt.in_bytes + info->cnt.out_bytes;
870 stat->monthly_stat += counters;
871 if (stat->week_start_ts <= info->interval->from)
872 stat->weekly_stat += counters;
873 if (stat->day_start_ts <= info->interval->from)
874 stat->daily_stat += counters;
879 static void __process_restriction(enum traffic_restriction_type rstn_type,
880 stc_rstn_key_s *rstn_key,
881 stc_rstn_value_s *rstn_value, void *data)
883 default_connection_s *old_connection = (default_connection_s *)data;
884 default_connection_s *connection = NULL;
886 if (old_connection != NULL)
887 connection = old_connection;
889 connection = stc_get_default_connection();
891 /* no default ifname */
892 if (connection->ifname == NULL)
895 /* rstn not applicable for this interface */
896 if (rstn_key->ifname != NULL && g_strcmp0("", rstn_key->ifname) != 0 &&
897 (g_strcmp0(connection->ifname, rstn_key->ifname) != 0) &&
898 (g_strcmp0(connection->tether_iface.ifname, rstn_key->ifname) != 0))
901 /* classid is invalid */
902 if (rstn_value->classid <= STC_UNKNOWN_CLASSID)
909 table_counters_info info;
910 int64_t effective_limit[STC_RSTN_LIMIT_TYPE_MAX] = { 0, };
912 memset(&info, 0, sizeof(table_counters_info));
913 rstn_value->limit_exceeded = 0;
915 if ((rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 &&
916 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) ||
917 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 &&
918 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) ||
919 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 &&
920 rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) ||
921 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 &&
922 rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) ||
923 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 &&
924 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) {
925 table_counters_get(rstn_value->restriction_id, &info);
927 time_t current_time = 0;
928 cumulative_data_s stat;
929 table_statistics_select_rule rule;
931 memset(&stat, 0, sizeof(cumulative_data_s));
932 stat.month_start_ts = rstn_value->month_start_ts;
933 stat.week_start_ts = g_system->last_week_ts;
934 stat.day_start_ts = g_system->last_day_ts;
936 memset(&rule, 0, sizeof(table_statistics_select_rule));
937 rule.from = rstn_value->month_start_ts;
939 rule.to = current_time;
940 rule.iftype = rstn_key->iftype;
941 rule.granularity = GRANULARITY;
943 table_statistics_per_app(rstn_key->app_id, &rule, __statistics_info_cb, &stat);
945 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter;
946 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter;
947 rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter + stat.monthly_stat;
948 rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter + stat.weekly_stat;
949 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter + stat.daily_stat;
952 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
953 if (rstn_value->limit[i] >= 0) {
954 effective_limit[i] = rstn_value->limit[i] - rstn_value->counter[i];
956 if (effective_limit[i] < 0)
957 rstn_value->limit_exceeded |= (1 << i);
961 STC_LOGD("rstn_id [%llu], datausage [%llu] bytes",
962 rstn_value->restriction_id, info.data_counter);
964 if (rstn_value->limit_exceeded != 0 &&
965 rstn_value->limit_exceeded != (1 << STC_RSTN_LIMIT_TYPE_DATA_WARN)) {
966 __add_iptables_rule(rstn_value->classid, NFACCT_BLOCK, rstn_key->iftype);
969 rstn_value->rstn_state = STC_RSTN_STATE_ACTIVATED;
973 __add_iptables_rule(rstn_value->classid, NFACCT_ALLOW,
976 rstn_value->rstn_state = STC_RSTN_STATE_ACTIVATED;
977 rstn_value->limit_exceeded = 0;
978 rstn_value->limit_notified = 0;
984 if (rstn_value->classid == STC_TETHERING_APP_CLASSID)
985 __del_iptables_rule(rstn_value->classid, NFACCT_BLOCK,
988 __del_iptables_rule(rstn_value->classid, rstn_value->rstn_type,
991 rstn_value->rstn_state = STC_RSTN_STATE_DEACTIVATED;
992 rstn_value->limit_exceeded = 0;
993 rstn_value->limit_notified = 0;
995 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++)
996 if (rstn_value->limit[i] >= 0)
997 rstn_value->counter[i] = 0;
999 __set_rstn_noti_state(STC_RSTN_STATE_UNSET);
1008 static gboolean __remove_rstns_foreach_application(gpointer key,
1012 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1013 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1014 gchar *app_id = (gchar *)data;
1016 /* rstn rule is not for applications */
1017 if (rstn_key->app_id == NULL)
1020 /* rstn rule is not for this application */
1021 if (g_strcmp0(rstn_key->app_id, app_id) != 0)
1024 /* rstn rule is already removed */
1025 if (rstn_value->rstn_state == STC_RSTN_STATE_DEACTIVATED)
1028 /* remove restriction from system */
1029 __process_restriction(RST_UNSET, rstn_key, rstn_value, NULL);
1031 __print_rstn(rstn_key, rstn_value);
1037 static void __remove_rstns_for_application(gchar *app_id)
1039 g_tree_foreach(g_system->rstns, __remove_rstns_foreach_application,
1043 static stc_error_e __application_remove_if_empty(const stc_app_key_s *app_key)
1045 stc_error_e ret = STC_ERROR_NONE;
1046 guint pid_count = 0;
1047 stc_app_value_s *lookup;
1049 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
1051 lookup = __application_lookup(g_system->apps, app_key);
1053 STC_LOGE("app_key not found"); //LCOV_EXCL_LINE
1054 return STC_ERROR_NO_DATA; //LCOV_EXCL_LINE
1057 g_tree_foreach(lookup->processes, __processes_tree_check_empty,
1061 /* remove nfacct rule for this classid */
1062 __remove_application_monitor((gpointer) app_key, lookup,
1063 stc_get_default_connection());
1064 __remove_rstns_for_application(app_key->app_id);
1067 if (!g_tree_remove(g_system->apps, app_key)) {
1068 ret = STC_ERROR_NO_DATA; //LCOV_EXCL_LINE
1069 STC_LOGE("key not found"); //LCOV_EXCL_LINE
1075 static stc_error_e __close_contr_sock(stc_system_s *system)
1077 ret_value_msg_if(system == NULL, STC_ERROR_INVALID_PARAMETER, "invalid parameter");
1079 /* close netlink socket for updating kernel counters */
1080 if (system->contr_sock != -1) {
1081 close(system->contr_sock);
1082 system->contr_sock = -1;
1085 if (system->contr_gsource_id != 0) {
1086 g_source_remove(system->contr_gsource_id);
1087 system->contr_gsource_id = 0;
1090 return STC_ERROR_NONE;
1093 static gboolean __process_contr_reply(GIOChannel *source,
1094 GIOCondition condition,
1095 gpointer user_data);
1098 static stc_error_e __close_and_reopen_contr_sock(stc_system_s *system)
1100 GIOChannel *gio = NULL;
1101 ret_value_msg_if(system == NULL, STC_ERROR_INVALID_PARAMETER, "invalid parameter");
1103 /* close netlink socket for updating kernel counters */
1104 if (system->contr_sock != -1) {
1105 close(system->contr_sock);
1106 system->contr_sock = -1;
1109 if (system->contr_gsource_id != 0) {
1110 g_source_remove(system->contr_gsource_id);
1111 system->contr_gsource_id = 0;
1114 /* create netlink socket for updating kernel counters */
1115 system->contr_sock = create_netlink(NETLINK_NETFILTER, 0);
1116 if (system->contr_sock < 0) {
1117 STC_LOGE("failed to open socket");
1119 return STC_ERROR_FAIL;
1122 gio = g_io_channel_unix_new(system->contr_sock);
1123 system->contr_gsource_id =
1124 g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP,
1125 (GIOFunc) __process_contr_reply,
1127 g_io_channel_unref(gio);
1129 return STC_ERROR_NONE;
1132 static void __action_when_rstn_limit_exceeded(stc_rstn_limit_type_e limit_type,
1133 stc_rstn_key_s *rstn_key,
1134 stc_rstn_value_s *rstn_value,
1135 classid_bytes_context_s *context)
1138 char iftype[MAX_INT_LENGTH] = { 0, };
1139 char byte[MAX_INT_LENGTH] = { 0, };
1140 const char *signal_name = NULL;
1141 const char *net_popup_content = NULL;
1142 const char *net_popup_type = NULL;
1143 stc_s *stc = (stc_s *)stc_get_manager();
1146 STC_LOGE("Failed to get stc data");
1150 switch (limit_type) {
1151 case STC_RSTN_LIMIT_TYPE_DATA_WARN:
1153 signal_name = "WarnThresholdCrossed";
1154 net_popup_content = "warn threshold crossed";
1155 net_popup_type = "warning_noti";
1158 case STC_RSTN_LIMIT_TYPE_DATA:
1159 case STC_RSTN_LIMIT_TYPE_MONTHLY:
1160 case STC_RSTN_LIMIT_TYPE_WEEKLY:
1161 case STC_RSTN_LIMIT_TYPE_DAILY:
1163 signal_name = "RestrictionThresholdCrossed";
1164 net_popup_content = "restriction threshold crossed";
1165 net_popup_type = "restriction_noti";
1167 /* block immediately */
1168 context->counter->intend = NFACCT_BLOCK;
1169 __del_iptables_in(context->counter);
1170 __del_iptables_out(context->counter);
1171 __add_iptables_in(context->counter);
1172 __add_iptables_out(context->counter);
1174 __del_ip6tables_in(context->counter);
1175 __del_ip6tables_out(context->counter);
1176 __add_ip6tables_in(context->counter);
1177 __add_ip6tables_out(context->counter);
1178 context->counter->intend = NFACCT_COUNTER;
1180 rstn_value->limit_exceeded |= (1 << limit_type);
1182 __set_rstn_noti_state(STC_RSTN_STATE_SET);
1189 if (signal_name == NULL) {
1190 STC_LOGE("Invalid parameter: limit_type");
1195 rv = stc_manager_dbus_emit_signal(stc->connection,
1196 STC_DBUS_SERVICE_RESTRICTION_PATH,
1197 STC_DBUS_INTERFACE_RESTRICTION,
1199 g_variant_new("(si)",
1204 rstn_value->limit_notified |= (1 << limit_type);
1206 snprintf(iftype, MAX_INT_LENGTH, "%d", rstn_key->iftype);
1207 snprintf(byte, MAX_INT_LENGTH, "%lld", rstn_value->limit[limit_type]);
1208 stc_plugin_appstatus_send_message(net_popup_content,
1209 net_popup_type, rstn_key->app_id, iftype, byte);
1212 static gboolean __rstn_counter_update(stc_rstn_key_s *rstn_key,
1213 stc_rstn_value_s *rstn_value,
1214 classid_bytes_context_s *context)
1217 switch (context->counter->iotype) {
1218 case NFACCT_COUNTER_IN:
1219 case NFACCT_COUNTER_OUT:
1220 if ((rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 &&
1221 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) ||
1222 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 &&
1223 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) ||
1224 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 &&
1225 rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) ||
1226 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 &&
1227 rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) ||
1228 (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 &&
1229 rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) {
1230 table_counters_info info;
1231 memset(&info, 0, sizeof(table_counters_info));
1232 table_counters_get(rstn_value->restriction_id, &info);
1234 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter;
1235 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter;
1236 rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter;
1237 rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter;
1238 rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter;
1241 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
1242 if (rstn_value->limit[i] >= 0 &&
1243 !(rstn_value->limit_notified & (1 << i))) {
1244 rstn_value->counter[i] += context->bytes;
1245 if (rstn_value->limit[i] <= rstn_value->counter[i])
1246 __action_when_rstn_limit_exceeded(i,
1253 g_system->rstns_tree_updated = TRUE;
1254 __print_rstn(rstn_key, rstn_value);
1257 STC_LOGE("unknown iotype");
1263 static gboolean __interface_rstn_counter_update(stc_rstn_key_s *rstn_key,
1264 stc_rstn_value_s *rstn_value,
1265 classid_bytes_context_s *context)
1267 if ((rstn_value->classid == STC_TOTAL_DATACALL_CLASSID &&
1268 context->counter->iftype == STC_IFACE_DATACALL) ||
1269 (rstn_value->classid == STC_TOTAL_WIFI_CLASSID &&
1270 context->counter->iftype == STC_IFACE_WIFI) ||
1271 (rstn_value->classid == STC_TOTAL_BLUETOOTH_CLASSID &&
1272 context->counter->iftype == STC_IFACE_BLUETOOTH) ||
1273 (rstn_value->classid == STC_TETHERING_APP_CLASSID &&
1274 context->counter->iftype == STC_IFACE_WIFI) ||
1275 (rstn_value->classid == STC_TETHERING_APP_CLASSID &&
1276 context->counter->iftype == STC_IFACE_BLUETOOTH) ||
1277 (rstn_value->classid == STC_TETHERING_APP_CLASSID &&
1278 context->counter->iftype == STC_IFACE_USB) ||
1279 (rstn_value->classid == STC_TETHERING_APP_CLASSID &&
1280 context->counter->iftype == STC_IFACE_P2P)) {
1281 context->counter->classid = rstn_value->classid;
1282 return __rstn_counter_update(rstn_key, rstn_value, context);
1288 static gboolean __rstn_counter_update_foreach_classid(gpointer key,
1292 gboolean rv = FALSE;
1293 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1294 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1295 classid_bytes_context_s *context = (classid_bytes_context_s *)data;
1298 if (context->counter->intend != NFACCT_COUNTER &&
1299 context->counter->intend != NFACCT_TETH_COUNTER)
1300 goto try_next_callback;
1302 if (rstn_value->limit_exceeded == TRUE) {
1303 context->data_limit_exceeded = TRUE; //LCOV_EXCL_LINE
1304 goto try_next_callback; //LCOV_EXCL_LINE
1307 classid = context->counter->classid;
1308 rv = __interface_rstn_counter_update(rstn_key, rstn_value, context);
1310 context->counter->classid = classid;
1311 if (rstn_value->classid != context->counter->classid)
1312 goto try_next_callback;
1314 rv = __rstn_counter_update(rstn_key, rstn_value, context);
1321 static gboolean __update_app_statistics(gpointer key, gpointer value,
1324 stc_app_key_s *app_key = (stc_app_key_s *)key;
1325 stc_app_value_s *app_value = (stc_app_value_s *)value;
1326 time_t *touch_time = (time_t *)data;
1327 stc_db_classid_iftype_key stat_key;
1328 stc_db_app_stats stat;
1329 default_connection_s *default_connection = stc_get_default_connection();
1331 memset(&stat_key, 0, sizeof(stc_db_classid_iftype_key));
1332 memset(&stat, 0 , sizeof(stc_db_app_stats));
1334 /* Do not update statistics for Tethering
1335 * if tethering is in-active found */
1336 if (default_connection &&
1337 default_connection->tether_state == FALSE &&
1338 !strcmp(app_key->app_id, STC_TOTAL_TETHERING))
1341 /* Do not update statistics for Wi-Fi
1342 * if tethering is active on wlan0 iface */
1343 if (default_connection && default_connection->tether_state &&
1344 default_connection->tether_iface.type == STC_IFACE_WIFI &&
1345 !strcmp(app_key->app_id, STC_TOTAL_WIFI))
1348 stat_key.classid = app_value->classid;
1350 if (app_value->classid == STC_TETHERING_APP_CLASSID &&
1351 default_connection->tether_state == TRUE)
1352 stat_key.iftype = default_connection->tether_iface.type;
1353 else if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX))
1354 stat_key.iftype = default_connection->tether_iface.type;
1356 stat_key.iftype = default_connection->type;
1358 if (STC_IFACE_DATACALL == stat_key.iftype)
1359 stat_key.subscriber_id = g_strdup(default_connection->subscriber_id);
1361 stat_key.subscriber_id = g_strdup("none_subid"); //LCOV_EXCL_LINE
1363 if (app_value->classid == STC_TETHERING_APP_CLASSID &&
1364 default_connection->tether_state == TRUE)
1365 g_strlcpy(stat_key.ifname, default_connection->tether_iface.ifname,
1367 else if (g_str_has_suffix(app_key->app_id, STC_TETHERING_APP_SUFFIX))
1368 g_strlcpy(stat_key.ifname, default_connection->tether_iface.ifname,
1371 g_strlcpy(stat_key.ifname, default_connection->ifname,
1374 stat.app_id = g_strdup(app_key->app_id);
1375 stat.snd_count = app_value->counter.out_bytes;
1376 stat.rcv_count = app_value->counter.in_bytes;
1377 stat.is_roaming = default_connection->roaming;
1379 if (strstr(stat.app_id, "_BACKGROUND")) {
1380 stat.ground = STC_APP_STATE_BACKGROUND;
1382 if (strstr(stat.app_id, "TOTAL_"))
1383 stat.ground = STC_APP_STATE_UNKNOWN;
1385 stat.ground = STC_APP_STATE_FOREGROUND;
1388 table_statistics_insert(&stat_key, &stat, *touch_time);
1390 app_value->counter.out_bytes = 0;
1391 app_value->counter.in_bytes = 0;
1394 FREE(stat_key.subscriber_id);
1399 static gboolean __flush_apps_stats_to_database(gpointer user_data)
1401 time_t current_time = 0;
1402 stc_s *stc = stc_get_manager();
1404 if (stc && stc->carg)
1405 current_time = stc->carg->last_run_time;
1407 if (g_system->apps_tree_updated == FALSE)
1408 return G_SOURCE_REMOVE;
1410 g_system->apps_tree_updated = FALSE;
1413 g_tree_foreach(g_system->apps,
1414 __update_app_statistics,
1417 STC_LOGI("Flushed app stats to database");
1418 return G_SOURCE_REMOVE;
1422 static gboolean __update_counter_statistics(gpointer key, gpointer value,
1425 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1426 table_counters_info info = {
1427 .restriction_id = rstn_value->restriction_id,
1428 .data_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA],
1429 .warn_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN],
1430 .monthly_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY],
1431 .weekly_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY],
1432 .daily_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY]
1435 table_counters_update_counters(&info);
1440 static gboolean __flush_rstns_counter_to_database(gpointer user_data)
1442 time_t current_time = 0;
1443 stc_s *stc = stc_get_manager();
1445 if (stc && stc->carg)
1446 current_time = stc->carg->last_run_time;
1448 if (g_system->rstns_tree_updated == FALSE)
1449 return G_SOURCE_REMOVE;
1451 g_system->rstns_tree_updated = FALSE;
1453 if (g_system->rstns)
1454 g_tree_foreach(g_system->rstns,
1455 __update_counter_statistics,
1458 STC_LOGI("Flushed rstns counters to database");
1459 return G_SOURCE_REMOVE;
1463 static void __app_counter_update(stc_app_key_s *app_key,
1464 stc_app_value_s *app_value,
1465 classid_bytes_context_s *context)
1467 switch (context->counter->iotype) {
1468 case NFACCT_COUNTER_IN:
1469 app_value->data_usage.in_bytes += context->bytes;
1470 app_value->counter.in_bytes = context->bytes;
1471 g_system->apps_tree_updated = TRUE;
1474 __apps_tree_foreach_print(app_key, app_value, NULL); //LCOV_EXCL_LINE
1477 case NFACCT_COUNTER_OUT:
1478 app_value->data_usage.out_bytes += context->bytes;
1479 app_value->counter.out_bytes = context->bytes;
1480 g_system->apps_tree_updated = TRUE;
1483 __apps_tree_foreach_print(app_key, app_value, NULL); //LCOV_EXCL_LINE
1487 STC_LOGE("unknown iotype"); //LCOV_EXCL_LINE
1491 static void __interface_counter_update(stc_app_key_s *app_key,
1492 stc_app_value_s *app_value,
1493 classid_bytes_context_s *context)
1495 if ((app_value->classid == STC_TOTAL_DATACALL_CLASSID &&
1496 context->counter->iftype == STC_IFACE_DATACALL) ||
1497 (app_value->classid == STC_TOTAL_WIFI_CLASSID &&
1498 context->counter->iftype == STC_IFACE_WIFI) ||
1499 (app_value->classid == STC_TOTAL_BLUETOOTH_CLASSID &&
1500 context->counter->iftype == STC_IFACE_BLUETOOTH) ||
1501 (app_value->classid == STC_TETHERING_APP_CLASSID &&
1502 context->counter->iftype == STC_IFACE_WIFI) ||
1503 (app_value->classid == STC_TETHERING_APP_CLASSID &&
1504 context->counter->iftype == STC_IFACE_BLUETOOTH) ||
1505 (app_value->classid == STC_TETHERING_APP_CLASSID &&
1506 context->counter->iftype == STC_IFACE_USB) ||
1507 (app_value->classid == STC_TETHERING_APP_CLASSID &&
1508 context->counter->iftype == STC_IFACE_P2P))
1509 __app_counter_update(app_key, app_value, context);
1513 static gboolean __apps_counter_update_foreach_classid(gpointer key,
1517 stc_app_key_s *app_key = (stc_app_key_s *)key;
1518 stc_app_value_s *app_value = (stc_app_value_s *)value;
1519 classid_bytes_context_s *context = (classid_bytes_context_s *)data;
1521 if (context->counter->intend != NFACCT_COUNTER &&
1522 context->counter->intend != NFACCT_TETH_COUNTER)
1523 goto try_next_callback;
1525 __interface_counter_update(app_key, app_value, context);
1527 if (app_value->classid != context->counter->classid)
1528 goto try_next_callback;
1530 __app_counter_update(app_key, app_value, context);
1536 static gboolean __reset_time_counter_foreach_rstn(gpointer key,
1540 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1541 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1542 reset_time_limits_context_s *context = (reset_time_limits_context_s *)data;
1544 time_t now_month_start_ts;
1546 if (rstn_value->month_start_date == 0) {
1547 table_counters_info info;
1548 memset(&info, 0, sizeof(table_counters_info));
1549 table_counters_get_timestamps(rstn_value->restriction_id, &info);
1551 if (info.month_start_date == 0)
1552 rstn_value->month_start_date = 1;
1554 rstn_value->month_start_date = info.month_start_date;
1555 rstn_value->month_start_ts = info.month_start_ts;
1558 now_month_start_ts =
1559 stc_time_get_month_start(context->now,
1560 rstn_value->month_start_date);
1562 if (rstn_value->month_start_ts != now_month_start_ts) {
1563 rstn_value->month_start_ts = now_month_start_ts;
1564 context->month_start_ts = now_month_start_ts;
1565 context->is_updated |= (1 << STC_RSTN_LIMIT_TYPE_MONTHLY);
1568 if (context->is_updated) {
1569 table_counters_info info;
1570 memset(&info, 0, sizeof(table_counters_info));
1572 info.restriction_id = rstn_value->restriction_id;
1573 info.month_start_date = rstn_value->month_start_date;
1574 info.month_start_ts = rstn_value->month_start_ts;
1575 info.week_start_ts = context->week_start_ts;
1576 info.day_start_ts = context->day_start_ts;
1578 table_counters_update_timestamps(&info);
1581 for (i = STC_RSTN_LIMIT_TYPE_MONTHLY; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
1583 if ((context->is_updated) & (1 << i)) {
1585 rstn_value->counter[i] = 0;
1587 if (rstn_value->limit_exceeded & (1 << i)) {
1588 /* remove iptables rule */
1589 char *default_ifname = stc_default_connection_get_ifname();
1590 struct nfacct_rule counter;
1591 stc_s *stc = stc_get_manager();
1593 STC_LOGE("Can't get stc data");
1594 g_free(default_ifname);
1595 goto try_next_callback;
1599 stc->carg = MALLOC0(counter_arg_s, 1);
1600 if (stc->carg == NULL) {
1601 g_free(default_ifname);
1602 goto try_next_callback;
1606 stc_monitor_get_counter_socket();
1609 memset(&counter, 0, sizeof(struct nfacct_rule));
1611 counter.carg = stc->carg;
1612 counter.classid = rstn_value->classid;
1613 counter.intend = NFACCT_BLOCK;
1614 counter.iftype = rstn_key->iftype;
1615 g_strlcpy(counter.ifname, default_ifname,
1618 g_free(default_ifname);
1621 __del_iptables_in(&counter);
1622 __del_iptables_out(&counter);
1624 /* ip6tables rule */
1625 __del_ip6tables_in(&counter);
1626 __del_ip6tables_out(&counter);
1628 rstn_value->rstn_state = STC_RSTN_STATE_DEACTIVATED;
1629 rstn_value->limit_exceeded &= ~(1 << i);
1630 rstn_value->limit_notified &= ~(1 << i);
1639 static void __reset_time_counters_if_required(void)
1641 reset_time_limits_context_s context;
1643 if (g_system == NULL) {
1644 STC_LOGE("stc monitor not initialized!");
1648 context.now = time(NULL);
1649 context.week_start_ts = stc_time_get_week_start(context.now);
1650 context.day_start_ts = stc_time_get_day_start(context.now);
1651 context.is_updated = 0;
1653 if (g_system->last_week_ts != context.week_start_ts) {
1654 g_system->last_week_ts = context.week_start_ts;
1655 context.is_updated |= (1 << STC_RSTN_LIMIT_TYPE_WEEKLY);
1658 if (g_system->last_day_ts != context.day_start_ts) {
1659 g_system->last_day_ts = context.day_start_ts;
1660 context.is_updated |= (1 << STC_RSTN_LIMIT_TYPE_DAILY);
1663 if (g_system->rstns) {
1664 g_tree_foreach(g_system->rstns,
1665 __reset_time_counter_foreach_rstn,
1667 if (context.is_updated)
1668 STC_LOGD("Counter reset completed month_start [%ld], week_start [%ld], day_start [%ld]",
1669 context.month_start_ts, g_system->last_week_ts, g_system->last_day_ts);
1673 static void __fill_nfacct_result(char *cnt_name, int64_t bytes,
1674 struct counter_arg *carg)
1676 __reset_time_counters_if_required();
1678 struct nfacct_rule counter = {
1685 classid_bytes_context_s context = {
1686 .counter = &counter,
1688 .data_limit_exceeded = FALSE,
1691 if (!recreate_counter_by_name(cnt_name, &counter)) {
1692 STC_LOGE("Can't parse counter name %s", cnt_name); //LCOV_EXCL_LINE
1693 return; //LCOV_EXCL_LINE
1697 STC_LOGI("classid %u, iftype %u, iotype %d, intend %d, ifname %s, bytes %lld",
1698 context.counter->classid, context.counter->iftype,
1699 context.counter->iotype, context.counter->intend,
1700 context.counter->ifname, context.bytes);
1702 if (g_system->rstns)
1703 g_tree_foreach(g_system->rstns,
1704 __rstn_counter_update_foreach_classid,
1708 g_tree_foreach(g_system->apps,
1709 __apps_counter_update_foreach_classid,
1713 static int __fill_counters(struct rtattr *attr_list[__NFACCT_MAX],
1716 struct counter_arg *carg = user_data;
1717 char *cnt_name = (char *)RTA_DATA(attr_list[NFACCT_NAME]);
1718 if (carg->initiate) {
1720 * TODO: this will be used when daemon starts to update existing
1721 * counter data if present.
1723 populate_counters(cnt_name, carg);
1727 (int64_t *)RTA_DATA(attr_list[NFACCT_BYTES]);
1728 int bytes = be64toh(*bytes_p);
1730 ++carg->serialized_counters;
1731 __fill_nfacct_result(cnt_name, bytes, carg);
1738 static int __post_fill_counters(void *user_data)
1740 struct counter_arg *carg = user_data;
1748 static void __process_network_counter(struct genl *ans,
1749 struct counter_arg *carg)
1751 struct netlink_serialization_params ser_params = {
1754 .eval_attr = __fill_counters,
1755 .post_eval_attr = __post_fill_counters,
1758 netlink_serialization_command *netlink =
1759 netlink_create_command(&ser_params);
1761 STC_LOGE("Can not create command"); //LCOV_EXCL_LINE
1762 return; //LCOV_EXCL_LINE
1765 netlink->deserialize_answer(&(netlink->params));
1768 static gboolean __process_contr_reply(GIOChannel *source,
1769 GIOCondition condition,
1772 int sock = g_io_channel_unix_get_fd(source);
1775 stc_s *stc = stc_get_manager();
1778 void __gcov_flush(void);
1782 if ((condition & G_IO_ERR) || (condition & G_IO_HUP) ||
1783 (condition & G_IO_NVAL)) {
1784 /* G_IO_ERR/G_IO_HUP/G_IO_NVAL received */
1786 STC_LOGE("Counter socket received G_IO event, closing socket." //LCOV_EXCL_LINE
1787 "G_IO_ERR [%u], G_IO_HUP [%u], G_IO_NVAL [%u]",
1788 (condition & G_IO_ERR), (condition & G_IO_HUP),
1789 (condition & G_IO_NVAL));
1790 __close_and_reopen_contr_sock(g_system); //LCOV_EXCL_LINE
1791 return FALSE; //LCOV_EXCL_LINE
1794 ans = MALLOC0(struct genl, 1);
1796 STC_LOGE("Failed allocate memory to genl reply message"); //LCOV_EXCL_LINE
1797 return TRUE; //LCOV_EXCL_LINE
1801 STC_LOGE("Can't get stc data"); //LCOV_EXCL_LINE
1802 goto out; //LCOV_EXCL_LINE
1805 ret = read_netlink(sock, ans, sizeof(struct genl));
1806 /* STC_LOGD("Counter data received ret [%d]", ret); */
1810 stc->carg->ans_len = ret;
1811 stc->carg->last_run_time = time(NULL);
1813 __process_network_counter(ans, stc->carg);
1815 g_idle_add(__flush_apps_stats_to_database, NULL);
1816 g_idle_add(__flush_rstns_counter_to_database, NULL);
1823 static gboolean __update_contr_cb(void *user_data)
1825 /* Here we just sent command, answer we receive in another callback */
1826 stc_s *stc = stc_get_manager();
1827 ret_value_msg_if(stc == NULL, STC_ERROR_FAIL, "Can't get stc data");
1829 stc->carg = MALLOC0(counter_arg_s, 1);
1830 if (stc->carg == NULL)
1831 return TRUE; /* we need to continue the timer */
1833 stc->carg->sock = stc_monitor_get_counter_socket();
1837 void __gcov_flush(void);
1841 /* STC_LOGD("Get all counters"); */
1842 nfacct_send_get_all(stc->carg);
1844 /* we need to continue the timer */
1850 static gboolean __rstn_tree_foreach_print(gpointer key, gpointer value,
1853 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1854 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1856 __print_rstn(rstn_key, rstn_value);
1860 static void __rstn_tree_printall(void)
1862 g_tree_foreach(g_system->rstns, __rstn_tree_foreach_print, NULL);
1867 static stc_rstn_value_s * __rstn_lookup(GTree *rstns_tree,
1868 const stc_rstn_key_s *key)
1870 stc_rstn_value_s *lookup;
1872 ret_value_msg_if(rstns_tree == NULL, NULL, "rstns_tree is null!");
1874 lookup = g_tree_lookup(rstns_tree, key);
1879 static gboolean __remove_restriction(gpointer key, gpointer value,
1882 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1883 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1885 __process_restriction(RST_UNSET, rstn_key, rstn_value, data);
1886 __print_rstn(rstn_key, rstn_value);
1890 static gboolean __add_restriction_debug(gpointer key, gpointer value,
1893 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1894 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1896 /* rstn rule is activated */
1897 if (rstn_value->rstn_state == STC_RSTN_STATE_ACTIVATED)
1900 if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
1901 __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, data);
1903 __process_restriction(RST_SET, rstn_key, rstn_value, data);
1905 __print_rstn(rstn_key, rstn_value);
1911 static gboolean __add_restriction(gpointer key, gpointer value, gpointer data)
1913 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
1914 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
1916 /* rstn rule is activated */
1917 if (rstn_value->rstn_state == STC_RSTN_STATE_ACTIVATED)
1920 if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
1921 __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, data);
1923 __process_restriction(RST_SET, rstn_key, rstn_value, data);
1929 static stc_error_e __rstn_tree_remove(stc_rstn_key_s *key)
1931 stc_rstn_value_s *lookup_value;
1933 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
1935 lookup_value = __rstn_lookup(g_system->rstns, key);
1936 if (!lookup_value) {
1937 STC_LOGE("key not found"); //LCOV_EXCL_LINE
1938 return STC_ERROR_NO_DATA; //LCOV_EXCL_LINE
1941 /* remove counter also */
1942 table_counters_delete(lookup_value->restriction_id);
1943 __remove_restriction(key, lookup_value, NULL);
1945 if (!g_tree_remove(g_system->rstns, key)) {
1946 STC_LOGD("key not found"); //LCOV_EXCL_LINE
1947 return STC_ERROR_NO_DATA; //LCOV_EXCL_LINE
1950 return STC_ERROR_NONE;
1953 static stc_error_e __rstn_tree_add(stc_rstn_key_s *key,
1954 stc_rstn_value_s *value, gboolean debug)
1956 stc_rstn_key_s *rstn_key;
1957 stc_rstn_value_s *rstn_value;
1959 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
1961 rstn_value = __rstn_lookup(g_system->rstns, key);
1963 __rstn_tree_remove(key);
1965 rstn_key = MALLOC0(stc_rstn_key_s, 1);
1967 STC_LOGE("rstn_key allocation failed"); //LCOV_EXCL_LINE
1968 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
1971 rstn_value = MALLOC0(stc_rstn_value_s, 1);
1973 STC_LOGE("rstn_value allocation failed"); //LCOV_EXCL_LINE
1974 FREE(rstn_key); //LCOV_EXCL_LINE
1975 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
1978 rstn_key->app_id = g_strdup(key->app_id);
1979 rstn_key->ifname = g_strdup(key->ifname);
1980 rstn_key->subscriber_id = g_strdup(key->subscriber_id);
1981 rstn_key->iftype = key->iftype;
1982 rstn_key->roaming = key->roaming;
1984 g_tree_insert(g_system->rstns, rstn_key, rstn_value);
1986 rstn_value->restriction_id = value->restriction_id;
1987 rstn_value->rstn_state = value->rstn_state;
1988 rstn_value->rstn_type = value->rstn_type;
1989 rstn_value->classid = value->classid;
1992 for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) {
1993 rstn_value->limit[i] = value->limit[i];
1994 rstn_value->counter[i] = 0;
1997 rstn_value->limit_exceeded = 0;
1998 rstn_value->limit_notified = 0;
1999 rstn_value->month_start_date = value->month_start_date;
2000 rstn_value->month_start_ts = value->month_start_ts;
2003 __add_restriction_debug(key, rstn_value, NULL);
2005 __add_restriction(key, rstn_value, NULL);
2007 return STC_ERROR_NONE;
2011 static stc_cb_ret_e __insert_restriction_cb(const table_restrictions_info *info,
2014 stc_cb_ret_e ret = STC_CONTINUE;
2017 stc_rstn_value_s value;
2019 memset(&key, 0, sizeof(stc_rstn_key_s));
2020 memset(&value, 0, sizeof(stc_rstn_value_s));
2022 key.app_id = g_strdup(info->app_id);
2023 key.ifname = g_strdup(info->ifname);
2024 key.subscriber_id = g_strdup(info->subscriber_id);
2025 key.iftype = info->iftype;
2026 key.roaming = info->roaming;
2028 value.rstn_type = info->rstn_type;
2029 value.rstn_state = STC_RSTN_STATE_UNKNOWN;
2030 value.restriction_id = info->restriction_id;
2033 value.classid = get_classid_by_app_id(info->app_id, TRUE);
2035 value.classid = STC_UNKNOWN_CLASSID;
2037 value.limit[STC_RSTN_LIMIT_TYPE_DATA] = info->data_limit;
2038 value.limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info->data_warn_limit;
2039 value.limit[STC_RSTN_LIMIT_TYPE_MONTHLY] = info->monthly_limit;
2040 value.limit[STC_RSTN_LIMIT_TYPE_WEEKLY] = info->weekly_limit;
2041 value.limit[STC_RSTN_LIMIT_TYPE_DAILY] = info->daily_limit;
2043 if (__rstn_tree_add(&key, &value, FALSE) != STC_ERROR_NONE)
2048 FREE(key.subscriber_id);
2052 static void __fill_restritions_list(void)
2054 table_restrictions_foreach(__insert_restriction_cb, NULL);
2056 /* __rstn_tree_printall(); */
2059 static gboolean __add_rstn_foreach_application(gpointer key,
2063 stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key;
2064 stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value;
2065 gchar *app_id = (gchar *)data;
2067 /* rstn rule is not for applications */
2068 if (rstn_key->app_id == NULL)
2071 /* rstn rule is not for this application */
2072 if (g_strcmp0(rstn_key->app_id, app_id) != 0)
2075 /* rstn rule is already applied */
2076 if (rstn_value->rstn_state == STC_RSTN_STATE_ACTIVATED)
2079 /* add restriction to system */
2080 if (rstn_value->rstn_type == STC_RSTN_TYPE_ACCEPT)
2081 __process_restriction(RST_EXCLUDE, rstn_key, rstn_value, NULL);
2083 __process_restriction(RST_SET, rstn_key, rstn_value, NULL);
2085 __print_rstn(rstn_key, rstn_value);
2091 static void __add_rstns_for_application(gchar *app_id)
2093 g_tree_foreach(g_system->rstns, __add_rstn_foreach_application,
2097 static void __add_application_by_interface(const char *app_id)
2099 stc_app_key_s app_key;
2100 stc_app_value_s app_value;
2103 return; //LCOV_EXCL_LINE
2105 memset(&app_key, 0, sizeof(stc_app_key_s));
2106 memset(&app_value, 0, sizeof(stc_app_value_s));
2108 app_key.pkg_id = g_strdup(app_id);
2109 app_key.app_id = g_strdup(app_id);
2111 app_value.type = STC_APP_TYPE_NONE;
2112 app_value.processes = NULL;
2113 app_value.counter.in_bytes = 0;
2114 app_value.counter.out_bytes = 0;
2116 stc_monitor_application_add(app_key, app_value);
2118 FREE(app_key.pkg_id);
2119 FREE(app_key.app_id);
2122 static guint __get_background_state(void)
2124 return g_system->background_state;;
2127 static void __set_background_state(guint state)
2129 g_system->background_state = state;
2132 static gboolean __processes_tree_foreach_background(gpointer key,
2136 stc_process_key_s *proc_key = (stc_process_key_s *)key;
2137 stc_app_key_s *app_key = (stc_app_key_s *)data;
2139 if (g_system->background_state)
2140 place_pids_to_net_cgroup(proc_key->pid, STC_BACKGROUND_APP_ID);
2142 place_pids_to_net_cgroup(proc_key->pid, app_key->app_id);
2147 static gboolean __apps_tree_foreach_background(gpointer key, gpointer value,
2150 stc_app_key_s *app_key = (stc_app_key_s *)key;
2151 stc_app_value_s *app_value = (stc_app_value_s *)value;
2153 if (strstr(app_key->app_id, STC_BACKGROUND_APP_SUFFIX))
2154 g_tree_foreach(app_value->processes,
2155 __processes_tree_foreach_background, app_key);
2160 static stc_error_e __process_update_background(void)
2162 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2164 g_tree_foreach(g_system->apps, __apps_tree_foreach_background, NULL);
2166 return STC_ERROR_NONE;
2170 static void __fill_exceptions_list(void)
2172 stc_plugin_fill_exception_list();
2175 stc_error_e stc_monitor_init(void)
2177 stc_system_s *system = MALLOC0(stc_system_s, 1);
2178 GIOChannel *gio = NULL;
2180 ret_value_msg_if(system == NULL, STC_ERROR_OUT_OF_MEMORY, "stc_system_s malloc fail!");
2182 /* initializing current classid */
2183 init_current_classid();
2185 /* initializing cgroups */
2188 /* creating monitored application tree */
2189 system->apps = g_tree_new_full(__apps_tree_key_compare, NULL,
2190 __apps_tree_key_free,
2191 __apps_tree_value_free);
2193 system->rstns = g_tree_new_full(__rstns_tree_key_compare, NULL,
2194 __rstns_tree_key_free,
2195 __rstns_tree_value_free);
2197 /* create netlink socket for updating kernel counters */
2198 system->contr_sock = create_netlink(NETLINK_NETFILTER, 0);
2199 if (system->contr_sock < 0) {
2200 STC_LOGE("failed to open socket"); //LCOV_EXCL_LINE
2201 FREE(system); //LCOV_EXCL_LINE
2202 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
2205 gio = g_io_channel_unix_new(system->contr_sock);
2206 system->contr_gsource_id =
2207 g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP,
2208 (GIOFunc) __process_contr_reply,
2210 g_io_channel_unref(gio);
2214 __add_application_by_interface(STC_TOTAL_DATACALL);
2215 __add_application_by_interface(STC_TOTAL_WIFI);
2216 __add_application_by_interface(STC_TOTAL_BLUETOOTH);
2217 __add_application_by_interface(STC_TOTAL_IPV4);
2218 __add_application_by_interface(STC_TOTAL_IPV6);
2219 __add_application_by_interface(STC_TOTAL_TETHERING);
2221 /* creating restriction rules tree */
2222 __update_contr_cb(NULL);
2224 /* registering periodic kernel counters update callback */
2225 g_system->contr_timer_id = g_timeout_add_seconds(CONTR_TIMER_INTERVAL,
2228 if (g_system->contr_timer_id == 0) {
2229 STC_LOGE("Failed to register kernel counters update timer"); //LCOV_EXCL_LINE
2230 __close_contr_sock(g_system); //LCOV_EXCL_LINE
2231 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
2234 __vconf_get_int(VCONFKEY_STC_BACKGROUND_STATE,
2235 (int *)&g_system->background_state);
2237 __fill_exceptions_list();
2238 __fill_restritions_list();
2240 return STC_ERROR_NONE;
2243 stc_error_e stc_monitor_deinit(void)
2245 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2247 /* close netlink socket for updating kernel counters */
2248 __close_contr_sock(g_system);
2250 /* remove kernel counters update timer */
2251 if (g_system->contr_timer_id > 0) {
2252 g_source_remove(g_system->contr_timer_id);
2253 g_system->contr_timer_id = 0;
2256 /* destroy monitored application tree */
2257 g_tree_destroy(g_system->apps);
2258 g_system->apps = NULL;
2260 /* destroy restriction rules tree */
2261 g_tree_destroy(g_system->rstns);
2262 g_system->rstns = NULL;
2266 return STC_ERROR_NONE;
2269 API stc_error_e stc_monitor_application_add(const stc_app_key_s app_key,
2270 const stc_app_value_s app_value)
2272 stc_error_e ret = STC_ERROR_NONE;
2274 stc_app_value_s *value;
2275 stc_app_value_s *lookup;
2277 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2279 lookup = __application_lookup(g_system->apps, &app_key);
2281 return STC_ERROR_NONE; //LCOV_EXCL_LINE
2283 key = MALLOC0(stc_app_key_s, 1);
2285 STC_LOGE("key allocation failed"); //LCOV_EXCL_LINE
2286 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
2289 value = MALLOC0(stc_app_value_s, 1);
2291 STC_LOGE("value allocation failed"); //LCOV_EXCL_LINE
2292 FREE(key); //LCOV_EXCL_LINE
2293 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
2296 key->app_id = g_strdup(app_key.app_id);
2297 key->pkg_id = g_strdup(app_key.pkg_id);
2299 value->type = app_value.type;
2300 value->data_usage.in_bytes = app_value.data_usage.in_bytes;
2301 value->data_usage.out_bytes = app_value.data_usage.out_bytes;
2302 g_strlcpy(value->ipaddr, app_value.ipaddr, IPV4_IPADDRESS_LEN);
2304 value->processes = g_tree_new_full(__processes_tree_key_compare, NULL,
2305 __processes_tree_key_free,
2306 __processes_tree_value_free);
2308 /* create cgroup and update classid */
2309 value->classid = get_classid_by_app_id(app_key.app_id, TRUE);
2311 g_tree_insert(g_system->apps, key, value);
2313 /* add nfacct rule for this classid */
2314 __add_application_monitor(key, value, stc_get_default_connection());
2315 __add_rstns_for_application(app_key.app_id);
2320 API stc_error_e stc_monitor_application_remove(const stc_app_key_s app_key)
2322 stc_error_e ret = STC_ERROR_NONE;
2323 stc_app_value_s *app_lookup;
2325 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2327 app_lookup = __application_lookup(g_system->apps, &app_key);
2330 STC_LOGD("app_key not found"); //LCOV_EXCL_LINE
2331 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
2334 /* remove nfacct rule for this classid */
2335 __remove_application_monitor((gpointer) &app_key, app_lookup,
2336 stc_get_default_connection());
2338 /* remove ristrictions if any */
2339 __remove_rstns_for_application(app_key.app_id);
2341 /* remove app_key from the stc-manager */
2342 if (!g_tree_remove(g_system->apps, &app_key)) {
2343 ret = STC_ERROR_NO_DATA;
2344 STC_LOGE("key not found");
2350 API stc_error_e stc_monitor_process_add(const stc_app_key_s app_key,
2351 const stc_process_key_s proc_key,
2352 const stc_process_value_s proc_value)
2354 stc_error_e ret = STC_ERROR_NONE;
2355 stc_app_value_s *app_lookup;
2356 stc_process_key_s *key;
2357 stc_process_value_s *value;
2358 stc_process_value_s *proc_lookup;
2360 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2362 app_lookup = __application_lookup(g_system->apps, &app_key);
2365 STC_LOGD("app_key not found"); //LCOV_EXCL_LINE
2366 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
2369 proc_lookup = __process_lookup(app_lookup->processes, &proc_key);
2371 return STC_ERROR_NONE; //LCOV_EXCL_LINE
2373 key = MALLOC0(stc_process_key_s, 1);
2375 STC_LOGE("key allocation failed"); //LCOV_EXCL_LINE
2376 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
2379 value = MALLOC0(stc_process_value_s, 1);
2381 STC_LOGE("value allocation failed"); //LCOV_EXCL_LINE
2382 FREE(key); //LCOV_EXCL_LINE
2383 return STC_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
2386 key->pid = proc_key.pid;
2388 value->ground = proc_value.ground;
2390 g_tree_insert(app_lookup->processes, key, value);
2392 /* add pid to application cgroup */
2393 place_pids_to_net_cgroup(proc_key.pid, app_key.app_id);
2396 __apps_tree_printall(); //LCOV_EXCL_LINE
2402 API stc_error_e stc_monitor_process_remove(pid_t pid)
2404 stc_error_e ret = STC_ERROR_NONE;
2405 stc_process_key_s proc_key = {
2409 remove_pid_context_s context = {
2411 .proc_key = &proc_key,
2412 .entry_removed = FALSE,
2415 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2417 g_tree_foreach(g_system->apps, __apps_tree_foreach_remove_pid,
2420 if (context.entry_removed)
2421 __application_remove_if_empty(context.app_key);
2424 __apps_tree_printall(); //LCOV_EXCL_LINE
2431 API stc_error_e stc_monitor_process_update_ground(const stc_app_key_s app_key,
2432 const stc_process_key_s proc_key,
2433 stc_app_state_e ground)
2435 stc_error_e ret = STC_ERROR_NONE;
2436 stc_app_value_s *app_lookup;
2437 stc_process_value_s *proc_lookup;
2439 ret_value_msg_if(g_system == NULL, STC_ERROR_FAIL, "stc monitor not initialized!");
2441 app_lookup = __application_lookup(g_system->apps, &app_key);
2443 STC_LOGD("app_key not found");
2444 return STC_ERROR_FAIL;
2447 proc_lookup = __process_lookup(app_lookup->processes, &proc_key);
2449 STC_LOGD("proc_key not found");
2450 return STC_ERROR_FAIL;
2453 if (proc_lookup->ground != ground)
2454 proc_lookup->ground = ground;
2456 if (ground == STC_APP_STATE_BACKGROUND && __get_background_state())
2457 place_pids_to_net_cgroup(proc_key.pid, STC_BACKGROUND_APP_ID);
2459 place_pids_to_net_cgroup(proc_key.pid, app_key.app_id);
2465 void stc_monitor_update_rstn_by_default_connection(void *data)
2467 static default_connection_s old_connection;
2468 default_connection_s *new_connection = (default_connection_s *)data;
2470 if (old_connection.path != NULL) {
2473 g_tree_foreach(g_system->apps,
2474 __remove_application_monitor,
2475 (gpointer)&old_connection);
2477 if (g_system->rstns)
2478 g_tree_foreach(g_system->rstns,
2479 __remove_restriction,
2480 (gpointer)&old_connection);
2482 iptables_flush_chains();
2486 FREE(old_connection.path);
2487 FREE(old_connection.ifname);
2488 FREE(old_connection.tether_iface.ifname);
2489 old_connection.type = 0;
2490 old_connection.roaming = 0;
2491 old_connection.tether_state = FALSE;
2492 old_connection.tether_iface.type = 0;
2494 if (new_connection != NULL && new_connection->path != NULL) {
2496 g_tree_foreach(g_system->apps,
2497 __add_application_monitor,
2498 (gpointer)new_connection);
2500 if (g_system->rstns)
2501 g_tree_foreach(g_system->rstns, __add_restriction,
2504 old_connection.path = g_strdup(new_connection->path);
2505 old_connection.ifname = g_strdup(new_connection->ifname);
2506 old_connection.tether_iface.ifname = g_strdup(new_connection->tether_iface.ifname);
2507 old_connection.type = new_connection->type;
2508 old_connection.roaming = new_connection->roaming;
2509 old_connection.tether_state = new_connection->tether_state;
2510 old_connection.tether_iface.type = new_connection->tether_iface.type;
2514 stc_error_e stc_monitor_rstns_tree_add(const table_restrictions_info *info)
2519 stc_rstn_value_s value;
2521 memset(&key, 0, sizeof(stc_rstn_key_s));
2522 memset(&value, 0, sizeof(stc_rstn_value_s));
2524 key.app_id = g_strdup(info->app_id);
2525 key.ifname = g_strdup(info->ifname);
2526 key.subscriber_id = g_strdup(info->subscriber_id);
2527 key.iftype = info->iftype;
2528 key.roaming = info->roaming;
2530 value.rstn_type = info->rstn_type;
2531 value.rstn_state = STC_RSTN_STATE_UNKNOWN;
2532 value.restriction_id = info->restriction_id;
2535 value.classid = get_classid_by_app_id(info->app_id, TRUE);
2537 value.classid = STC_UNKNOWN_CLASSID;
2539 if (value.classid == STC_BACKGROUND_APP_CLASSID) {
2540 __set_background_state(TRUE); //LCOV_EXCL_LINE
2541 __vconf_set_int(VCONFKEY_STC_BACKGROUND_STATE, g_system->background_state); //LCOV_EXCL_LINE
2542 __process_update_background(); //LCOV_EXCL_LINE
2545 value.limit[STC_RSTN_LIMIT_TYPE_DATA] = info->data_limit;
2546 value.limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info->data_warn_limit;
2547 value.limit[STC_RSTN_LIMIT_TYPE_MONTHLY] = info->monthly_limit;
2548 value.limit[STC_RSTN_LIMIT_TYPE_WEEKLY] = info->weekly_limit;
2549 value.limit[STC_RSTN_LIMIT_TYPE_DAILY] = info->daily_limit;
2550 value.month_start_date = info->month_start_date;
2551 value.month_start_ts = stc_time_get_month_start(time(NULL),
2552 info->month_start_date);
2554 ret = __rstn_tree_add(&key, &value, TRUE);
2558 FREE(key.subscriber_id);
2562 stc_error_e stc_monitor_rstns_tree_remove(const table_restrictions_info *info)
2566 stc_rstn_key_s key = {
2567 .app_id = g_strdup(info->app_id),
2568 .ifname = g_strdup(info->ifname),
2569 .subscriber_id = g_strdup(info->subscriber_id),
2570 .iftype = info->iftype,
2571 .roaming = info->roaming,
2574 if (!strcmp(key.app_id, STC_BACKGROUND_APP_ID)) {
2575 __set_background_state(FALSE); //LCOV_EXCL_LINE
2576 __vconf_set_int(VCONFKEY_STC_BACKGROUND_STATE, g_system->background_state); //LCOV_EXCL_LINE
2577 __process_update_background(); //LCOV_EXCL_LINE
2580 ret = __rstn_tree_remove(&key);
2584 FREE(key.subscriber_id);
2588 API stc_error_e stc_monitor_check_excn_by_cmdline(char *cmdline)
2590 return stc_plugin_check_exception_by_cmdline(cmdline);
2593 int stc_monitor_get_counter_socket(void)
2595 return g_system->contr_sock;