be12dd1fac46846fdb8ce01bbef1ab2ef6fcf748
[platform/core/connectivity/stc-manager.git] / src / monitor / stc-monitor-proc.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "stc-monitor.h"
18 #include "stc-monitor-proc.h"
19 #include "stc-connection.h"
20 #include "helper-net-cls.h"
21
22 static void __print_proc(gpointer key, gpointer value,
23                                 gpointer data)
24 {
25         stc_proc_value_s *proc_value = (stc_proc_value_s *)value;
26
27         STC_LOGD("pid[\033[1;33m%d\033[0;m] ground[%d]",
28                  proc_value->pid, proc_value->ground);
29 }
30
31 static void __print_proc_all(GHashTable *procs)
32 {
33         g_hash_table_foreach(procs, __print_proc, NULL);
34 }
35
36 static void __proc_remove_pid(gpointer key, gpointer value,
37                                 gpointer data)
38 {
39         stc_app_value_s *app_value = (stc_app_value_s *)value;
40         remove_pid_context_s *context = (remove_pid_context_s *)data;
41
42         if (!g_hash_table_remove(app_value->processes, GUINT_TO_POINTER(context->pid)))
43                 return;
44
45         if (STC_DEBUG_LOG && STC_STAT_LOG) {
46                 __print_proc_all(app_value->processes);
47                 STC_LOGD("\033[1;31mProcess removed\033[0;m "
48                         "[\033[1;33m%d\033[0;m]", context->pid);
49         }
50
51         context->entry_removed = TRUE;
52         context->app_value = app_value;
53 }
54
55 static void __proc_move_pid(gpointer key, gpointer value,
56                                 gpointer data)
57 {
58         stc_proc_value_s *from_value = (stc_proc_value_s *)value;
59         stc_app_value_s *to_app_value = (stc_app_value_s *)data;
60         stc_proc_value_s *to_value;
61
62         to_value = MALLOC0(stc_proc_value_s, 1);
63         if (!to_value)
64                 return;
65
66         to_value->pid = from_value->pid;
67         to_value->ground = to_app_value->state;
68
69         g_hash_table_insert(to_app_value->processes,
70                         GUINT_TO_POINTER(to_value->pid),
71                         to_value);
72
73         /* add pid to application cgroup */
74         place_pids_to_net_cgroup(to_value->pid, to_app_value->app_id);
75 }
76
77 API stc_error_e stc_monitor_proc_update_ground(uint32_t classid,
78                                                 const char *app_id,
79                                                 const stc_proc_value_s value)
80 {
81         stc_error_e ret = STC_ERROR_NONE;
82         stc_app_value_s *app_lookup;
83         stc_proc_value_s *proc_lookup;
84         GHashTable *apps = stc_monitor_get_system_apps();
85
86         if (!apps)
87                 return STC_ERROR_NO_DATA;
88
89         if (classid == STC_UNKNOWN_CLASSID)
90                 classid = get_classid_by_app_id(app_id, TRUE);
91
92         app_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
93         if (!app_lookup) {
94                 if (STC_DEBUG_LOG && STC_STAT_LOG)
95                         STC_LOGD("Application not found [\033[1;36m%d\033[0;m]", classid);
96                 return STC_ERROR_NO_DATA;
97         }
98
99         proc_lookup = g_hash_table_lookup(app_lookup->processes,
100                                         GUINT_TO_POINTER(value.pid));
101         if (!proc_lookup) {
102                 if (STC_DEBUG_LOG && STC_STAT_LOG)
103                         STC_LOGD("Process not found [\033[1;33m%d\033[0;m]", value.pid);
104                 return STC_ERROR_NO_DATA;
105         }
106
107         if (proc_lookup->ground != value.ground)
108                 proc_lookup->ground = value.ground;
109
110         place_pids_to_net_cgroup(value.pid, app_id);
111
112         return ret;
113 }
114
115 API stc_error_e stc_monitor_proc_add(uint32_t classid,
116                                         const char *app_id,
117                                         const stc_proc_value_s value)
118 {
119         stc_error_e ret = STC_ERROR_NONE;
120         stc_app_value_s *app_lookup;
121         stc_proc_value_s *proc_lookup;
122         stc_proc_value_s *proc_value;
123         GHashTable *apps = stc_monitor_get_system_apps();
124
125         if (!apps)
126                 return STC_ERROR_NO_DATA;
127
128         if (classid == STC_UNKNOWN_CLASSID)
129                 classid = get_classid_by_app_id(app_id, TRUE);
130
131         app_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
132         if (!app_lookup) {
133                 if (STC_DEBUG_LOG && STC_STAT_LOG)
134                         STC_LOGD("Application not found [\033[1;36m%d\033[0;m]", classid);
135                 return STC_ERROR_NO_DATA;
136         }
137
138         proc_lookup = g_hash_table_lookup(app_lookup->processes,
139                                         GUINT_TO_POINTER(value.pid));
140         if (proc_lookup) {
141                 if (STC_DEBUG_LOG && STC_STAT_LOG)
142                         STC_LOGE("Already exists [\033[1;36m%d\033[0;m]", value.pid);
143                 return STC_ERROR_NONE;
144         }
145
146         proc_value = MALLOC0(stc_proc_value_s, 1);
147         if (!proc_value) {
148                 if (STC_DEBUG_LOG && STC_STAT_LOG)
149                         STC_LOGE("Value allocation failed");
150                 return STC_ERROR_OUT_OF_MEMORY;
151         }
152
153         proc_value->pid = value.pid;
154         proc_value->ground = value.ground;
155
156         g_hash_table_insert(app_lookup->processes,
157                         GUINT_TO_POINTER(proc_value->pid),
158                         proc_value);
159
160         /* add pid to application cgroup */
161         place_pids_to_net_cgroup(proc_value->pid, app_id);
162
163         if (STC_DEBUG_LOG && STC_STAT_LOG) {
164                 __print_proc_all(app_lookup->processes);
165                 STC_LOGD("\033[1;32mProcess added\033[0;m "
166                         "[\033[1;33m%d\033[0;m]", proc_value->pid);
167         }
168
169         return ret;
170 }
171
172 API stc_error_e stc_monitor_proc_remove(uint32_t classid,
173                                                 pid_t pid)
174 {
175         stc_error_e ret = STC_ERROR_NONE;
176         stc_app_value_s *app_lookup = NULL;
177         guint pid_count = 0;
178         GHashTable *apps = stc_monitor_get_system_apps();
179         GSList *conn_list = stc_get_connection_list();
180         remove_pid_context_s context = {
181                 .pid = pid,
182                 .app_value = NULL,
183                 .entry_removed = FALSE,
184         };
185
186         if (!apps)
187                 return STC_ERROR_NO_DATA;
188
189         if (classid == STC_UNKNOWN_CLASSID) {
190                 g_hash_table_foreach(apps, __proc_remove_pid, &context);
191
192                 if (context.entry_removed)
193                         app_lookup = context.app_value;
194
195                 if (!app_lookup) {
196                         if (STC_DEBUG_LOG && STC_STAT_LOG)
197                                 STC_LOGD("Process not found [\033[1;33m%d\033[0;m]", pid);
198                         return STC_ERROR_NO_DATA;
199                 }
200         } else {
201                 app_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
202                 if (!app_lookup) {
203                         if (STC_DEBUG_LOG && STC_STAT_LOG)
204                                 STC_LOGD("Application not found [\033[1;36m%d\033[0;m]",
205                                                         classid);
206                         return STC_ERROR_NO_DATA;
207                 }
208
209                 if (g_hash_table_remove(app_lookup->processes, GUINT_TO_POINTER(pid))) {
210                         if (STC_DEBUG_LOG && STC_STAT_LOG) {
211                                 __print_proc_all(app_lookup->processes);
212                                 STC_LOGD("\033[1;31mProcess removed\033[0;m "
213                                         "[\033[1;33m%d\033[0;m]", pid);
214                         }
215                 } else {
216                         STC_LOGD("Process not found [\033[1;33m%d\033[0;m]", pid);
217                 }
218         }
219
220         pid_count = g_hash_table_size(app_lookup->processes);
221
222         if (!pid_count) {
223                 for (; conn_list != NULL; conn_list = conn_list->next) {
224                         stc_connection_s *conn = conn_list->data;
225                         /* remove nfacct rule for this classid */
226                         stc_monitor_app_remove_monitor(GUINT_TO_POINTER(classid),
227                                                 app_lookup, conn);
228
229                         if (app_lookup->state == STC_APP_STATE_FOREGROUND)
230                                 stc_monitor_app_remove_accept(GUINT_TO_POINTER(classid),
231                                                 app_lookup, conn);
232                 }
233
234                 stc_monitor_rstn_remove_for_app(classid);
235
236                 g_hash_table_remove(apps, GUINT_TO_POINTER(classid));
237
238                 if (STC_DEBUG_LOG && STC_STAT_LOG)
239                         STC_LOGD("\033[1;31mApplication removed\033[0;m "
240                                 "[\033[1;36m%d\033[0;m]", classid);
241         }
242
243         return ret;
244 }
245
246 API stc_error_e stc_monitor_proc_move(uint32_t from,
247                                                 uint32_t to)
248 {
249         stc_error_e ret = STC_ERROR_NONE;
250         stc_app_value_s *from_lookup = NULL;
251         stc_app_value_s *to_lookup = NULL;
252         GSList *conn_list = stc_get_connection_list();
253         GHashTable *apps = stc_monitor_get_system_apps();
254
255         if (!apps)
256                 return STC_ERROR_NO_DATA;
257
258         if (from != STC_UNKNOWN_CLASSID &&
259                 to != STC_UNKNOWN_CLASSID) {
260                 from_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(from));
261                 if (!from_lookup) {
262                         if (STC_DEBUG_LOG && STC_STAT_LOG)
263                                 STC_LOGD("Application not found [\033[1;36m%d\033[0;m]", from);
264                         return STC_ERROR_NO_DATA;
265                 }
266
267                 to_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(to));
268                 if (!to_lookup) {
269                         if (STC_DEBUG_LOG && STC_STAT_LOG)
270                                 STC_LOGD("Application not found [\033[1;36m%d\033[0;m]", to);
271                         return STC_ERROR_NO_DATA;
272                 }
273
274                 g_hash_table_foreach(from_lookup->processes,
275                                 __proc_move_pid, to_lookup);
276
277                 if (STC_DEBUG_LOG && STC_STAT_LOG) {
278                         __print_proc_all(to_lookup->processes);
279                         STC_LOGD("\033[1;34mProcesses moved\033[0;m "
280                                 "[\033[1;36m%d\033[0;m] -> [\033[1;36m%d\033[0;m]",
281                                 from, to);
282                 }
283
284                 g_hash_table_remove_all(from_lookup->processes);
285
286                 if (STC_DEBUG_LOG && STC_STAT_LOG) {
287                         __print_proc_all(from_lookup->processes);
288                         STC_LOGD("\033[1;31mProcesses removed\033[0;m "
289                                 "[\033[1;36m%d\033[0;m]", from);
290                 }
291
292                 for (; conn_list != NULL; conn_list = conn_list->next) {
293                         stc_connection_s *conn = conn_list->data;
294                         stc_monitor_app_remove_monitor(GUINT_TO_POINTER(from),
295                                                 from_lookup, conn);
296
297                         if (from_lookup->state == STC_APP_STATE_FOREGROUND)
298                                 stc_monitor_app_remove_accept(GUINT_TO_POINTER(from),
299                                                 from_lookup, conn);
300                 }
301
302                 stc_monitor_rstn_remove_for_app(from);
303
304                 g_hash_table_remove(apps, GUINT_TO_POINTER(from));
305
306                 if (STC_DEBUG_LOG && STC_STAT_LOG)
307                         STC_LOGD("\033[1;31mApplication removed\033[0;m "
308                                 "[\033[1;36m%d\033[0;m]", from);
309         }
310
311         return ret;
312 }