Fix declaration-after-statement error for gcc9
[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                 } else {
861                         WMESH_LOGE("Unable to get address !");
862                         g_free(peer_info);
863                         continue;
864                 }
865
866                 service->connected_mesh_peers =
867                         g_list_prepend(service->connected_mesh_peers, peer_info);
868                 /* LCOV_EXCL_STOP */
869         }
870         g_variant_iter_free(peer);
871 }
872
873 int wmesh_gdbus_get_mesh_networks(wmesh_service *service)
874 {
875         GVariant *variant = NULL;
876         GError *error = NULL;
877
878         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
879         wmeshd_check_null_ret_error("connection", service->connection,
880                         WMESHD_ERROR_INVALID_PARAMETER);
881         wmeshd_check_null_ret_error("_gproxy_connman",
882                         _gproxy_connman, WMESHD_ERROR_IO_ERROR);
883
884         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
885                                 NULL,
886                                 G_DBUS_CALL_FLAGS_NONE,
887                                 -1, NULL, &error);
888         if (variant) {
889                 WMESH_LOGD("Successfully requested. [GetMeshPeers]");
890
891                 if (service->scanned_mesh_network) {
892                         /* LCOV_EXCL_START */
893                         g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
894                         service->scanned_mesh_network = NULL;
895                         /* LCOV_EXCL_STOP */
896                 }
897
898                 _get_mesh_peers(service, variant);
899
900                 /* List item is saved with reversed order for efficiency. */
901                 service->scanned_mesh_network =
902                                 g_list_reverse(service->scanned_mesh_network);
903         /* LCOV_EXCL_START */
904         } else if (error) {
905                 WMESH_LOGE("Failed DBus call [%s]", error->message);
906                 g_error_free(error);
907                 return WMESHD_ERROR_IO_ERROR;
908         }
909         /* LCOV_EXCL_STOP */
910
911         return WMESHD_ERROR_NONE;
912 }
913
914 int wmesh_gdbus_get_joined_mesh_network(wmesh_service *service)
915 {
916         GVariant *variant = NULL;
917         GError *error = NULL;
918
919         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
920         wmeshd_check_null_ret_error("connection", service->connection,
921                         WMESHD_ERROR_INVALID_PARAMETER);
922         wmeshd_check_null_ret_error("_gproxy_connman",
923                         _gproxy_connman, WMESHD_ERROR_IO_ERROR);
924
925         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
926                                 NULL,
927                                 G_DBUS_CALL_FLAGS_NONE,
928                                 -1, NULL, &error);
929         if (variant) {
930                 WMESH_LOGD("Successfully requested. [GetMeshPeers]");
931
932                 if (service->joined_network) {
933                         /* LCOV_EXCL_START */
934                         g_free(service->joined_network->mesh_id);
935                         g_free(service->joined_network->bssid);
936                         g_free(service->joined_network->ipv4_address);
937                         g_free(service->joined_network->ipv4_netmask);
938                         g_free(service->joined_network);
939                         service->joined_network = NULL;
940                         /* LCOV_EXCL_STOP */
941                 }
942
943                 _get_joined_network(service, variant);
944         /* LCOV_EXCL_START */
945         } else if (error) {
946                 WMESH_LOGE("Failed DBus call [%s]", error->message);
947                 g_error_free(error);
948                 return WMESHD_ERROR_IO_ERROR;
949         }
950         /* LCOV_EXCL_STOP */
951
952         return WMESHD_ERROR_NONE;
953 }
954
955 /* LCOV_EXCL_START */
956 int wmesh_gdbus_get_connected_peers(wmesh_service *service)
957 {
958         GVariant *variant = NULL;
959         GError *error = NULL;
960
961         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
962         wmeshd_check_null_ret_error("connection", service->connection,
963                         WMESHD_ERROR_INVALID_PARAMETER);
964         wmeshd_check_null_ret_error("_gproxy_connman",
965                         _gproxy_connman, WMESHD_ERROR_IO_ERROR);
966
967         variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetConnectedMeshPeers",
968                                 NULL,
969                                 G_DBUS_CALL_FLAGS_NONE,
970                                 -1, NULL, &error);
971         if (variant) {
972                 WMESH_LOGD("Successfully requested. [GetConnectedMeshPeers]");
973
974                 if (service->connected_mesh_peers) {
975                         g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
976                         service->connected_mesh_peers = NULL;
977                 }
978
979                 _get_connected_mesh_peers(service, variant);
980
981                 /* List item is saved with reversed order for efficiency. */
982                 service->connected_mesh_peers =
983                                 g_list_reverse(service->connected_mesh_peers);
984         } else if (error) {
985                 WMESH_LOGE("Failed DBus call [%s]", error->message);
986                 g_error_free(error);
987                 return WMESHD_ERROR_IO_ERROR;
988         }
989
990         return WMESHD_ERROR_NONE;
991 }
992
993 static void _get_mesh_property(GVariant *variant, wmesh_network_info_s *result)
994 {
995         GVariantIter *property = NULL;
996         gchar *key = NULL;
997         GVariant *val = NULL;
998         gsize len = 0;
999
1000         WMESH_LOGD("Type [%s]", g_variant_get_type_string(variant));
1001
1002         g_variant_get(variant, "(a{sv})", &property);
1003
1004         while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
1005                 if (strcasecmp(key, "Name") == 0) {
1006                         const char *buf = g_variant_get_string(val, &len);
1007                         result->mesh_id = g_strdup(buf);
1008                         WMESH_LOGD("    Mesh ID : %s", result->mesh_id);
1009                 } else if (strcasecmp(key, "BSSID") == 0) {
1010                         const char *buf = g_variant_get_string(val, &len);
1011                         result->bssid = g_strdup(buf);
1012                         WMESH_LOGD("    BSSID : %s", result->bssid);
1013                 } else if (strcasecmp(key, "State") == 0) {
1014                         const char *buf = g_variant_get_string(val, &len);
1015                         WMESH_LOGD("    State : %s", buf);
1016
1017                         if (g_strcmp0(buf, "idle") == 0
1018                                 || g_strcmp0(buf, "disconnect") == 0
1019                                 || g_strcmp0(buf, "failure") == 0) {
1020                                 result->state = WMESHD_CONNECTION_STATE_DISCONNECTED;
1021                         } else if (g_strcmp0(buf, "association") == 0) {
1022                                 result->state = WMESHD_CONNECTION_STATE_ASSOCIATION;
1023                         } else if (g_strcmp0(buf, "configuration") == 0) {
1024                                 result->state = WMESHD_CONNECTION_STATE_CONFIGURATION;
1025                         } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
1026                                 result->state = WMESHD_CONNECTION_STATE_CONNECTED;
1027                         }
1028                 } else if (strcasecmp(key, "Security") == 0) {
1029                         const char *buf = g_variant_get_string(val, &len);
1030                         WMESH_LOGD("    Security : %s", buf);
1031                         if (g_strcmp0("sae", buf) == 0)
1032                                 result->security = WMESHD_SECURITY_SAE;
1033                         else
1034                                 result->security = WMESHD_SECURITY_NONE;
1035                 } else if (strcasecmp(key, "Frequency") == 0) {
1036                         result->channel = __frequency_to_channel(g_variant_get_uint16(val));
1037                         WMESH_LOGD("    Channel : %d", result->channel);
1038                 } else if (strcasecmp(key, "Favorite") == 0) {
1039                         const char *buf = g_variant_get_string(val, &len);
1040                         WMESH_LOGD("    Favorite : %s", buf);
1041                 } else if (strcasecmp(key, "Strength") == 0) {
1042                         gint rssi = (gint)g_variant_get_byte(val);
1043                         WMESH_LOGD("    RSSI : %d", rssi);
1044                 }
1045         }
1046         g_variant_iter_free(property);
1047 }
1048 /* LCOV_EXCL_STOP */
1049
1050 static int _wmesh_gdbus_get_mesh_network_property(wmesh_service *service,
1051         const gchar* object_path, wmesh_network_info_s *result)
1052 {
1053         GVariant *variant = NULL;
1054         GError *error = NULL;
1055
1056         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1057         wmeshd_check_null_ret_error("connection", service->connection,
1058                         WMESHD_ERROR_INVALID_PARAMETER);
1059         wmeshd_check_null_ret_error("result", result, WMESHD_ERROR_INVALID_PARAMETER);
1060
1061         variant = g_dbus_connection_call_sync(service->connection,
1062                         CONNMAN_SERVER_NAME,
1063                         object_path,
1064                         CONNMAN_INTERFACE_MESH,
1065                         "GetProperties",
1066                         NULL, NULL,
1067                         G_DBUS_CALL_FLAGS_NONE,
1068                         -1, NULL, &error);
1069         if (variant) {
1070                 WMESH_LOGD("Successfully requested. [GetProperties]");
1071
1072                 /* Get properties */
1073                 _get_mesh_property(variant, result);
1074         /* LCOV_EXCL_START */
1075         } else if (error) {
1076                 LOGE("Failed DBus call [%s]", error->message);
1077                 g_error_free(error);
1078                 return WMESHD_ERROR_IO_ERROR;
1079         }
1080         /* LCOV_EXCL_STOP */
1081
1082         return WMESHD_ERROR_NONE;
1083 }
1084
1085 int wmesh_gdbus_create_network(wmesh_service *service, gchar *mesh_id,
1086                 gint channel, wmeshd_security_type_e sec, wmeshd_pmf_type_e pmf)
1087 {
1088         GVariant *variant = NULL;
1089         GError *error = NULL;
1090         GVariant *var_dict = NULL;
1091         GVariantBuilder builder;
1092         const gchar* security = (WMESHD_SECURITY_SAE == sec) ? "sae" : "none";
1093
1094         enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
1095         gushort freq = __channel_to_frequency(channel, band);
1096
1097         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1098         wmeshd_check_null_ret_error("connection", service->connection,
1099                         WMESHD_ERROR_INVALID_PARAMETER);
1100         wmeshd_check_null_ret_error("_gproxy_connman_technology",
1101                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
1102
1103         g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
1104         g_variant_builder_open(&builder, G_VARIANT_TYPE("a{sv}"));
1105
1106         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1107         g_variant_builder_add(&builder, "s", "Name");
1108         g_variant_builder_add(&builder, "v", g_variant_new_string(mesh_id));
1109         g_variant_builder_close(&builder); /* {sv} */
1110
1111         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1112         g_variant_builder_add(&builder, "s", "Frequency");
1113         g_variant_builder_add(&builder, "v", g_variant_new_uint16(freq));
1114         g_variant_builder_close(&builder); /* {sv} */
1115
1116         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1117         g_variant_builder_add(&builder, "s", "Security");
1118         g_variant_builder_add(&builder, "v", g_variant_new_string(security));
1119         g_variant_builder_close(&builder); /* {sv} */
1120
1121         g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
1122         g_variant_builder_add(&builder, "s", "Pmf");
1123         g_variant_builder_add(&builder, "v", g_variant_new_uint16(pmf));
1124         g_variant_builder_close(&builder); /* {sv} */
1125
1126         g_variant_builder_close(&builder); /* a{sv} */
1127
1128         var_dict = g_variant_builder_end(&builder);
1129
1130         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
1131                                 g_variant_new("(sv)", "MeshCreateNetwork", var_dict),
1132                                 G_DBUS_CALL_FLAGS_NONE,
1133                                 -1, NULL, &error);
1134         g_variant_builder_unref(&builder);
1135         if (variant) {
1136                 WMESH_LOGD("Successfully requested. [MeshCreateNetwork]"); /* LCOV_EXCL_LINE */
1137         /* LCOV_EXCL_START */
1138         } else if (error) {
1139                 WMESH_LOGE("Failed DBus call [%s]", error->message);
1140                 g_error_free(error);
1141                 return WMESHD_ERROR_IO_ERROR;
1142         }
1143         /* LCOV_EXCL_STOP */
1144
1145         return WMESHD_ERROR_NONE;
1146 }
1147
1148 /* LCOV_EXCL_START */
1149 int wmesh_gdbus_set_passphrase(wmesh_service *service, wmesh_scan_result_s *info, gchar *passphrase)
1150 {
1151         int ret = WMESHD_ERROR_NONE;
1152         GVariant *variant = NULL;
1153         GVariant *var_passphrase = NULL;
1154         GError *error = NULL;
1155
1156         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1157         wmeshd_check_null_ret_error("passphrase", passphrase, WMESHD_ERROR_INVALID_PARAMETER);
1158
1159         var_passphrase = g_variant_new_string(passphrase);
1160         variant = g_dbus_connection_call_sync(service->connection,
1161                         CONNMAN_SERVER_NAME,
1162                         info->object_path,
1163                         CONNMAN_INTERFACE_MESH,
1164                         "SetProperty",
1165                         g_variant_new("(sv)", "Passphrase", var_passphrase),
1166                         NULL,
1167                         G_DBUS_CALL_FLAGS_NONE,
1168                         -1, NULL, &error);
1169         if (variant) {
1170                 WMESH_LOGD("Successfully requested. [SetProperty]");
1171         } else if (error) {
1172                 LOGE("Failed DBus call [%s]", error->message);
1173                 g_error_free(error);
1174                 ret = WMESHD_ERROR_IO_ERROR;
1175         }
1176         g_variant_unref(var_passphrase);
1177         return ret;
1178 }
1179
1180 #if 0
1181 static void on_response_connect_network(GObject *source_object,
1182         GAsyncResult *res, gpointer user_data)
1183 {
1184         int ret = WMESHD_ERROR_NONE;
1185         GError *error = NULL;
1186         GVariant *variant = NULL;
1187
1188         NOTUSED(user_data);
1189
1190         variant = g_dbus_connection_call_finish(
1191                         G_DBUS_CONNECTION(source_object), res, &error);
1192         if (variant) {
1193                 WMESH_LOGD("Successfully requested. [Connect]");
1194
1195                 /* TODO: Unregister property change event */
1196         } else if (error) {
1197                 ret = WMESHD_ERROR_IO_ERROR;
1198                 LOGE("Failed DBus call [%s]", error->message);
1199
1200                 if (g_strrstr(error->message, "Already exists"))
1201                         ret = WMESHD_ERROR_ALREADY_REGISTERED;
1202                 else if (g_strrstr(error->message, "In progress"))
1203                         ret = WMESHD_ERROR_IN_PROGRESS;
1204                 else
1205                         ret = WMESHD_ERROR_IO_ERROR;
1206
1207                 g_error_free(error);
1208         }
1209 }
1210 #endif
1211
1212 int wmesh_gdbus_connect_network(wmesh_service *service, wmesh_scan_result_s *info)
1213 {
1214         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1215         wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
1216
1217         g_dbus_connection_call(service->connection,
1218                         CONNMAN_SERVER_NAME,
1219                         info->object_path,
1220                         CONNMAN_INTERFACE_MESH,
1221                         "Connect",
1222                         NULL, NULL,
1223                         G_DBUS_CALL_FLAGS_NONE,
1224                         -1,
1225                         NULL, /* G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED */
1226                         NULL, NULL);
1227         WMESH_LOGD("Successfully requested. [Connect]");
1228
1229         return WMESHD_ERROR_NONE;
1230 }
1231
1232 int wmesh_gdbus_disconnect_network(wmesh_service *service, wmesh_scan_result_s *info)
1233 {
1234         GVariant *variant = NULL;
1235         GError *error = NULL;
1236
1237         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1238         wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
1239
1240         variant = g_dbus_connection_call_sync(service->connection,
1241                         CONNMAN_SERVER_NAME,
1242                         info->object_path,
1243                         CONNMAN_INTERFACE_MESH,
1244                         "Disconnect",
1245                         NULL, NULL,
1246                         G_DBUS_CALL_FLAGS_NONE,
1247                         -1, NULL, &error);
1248         if (variant) {
1249                 WMESH_LOGD("Successfully requested. [Disconnect]");
1250         } else if (error) {
1251                 LOGE("Failed DBus call [%s]", error->message);
1252                 g_error_free(error);
1253                 return WMESHD_ERROR_IO_ERROR;
1254         }
1255
1256         return WMESHD_ERROR_NONE;
1257 }
1258
1259 int wmesh_gdbus_remove_network(wmesh_service *service, wmesh_scan_result_s *info)
1260 {
1261         GVariant *variant = NULL;
1262         GError *error = NULL;
1263
1264         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1265         wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
1266
1267         variant = g_dbus_connection_call_sync(service->connection,
1268                         CONNMAN_SERVER_NAME,
1269                         info->object_path,
1270                         CONNMAN_INTERFACE_MESH,
1271                         "Remove",
1272                         NULL, NULL,
1273                         G_DBUS_CALL_FLAGS_NONE,
1274                         -1, NULL, &error);
1275         if (variant) {
1276                 WMESH_LOGD("Successfully requested. [Remove]");
1277         } else if (error) {
1278                 LOGE("Failed DBus call [%s]", error->message);
1279                 g_error_free(error);
1280                 return WMESHD_ERROR_IO_ERROR;
1281         }
1282
1283         return WMESHD_ERROR_NONE;
1284 }
1285
1286
1287 int wmesh_gdbus_enable_ethernet_interface(wmesh_service *service, bool state)
1288 {
1289         int ret = WMESHD_ERROR_NONE;
1290         GVariant *variant = NULL;
1291         GVariant *var_state = NULL;
1292         GError *error = NULL;
1293         wmesh_interface_s *info = NULL;
1294
1295         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1296         wmeshd_check_null_ret_error("connection", service->connection,
1297                         WMESHD_ERROR_INVALID_PARAMETER);
1298         wmeshd_check_null_ret_error("_gproxy_connman_technology",
1299                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
1300
1301         info = service->interface_info;
1302         wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
1303
1304         var_state = g_variant_new_boolean(state);
1305         variant = g_dbus_proxy_call_sync(_gproxy_connman_ethernet, "SetProperty",
1306                                 g_variant_new("(sv)", "Powered", var_state),
1307                                 G_DBUS_CALL_FLAGS_NONE,
1308                                 -1, NULL, &error);
1309         if (variant) {
1310                 WMESH_LOGD("Successfully requested. [Powered]");
1311         } else if (error) {
1312                 ret = WMESHD_ERROR_IO_ERROR;
1313                 WMESH_LOGE("Failed DBus call [%s]", error->message);
1314
1315                 /* Interface not exists (Not created yet) */
1316                 if (g_strrstr(error->message, "No such device"))
1317                         ret = WMESHD_ERROR_NONE;
1318                 g_error_free(error);
1319         }
1320         g_variant_unref(var_state);
1321
1322         return ret;
1323 }
1324 /* LCOV_EXCL_STOP */
1325
1326 int wmesh_gdbus_set_mesh_gate(wmesh_service *service)
1327 {
1328         int ret = WMESHD_ERROR_NONE;
1329         GVariant *variant = NULL;
1330         GError *error = NULL;
1331         GVariant *var_dict = NULL;
1332         GVariantDict dict;
1333         wmesh_interface_s *info = NULL;
1334
1335         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
1336         wmeshd_check_null_ret_error("connection", service->connection,
1337                         WMESHD_ERROR_INVALID_PARAMETER);
1338         wmeshd_check_null_ret_error("_gproxy_connman_technology",
1339                         _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
1340
1341         info = service->interface_info;
1342
1343         g_variant_dict_init(&dict, NULL);
1344         g_variant_dict_insert(&dict, "GateAnnounce", "b", info->gate_announce);
1345         g_variant_dict_insert(&dict, "HWMPRootMode", "q", info->hwmp_root_mode);
1346         g_variant_dict_insert(&dict, "STP", "q", info->stp);
1347         var_dict = g_variant_dict_end(&dict);
1348
1349         variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
1350                                 g_variant_new("(sv)", "SetMeshGate", var_dict),
1351                                 G_DBUS_CALL_FLAGS_NONE,
1352                                 -1, NULL, &error);
1353         if (variant) {
1354                 WMESH_LOGD("Successfully requested. [SetMeshGate]"); /* LCOV_EXCL_LINE */
1355         /* LCOV_EXCL_START */
1356         } else if (error) {
1357                 ret = WMESHD_ERROR_IO_ERROR;
1358                 WMESH_LOGE("Failed DBus call [%s]", error->message);
1359
1360                 /* Interface not exists */
1361                 if (g_strrstr(error->message, "No such device"))
1362                         ret = WMESHD_ERROR_INVALID_PARAMETER;
1363                 g_error_free(error);
1364         }
1365         /* LCOV_EXCL_STOP */
1366
1367         return ret;
1368 }
1369
1370 /* LCOV_EXCL_START */
1371 int wmesh_gdbus_mesh_remove_peer(wmesh_service *service, char *peer)
1372 {
1373         GVariant *variant = NULL;
1374         GError *error = NULL;
1375         int ret = WMESHD_ERROR_NONE;
1376
1377         wmeshd_check_null_ret_error("service", service,
1378                                                                 WMESHD_ERROR_INVALID_PARAMETER);
1379         wmeshd_check_null_ret_error("connection", service->connection,
1380                         WMESHD_ERROR_INVALID_PARAMETER);
1381         wmeshd_check_null_ret_error("_gproxy_connman",
1382                         _gproxy_connman, WMESHD_ERROR_IO_ERROR);
1383
1384         variant = g_dbus_proxy_call_sync(_gproxy_connman, "MeshRemovePeer",
1385                                 g_variant_new("(s)", peer), G_DBUS_CALL_FLAGS_NONE, -1, NULL,
1386                                 &error);
1387         if (variant) {
1388                 WMESH_LOGD("Successfully requested. [MeshRemovePeer]");
1389         } else if (error) {
1390                 ret = WMESHD_ERROR_IO_ERROR;
1391                 WMESH_LOGE("Failed DBus call [%s]", error->message);
1392
1393                 /* Interface not exists */
1394                 if (g_strrstr(error->message, "No such device"))
1395                         ret = WMESHD_ERROR_INVALID_PARAMETER;
1396                 g_error_free(error);
1397         }
1398
1399         return ret;
1400 }
1401 /* LCOV_EXCL_STOP */
1402