2 * Network Configuration Module
4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #ifdef USE_UDEV_MONITOR
22 #include <gudev/gudev.h>
23 #endif /* USE_UDEV_MONITOR */
30 #include <arpa/inet.h>
31 #include <sys/ioctl.h>
38 #include "mesh-util.h"
39 #include "mesh-service.h"
40 #include "mesh-interface.h"
42 #define IPV4_MAX_LENGTH 16
43 #define BUF_LENGTH 256
45 #define MESH_DEFAULT_BASE_INTERFACE "wlan0"
46 #define MESH_DEFAULT_MESH_INTERFACE "mesh0"
47 #define MESH_DEFAULT_BRIDGE_INTERFACE "br0"
48 #define MESH_DEFAULT_EXTERNAL_INTERFACE "eth0"
49 #define MESH_DEFAULT_SOFTAP_INTERFACE "wlan1"
52 ETHERNET_CABLE_DETACHED = 0,
53 ETHERNET_CABLE_ATTACHED
56 int mesh_interface_set(const char *interface, const char* ip_addr,
57 mesh_set_interface_type_e type)
63 char ip[IPV4_MAX_LENGTH] = {0,};
64 char buf[BUF_LENGTH] = {0,};
66 if (interface == NULL) {
67 MESH_LOGE("Invalid interface name !");
68 return MESHD_ERROR_INVALID_PARAMETER;
71 sock = socket(AF_INET, SOCK_STREAM, 0);
73 MESH_LOGE("Cannot open network interface socket");
74 return MESHD_ERROR_IO_ERROR;
77 MESH_LOGD("Initialize interface [%s]...", interface);
78 snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
81 if (NULL != ip_addr) {
82 struct sockaddr_in sai;
83 memset(&sai, 0, sizeof(struct sockaddr_in));
84 sai.sin_family = AF_INET;
86 snprintf(ip, IPV4_MAX_LENGTH, "%s", ip_addr);
88 MESH_LOGD("Setting IP address: [%s]\n", ip);
89 if (!inet_aton(ip, &sai.sin_addr)) {
90 MESH_LOGE("Failed to convert ip address");
92 return MESHD_ERROR_OPERATION_FAILED;
95 memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
97 ret = ioctl(sock, SIOCSIFADDR, &ifr);
99 (void) strerror_r(errno, buf, BUF_LENGTH);
100 MESH_LOGE("Failed to set IP[%s] for interface[%s] : %s",
101 ip, ifr.ifr_name, buf);
105 /* Get status flag */
106 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
107 (void) strerror_r(errno, buf, BUF_LENGTH);
108 MESH_LOGE("Failed to get interface[%s] status : %s",
111 snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
113 /* Set status flag */
114 if (MESH_INTERFACE_UP == type) {
115 ifr.ifr_flags |= (IFF_UP);
116 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
117 (void) strerror_r(errno, buf, BUF_LENGTH);
118 MESH_LOGE("Failed to change interface[%s] status UP : %s",
121 } else if (MESH_INTERFACE_DOWN == type) {
122 ifr.ifr_flags &= (~IFF_UP);
123 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
124 (void) strerror_r(errno, buf, BUF_LENGTH);
125 MESH_LOGE("Failed to change interface[%s] status DOWN : %s",
129 MESH_LOGD("Do not change up/down status");
133 return MESHD_ERROR_NONE;
137 /* Returns interface name in sequence order which is exists */
138 static char* _get_interface_exists_in_seq(const char* prefix)
144 const int IF_INDEX_MAX = 9;
146 for (i = 0; i <= IF_INDEX_MAX; i++) {
147 snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
149 ret = access(buf, F_OK);
151 /* This name is exists. use it */
152 snprintf(buf, sizeof(buf), "%s%d", prefix, i);
154 MESH_LOGD(" use [%s]", res);
162 /* Returns interface name in sequence order which is exists */
163 static char* _get_interface_not_exists_in_seq(const char* prefix)
169 const int IF_INDEX_MAX = 9;
171 for (i = 0; i <= IF_INDEX_MAX; i++) {
172 snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
174 ret = access(buf, F_OK);
176 /* This name is not exists. use it */
177 snprintf(buf, sizeof(buf), "%s%d", prefix, i);
179 MESH_LOGD(" use [%s]", res);
188 static bool _check_interface_exists(const char* if_name)
193 const int IF_INDEX_MAX = 9;
195 for (i = 0; i <= IF_INDEX_MAX; i++) {
196 snprintf(buf, sizeof(buf), "/sys/class/net/%s", if_name);
198 ret = access(buf, F_OK);
200 /* This name is exists. */
208 /* Check if interface is bridged */
209 static bool _check_bridge_interface_exists(const char* bridge, const char* if_name)
214 const int IF_INDEX_MAX = 9;
216 for (i = 0; i <= IF_INDEX_MAX; i++) {
217 snprintf(buf, sizeof(buf), "/sys/class/net/%s/brif/%s", bridge, if_name);
219 ret = access(buf, F_OK);
221 /* This name is exists. */
229 char* mesh_interface_get_address(const char* if_name)
232 char buf[32] = { 0, };
235 snprintf(buf, sizeof(buf), "/sys/class/net/%s/address", if_name);
236 pf = fopen(buf, "r");
239 MESH_LOGD("Interface[%s] address[%s]", if_name, buf);
242 result = g_strdup(buf);
250 #ifdef USE_UDEV_MONITOR
251 static void __on_uevent(GUdevClient *client, gchar *action, GUdevDevice *device, gpointer user_data)
257 MESH_LOGD("KSR : action:[%s]", action);
260 static void _interface_status_monitor_init(mesh_interface_s *info)
262 const gchar *subsystem[] = {"net", NULL};
264 info->udev_client = g_udev_client_new(subsystem);
265 g_signal_connect(info->udev_client, "uevent", G_CALLBACK(__on_uevent), info);
267 #endif /* USE_UDEV_MONITOR */
269 int mesh_interface_initialize(mesh_interface_s *info)
272 MESH_LOGE("Invalid parameter");
273 return MESHD_ERROR_INVALID_PARAMETER;
276 info->bridge_interface = g_strdup(MESH_DEFAULT_BRIDGE_INTERFACE);
277 if (NULL == info->bridge_interface) {
278 MESH_LOGE("Failed to get bridge interface !");
279 return MESHD_ERROR_OPERATION_FAILED;
282 info->base_interface = g_strdup(MESH_DEFAULT_BASE_INTERFACE);
283 if (NULL == info->bridge_interface) {
284 MESH_LOGE("Failed to get base interface !");
285 return MESHD_ERROR_OPERATION_FAILED;
288 info->mesh_interface = g_strdup(MESH_DEFAULT_MESH_INTERFACE);
289 if (NULL == info->bridge_interface) {
290 MESH_LOGE("Failed to get mesh interface !");
291 return MESHD_ERROR_OPERATION_FAILED;
294 info->softap_interface = g_strdup(MESH_DEFAULT_SOFTAP_INTERFACE);
295 info->external_interface = g_strdup(MESH_DEFAULT_EXTERNAL_INTERFACE);
297 MESH_LOGD("Interface configuration for mesh network :");
298 MESH_LOGD(" Base : [%s]", info->base_interface);
299 MESH_LOGD(" Mesh : [%s]", info->mesh_interface);
300 MESH_LOGD(" Bridge : [%s]", info->bridge_interface);
301 MESH_LOGD(" SoftAP : [%s]", info->softap_interface);
302 MESH_LOGD(" External: [%s]", info->external_interface);
304 #ifdef USE_UDEV_MONITOR
305 _interface_status_monitor_init(info);
306 #endif /* USE_UDEV_MONITOR */
307 return MESHD_ERROR_NONE;
310 static int _check_ethernet_cable_plugin_status(const char* interface,
311 cable_state_e *status)
316 char error_buf[256] = {0, };
317 char file_path[256] = {0, };
319 snprintf(file_path, 256, "/sys/class/net/%s/carrier", interface);
321 if (0 == access(file_path, F_OK)) {
322 fd = fopen(file_path, "r");
324 MESH_LOGE("Error! Could not open /sys/class/net/%s/carrier file",
326 return MESHD_ERROR_IO_ERROR;
329 MESH_LOGE("Error! Could not access /sys/class/net/%s/carrier file",
331 return MESHD_ERROR_IO_ERROR;
335 rv = fscanf(fd, "%d", &ret);
337 strerror_r(errno, error_buf, 256);
338 MESH_LOGE("Error! Failed to read from file, rv:[%d], error:[%s]",
341 return MESHD_ERROR_IO_ERROR;
345 MESH_LOGD("/sys/class/net/%s/carrier : [%d]", interface, ret);
346 *status = ETHERNET_CABLE_ATTACHED;
347 } else if (ret == 0) {
348 MESH_LOGD("/sys/class/net/%s/carrier : [%d]", interface, ret);
349 *status = ETHERNET_CABLE_DETACHED;
353 return MESHD_ERROR_NONE;
356 int mesh_interface_check_external_exists(const char* external_interface, bool *state)
358 /* TODO: Current logic checks only ethernet interface.
359 This logic should consider wireless interface if can */
360 int ret = MESHD_ERROR_NONE;
361 cable_state_e cable_state = ETHERNET_CABLE_DETACHED;
363 if (NULL == external_interface || NULL == state)
364 return MESHD_ERROR_INVALID_PARAMETER;
366 bool ex = _check_interface_exists(external_interface);
368 MESH_LOGE("External interface[%s] was not found.", external_interface);
369 return MESHD_ERROR_INVALID_PARAMETER;
372 /* If external interface seems Ethernet, check cable state */
373 if (g_str_has_prefix(external_interface, "eth")) {
374 ret = _check_ethernet_cable_plugin_status(external_interface, &cable_state);
375 if (MESHD_ERROR_NONE != ret) {
376 MESH_LOGE("Failed to get Ethernet cable state");
377 return MESHD_ERROR_OPERATION_FAILED;
382 if (ETHERNET_CABLE_ATTACHED == cable_state)
385 return MESHD_ERROR_NONE;
388 int mesh_interface_check(const char* interface)
392 if (NULL == interface || strlen(interface) == 0)
393 return MESHD_ERROR_INVALID_PARAMETER;
395 ex = _check_interface_exists(interface);
397 MESH_LOGE("Interface[%s] was not found.", interface);
398 return MESHD_ERROR_NO_DATA;
401 return MESHD_ERROR_NONE;
404 int mesh_interface_check_bridge_interface_exists(const char* bridge, const char* interface)
408 if (NULL == bridge || NULL == interface ||
409 strlen(bridge) == 0 || strlen(interface) == 0)
410 return MESHD_ERROR_INVALID_PARAMETER;
412 ex = _check_bridge_interface_exists(bridge, interface);
414 MESH_LOGE("Interface[%s] was not found.", interface);
415 return MESHD_ERROR_NO_DATA;
418 return MESHD_ERROR_NONE;