Implement methods
[platform/core/connectivity/wifi-mesh-manager.git] / src / mesh-interface.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 #include <gio/gio.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include <net/if.h>
28 #include <arpa/inet.h>
29 #include <sys/ioctl.h>
30 #include <sys/wait.h>
31
32 #include <errno.h>
33
34 #include <net_connection.h>
35
36 #include "mesh.h"
37 #include "mesh-log.h"
38 #include "mesh-util.h"
39 #include "mesh-service.h"
40 #include "mesh-interface.h"
41
42 #define IPV4_MAX_LENGTH   16
43 #define BUF_LENGTH        256
44
45 int mesh_interface_set(const char *interface, const char* ip_addr,
46                 mesh_set_interface_type_e type)
47 {
48         int sock = 0;
49         struct ifreq ifr;
50         int ret = 0;
51
52         char ip[IPV4_MAX_LENGTH] = {0,};
53         char buf[BUF_LENGTH] = {0,};
54
55         if (interface == NULL) {
56                 MESH_LOGE("Invalid interface name !");
57                 return MESHD_ERROR_INVALID_PARAMETER;
58         }
59
60         sock = socket(AF_INET, SOCK_STREAM, 0);
61         if (sock < 0) {
62                 MESH_LOGE("Cannot open network interface socket");
63                 return MESHD_ERROR_IO_ERROR;
64         }
65
66         MESH_LOGD("Initialize interface [%s]...", interface);
67         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
68
69         /* Set IP Address */
70         if (NULL != ip_addr) {
71                 struct sockaddr_in sai;
72                 memset(&sai, 0, sizeof(struct sockaddr_in));
73                 sai.sin_family = AF_INET;
74                 sai.sin_port = 0;
75                 snprintf(ip, IPV4_MAX_LENGTH, "%s", ip_addr);
76
77                 MESH_LOGD("Setting IP address: [%s]\n", ip);
78                 if (!inet_aton(ip, &sai.sin_addr)) {
79                         MESH_LOGE("Failed to convert ip address");
80                         close(sock);
81                         return MESHD_ERROR_OPERATION_FAILED;
82                 }
83
84                 memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
85
86                 ret = ioctl(sock, SIOCSIFADDR, &ifr);
87                 if (ret < 0) {
88                         (void) strerror_r(errno, buf, BUF_LENGTH);
89                         MESH_LOGE("Failed to set IP[%s] for interface[%s] : %s",
90                                 ip, ifr.ifr_name, buf);
91                 }
92         }
93
94         /* Get status flag */
95         if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
96                 (void) strerror_r(errno, buf, BUF_LENGTH);
97                 MESH_LOGE("Failed to get interface[%s] status : %s",
98                         ifr.ifr_name, buf);
99         }
100         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
101
102         /* Set status flag */
103         if (MESH_INTERFACE_UP == type) {
104                 ifr.ifr_flags |= (IFF_UP);
105                 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
106                         (void) strerror_r(errno, buf, BUF_LENGTH);
107                         MESH_LOGE("Failed to change interface[%s] status UP : %s",
108                                 ifr.ifr_name, buf);
109                 }
110         } else if (MESH_INTERFACE_DOWN == type) {
111                 ifr.ifr_flags &= (~IFF_UP);
112                 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
113                         (void) strerror_r(errno, buf, BUF_LENGTH);
114                         MESH_LOGE("Failed to change interface[%s] status DOWN : %s",
115                                 ifr.ifr_name, buf);
116                 }
117         } else {
118                 MESH_LOGD("Do not change up/down status");
119         }
120
121         close(sock);
122         return MESHD_ERROR_NONE;
123 }
124
125 /* Returns interface name in sequence order which is exists */
126 static char* _get_interface_exists_in_seq(const char* prefix)
127 {
128         char *res = NULL;
129         char buf[32];
130         int ret;
131         int i = 0;
132         const int IF_INDEX_MAX = 9;
133
134         for (i = 0; i <= IF_INDEX_MAX; i++) {
135                 snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
136
137                 ret = access(buf, F_OK);
138                 if (ret >= 0) {
139                         /* This name is exists. use it */
140                         snprintf(buf, sizeof(buf), "%s%d", prefix, i);
141                         res = g_strdup(buf);
142                         MESH_LOGD("  use [%s]", res);
143                         break;
144                 }
145         }
146
147         return res;
148 }
149
150 /* Returns interface name in sequence order which is exists */
151 static char* _get_interface_not_exists_in_seq(const char* prefix)
152 {
153         char *res = NULL;
154         char buf[32];
155         int ret;
156         int i = 0;
157         const int IF_INDEX_MAX = 9;
158
159         for (i = 0; i <= IF_INDEX_MAX; i++) {
160                 snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
161
162                 ret = access(buf, F_OK);
163                 if (ret < 0) {
164                         /* This name is not exists. use it */
165                         snprintf(buf, sizeof(buf), "%s%d", prefix, i);
166                         res = g_strdup(buf);
167                         MESH_LOGD("  use [%s]", res);
168                         break;
169                 }
170         }
171
172         return res;
173 }
174
175 /* Returns interface name in sequence order which is exists */
176 static bool _check_interface_exists(const char* if_name)
177 {
178         int ret;
179         char buf[32];
180         int i = 0;
181         const int IF_INDEX_MAX = 9;
182
183         for (i = 0; i <= IF_INDEX_MAX; i++) {
184                 snprintf(buf, sizeof(buf), "/sys/class/net/%s", if_name);
185
186                 ret = access(buf, F_OK);
187                 if (ret >= 0) {
188                         /* This name is exists. */
189                         return true;
190                 }
191         }
192
193         return false;
194 }
195
196 int mesh_interface_initialize(mesh_interface_s *info)
197 {
198         info->bridge_interface = _get_interface_not_exists_in_seq("br");
199         if (NULL == info->bridge_interface) {
200                 MESH_LOGE("Failed to get bridge interface !");
201                 return MESHD_ERROR_OPERATION_FAILED;
202         }
203
204         info->base_interface = _get_interface_exists_in_seq("wlan");
205         if (NULL == info->bridge_interface) {
206                 MESH_LOGE("Failed to get base interface !");
207                 return MESHD_ERROR_OPERATION_FAILED;
208         }
209
210         info->mesh_interface = _get_interface_not_exists_in_seq("mesh");
211         if (NULL == info->bridge_interface) {
212                 MESH_LOGE("Failed to get mesh interface !");
213                 return MESHD_ERROR_OPERATION_FAILED;
214         }
215
216         info->softap_interface = g_strdup("wlan1"); /* CHECK: interface changed */
217         info->external_interface = _get_interface_exists_in_seq("eth");
218         info->mesh_id = g_strdup("meshnet");
219         if (NULL == info->bridge_interface) {
220                 MESH_LOGE("Failed to get mesh id !");
221                 return MESHD_ERROR_OPERATION_FAILED;
222         }
223         info->mesh_channel = 7;
224
225         return MESHD_ERROR_NONE;
226 }
227
228 int mesh_interface_check_external_exists(const char* external_interface, bool *state)
229 {
230         /* TODO: Current logic checks only ethernet interface.
231                         This logic should consider wireless interface if can */
232         int ret = MESHD_ERROR_NONE;
233         connection_h handle;
234         connection_ethernet_cable_state_e cable_state =
235                         CONNECTION_ETHERNET_CABLE_DETACHED;
236
237         if (NULL == external_interface || NULL == state) {
238                 return MESHD_ERROR_INVALID_PARAMETER;
239         }
240
241         bool ex = _check_interface_exists(external_interface);
242         if (FALSE == ex) {
243                 MESH_LOGE("External interface[%s] was not found.", external_interface);
244                 return MESHD_ERROR_INVALID_PARAMETER;
245         }
246
247         ret = connection_create(&handle);
248         if (CONNECTION_ERROR_NONE != ret) {
249                 MESH_LOGE("Failed to get connection handle");
250                 return MESHD_ERROR_OPERATION_FAILED;
251         }
252
253         ret = connection_get_ethernet_cable_state(handle, &cable_state);
254         if (CONNECTION_ERROR_NONE != ret) {
255                 MESH_LOGE("Failed to get ethernet cable state");
256                 return MESHD_ERROR_OPERATION_FAILED;
257         }
258
259         *state = FALSE;
260         if (CONNECTION_ETHERNET_CABLE_ATTACHED == cable_state) {
261                 *state = TRUE;
262         }
263
264         return MESHD_ERROR_NONE;
265 }