Separate monitoring function plugin
[platform/core/connectivity/stc-manager.git] / plugin / monitor / stc-plugin-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-plugin-monitor.h"
18 #include "stc-plugin-monitor-proc.h"
19 #include "stc-plugin-monitor-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_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_plugin_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_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_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_plugin_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_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_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_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_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_plugin_monitor_proc_remove(uint32_t classid, pid_t pid)
173 {
174         stc_error_e ret = STC_ERROR_NONE;
175         stc_app_value_s *app_lookup = NULL;
176         guint pid_count = 0;
177         GHashTable *apps = stc_monitor_get_system_apps();
178         GSList *conn_list = stc_get_connection_list();
179         remove_pid_context_s context = {
180                 .pid = pid,
181                 .app_value = NULL,
182                 .entry_removed = FALSE,
183         };
184
185         if (!apps)
186                 return STC_ERROR_NO_DATA;
187
188         if (classid == STC_UNKNOWN_CLASSID) {
189                 g_hash_table_foreach(apps, __proc_remove_pid, &context);
190
191                 if (context.entry_removed)
192                         app_lookup = context.app_value;
193
194                 if (!app_lookup) {
195                         if (STC_STAT_LOG)
196                                 STC_LOGD("Process not found [\033[1;33m%d\033[0;m]", pid);
197                         return STC_ERROR_NO_DATA;
198                 }
199         } else {
200                 app_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(classid));
201                 if (!app_lookup) {
202                         if (STC_STAT_LOG)
203                                 STC_LOGD("Application not found [\033[1;36m%d\033[0;m]",
204                                                         classid);
205                         return STC_ERROR_NO_DATA;
206                 }
207
208                 if (g_hash_table_remove(app_lookup->processes, GUINT_TO_POINTER(pid))) {
209                         if (STC_STAT_LOG) {
210                                 __print_proc_all(app_lookup->processes);
211                                 STC_LOGD("\033[1;31mProcess removed\033[0;m "
212                                         "[\033[1;33m%d\033[0;m]", pid);
213                         }
214                 } else {
215                         STC_LOGD("Process not found [\033[1;33m%d\033[0;m]", pid);
216                 }
217         }
218
219         pid_count = g_hash_table_size(app_lookup->processes);
220
221         if (!pid_count) {
222                 for (; conn_list != NULL; conn_list = conn_list->next) {
223                         stc_connection_s *conn = conn_list->data;
224                         /* remove nfacct rule for this classid */
225                         stc_monitor_app_remove_monitor(GUINT_TO_POINTER(classid),
226                                                 app_lookup, conn);
227
228                         if (app_lookup->state == STC_APP_STATE_FOREGROUND)
229                                 stc_monitor_app_remove_accept(GUINT_TO_POINTER(classid),
230                                                 app_lookup, conn);
231                 }
232
233                 stc_monitor_rstn_remove_for_app(classid);
234
235                 g_hash_table_remove(apps, GUINT_TO_POINTER(classid));
236
237                 if (STC_STAT_LOG)
238                         STC_LOGD("\033[1;31mApplication removed\033[0;m "
239                                 "[\033[1;36m%d\033[0;m]", classid);
240         }
241
242         return ret;
243 }
244
245 API stc_error_e stc_plugin_monitor_proc_move(uint32_t from, uint32_t to)
246 {
247         stc_error_e ret = STC_ERROR_NONE;
248         stc_app_value_s *from_lookup = NULL;
249         stc_app_value_s *to_lookup = NULL;
250         GSList *conn_list = stc_get_connection_list();
251         GHashTable *apps = stc_monitor_get_system_apps();
252
253         if (!apps)
254                 return STC_ERROR_NO_DATA;
255
256         if (from != STC_UNKNOWN_CLASSID &&
257                 to != STC_UNKNOWN_CLASSID) {
258                 from_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(from));
259                 if (!from_lookup) {
260                         if (STC_STAT_LOG)
261                                 STC_LOGD("Application not found [\033[1;36m%d\033[0;m]", from);
262                         return STC_ERROR_NO_DATA;
263                 }
264
265                 to_lookup = g_hash_table_lookup(apps, GUINT_TO_POINTER(to));
266                 if (!to_lookup) {
267                         if (STC_STAT_LOG)
268                                 STC_LOGD("Application not found [\033[1;36m%d\033[0;m]", to);
269                         return STC_ERROR_NO_DATA;
270                 }
271
272                 g_hash_table_foreach(from_lookup->processes,
273                                 __proc_move_pid, to_lookup);
274
275                 if (STC_STAT_LOG) {
276                         __print_proc_all(to_lookup->processes);
277                         STC_LOGD("\033[1;34mProcesses moved\033[0;m "
278                                 "[\033[1;36m%d\033[0;m] -> [\033[1;36m%d\033[0;m]",
279                                 from, to);
280                 }
281
282                 g_hash_table_remove_all(from_lookup->processes);
283
284                 if (STC_STAT_LOG) {
285                         __print_proc_all(from_lookup->processes);
286                         STC_LOGD("\033[1;31mProcesses removed\033[0;m "
287                                 "[\033[1;36m%d\033[0;m]", from);
288                 }
289
290                 for (; conn_list != NULL; conn_list = conn_list->next) {
291                         stc_connection_s *conn = conn_list->data;
292                         stc_monitor_app_remove_monitor(GUINT_TO_POINTER(from),
293                                                 from_lookup, conn);
294
295                         if (from_lookup->state == STC_APP_STATE_FOREGROUND)
296                                 stc_monitor_app_remove_accept(GUINT_TO_POINTER(from),
297                                                 from_lookup, conn);
298                 }
299
300                 stc_monitor_rstn_remove_for_app(from);
301
302                 g_hash_table_remove(apps, GUINT_TO_POINTER(from));
303
304                 if (STC_STAT_LOG)
305                         STC_LOGD("\033[1;31mApplication removed\033[0;m "
306                                 "[\033[1;36m%d\033[0;m]", from);
307         }
308
309         return ret;
310 }