Fix resource leak (Prevent)
[platform/core/connectivity/wifi-mesh-manager.git] / src / wmesh-peer-monitor.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 <glib.h>
20
21 #include "wmesh.h"
22 #include "wmesh-log.h"
23 #include "wmesh-util.h"
24 #include "wmesh-gdbus.h"
25 #include "wmesh-request.h"
26 #include "wmesh-netlink.h"
27 #include "wmesh-interface.h"
28 #include "wmesh-peer-monitor.h"
29
30 #define MESH_MONITORING_TIME 5
31 #define MESH_MAXIMUM_BEACON_LOST_COUNT 10
32
33 static void _on_station_list_destroy(gpointer data)
34 {
35         wmesh_station_info_s *info = (wmesh_station_info_s*)data;
36
37         if (info) {
38                 g_free(info->bssid);
39                 g_free(info);
40         }
41 }
42 #if 0
43 static void _on_mpath_list_destroy(gpointer data)
44 {
45         wmesh_mpath_info_s *info = (wmesh_mpath_info_s*)data;
46
47         if (info) {
48                 g_free(info->dest_addr);
49                 g_free(info->next_hop);
50                 g_free(info->interface);
51                 g_free(info);
52         }
53 }
54 #endif
55
56 static int _get_station_info(void *pdata)
57 {
58         int is_new;
59         int ret = WMESHD_ERROR_NONE;
60
61         GList *iter = NULL;
62         GList *sta_list = NULL;
63         GList *cmp_iter = NULL;
64
65         wmesh_service *service = (wmesh_service *)pdata;
66         wmesh_interface_s *info = service->interface_info;
67
68         ret = wmesh_request_get_station_info(info->mesh_interface, &sta_list);
69         if (WMESHD_ERROR_NONE != ret) {
70                 WMESH_LOGE("Failed to wmesh_request_get_station_info");
71                 return ret;
72         }
73
74         iter = service->station_list;
75         while (iter) {
76                 wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
77                 WMESH_LOGD("[%s]", item->bssid);
78                 iter = g_list_next(iter);
79         }
80
81         iter = sta_list;
82         while (iter) {
83                 wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
84
85                 /* Found this in th existing station infomation list. */
86                 if (item->inactive_time > item->beacon_interval * MESH_MAXIMUM_BEACON_LOST_COUNT) {
87                         /* Remove this node from station list in kernel */
88                         wmesh_gdbus_mesh_remove_peer(service, item->bssid);
89                         /* Remove current linked list */
90                         sta_list = g_list_remove(iter, item);
91                         /* Send existing node disjoined */
92                         WMESH_LOGE("[%s] disjoined", item->bssid);
93
94                 }
95
96                 is_new = TRUE;
97                 cmp_iter = service->station_list;
98                 while (cmp_iter) {
99                         wmesh_station_info_s *cmp_item = (wmesh_station_info_s*)cmp_iter->data;
100                         if (0 == strncmp(item->bssid, cmp_item->bssid, sizeof("11:22:33:44:55:66"))) {
101                                 is_new = FALSE;
102                                 break;
103                         }
104                         cmp_iter = g_list_next(cmp_iter);
105                 }
106
107                 if (is_new) {
108                         /* Send new station joined event */
109                         WMESH_LOGE("[%s] joined", item->bssid);
110                 }
111
112                 iter = g_list_next(iter);
113         }
114
115         /* Clear mesh station list */
116         g_list_free_full(service->station_list, _on_station_list_destroy);
117         /* Copy new mesh station list */
118         service->station_list = sta_list;
119         WMESH_LOGD("station_list length %d", g_list_length(service->station_list));
120
121         iter = service->station_list;
122         while (iter) {
123                 wmesh_station_info_s *item2 = (wmesh_station_info_s*)iter->data;
124                 WMESH_LOGE("[%s]", item2->bssid);
125                 iter = g_list_next(iter);
126         }
127
128         return ret;
129 }
130 #if 0
131 static gboolean _get_mpath_info(void *pdata)
132 {
133         int ret = WMESHD_ERROR_NONE;
134         GVariantBuilder builder;
135         GVariant* mpath_data;
136         GList *iter = NULL;
137
138         wmesh_service *service = (wmesh_service *)pdata;
139         wmesh_interface_s *info = service->interface_info;
140
141         /* Clear mesh path list */
142         g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
143         service->mpath_list = NULL;
144
145         ret = wmesh_request_get_mpath_info(info->mesh_interface, &service->mpath_list);
146         if (WMESHD_ERROR_NONE == ret) {
147         /*
148          * Example) sh-3.2# iw mesh0 mpath dump
149          * DEST ADDR         NEXT HOP          IFACE    SN      METRIC  QLEN    EXPTIME         DTIM    DRET    FLAGS
150          * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0    221     152             0               10                      100             0               0x5
151          */
152                 /* Get mesh path information and make variant data */
153                 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
154
155                 iter = service->mpath_list;
156                 while (iter != NULL) {
157                         wmesh_mpath_info_s *item = (wmesh_mpath_info_s*)iter->data;
158
159                         g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
160                         g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
161                                                 g_variant_new_string(item->dest_addr));
162                         g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
163                                                 g_variant_new_string(item->next_hop));
164                         g_variant_builder_add(&builder, "{sv}", "IFACE",
165                                                 g_variant_new_string(item->interface));
166                         g_variant_builder_add(&builder, "{sv}", "SN",
167                                                 g_variant_new_uint32(item->sn));
168                         g_variant_builder_add(&builder, "{sv}", "METRIC",
169                                                 g_variant_new_uint32(item->metric));
170                         g_variant_builder_add(&builder, "{sv}", "QLEN",
171                                                 g_variant_new_uint32(item->qlen));
172                         g_variant_builder_add(&builder, "{sv}", "EXPTIME",
173                                                 g_variant_new_uint32(item->exptime));
174                         g_variant_builder_add(&builder, "{sv}", "DTIM",
175                                                 g_variant_new_uint32(item->discovery_timeout));
176                         g_variant_builder_add(&builder, "{sv}", "DRET",
177                                                 g_variant_new_byte(item->discovery_retries));
178                         g_variant_builder_add(&builder, "{sv}", "FLAGS",
179                                                 g_variant_new_byte(item->flags));
180                         g_variant_builder_close(&builder);
181
182                         iter = g_list_next(iter);
183                 }
184
185                 mpath_data = g_variant_builder_end(&builder);
186                 g_object_unref(mpath_data);
187         } else
188                 WMESH_LOGE("Failed to wmesh_request_get_mpath_info");
189
190         return ret;
191 }
192 #endif
193 static gboolean _on_mesh_monitor_cb(gpointer pdata)
194 {
195         int ret;
196         bool state;
197         wmesh_service *service = (wmesh_service *)pdata;
198         if (service) {
199                 wmesh_interface_s *info = service->interface_info;
200                 if (info) {
201                         /* Exceptionally, checking external interface processes here. */
202                         ret = wmesh_interface_check_external_exists(info->external_interface, &state);
203                         WMESH_LOGD("Status : %d %d %d", ret, info->can_be_gate, state);
204                         if (WMESHD_ERROR_NONE == ret) {
205                                 if (info->can_be_gate != state) {
206                                         wmesh_gdbus_enable_ethernet_interface(service, state);
207 #if 0
208                                         /* Detect external network state (i.e. Ethernet)
209                                                 and decide to make gate enabled */
210                                         if (state)
211                                                 wmesh_request_set_mesh_gate(info->bridge_interface,
212                                                                 info->mesh_interface, info->external_interface);
213                                         else
214                                                 wmesh_request_unset_mesh_gate(info->bridge_interface,
215                                                                 info->mesh_interface, info->external_interface);
216 #endif
217                                         WMESH_LOGD("External interface state has been changed : [%d]", state);
218                                         info->can_be_gate = state;
219                                 }
220                         } else {
221                                 /* In error case, we call enable etheret again for OdroidU3 */
222                                 wmesh_gdbus_enable_ethernet_interface(service, true);
223                         }
224 #if 0
225                         _get_mpath_info(service);
226 #endif
227                         _get_station_info(service);
228                 }
229         }
230
231         return G_SOURCE_CONTINUE;
232 }
233
234 int wmesh_start_monitor_service(void *pdata)
235 {
236         int ret = WMESHD_ERROR_NONE;
237         wmesh_service *service = (wmesh_service *)pdata;
238         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
239
240         if (service->monitor_timer)
241                 wmesh_stop_monitor_service(pdata);
242
243         service->monitor_timer = g_timeout_add_seconds(MESH_MONITORING_TIME, _on_mesh_monitor_cb, service);
244
245         WMESH_LOGD("Peer Monitoring Service Started");
246
247         return ret;
248 }
249
250 int wmesh_stop_monitor_service(void *pdata)
251 {
252         int ret = WMESHD_ERROR_NONE;
253         wmesh_service *service = (wmesh_service *)pdata;
254         wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
255
256         if (service->monitor_timer) {
257                 g_source_remove(service->monitor_timer);
258                 service->monitor_timer = 0;
259         }
260
261         WMESH_LOGD("Peer Monitoring Service Stopped");
262
263         /* After mesh interface is removed then ethernet is disabled when ethernet
264          * interface is bridged, so try to enable ethernet again */
265         WMESH_LOGD("Enable ethernet interface");
266         wmesh_gdbus_enable_ethernet_interface(service, true);
267         return ret;
268 }