Fix resource leak (Prevent)
[platform/core/connectivity/wifi-mesh-manager.git] / src / wmesh-request.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <stdlib.h>
20
21 #include <glib.h>
22 #include <gio/gio.h>
23
24 #include "wmesh.h"
25 #include "wmesh-log.h"
26 #include "wmesh-util.h"
27 #include "wmesh-service-interface.h"
28 #include "wmesh-generated-code.h"
29
30 #include "wmesh-bridge.h"
31 #include "wmesh-netlink.h"
32 #include "wmesh-interface.h"
33 #include "wmesh-request.h"
34 #include "wmesh-softap.h"
35 #include "wmesh-gdbus.h"
36
37 int wmesh_request_set_mesh_gate(const char* bridge_interface,
38                 const char* mesh_interface, const char* external_interface)
39 {
40         int ret = WMESHD_ERROR_NONE;
41         bool state = FALSE;
42
43         ret = wmesh_interface_check_external_exists(external_interface, &state);
44         if (WMESHD_ERROR_NONE != ret) {
45                 WMESH_LOGE("Failed to get external interface state !");
46                 return WMESHD_ERROR_OPERATION_FAILED;
47         }
48         WMESH_LOGD("  Ethernet cable state [%s]",
49                 (state) ? "Connected" : "Disconnected");
50
51         /* Turn STP on */
52         ret = wmesh_bridge_set_stp(bridge_interface, TRUE);
53         if (WMESHD_ERROR_NONE != ret) {
54                 WMESH_LOGE("Failed to turn STP on !");
55                 return ret;
56         }
57
58         /* Set mesh parameters */
59         ret = wmesh_netlink_set_mesh_parameter(mesh_interface,
60                         "mesh_hwmp_rootmode", 4);
61         if (WMESHD_ERROR_NONE != ret)
62                 WMESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4");
63
64         ret = wmesh_netlink_set_mesh_parameter(mesh_interface,
65                         "mesh_gate_announcements", 1);
66         if (WMESHD_ERROR_NONE != ret)
67                 WMESH_LOGE("Failed to set [mesh_gate_announcements] : 1");
68
69         return WMESHD_ERROR_NONE;
70 }
71
72 int wmesh_request_unset_mesh_gate(const char* bridge_interface,
73                 const char* mesh_interface, const char* external_interface)
74 {
75         int ret = WMESHD_ERROR_NONE;
76
77         NOTUSED(external_interface);
78
79         /* Set mesh parameters */
80         ret = wmesh_netlink_set_mesh_parameter(mesh_interface,
81                         "mesh_hwmp_rootmode", 0);
82         if (WMESHD_ERROR_NONE != ret)
83                 WMESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 0");
84
85         ret = wmesh_netlink_set_mesh_parameter(mesh_interface,
86                         "mesh_gate_announcements", 0);
87         if (WMESHD_ERROR_NONE != ret)
88                 WMESH_LOGE("Failed to set [mesh_gate_announcements] : 0");
89
90         /* Turn STP off */
91         ret = wmesh_bridge_set_stp(bridge_interface, FALSE);
92         if (WMESHD_ERROR_NONE != ret) {
93                 WMESH_LOGE("Failed to turn STP off!");
94                 return ret;
95         }
96
97         return WMESHD_ERROR_NONE;
98 }
99
100 int wmesh_request_add_bridge_interface(const char* bridge_interface,
101                 const char* interface)
102 {
103         int ret = WMESHD_ERROR_NONE;
104
105         if (NULL == bridge_interface || NULL == interface) {
106                 WMESH_LOGE("Invalid parameters");
107                 return WMESHD_ERROR_INVALID_PARAMETER;
108         }
109
110         WMESH_LOGD("Adding interface[%s] into bridge[%s]...", interface, bridge_interface);
111
112         /* Add external interface into bridge */
113         ret = wmesh_bridge_add_interface(bridge_interface, interface);
114         if (WMESHD_ERROR_NONE != ret) {
115                 WMESH_LOGE("Failed to add interface !");
116                 return ret;
117         }
118
119         /* Make external interface down */
120         ret = wmesh_interface_set(interface, NULL, WMESH_INTERFACE_DOWN);
121         if (WMESHD_ERROR_NONE != ret) {
122                 WMESH_LOGE("Failed to change external interface state");
123                 return ret;
124         }
125
126         /* Make external interface up with cleared IP */
127         ret = wmesh_interface_set(interface, "0.0.0.0", WMESH_INTERFACE_UP);
128         if (WMESHD_ERROR_NONE != ret) {
129                 WMESH_LOGE("Failed to change external interface state");
130                 return ret;
131         }
132
133         return WMESHD_ERROR_NONE;
134 }
135
136 int wmesh_request_remove_bridge_interface(const char* bridge_interface,
137                 const char* interface)
138 {
139         int ret = WMESHD_ERROR_NONE;
140
141         if (NULL == bridge_interface || NULL == interface) {
142                 WMESH_LOGE("Invalid parameters");
143                 return WMESHD_ERROR_INVALID_PARAMETER;
144         }
145
146         WMESH_LOGD("Removing interface[%s] from bridge[%s]...", interface, bridge_interface);
147
148         ret = wmesh_interface_check_bridge_interface_exists(bridge_interface, interface);
149         if (WMESHD_ERROR_NONE != ret) {
150                 WMESH_LOGD("Interface is not exist in bridge");
151                 return WMESHD_ERROR_NONE;
152         }
153
154         /* Remove external interface into bridge */
155         ret = wmesh_bridge_del_interface(bridge_interface, interface);
156         if (WMESHD_ERROR_NONE != ret) {
157                 WMESH_LOGE("Failed to remove interface !");
158                 return ret;
159         }
160
161         return WMESHD_ERROR_NONE;
162 }
163
164 int wmesh_request_set_softap_config(const char* softap_interface,
165                 const char *ssid, const char* mode, int channel, int visibility,
166                 int max_sta, int security, const char* passphrase)
167 {
168         int ret = WMESHD_ERROR_NONE;
169
170         WMESH_LOGD("Setting configuration for SoftAP");
171
172         ret = wmesh_softap_set_configuration(softap_interface, ssid, mode, channel,
173                         visibility, max_sta, security, passphrase);
174         if (WMESHD_ERROR_NONE != ret) {
175                 WMESH_LOGE("Failed to set Configuration for SoftAP");
176                 return ret;
177         }
178
179         return ret;
180 }
181
182 int wmesh_request_get_softap_config(char **softap_interface, char **ssid,
183                         char **mode, int *channel, int *visibility,
184                 int *max_sta, int *security, char **passphrase)
185 {
186         int ret = WMESHD_ERROR_NONE;
187
188         WMESH_LOGD("Get configuration for SoftAP");
189
190         ret = wmesh_softap_get_configuration(softap_interface, ssid, mode, channel,
191                         visibility, max_sta, security, passphrase);
192         if (WMESHD_ERROR_NONE != ret) {
193                 WMESH_LOGE("Failed to get Configuration for SoftAP");
194                 return ret;
195         }
196
197         return ret;
198 }
199
200 int wmesh_request_enable_softap(
201                 const char* bridge_interface, const char* softap_interface)
202 {
203         int ret = WMESHD_ERROR_NONE;
204
205         WMESH_LOGD("Request to turn SoftAP on");
206         ret = wmesh_softap_enable_softap(softap_interface);
207         if (WMESHD_ERROR_NONE != ret) {
208                 WMESH_LOGE("Failed to wmesh_softap_enable_softap");
209                 return ret;
210         }
211
212         /* Add softAP interface into bridge */
213         ret = wmesh_request_add_bridge_interface(bridge_interface, softap_interface);
214         if (WMESHD_ERROR_NONE != ret) {
215                 wmesh_softap_disable_softap();
216                 return ret;
217         }
218
219         return ret;
220 }
221
222 int wmesh_request_disable_softap(
223                 const char* bridge_interface, const char* softap_interface)
224 {
225         int ret = WMESHD_ERROR_NONE;
226
227         WMESH_LOGD("Request to turn SoftAP off");
228         ret = wmesh_softap_disable_softap();
229
230         /* Remove softAP interface from bridge */
231         ret = wmesh_request_remove_bridge_interface(bridge_interface, softap_interface);
232         if (WMESHD_ERROR_NONE != ret)
233                 return ret;
234
235         return ret;
236 }
237
238 bool wmesh_request_check_softap_status()
239 {
240         WMESH_LOGD("Check softAp status");
241
242         return  wmesh_softap_check_softap_status();
243 }
244
245 int wmesh_request_get_station_info(const char* mesh_interface, GList **station_list)
246 {
247         int ret = WMESHD_ERROR_NONE;
248
249         WMESH_LOGD("Request to get station info");
250
251         /* Get station info */
252         ret = wmesh_netlink_get_station_info(mesh_interface, station_list);
253         if (WMESHD_ERROR_NONE != ret)
254                 return ret;
255
256         return WMESHD_ERROR_NONE;
257 }
258
259 int wmesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list)
260 {
261         int ret = WMESHD_ERROR_NONE;
262
263         WMESH_LOGD("Request to get mpath info");
264
265         /* Get MPath info */
266         ret = wmesh_netlink_get_mpath_info(mesh_interface, mpath_list);
267         if (WMESHD_ERROR_NONE != ret)
268                 return ret;
269
270         return WMESHD_ERROR_NONE;
271 }
272
273 int wmesh_request_get_meshconf_info(wmesh_service *service)
274 {
275         int ret = WMESHD_ERROR_NONE;
276
277         WMESH_LOGD("Request to get meshconf info");
278
279         /* Get MPath info */
280         ret = wmesh_netlink_get_meshconf_info(service);
281         if (WMESHD_ERROR_NONE != ret)
282                 return ret;
283
284         return WMESHD_ERROR_NONE;
285 }
286
287 int wmesh_request_register_event_handler(wmesh_service *service)
288 {
289         int ret = WMESHD_ERROR_NONE;
290
291         WMESH_LOGD("Request to register mesh event handler");
292
293         /* Get MPath info */
294         ret = wmesh_netlink_register_event_handler(service);
295         if (WMESHD_ERROR_NONE != ret)
296                 return ret;
297
298         return WMESHD_ERROR_NONE;
299 }
300
301 int wmesh_request_unregister_event_handler()
302 {
303         int ret = WMESHD_ERROR_NONE;
304
305         WMESH_LOGD("Request to unregister mesh event handler");
306
307         /* Get MPath info */
308         ret = wmesh_netlink_unregister_event_handler();
309         if (WMESHD_ERROR_NONE != ret)
310                 return ret;
311
312         return WMESHD_ERROR_NONE;
313 }
314
315 int wmesh_request_enable_network(wmesh_service *service)
316 {
317         int ret;
318         wmesh_interface_s *info = NULL;
319
320         if (NULL == service) {
321                 WMESH_LOGE("Invalid parameter");
322                 return WMESHD_ERROR_INVALID_PARAMETER;
323         }
324
325         WMESH_LOGD("[IPC] Enable mesh network");
326
327         /* Check if mesh interface exists */
328         info = service->interface_info;
329         ret = wmesh_interface_check(info->mesh_interface);
330         if (WMESHD_ERROR_NONE == ret) {
331                 /* Interface already exists */
332                 return WMESHD_ERROR_NONE;
333         }
334
335         ret = wmesh_gdbus_create_mesh_interface(service);
336         if (WMESHD_ERROR_NONE != ret) {
337                 WMESH_LOGE("Failed to create mesh network");
338                 return ret;
339         }
340
341         return WMESHD_ERROR_NONE;
342 }
343
344 int wmesh_request_disable_network(wmesh_service *service)
345 {
346         int ret;
347         if (NULL == service) {
348                 WMESH_LOGE("Invalid parameter");
349                 return WMESHD_ERROR_INVALID_PARAMETER;
350         }
351
352         WMESH_LOGD("[IPC] Disable mesh network");
353
354         ret = wmesh_gdbus_remove_mesh_interface(service);
355         if (WMESHD_ERROR_NONE != ret) {
356                 WMESH_LOGE("Failed to disable mesh network");
357                 return ret;
358         }
359
360         return WMESHD_ERROR_NONE;
361 }
362
363 int wmesh_request_scan(wmesh_service *service)
364 {
365         int ret;
366         if (NULL == service) {
367                 WMESH_LOGE("Invalid parameter");
368                 return WMESHD_ERROR_INVALID_PARAMETER;
369         }
370
371         WMESH_LOGD("[IPC] Request scan for mesh network");
372
373         ret = wmesh_gdbus_mesh_scan(service);
374         if (WMESHD_ERROR_NONE != ret) {
375                 WMESH_LOGE("Failed to request scan for mesh network");
376                 return ret;
377         }
378
379         return WMESHD_ERROR_NONE;
380 }
381
382 int wmesh_request_specific_scan(wmesh_service *service, gchar *mesh_id, gint channel)
383 {
384         int ret;
385         if (NULL == service) {
386                 WMESH_LOGE("Invalid parameter");
387                 return WMESHD_ERROR_INVALID_PARAMETER;
388         }
389
390         WMESH_LOGD("[IPC] Request specific scan for mesh network");
391
392         ret = wmesh_gdbus_mesh_specific_scan(service, mesh_id, channel);
393         if (WMESHD_ERROR_NONE != ret) {
394                 WMESH_LOGE("Failed to request specific scan for mesh network");
395                 return ret;
396         }
397
398         return WMESHD_ERROR_NONE;
399 }
400
401 int wmesh_request_cancel_scan(wmesh_service *service)
402 {
403         int ret;
404         if (NULL == service) {
405                 WMESH_LOGE("Invalid parameter");
406                 return WMESHD_ERROR_INVALID_PARAMETER;
407         }
408
409         WMESH_LOGD("[IPC] Cancel scan for mesh network");
410
411         ret = wmesh_gdbus_mesh_cancel_scan(service);
412         if (WMESHD_ERROR_NONE != ret) {
413                 WMESH_LOGE("Failed to cancel scan for mesh network");
414                 return ret;
415         }
416
417         return WMESHD_ERROR_NONE;
418 }
419
420 int wmesh_request_get_networks(wmesh_service *service)
421 {
422         int ret;
423         if (NULL == service) {
424                 WMESH_LOGE("Invalid parameter");
425                 return WMESHD_ERROR_INVALID_PARAMETER;
426         }
427
428         WMESH_LOGD("[IPC] Get mesh networks");
429
430         ret = wmesh_gdbus_get_mesh_networks(service);
431         if (WMESHD_ERROR_NONE != ret) {
432                 WMESH_LOGE("Failed to get mesh networks !");
433                 return ret;
434         }
435
436         return WMESHD_ERROR_NONE;
437 }
438
439 static int _select_matched_network(GList *scanned_network,
440                 const char *mesh_id, int mesh_channel, wmeshd_security_type_e sec,
441                 wmesh_scan_result_s **info)
442 {
443         int ret = WMESHD_ERROR_NONE;
444         GList *iter = NULL;
445         wmesh_scan_result_s *item = NULL;
446         gboolean found = FALSE;
447
448         wmeshd_check_null_ret_error("scanned_network", scanned_network,
449                         WMESHD_ERROR_INVALID_PARAMETER);
450
451         iter = scanned_network;
452         while (iter != NULL) {
453                 item = (wmesh_scan_result_s*)iter->data;
454
455                 if (g_strcmp0(mesh_id, item->mesh_id) == 0) {
456                         if (item->channel == mesh_channel && item->security == sec) {
457                                 *info = item;
458                                 found = TRUE;
459                                 break;
460                         }
461                 }
462                 iter = g_list_next(iter);
463         }
464
465         if (FALSE == found)
466                 return WMESHD_ERROR_NO_DATA;
467
468         return ret;
469 }
470
471 int wmesh_request_get_joined_network(wmesh_service *service)
472 {
473         int ret;
474
475         if (NULL == service) {
476                 WMESH_LOGE("Invalid parameter");
477                 return WMESHD_ERROR_INVALID_PARAMETER;
478         }
479
480         WMESH_LOGD("[IPC] Get joined mesh network");
481
482         ret = wmesh_gdbus_get_joined_mesh_network(service);
483         if (WMESHD_ERROR_NONE != ret) {
484                 WMESH_LOGE("Failed to get joined mesh network");
485                 return ret;
486         }
487
488         return WMESHD_ERROR_NONE;
489 }
490
491 int wmesh_request_get_connected_peers(wmesh_service *service)
492 {
493         int ret;
494
495         if (NULL == service) {
496                 WMESH_LOGE("Invalid parameter");
497                 return WMESHD_ERROR_INVALID_PARAMETER;
498         }
499
500         WMESH_LOGD("[IPC] Get connected mesh peers");
501
502         ret = wmesh_gdbus_get_connected_peers(service);
503         if (WMESHD_ERROR_NONE != ret) {
504                 WMESH_LOGE("Failed to get connected mesh peers");
505                 return ret;
506         }
507
508         return WMESHD_ERROR_NONE;
509 }
510
511 int wmesh_request_create_mesh_network(wmesh_service *service, gchar *mesh_id,
512                 gint channel, wmeshd_security_type_e sec)
513 {
514         int ret;
515
516         if (NULL == service) {
517                 WMESH_LOGE("Invalid parameter");
518                 return WMESHD_ERROR_INVALID_PARAMETER;
519         }
520
521         WMESH_LOGD("[IPC] Create a new mesh network");
522
523         ret = wmesh_gdbus_create_network(service, mesh_id, channel, sec);
524         if (WMESHD_ERROR_NONE != ret) {
525                 WMESH_LOGE("Failed to create mesh network");
526                 return ret;
527         }
528
529         return WMESHD_ERROR_NONE;
530 }
531
532 int wmesh_request_connect_mesh_network(wmesh_service *service, gchar *mesh_id,
533                 gint channel, wmeshd_security_type_e sec, gchar *passphrase)
534 {
535         int ret;
536         wmesh_scan_result_s *info = NULL;
537
538         if (NULL == service) {
539                 WMESH_LOGE("Invalid parameter");
540                 return WMESHD_ERROR_INVALID_PARAMETER;
541         }
542
543         WMESH_LOGD("[IPC] Connect mesh network");
544
545         /* Get mesh_id and channel from saved network */
546         ret = _select_matched_network(service->scanned_mesh_network,
547                         mesh_id, channel, sec, &info);
548         if (WMESHD_ERROR_NONE != ret) {
549                 WMESH_LOGE("Failed to mesh_network_get_first_mesh_network");
550                 return ret;
551         }
552
553         /* Set passphrase */
554         if (WMESHD_SECURITY_NONE != sec) {
555                 if (NULL != passphrase) {
556                         ret = wmesh_gdbus_set_passphrase(service, info, passphrase);
557                         if (WMESHD_ERROR_NONE != ret) {
558                                 WMESH_LOGE("Failed to set passphrase for mesh network");
559                                 return ret;
560                         }
561                 } else {
562                         WMESH_LOGE("Passphrase is required !");
563                         return WMESHD_ERROR_INVALID_PARAMETER;
564                 }
565         }
566
567         ret = wmesh_gdbus_connect_network(service, info);
568         if (WMESHD_ERROR_NONE != ret) {
569                 WMESH_LOGE("Failed to connect mesh network");
570                 return ret;
571         }
572
573         return WMESHD_ERROR_NONE;
574 }
575
576 int wmesh_request_disconnect_mesh_network(wmesh_service *service,
577                 gchar *mesh_id, gint channel, wmeshd_security_type_e sec)
578 {
579         int ret;
580         wmesh_scan_result_s *info = NULL;
581
582         if (NULL == service) {
583                 WMESH_LOGE("Invalid parameter");
584                 return WMESHD_ERROR_INVALID_PARAMETER;
585         }
586
587         WMESH_LOGD("[IPC] Disconnect mesh network");
588
589         /* Get mesh_id and channel from saved network */
590         ret = _select_matched_network(service->scanned_mesh_network,
591                         mesh_id, channel, sec, &info);
592         if (WMESHD_ERROR_NONE != ret) {
593                 WMESH_LOGE("Failed to _select_matched_network");
594                 return ret;
595         }
596
597         ret = wmesh_gdbus_disconnect_network(service, info);
598         if (WMESHD_ERROR_NONE != ret) {
599                 WMESH_LOGE("Failed to disconnect mesh network");
600                 return ret;
601         }
602
603         return WMESHD_ERROR_NONE;
604 }
605
606 int wmesh_request_remove_mesh_network(wmesh_service *service,
607                 gchar *mesh_id, gint channel, wmeshd_security_type_e sec)
608 {
609         int ret;
610         wmesh_scan_result_s *info = NULL;
611
612         if (NULL == service) {
613                 WMESH_LOGE("Invalid parameter");
614                 return WMESHD_ERROR_INVALID_PARAMETER;
615         }
616
617         WMESH_LOGD("[IPC] Remove mesh network");
618
619         /* Get mesh_id and channel from saved network */
620         ret = _select_matched_network(service->scanned_mesh_network,
621                         mesh_id, channel, sec, &info);
622         if (WMESHD_ERROR_NONE != ret) {
623                 WMESH_LOGE("Failed to _select_matched_network");
624                 return ret;
625         }
626
627         ret = wmesh_gdbus_remove_network(service, info);
628         if (WMESHD_ERROR_NONE != ret) {
629                 WMESH_LOGE("Failed to remove mesh network");
630                 return ret;
631         }
632
633         return WMESHD_ERROR_NONE;
634 }
635
636 /* Notifications */
637 void wmesh_notify_scan_done()
638 {
639         NetWmesh *object = wmeshd_dbus_get_object();
640
641         net_wmesh_emit_scan_done(object);
642 }
643
644 void wmesh_notify_connection_state(const char* mesh_id, const char* bssid,
645                 int channel, wmeshd_security_type_e sec, wmeshd_connection_state_e state)
646 {
647         NetWmesh *object = wmeshd_dbus_get_object();
648
649         net_wmesh_emit_connection_state(object, mesh_id, bssid, channel, (int)sec, (int)state);
650 }
651
652 void wmesh_notify_station_joined(const char* bssid,
653                                                                  wmeshd_station_type_e station_type)
654 {
655         NetWmesh *object = wmeshd_dbus_get_object();
656
657         net_wmesh_emit_sta_joined(object, bssid, station_type);
658 }
659
660 void wmesh_notify_station_left(const char* bssid,
661                                                            wmeshd_station_type_e station_type)
662 {
663         NetWmesh *object = wmeshd_dbus_get_object();
664
665         net_wmesh_emit_sta_left(object, bssid, station_type);
666 }