Fix memory leak in wmesh_gdbus_create_network()
[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
187         struct ifreq ifr;
188         int if_index = if_nametoindex(interface);
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         br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
206         if (br_fd < 0) {
207                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
208                 WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
209
210                 return WMESHD_ERROR_IO_ERROR;
211         }
212
213         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", bridge_name);
214 #ifdef SIOCBRDELIF
215         ifr.ifr_ifindex = if_index;
216         val = ioctl(br_fd, SIOCBRDELIF, &ifr);
217 #else
218         ifr.ifr_data = (char *)args;
219         val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
220 #endif
221         if (val < 0) {
222                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
223                 WMESH_LOGD("Failed to delete interface [%s] from bridge [%s(%d)]",
224                                 interface, str_error, errno);
225
226                 ret = WMESHD_ERROR_IO_ERROR;
227         }
228
229         close(br_fd);
230
231         return ret;
232 }
233
234 int wmesh_bridge_set_stp(const char* bridge_name, bool state)
235 {
236         int ret = WMESHD_ERROR_NONE;
237         int val = 0;
238         int br_fd = 0;
239         char str_error[ERROR_MESSAGE_LENGTH];
240         int stp_state = (state) ? 1 : 0;
241         struct ifreq ifr;
242         unsigned long arg[4] = {
243                 BRCTL_SET_BRIDGE_STP_STATE,
244                 stp_state, 0, 0 };
245
246         if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
247                 WMESH_LOGE("Invalid parameter [%p]", bridge_name);
248                 return WMESHD_ERROR_INVALID_PARAMETER;
249         }
250
251         br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
252         if (br_fd < 0) {
253                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
254                 WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
255
256                 return WMESHD_ERROR_IO_ERROR;
257         }
258
259         strncpy(ifr.ifr_name, bridge_name, IFNAMSIZ);
260         ifr.ifr_data = (char *)arg;
261
262         val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
263         if (val < 0) {
264                 strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
265                 WMESH_LOGE("Failed to set bridge[%s] stp state", bridge_name);
266                 WMESH_LOGE("  %s(%d)", str_error, errno);
267
268                 ret = WMESHD_ERROR_IO_ERROR;
269         }
270
271         close(br_fd);
272
273         return ret;
274 }