Fix for UTC error case
[platform/core/connectivity/wifi-mesh-manager.git] / src / mesh-service-interface.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include <glib.h>
23 #include <gio/gio.h>
24
25 #include "mesh.h"
26 #include "mesh-log.h"
27 #include "mesh-util.h"
28 #include "mesh-gdbus.h"
29 #include "mesh-service.h"
30 #include "mesh-service-interface.h"
31 #include "mesh-generated-code.h"
32
33 #include "mesh-request.h"
34 #include "mesh-interface.h"
35
36 static NetMesh *meshd_dbus_object;
37 static Manager *meshd_activator_dbus_object;
38
39 /* global list to care resource handle for each client */
40 static GList *meshd_dbus_client_list;
41 static GMutex meshd_dbus_client_list_mutex;
42
43 typedef struct _meshd_dbus_client_s {
44         gchar *bus_name;
45 } meshd_dbus_client_s;
46
47 NetMesh* meshd_dbus_get_object()
48 {
49         return meshd_dbus_object;
50 }
51
52 int64_t meshd_dbus_generate_signal_number()
53 {
54         static int64_t i = 0;
55
56         return i++;
57 }
58
59 static int _meshd_dbus_client_list_cleanup(GList *client_list)
60 {
61         meshd_dbus_client_s *client;
62
63         meshd_check_null_ret_error("client_list", client_list, FALSE);
64
65         client = client_list->data;
66
67         free(client->bus_name);
68         client->bus_name = NULL;
69         free(client);
70         g_list_free(client_list);
71
72         return MESHD_ERROR_NONE;
73 }
74
75 static int _meshd_dbus_client_list_compare_bus_name(const void *a, const void *b)
76 {
77         const meshd_dbus_client_s *client = a;
78
79         return g_strcmp0(client->bus_name, b);
80 }
81
82 static inline GList* _meshd_dbus_client_list_find_client(const gchar *owner)
83 {
84         return g_list_find_custom(meshd_dbus_client_list, owner,
85                         _meshd_dbus_client_list_compare_bus_name);
86 }
87
88 static void _meshd_dbus_name_owner_changed_cb(GDBusConnection *conn,
89                 const gchar *sender_name,
90                 const gchar *object_path,
91                 const gchar *interface_name,
92                 const gchar *signal_name,
93                 GVariant *parameters,
94                 gpointer user_data)
95 {
96         int ret;
97         GList *client = NULL;
98         gchar *name, *old_owner, *new_owner;
99
100         NOTUSED(conn);
101         NOTUSED(sender_name);
102         NOTUSED(object_path);
103         NOTUSED(interface_name);
104         NOTUSED(signal_name);
105         NOTUSED(user_data);
106
107         g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
108
109         if (0 == strlen(new_owner)) {
110                 g_mutex_lock(&meshd_dbus_client_list_mutex);
111                 client = _meshd_dbus_client_list_find_client(old_owner);
112                 if (client) { /* found bus name in our bus list */
113                         MESH_LOGD("bus(%s) stopped", old_owner);
114                         meshd_dbus_client_list = g_list_remove_link(meshd_dbus_client_list, client);
115                 }
116                 g_mutex_unlock(&meshd_dbus_client_list_mutex);
117
118                 if (client) {
119                         ret = _meshd_dbus_client_list_cleanup(client);
120                         if (MESHD_ERROR_NONE != ret)
121                                 MESH_LOGE("_meshd_dbus_client_list_cleanup() Fail(%d)", ret);
122                 }
123         }
124 }
125
126 static int _meshd_dbus_subscribe_name_owner_changed(GDBusConnection *conn)
127 {
128         unsigned int id;
129
130         id = g_dbus_connection_signal_subscribe(conn,
131                         "org.freedesktop.DBus", /* bus name */
132                         "org.freedesktop.DBus", /* interface */
133                         "NameOwnerChanged", /* member */
134                         "/org/freedesktop/DBus", /* path */
135                         NULL, /* arg0 */
136                         G_DBUS_SIGNAL_FLAGS_NONE,
137                         _meshd_dbus_name_owner_changed_cb,
138                         NULL,
139                         NULL);
140         if (0 == id) {
141                 MESH_LOGE("g_dbus_connection_signal_subscribe() Fail");
142                 return MESHD_ERROR_IO_ERROR;
143         }
144
145         return MESHD_ERROR_NONE;
146 }
147
148 static gboolean _meshd_dbus_handle_enable(Manager *object,
149                 GDBusMethodInvocation *invocation,
150                 gpointer user_data)
151 {
152         int ret = MESHD_ERROR_NONE;
153         mesh_service *service = (mesh_service *)user_data;
154         mesh_interface_s *info = service->interface_info;
155
156         if (service->mesh_activated) {
157                 /* Already activated */
158                 manager_complete_enable(object, invocation, MESHD_ERROR_NONE);
159                 goto FINISH;
160         }
161
162         /* Do API response first */
163         manager_complete_enable(object, invocation, ret);
164         service->mesh_activated = TRUE;
165
166         meshd_check_null_ret_error("info", info, FALSE);
167
168         /* Register event handler first */
169         ret = mesh_request_register_event_handler();
170         if (MESHD_ERROR_NONE != ret)
171                 MESH_LOGE("Failed to register mesh event handler !! [%d]", ret);
172
173         ret = mesh_interface_initialize(service->interface_info);
174         if (MESHD_ERROR_NONE != ret) {
175                 MESH_LOGE("Failed to mesh_interface_initialize [%d]", ret);
176                 goto FINISH;
177         }
178
179 FINISH:
180         net_mesh_emit_mesh_enabled(meshd_dbus_get_object(), ret);
181
182         return TRUE;
183 }
184
185 static gboolean _meshd_dbus_handle_disable(Manager *object,
186                 GDBusMethodInvocation *invocation,
187                 gpointer user_data)
188 {
189         int ret = MESHD_ERROR_NONE;
190         mesh_service *service = (mesh_service *)user_data;
191         mesh_interface_s *info = service->interface_info;
192
193         meshd_check_null_ret_error("info", info, FALSE);
194
195         /* Make response first */
196         manager_complete_disable(object, invocation, ret);
197
198         ret = mesh_request_unregister_event_handler();
199         if (MESHD_ERROR_NONE != ret)
200                 MESH_LOGE("Failed to unregister mesh event handler !! [%d]", ret);
201
202         /* Terminate daemon */
203         meshd_service_exit(service);
204
205         return TRUE;
206 }
207
208 static gboolean _meshd_dbus_handle_scan(NetMesh *object,
209                 GDBusMethodInvocation *invocation,
210                 gpointer user_data)
211 {
212         int ret = MESHD_ERROR_NONE;
213         mesh_service *service = (mesh_service *)user_data;
214         mesh_interface_s *info = service->interface_info;
215
216         meshd_check_null_ret_error("info", info, FALSE);
217
218         ret = mesh_request_scan(service);
219         if (MESHD_ERROR_NONE != ret)
220                 MESH_LOGE("Failed to mesh_request_scan !");
221
222         net_mesh_complete_scan(object, invocation, ret);
223
224         return TRUE;
225 }
226
227 static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object,
228                 GDBusMethodInvocation *invocation,
229                 gchar *mesh_id,
230                 gint channel,
231                 gpointer user_data)
232 {
233         int ret = MESHD_ERROR_NONE;
234         mesh_service *service = (mesh_service *)user_data;
235         mesh_interface_s *info = service->interface_info;
236
237         meshd_check_null_ret_error("info", info, FALSE);
238
239         ret = mesh_request_specific_scan(service, mesh_id, channel);
240         if (MESHD_ERROR_NONE != ret)
241                 MESH_LOGE("Failed to mesh_request_specific_scan !");
242
243         net_mesh_complete_specific_scan(object, invocation, ret);
244
245         return TRUE;
246 }
247
248 static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object,
249                 GDBusMethodInvocation *invocation,
250                 gpointer user_data)
251 {
252         int ret = MESHD_ERROR_NONE;
253         mesh_service *service = (mesh_service *)user_data;
254
255         ret = mesh_request_cancel_scan(service);
256         if (MESHD_ERROR_NONE != ret)
257                 MESH_LOGE("Failed to mesh_request_cancel_scan");
258
259         net_mesh_complete_cancel_scan(object, invocation, ret);
260
261         return TRUE;
262 }
263
264 static void _on_scan_result_destroy(gpointer data)
265 {
266         mesh_scan_result_s *scan_item = (mesh_scan_result_s *)data;
267
268         if (scan_item) {
269                 g_free(scan_item->mesh_id);
270                 g_free(scan_item->bssid);
271                 g_free(scan_item->object_path);
272         }
273         g_free(scan_item);
274 }
275
276 static void _on_peer_info_destroy(gpointer data)
277 {
278         mesh_peer_info_s *peer = (mesh_peer_info_s *)data;
279         if (peer)
280                 g_free(peer->address);
281         g_free(peer);
282 }
283
284 static void _on_station_list_destroy(gpointer data)
285 {
286         mesh_station_info_s *info = (mesh_station_info_s*)data;
287
288         if (info) {
289                 g_free(info->bssid);
290                 g_free(info);
291         }
292 }
293
294 static void _on_mpath_list_destroy(gpointer data)
295 {
296         mesh_mpath_info_s *info = (mesh_mpath_info_s*)data;
297
298         if (info) {
299                 g_free(info->dest_addr);
300                 g_free(info->next_hop);
301                 g_free(info->interface);
302                 g_free(info);
303         }
304 }
305
306 static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object,
307                 GDBusMethodInvocation *invocation,
308                 gpointer user_data)
309 {
310         int ret = MESHD_ERROR_NONE;
311         mesh_service *service = (mesh_service *)user_data;
312
313         GVariantBuilder builder;
314         GVariant* networks;
315         GList *iter = NULL;
316         mesh_scan_result_s *scan_item = NULL;
317
318         MESH_LOGD("Request to get scanned mesh network list");
319
320         ret = mesh_request_get_networks(service);
321         if (MESHD_ERROR_NONE != ret)
322                 MESH_LOGE("Failed to mesh_request_get_networks");
323
324         g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
325
326         /* scanned_mesh_network would be filled above request */
327         iter = service->scanned_mesh_network;
328         while (iter != NULL) {
329                 scan_item = (mesh_scan_result_s*)iter->data;
330
331                 g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
332                 g_variant_builder_add(&builder, "{sv}", "mesh_id",
333                                 g_variant_new_string(scan_item->mesh_id));
334                 g_variant_builder_add(&builder, "{sv}", "bssid",
335                                 g_variant_new_string(scan_item->bssid));
336                 g_variant_builder_add(&builder, "{sv}", "rssi",
337                                 g_variant_new_int32(scan_item->rssi));
338                 g_variant_builder_add(&builder, "{sv}", "channel",
339                                 g_variant_new_uint32(scan_item->channel));
340                 g_variant_builder_add(&builder, "{sv}", "security",
341                                 g_variant_new_uint32((int)scan_item->security));
342                 g_variant_builder_add(&builder, "{sv}", "state",
343                                 g_variant_new_uint32(scan_item->state));
344                 g_variant_builder_close(&builder);
345
346                 iter = g_list_next(iter);
347         }
348
349         networks = g_variant_builder_end(&builder);
350
351         net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret);
352
353         return TRUE;
354 }
355
356 static gboolean _meshd_dbus_handle_enable_mesh(NetMesh *object,
357                 GDBusMethodInvocation *invocation,
358                 gpointer user_data)
359 {
360         int ret = MESHD_ERROR_NONE;
361         mesh_service *service = (mesh_service *)user_data;
362
363         /* It handles creating virtual network and bridge */
364         ret = mesh_request_enable_network(service);
365         if (MESHD_ERROR_NONE != ret)
366                 MESH_LOGE("Failed to mesh_request_enable_network [%d]", ret);
367
368 #if 0
369         /* Detect external network state (i.e. Ethernet)
370                         and decide to make gate enabled */
371         ret = mesh_request_set_mesh_gate(info->bridge_interface,
372                         info->mesh_interface, info->external_interface);
373         if (MESHD_ERROR_NONE != ret)
374                 MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret);
375 #endif
376
377         net_mesh_complete_enable_mesh(object, invocation, ret);
378
379         return TRUE;
380 }
381
382 static gboolean _meshd_dbus_handle_disable_mesh(NetMesh *object,
383                 GDBusMethodInvocation *invocation,
384                 gpointer user_data)
385 {
386         int ret = MESHD_ERROR_NONE;
387         mesh_service *service = (mesh_service *)user_data;
388         mesh_interface_s *info = service->interface_info;
389
390         meshd_check_null_ret_error("info", info, FALSE);
391
392         if (FALSE == service->mesh_activated) {
393                 MESH_LOGD("Mesh network is not activated yet");
394                 ret = MESHD_ERROR_OPERATION_FAILED;
395                 net_mesh_complete_disable_mesh(object, invocation, ret);
396                 return TRUE;
397         }
398
399         ret = mesh_request_disable_network(service);
400         if (MESHD_ERROR_NONE != ret)
401                 MESH_LOGE("Failed to disable mesh network !");
402
403         /* Make response */
404         net_mesh_complete_disable_mesh(object, invocation, ret);
405
406         return TRUE;
407 }
408
409 static gboolean _meshd_dbus_handle_get_joined_mesh_network(NetMesh *object,
410                 GDBusMethodInvocation *invocation,
411                 gpointer user_data)
412 {
413         int ret = MESHD_ERROR_NONE;
414         mesh_service *service = (mesh_service *)user_data;
415         mesh_network_info_s *joined = NULL;
416
417         ret = mesh_request_get_joined_network(service);
418         if (MESHD_ERROR_NONE == ret) {
419                 joined = service->joined_network;
420                 if (joined) {
421                         net_mesh_complete_get_joined_mesh_network(object, invocation,
422                                 joined->mesh_id, joined->bssid,
423                                 joined->channel, (int)joined->security,
424                                 joined->state, ret);
425                 } else {
426                         net_mesh_complete_get_joined_mesh_network(object, invocation,
427                                 "", "", 0, 0, 0, MESHD_ERROR_NO_DATA);
428                 }
429         } else {
430                 net_mesh_complete_get_joined_mesh_network(object, invocation,
431                         "", "", 0, 0, 0, ret);
432         }
433
434         return TRUE;
435 }
436
437 static gboolean _meshd_dbus_handle_get_connected_peers(NetMesh *object,
438                 GDBusMethodInvocation *invocation,
439                 gpointer user_data)
440 {
441         int ret = MESHD_ERROR_NONE;
442         mesh_service *service = (mesh_service *)user_data;
443
444         GVariantBuilder builder;
445         GVariant* peer_list;
446         GList *iter = NULL;
447         mesh_peer_info_s *peer = NULL;
448
449         MESH_LOGD("Request to get connected peers");
450
451         ret = mesh_request_get_connected_peers(service);
452         if (MESHD_ERROR_NONE != ret)
453                 MESH_LOGE("Failed to mesh_request_get_connected_peers");
454         g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
455
456         iter = service->connected_mesh_peers;
457         while (iter != NULL) {
458                 peer = (mesh_peer_info_s*)iter->data;
459
460                 g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
461                 g_variant_builder_add(&builder, "{sv}", "Address",
462                                 g_variant_new_string(peer->address));
463                 g_variant_builder_close(&builder);
464
465                 iter = g_list_next(iter);
466         }
467
468         peer_list = g_variant_builder_end(&builder);
469
470         net_mesh_complete_get_connected_peers(object, invocation, peer_list, ret);
471
472         return TRUE;
473 }
474
475 static gboolean _meshd_dbus_handle_set_gate(NetMesh *object,
476                 GDBusMethodInvocation *invocation, gboolean stp, gboolean gate_announce,
477                 gpointer user_data)
478 {
479         int ret = MESHD_ERROR_NONE;
480         mesh_service *service = (mesh_service *)user_data;
481         mesh_interface_s *info = service->interface_info;
482
483         MESH_LOGD("STP = %d", stp);
484         MESH_LOGD("gate_announce = %d", gate_announce);
485
486         /* Set STP and gate_announce */
487         ret = mesh_request_set_mesh_gate(info->bridge_interface,
488                         info->mesh_interface, info->external_interface);
489         if (MESHD_ERROR_NONE != ret)
490                 MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret);
491
492         net_mesh_complete_set_gate(object, invocation, ret);
493
494         return TRUE;
495 }
496
497 static gboolean _meshd_dbus_handle_unset_gate(NetMesh *object,
498                 GDBusMethodInvocation *invocation,
499                 gpointer user_data)
500 {
501         int ret = MESHD_ERROR_NONE;
502         mesh_service *service = (mesh_service *)user_data;
503         mesh_interface_s *info = service->interface_info;
504
505         ret = mesh_request_unset_mesh_gate(info->bridge_interface,
506                         info->mesh_interface, info->external_interface);
507         if (MESHD_ERROR_NONE != ret)
508                 MESH_LOGE("Failed to mesh_request_unset_mesh_gate [%d]", ret);
509
510         net_mesh_complete_unset_gate(object, invocation, ret);
511
512         return TRUE;
513 }
514
515 static gboolean _meshd_dbus_handle_set_softap(NetMesh *object,
516                 GDBusMethodInvocation *invocation,
517                 gchar *ssid, gchar *passphrase,
518                 gchar *mode, gint channel, gint visibility, gint max_sta,
519                 gint security, gpointer user_data)
520 {
521         int ret = MESHD_ERROR_NONE;
522         mesh_service *service = (mesh_service *)user_data;
523         mesh_interface_s *info = service->interface_info;
524
525         MESH_LOGD("SSID      : %s", ssid);
526         MESH_LOGD("mode      : %s", mode);
527         MESH_LOGD("channel   : %d", channel);
528         MESH_LOGD("visibility: %d", visibility);
529         MESH_LOGD("max_sta   : %d", max_sta);
530         MESH_LOGD("security  : %d", security);
531
532         /* Save softAP information */
533         ret = mesh_request_set_softap_config(info->softap_interface,
534                 ssid, mode, channel, visibility, max_sta,
535                 security, passphrase);
536         if (MESHD_ERROR_NONE != ret)
537                 MESH_LOGE("Failed to mesh_request_set_softap_config [%d]", ret);
538
539         net_mesh_complete_set_softap(object, invocation, ret);
540
541         return TRUE;
542 }
543
544 static gboolean _meshd_dbus_handle_enable_softap(NetMesh *object,
545                 GDBusMethodInvocation *invocation, gpointer user_data)
546 {
547         int ret = MESHD_ERROR_NONE;
548         mesh_service *service = (mesh_service *)user_data;
549         mesh_interface_s *info = service->interface_info;
550
551         /* Check softAP interface and execute it */
552         ret = mesh_request_enable_softap(info->bridge_interface, info->softap_interface);
553         if (MESHD_ERROR_NONE != ret)
554                 MESH_LOGE("Failed to mesh_request_enable_softap [%d]", ret);
555
556         net_mesh_complete_enable_softap(object, invocation, ret);
557
558         return TRUE;
559 }
560
561 static gboolean _meshd_dbus_handle_disable_softap(NetMesh *object,
562                 GDBusMethodInvocation *invocation, gpointer user_data)
563 {
564         int ret = MESHD_ERROR_NONE;
565         mesh_service *service = (mesh_service *)user_data;
566         mesh_interface_s *info = service->interface_info;
567
568         /* Destroy softAP */
569         ret = mesh_request_disable_softap(info->bridge_interface, info->softap_interface);
570         if (MESHD_ERROR_NONE != ret)
571                 MESH_LOGE("Failed to mesh_request_disable_softap [%d]", ret);
572
573         net_mesh_complete_disable_softap(object, invocation, ret);
574
575         return TRUE;
576 }
577
578 static gboolean _meshd_dbus_handle_create_mesh_network(NetMesh *object,
579                 GDBusMethodInvocation *invocation,
580                 gchar *mesh_id, gint channel, gint security,
581                 gpointer user_data)
582 {
583         int ret = MESHD_ERROR_NONE;
584         mesh_service *service = (mesh_service *)user_data;
585         meshd_security_type_e sec = (1 == security) ? MESHD_SECURITY_SAE : MESHD_SECURITY_NONE;
586
587         ret = mesh_request_create_mesh_network(service, mesh_id, channel, sec);
588
589         net_mesh_complete_create_mesh_network(object, invocation, ret);
590
591         return TRUE;
592 }
593
594 static gboolean _meshd_dbus_handle_connect_mesh_network(NetMesh *object,
595                 GDBusMethodInvocation *invocation,
596                 gchar *mesh_id, gint channel, gint security, gchar *passphrase,
597                 gpointer user_data)
598 {
599         int ret = MESHD_ERROR_NONE;
600         mesh_service *service = (mesh_service *)user_data;
601         meshd_security_type_e sec = (1 == security) ? MESHD_SECURITY_SAE : MESHD_SECURITY_NONE;
602
603         ret = mesh_request_connect_mesh_network(service, mesh_id, channel, sec, passphrase);
604
605         net_mesh_complete_connect_mesh_network(object, invocation, ret);
606
607         return TRUE;
608 }
609 static gboolean _meshd_dbus_handle_disconnect_mesh_network(NetMesh *object,
610                 GDBusMethodInvocation *invocation,
611                 gchar *mesh_id, gint channel, gint security,
612                 gpointer user_data)
613 {
614         int ret = MESHD_ERROR_NONE;
615         mesh_service *service = (mesh_service *)user_data;
616         meshd_security_type_e sec = (1 == security) ? MESHD_SECURITY_SAE : MESHD_SECURITY_NONE;
617
618         ret = mesh_request_disconnect_mesh_network(service, mesh_id, channel, sec);
619
620         net_mesh_complete_disconnect_mesh_network(object, invocation, ret);
621
622         return TRUE;
623 }
624
625 static gboolean _meshd_dbus_handle_forget_mesh_network(NetMesh *object,
626                 GDBusMethodInvocation *invocation,
627                 gchar *mesh_id, gint channel, gint security,
628                 gpointer user_data)
629 {
630         int ret = MESHD_ERROR_NONE;
631         mesh_service *service = (mesh_service *)user_data;
632         meshd_security_type_e sec = (1 == security) ? MESHD_SECURITY_SAE : MESHD_SECURITY_NONE;
633
634         ret = mesh_request_remove_mesh_network(service, mesh_id, channel, sec);
635
636         net_mesh_complete_forget_mesh_network(object, invocation, ret);
637
638         return TRUE;
639 }
640
641 static gboolean _meshd_dbus_handle_set_interfaces(NetMesh *object,
642                 GDBusMethodInvocation *invocation,
643                 gchar *mesh, gchar *gate, gchar *softap,
644                 gpointer user_data)
645 {
646         int ret = MESHD_ERROR_NONE;
647         mesh_service *service = (mesh_service *)user_data;
648         mesh_interface_s *info = service->interface_info;
649
650         g_free(info->mesh_interface);
651         info->mesh_interface = g_strdup(mesh);
652
653         g_free(info->external_interface);
654         info->external_interface = g_strdup(gate);
655
656         g_free(info->softap_interface);
657         info->softap_interface = g_strdup(softap);
658
659         MESH_LOGD("Interface configuration for mesh network :");
660         MESH_LOGD("  Base    : [%s]", info->base_interface);
661         MESH_LOGD("  Mesh    : [%s]", info->mesh_interface);
662         MESH_LOGD("  Bridge  : [%s]", info->bridge_interface);
663         MESH_LOGD("  SoftAP  : [%s]", info->softap_interface);
664         MESH_LOGD("  External: [%s]", info->external_interface);
665
666         net_mesh_complete_set_interfaces(object, invocation, ret);
667
668         return TRUE;
669 }
670
671 static gboolean _meshd_dbus_handle_get_station_info(NetMesh *object,
672                 GDBusMethodInvocation *invocation,
673                 gpointer user_data)
674 {
675         int ret = MESHD_ERROR_NONE;
676
677         GVariantBuilder builder;
678         GVariant* station;
679         GList *iter = NULL;
680
681         mesh_service *service = (mesh_service *)user_data;
682         mesh_interface_s *info = service->interface_info;
683
684         /* Clear mesh station list */
685         g_list_free_full(service->station_list, _on_station_list_destroy);
686         service->station_list = NULL;
687
688         ret = mesh_request_get_station_info(
689                                 info->mesh_interface, &service->station_list);
690         if (MESHD_ERROR_NONE != ret) {
691                 MESH_LOGE("Failed to mesh_request_get_station_info");
692
693                 g_dbus_method_invocation_return_error(invocation,
694                                 G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
695         } else {
696         /*
697          * sh-3.2#  iw mesh0 station dump
698          * Station 7c:dd:90:62:37:cf (on mesh0)
699          * inactive time:       1685 ms
700          * rx bytes:    34174
701          * rx packets:  1181
702          * tx bytes:    6877
703          * tx packets:  76
704          * tx retries:  0
705          * tx failed:   0
706          * beacon loss: 0
707          * signal:              -64 dBm
708          * signal avg:  -63 dBm
709          * tx bitrate:  54.0 MBit/s
710          * rx bitrate:  5.5 MBit/s
711          * mesh llid:   51731
712          * mesh plid:   35432
713          * mesh plink:  ESTAB
714          * mesh local PS mode:  ACTIVE
715          * mesh peer PS mode:   ACTIVE
716          * mesh non-peer PS mode:       ACTIVE
717          * authorized:  yes
718          * authenticated:       yes
719          * associated:  yes
720          * preamble:    long
721          * WMM/WME:     yes
722          * MFP:         no
723          * TDLS peer:   no
724          * DTIM period: 0
725          * beacon interval:1000
726          * short slot time:yes
727          * connected time:      256 seconds
728          */
729                 /* Get station information and make variant data */
730                 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
731
732                 iter = service->station_list;
733                 while (iter != NULL) {
734                         mesh_station_info_s *item = (mesh_station_info_s*)iter->data;
735
736                         g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
737                         g_variant_builder_add(&builder, "{sv}", "bssid",
738                                                 g_variant_new_string(item->bssid));
739                         g_variant_builder_add(&builder, "{sv}", "inactive_time",
740                                                 g_variant_new_uint32(item->inactive_time));
741                         g_variant_builder_add(&builder, "{sv}", "rx_bytes",
742                                                 g_variant_new_uint64(item->rx_bytes));
743                         g_variant_builder_add(&builder, "{sv}", "rx_packets",
744                                                 g_variant_new_uint32(item->rx_packets));
745                         g_variant_builder_add(&builder, "{sv}", "tx_bytes",
746                                                 g_variant_new_uint64(item->tx_bytes));
747                         g_variant_builder_add(&builder, "{sv}", "tx_packets",
748                                                 g_variant_new_uint32(item->tx_packets));
749                         g_variant_builder_add(&builder, "{sv}", "tx_retries",
750                                                 g_variant_new_uint32(item->tx_retries));
751                         g_variant_builder_add(&builder, "{sv}", "tx_failed",
752                                                 g_variant_new_uint32(item->tx_failed));
753                         g_variant_builder_add(&builder, "{sv}", "beacon_loss",
754                                                 g_variant_new_uint32(item->beacon_loss));
755                         g_variant_builder_add(&builder, "{sv}", "beacon_rx",
756                                                 g_variant_new_uint64(item->beacon_rx));
757                         g_variant_builder_add(&builder, "{sv}", "rx_drop_misc",
758                                                 g_variant_new_uint64(item->rx_drop_misc));
759                         g_variant_builder_add(&builder, "{sv}", "signal",
760                                                 g_variant_new_int32(item->rssi));
761                         g_variant_builder_add(&builder, "{sv}", "signal_avg",
762                                                 g_variant_new_int32(item->rssi_avg));
763                         g_variant_builder_add(&builder, "{sv}", "tx_bitrate",
764                                                 g_variant_new_uint32(item->tx_bitrate)); /* 10 times */
765                         g_variant_builder_add(&builder, "{sv}", "rx_bitrate",
766                                                 g_variant_new_uint32(item->rx_bitrate)); /* 10 times */
767                         g_variant_builder_add(&builder, "{sv}", "mesh_llid",
768                                                 g_variant_new_uint16(item->llid));
769                         g_variant_builder_add(&builder, "{sv}", "mesh_plid",
770                                                 g_variant_new_uint16(item->plid));
771                         g_variant_builder_add(&builder, "{sv}", "mesh_plink",
772                                                 g_variant_new_byte(item->mesh_plink)); /* 0 : DISCON, 1 : ESTAB */
773                         g_variant_builder_add(&builder, "{sv}", "local_ps_mode",
774                                                 g_variant_new_uint32(item->local_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
775                         g_variant_builder_add(&builder, "{sv}", "peer_ps_mode",
776                                                 g_variant_new_uint32(item->peer_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
777                         g_variant_builder_add(&builder, "{sv}", "non_peer_ps_mode",
778                                                 g_variant_new_uint32(item->non_peer_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
779                         g_variant_builder_add(&builder, "{sv}", "authorized",
780                                                 g_variant_new_boolean(item->authorized));
781                         g_variant_builder_add(&builder, "{sv}", "associated",
782                                                 g_variant_new_boolean(item->associated));
783                         g_variant_builder_add(&builder, "{sv}", "preamble",
784                                                 g_variant_new_boolean(item->preamble));
785                         g_variant_builder_add(&builder, "{sv}", "WMM_WME",
786                                                 g_variant_new_boolean(item->wme));
787                         g_variant_builder_add(&builder, "{sv}", "MFP",
788                                                 g_variant_new_boolean(item->mfp));
789                         g_variant_builder_add(&builder, "{sv}", "TDLS_peer",
790                                                 g_variant_new_boolean(item->tdls_peer));
791                         g_variant_builder_add(&builder, "{sv}", "DTIM_period",
792                                                 g_variant_new_byte(item->dtim_period));
793                         g_variant_builder_add(&builder, "{sv}", "beacon_interval",
794                                                 g_variant_new_uint16(item->beacon_interval));
795                         g_variant_builder_add(&builder, "{sv}", "short_slot_time",
796                                                 g_variant_new_boolean(item->short_slot_time));
797                         g_variant_builder_add(&builder, "{sv}", "connected_time",
798                                                 g_variant_new_uint32(item->connected_time));
799                         g_variant_builder_close(&builder);
800
801                         iter = g_list_next(iter);
802                 }
803
804                 station = g_variant_builder_end(&builder);
805                 net_mesh_complete_get_station_info(object, invocation, station, ret);
806
807                 g_object_unref(station);
808         }
809
810         return TRUE;
811 }
812
813 static gboolean _meshd_dbus_handle_get_mpath_info(NetMesh *object,
814                 GDBusMethodInvocation *invocation,
815                 gpointer user_data)
816 {
817         int ret = MESHD_ERROR_NONE;
818         GVariantBuilder builder;
819         GVariant* mpath_data;
820         GList *iter = NULL;
821
822         mesh_service *service = (mesh_service *)user_data;
823         mesh_interface_s *info = service->interface_info;
824
825         /* Clear mesh path list */
826         g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
827         service->mpath_list = NULL;
828
829         ret = mesh_request_get_mpath_info(
830                                 info->mesh_interface, &service->mpath_list);
831         if (MESHD_ERROR_NONE != ret) {
832                 MESH_LOGE("Failed to mesh_request_get_mpath_info");
833
834                 g_dbus_method_invocation_return_error(invocation,
835                                 G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
836         } else {
837         /*
838          * Example) sh-3.2# iw mesh0 mpath dump
839          * DEST ADDR         NEXT HOP          IFACE    SN      METRIC  QLEN    EXPTIME         DTIM    DRET    FLAGS
840          * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0    221     152             0               10                      100             0               0x5
841          */
842                 /* Get mesh path information and make variant data */
843                 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
844
845                 iter = service->mpath_list;
846                 while (iter != NULL) {
847                         mesh_mpath_info_s *item = (mesh_mpath_info_s*)iter->data;
848
849                         g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
850                         g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
851                                                 g_variant_new_string(item->dest_addr));
852                         g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
853                                                 g_variant_new_string(item->next_hop));
854                         g_variant_builder_add(&builder, "{sv}", "IFACE",
855                                                 g_variant_new_string(item->interface));
856                         g_variant_builder_add(&builder, "{sv}", "SN",
857                                                 g_variant_new_uint32(item->sn));
858                         g_variant_builder_add(&builder, "{sv}", "METRIC",
859                                                 g_variant_new_uint32(item->metric));
860                         g_variant_builder_add(&builder, "{sv}", "QLEN",
861                                                 g_variant_new_uint32(item->qlen));
862                         g_variant_builder_add(&builder, "{sv}", "EXPTIME",
863                                                 g_variant_new_uint32(item->exptime));
864                         g_variant_builder_add(&builder, "{sv}", "DTIM",
865                                                 g_variant_new_uint32(item->discovery_timeout));
866                         g_variant_builder_add(&builder, "{sv}", "DRET",
867                                                 g_variant_new_byte(item->discovery_retries));
868                         g_variant_builder_add(&builder, "{sv}", "FLAGS",
869                                                 g_variant_new_byte(item->flags));
870                         g_variant_builder_close(&builder);
871
872                         iter = g_list_next(iter);
873                 }
874
875                 mpath_data = g_variant_builder_end(&builder);
876                 net_mesh_complete_get_mpath_info(object, invocation, mpath_data, ret);
877
878                 g_object_unref(mpath_data);
879         }
880
881         return TRUE;
882 }
883
884 static void _meshd_dbus_on_activator_bus_acquired(GDBusConnection *conn,
885                 const gchar *name, gpointer user_data)
886 {
887         gboolean ret;
888         GError *error = NULL;
889         mesh_service *service = (mesh_service *)user_data;
890
891         NOTUSED(name);
892
893         meshd_activator_dbus_object = manager_skeleton_new();
894         if (NULL == meshd_activator_dbus_object) {
895                 MESH_LOGE("manager_skeleton_new() Fail");
896                 return;
897         }
898
899         g_signal_connect(meshd_activator_dbus_object, "handle-enable",
900                         G_CALLBACK(_meshd_dbus_handle_enable), service);
901         g_signal_connect(meshd_activator_dbus_object, "handle-disable",
902                         G_CALLBACK(_meshd_dbus_handle_disable), service);
903
904         ret = g_dbus_interface_skeleton_export(
905                                 G_DBUS_INTERFACE_SKELETON(meshd_activator_dbus_object),
906                                 conn, MESH_DBUS_MANAGER_OBJPATH, &error);
907         if (FALSE == ret) {
908                 MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
909                 g_error_free(error);
910         }
911 }
912
913 static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
914                 gpointer user_data)
915 {
916         gboolean ret;
917         GError *error = NULL;
918         mesh_service *service = (mesh_service *)user_data;
919
920         NOTUSED(name);
921
922         meshd_dbus_object = net_mesh_skeleton_new();
923         if (NULL == meshd_dbus_object) {
924                 MESH_LOGE("net_mesh_skeleton_new() Fail");
925                 return;
926         }
927
928         g_signal_connect(meshd_dbus_object, "handle-scan",
929                         G_CALLBACK(_meshd_dbus_handle_scan), service);
930         g_signal_connect(meshd_dbus_object, "handle-specific-scan",
931                         G_CALLBACK(_meshd_dbus_handle_specific_scan), service);
932         g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
933                         G_CALLBACK(_meshd_dbus_handle_cancel_scan), service);
934         g_signal_connect(meshd_dbus_object, "handle-get-found-mesh-networks",
935                         G_CALLBACK(_meshd_dbus_handle_get_found_mesh_networks), service);
936         g_signal_connect(meshd_dbus_object, "handle-enable-mesh",
937                         G_CALLBACK(_meshd_dbus_handle_enable_mesh), service);
938         g_signal_connect(meshd_dbus_object, "handle-disable-mesh",
939                         G_CALLBACK(_meshd_dbus_handle_disable_mesh), service);
940         g_signal_connect(meshd_dbus_object, "handle-get-joined-mesh-network",
941                         G_CALLBACK(_meshd_dbus_handle_get_joined_mesh_network), service);
942         g_signal_connect(meshd_dbus_object, "handle-get-connected-peers",
943                         G_CALLBACK(_meshd_dbus_handle_get_connected_peers), service);
944         g_signal_connect(meshd_dbus_object, "handle-set-gate",
945                         G_CALLBACK(_meshd_dbus_handle_set_gate), service);
946         g_signal_connect(meshd_dbus_object, "handle-unset-gate",
947                         G_CALLBACK(_meshd_dbus_handle_unset_gate), service);
948         g_signal_connect(meshd_dbus_object, "handle-set-softap",
949                         G_CALLBACK(_meshd_dbus_handle_set_softap), service);
950         g_signal_connect(meshd_dbus_object, "handle-enable-softap",
951                         G_CALLBACK(_meshd_dbus_handle_enable_softap), service);
952         g_signal_connect(meshd_dbus_object, "handle-disable-softap",
953                         G_CALLBACK(_meshd_dbus_handle_disable_softap), service);
954         g_signal_connect(meshd_dbus_object, "handle-create-mesh-network",
955                         G_CALLBACK(_meshd_dbus_handle_create_mesh_network), service);
956         g_signal_connect(meshd_dbus_object, "handle-connect-mesh-network",
957                         G_CALLBACK(_meshd_dbus_handle_connect_mesh_network), service);
958         g_signal_connect(meshd_dbus_object, "handle-disconnect-mesh-network",
959                         G_CALLBACK(_meshd_dbus_handle_disconnect_mesh_network), service);
960         g_signal_connect(meshd_dbus_object, "handle-forget-mesh-network",
961                         G_CALLBACK(_meshd_dbus_handle_forget_mesh_network), service);
962         g_signal_connect(meshd_dbus_object, "handle-set-interfaces",
963                         G_CALLBACK(_meshd_dbus_handle_set_interfaces), service);
964         g_signal_connect(meshd_dbus_object, "handle-get-station-info",
965                         G_CALLBACK(_meshd_dbus_handle_get_station_info), service);
966         g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
967                         G_CALLBACK(_meshd_dbus_handle_get_mpath_info), service);
968
969         ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
970                         conn, MESH_DBUS_OBJPATH, &error);
971         if (FALSE == ret) {
972                 MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
973                 g_error_free(error);
974         }
975
976         ret = _meshd_dbus_subscribe_name_owner_changed(conn);
977         if (MESHD_ERROR_NONE != ret) {
978                 MESH_LOGE("_meshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
979                 return;
980         }
981 }
982
983 static void _meshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
984                 gpointer user_data)
985 {
986         NOTUSED(conn);
987         NOTUSED(user_data);
988
989         MESH_LOGD("Lost the name %s", name);
990 }
991
992 static void _meshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
993                 gpointer user_data)
994 {
995         NOTUSED(conn);
996         NOTUSED(user_data);
997
998         MESH_LOGD("Acquired the name %s", name);
999 }
1000
1001 static gboolean _meshd_dbus_interface_init(mesh_service *service)
1002 {
1003         guint id;
1004         guint activation_dbus_id;
1005         meshd_check_null_ret_error("service", service, FALSE);
1006
1007         id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1008                         MESH_DBUS_INTERFACE,
1009                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
1010                         _meshd_dbus_on_bus_acquired,
1011                         _meshd_dbus_on_name_acquired,
1012                         _meshd_dbus_on_name_lost,
1013                         service,
1014                         NULL);
1015         if (0 == id) {
1016                 MESH_LOGE("g_bus_own_name() Fail");
1017                 return FALSE;
1018         }
1019
1020         /* Get D-Bus owner to activate mesh service daemon */
1021         activation_dbus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
1022                         MESH_DBUS_INTERFACE".manager",
1023                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
1024                         _meshd_dbus_on_activator_bus_acquired,
1025                         NULL,
1026                         NULL,
1027                         service,
1028                         NULL);
1029
1030         service->dbus_id = id;
1031         service->activation_dbus_id = activation_dbus_id;
1032         service->interface_info = g_new0(mesh_interface_s, 1);
1033         service->scanned_mesh_network = NULL;
1034
1035         /* Initialize DBus sendor logic */
1036         meshd_dbus_start(service);
1037
1038         return TRUE;
1039 }
1040
1041 static void _meshd_dbus_deinit(mesh_service *service)
1042 {
1043         mesh_interface_s *info = NULL;
1044         meshd_check_null_ret("service", service);
1045
1046         /* De-Initialize DBus sendor logic */
1047         meshd_dbus_stop(service);
1048
1049         g_bus_unown_name(service->dbus_id);
1050         g_bus_unown_name(service->activation_dbus_id);
1051
1052         info = service->interface_info;
1053         meshd_check_null_ret("info", info);
1054         if (info->bridge_interface)
1055                 g_free(info->bridge_interface);
1056         if (info->base_interface)
1057                 g_free(info->base_interface);
1058         if (info->mesh_interface)
1059                 g_free(info->mesh_interface);
1060         if (info->softap_interface)
1061                 g_free(info->softap_interface);
1062         if (info->external_interface)
1063                 g_free(info->external_interface);
1064
1065         if (service->joined_network) {
1066                 g_free(service->joined_network->mesh_id);
1067                 g_free(service->joined_network->bssid);
1068                 g_free(service->joined_network);
1069                 service->joined_network = NULL;
1070         }
1071
1072         /* Clear scan list */
1073         g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
1074         service->scanned_mesh_network = NULL;
1075
1076         /* Clear connected peers list */
1077         g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
1078         service->connected_mesh_peers = NULL;
1079
1080         g_free(service->interface_info);
1081         service->interface_info = NULL;
1082 }
1083
1084 /**< Mesh service interface initialization */
1085 gboolean meshd_service_interface_init(mesh_service *service)
1086 {
1087         guint ret;
1088         meshd_check_null_ret_error("service", service, FALSE);
1089
1090         /* Initialize dbus interface */
1091         ret = _meshd_dbus_interface_init(service);
1092         if (FALSE == ret) {
1093                 MESH_LOGE("_meshd_dbus_interface_init failed!!!");
1094                 return FALSE;
1095         }
1096
1097         return TRUE;
1098 }
1099
1100 /**< Mesh service interface de-initialization */
1101 void meshd_service_interface_deinit(mesh_service *service)
1102 {
1103         meshd_check_null_ret("service", service);
1104
1105         /* De-initialize dbus interface */
1106         _meshd_dbus_deinit(service);
1107 }