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.
28 #include <arpa/inet.h>
29 #include <sys/ioctl.h>
36 #include "mesh-util.h"
37 #include "mesh-service.h"
38 #include "mesh-interface.h"
40 #define IPV4_MAX_LENGTH 16
41 #define BUF_LENGTH 256
44 ETHERNET_CABLE_DETACHED = 0,
45 ETHERNET_CABLE_ATTACHED
48 int mesh_interface_set(const char *interface, const char* ip_addr,
49 mesh_set_interface_type_e type)
55 char ip[IPV4_MAX_LENGTH] = {0,};
56 char buf[BUF_LENGTH] = {0,};
58 if (interface == NULL) {
59 MESH_LOGE("Invalid interface name !");
60 return MESHD_ERROR_INVALID_PARAMETER;
63 sock = socket(AF_INET, SOCK_STREAM, 0);
65 MESH_LOGE("Cannot open network interface socket");
66 return MESHD_ERROR_IO_ERROR;
69 MESH_LOGD("Initialize interface [%s]...", interface);
70 snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
73 if (NULL != ip_addr) {
74 struct sockaddr_in sai;
75 memset(&sai, 0, sizeof(struct sockaddr_in));
76 sai.sin_family = AF_INET;
78 snprintf(ip, IPV4_MAX_LENGTH, "%s", ip_addr);
80 MESH_LOGD("Setting IP address: [%s]\n", ip);
81 if (!inet_aton(ip, &sai.sin_addr)) {
82 MESH_LOGE("Failed to convert ip address");
84 return MESHD_ERROR_OPERATION_FAILED;
87 memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
89 ret = ioctl(sock, SIOCSIFADDR, &ifr);
91 (void) strerror_r(errno, buf, BUF_LENGTH);
92 MESH_LOGE("Failed to set IP[%s] for interface[%s] : %s",
93 ip, ifr.ifr_name, buf);
98 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
99 (void) strerror_r(errno, buf, BUF_LENGTH);
100 MESH_LOGE("Failed to get interface[%s] status : %s",
103 snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
105 /* Set status flag */
106 if (MESH_INTERFACE_UP == type) {
107 ifr.ifr_flags |= (IFF_UP);
108 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
109 (void) strerror_r(errno, buf, BUF_LENGTH);
110 MESH_LOGE("Failed to change interface[%s] status UP : %s",
113 } else if (MESH_INTERFACE_DOWN == type) {
114 ifr.ifr_flags &= (~IFF_UP);
115 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
116 (void) strerror_r(errno, buf, BUF_LENGTH);
117 MESH_LOGE("Failed to change interface[%s] status DOWN : %s",
121 MESH_LOGD("Do not change up/down status");
125 return MESHD_ERROR_NONE;
128 /* Returns interface name in sequence order which is exists */
129 static char* _get_interface_exists_in_seq(const char* prefix)
135 const int IF_INDEX_MAX = 9;
137 for (i = 0; i <= IF_INDEX_MAX; i++) {
138 snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
140 ret = access(buf, F_OK);
142 /* This name is exists. use it */
143 snprintf(buf, sizeof(buf), "%s%d", prefix, i);
145 MESH_LOGD(" use [%s]", res);
153 /* Returns interface name in sequence order which is exists */
154 static char* _get_interface_not_exists_in_seq(const char* prefix)
160 const int IF_INDEX_MAX = 9;
162 for (i = 0; i <= IF_INDEX_MAX; i++) {
163 snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
165 ret = access(buf, F_OK);
167 /* This name is not exists. use it */
168 snprintf(buf, sizeof(buf), "%s%d", prefix, i);
170 MESH_LOGD(" use [%s]", res);
178 /* Returns interface name in sequence order which is exists */
179 static bool _check_interface_exists(const char* if_name)
184 const int IF_INDEX_MAX = 9;
186 for (i = 0; i <= IF_INDEX_MAX; i++) {
187 snprintf(buf, sizeof(buf), "/sys/class/net/%s", if_name);
189 ret = access(buf, F_OK);
191 /* This name is exists. */
199 char* mesh_interface_get_address(const char* if_name)
206 snprintf(buf, sizeof(buf), "/sys/class/net/%s/address", if_name);
207 pf = fopen(buf, "r");
209 cnt = fscanf(pf, "%s", buf);
210 MESH_LOGD("Interface[%s] address[%s] %d", if_name, buf, cnt);
211 result = g_strdup(buf);
219 int mesh_interface_initialize(mesh_interface_s *info)
221 info->bridge_interface = _get_interface_not_exists_in_seq("br");
222 if (NULL == info->bridge_interface) {
223 MESH_LOGE("Failed to get bridge interface !");
224 return MESHD_ERROR_OPERATION_FAILED;
227 info->base_interface = _get_interface_exists_in_seq("wlan");
228 if (NULL == info->bridge_interface) {
229 MESH_LOGE("Failed to get base interface !");
230 return MESHD_ERROR_OPERATION_FAILED;
233 info->mesh_interface = _get_interface_not_exists_in_seq("mesh");
234 if (NULL == info->bridge_interface) {
235 MESH_LOGE("Failed to get mesh interface !");
236 return MESHD_ERROR_OPERATION_FAILED;
239 info->softap_interface = g_strdup("wlan1"); /* CHECK: interface changed */
240 info->external_interface = _get_interface_exists_in_seq("eth");
241 info->mesh_id = g_strdup("meshnet");
242 if (NULL == info->bridge_interface) {
243 MESH_LOGE("Failed to get mesh id !");
244 return MESHD_ERROR_OPERATION_FAILED;
246 info->mesh_channel = 7;
248 return MESHD_ERROR_NONE;
251 static int _check_ethernet_cable_plugin_status(const char* interface,
252 cable_state_e *status)
257 char error_buf[256] = {0, };
258 char file_path[256] = {0, };
260 snprintf(file_path, 256, "/sys/class/net/%s/carrier", interface);
262 if (0 == access(file_path, F_OK)) {
263 fd = fopen(file_path, "r");
265 MESH_LOGE("Error! Could not open /sys/class/net/%s/carrier file",
267 return MESHD_ERROR_IO_ERROR;
270 MESH_LOGE("Error! Could not access /sys/class/net/%s/carrier file",
272 return MESHD_ERROR_IO_ERROR;
276 rv = fscanf(fd, "%d", &ret);
278 strerror_r(errno, error_buf, 256);
279 MESH_LOGE("Error! Failed to read from file, rv:[%d], error:[%s]",
282 return MESHD_ERROR_IO_ERROR;
286 MESH_LOGD("/sys/class/net/%s/carrier : [%d]", interface, ret);
287 *status = ETHERNET_CABLE_ATTACHED;
288 } else if (ret == 0) {
289 MESH_LOGD("/sys/class/net/%s/carrier : [%d]", interface, ret);
290 *status = ETHERNET_CABLE_DETACHED;
294 return MESHD_ERROR_NONE;
297 int mesh_interface_check_external_exists(const char* external_interface, bool *state)
299 /* TODO: Current logic checks only ethernet interface.
300 This logic should consider wireless interface if can */
301 int ret = MESHD_ERROR_NONE;
302 cable_state_e cable_state = ETHERNET_CABLE_DETACHED;
304 if (NULL == external_interface || NULL == state) {
305 return MESHD_ERROR_INVALID_PARAMETER;
308 bool ex = _check_interface_exists(external_interface);
310 MESH_LOGE("External interface[%s] was not found.", external_interface);
311 return MESHD_ERROR_INVALID_PARAMETER;
314 /* If external interface seems Ethernet, check cable state */
315 if (g_str_has_prefix(external_interface, "eth")) {
316 ret = _check_ethernet_cable_plugin_status(external_interface, &cable_state);
317 if (MESHD_ERROR_NONE != ret) {
318 MESH_LOGE("Failed to get Ethernet cable state");
319 return MESHD_ERROR_OPERATION_FAILED;
324 if (ETHERNET_CABLE_ATTACHED == cable_state) {
328 return MESHD_ERROR_NONE;