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