• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/if_tun.h>
22 #include <netinet/in.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 #include <sys/un.h>
27 #include <thread>
28 #include <unistd.h>
29 
30 #include "init_socket.h"
31 #include "net_manager_constants.h"
32 #include "netnative_log_wrapper.h"
33 #include "securec.h"
34 
35 namespace OHOS {
36 namespace NetManagerStandard {
37 
38 namespace {
39 constexpr const char *TUN_CARD_NAME = "vpn-tun";
40 constexpr const char *TUN_DEVICE_PATH = "/dev/tun";
41 constexpr int32_t NET_MASK_MAX_LENGTH = 32;
42 constexpr int32_t MAX_UNIX_SOCKET_CLIENT = 5;
43 } // namespace
44 
CreateVpnInterface()45 int32_t VpnManager::CreateVpnInterface()
46 {
47     if (tunFd_ != 0) {
48         StartVpnInterfaceFdListen();
49         return NETMANAGER_SUCCESS;
50     }
51 
52     ifreq ifr = {};
53     if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
54         return NETMANAGER_ERROR;
55     }
56 
57     int32_t tunfd = open(TUN_DEVICE_PATH, O_RDWR | O_NONBLOCK);
58     if (tunfd <= 0) {
59         NETNATIVE_LOGE("open virtual device failed: %{public}d", errno);
60         return NETMANAGER_ERROR;
61     }
62 
63     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
64     if (ioctl(tunfd, TUNSETIFF, &ifr) < 0) {
65         close(tunfd);
66         NETNATIVE_LOGE("tun set iff error: %{public}d", errno);
67         return NETMANAGER_ERROR;
68     }
69 
70     net4Sock_ = socket(AF_INET, SOCK_DGRAM, 0);
71     if (net4Sock_ < 0) {
72         close(tunfd);
73         NETNATIVE_LOGE("create SOCK_DGRAM failed: %{public}d", errno);
74         return NETMANAGER_ERROR;
75     }
76 
77     NETNATIVE_LOGI("open virtual device successfully, [%{public}d]", tunfd);
78     tunFd_ = tunfd;
79     SetVpnUp();
80     StartVpnInterfaceFdListen();
81     return NETMANAGER_SUCCESS;
82 }
83 
DestroyVpnInterface()84 void VpnManager::DestroyVpnInterface()
85 {
86     SetVpnDown();
87     if (net4Sock_ != 0) {
88         close(net4Sock_);
89         net4Sock_ = 0;
90     }
91     if (tunFd_ != 0) {
92         close(tunFd_);
93         tunFd_ = 0;
94     }
95 }
96 
SetVpnMtu(const std::string & ifName,int32_t mtu)97 int32_t VpnManager::SetVpnMtu(const std::string &ifName, int32_t mtu)
98 {
99     if (mtu <= 0) {
100         NETNATIVE_LOGE("invalid mtu value");
101         return NETMANAGER_ERROR;
102     }
103 
104     ifreq ifr;
105     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
106         return NETMANAGER_ERROR;
107     }
108 
109     ifr.ifr_mtu = mtu;
110     if (ioctl(net4Sock_, SIOCSIFMTU, &ifr) < 0) {
111         NETNATIVE_LOGE("set MTU error, errno:%{public}d", errno);
112         return NETMANAGER_ERROR;
113     }
114     NETNATIVE_LOGI("set MTU success");
115     return NETMANAGER_SUCCESS;
116 }
117 
SetVpnAddress(const std::string & ifName,const std::string & tunAddr,int32_t prefix)118 int32_t VpnManager::SetVpnAddress(const std::string &ifName, const std::string &tunAddr, int32_t prefix)
119 {
120     ifreq ifr = {};
121     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
122         return NETMANAGER_ERROR;
123     }
124 
125     in_addr ipv4Addr = {};
126     if (inet_aton(tunAddr.c_str(), &ipv4Addr) == 0) {
127         NETNATIVE_LOGE("addr: %{public}s inet_aton error", tunAddr.c_str());
128         return NETMANAGER_ERROR;
129     }
130 
131     auto sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_addr);
132     sin->sin_family = AF_INET;
133     sin->sin_addr = ipv4Addr;
134     if (ioctl(net4Sock_, SIOCSIFADDR, &ifr) < 0) {
135         NETNATIVE_LOGE("ioctl set ip address failed: %{public}d", errno);
136         return NETMANAGER_ERROR;
137     }
138 
139     if (prefix <= 0 || prefix >= NET_MASK_MAX_LENGTH) {
140         NETNATIVE_LOGE("prefix: %{public}d error", prefix);
141         return NETMANAGER_ERROR;
142     }
143     in_addr_t mask = prefix ? (~0 << (NET_MASK_MAX_LENGTH - prefix)) : 0;
144     sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_netmask);
145     sin->sin_family = AF_INET;
146     sin->sin_addr.s_addr = htonl(mask);
147     if (ioctl(net4Sock_, SIOCSIFNETMASK, &ifr) < 0) {
148         NETNATIVE_LOGE("ioctl set ip mask failed: %{public}d", errno);
149         return NETMANAGER_ERROR;
150     }
151 
152     NETNATIVE_LOGI("set ip address success");
153     return NETMANAGER_SUCCESS;
154 }
155 
SetVpnUp()156 int32_t VpnManager::SetVpnUp()
157 {
158     ifreq ifr = {};
159     if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
160         return NETMANAGER_ERROR;
161     }
162 
163     ifr.ifr_flags = IFF_UP;
164     if (ioctl(net4Sock_, SIOCSIFFLAGS, &ifr) < 0) {
165         NETNATIVE_LOGE("set iff up failed: %{public}d", errno);
166         return NETMANAGER_ERROR;
167     }
168     NETNATIVE_LOGI("set iff up success");
169     return NETMANAGER_SUCCESS;
170 }
171 
SetVpnDown()172 int32_t VpnManager::SetVpnDown()
173 {
174     ifreq ifr = {};
175     if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
176         return NETMANAGER_ERROR;
177     }
178 
179     ifr.ifr_flags &= ~IFF_UP;
180     if (ioctl(net4Sock_, SIOCSIFFLAGS, &ifr) < 0) {
181         NETNATIVE_LOGE("set iff down failed: %{public}d", errno);
182         return NETMANAGER_ERROR;
183     }
184     NETNATIVE_LOGI("set iff down success");
185     return NETMANAGER_SUCCESS;
186 }
187 
InitIfreq(ifreq & ifr,const std::string & cardName)188 int32_t VpnManager::InitIfreq(ifreq &ifr, const std::string &cardName)
189 {
190     if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
191         NETNATIVE_LOGE("memset_s ifr failed!");
192         return NETMANAGER_ERROR;
193     }
194     if (strncpy_s(ifr.ifr_name, IFNAMSIZ, cardName.c_str(), strlen(cardName.c_str())) != EOK) {
195         NETNATIVE_LOGE("strcpy_s ifr name fail");
196         return NETMANAGER_ERROR;
197     }
198     return NETMANAGER_SUCCESS;
199 }
200 
SendVpnInterfaceFdToClient(int32_t clientFd,int32_t tunFd)201 int32_t VpnManager::SendVpnInterfaceFdToClient(int32_t clientFd, int32_t tunFd)
202 {
203     char buf[1] = {0};
204     iovec iov;
205     iov.iov_base = buf;
206     iov.iov_len = sizeof(buf);
207     union {
208         cmsghdr align;
209         char cmsg[CMSG_SPACE(sizeof(int32_t))];
210     } cmsgu;
211     if (memset_s(cmsgu.cmsg, sizeof(cmsgu.cmsg), 0, sizeof(cmsgu.cmsg)) != EOK) {
212         NETNATIVE_LOGE("memset_s cmsgu.cmsg failed!");
213         return NETMANAGER_ERROR;
214     }
215     msghdr message;
216     if (memset_s(&message, sizeof(message), 0, sizeof(message)) != EOK) {
217         NETNATIVE_LOGE("memset_s message failed!");
218         return NETMANAGER_ERROR;
219     }
220 
221     message.msg_iov = &iov;
222     message.msg_iovlen = 1;
223     message.msg_control = cmsgu.cmsg;
224     message.msg_controllen = sizeof(cmsgu.cmsg);
225     cmsghdr *cmsgh = CMSG_FIRSTHDR(&message);
226     cmsgh->cmsg_len = CMSG_LEN(sizeof(tunFd));
227     cmsgh->cmsg_level = SOL_SOCKET;
228     cmsgh->cmsg_type = SCM_RIGHTS;
229     if (memcpy_s(CMSG_DATA(cmsgh), sizeof(tunFd), &tunFd, sizeof(tunFd)) != EOK) {
230         NETNATIVE_LOGE("memcpy_s cmsgu failed!");
231         return NETMANAGER_ERROR;
232     }
233     if (sendmsg(clientFd, &message, 0) < 0) {
234         NETNATIVE_LOGE("sendmsg error: %{public}d, clientfd[%{public}d], tunfd[%{public}d]", errno, clientFd, tunFd);
235         return NETMANAGER_ERROR;
236     }
237     return NETMANAGER_SUCCESS;
238 }
239 
StartUnixSocketListen()240 void VpnManager::StartUnixSocketListen()
241 {
242     NETNATIVE_LOGI("StartUnixSocketListen...");
243     int32_t serverfd = GetControlSocket("tunfd");
244     if (listen(serverfd, MAX_UNIX_SOCKET_CLIENT) < 0) {
245         close(serverfd);
246         NETNATIVE_LOGE("listen socket error: %{public}d", errno);
247         return;
248     }
249 
250     sockaddr_in clientAddr;
251     socklen_t len = sizeof(clientAddr);
252     while (true) {
253         int32_t clientFd = accept(serverfd, reinterpret_cast<sockaddr *>(&clientAddr), &len);
254         if (clientFd < 0) {
255             NETNATIVE_LOGE("accept socket error: %{public}d", errno);
256             continue;
257         }
258 
259         SendVpnInterfaceFdToClient(clientFd, tunFd_);
260         close(clientFd);
261     }
262 
263     close(serverfd);
264     listeningFlag_ = false;
265 }
266 
StartVpnInterfaceFdListen()267 void VpnManager::StartVpnInterfaceFdListen()
268 {
269     if (listeningFlag_) {
270         NETNATIVE_LOGI("VpnInterface fd is listening...");
271         return;
272     }
273 
274     NETNATIVE_LOGI("StartVpnInterfaceFdListen...");
275     std::thread unixThread([this]() { StartUnixSocketListen(); });
276     unixThread.detach();
277     pthread_setname_np(unixThread.native_handle(), "unix_socket_tunfd");
278     listeningFlag_ = true;
279 }
280 
281 } // namespace NetManagerStandard
282 } // namespace OHOS
283