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