c8123b386733374e1f0aa8414105ff6d630fd043
[platform/core/connectivity/wifi-mesh-manager.git] / src / wmesh-gdbus.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "wmesh-log.h"
18 #include "wmesh-util.h"
19 #include "wmesh-gdbus.h"
20 #include "wmesh-request.h"
21
22 #include <linux/nl80211.h>
23
24 static GDBusProxy *_gproxy_connman = NULL;
25 static GDBusProxy *_gproxy_connman_mesh = NULL;
26 static GDBusProxy *_gproxy_connman_technology = NULL;
27 static GDBusProxy *_gproxy_connman_ethernet = NULL;
28
29 static int _wmeshd_close_gdbus_call(wmesh_service *service);
30 static int _wmesh_gdbus_get_mesh_network_property(wmesh_service *service,
31         const gchar* object_path, wmesh_network_info_s *result);
32
33 static int __channel_to_frequency(int channel, enum nl80211_band band)
34 {
35         if (channel <= 0)
36                 return 0;
37
38         switch (band) {
39         case NL80211_BAND_2GHZ:
40                 if (channel == 14)
41                         return 2484;
42                 else if (channel < 14)
43                         return 2407 + channel * 5;
44                 break;
45         case NL80211_BAND_5GHZ:
46                 if (channel >= 182 && channel <= 196)
47                         return 4000 + channel * 5;
48                 else
49                         return 5000 + channel * 5;
50                 break;
51         default:
52                 break;
53         }
54
55         /* not supported */
56         return 0;
57 }
58
59 static int __frequency_to_channel(int freq)
60 {
61         if (freq == 2484)
62                 return 14;
63         else if (freq < 2484)
64                 return (freq - 2407) / 5;
65         else if (freq >= 4910 && freq <= 4980)
66                 return (freq - 4000) / 5;
67         else if (freq <= 45000)
68                 return (freq - 5000) / 5;
69         else if (freq >= 58320 && freq <= 64800)
70                 return (freq - 56160) / 2160;
71         else
72                 return 0;
73 }
74
75 static GDBusProxy *_proxy_get_connman(wmesh_service *service)
76 {
77         GDBusProxy *proxy = NULL;
78         wmeshd_check_null_ret_error("service", service, NULL);
79
80         if (NULL == _gproxy_connman) {
81                 proxy = g_dbus_proxy_new_sync(service->connection,
82                         G_DBUS_PROXY_FLAGS_NONE, NULL,
83                         CONNMAN_SERVER_NAME,
84                         CONNMAN_OBJECT_PATH,
85                         CONNMAN_INTERFACE_MANAGER,
86                         NULL, NULL);
87         } else
88                 proxy = _gproxy_connman;
89
90         return proxy;
91 }
92
93 static GDBusProxy *_proxy_get_connman_mesh(wmesh_service *service)
94 {
95         GDBusProxy *proxy = NULL;
96         wmeshd_check_null_ret_error("service", service, NULL);
97
98         if (NULL == _gproxy_connman_mesh) {
99                 proxy = g_dbus_proxy_new_sync(service->connection,
100                         G_DBUS_PROXY_FLAGS_NONE, NULL,
101                         CONNMAN_SERVER_NAME,
102                         CONNMAN_OBJECT_PATH_MESH,
103                         CONNMAN_INTERFACE_MESH,
104                         NULL, NULL);
105         } else
106                 proxy = _gproxy_connman_mesh;
107
108         return proxy;
109 }
110
111 static GDBusProxy *_proxy_get_connman_ethernet(wmesh_service *service)
112 {
113         GDBusProxy *proxy = NULL;
114         wmeshd_check_null_ret_error("service", service, NULL);
115
116         if (NULL == _gproxy_connman_ethernet) {
117                 proxy = g_dbus_proxy_new_sync(service->connection,
118                         G_DBUS_PROXY_FLAGS_NONE, NULL,
119                         CONNMAN_SERVER_NAME, /* Name */
120                         "/net/connman/technology/ethernet", /* Object Path */
121                         CONNMAN_INTERFACE_TECH, /* interface Name */
122                         NULL, NULL);
123         } else
124                 proxy = _gproxy_connman_ethernet;
125
126         return proxy;
127 }
128
129 static GDBusProxy *_proxy_get_connman_technology(wmesh_service *service)
130 {
131         GDBusProxy *proxy = NULL;
132         wmeshd_check_null_ret_error("service", service, NULL);
133
134         if (NULL == _gproxy_connman_technology) {
135                 proxy = g_dbus_proxy_new_sync(service->connection,
136                         G_DBUS_PROXY_FLAGS_NONE, NULL,
137                         CONNMAN_SERVER_NAME,
138                         CONNMAN_OBJECT_PATH_TECH_MESH,
139                         CONNMAN_INTERFACE_TECH,
140                         NULL, NULL);
141         } else
142                 proxy = _gproxy_connman_technology;
143
144         return proxy;
145 }
146
147 static void _dbus_name_owner_notify(GObject *object, GParamSpec *pspec,
148                 gpointer *user_data)
149 {
150         GDBusProxy *proxy = G_DBUS_PROXY(object);
151         gchar *name_owner = g_dbus_proxy_get_name_owner(proxy);
152         wmesh_service *service = (wmesh_service*)user_data;
153
154         NOTUSED(pspec);
155
156         if (NULL == name_owner) {
157                 WMESH_LOGE("name_owner is not exists !");
158                 _wmeshd_close_gdbus_call(service);
159         }
160
161         g_free(name_owner);
162 }
163
164 static int _wmeshd_create_gdbus_call(wmesh_service *service)
165 {
166         int id;
167         GError *error = NULL;
168
169         if (NULL == service)
170                 return WMESHD_ERROR_INVALID_PARAMETER;
171
172         if (NULL != service->connection)
173                 return WMESHD_ERROR_ALREADY_REGISTERED;
174
175         service->connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
176         if (service->connection == NULL) {
177                 if (error != NULL) {
178                         WMESH_LOGE("Failed to connect to the D-BUS daemon [%s]", error->message);
179                         g_error_free(error);
180                 }
181                 return WMESHD_ERROR_IO_ERROR;
182         }
183
184         id = g_signal_connect(service->connection, "notify::g-name-owner",
185                         G_CALLBACK(_dbus_name_owner_notify), service);
186         if (0 == id) {
187                 WMESH_LOGE("g_signal_connect() Fail");
188                 g_object_unref(service->connection);
189                 service->connection = NULL;
190                 return WMESHD_ERROR_IO_ERROR;
191         }
192
193         return WMESHD_ERROR_NONE;
194 }
195
196 static int _wmeshd_close_gdbus_call(wmesh_service *service)
197 {
198         /* CHECK: is connection ref count required? */
199         g_object_unref(service->connection);
200         service->connection = NULL;
201
202         return WMESHD_ERROR_NONE;
203 }
204
205 static void _wmeshd_signal_handler(GDBusConnection *connection,
206                 const gchar *sender_name, const gchar *object_path, const gchar *interface_name,
207                 const gchar *signal_name, GVariant *parameters, gpointer user_data)
208 {
209         wmesh_service *service = (wmesh_service*)user_data;
210         wmesh_network_info_s network_info = { 0, 0, 0, 0, 0, 0, 0, 0};
211         int ret = WMESHD_ERROR_NONE;
212
213         wmeshd_check_null_ret("user_data", user_data);
214         NOTUSED(connection);
215         NOTUSED(sender_name);
216         NOTUSED(interface_name);
217
218         WMESH_LOGD("signal received = %s", signal_name);
219         if (0 == g_strcmp0(signal_name, "ScanDone")) {
220                 /* TODO: Handle event */
221                 wmesh_notify_scan_done();
222         } else if (0 == g_strcmp0(signal_name, "PropertyChanged")) {
223                 const gchar* var = NULL;
224                 gchar* key = NULL;
225                 GVariant *variant = NULL;
226                 wmeshd_connection_state_e state = WMESHD_CONNECTION_STATE_DISCONNECTED;
227
228                 if (NULL == parameters) {
229                         WMESH_LOGE("Unexpected parameter");
230                         return;
231                 }
232
233                 g_variant_get(parameters, "(sv)", &key, &variant);
234                 if (NULL == variant) {
235                         WMESH_LOGE("Invalid variant");
236                         return;
237                 }
238
239                 /* State [???] */
240                 var = g_variant_get_string(variant, NULL);
241                 WMESH_LOGD("  %s [%s]", key, var);
242                 WMESH_LOGD("    %s", object_path);
243
244                 ret = _wmesh_gdbus_get_mesh_network_property(service, object_path, &network_info);
245                 if (WMESHD_ERROR_NONE != ret)
246                         WMESH_LOGE("Cannot get valid network property !");
247
248                 if (g_strcmp0("association", var) == 0) {
249                         /* Joined mesh network */
250                         state = WMESHD_CONNECTION_STATE_ASSOCIATION;
251                 } else if (g_strcmp0("configuration", var) == 0) {
252                         /* Trying to get IP address */
253                         state = WMESHD_CONNECTION_STATE_CONFIGURATION;
254                 } else if (g_strcmp0("ready", var) == 0 || g_strcmp0("online", var) == 0) {
255                         /* IP address is obtained */
256                         state = WMESHD_CONNECTION_STATE_CONNECTED;
257                 } else if (g_strcmp0("disconnect", var) == 0 || g_strcmp0("failure", var) == 0) {
258                         state = WMESHD_CONNECTION_STATE_DISCONNECTED;
259                 } else {
260                         WMESH_LOGE("  Unhandled state !");
261                         g_free(network_info.mesh_id);
262                         g_free(network_info.bssid);
263                         return;
264                 }
265
266                 wmesh_notify_connection_state(network_info.mesh_id, network_info.bssid,
267                         network_info.channel, network_info.security, state);
268
269                 g_free(network_info.mesh_id);
270                 g_free(network_info.bssid);
271         }
272 }
273
274 static void _wmeshd_subscribe_event(wmesh_service *service)
275 {
276         unsigned int id = 0;
277
278         wmeshd_check_null_ret("service", service);
279
280         id = g_dbus_connection_signal_subscribe(
281                         (GDBusConnection *)service->connection,
282                         CONNMAN_SERVER_NAME, CONNMAN_INTERFACE_MANAGER,
283                         "ScanDone", "/", NULL,
284                         G_DBUS_CALL_FLAGS_NONE, _wmeshd_signal_handler, service, NULL);
285         if (0 == id) {
286                 WMESH_LOGE("g_dbus_connection_signal_subscribe(ScanDone) Fail(%d)", errno);
287                 return;
288         }
289         service->dbus_sub_ids = g_list_append(service->dbus_sub_ids, GUINT_TO_POINTER(id));
290         WMESH_LOGD("[Signal subscribe] : ScanDone (%d)", id);
291
292         /* To monitor mesh profiles */
293         id = g_dbus_connection_signal_subscribe(
294                         (GDBusConnection *)service->connection,
295                         CONNMAN_SERVER_NAME,
296                         CONNMAN_INTERFACE_MESH,
297                         "PropertyChanged",
298                         NULL, /* Path */
299                         NULL,
300                         G_DBUS_CALL_FLAGS_NONE, _wmeshd_signal_handler, service, NULL);
301         if (0 == id) {
302                 WMESH_LOGE("g_dbus_connection_signal_subscribe(ScanDone) Fail(%d)", errno);
303                 return;
304         }
305         service->dbus_sub_ids = g_list_append(service->dbus_sub_ids, GUINT_TO_POINTER(id));
306         WMESH_LOGD("[Signal subscribe] : PropertyChanged (%d)", id);
307
308         /* End of subscription */
309 }
310
311 static void _on_unsubscribe_ids(gpointer data, gpointer user_data)
312 {
313         unsigned int id = GPOINTER_TO_UINT(data);
314         wmesh_service *service = (wmesh_service*)user_data;
315
316         WMESH_LOGD("[Signal unsubscribe] : %d", id);
317         g_dbus_connection_signal_unsubscribe(
318                 (GDBusConnection *)service->connection, id);
319 }
320
321 static void _wmeshd_unsubscribe_event(wmesh_service *service)
322 {
323         wmeshd_check_null_ret("service", service);
324
325         g_list_foreach(service->dbus_sub_ids, _on_unsubscribe_ids, service);
326
327         g_list_free(service->dbus_sub_ids);
328         service->dbus_sub_ids = NULL;
329 }
330
331 int wmeshd_dbus_start(wmesh_service *service)
332 {
333         int rv;
334
335         rv = _wmeshd_create_gdbus_call(service);
336         if (WMESHD_ERROR_NONE != rv)
337                 return rv;
338
339         service->ca = g_cancellable_new();
340
341         /* Create all required proxies here */
342         _gproxy_connman = _proxy_get_connman(service);
343         wmeshd_check_null_ret_error("_gproxy_connman", _gproxy_connman,
344                                 WMESHD_ERROR_IO_ERROR);
345         g_dbus_proxy_set_default_timeout(
346                         G_DBUS_PROXY(_gproxy_connman), WMESH_DBUS_PROXY_TIMEOUT);
347
348         _gproxy_connman_mesh = _proxy_get_connman_mesh(service);
349         wmeshd_check_null_ret_error("_gproxy_connman_mesh", _gproxy_connman_mesh,
350                                 WMESHD_ERROR_IO_ERROR);
351         g_dbus_proxy_set_default_timeout(
352                         G_DBUS_PROXY(_gproxy_connman_mesh), WMESH_DBUS_PROXY_TIMEOUT);
353
354         _gproxy_connman_technology = _proxy_get_connman_technology(service);
355         wmeshd_check_null_ret_error("_gproxy_connman_technology", _gproxy_connman_technology,
356                                 WMESHD_ERROR_IO_ERROR);
357         g_dbus_proxy_set_default_timeout(
358                         G_DBUS_PROXY(_gproxy_connman_technology), WMESH_DBUS_PROXY_TIMEOUT);
359
360         _gproxy_connman_ethernet = _proxy_get_connman_ethernet(service);
361         wmeshd_check_null_ret_error("_gproxy_connman_ethernet", _gproxy_connman_ethernet,
362                                 WMESHD_ERROR_IO_ERROR);
363         g_dbus_proxy_set_default_timeout(
364                         G_DBUS_PROXY(_gproxy_connman_ethernet), WMESH_DBUS_PROXY_TIMEOUT);
365
366         /* Subscribe events */
367         _wmeshd_subscribe_event(service);
368
369         return WMESHD_ERROR_NONE;
370 }
371
372 int wmeshd_dbus_stop(wmesh_service *service)
373 {
374         int rv;
375
376         if (NULL == service)
377                 return WMESHD_ERROR_INVALID_PARAMETER;
378
379         /* Unsubscribe events */
380         _wmeshd_unsubscribe_event(service);
381
382         /* Unref all proxies here */
383         if (_gproxy_connman) {
384                 g_object_unref(_gproxy_connman);
385                 _gproxy_connman = NULL;
386         }
387         if (_gproxy_connman_mesh) {
388                 g_object_unref(_gproxy_connman_mesh);
389                 _gproxy_connman_mesh = NULL;
390         }
391         if (_gproxy_connman_technology) {
392                 g_object_unref(_gproxy_connman_technology);
393                 _gproxy_connman_technology = NULL;
394         }
395
396         g_cancellable_cancel(service->ca);
397         g_object_unref(service->ca);
398         service->ca = NULL;
399
400         rv = _wmeshd_close_gdbus_call(service);
401         return rv;
402 }
403
404 int wmesh_gdbus_create_mesh_interface(wmesh_service *service)
405 {
406         int ret = WMESHD_ERROR_NONE;
407         GVariant *variant = NULL;
408         GError *error = NULL;
409         GVariant *var_dict = NULL;
410         GVariantDict dict;
411         wmesh_interface_s *info = NULL;
412
413         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
414         wmeshd_check_null_ret_error("connection", service->connection,
415                         WMESHD_ERROR_INVALID_PARAMETER);
416         wmeshd_check_null_ret_error("_gproxy_connman_technology",
417                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
418
419         info = service->interface_info;
420
421         g_variant_dict_init(&dict, NULL);
422         g_variant_dict_insert(&dict, "Ifname", "s", info->mesh_interface);
423         g_variant_dict_insert(&dict, "ParentIfname", "s", info->base_interface);
424         g_variant_dict_insert(&dict, "BridgeIfname", "s", info->bridge_interface);
425         var_dict = g_variant_dict_end(&dict);
426
427         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
428                                 g_variant_new("(sv)", "MeshInterfaceAdd", var_dict),
429                                 G_DBUS_CALL_FLAGS_NONE,
430                                 -1, NULL, &error);
431         if (variant) {
432                 WMESH_LOGD("Successfully requested. [MeshInterfaceAdd]");
433         } else if (error) {
434                 ret = WMESHD_ERROR_IO_ERROR;
435                 WMESH_LOGE("Failed DBus call [%s]", error->message);
436
437                 /* Interface not exists */
438                 if (g_strrstr(error->message, "No such device"))
439                         ret = WMESHD_ERROR_INVALID_PARAMETER;
440                 g_error_free(error);
441         }
442
443         return ret;
444 }
445
446 int wmesh_gdbus_remove_mesh_interface(wmesh_service *service)
447 {
448         int ret = WMESHD_ERROR_NONE;
449         GVariant *variant = NULL;
450         GError *error = NULL;
451         GVariant *var_dict = NULL;
452         GVariantDict dict;
453         wmesh_interface_s *info = NULL;
454
455         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
456         wmeshd_check_null_ret_error("connection", service->connection,
457                         WMESHD_ERROR_INVALID_PARAMETER);
458         wmeshd_check_null_ret_error("_gproxy_connman_technology",
459                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
460
461         info = service->interface_info;
462
463         g_variant_dict_init(&dict, NULL);
464         g_variant_dict_insert(&dict, "Ifname", "s", info->mesh_interface);
465         var_dict = g_variant_dict_end(&dict);
466
467         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
468                                 g_variant_new("(sv)", "MeshInterfaceRemove", var_dict),
469                                 G_DBUS_CALL_FLAGS_NONE,
470                                 -1, NULL, &error);
471         if (variant) {
472                 WMESH_LOGD("Successfully requested. [MeshInterfaceRemove]");
473         } else if (error) {
474                 ret = WMESHD_ERROR_IO_ERROR;
475                 WMESH_LOGE("Failed DBus call [%s]", error->message);
476
477                 /* Interface not exists (Not created yet) */
478                 if (g_strrstr(error->message, "No such device"))
479                         ret = WMESHD_ERROR_NONE;
480                 g_error_free(error);
481         }
482
483         return ret;
484 }
485
486 int wmesh_gdbus_mesh_scan(wmesh_service *service)
487 {
488         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
489         wmeshd_check_null_ret_error("connection", service->connection,
490                         WMESHD_ERROR_INVALID_PARAMETER);
491         wmeshd_check_null_ret_error("_gproxy_connman_technology",
492                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
493
494         g_dbus_proxy_call(_gproxy_connman_technology, "Scan",
495                                 NULL,
496                                 G_DBUS_CALL_FLAGS_NONE,
497                                 -1, NULL, NULL, NULL);
498
499         WMESH_LOGD("Successfully requested. [Scan]");
500
501         return WMESHD_ERROR_NONE;
502 }
503
504 int wmesh_gdbus_mesh_specific_scan(wmesh_service *service, gchar *mesh_id, gint channel)
505 {
506         GVariant *variant = NULL;
507         GError *error = NULL;
508         GVariant *var_dict = NULL;
509         GVariantDict dict;
510
511         enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
512         gushort freq = __channel_to_frequency(channel, band);
513
514         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
515         wmeshd_check_null_ret_error("connection", service->connection,
516                         WMESHD_ERROR_INVALID_PARAMETER);
517         wmeshd_check_null_ret_error("_gproxy_connman_technology",
518                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
519
520         g_variant_dict_init(&dict, NULL);
521         g_variant_dict_insert(&dict, "Name", "s", mesh_id);
522         g_variant_dict_insert(&dict, "Frequency", "q", freq);
523         var_dict = g_variant_dict_end(&dict);
524
525         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
526                                 g_variant_new("(sv)", "MeshSpecificScan", var_dict),
527                                 G_DBUS_CALL_FLAGS_NONE,
528                                 -1, NULL, &error);
529         if (variant) {
530                 WMESH_LOGD("Successfully requested. [MeshSpecificScan]");
531         } else if (error) {
532                 WMESH_LOGE("Failed DBus call [%s]", error->message);
533                 g_error_free(error);
534                 return WMESHD_ERROR_IO_ERROR;
535         }
536
537         return WMESHD_ERROR_NONE;
538 }
539
540 int wmesh_gdbus_mesh_cancel_scan(wmesh_service *service)
541 {
542         int ret = WMESHD_ERROR_NONE;
543         GVariant *variant = NULL;
544         GError *error = NULL;
545         GVariant *var_dict = NULL;
546         GVariantDict dict;
547
548         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
549         wmeshd_check_null_ret_error("connection", service->connection,
550                         WMESHD_ERROR_INVALID_PARAMETER);
551         wmeshd_check_null_ret_error("_gproxy_connman_technology",
552                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
553
554         g_variant_dict_init(&dict, NULL);
555         var_dict = g_variant_dict_end(&dict);
556
557         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
558                                 g_variant_new("(sv)", "AbortScan", var_dict),
559                                 G_DBUS_CALL_FLAGS_NONE,
560                                 -1, NULL, &error);
561         if (variant) {
562                 WMESH_LOGD("Successfully requested. [AbortScan]");
563         } else if (error) {
564                 ret = WMESHD_ERROR_IO_ERROR;
565                 WMESH_LOGE("Failed DBus call [%s]", error->message);
566
567                 /* Scan is not in progress */
568                 if (g_strrstr(error->message, "Already exists"))
569                         ret = WMESHD_ERROR_NONE;
570
571                 g_error_free(error);
572         }
573
574         return ret;
575 }
576
577 static void _on_scan_result_destroy(gpointer data)
578 {
579         wmesh_scan_result_s *scan_item = (wmesh_scan_result_s *)data;
580
581         if (scan_item) {
582                 g_free(scan_item->mesh_id);
583                 g_free(scan_item->bssid);
584                 g_free(scan_item->object_path);
585         }
586         g_free(scan_item);
587 }
588
589 static void _on_peer_info_destroy(gpointer data)
590 {
591         wmesh_peer_info_s *peer = (wmesh_peer_info_s *)data;
592
593         if (peer)
594                 g_free(peer->address);
595         g_free(peer);
596 }
597
598 static void _get_joined_network(wmesh_service *service, GVariant *variant)
599 {
600         GVariantIter *peer = NULL;
601         GVariantIter *property = NULL;
602         GVariantIter  *iter = NULL;
603         gchar *key = NULL;
604         gchar *sub_key = NULL;
605         GVariant *val = NULL;
606         GVariant *sub_val = NULL;
607         gsize len = 0;
608         GVariant *child;
609         const gchar* obj_path = NULL;
610         const gchar* buf = NULL;
611
612         g_variant_get(variant, "(a(oa{sv}))", &peer);
613         while ((child = g_variant_iter_next_value(peer))) {
614                 wmesh_network_info_s *joined_info = NULL;
615                 gboolean valid_state = TRUE;
616
617                 g_variant_get(child, "(oa{sv})", &obj_path, &property);
618                 WMESH_LOGD("  Object: [%s]", obj_path);
619                 if (NULL == obj_path) {
620                         WMESH_LOGE("Null object");
621                         continue;
622                 }
623
624                 /* Create an information structure for joined network */
625                 joined_info = g_try_new0(wmesh_network_info_s, 1);
626                 if (NULL == joined_info) {
627                         WMESH_LOGE("Failed to allocate !");
628                         return;
629                 }
630
631                 while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
632                         if (strcasecmp(key, "Name") == 0) {
633                                 buf = g_variant_get_string(val, &len);
634                                 joined_info->mesh_id = g_strdup(buf);
635                         } else if (strcasecmp(key, "BSSID") == 0) {
636                                 buf = g_variant_get_string(val, &len);
637                                 joined_info->bssid = g_strdup(buf);
638                         } else if (strcasecmp(key, "State") == 0) {
639                                 buf = g_variant_get_string(val, &len);
640                                 WMESH_LOGD("    State : %s", buf);
641
642                                 /* Skip ignorable state */
643                                 if (g_strcmp0(buf, "idle") == 0
644                                         || g_strcmp0(buf, "disconnect") == 0
645                                         || g_strcmp0(buf, "failure") == 0) {
646                                         valid_state = FALSE;
647                                         break;
648                                 } else if (g_strcmp0(buf, "association") == 0) {
649                                         joined_info->state = WMESHD_CONNECTION_STATE_ASSOCIATION;
650                                 } else if (g_strcmp0(buf, "configuration") == 0) {
651                                         joined_info->state = WMESHD_CONNECTION_STATE_CONFIGURATION;
652                                 } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
653                                         joined_info->state = WMESHD_CONNECTION_STATE_CONNECTED;
654                                 }
655                         } else if (strcasecmp(key, "Security") == 0) {
656                                 buf = g_variant_get_string(val, &len);
657                                 if (g_strcmp0("sae", buf) == 0)
658                                         joined_info->security = WMESHD_SECURITY_SAE;
659                                 else
660                                         joined_info->security = WMESHD_SECURITY_NONE;
661                         } else if (strcasecmp(key, "Frequency") == 0) {
662                                 joined_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
663                         } else if (strcasecmp(key, "IPv4") == 0) {
664                                 g_variant_get(val, "a{sv}", &iter);
665                                 while (g_variant_iter_loop(iter, "{sv}", &sub_key, &sub_val)) {
666
667                                         if (strcasecmp(sub_key, "Method") == 0) {
668                                                 buf = g_variant_get_string(sub_val, &len);
669                                                 WMESH_LOGD("Method %s", buf);
670
671                                                 if (strcasecmp(buf, "dhcp") == 0)
672                                                         joined_info->ipv4_type =
673                                                                 WMESHD_IP_CONFIG_TYPE_DYNAMIC;
674                                                 else if (strcasecmp(buf, "manual") == 0)
675                                                         joined_info->ipv4_type =
676                                                                 WMESHD_IP_CONFIG_TYPE_STATIC;
677                                                 else
678                                                         joined_info->ipv4_type =
679                                                                 WMESHD_IP_CONFIG_TYPE_UNKNOWN;
680                                         } else if (strcasecmp(sub_key, "Address") == 0) {
681                                                 buf = g_variant_get_string(sub_val, &len);
682                                                 WMESH_LOGD("Address %s", buf);
683                                                 joined_info->ipv4_address = g_strdup(buf);
684                                         } else if (strcasecmp(sub_key, "Netmask") == 0) {
685                                                 buf = g_variant_get_string(sub_val, &len);
686                                                 WMESH_LOGD("Netmask %s", buf);
687                                                 joined_info->ipv4_netmask = g_strdup(buf);
688                                         }
689                                 }
690                                 g_variant_iter_free(iter);
691                         }
692                 }
693
694                 /* Skip ignorable state */
695                 if (FALSE == valid_state) {
696                         g_free(joined_info->mesh_id);
697                         g_free(joined_info->bssid);
698                         g_free(joined_info->ipv4_address);
699                         g_free(joined_info->ipv4_netmask);
700                         continue;
701                 }
702
703                 WMESH_LOGD("    Mesh ID  : %s", joined_info->mesh_id);
704                 WMESH_LOGD("    BSSID    : %s", joined_info->bssid);
705                 WMESH_LOGD("    Channel  : %d", joined_info->channel);
706                 WMESH_LOGD("    Security : %s",
707                         (WMESHD_SECURITY_SAE == joined_info->security) ? "SAE" : "NONE");
708                 service->joined_network = joined_info;
709
710                 g_variant_iter_free(property);
711
712                 /* If found, stop loop iteration */
713                 break;
714         }
715         g_variant_iter_free(peer);
716 }
717
718 static void _get_mesh_peers(wmesh_service *service, GVariant *variant)
719 {
720         GVariantIter *peer = NULL;
721         GVariantIter *property = NULL;
722         gchar *key = NULL;
723         GVariant *val = NULL;
724         gsize len = 0;
725         GVariant *child;
726         const gchar* obj_path = NULL;
727
728         g_variant_get(variant, "(a(oa{sv}))", &peer);
729         while ((child = g_variant_iter_next_value(peer))) {
730                 wmesh_scan_result_s *scan_info = NULL;
731
732                 scan_info = g_try_new0(wmesh_scan_result_s, 1);
733                 if (NULL == scan_info) {
734                         WMESH_LOGE("Failed to allocate !");
735                         return;
736                 }
737
738                 g_variant_get(child, "(oa{sv})", &obj_path, &property);
739                 if (NULL == obj_path) {
740                         WMESH_LOGE("Null object");
741                         g_free(scan_info);
742                         continue;
743                 }
744                 WMESH_LOGD("    Obj path : [%s]", obj_path);
745                 scan_info->object_path = g_strdup(obj_path);
746
747                 while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
748                         if (strcasecmp(key, "Name") == 0) {
749                                 const char *buf = g_variant_get_string(val, &len);
750                                 scan_info->mesh_id = g_strdup(buf);
751                                 WMESH_LOGD("    Mesh ID : %s", scan_info->mesh_id);
752                         } else if (strcasecmp(key, "BSSID") == 0) {
753                                 const char *buf = g_variant_get_string(val, &len);
754                                 scan_info->bssid = g_strdup(buf);
755                                 WMESH_LOGD("    BSSID : %s", scan_info->bssid);
756                         } else if (strcasecmp(key, "State") == 0) {
757                                 const char *buf = g_variant_get_string(val, &len);
758                                 WMESH_LOGD("    State : %s", buf);
759
760                                 if (g_strcmp0(buf, "idle") == 0
761                                         || g_strcmp0(buf, "disconnect") == 0
762                                         || g_strcmp0(buf, "failure") == 0) {
763                                         scan_info->state = WMESHD_CONNECTION_STATE_DISCONNECTED;
764                                 } else if (g_strcmp0(buf, "association") == 0) {
765                                         scan_info->state = WMESHD_CONNECTION_STATE_ASSOCIATION;
766                                 } else if (g_strcmp0(buf, "configuration") == 0) {
767                                         scan_info->state = WMESHD_CONNECTION_STATE_CONFIGURATION;
768                                 } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
769                                         scan_info->state = WMESHD_CONNECTION_STATE_CONNECTED;
770                                 }
771                         } else if (strcasecmp(key, "Security") == 0) {
772                                 const char *buf = g_variant_get_string(val, &len);
773                                 WMESH_LOGD("    Security : %s", buf);
774                                 if (g_strcmp0("sae", buf) == 0)
775                                         scan_info->security = WMESHD_SECURITY_SAE;
776                                 else
777                                         scan_info->security = WMESHD_SECURITY_NONE;
778                         } else if (strcasecmp(key, "Frequency") == 0) {
779                                 scan_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
780                                 WMESH_LOGD("    Channel : %d", scan_info->channel);
781                         } else if (strcasecmp(key, "Favorite") == 0) {
782                                 const char *buf = g_variant_get_string(val, &len);
783                                 WMESH_LOGD("    Favorite : %s", buf);
784                         } else if (strcasecmp(key, "Strength") == 0) {
785                                 scan_info->rssi = (gint)g_variant_get_byte(val);
786                                 WMESH_LOGD("    RSSI : %d", scan_info->rssi);
787                         }
788                 }
789                 /* Last element */
790                 service->scanned_mesh_network =
791                         g_list_prepend(service->scanned_mesh_network, scan_info);
792
793                 g_variant_iter_free(property);
794         }
795         g_variant_iter_free(peer);
796 }
797
798 static void _get_connected_mesh_peers(wmesh_service *service, GVariant *variant)
799 {
800         GVariantIter *peer = NULL;
801         GVariant *val = NULL;
802         gsize len = 0;
803         GVariant *child;
804         GVariant *dict = NULL;
805
806         g_variant_get(variant, "(a(a{sv}))", &peer);
807         while ((child = g_variant_iter_next_value(peer))) {
808                 wmesh_peer_info_s *peer_info = NULL;
809
810                 peer_info = g_try_new0(wmesh_peer_info_s, 1);
811                 if (NULL == peer_info) {
812                         WMESH_LOGE("Failed to allocate !");
813                         return;
814                 }
815
816                 /* a{sv} <- (a{sv}) */
817                 dict = g_variant_get_child_value(child, 0);
818                 val = g_variant_lookup_value(dict, "PeerAddress", NULL);
819                 if (NULL != val) {
820                         const char *buf = g_variant_get_string(val, &len);
821                         peer_info->address = g_strdup(buf);
822                         WMESH_LOGD("    Address : %s", peer_info->address);
823                         g_variant_unref(val);
824                 } else {
825                         WMESH_LOGE("Unable to get address !");
826                         g_free(peer_info);
827                         continue;
828                 }
829
830                 service->connected_mesh_peers =
831                         g_list_prepend(service->connected_mesh_peers, peer_info);
832         }
833         g_variant_iter_free(peer);
834 }
835
836 int wmesh_gdbus_get_mesh_networks(wmesh_service *service)
837 {
838         GVariant *variant = NULL;
839         GError *error = NULL;
840
841         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
842         wmeshd_check_null_ret_error("connection", service->connection,
843                         WMESHD_ERROR_INVALID_PARAMETER);
844         wmeshd_check_null_ret_error("_gproxy_connman",
845                         _gproxy_connman, WMESHD_ERROR_IO_ERROR);
846
847         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
848                                 NULL,
849                                 G_DBUS_CALL_FLAGS_NONE,
850                                 -1, NULL, &error);
851         if (variant) {
852                 WMESH_LOGD("Successfully requested. [GetMeshPeers]");
853
854                 if (service->scanned_mesh_network) {
855                         g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
856                         service->scanned_mesh_network = NULL;
857                 }
858
859                 _get_mesh_peers(service, variant);
860
861                 /* List item is saved with reversed order for efficiency. */
862                 service->scanned_mesh_network =
863                                 g_list_reverse(service->scanned_mesh_network);
864         } else if (error) {
865                 WMESH_LOGE("Failed DBus call [%s]", error->message);
866                 g_error_free(error);
867                 return WMESHD_ERROR_IO_ERROR;
868         }
869
870         return WMESHD_ERROR_NONE;
871 }
872
873 int wmesh_gdbus_get_joined_mesh_network(wmesh_service *service)
874 {
875         GVariant *variant = NULL;
876         GError *error = NULL;
877
878         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
879         wmeshd_check_null_ret_error("connection", service->connection,
880                         WMESHD_ERROR_INVALID_PARAMETER);
881         wmeshd_check_null_ret_error("_gproxy_connman",
882                         _gproxy_connman, WMESHD_ERROR_IO_ERROR);
883
884         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
885                                 NULL,
886                                 G_DBUS_CALL_FLAGS_NONE,
887                                 -1, NULL, &error);
888         if (variant) {
889                 WMESH_LOGD("Successfully requested. [GetMeshPeers]");
890
891                 if (service->joined_network) {
892                         g_free(service->joined_network->mesh_id);
893                         g_free(service->joined_network->bssid);
894                         g_free(service->joined_network->ipv4_address);
895                         g_free(service->joined_network->ipv4_netmask);
896                         g_free(service->joined_network);
897                         service->joined_network = NULL;
898                 }
899
900                 _get_joined_network(service, variant);
901         } else if (error) {
902                 WMESH_LOGE("Failed DBus call [%s]", error->message);
903                 g_error_free(error);
904                 return WMESHD_ERROR_IO_ERROR;
905         }
906
907         return WMESHD_ERROR_NONE;
908 }
909
910 int wmesh_gdbus_get_connected_peers(wmesh_service *service)
911 {
912         GVariant *variant = NULL;
913         GError *error = NULL;
914
915         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
916         wmeshd_check_null_ret_error("connection", service->connection,
917                         WMESHD_ERROR_INVALID_PARAMETER);
918         wmeshd_check_null_ret_error("_gproxy_connman",
919                         _gproxy_connman, WMESHD_ERROR_IO_ERROR);
920
921         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetConnectedMeshPeers",
922                                 NULL,
923                                 G_DBUS_CALL_FLAGS_NONE,
924                                 -1, NULL, &error);
925         if (variant) {
926                 WMESH_LOGD("Successfully requested. [GetConnectedMeshPeers]");
927
928                 if (service->connected_mesh_peers) {
929                         g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
930                         service->connected_mesh_peers = NULL;
931                 }
932
933                 _get_connected_mesh_peers(service, variant);
934
935                 /* List item is saved with reversed order for efficiency. */
936                 service->connected_mesh_peers =
937                                 g_list_reverse(service->connected_mesh_peers);
938         } else if (error) {
939                 WMESH_LOGE("Failed DBus call [%s]", error->message);
940                 g_error_free(error);
941                 return WMESHD_ERROR_IO_ERROR;
942         }
943
944         return WMESHD_ERROR_NONE;
945 }
946
947 static void _get_mesh_property(GVariant *variant, wmesh_network_info_s *result)
948 {
949         GVariantIter *property = NULL;
950         gchar *key = NULL;
951         GVariant *val = NULL;
952         gsize len = 0;
953
954         WMESH_LOGD("Type [%s]", g_variant_get_type_string(variant));
955
956         g_variant_get(variant, "(a{sv})", &property);
957
958         while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
959                 if (strcasecmp(key, "Name") == 0) {
960                         const char *buf = g_variant_get_string(val, &len);
961                         result->mesh_id = g_strdup(buf);
962                         WMESH_LOGD("    Mesh ID : %s", result->mesh_id);
963                 } else if (strcasecmp(key, "BSSID") == 0) {
964                         const char *buf = g_variant_get_string(val, &len);
965                         result->bssid = g_strdup(buf);
966                         WMESH_LOGD("    BSSID : %s", result->bssid);
967                 } else if (strcasecmp(key, "State") == 0) {
968                         const char *buf = g_variant_get_string(val, &len);
969                         WMESH_LOGD("    State : %s", buf);
970
971                         if (g_strcmp0(buf, "idle") == 0
972                                 || g_strcmp0(buf, "disconnect") == 0
973                                 || g_strcmp0(buf, "failure") == 0) {
974                                 result->state = WMESHD_CONNECTION_STATE_DISCONNECTED;
975                         } else if (g_strcmp0(buf, "association") == 0) {
976                                 result->state = WMESHD_CONNECTION_STATE_ASSOCIATION;
977                         } else if (g_strcmp0(buf, "configuration") == 0) {
978                                 result->state = WMESHD_CONNECTION_STATE_CONFIGURATION;
979                         } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
980                                 result->state = WMESHD_CONNECTION_STATE_CONNECTED;
981                         }
982                 } else if (strcasecmp(key, "Security") == 0) {
983                         const char *buf = g_variant_get_string(val, &len);
984                         WMESH_LOGD("    Security : %s", buf);
985                         if (g_strcmp0("sae", buf) == 0)
986                                 result->security = WMESHD_SECURITY_SAE;
987                         else
988                                 result->security = WMESHD_SECURITY_NONE;
989                 } else if (strcasecmp(key, "Frequency") == 0) {
990                         result->channel = __frequency_to_channel(g_variant_get_uint16(val));
991                         WMESH_LOGD("    Channel : %d", result->channel);
992                 } else if (strcasecmp(key, "Favorite") == 0) {
993                         const char *buf = g_variant_get_string(val, &len);
994                         WMESH_LOGD("    Favorite : %s", buf);
995                 } else if (strcasecmp(key, "Strength") == 0) {
996                         gint rssi = (gint)g_variant_get_byte(val);
997                         WMESH_LOGD("    RSSI : %d", rssi);
998                 }
999         }
1000         g_variant_iter_free(property);
1001 }
1002
1003 static int _wmesh_gdbus_get_mesh_network_property(wmesh_service *service,
1004         const gchar* object_path, wmesh_network_info_s *result)
1005 {
1006         GVariant *variant = NULL;
1007         GError *error = NULL;
1008
1009         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1010         wmeshd_check_null_ret_error("connection", service->connection,
1011                         WMESHD_ERROR_INVALID_PARAMETER);
1012         wmeshd_check_null_ret_error("result", result, WMESHD_ERROR_INVALID_PARAMETER);
1013
1014         variant = g_dbus_connection_call_sync(service->connection,
1015                         CONNMAN_SERVER_NAME,
1016                         object_path,
1017                         CONNMAN_INTERFACE_MESH,
1018                         "GetProperties",
1019                         NULL, NULL,
1020                         G_DBUS_CALL_FLAGS_NONE,
1021                         -1, NULL, &error);
1022         if (variant) {
1023                 WMESH_LOGD("Successfully requested. [GetProperties]");
1024
1025                 /* Get properties */
1026                 _get_mesh_property(variant, result);
1027         } else if (error) {
1028                 LOGE("Failed DBus call [%s]", error->message);
1029                 g_error_free(error);
1030                 return WMESHD_ERROR_IO_ERROR;
1031         }
1032
1033         return WMESHD_ERROR_NONE;
1034 }
1035
1036 int wmesh_gdbus_create_network(wmesh_service *service, gchar *mesh_id,
1037                 gint channel, wmeshd_security_type_e sec)
1038 {
1039         GVariant *variant = NULL;
1040         GError *error = NULL;
1041         GVariant *var_dict = NULL;
1042         GVariantBuilder builder;
1043         const gchar* security = (WMESHD_SECURITY_SAE == sec) ? "sae" : "none";
1044
1045         enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
1046         gushort freq = __channel_to_frequency(channel, band);
1047
1048         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1049         wmeshd_check_null_ret_error("connection", service->connection,
1050                         WMESHD_ERROR_INVALID_PARAMETER);
1051         wmeshd_check_null_ret_error("_gproxy_connman_technology",
1052                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
1053
1054         g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
1055         g_variant_builder_open(&builder, G_VARIANT_TYPE("a{sv}"));
1056
1057         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1058         g_variant_builder_add(&builder, "s", "Name");
1059         g_variant_builder_add(&builder, "v", g_variant_new_string(mesh_id));
1060         g_variant_builder_close(&builder); /* {sv} */
1061
1062         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1063         g_variant_builder_add(&builder, "s", "Frequency");
1064         g_variant_builder_add(&builder, "v", g_variant_new_uint16(freq));
1065         g_variant_builder_close(&builder); /* {sv} */
1066
1067         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1068         g_variant_builder_add(&builder, "s", "Security");
1069         g_variant_builder_add(&builder, "v", g_variant_new_string(security));
1070         g_variant_builder_close(&builder); /* {sv} */
1071
1072         g_variant_builder_close(&builder); /* a{sv} */
1073
1074         var_dict = g_variant_builder_end(&builder);
1075
1076         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
1077                                 g_variant_new("(sv)", "MeshCreateNetwork", var_dict),
1078                                 G_DBUS_CALL_FLAGS_NONE,
1079                                 -1, NULL, &error);
1080         if (variant) {
1081                 WMESH_LOGD("Successfully requested. [MeshCreateNetwork]");
1082         } else if (error) {
1083                 WMESH_LOGE("Failed DBus call [%s]", error->message);
1084                 g_error_free(error);
1085                 return WMESHD_ERROR_IO_ERROR;
1086         }
1087
1088         return WMESHD_ERROR_NONE;
1089 }
1090
1091 int wmesh_gdbus_set_passphrase(wmesh_service *service, wmesh_scan_result_s *info, gchar *passphrase)
1092 {
1093         GVariant *variant = NULL;
1094         GError *error = NULL;
1095
1096         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1097         wmeshd_check_null_ret_error("passphrase", passphrase, WMESHD_ERROR_INVALID_PARAMETER);
1098
1099         variant = g_dbus_connection_call_sync(service->connection,
1100                         CONNMAN_SERVER_NAME,
1101                         info->object_path,
1102                         CONNMAN_INTERFACE_MESH,
1103                         "SetProperty",
1104                         g_variant_new("(sv)", "Passphrase", g_variant_new_string(passphrase)),
1105                         NULL,
1106                         G_DBUS_CALL_FLAGS_NONE,
1107                         -1, NULL, &error);
1108         if (variant) {
1109                 WMESH_LOGD("Successfully requested. [SetProperty]");
1110         } else if (error) {
1111                 LOGE("Failed DBus call [%s]", error->message);
1112                 g_error_free(error);
1113                 return WMESHD_ERROR_IO_ERROR;
1114         }
1115
1116         return WMESHD_ERROR_NONE;
1117 }
1118
1119 #if 0
1120 static void on_response_connect_network(GObject *source_object,
1121         GAsyncResult *res, gpointer user_data)
1122 {
1123         int ret = WMESHD_ERROR_NONE;
1124         GError *error = NULL;
1125         GVariant *variant = NULL;
1126
1127         NOTUSED(user_data);
1128
1129         variant = g_dbus_connection_call_finish(
1130                         G_DBUS_CONNECTION(source_object), res, &error);
1131         if (variant) {
1132                 WMESH_LOGD("Successfully requested. [Connect]");
1133
1134                 /* TODO: Unregister property change event */
1135         } else if (error) {
1136                 ret = WMESHD_ERROR_IO_ERROR;
1137                 LOGE("Failed DBus call [%s]", error->message);
1138
1139                 if (g_strrstr(error->message, "Already exists"))
1140                         ret = WMESHD_ERROR_ALREADY_REGISTERED;
1141                 else if (g_strrstr(error->message, "In progress"))
1142                         ret = WMESHD_ERROR_IN_PROGRESS;
1143                 else
1144                         ret = WMESHD_ERROR_IO_ERROR;
1145
1146                 g_error_free(error);
1147         }
1148 }
1149 #endif
1150
1151 int wmesh_gdbus_connect_network(wmesh_service *service, wmesh_scan_result_s *info)
1152 {
1153         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1154         wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
1155
1156         g_dbus_connection_call(service->connection,
1157                         CONNMAN_SERVER_NAME,
1158                         info->object_path,
1159                         CONNMAN_INTERFACE_MESH,
1160                         "Connect",
1161                         NULL, NULL,
1162                         G_DBUS_CALL_FLAGS_NONE,
1163                         -1,
1164                         NULL, /* G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED */
1165                         NULL, NULL);
1166         WMESH_LOGD("Successfully requested. [Connect]");
1167
1168         return WMESHD_ERROR_NONE;
1169 }
1170
1171 int wmesh_gdbus_disconnect_network(wmesh_service *service, wmesh_scan_result_s *info)
1172 {
1173         GVariant *variant = NULL;
1174         GError *error = NULL;
1175
1176         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1177         wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
1178
1179         variant = g_dbus_connection_call_sync(service->connection,
1180                         CONNMAN_SERVER_NAME,
1181                         info->object_path,
1182                         CONNMAN_INTERFACE_MESH,
1183                         "Disconnect",
1184                         NULL, NULL,
1185                         G_DBUS_CALL_FLAGS_NONE,
1186                         -1, NULL, &error);
1187         if (variant) {
1188                 WMESH_LOGD("Successfully requested. [Disconnect]");
1189         } else if (error) {
1190                 LOGE("Failed DBus call [%s]", error->message);
1191                 g_error_free(error);
1192                 return WMESHD_ERROR_IO_ERROR;
1193         }
1194
1195         return WMESHD_ERROR_NONE;
1196 }
1197
1198 int wmesh_gdbus_remove_network(wmesh_service *service, wmesh_scan_result_s *info)
1199 {
1200         GVariant *variant = NULL;
1201         GError *error = NULL;
1202
1203         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1204         wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
1205
1206         variant = g_dbus_connection_call_sync(service->connection,
1207                         CONNMAN_SERVER_NAME,
1208                         info->object_path,
1209                         CONNMAN_INTERFACE_MESH,
1210                         "Remove",
1211                         NULL, NULL,
1212                         G_DBUS_CALL_FLAGS_NONE,
1213                         -1, NULL, &error);
1214         if (variant) {
1215                 WMESH_LOGD("Successfully requested. [Remove]");
1216         } else if (error) {
1217                 LOGE("Failed DBus call [%s]", error->message);
1218                 g_error_free(error);
1219                 return WMESHD_ERROR_IO_ERROR;
1220         }
1221
1222         return WMESHD_ERROR_NONE;
1223 }
1224
1225
1226 int wmesh_gdbus_enable_ethernet_interface(wmesh_service *service, bool state)
1227 {
1228         int ret = WMESHD_ERROR_NONE;
1229         GVariant *variant = NULL;
1230         GError *error = NULL;
1231         wmesh_interface_s *info = NULL;
1232
1233         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1234         wmeshd_check_null_ret_error("connection", service->connection,
1235                         WMESHD_ERROR_INVALID_PARAMETER);
1236         wmeshd_check_null_ret_error("_gproxy_connman_technology",
1237                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
1238
1239         info = service->interface_info;
1240         wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
1241
1242         variant = g_dbus_proxy_call_sync(_gproxy_connman_ethernet, "SetProperty",
1243                                 g_variant_new("(sv)", "Powered", g_variant_new_boolean(state)),
1244                                 G_DBUS_CALL_FLAGS_NONE,
1245                                 -1, NULL, &error);
1246         if (variant) {
1247                 WMESH_LOGD("Successfully requested. [Powered]");
1248         } else if (error) {
1249                 ret = WMESHD_ERROR_IO_ERROR;
1250                 WMESH_LOGE("Failed DBus call [%s]", error->message);
1251
1252                 /* Interface not exists (Not created yet) */
1253                 if (g_strrstr(error->message, "No such device"))
1254                         ret = WMESHD_ERROR_NONE;
1255                 g_error_free(error);
1256         }
1257
1258         return ret;
1259 }
1260
1261 int wmesh_gdbus_set_mesh_gate(wmesh_service *service)
1262 {
1263         int ret = WMESHD_ERROR_NONE;
1264         GVariant *variant = NULL;
1265         GError *error = NULL;
1266         GVariant *var_dict = NULL;
1267         GVariantDict dict;
1268         wmesh_interface_s *info = NULL;
1269
1270         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1271         wmeshd_check_null_ret_error("connection", service->connection,
1272                         WMESHD_ERROR_INVALID_PARAMETER);
1273         wmeshd_check_null_ret_error("_gproxy_connman_technology",
1274                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
1275
1276         info = service->interface_info;
1277
1278         g_variant_dict_init(&dict, NULL);
1279         g_variant_dict_insert(&dict, "GateAnnounce", "b", info->gate_announce);
1280         g_variant_dict_insert(&dict, "HWMPRootMode", "q", info->hwmp_root_mode);
1281         g_variant_dict_insert(&dict, "STP", "q", info->stp);
1282         var_dict = g_variant_dict_end(&dict);
1283
1284         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
1285                                 g_variant_new("(sv)", "SetMeshGate", var_dict),
1286                                 G_DBUS_CALL_FLAGS_NONE,
1287                                 -1, NULL, &error);
1288         if (variant) {
1289                 WMESH_LOGD("Successfully requested. [SetMeshGate]");
1290         } else if (error) {
1291                 ret = WMESHD_ERROR_IO_ERROR;
1292                 WMESH_LOGE("Failed DBus call [%s]", error->message);
1293
1294                 /* Interface not exists */
1295                 if (g_strrstr(error->message, "No such device"))
1296                         ret = WMESHD_ERROR_INVALID_PARAMETER;
1297                 g_error_free(error);
1298         }
1299
1300         return ret;
1301 }
1302
1303 int wmesh_gdbus_mesh_remove_peer(wmesh_service *service, char *peer)
1304 {
1305         GVariant *variant = NULL;
1306         GError *error = NULL;
1307         int ret = WMESHD_ERROR_NONE;
1308
1309         wmeshd_check_null_ret_error("service", service,
1310                                                                 WMESHD_ERROR_INVALID_PARAMETER);
1311         wmeshd_check_null_ret_error("connection", service->connection,
1312                         WMESHD_ERROR_INVALID_PARAMETER);
1313         wmeshd_check_null_ret_error("_gproxy_connman",
1314                         _gproxy_connman, WMESHD_ERROR_IO_ERROR);
1315
1316         variant = g_dbus_proxy_call_sync(_gproxy_connman, "MeshRemovePeer",
1317                                 g_variant_new("(s)", peer), G_DBUS_CALL_FLAGS_NONE, 1, NULL,
1318                                 &error);
1319         if (variant) {
1320                 WMESH_LOGD("Successfully requested. [MeshRemovePeer]");
1321         } else if (error) {
1322                 ret = WMESHD_ERROR_IO_ERROR;
1323                 WMESH_LOGE("Failed DBus call [%s]", error->message);
1324
1325                 /* Interface not exists */
1326                 if (g_strrstr(error->message, "No such device"))
1327                         ret = WMESHD_ERROR_INVALID_PARAMETER;
1328                 g_error_free(error);
1329         }
1330
1331         return ret;
1332 }
1333