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