Merge "Return errors to caller" into tizen_5.5
[platform/core/connectivity/stc-manager.git] / src / stc-manager-gdbus.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-manager-gdbus.h"
18 #include "stc-manager.h"
19 #include "stc-statistics.h"
20 #include "stc-restriction.h"
21 #include "stc-firewall.h"
22 #include "stc-pcap.h"
23 #include "stc-manager-util.h"
24 #include "stc-manager-plugin-appstatus.h"
25 #include "stc-manager-plugin-procfs.h"
26 #include "stc-manager-plugin-monitor.h"
27 #include "stc-manager-plugin-firewall.h"
28 #include "helper-iptables.h"
29
30 #define MANAGER_DBUS_ERROR_NAME "net.stc.manager.Error.Failed"
31
32 #define STC_MANAGER_DBUS_REPLY_ERROR(invocation, err_num) \
33         g_dbus_method_invocation_return_dbus_error((invocation), \
34                                                    MANAGER_DBUS_ERROR_NAME, \
35                                                    stc_err_strs[-(err_num)])
36
37 static const gchar *stc_err_strs[] = {
38         "ERROR_NONE",
39         "FAIL",
40         "DB_FAILED",
41         "OUT_OF_MEMORY",
42         "INVALID_PARAMETER",
43         "NO_DATA",
44         "ALREADY_DATA",
45         "UNINITIALIZED",
46         "PERMISSION_DENIED",
47         "NOTIMPL"
48 };
49
50 static gboolean __stc_manager_gdbus_statistics_init(stc_s *stc)
51 {
52         __STC_LOG_FUNC_ENTER__;
53         gboolean ret = TRUE;
54         gchar *s = NULL;
55
56         StcObjectSkeleton *object = NULL;
57         StcStatistics *statistics = NULL;
58         s = g_strdup_printf(STC_DBUS_SERVICE_STATISTICS_PATH);
59
60         /* Add interface to default object path */
61         object = stc_object_skeleton_new(s);
62         g_free(s);
63
64         /* Make the newly created object export the interface
65          * net.stc.statistics (note
66          * that @object takes its own reference to @statistics).
67          */
68
69         statistics = stc_statistics_skeleton_new();
70         stc_object_skeleton_set_statistics(object, statistics);
71         g_object_unref(statistics);
72
73         /* Register for method callbacks as signal callbacks */
74
75         g_signal_connect(statistics, "handle-init",
76                          G_CALLBACK(handle_statistics_init),
77                          stc);
78
79         g_signal_connect(statistics, "handle-get",
80                          G_CALLBACK(handle_statistics_get),
81                          stc);
82
83         g_signal_connect(statistics, "handle-get-all",
84                          G_CALLBACK(handle_statistics_get_all),
85                          stc);
86
87         g_signal_connect(statistics, "handle-reset",
88                          G_CALLBACK(handle_statistics_reset),
89                          stc);
90
91         /* Export the object (@manager takes its own reference to @object) */
92         g_dbus_object_manager_server_export(stc->obj_mgr,
93                                             G_DBUS_OBJECT_SKELETON(object));
94         g_object_unref(object);
95
96         stc->statistics_obj = (gpointer)statistics;
97
98         __STC_LOG_FUNC_EXIT__;
99         return ret;
100 }
101
102 static gboolean __stc_manager_gdbus_restriction_init(stc_s *stc)
103 {
104         __STC_LOG_FUNC_ENTER__;
105         gboolean ret = TRUE;
106         gchar *s = NULL;
107
108         StcObjectSkeleton *object = NULL;
109         StcRestriction *restriction = NULL;
110         s = g_strdup_printf(STC_DBUS_SERVICE_RESTRICTION_PATH);
111
112         /* Add interface to default object path */
113         object = stc_object_skeleton_new(s);
114         g_free(s);
115
116         /* Make the newly created object export the interface
117          * net.stc.restriction (note
118          * that @object takes its own reference to @restriction).
119          */
120
121         restriction = stc_restriction_skeleton_new();
122         stc_object_skeleton_set_restriction(object, restriction);
123         g_object_unref(restriction);
124
125         /* Register for method callbacks as signal callbacks */
126
127         g_signal_connect(restriction, "handle-set",
128                          G_CALLBACK(handle_restriction_set), stc);
129
130         g_signal_connect(restriction, "handle-get",
131                          G_CALLBACK(handle_restriction_get), stc);
132
133         g_signal_connect(restriction, "handle-get-all",
134                          G_CALLBACK(handle_restriction_get_all), stc);
135
136         g_signal_connect(restriction, "handle-get-type",
137                          G_CALLBACK(handle_restriction_get_type),
138                          stc);
139
140         g_signal_connect(restriction, "handle-unset",
141                          G_CALLBACK(handle_restriction_unset), stc);
142
143         g_signal_connect(restriction, "handle-set-list",
144                          G_CALLBACK(handle_restriction_set_list), stc);
145
146         g_signal_connect(restriction, "handle-unset-list",
147                          G_CALLBACK(handle_restriction_unset_list), stc);
148
149         /* Export the object (@manager takes its own reference to @object) */
150         g_dbus_object_manager_server_export(stc->obj_mgr,
151                                             G_DBUS_OBJECT_SKELETON(object));
152         g_object_unref(object);
153
154         stc->restriction_obj = (gpointer)restriction;
155
156         __STC_LOG_FUNC_EXIT__;
157         return ret;
158 }
159
160 static gboolean __stc_manager_gdbus_firewall_init(stc_s *stc)
161 {
162         __STC_LOG_FUNC_ENTER__;
163         gboolean ret = TRUE;
164         gchar *s = NULL;
165
166         StcObjectSkeleton *object = NULL;
167         StcFirewall *firewall = NULL;
168         s = g_strdup_printf(STC_DBUS_SERVICE_FIREWALL_PATH);
169
170         /* Add interface to default object path */
171         object = stc_object_skeleton_new(s);
172         g_free(s);
173
174         firewall = stc_firewall_skeleton_new();
175         stc_object_skeleton_set_firewall(object, firewall);
176         g_object_unref(firewall);
177
178         /* Register for method callbacks as signal callbacks */
179
180         g_signal_connect(firewall, "handle-lock",
181                          G_CALLBACK(handle_firewall_lock),
182                          stc);
183
184         g_signal_connect(firewall, "handle-unlock",
185                          G_CALLBACK(handle_firewall_unlock),
186                          stc);
187
188         g_signal_connect(firewall, "handle-get-lock",
189                          G_CALLBACK(handle_firewall_get_lock),
190                          stc);
191
192         g_signal_connect(firewall, "handle-add-chain",
193                          G_CALLBACK(handle_firewall_add_chain),
194                          stc);
195
196         g_signal_connect(firewall, "handle-remove-chain",
197                          G_CALLBACK(handle_firewall_remove_chain),
198                          stc);
199
200         g_signal_connect(firewall, "handle-flush-chain",
201                          G_CALLBACK(handle_firewall_flush_chain),
202                          stc);
203
204         g_signal_connect(firewall, "handle-get-all-chain",
205                          G_CALLBACK(handle_firewall_get_all_chain),
206                          stc);
207
208         g_signal_connect(firewall, "handle-set-chain",
209                          G_CALLBACK(handle_firewall_set_chain),
210                          stc);
211
212         g_signal_connect(firewall, "handle-unset-chain",
213                          G_CALLBACK(handle_firewall_unset_chain),
214                          stc);
215
216         g_signal_connect(firewall, "handle-add-rule",
217                          G_CALLBACK(handle_firewall_add_rule),
218                          stc);
219
220         g_signal_connect(firewall, "handle-remove-rule",
221                          G_CALLBACK(handle_firewall_remove_rule),
222                          stc);
223
224         g_signal_connect(firewall, "handle-update-rule",
225                          G_CALLBACK(handle_firewall_update_rule),
226                          stc);
227
228         g_signal_connect(firewall, "handle-get-all-rule",
229                          G_CALLBACK(handle_firewall_get_all_rule),
230                          stc);
231
232         /* Export the object (@manager takes its own reference to @object) */
233         g_dbus_object_manager_server_export(stc->obj_mgr,
234                                             G_DBUS_OBJECT_SKELETON(object));
235         g_object_unref(object);
236
237         stc->firewall_obj = (gpointer)firewall;
238
239         __STC_LOG_FUNC_EXIT__;
240         return ret;
241 }
242
243 static gboolean __stc_manager_gdbus_pcap_init(stc_s *stc)
244 {
245         __STC_LOG_FUNC_ENTER__;
246         gboolean ret = TRUE;
247         gchar *s = NULL;
248
249         StcObjectSkeleton *object = NULL;
250         StcPcap *pcap = NULL;
251         s = g_strdup_printf(STC_DBUS_SERVICE_PCAP_PATH);
252
253         /* Add interface to default object path */
254         object = stc_object_skeleton_new(s);
255         g_free(s);
256
257         pcap = stc_pcap_skeleton_new();
258         stc_object_skeleton_set_pcap(object, pcap);
259         g_object_unref(pcap);
260
261         /* Register for method callbacks as signal callbacks */
262
263         g_signal_connect(pcap, "handle-start",
264                          G_CALLBACK(handle_pcap_start),
265                          stc);
266
267         g_signal_connect(pcap, "handle-stop",
268                          G_CALLBACK(handle_pcap_stop),
269                          stc);
270
271         g_signal_connect(pcap, "handle-get-all",
272                          G_CALLBACK(handle_pcap_get_all),
273                          stc);
274
275         g_signal_connect(pcap, "handle-find-all-devs",
276                          G_CALLBACK(handle_pcap_find_all_devs),
277                          stc);
278
279         /* Export the object (@manager takes its own reference to @object) */
280         g_dbus_object_manager_server_export(stc->obj_mgr,
281                                             G_DBUS_OBJECT_SKELETON(object));
282         g_object_unref(object);
283
284         stc->pcap_obj = (gpointer)pcap;
285
286         __STC_LOG_FUNC_EXIT__;
287         return ret;
288 }
289
290 static gboolean __stc_manager_gdbus_manager_init(stc_s *stc)
291 {
292         __STC_LOG_FUNC_ENTER__;
293         gboolean ret = TRUE;
294         gchar *s = NULL;
295
296         StcObjectSkeleton *object = NULL;
297         StcManager *manager = NULL;
298         s = g_strdup_printf(STC_DBUS_SERVICE_MANAGER_PATH);
299
300         object = stc_object_skeleton_new(s);
301         g_free(s);
302
303         manager = stc_manager_skeleton_new();
304         stc_object_skeleton_set_manager(object, manager);
305         g_object_unref(manager);
306
307         g_signal_connect(manager, "handle-stop",
308                          G_CALLBACK(handle_manager_stop), stc);
309
310         g_signal_connect(manager, "handle-commit-iptables",
311                          G_CALLBACK(handle_manager_commit_iptables), stc);
312
313         g_signal_connect(manager, "handle-commit-ip6tables",
314                          G_CALLBACK(handle_manager_commit_ip6tables), stc);
315
316         g_dbus_object_manager_server_export(stc->obj_mgr,
317                                             G_DBUS_OBJECT_SKELETON(object));
318         g_object_unref(object);
319
320         stc->manager_obj = (gpointer)manager;
321
322         __STC_LOG_FUNC_EXIT__;
323         return ret;
324 }
325
326
327 static void __stc_manager_gdbus_on_bus_acquired(GDBusConnection *connection,
328                                                 const gchar *name,
329                                                 gpointer user_data)
330 {
331         __STC_LOG_FUNC_ENTER__;
332         stc_s* stc = (stc_s*)user_data;
333
334         stc->obj_mgr = g_dbus_object_manager_server_new("/net/stc");
335
336         STC_LOGD("path : %s", name);
337
338         stc->connection = connection;
339
340         if (__stc_manager_gdbus_statistics_init(stc) == FALSE) {
341                 STC_LOGE("Can not signal connect to statistics"); //LCOV_EXCL_LINE
342                 /* Deinitialize and quit manager */
343         }
344
345         if (__stc_manager_gdbus_restriction_init(stc) == FALSE) {
346                 STC_LOGE("Cannot signal connect to restriction"); //LCOV_EXCL_LINE
347                 /* Deinitialize and quit manager */
348         }
349
350         if (__stc_manager_gdbus_firewall_init(stc) == FALSE) {
351                 STC_LOGE("Cannot signal connect to firewall"); //LCOV_EXCL_LINE
352                 /* Deinitialize and quit manager */
353         }
354
355         if (__stc_manager_gdbus_pcap_init(stc) == FALSE) {
356                 STC_LOGE("Cannot signal connect to pcap"); //LCOV_EXCL_LINE
357                 /* Deinitialize and quit manager */
358         }
359
360         if (__stc_manager_gdbus_manager_init(stc) == FALSE) {
361                 STC_LOGE("Cannot signal connect to manager"); //LCOV_EXCL_LINE
362                 /* Deinitialize and quit manager */
363         }
364
365         g_dbus_object_manager_server_set_connection(stc->obj_mgr,
366                                                     stc->connection);
367
368         iptables_init();
369         stc_plugin_firewall_update();
370         stc_plugin_monitor_init_connection(stc);
371
372         stc_plugin_appstatus_register_state_changed_cb(stc,
373                         stc_plugin_procfs_app_status_changed, NULL);
374
375         __STC_LOG_FUNC_EXIT__;
376 }
377
378 static void __stc_manager_gdbus_on_name_acquired(GDBusConnection *connection,
379                                                  const gchar *name,
380                                                  gpointer user_data)
381 {
382         STC_LOGD("name : %s", name);
383 }
384
385 //LCOV_EXCL_START
386 static void __stc_manager_gdbus_on_name_lost(GDBusConnection *connection,
387                                              const gchar *name,
388                                              gpointer user_data)
389 {
390         STC_LOGD("name : %s", name);
391 }
392 //LCOV_EXCL_STOP
393
394 void stc_manager_gdbus_init(gpointer stc_data)
395 {
396         __STC_LOG_FUNC_ENTER__;
397         stc_s *stc = (stc_s *)stc_data;
398
399         stc->gdbus_owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
400                                              STC_DBUS_SERVICE,
401                                              G_BUS_NAME_OWNER_FLAGS_NONE,
402                                              __stc_manager_gdbus_on_bus_acquired,
403                                              __stc_manager_gdbus_on_name_acquired,
404                                              __stc_manager_gdbus_on_name_lost,
405                                              stc,
406                                              NULL);
407
408         __STC_LOG_FUNC_EXIT__;
409 }
410
411 void stc_manager_gdbus_deinit(gpointer stc_data)
412 {
413         __STC_LOG_FUNC_ENTER__;
414         stc_s *stc = (stc_s *)stc_data;
415
416         stc_plugin_appstatus_deregister_state_changed_cb(stc);
417         stc_plugin_monitor_deinit_connection(stc);
418
419         g_bus_unown_name(stc->gdbus_owner_id);
420
421         stc->statistics_obj = NULL;
422         stc->restriction_obj = NULL;
423         stc->firewall_obj = NULL;
424         stc->pcap_obj = NULL;
425         stc->manager_obj = NULL;
426         __STC_LOG_FUNC_EXIT__;
427 }
428
429 API GVariant *stc_manager_gdbus_call_sync(GDBusConnection *connection,
430                                       const char *dest, const char *path,
431                                       const char *interface_name,
432                                       const char *method, GVariant *params)
433 {
434         GError *error = NULL;
435         GVariant *reply = NULL;
436
437         if (connection == NULL) {
438                 STC_LOGE("Failed to get GDBusconnection"); //LCOV_EXCL_LINE
439                 return reply; //LCOV_EXCL_LINE
440         }
441
442         reply = g_dbus_connection_call_sync(connection,
443                                             dest,
444                                             path,
445                                             interface_name,
446                                             method,
447                                             params,
448                                             NULL,
449                                             G_DBUS_CALL_FLAGS_NONE,
450                                             (5 * 1000),  /* 5 seconds timeout */
451                                             NULL,
452                                             &error);
453
454         if (reply == NULL) {
455                 if (error != NULL) {
456                         STC_LOGE("g_dbus_connection_call_sync() failed" //LCOV_EXCL_LINE
457                                  " error [%d: %s]", error->code, error->message);
458                         g_error_free(error); //LCOV_EXCL_LINE
459                 } else {
460                         STC_LOGE("g_dbus_connection_call_sync() failed"); //LCOV_EXCL_LINE
461                 }
462
463                 return NULL;
464         }
465
466         return reply;
467 }
468
469 API int stc_manager_gdbus_call_async(GDBusConnection *connection,
470                                       const char *dest, const char *path,
471                                       const char *interface_name,
472                                       const char *method, GVariant *params,
473                                       GAsyncReadyCallback notify_func,
474                                       void *user_data)
475 {
476         if (connection == NULL) {
477                 STC_LOGE("Failed to get GDBusconnection"); //LCOV_EXCL_LINE
478                 return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
479         }
480
481         g_dbus_connection_call(connection,
482                             dest,
483                             path,
484                             interface_name,
485                             method,
486                             params,
487                             NULL,
488                             G_DBUS_CALL_FLAGS_NONE,
489                             (5 * 1000),  /* 5 seconds timeout */
490                             NULL,
491                             (GAsyncReadyCallback)notify_func,
492                             (gpointer)user_data);
493
494         return STC_ERROR_NONE;
495 }
496
497 API guint stc_manager_gdbus_subscribe_signal(GDBusConnection *connection,
498                                          const gchar *sender,
499                                          const gchar *interface_name,
500                                          const gchar *member,
501                                          const gchar *object_path,
502                                          const gchar *arg0,
503                                          GDBusSignalFlags flags,
504                                          GDBusSignalCallback callback,
505                                          gpointer user_data,
506                                          GDestroyNotify user_data_free_func)
507 {
508         if (connection == NULL) {
509                 STC_LOGE("Failed to get GDBusconnection"); //LCOV_EXCL_LINE
510                 return 0; //LCOV_EXCL_LINE
511         }
512
513         return g_dbus_connection_signal_subscribe(connection,
514                                                   sender,
515                                                   interface_name,
516                                                   member,
517                                                   object_path,
518                                                   NULL,
519                                                   G_DBUS_SIGNAL_FLAGS_NONE,
520                                                   callback,
521                                                   user_data,
522                                                   user_data_free_func);
523 }
524
525 API void stc_manager_gdbus_unsubscribe_signal(GDBusConnection *connection,
526                                           guint subscription_id)
527 {
528         if (connection == NULL) {
529                 STC_LOGE("Failed to get GDBusconnection"); //LCOV_EXCL_LINE
530                 return; //LCOV_EXCL_LINE
531         }
532
533         g_dbus_connection_signal_unsubscribe(connection, subscription_id);
534 }
535
536 API void stc_manager_gdbus_dict_foreach(GVariantIter *iter, dbus_dict_cb cb,
537                                     void *user_data)
538 {
539         __STC_LOG_FUNC_ENTER__;
540
541         gchar *key = NULL;
542         GVariant *value = NULL;
543
544         if (!cb) {
545                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
546                 return; //LCOV_EXCL_LINE
547         }
548
549         while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
550                 /* DEBUG_GDBUS_KEY_VALUE(key, value); */
551                 if (key)
552                         cb(key, value, user_data);
553         }
554
555         __STC_LOG_FUNC_EXIT__;
556 }
557
558 API gboolean stc_manager_dbus_emit_signal(GDBusConnection *connection,
559                                       const gchar *object_path,
560                                       const gchar *interface_name,
561                                       const gchar *signal_name,
562                                       GVariant *parameters)
563 {
564         gboolean rv = FALSE;
565         GError *error = NULL;
566
567         if (connection == NULL) {
568                 STC_LOGE("GDBusconnection is NULL"); //LCOV_EXCL_LINE
569                 return 0;
570         }
571
572         DEBUG_GDBUS_VARIANT("Signal params: ", parameters);
573
574         rv = g_dbus_connection_emit_signal(connection,
575                                            NULL,
576                                            object_path,
577                                            interface_name,
578                                            signal_name,
579                                            parameters,
580                                            &error);
581         if (rv != TRUE) {
582                 STC_LOGE("Failed to emit signal [%s] interface [%s] Error [%s]", //LCOV_EXCL_LINE
583                          signal_name, interface_name, error->message);
584                 g_error_free(error); //LCOV_EXCL_LINE
585         } else {
586                 STC_LOGD("[%s] signal sent on [%s] interface", signal_name,
587                          interface_name);
588         }
589
590         return rv;
591 }
592
593 gboolean handle_manager_stop(StcManager *object,
594                                GDBusMethodInvocation *invocation)
595 {
596         __STC_LOG_FUNC_ENTER__;
597         GVariant *return_parameters = NULL;
598
599         stc_set_keep_alive(TRUE);
600
601         STC_LOGI("stc manager stop");
602
603         return_parameters = g_variant_new("(i)", STC_ERROR_NONE);
604
605         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
606         STC_DBUS_REPLY(invocation, return_parameters);
607
608         stc_stop_manager();
609
610         __STC_LOG_FUNC_EXIT__;
611         return TRUE;
612 }
613
614 gboolean handle_manager_commit_iptables(StcManager *object,
615                                         GDBusMethodInvocation *invocation,
616                                         const gchar *option,
617                                         void *user_data)
618 {
619         __STC_LOG_FUNC_ENTER__;
620         GVariant *return_parameters = NULL;
621         int ret = STC_ERROR_NONE;
622         int err_num = 0;
623         char *err_str = NULL;
624         char cmd[STC_CMD_SIZE] = { 0, };
625
626         stc_set_keep_alive(TRUE);
627
628         if (option == NULL) {
629                 STC_MANAGER_DBUS_REPLY_ERROR(invocation,
630                                                  STC_ERROR_INVALID_PARAMETER);
631                 __STC_LOG_FUNC_EXIT__;
632                 return TRUE;
633         }
634
635         STC_LOGD("[%s]", option);
636         g_snprintf(cmd, STC_CMD_SIZE, "%s %s", STC_IPTABLES, option);
637
638         ret = stc_commit_iptables(cmd, &err_num, &err_str);
639
640         return_parameters = g_variant_new("(iis)", ret, err_num, err_str);
641
642         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
643         STC_DBUS_REPLY(invocation, return_parameters);
644
645         __STC_LOG_FUNC_EXIT__;
646         return TRUE;
647 }
648
649 gboolean handle_manager_commit_ip6tables(StcManager *object,
650                                         GDBusMethodInvocation *invocation,
651                                         const gchar *option,
652                                         void *user_data)
653 {
654         __STC_LOG_FUNC_ENTER__;
655         GVariant *return_parameters = NULL;
656         int ret = STC_ERROR_NONE;
657         int err_num = 0;
658         char *err_str = NULL;
659         char cmd[STC_CMD_SIZE] = { 0, };
660
661         stc_set_keep_alive(TRUE);
662
663         if (option == NULL) {
664                 STC_MANAGER_DBUS_REPLY_ERROR(invocation,
665                                                  STC_ERROR_INVALID_PARAMETER);
666                 __STC_LOG_FUNC_EXIT__;
667                 return TRUE;
668         }
669
670         STC_LOGD("[%s]", option);
671         g_snprintf(cmd, STC_CMD_SIZE, "%s %s", STC_IP6TABLES, option);
672
673         ret = stc_commit_iptables(cmd, &err_num, &err_str);
674
675         return_parameters = g_variant_new("(iis)", ret, err_num, err_str);
676
677         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
678         STC_DBUS_REPLY(invocation, return_parameters);
679
680         __STC_LOG_FUNC_EXIT__;
681         return TRUE;
682 }