Modified sometings related to 'mesh_set_gate'
[platform/core/connectivity/wifi-mesh-manager.git] / src / mesh-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 "mesh-log.h"
18 #include "mesh-util.h"
19 #include "mesh-gdbus.h"
20 #include "mesh-request.h"
21
22 #include "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 _meshd_close_gdbus_call(mesh_service *service);
30 static int _mesh_gdbus_get_mesh_network_property(mesh_service *service,
31         const gchar* object_path, mesh_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(mesh_service *service)
76 {
77         GDBusProxy *proxy = NULL;
78         meshd_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(mesh_service *service)
94 {
95         GDBusProxy *proxy = NULL;
96         meshd_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(mesh_service *service)
112 {
113         GDBusProxy *proxy = NULL;
114         meshd_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(mesh_service *service)
130 {
131         GDBusProxy *proxy = NULL;
132         meshd_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         mesh_service *service = (mesh_service*)user_data;
153
154         NOTUSED(pspec);
155
156         if (NULL == name_owner) {
157                 MESH_LOGE("name_owner is not exists !");
158                 _meshd_close_gdbus_call(service);
159         }
160
161         g_free(name_owner);
162 }
163
164 static int _meshd_create_gdbus_call(mesh_service *service)
165 {
166         int id;
167         GError *error = NULL;
168
169         if (NULL == service)
170                 return MESHD_ERROR_INVALID_PARAMETER;
171
172         if (NULL != service->connection)
173                 return MESHD_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                         MESH_LOGE("Failed to connect to the D-BUS daemon [%s]", error->message);
179                         g_error_free(error);
180                 }
181                 return MESHD_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                 MESH_LOGE("g_signal_connect() Fail");
188                 g_object_unref(service->connection);
189                 service->connection = NULL;
190                 return MESHD_ERROR_IO_ERROR;
191         }
192
193         return MESHD_ERROR_NONE;
194 }
195
196 static int _meshd_close_gdbus_call(mesh_service *service)
197 {
198         /* CHECK: is connection ref count required? */
199         g_object_unref(service->connection);
200         service->connection = NULL;
201
202         return MESHD_ERROR_NONE;
203 }
204
205 static void _meshd_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         mesh_service *service = (mesh_service*)user_data;
210         mesh_network_info_s network_info = { 0, 0, 0, 0, 0 };
211         int ret = MESHD_ERROR_NONE;
212
213         meshd_check_null_ret("user_data", user_data);
214         NOTUSED(connection);
215         NOTUSED(sender_name);
216         NOTUSED(interface_name);
217
218         MESH_LOGD("signal received = %s", signal_name);
219         if (0 == g_strcmp0(signal_name, "ScanDone")) {
220                 /* TODO: Handle event */
221                 mesh_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                 meshd_connection_state_e state = MESHD_CONNECTION_STATE_DISCONNECTED;
227
228                 if (NULL == parameters) {
229                         MESH_LOGE("Unexpected parameter");
230                         return;
231                 }
232
233                 g_variant_get(parameters, "(sv)", &key, &variant);
234                 if (NULL == variant) {
235                         MESH_LOGE("Invalid variant");
236                         return;
237                 }
238
239                 /* State [???] */
240                 var = g_variant_get_string(variant, NULL);
241                 MESH_LOGD("  %s [%s]", key, var);
242                 MESH_LOGD("    %s", object_path);
243
244                 ret = _mesh_gdbus_get_mesh_network_property(service, object_path, &network_info);
245                 if (MESHD_ERROR_NONE != ret)
246                         MESH_LOGE("Cannot get valid network property !");
247
248                 if (g_strcmp0("association", var) == 0) {
249                         /* Joined mesh network */
250                         state = MESHD_CONNECTION_STATE_ASSOCIATION;
251                 } else if (g_strcmp0("configuration", var) == 0) {
252                         /* Trying to get IP address */
253                         state = MESHD_CONNECTION_STATE_CONFIGURATION;
254                 } else if (g_strcmp0("ready", var) == 0 || g_strcmp0("online", var) == 0) {
255                         /* IP address is obtained */
256                         state = MESHD_CONNECTION_STATE_CONNECTED;
257                 } else if (g_strcmp0("disconnect", var) == 0 || g_strcmp0("failure", var) == 0) {
258                         state = MESHD_CONNECTION_STATE_DISCONNECTED;
259                 } else {
260                         MESH_LOGE("  Unhandled state !");
261                         g_free(network_info.mesh_id);
262                         g_free(network_info.bssid);
263                         return;
264                 }
265
266                 mesh_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 _meshd_subscribe_event(mesh_service *service)
275 {
276         unsigned int id = 0;
277
278         meshd_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, _meshd_signal_handler, service, NULL);
285         if (0 == id) {
286                 MESH_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         MESH_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, _meshd_signal_handler, service, NULL);
301         if (0 == id) {
302                 MESH_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         MESH_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         mesh_service *service = (mesh_service*)user_data;
315
316         MESH_LOGD("[Signal unsubscribe] : %d", id);
317         g_dbus_connection_signal_unsubscribe(
318                 (GDBusConnection *)service->connection, id);
319 }
320
321 static void _meshd_unsubscribe_event(mesh_service *service)
322 {
323         meshd_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 meshd_dbus_start(mesh_service *service)
332 {
333         int rv;
334
335         rv = _meshd_create_gdbus_call(service);
336         if (MESHD_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         meshd_check_null_ret_error("_gproxy_connman", _gproxy_connman,
344                                 MESHD_ERROR_IO_ERROR);
345         g_dbus_proxy_set_default_timeout(
346                         G_DBUS_PROXY(_gproxy_connman), MESH_DBUS_PROXY_TIMEOUT);
347
348         _gproxy_connman_mesh = _proxy_get_connman_mesh(service);
349         meshd_check_null_ret_error("_gproxy_connman_mesh", _gproxy_connman_mesh,
350                                 MESHD_ERROR_IO_ERROR);
351         g_dbus_proxy_set_default_timeout(
352                         G_DBUS_PROXY(_gproxy_connman_mesh), MESH_DBUS_PROXY_TIMEOUT);
353
354         _gproxy_connman_technology = _proxy_get_connman_technology(service);
355         meshd_check_null_ret_error("_gproxy_connman_technology", _gproxy_connman_technology,
356                                 MESHD_ERROR_IO_ERROR);
357         g_dbus_proxy_set_default_timeout(
358                         G_DBUS_PROXY(_gproxy_connman_technology), MESH_DBUS_PROXY_TIMEOUT);
359
360         _gproxy_connman_ethernet = _proxy_get_connman_ethernet(service);
361         meshd_check_null_ret_error("_gproxy_connman_ethernet", _gproxy_connman_ethernet,
362                                 MESHD_ERROR_IO_ERROR);
363         g_dbus_proxy_set_default_timeout(
364                         G_DBUS_PROXY(_gproxy_connman_ethernet), MESH_DBUS_PROXY_TIMEOUT);
365
366         /* Subscribe events */
367         _meshd_subscribe_event(service);
368
369         return MESHD_ERROR_NONE;
370 }
371
372 int meshd_dbus_stop(mesh_service *service)
373 {
374         int rv;
375
376         if (NULL == service)
377                 return MESHD_ERROR_INVALID_PARAMETER;
378
379         /* Unsubscribe events */
380         _meshd_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 = _meshd_close_gdbus_call(service);
401         return rv;
402 }
403
404 int mesh_gdbus_create_mesh_interface(mesh_service *service)
405 {
406         int ret = MESHD_ERROR_NONE;
407         GVariant *variant = NULL;
408         GError *error = NULL;
409         GVariant *var_dict = NULL;
410         GVariantDict dict;
411         mesh_interface_s *info = NULL;
412
413         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
414         meshd_check_null_ret_error("connection", service->connection,
415                         MESHD_ERROR_INVALID_PARAMETER);
416         meshd_check_null_ret_error("_gproxy_connman_technology",
417                         _gproxy_connman_technology, MESHD_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                 MESH_LOGD("Successfully requested. [MeshInterfaceAdd]");
433         } else if (error) {
434                 ret = MESHD_ERROR_IO_ERROR;
435                 MESH_LOGE("Failed DBus call [%s]", error->message);
436
437                 /* Interface not exists */
438                 if (g_strrstr(error->message, "No such device"))
439                         ret = MESHD_ERROR_INVALID_PARAMETER;
440                 g_error_free(error);
441         }
442
443         return ret;
444 }
445
446 int mesh_gdbus_remove_mesh_interface(mesh_service *service)
447 {
448         int ret = MESHD_ERROR_NONE;
449         GVariant *variant = NULL;
450         GError *error = NULL;
451         GVariant *var_dict = NULL;
452         GVariantDict dict;
453         mesh_interface_s *info = NULL;
454
455         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
456         meshd_check_null_ret_error("connection", service->connection,
457                         MESHD_ERROR_INVALID_PARAMETER);
458         meshd_check_null_ret_error("_gproxy_connman_technology",
459                         _gproxy_connman_technology, MESHD_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                 MESH_LOGD("Successfully requested. [MeshInterfaceRemove]");
473         } else if (error) {
474                 ret = MESHD_ERROR_IO_ERROR;
475                 MESH_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 = MESHD_ERROR_NONE;
480                 g_error_free(error);
481         }
482
483         return ret;
484 }
485
486 int mesh_gdbus_mesh_scan(mesh_service *service)
487 {
488         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
489         meshd_check_null_ret_error("connection", service->connection,
490                         MESHD_ERROR_INVALID_PARAMETER);
491         meshd_check_null_ret_error("_gproxy_connman_technology",
492                         _gproxy_connman_technology, MESHD_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         MESH_LOGD("Successfully requested. [Scan]");
500
501         return MESHD_ERROR_NONE;
502 }
503
504 int mesh_gdbus_mesh_specific_scan(mesh_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         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
515         meshd_check_null_ret_error("connection", service->connection,
516                         MESHD_ERROR_INVALID_PARAMETER);
517         meshd_check_null_ret_error("_gproxy_connman_technology",
518                         _gproxy_connman_technology, MESHD_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                 MESH_LOGD("Successfully requested. [MeshSpecificScan]");
531         } else if (error) {
532                 MESH_LOGE("Failed DBus call [%s]", error->message);
533                 g_error_free(error);
534                 return MESHD_ERROR_IO_ERROR;
535         }
536
537         return MESHD_ERROR_NONE;
538 }
539
540 int mesh_gdbus_mesh_cancel_scan(mesh_service *service)
541 {
542         int ret = MESHD_ERROR_NONE;
543         GVariant *variant = NULL;
544         GError *error = NULL;
545         GVariant *var_dict = NULL;
546         GVariantDict dict;
547
548         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
549         meshd_check_null_ret_error("connection", service->connection,
550                         MESHD_ERROR_INVALID_PARAMETER);
551         meshd_check_null_ret_error("_gproxy_connman_technology",
552                         _gproxy_connman_technology, MESHD_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                 MESH_LOGD("Successfully requested. [AbortScan]");
563         } else if (error) {
564                 ret = MESHD_ERROR_IO_ERROR;
565                 MESH_LOGE("Failed DBus call [%s]", error->message);
566
567                 /* Scan is not in progress */
568                 if (g_strrstr(error->message, "Already exists"))
569                         ret = MESHD_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         mesh_scan_result_s *scan_item = (mesh_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         mesh_peer_info_s *peer = (mesh_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(mesh_service *service, GVariant *variant)
599 {
600         GVariantIter *peer = NULL;
601         GVariantIter *property = NULL;
602         gchar *key = NULL;
603         GVariant *val = NULL;
604         gsize len = 0;
605         GVariant *child;
606         const gchar* obj_path = NULL;
607         const gchar* buf = NULL;
608
609         g_variant_get(variant, "(a(oa{sv}))", &peer);
610         while ((child = g_variant_iter_next_value(peer))) {
611                 mesh_network_info_s *joined_info = NULL;
612                 gboolean valid_state = TRUE;
613
614                 g_variant_get(child, "(oa{sv})", &obj_path, &property);
615                 MESH_LOGD("  Object: [%s]", obj_path);
616                 if (NULL == obj_path) {
617                         MESH_LOGE("Null object");
618                         continue;
619                 }
620
621                 /* Create an information structure for joined network */
622                 joined_info = g_try_new0(mesh_network_info_s, 1);
623                 if (NULL == joined_info) {
624                         MESH_LOGE("Failed to allocate !");
625                         return;
626                 }
627
628                 while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
629                         if (strcasecmp(key, "Name") == 0) {
630                                 buf = g_variant_get_string(val, &len);
631                                 joined_info->mesh_id = g_strdup(buf);
632                         } else if (strcasecmp(key, "BSSID") == 0) {
633                                 buf = g_variant_get_string(val, &len);
634                                 joined_info->bssid = g_strdup(buf);
635                         } else if (strcasecmp(key, "State") == 0) {
636                                 buf = g_variant_get_string(val, &len);
637                                 MESH_LOGD("    State : %s", buf);
638
639                                 /* Skip ignorable state */
640                                 if (g_strcmp0(buf, "idle") == 0
641                                         || g_strcmp0(buf, "disconnect") == 0
642                                         || g_strcmp0(buf, "failure") == 0) {
643                                         valid_state = FALSE;
644                                         break;
645                                 } else if (g_strcmp0(buf, "association") == 0) {
646                                         joined_info->state = MESHD_CONNECTION_STATE_ASSOCIATION;
647                                 } else if (g_strcmp0(buf, "configuration") == 0) {
648                                         joined_info->state = MESHD_CONNECTION_STATE_CONFIGURATION;
649                                 } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
650                                         joined_info->state = MESHD_CONNECTION_STATE_CONNECTED;
651                                 }
652                         } else if (strcasecmp(key, "Security") == 0) {
653                                 buf = g_variant_get_string(val, &len);
654                                 if (g_strcmp0("sae", buf) == 0)
655                                         joined_info->security = MESHD_SECURITY_SAE;
656                                 else
657                                         joined_info->security = MESHD_SECURITY_NONE;
658                         } else if (strcasecmp(key, "Frequency") == 0) {
659                                 joined_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
660                         }
661                 }
662
663                 /* Skip ignorable state */
664                 if (FALSE == valid_state) {
665                         g_free(joined_info->mesh_id);
666                         g_free(joined_info->bssid);
667                         continue;
668                 }
669
670                 MESH_LOGD("    Mesh ID  : %s", joined_info->mesh_id);
671                 MESH_LOGD("    BSSID    : %s", joined_info->bssid);
672                 MESH_LOGD("    Channel  : %d", joined_info->channel);
673                 MESH_LOGD("    Security : %s",
674                         (MESHD_SECURITY_SAE == joined_info->security) ? "SAE" : "NONE");
675                 service->joined_network = joined_info;
676
677                 g_variant_iter_free(property);
678
679                 /* If found, stop loop iteration */
680                 break;
681         }
682         g_variant_iter_free(peer);
683 }
684
685 static void _get_mesh_peers(mesh_service *service, GVariant *variant)
686 {
687         GVariantIter *peer = NULL;
688         GVariantIter *property = NULL;
689         gchar *key = NULL;
690         GVariant *val = NULL;
691         gsize len = 0;
692         GVariant *child;
693         const gchar* obj_path = NULL;
694
695         g_variant_get(variant, "(a(oa{sv}))", &peer);
696         while ((child = g_variant_iter_next_value(peer))) {
697                 mesh_scan_result_s *scan_info = NULL;
698
699                 scan_info = g_try_new0(mesh_scan_result_s, 1);
700                 if (NULL == scan_info) {
701                         MESH_LOGE("Failed to allocate !");
702                         return;
703                 }
704
705                 g_variant_get(child, "(oa{sv})", &obj_path, &property);
706                 if (NULL == obj_path) {
707                         MESH_LOGE("Null object");
708                         g_free(scan_info);
709                         continue;
710                 }
711                 MESH_LOGD("    Obj path : [%s]", obj_path);
712                 scan_info->object_path = g_strdup(obj_path);
713
714                 while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
715                         if (strcasecmp(key, "Name") == 0) {
716                                 const char *buf = g_variant_get_string(val, &len);
717                                 scan_info->mesh_id = g_strdup(buf);
718                                 MESH_LOGD("    Mesh ID : %s", scan_info->mesh_id);
719                         } else if (strcasecmp(key, "BSSID") == 0) {
720                                 const char *buf = g_variant_get_string(val, &len);
721                                 scan_info->bssid = g_strdup(buf);
722                                 MESH_LOGD("    BSSID : %s", scan_info->bssid);
723                         } else if (strcasecmp(key, "State") == 0) {
724                                 const char *buf = g_variant_get_string(val, &len);
725                                 MESH_LOGD("    State : %s", buf);
726
727                                 if (g_strcmp0(buf, "idle") == 0
728                                         || g_strcmp0(buf, "disconnect") == 0
729                                         || g_strcmp0(buf, "failure") == 0) {
730                                         scan_info->state = MESHD_CONNECTION_STATE_DISCONNECTED;
731                                 } else if (g_strcmp0(buf, "association") == 0) {
732                                         scan_info->state = MESHD_CONNECTION_STATE_ASSOCIATION;
733                                 } else if (g_strcmp0(buf, "configuration") == 0) {
734                                         scan_info->state = MESHD_CONNECTION_STATE_CONFIGURATION;
735                                 } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
736                                         scan_info->state = MESHD_CONNECTION_STATE_CONNECTED;
737                                 }
738                         } else if (strcasecmp(key, "Security") == 0) {
739                                 const char *buf = g_variant_get_string(val, &len);
740                                 MESH_LOGD("    Security : %s", buf);
741                                 if (g_strcmp0("sae", buf) == 0)
742                                         scan_info->security = MESHD_SECURITY_SAE;
743                                 else
744                                         scan_info->security = MESHD_SECURITY_NONE;
745                         } else if (strcasecmp(key, "Frequency") == 0) {
746                                 scan_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
747                                 MESH_LOGD("    Channel : %d", scan_info->channel);
748                         } else if (strcasecmp(key, "Favorite") == 0) {
749                                 const char *buf = g_variant_get_string(val, &len);
750                                 MESH_LOGD("    Favorite : %s", buf);
751                         } else if (strcasecmp(key, "Strength") == 0) {
752                                 scan_info->rssi = (gint)g_variant_get_byte(val);
753                                 MESH_LOGD("    RSSI : %d", scan_info->rssi);
754                         }
755                 }
756                 /* Last element */
757                 service->scanned_mesh_network =
758                         g_list_prepend(service->scanned_mesh_network, scan_info);
759
760                 g_variant_iter_free(property);
761         }
762         g_variant_iter_free(peer);
763 }
764
765 static void _get_connected_mesh_peers(mesh_service *service, GVariant *variant)
766 {
767         GVariantIter *peer = NULL;
768         GVariant *val = NULL;
769         gsize len = 0;
770         GVariant *child;
771         GVariant *dict = NULL;
772
773         g_variant_get(variant, "(a(a{sv}))", &peer);
774         while ((child = g_variant_iter_next_value(peer))) {
775                 mesh_peer_info_s *peer_info = NULL;
776
777                 peer_info = g_try_new0(mesh_peer_info_s, 1);
778                 if (NULL == peer_info) {
779                         MESH_LOGE("Failed to allocate !");
780                         return;
781                 }
782
783                 /* a{sv} <- (a{sv}) */
784                 dict = g_variant_get_child_value(child, 0);
785                 val = g_variant_lookup_value(dict, "PeerAddress", NULL);
786                 if (NULL != val) {
787                         const char *buf = g_variant_get_string(val, &len);
788                         peer_info->address = g_strdup(buf);
789                         MESH_LOGD("    Address : %s", peer_info->address);
790                         g_variant_unref(val);
791                 } else {
792                         MESH_LOGE("Unable to get address !");
793                         g_free(peer_info);
794                         continue;
795                 }
796
797                 service->connected_mesh_peers =
798                         g_list_prepend(service->connected_mesh_peers, peer_info);
799         }
800         g_variant_iter_free(peer);
801 }
802
803 int mesh_gdbus_get_mesh_networks(mesh_service *service)
804 {
805         GVariant *variant = NULL;
806         GError *error = NULL;
807
808         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
809         meshd_check_null_ret_error("connection", service->connection,
810                         MESHD_ERROR_INVALID_PARAMETER);
811         meshd_check_null_ret_error("_gproxy_connman",
812                         _gproxy_connman, MESHD_ERROR_IO_ERROR);
813
814         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
815                                 NULL,
816                                 G_DBUS_CALL_FLAGS_NONE,
817                                 -1, NULL, &error);
818         if (variant) {
819                 MESH_LOGD("Successfully requested. [GetMeshPeers]");
820
821                 if (service->scanned_mesh_network) {
822                         g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
823                         service->scanned_mesh_network = NULL;
824                 }
825
826                 _get_mesh_peers(service, variant);
827
828                 /* List item is saved with reversed order for efficiency. */
829                 service->scanned_mesh_network =
830                                 g_list_reverse(service->scanned_mesh_network);
831         } else if (error) {
832                 MESH_LOGE("Failed DBus call [%s]", error->message);
833                 g_error_free(error);
834                 return MESHD_ERROR_IO_ERROR;
835         }
836
837         return MESHD_ERROR_NONE;
838 }
839
840 int mesh_gdbus_get_joined_mesh_network(mesh_service *service)
841 {
842         GVariant *variant = NULL;
843         GError *error = NULL;
844
845         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
846         meshd_check_null_ret_error("connection", service->connection,
847                         MESHD_ERROR_INVALID_PARAMETER);
848         meshd_check_null_ret_error("_gproxy_connman",
849                         _gproxy_connman, MESHD_ERROR_IO_ERROR);
850
851         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
852                                 NULL,
853                                 G_DBUS_CALL_FLAGS_NONE,
854                                 -1, NULL, &error);
855         if (variant) {
856                 MESH_LOGD("Successfully requested. [GetMeshPeers]");
857
858                 if (service->joined_network) {
859                         g_free(service->joined_network->mesh_id);
860                         g_free(service->joined_network->bssid);
861                         g_free(service->joined_network);
862                         service->joined_network = NULL;
863                 }
864
865                 _get_joined_network(service, variant);
866         } else if (error) {
867                 MESH_LOGE("Failed DBus call [%s]", error->message);
868                 g_error_free(error);
869                 return MESHD_ERROR_IO_ERROR;
870         }
871
872         return MESHD_ERROR_NONE;
873 }
874
875 int mesh_gdbus_get_connected_peers(mesh_service *service)
876 {
877         GVariant *variant = NULL;
878         GError *error = NULL;
879
880         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
881         meshd_check_null_ret_error("connection", service->connection,
882                         MESHD_ERROR_INVALID_PARAMETER);
883         meshd_check_null_ret_error("_gproxy_connman",
884                         _gproxy_connman, MESHD_ERROR_IO_ERROR);
885
886         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetConnectedMeshPeers",
887                                 NULL,
888                                 G_DBUS_CALL_FLAGS_NONE,
889                                 -1, NULL, &error);
890         if (variant) {
891                 MESH_LOGD("Successfully requested. [GetConnectedMeshPeers]");
892
893                 if (service->connected_mesh_peers) {
894                         g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
895                         service->connected_mesh_peers = NULL;
896                 }
897
898                 _get_connected_mesh_peers(service, variant);
899
900                 /* List item is saved with reversed order for efficiency. */
901                 service->connected_mesh_peers =
902                                 g_list_reverse(service->connected_mesh_peers);
903         } else if (error) {
904                 MESH_LOGE("Failed DBus call [%s]", error->message);
905                 g_error_free(error);
906                 return MESHD_ERROR_IO_ERROR;
907         }
908
909         return MESHD_ERROR_NONE;
910 }
911
912 static void _get_mesh_property(GVariant *variant, mesh_network_info_s *result)
913 {
914         GVariantIter *property = NULL;
915         gchar *key = NULL;
916         GVariant *val = NULL;
917         gsize len = 0;
918
919         MESH_LOGD("Type [%s]", g_variant_get_type_string(variant));
920
921         g_variant_get(variant, "(a{sv})", &property);
922
923         while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
924                 if (strcasecmp(key, "Name") == 0) {
925                         const char *buf = g_variant_get_string(val, &len);
926                         result->mesh_id = g_strdup(buf);
927                         MESH_LOGD("    Mesh ID : %s", result->mesh_id);
928                 } else if (strcasecmp(key, "BSSID") == 0) {
929                         const char *buf = g_variant_get_string(val, &len);
930                         result->bssid = g_strdup(buf);
931                         MESH_LOGD("    BSSID : %s", result->bssid);
932                 } else if (strcasecmp(key, "State") == 0) {
933                         const char *buf = g_variant_get_string(val, &len);
934                         MESH_LOGD("    State : %s", buf);
935
936                         if (g_strcmp0(buf, "idle") == 0
937                                 || g_strcmp0(buf, "disconnect") == 0
938                                 || g_strcmp0(buf, "failure") == 0) {
939                                 result->state = MESHD_CONNECTION_STATE_DISCONNECTED;
940                         } else if (g_strcmp0(buf, "association") == 0) {
941                                 result->state = MESHD_CONNECTION_STATE_ASSOCIATION;
942                         } else if (g_strcmp0(buf, "configuration") == 0) {
943                                 result->state = MESHD_CONNECTION_STATE_CONFIGURATION;
944                         } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
945                                 result->state = MESHD_CONNECTION_STATE_CONNECTED;
946                         }
947                 } else if (strcasecmp(key, "Security") == 0) {
948                         const char *buf = g_variant_get_string(val, &len);
949                         MESH_LOGD("    Security : %s", buf);
950                         if (g_strcmp0("sae", buf) == 0)
951                                 result->security = MESHD_SECURITY_SAE;
952                         else
953                                 result->security = MESHD_SECURITY_NONE;
954                 } else if (strcasecmp(key, "Frequency") == 0) {
955                         result->channel = __frequency_to_channel(g_variant_get_uint16(val));
956                         MESH_LOGD("    Channel : %d", result->channel);
957                 } else if (strcasecmp(key, "Favorite") == 0) {
958                         const char *buf = g_variant_get_string(val, &len);
959                         MESH_LOGD("    Favorite : %s", buf);
960                 } else if (strcasecmp(key, "Strength") == 0) {
961                         gint rssi = (gint)g_variant_get_byte(val);
962                         MESH_LOGD("    RSSI : %d", rssi);
963                 }
964         }
965         g_variant_iter_free(property);
966 }
967
968 static int _mesh_gdbus_get_mesh_network_property(mesh_service *service,
969         const gchar* object_path, mesh_network_info_s *result)
970 {
971         GVariant *variant = NULL;
972         GError *error = NULL;
973
974         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
975         meshd_check_null_ret_error("connection", service->connection,
976                         MESHD_ERROR_INVALID_PARAMETER);
977         meshd_check_null_ret_error("result", result, MESHD_ERROR_INVALID_PARAMETER);
978
979         variant = g_dbus_connection_call_sync(service->connection,
980                         CONNMAN_SERVER_NAME,
981                         object_path,
982                         CONNMAN_INTERFACE_MESH,
983                         "GetProperties",
984                         NULL, NULL,
985                         G_DBUS_CALL_FLAGS_NONE,
986                         -1, NULL, &error);
987         if (variant) {
988                 MESH_LOGD("Successfully requested. [GetProperties]");
989
990                 /* Get properties */
991                 _get_mesh_property(variant, result);
992         } else if (error) {
993                 LOGE("Failed DBus call [%s]", error->message);
994                 g_error_free(error);
995                 return MESHD_ERROR_IO_ERROR;
996         }
997
998         return MESHD_ERROR_NONE;
999 }
1000
1001 int mesh_gdbus_create_network(mesh_service *service, gchar *mesh_id,
1002                 gint channel, meshd_security_type_e sec)
1003 {
1004         GVariant *variant = NULL;
1005         GError *error = NULL;
1006         GVariant *var_dict = NULL;
1007         GVariantBuilder builder;
1008         const gchar* security = (MESHD_SECURITY_SAE == sec) ? "sae" : "none";
1009
1010         enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
1011         gushort freq = __channel_to_frequency(channel, band);
1012
1013         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1014         meshd_check_null_ret_error("connection", service->connection,
1015                         MESHD_ERROR_INVALID_PARAMETER);
1016         meshd_check_null_ret_error("_gproxy_connman_technology",
1017                         _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
1018
1019         g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
1020         g_variant_builder_open(&builder, G_VARIANT_TYPE("a{sv}"));
1021
1022         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1023         g_variant_builder_add(&builder, "s", "Name");
1024         g_variant_builder_add(&builder, "v", g_variant_new_string(mesh_id));
1025         g_variant_builder_close(&builder); /* {sv} */
1026
1027         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1028         g_variant_builder_add(&builder, "s", "Frequency");
1029         g_variant_builder_add(&builder, "v", g_variant_new_uint16(freq));
1030         g_variant_builder_close(&builder); /* {sv} */
1031
1032         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1033         g_variant_builder_add(&builder, "s", "Security");
1034         g_variant_builder_add(&builder, "v", g_variant_new_string(security));
1035         g_variant_builder_close(&builder); /* {sv} */
1036
1037         g_variant_builder_close(&builder); /* a{sv} */
1038
1039         var_dict = g_variant_builder_end(&builder);
1040
1041         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
1042                                 g_variant_new("(sv)", "MeshCreateNetwork", var_dict),
1043                                 G_DBUS_CALL_FLAGS_NONE,
1044                                 -1, NULL, &error);
1045         if (variant) {
1046                 MESH_LOGD("Successfully requested. [MeshCreateNetwork]");
1047         } else if (error) {
1048                 MESH_LOGE("Failed DBus call [%s]", error->message);
1049                 g_error_free(error);
1050                 return MESHD_ERROR_IO_ERROR;
1051         }
1052
1053         return MESHD_ERROR_NONE;
1054 }
1055
1056 int mesh_gdbus_set_passphrase(mesh_service *service, mesh_scan_result_s *info, gchar *passphrase)
1057 {
1058         GVariant *variant = NULL;
1059         GError *error = NULL;
1060
1061         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1062         meshd_check_null_ret_error("passphrase", passphrase, MESHD_ERROR_INVALID_PARAMETER);
1063
1064         variant = g_dbus_connection_call_sync(service->connection,
1065                         CONNMAN_SERVER_NAME,
1066                         info->object_path,
1067                         CONNMAN_INTERFACE_MESH,
1068                         "SetProperty",
1069                         g_variant_new("(sv)", "Passphrase", g_variant_new_string(passphrase)),
1070                         NULL,
1071                         G_DBUS_CALL_FLAGS_NONE,
1072                         -1, NULL, &error);
1073         if (variant) {
1074                 MESH_LOGD("Successfully requested. [SetProperty]");
1075         } else if (error) {
1076                 LOGE("Failed DBus call [%s]", error->message);
1077                 g_error_free(error);
1078                 return MESHD_ERROR_IO_ERROR;
1079         }
1080
1081         return MESHD_ERROR_NONE;
1082 }
1083
1084 #if 0
1085 static void on_response_connect_network(GObject *source_object,
1086         GAsyncResult *res, gpointer user_data)
1087 {
1088         int ret = MESHD_ERROR_NONE;
1089         GError *error = NULL;
1090         GVariant *variant = NULL;
1091
1092         NOTUSED(user_data);
1093
1094         variant = g_dbus_connection_call_finish(
1095                         G_DBUS_CONNECTION(source_object), res, &error);
1096         if (variant) {
1097                 MESH_LOGD("Successfully requested. [Connect]");
1098
1099                 /* TODO: Unregister property change event */
1100         } else if (error) {
1101                 ret = MESHD_ERROR_IO_ERROR;
1102                 LOGE("Failed DBus call [%s]", error->message);
1103
1104                 if (g_strrstr(error->message, "Already exists"))
1105                         ret = MESHD_ERROR_ALREADY_REGISTERED;
1106                 else if (g_strrstr(error->message, "In progress"))
1107                         ret = MESHD_ERROR_IN_PROGRESS;
1108                 else
1109                         ret = MESHD_ERROR_IO_ERROR;
1110
1111                 g_error_free(error);
1112         }
1113 }
1114 #endif
1115
1116 int mesh_gdbus_connect_network(mesh_service *service, mesh_scan_result_s *info)
1117 {
1118         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1119         meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
1120
1121         g_dbus_connection_call(service->connection,
1122                         CONNMAN_SERVER_NAME,
1123                         info->object_path,
1124                         CONNMAN_INTERFACE_MESH,
1125                         "Connect",
1126                         NULL, NULL,
1127                         G_DBUS_CALL_FLAGS_NONE,
1128                         -1,
1129                         NULL, /* G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED */
1130                         NULL, NULL);
1131         MESH_LOGD("Successfully requested. [Connect]");
1132
1133         return MESHD_ERROR_NONE;
1134 }
1135
1136 int mesh_gdbus_disconnect_network(mesh_service *service, mesh_scan_result_s *info)
1137 {
1138         GVariant *variant = NULL;
1139         GError *error = NULL;
1140
1141         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1142         meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
1143
1144         variant = g_dbus_connection_call_sync(service->connection,
1145                         CONNMAN_SERVER_NAME,
1146                         info->object_path,
1147                         CONNMAN_INTERFACE_MESH,
1148                         "Disconnect",
1149                         NULL, NULL,
1150                         G_DBUS_CALL_FLAGS_NONE,
1151                         -1, NULL, &error);
1152         if (variant) {
1153                 MESH_LOGD("Successfully requested. [Disconnect]");
1154         } else if (error) {
1155                 LOGE("Failed DBus call [%s]", error->message);
1156                 g_error_free(error);
1157                 return MESHD_ERROR_IO_ERROR;
1158         }
1159
1160         return MESHD_ERROR_NONE;
1161 }
1162
1163 int mesh_gdbus_remove_network(mesh_service *service, mesh_scan_result_s *info)
1164 {
1165         GVariant *variant = NULL;
1166         GError *error = NULL;
1167
1168         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1169         meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
1170
1171         variant = g_dbus_connection_call_sync(service->connection,
1172                         CONNMAN_SERVER_NAME,
1173                         info->object_path,
1174                         CONNMAN_INTERFACE_MESH,
1175                         "Remove",
1176                         NULL, NULL,
1177                         G_DBUS_CALL_FLAGS_NONE,
1178                         -1, NULL, &error);
1179         if (variant) {
1180                 MESH_LOGD("Successfully requested. [Remove]");
1181         } else if (error) {
1182                 LOGE("Failed DBus call [%s]", error->message);
1183                 g_error_free(error);
1184                 return MESHD_ERROR_IO_ERROR;
1185         }
1186
1187         return MESHD_ERROR_NONE;
1188 }
1189
1190
1191 int mesh_gdbus_enable_ethernet_interface(mesh_service *service, bool state)
1192 {
1193         int ret = MESHD_ERROR_NONE;
1194         GVariant *variant = NULL;
1195         GError *error = NULL;
1196         mesh_interface_s *info = NULL;
1197
1198         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1199         meshd_check_null_ret_error("connection", service->connection,
1200                         MESHD_ERROR_INVALID_PARAMETER);
1201         meshd_check_null_ret_error("_gproxy_connman_technology",
1202                         _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
1203
1204         info = service->interface_info;
1205         meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
1206
1207         variant = g_dbus_proxy_call_sync(_gproxy_connman_ethernet, "SetProperty",
1208                                 g_variant_new("(sv)", "Powered", g_variant_new_boolean(state)),
1209                                 G_DBUS_CALL_FLAGS_NONE,
1210                                 -1, NULL, &error);
1211         if (variant) {
1212                 MESH_LOGD("Successfully requested. [Powered]");
1213         } else if (error) {
1214                 ret = MESHD_ERROR_IO_ERROR;
1215                 MESH_LOGE("Failed DBus call [%s]", error->message);
1216
1217                 /* Interface not exists (Not created yet) */
1218                 if (g_strrstr(error->message, "No such device"))
1219                         ret = MESHD_ERROR_NONE;
1220                 g_error_free(error);
1221         }
1222
1223         return ret;
1224 }
1225
1226 int mesh_gdbus_set_mesh_gate(mesh_service *service)
1227 {
1228         int ret = MESHD_ERROR_NONE;
1229         GVariant *variant = NULL;
1230         GError *error = NULL;
1231         GVariant *var_dict = NULL;
1232         GVariantDict dict;
1233         mesh_interface_s *info = NULL;
1234
1235         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
1236         meshd_check_null_ret_error("connection", service->connection,
1237                         MESHD_ERROR_INVALID_PARAMETER);
1238         meshd_check_null_ret_error("_gproxy_connman_technology",
1239                         _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
1240
1241         info = service->interface_info;
1242
1243         g_variant_dict_init(&dict, NULL);
1244         g_variant_dict_insert(&dict, "GateAnnounce", "b", info->gate_announce);
1245         g_variant_dict_insert(&dict, "HWMPRootMode", "q", info->hwmp_root_mode);
1246         g_variant_dict_insert(&dict, "STP", "q", info->stp);
1247         var_dict = g_variant_dict_end(&dict);
1248
1249         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
1250                                 g_variant_new("(sv)", "SetMeshGate", var_dict),
1251                                 G_DBUS_CALL_FLAGS_NONE,
1252                                 -1, NULL, &error);
1253         if (variant) {
1254                 MESH_LOGD("Successfully requested. [SetMeshGate]");
1255         } else if (error) {
1256                 ret = MESHD_ERROR_IO_ERROR;
1257                 MESH_LOGE("Failed DBus call [%s]", error->message);
1258
1259                 /* Interface not exists */
1260                 if (g_strrstr(error->message, "No such device"))
1261                         ret = MESHD_ERROR_INVALID_PARAMETER;
1262                 g_error_free(error);
1263         }
1264
1265         return ret;
1266 }
1267