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