Initian code sync up from private gerrit
[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 "mesh.h"
35 #include "mesh-log.h"
36 #include "mesh-util.h"
37 #include "mesh-service.h"
38 #include "mesh-interface.h"
39
40 #define IPV4_MAX_LENGTH   16
41 #define BUF_LENGTH        256
42
43 int mesh_interface_set(const char *interface, const char* ip_addr,
44                 mesh_set_interface_type_e type)
45 {
46         int sock = 0;
47         struct ifreq ifr;
48         int ret = 0;
49
50         char ip[IPV4_MAX_LENGTH] = {0,};
51         char buf[BUF_LENGTH] = {0,};
52
53         if (interface == NULL) {
54                 MESH_LOGE("Invalid interface name !");
55                 return MESHD_ERROR_INVALID_PARAMETER;
56         }
57
58         sock = socket(AF_INET, SOCK_STREAM, 0);
59         if (sock < 0) {
60                 MESH_LOGE("Cannot open network interface socket");
61                 return MESHD_ERROR_IO_ERROR;
62         }
63
64         MESH_LOGD("Initialize interface [%s]...", interface);
65         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
66
67         /* Set IP Address */
68         if (NULL != ip_addr) {
69                 struct sockaddr_in sai;
70                 memset(&sai, 0, sizeof(struct sockaddr_in));
71                 sai.sin_family = AF_INET;
72                 sai.sin_port = 0;
73                 snprintf(ip, IPV4_MAX_LENGTH, "%s", ip_addr);
74
75                 MESH_LOGD("Setting IP address: [%s]\n", ip);
76                 if (!inet_aton(ip, &sai.sin_addr)) {
77                         MESH_LOGE("Failed to convert ip address");
78                         close(sock);
79                         return MESHD_ERROR_OPERATION_FAILED;
80                 }
81
82                 memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
83
84                 ret = ioctl(sock, SIOCSIFADDR, &ifr);
85                 if (ret < 0) {
86                         (void) strerror_r(errno, buf, BUF_LENGTH);
87                         MESH_LOGE("Failed to set IP[%s] for interface[%s] : %s",
88                                 ip, ifr.ifr_name, buf);
89                 }
90         }
91
92         /* Get status flag */
93         if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
94                 (void) strerror_r(errno, buf, BUF_LENGTH);
95                 MESH_LOGE("Failed to get interface[%s] status : %s",
96                         ifr.ifr_name, buf);
97         }
98         snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
99
100         /* Set status flag */
101         if (MESH_INTERFACE_UP == type) {
102                 ifr.ifr_flags |= (IFF_UP);
103                 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
104                         (void) strerror_r(errno, buf, BUF_LENGTH);
105                         MESH_LOGE("Failed to change interface[%s] status UP : %s",
106                                 ifr.ifr_name, buf);
107                 }
108         } else if (MESH_INTERFACE_DOWN == type) {
109                 ifr.ifr_flags &= (~IFF_UP);
110                 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
111                         (void) strerror_r(errno, buf, BUF_LENGTH);
112                         MESH_LOGE("Failed to change interface[%s] status DOWN : %s",
113                                 ifr.ifr_name, buf);
114                 }
115         } else {
116                 MESH_LOGD("Do not change up/down status");
117         }
118
119         close(sock);
120         return MESHD_ERROR_NONE;
121 }
122
123 /* Returns interface name in sequence order which is exists */
124 static char* _get_interface_exists_in_seq(const char* prefix)
125 {
126         char *res = NULL;
127         char buf[32];
128         int ret;
129         int i = 0;
130         const int IF_INDEX_MAX = 9;
131
132         for (i = 0; i <= IF_INDEX_MAX; i++) {
133                 snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
134
135                 ret = access(buf, F_OK);
136                 if (ret >= 0) {
137                         /* This name is exists. use it */
138                         snprintf(buf, sizeof(buf), "%s%d", prefix, i);
139                         res = g_strdup(buf);
140                         MESH_LOGD("  use [%s]", res);
141                         break;
142                 }
143         }
144
145         return res;
146 }
147
148 /* Returns interface name in sequence order which is exists */
149 static char* _get_interface_not_exists_in_seq(const char* prefix)
150 {
151         char *res = NULL;
152         char buf[32];
153         int ret;
154         int i = 0;
155         const int IF_INDEX_MAX = 9;
156
157         for (i = 0; i <= IF_INDEX_MAX; i++) {
158                 snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
159
160                 ret = access(buf, F_OK);
161                 if (ret < 0) {
162                         /* This name is not exists. use it */
163                         snprintf(buf, sizeof(buf), "%s%d", prefix, i);
164                         res = g_strdup(buf);
165                         MESH_LOGD("  use [%s]", res);
166                         break;
167                 }
168         }
169
170         return res;
171 }
172
173 int mesh_interface_initialize(mesh_interface_s *info)
174 {
175         info->bridge_interface = _get_interface_not_exists_in_seq("br");
176         if (NULL == info->bridge_interface) {
177                 MESH_LOGE("Failed to get bridge interface !");
178                 return MESHD_ERROR_OPERATION_FAILED;
179         }
180
181         info->base_interface = _get_interface_exists_in_seq("wlan");
182         if (NULL == info->bridge_interface) {
183                 MESH_LOGE("Failed to get base interface !");
184                 return MESHD_ERROR_OPERATION_FAILED;
185         }
186
187         info->mesh_interface = _get_interface_not_exists_in_seq("mesh");
188         if (NULL == info->bridge_interface) {
189                 MESH_LOGE("Failed to get mesh interface !");
190                 return MESHD_ERROR_OPERATION_FAILED;
191         }
192
193         info->softap_interface = g_strdup("wlan1"); /* CHECK: interface changed */
194         info->external_interface = _get_interface_exists_in_seq("eth");
195         info->mesh_id = g_strdup("meshnet");
196         if (NULL == info->bridge_interface) {
197                 MESH_LOGE("Failed to get mesh id !");
198                 return MESHD_ERROR_OPERATION_FAILED;
199         }
200         info->mesh_channel = 7;
201
202         return MESHD_ERROR_NONE;
203 }