1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "vpn_manager.h"
17
18 #include <arpa/inet.h>
19 #include <fcntl.h>
20 #include <linux/if.h>
21 #include <linux/ipv6.h>
22 #include <linux/if_tun.h>
23 #include <netinet/in.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <sys/un.h>
28 #include <thread>
29 #include <unistd.h>
30
31 #include "init_socket.h"
32 #include "net_manager_constants.h"
33 #include "netnative_log_wrapper.h"
34 #include "securec.h"
35 #include "netmanager_base_common_utils.h"
36
37 namespace OHOS {
38 namespace NetManagerStandard {
39
40 namespace {
41 constexpr const char *TUN_CARD_NAME = "vpn-tun";
42 constexpr const char *TUN_DEVICE_PATH = "/dev/tun";
43 constexpr int32_t NET_MASK_MAX_LENGTH = 32;
44 constexpr int32_t MAX_UNIX_SOCKET_CLIENT = 5;
45 } // namespace
46
CreateVpnInterface()47 int32_t VpnManager::CreateVpnInterface()
48 {
49 if (tunFd_ != 0) {
50 StartVpnInterfaceFdListen();
51 return NETMANAGER_SUCCESS;
52 }
53
54 ifreq ifr = {};
55 if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
56 return NETMANAGER_ERROR;
57 }
58
59 int32_t tunfd = open(TUN_DEVICE_PATH, O_RDWR | O_NONBLOCK);
60 if (tunfd <= 0) {
61 NETNATIVE_LOGE("open virtual device failed: %{public}d", errno);
62 return NETMANAGER_ERROR;
63 }
64
65 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
66 if (ioctl(tunfd, TUNSETIFF, &ifr) < 0) {
67 close(tunfd);
68 NETNATIVE_LOGE("tun set iff error: %{public}d", errno);
69 return NETMANAGER_ERROR;
70 }
71
72 net4Sock_ = socket(AF_INET, SOCK_DGRAM, 0);
73 if (net4Sock_ < 0) {
74 NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
75 }
76 net6Sock_ = socket(AF_INET6, SOCK_DGRAM, 0);
77 if (net6Sock_ < 0) {
78 NETNATIVE_LOGE("create SOCK_DGRAM ipv6 failed: %{public}d", errno);
79 }
80 if (net4Sock_ < 0 && net6Sock_ < 0) {
81 close(tunfd);
82 NETNATIVE_LOGE("create SOCK_DGRAM ip failed");
83 return NETMANAGER_ERROR;
84 }
85
86 NETNATIVE_LOGI("open virtual device successfully, [%{public}d]", tunfd);
87 tunFd_ = tunfd;
88 SetVpnUp();
89 StartVpnInterfaceFdListen();
90 return NETMANAGER_SUCCESS;
91 }
92
DestroyVpnInterface()93 void VpnManager::DestroyVpnInterface()
94 {
95 SetVpnDown();
96 if (net4Sock_ != 0) {
97 close(net4Sock_);
98 net4Sock_ = 0;
99 }
100 if (net6Sock_ != 0) {
101 close(net6Sock_);
102 net6Sock_ = 0;
103 }
104 if (tunFd_ != 0) {
105 close(tunFd_);
106 tunFd_ = 0;
107 }
108 }
109
SetVpnResult(std::atomic_int & fd,unsigned long cmd,ifreq & ifr)110 int32_t VpnManager::SetVpnResult(std::atomic_int &fd, unsigned long cmd, ifreq &ifr)
111 {
112 if (fd > 0) {
113 if (ioctl(fd, cmd, &ifr) < 0) {
114 NETNATIVE_LOGE("set vpn error, errno:%{public}d", errno);
115 return NETMANAGER_ERROR;
116 }
117 }
118 return NETMANAGER_SUCCESS;
119 }
120
SetVpnMtu(const std::string & ifName,int32_t mtu)121 int32_t VpnManager::SetVpnMtu(const std::string &ifName, int32_t mtu)
122 {
123 if (mtu <= 0) {
124 NETNATIVE_LOGE("invalid mtu value");
125 return NETMANAGER_ERROR;
126 }
127
128 ifreq ifr;
129 if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
130 return NETMANAGER_ERROR;
131 }
132
133 ifr.ifr_mtu = mtu;
134 int32_t ret4 = SetVpnResult(net4Sock_, SIOCSIFMTU, ifr);
135 int32_t ret6 = SetVpnResult(net6Sock_, SIOCSIFMTU, ifr);
136 if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (net4Sock_ < 0 && net6Sock_ < 0)) {
137 NETNATIVE_LOGI("set MTU failed");
138 return NETMANAGER_ERROR;
139 } else {
140 NETNATIVE_LOGI("set MTU success");
141 return NETMANAGER_SUCCESS;
142 }
143 }
144
SetVpnAddress(const std::string & ifName,const std::string & tunAddr,int32_t prefix)145 int32_t VpnManager::SetVpnAddress(const std::string &ifName, const std::string &tunAddr, int32_t prefix)
146 {
147 ifreq ifr = {};
148 if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
149 return NETMANAGER_ERROR;
150 }
151
152 bool isIpv6 = CommonUtils::IsValidIPV6(tunAddr);
153 if (isIpv6) {
154 struct in6_ifreq ifr6 = {};
155 if (ioctl(net6Sock_, SIOCGIFINDEX, &ifr) <0) {
156 NETNATIVE_LOGE(" get network interface ipv6 failed: %{public}d", errno);
157 return NETMANAGER_ERROR;
158 }
159 if (inet_pton(AF_INET6, tunAddr.c_str(), &ifr6.ifr6_addr) == 0) {
160 NETNATIVE_LOGE("inet_pton ipv6 address failed: %{public}d", errno);
161 }
162 ifr6.ifr6_prefixlen = prefix;
163 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
164 if (ioctl(net6Sock_, SIOCSIFADDR, &ifr6) < 0) {
165 NETNATIVE_LOGE("ioctl set ipv6 address failed: %{public}d", errno);
166 return NETMANAGER_ERROR;
167 }
168 } else {
169 in_addr ipv4Addr = {};
170 if (inet_aton(tunAddr.c_str(), &ipv4Addr) == 0) {
171 NETNATIVE_LOGE("addr inet_aton error");
172 return NETMANAGER_ERROR;
173 }
174
175 auto sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_addr);
176 sin->sin_family = AF_INET;
177 sin->sin_addr = ipv4Addr;
178 if (ioctl(net4Sock_, SIOCSIFADDR, &ifr) < 0) {
179 NETNATIVE_LOGE("ioctl set ipv4 address failed: %{public}d", errno);
180 return NETMANAGER_ERROR;
181 }
182
183 if (prefix <= 0 || prefix >= NET_MASK_MAX_LENGTH) {
184 NETNATIVE_LOGE("prefix: %{public}d error", prefix);
185 return NETMANAGER_ERROR;
186 }
187 in_addr_t mask = prefix ? (~0 << (NET_MASK_MAX_LENGTH - prefix)) : 0;
188 sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_netmask);
189 sin->sin_family = AF_INET;
190 sin->sin_addr.s_addr = htonl(mask);
191 if (ioctl(net4Sock_, SIOCSIFNETMASK, &ifr) < 0) {
192 NETNATIVE_LOGE("ioctl set ip mask failed: %{public}d", errno);
193 return NETMANAGER_ERROR;
194 }
195 }
196
197 NETNATIVE_LOGI("set ip address success");
198 return NETMANAGER_SUCCESS;
199 }
200
SetVpnUp()201 int32_t VpnManager::SetVpnUp()
202 {
203 ifreq ifr = {};
204 if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
205 return NETMANAGER_ERROR;
206 }
207
208 ifr.ifr_flags = IFF_UP;
209 int32_t ret4 = SetVpnResult(net4Sock_, SIOCSIFFLAGS, ifr);
210 int32_t ret6 = SetVpnResult(net6Sock_, SIOCSIFFLAGS, ifr);
211 if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (net4Sock_ < 0 && net6Sock_ < 0)) {
212 NETNATIVE_LOGI("set iff up failed");
213 return NETMANAGER_ERROR;
214 } else {
215 NETNATIVE_LOGI("set iff up success");
216 return NETMANAGER_SUCCESS;
217 }
218 }
219
SetVpnDown()220 int32_t VpnManager::SetVpnDown()
221 {
222 ifreq ifr = {};
223 if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
224 return NETMANAGER_ERROR;
225 }
226
227 ifr.ifr_flags &= ~IFF_UP;
228 int32_t ret4 = SetVpnResult(net4Sock_, SIOCSIFFLAGS, ifr);
229 int32_t ret6 = SetVpnResult(net6Sock_, SIOCSIFFLAGS, ifr);
230 if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (net4Sock_ < 0 && net6Sock_ < 0)) {
231 NETNATIVE_LOGI("set iff down failed");
232 return NETMANAGER_ERROR;
233 } else {
234 NETNATIVE_LOGI("set iff down success");
235 return NETMANAGER_SUCCESS;
236 }
237 }
238
InitIfreq(ifreq & ifr,const std::string & cardName)239 int32_t VpnManager::InitIfreq(ifreq &ifr, const std::string &cardName)
240 {
241 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
242 NETNATIVE_LOGE("memset_s ifr failed!");
243 return NETMANAGER_ERROR;
244 }
245 if (strncpy_s(ifr.ifr_name, IFNAMSIZ, cardName.c_str(), strlen(cardName.c_str())) != EOK) {
246 NETNATIVE_LOGE("strcpy_s ifr name fail");
247 return NETMANAGER_ERROR;
248 }
249 return NETMANAGER_SUCCESS;
250 }
251
SendVpnInterfaceFdToClient(int32_t clientFd,int32_t tunFd)252 int32_t VpnManager::SendVpnInterfaceFdToClient(int32_t clientFd, int32_t tunFd)
253 {
254 char buf[1] = {0};
255 iovec iov;
256 iov.iov_base = buf;
257 iov.iov_len = sizeof(buf);
258 union {
259 cmsghdr align;
260 char cmsg[CMSG_SPACE(sizeof(int32_t))];
261 } cmsgu;
262 if (memset_s(cmsgu.cmsg, sizeof(cmsgu.cmsg), 0, sizeof(cmsgu.cmsg)) != EOK) {
263 NETNATIVE_LOGE("memset_s cmsgu.cmsg failed!");
264 return NETMANAGER_ERROR;
265 }
266 msghdr message;
267 if (memset_s(&message, sizeof(message), 0, sizeof(message)) != EOK) {
268 NETNATIVE_LOGE("memset_s message failed!");
269 return NETMANAGER_ERROR;
270 }
271
272 message.msg_iov = &iov;
273 message.msg_iovlen = 1;
274 message.msg_control = cmsgu.cmsg;
275 message.msg_controllen = sizeof(cmsgu.cmsg);
276 cmsghdr *cmsgh = CMSG_FIRSTHDR(&message);
277 cmsgh->cmsg_len = CMSG_LEN(sizeof(tunFd));
278 cmsgh->cmsg_level = SOL_SOCKET;
279 cmsgh->cmsg_type = SCM_RIGHTS;
280 if (memcpy_s(CMSG_DATA(cmsgh), sizeof(tunFd), &tunFd, sizeof(tunFd)) != EOK) {
281 NETNATIVE_LOGE("memcpy_s cmsgu failed!");
282 return NETMANAGER_ERROR;
283 }
284 if (sendmsg(clientFd, &message, 0) < 0) {
285 NETNATIVE_LOGE("sendmsg error: %{public}d, clientfd[%{public}d], tunfd[%{public}d]", errno, clientFd, tunFd);
286 return NETMANAGER_ERROR;
287 }
288 return NETMANAGER_SUCCESS;
289 }
290
StartUnixSocketListen()291 void VpnManager::StartUnixSocketListen()
292 {
293 NETNATIVE_LOGI("StartUnixSocketListen...");
294 int32_t serverfd = GetControlSocket("tunfd");
295 if (listen(serverfd, MAX_UNIX_SOCKET_CLIENT) < 0) {
296 close(serverfd);
297 NETNATIVE_LOGE("listen socket error: %{public}d", errno);
298 return;
299 }
300
301 sockaddr_in clientAddr;
302 socklen_t len = sizeof(clientAddr);
303 while (true) {
304 int32_t clientFd = accept(serverfd, reinterpret_cast<sockaddr *>(&clientAddr), &len);
305 if (clientFd < 0) {
306 NETNATIVE_LOGE("accept socket error: %{public}d", errno);
307 continue;
308 }
309
310 SendVpnInterfaceFdToClient(clientFd, tunFd_);
311 close(clientFd);
312 }
313
314 close(serverfd);
315 listeningFlag_ = false;
316 }
317
StartVpnInterfaceFdListen()318 void VpnManager::StartVpnInterfaceFdListen()
319 {
320 if (listeningFlag_) {
321 NETNATIVE_LOGI("VpnInterface fd is listening...");
322 return;
323 }
324
325 NETNATIVE_LOGI("StartVpnInterfaceFdListen...");
326 std::thread unixThread([this]() { StartUnixSocketListen(); });
327 unixThread.detach();
328 pthread_setname_np(unixThread.native_handle(), "unix_socket_tunfd");
329 listeningFlag_ = true;
330 }
331
332 } // namespace NetManagerStandard
333 } // namespace OHOS
334