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