Fix resource leak (Prevent)
[platform/core/connectivity/wifi-mesh-manager.git] / src / wmesh-bridge.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 <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
29 #include <netinet/in.h>
30 #include <linux/if.h>
31 #include <linux/if_bridge.h>
32 #include <linux/sockios.h>
33
34 extern unsigned int if_nametoindex(const char *__ifname);
35
36 #include "wmesh.h"
37 #include "wmesh-log.h"
38 #include "wmesh-util.h"
39 #include "wmesh-service.h"
40 #include "wmesh-bridge.h"
41
42 #define ERROR_MESSAGE_LENGTH    256
43
44 int wmesh_bridge_create(const char* bridge_name)
45 {
46         int ret = WMESHD_ERROR_NONE;
47         int val = 0;
48         int br_fd = 0;
49         char bridge[IFNAMSIZ];
50         char str_error[ERROR_MESSAGE_LENGTH];
51 #if !defined(SIOCBRADDBR)
52         unsigned long arg[3] = { BRCTL_ADD_BRIDGE, (unsigned long)bridge };
53 #endif
54
55         if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
56                 WMESH_LOGE("Invalid parameter [%p]", bridge_name);
57                 return WMESHD_ERROR_INVALID_PARAMETER;
58         }
59
60         br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
61         if (br_fd < 0) {
62                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
63                 WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
64
65                 return WMESHD_ERROR_IO_ERROR;
66         }
67
68         snprintf(bridge, IFNAMSIZ, "%s", bridge_name);
69 #ifdef SIOCBRADDBR
70         val = ioctl(br_fd, SIOCBRADDBR, bridge_name);
71 #else
72         val = ioctl(br_fd, SIOCSIFBR, arg);
73 #endif
74         if (val < 0) {
75                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
76                 WMESH_LOGD("Failed to create bridge [%s(%d)]", str_error, errno);
77
78                 ret = WMESHD_ERROR_IO_ERROR;
79         }
80
81         close(br_fd);
82
83         return ret;
84 }
85
86 int wmesh_bridge_remove(const char* bridge_name)
87 {
88         int ret = WMESHD_ERROR_NONE;
89         int val = 0;
90         int br_fd = 0;
91         char bridge[IFNAMSIZ];
92         char str_error[ERROR_MESSAGE_LENGTH];
93 #if !defined(SIOCBRDELBR)
94         unsigned long arg[3] = { BRCTL_DEL_BRIDGE, (unsigned long)bridge };
95 #endif
96
97         if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
98                 WMESH_LOGE("Invalid parameter [%p]", bridge_name);
99                 return WMESHD_ERROR_INVALID_PARAMETER;
100         }
101
102         br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
103         if (br_fd < 0) {
104                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
105                 WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
106
107                 return WMESHD_ERROR_IO_ERROR;
108         }
109
110         snprintf(bridge, IFNAMSIZ, "%s", bridge_name);
111 #ifdef SIOCBRDELBR
112         val = ioctl(br_fd, SIOCBRDELBR, bridge_name);
113 #else
114         val = ioctl(br_fd, SIOCSIFBR, arg);
115 #endif
116         if (val < 0) {
117                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
118                 WMESH_LOGD("Failed to remove bridge [%s(%d)]", str_error, errno);
119
120                 ret = WMESHD_ERROR_IO_ERROR;
121         }
122
123         close(br_fd);
124
125         return ret;
126 }
127
128 int wmesh_bridge_add_interface(const char* bridge_name, const char* interface)
129 {
130         int ret = WMESHD_ERROR_NONE;
131         int val = 0;
132         int br_fd = 0;
133
134         struct ifreq ifr;
135         int if_index = if_nametoindex(interface);
136
137         char str_error[ERROR_MESSAGE_LENGTH];
138 #if !defined(SIOCBRADDIF)
139         unsigned long args[4] = { BRCTL_ADD_IF, if_index, 0, 0 };
140 #endif
141
142         if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
143                 WMESH_LOGE("Invalid parameter [%p]", bridge_name);
144                 return WMESHD_ERROR_INVALID_PARAMETER;
145         }
146
147         if (NULL == interface || strlen(interface) > IFNAMSIZ) {
148                 WMESH_LOGE("Invalid parameter [%p]", interface);
149                 return WMESHD_ERROR_INVALID_PARAMETER;
150         }
151
152         br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
153         if (br_fd < 0) {
154                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
155                 WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
156
157                 return WMESHD_ERROR_IO_ERROR;
158         }
159
160         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", bridge_name);
161 #ifdef SIOCBRADDIF
162         ifr.ifr_ifindex = if_index;
163         val = ioctl(br_fd, SIOCBRADDIF, &ifr);
164 #else
165         ifr.ifr_data = (char *)args;
166         val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
167 #endif
168         if (val < 0) {
169                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
170                 WMESH_LOGD("Failed to add interface [%s] into bridge [%s(%d)]",
171                                 interface, str_error, errno);
172
173                 ret = WMESHD_ERROR_IO_ERROR;
174         }
175
176         close(br_fd);
177
178         return ret;
179 }
180
181 int wmesh_bridge_del_interface(const char* bridge_name, const char* interface)
182 {
183         int ret = WMESHD_ERROR_NONE;
184         int val = 0;
185         int br_fd = 0;
186         int if_index;
187
188         struct ifreq ifr;
189
190         char str_error[ERROR_MESSAGE_LENGTH];
191 #if !defined(SIOCBRDELIF)
192         unsigned long args[4] = { BRCTL_DEL_IF, if_index, 0, 0 };
193 #endif
194
195         if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
196                 WMESH_LOGE("Invalid parameter [%p]", bridge_name);
197                 return WMESHD_ERROR_INVALID_PARAMETER;
198         }
199
200         if (NULL == interface || strlen(interface) > IFNAMSIZ) {
201                 WMESH_LOGE("Invalid parameter [%p]", interface);
202                 return WMESHD_ERROR_INVALID_PARAMETER;
203         }
204
205         if_index = if_nametoindex(interface);
206
207         br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
208         if (br_fd < 0) {
209                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
210                 WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
211
212                 return WMESHD_ERROR_IO_ERROR;
213         }
214
215         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", bridge_name);
216 #ifdef SIOCBRDELIF
217         ifr.ifr_ifindex = if_index;
218         val = ioctl(br_fd, SIOCBRDELIF, &ifr);
219 #else
220         ifr.ifr_data = (char *)args;
221         val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
222 #endif
223         if (val < 0) {
224                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
225                 WMESH_LOGD("Failed to delete interface [%s] from bridge [%s(%d)]",
226                                 interface, str_error, errno);
227
228                 ret = WMESHD_ERROR_IO_ERROR;
229         }
230
231         close(br_fd);
232
233         return ret;
234 }
235
236 int wmesh_bridge_set_stp(const char* bridge_name, bool state)
237 {
238         int ret = WMESHD_ERROR_NONE;
239         int val = 0;
240         int br_fd = 0;
241         char str_error[ERROR_MESSAGE_LENGTH];
242         int stp_state = (state) ? 1 : 0;
243         struct ifreq ifr;
244         unsigned long arg[4] = {
245                 BRCTL_SET_BRIDGE_STP_STATE,
246                 stp_state, 0, 0 };
247
248         if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ - 1) {
249                 WMESH_LOGE("Invalid parameter [%p]", bridge_name);
250                 return WMESHD_ERROR_INVALID_PARAMETER;
251         }
252
253         br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
254         if (br_fd < 0) {
255                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
256                 WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
257
258                 return WMESHD_ERROR_IO_ERROR;
259         }
260
261         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", bridge_name);
262         ifr.ifr_data = (char *)arg;
263
264         val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
265         if (val < 0) {
266                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
267                 WMESH_LOGE("Failed to set bridge[%s] stp state", bridge_name);
268                 WMESH_LOGE("  %s(%d)", str_error, errno);
269
270                 ret = WMESHD_ERROR_IO_ERROR;
271         }
272
273         close(br_fd);
274
275         return ret;
276 }