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