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/ipv6.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 #include <linux/netlink.h>
30 #include <linux/rtnetlink.h>
31 #include <net/if.h>
32 #include <cstring>
33 #include <string>
34
35 #include "netlink_msg.h"
36 #include "netlink_socket.h"
37 #include "init_socket.h"
38 #include "net_manager_constants.h"
39 #include "netnative_log_wrapper.h"
40 #include "securec.h"
41 #include "netmanager_base_common_utils.h"
42
43 namespace OHOS {
44 namespace NetManagerStandard {
45
46 namespace {
47 constexpr const char *TUN_CARD_NAME = "vpn-tun";
48 constexpr const char *TUN_DEVICE_PATH = "/dev/tun";
49 constexpr int32_t NET_MASK_MAX_LENGTH = 32;
50 constexpr int32_t MAX_UNIX_SOCKET_CLIENT = 5;
51 constexpr uint8_t IPV4_LEN = 32;
52 constexpr uint8_t IPV6_LEN = 128;
53 } // namespace
54
CreateVpnInterface()55 int32_t VpnManager::CreateVpnInterface()
56 {
57 if (tunFd_ != 0) {
58 StartVpnInterfaceFdListen();
59 return NETMANAGER_SUCCESS;
60 }
61
62 ifreq ifr = {};
63 if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
64 return NETMANAGER_ERROR;
65 }
66
67 int32_t tunfd = open(TUN_DEVICE_PATH, O_RDWR | O_NONBLOCK | O_CLOEXEC);
68 if (tunfd <= 0) {
69 NETNATIVE_LOGE("open virtual device failed: %{public}d", errno);
70 return NETMANAGER_ERROR;
71 }
72
73 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
74 if (ioctl(tunfd, TUNSETIFF, &ifr) < 0) {
75 close(tunfd);
76 NETNATIVE_LOGE("tun set iff error: %{public}d", errno);
77 return NETMANAGER_ERROR;
78 }
79
80 net4Sock_ = socket(AF_INET, SOCK_DGRAM, 0);
81 if (net4Sock_ < 0) {
82 NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
83 }
84 net6Sock_ = socket(AF_INET6, SOCK_DGRAM, 0);
85 if (net6Sock_ < 0) {
86 NETNATIVE_LOGE("create SOCK_DGRAM ipv6 failed: %{public}d", errno);
87 }
88 if (net4Sock_ < 0 && net6Sock_ < 0) {
89 close(tunfd);
90 NETNATIVE_LOGE("create SOCK_DGRAM ip failed");
91 return NETMANAGER_ERROR;
92 }
93
94 NETNATIVE_LOGI("open virtual device successfully, [%{public}d]", tunfd);
95 tunFd_ = tunfd;
96 SetVpnUp();
97 StartVpnInterfaceFdListen();
98 return NETMANAGER_SUCCESS;
99 }
100
DestroyVpnInterface()101 void VpnManager::DestroyVpnInterface()
102 {
103 SetVpnDown();
104 if (net4Sock_ != 0) {
105 close(net4Sock_);
106 net4Sock_ = 0;
107 }
108 if (net6Sock_ != 0) {
109 close(net6Sock_);
110 net6Sock_ = 0;
111 }
112 if (tunFd_ != 0) {
113 close(tunFd_);
114 tunFd_ = 0;
115 }
116 }
117
SetVpnResult(std::atomic_int & fd,unsigned long cmd,ifreq & ifr)118 int32_t VpnManager::SetVpnResult(std::atomic_int &fd, unsigned long cmd, ifreq &ifr)
119 {
120 if (fd > 0) {
121 if (ioctl(fd, cmd, &ifr) < 0) {
122 NETNATIVE_LOGE("set vpn error, errno:%{public}d", errno);
123 return NETMANAGER_ERROR;
124 }
125 }
126 return NETMANAGER_SUCCESS;
127 }
128
SetVpnMtu(const std::string & ifName,int32_t mtu)129 int32_t VpnManager::SetVpnMtu(const std::string &ifName, int32_t mtu)
130 {
131 if (mtu <= 0) {
132 NETNATIVE_LOGE("invalid mtu value");
133 return NETMANAGER_ERROR;
134 }
135
136 ifreq ifr;
137 if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
138 return NETMANAGER_ERROR;
139 }
140
141 ifr.ifr_mtu = mtu;
142 int32_t ret4 = SetVpnResult(net4Sock_, SIOCSIFMTU, ifr);
143 int32_t ret6 = SetVpnResult(net6Sock_, SIOCSIFMTU, ifr);
144 if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (net4Sock_ < 0 && net6Sock_ < 0)) {
145 NETNATIVE_LOGI("set MTU failed");
146 return NETMANAGER_ERROR;
147 } else {
148 NETNATIVE_LOGI("set MTU success");
149 return NETMANAGER_SUCCESS;
150 }
151 }
152
SetVpnAddress(const std::string & ifName,const std::string & tunAddr,int32_t prefix)153 int32_t VpnManager::SetVpnAddress(const std::string &ifName, const std::string &tunAddr, int32_t prefix)
154 {
155 char addrbuf[sizeof(in6_addr)] = {0};
156 int family = -1;
157
158 if (inet_pton(AF_INET, tunAddr.c_str(), addrbuf) == 1) {
159 family = AF_INET;
160 } else if (inet_pton(AF_INET6, tunAddr.c_str(), addrbuf) == 1) {
161 family = AF_INET6;
162 } else {
163 NETNATIVE_LOGE("invalid IP address: %{public}s", tunAddr.c_str());
164 return NETMANAGER_ERROR;
165 }
166
167 uint32_t ifindex = if_nametoindex(ifName.c_str());
168 if (ifindex == 0) {
169 NETNATIVE_LOGE("if_nametoindex failed: %{public}d", errno);
170 return NETMANAGER_ERROR;
171 }
172
173 return SendNetlinkAddress(ifindex, family, addrbuf, prefix);
174 }
175
SendNetlinkAddress(int ifindex,int family,const char * addrbuf,int prefix)176 int32_t VpnManager::SendNetlinkAddress(int ifindex, int family, const char* addrbuf, int prefix)
177 {
178 if ((family == AF_INET && (prefix < 0 || prefix > IPV4_LEN)) ||
179 (family == AF_INET6 && (prefix < 0 || prefix > IPV6_LEN))) {
180 NETNATIVE_LOGE("Invalid prefix length: %{public}d", prefix);
181 return NETMANAGER_ERROR;
182 }
183
184 constexpr size_t kMaxMsgLen = 4096;
185 nmd::NetlinkMsg netMsg(NLM_F_CREATE, kMaxMsgLen, getpid());
186
187 ifaddrmsg ifa {};
188 ifa.ifa_family = static_cast<uint8_t>(family);
189 ifa.ifa_prefixlen = static_cast<uint8_t>(prefix);
190 ifa.ifa_flags = IFA_F_PERMANENT;
191 ifa.ifa_scope = 0;
192 ifa.ifa_index = static_cast<uint32_t>(ifindex);
193
194 netMsg.AddAddress(RTM_NEWADDR, ifa);
195
196 int addrLen = (family == AF_INET) ? 4 : 16;
197 int32_t resultLocal = netMsg.AddAttr(IFA_LOCAL, const_cast<char*>(addrbuf), addrLen);
198 int32_t resultAddress = netMsg.AddAttr(IFA_ADDRESS, const_cast<char*>(addrbuf), addrLen);
199 if (resultLocal < 0 || resultAddress < 0) {
200 NETNATIVE_LOGE("AddAttr failed");
201 return NETMANAGER_ERROR;
202 }
203
204 return nmd::SendNetlinkMsgToKernel(netMsg.GetNetLinkMessage(), 0);
205 }
206
SetVpnUp()207 int32_t VpnManager::SetVpnUp()
208 {
209 ifreq ifr = {};
210 if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
211 return NETMANAGER_ERROR;
212 }
213
214 ifr.ifr_flags = IFF_UP;
215 int32_t ret4 = SetVpnResult(net4Sock_, SIOCSIFFLAGS, ifr);
216 int32_t ret6 = SetVpnResult(net6Sock_, SIOCSIFFLAGS, ifr);
217 if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (net4Sock_ < 0 && net6Sock_ < 0)) {
218 NETNATIVE_LOGI("set iff up failed");
219 return NETMANAGER_ERROR;
220 } else {
221 NETNATIVE_LOGI("set iff up success");
222 return NETMANAGER_SUCCESS;
223 }
224 }
225
SetVpnDown()226 int32_t VpnManager::SetVpnDown()
227 {
228 ifreq ifr = {};
229 if (InitIfreq(ifr, TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
230 return NETMANAGER_ERROR;
231 }
232
233 ifr.ifr_flags &= ~IFF_UP;
234 int32_t ret4 = SetVpnResult(net4Sock_, SIOCSIFFLAGS, ifr);
235 int32_t ret6 = SetVpnResult(net6Sock_, SIOCSIFFLAGS, ifr);
236 if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (net4Sock_ < 0 && net6Sock_ < 0)) {
237 NETNATIVE_LOGI("set iff down failed");
238 return NETMANAGER_ERROR;
239 } else {
240 NETNATIVE_LOGI("set iff down success");
241 return NETMANAGER_SUCCESS;
242 }
243 }
244
InitIfreq(ifreq & ifr,const std::string & cardName)245 int32_t VpnManager::InitIfreq(ifreq &ifr, const std::string &cardName)
246 {
247 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
248 NETNATIVE_LOGE("memset_s ifr failed!");
249 return NETMANAGER_ERROR;
250 }
251 if (strncpy_s(ifr.ifr_name, IFNAMSIZ, cardName.c_str(), strlen(cardName.c_str())) != EOK) {
252 NETNATIVE_LOGE("strcpy_s ifr name fail");
253 return NETMANAGER_ERROR;
254 }
255 return NETMANAGER_SUCCESS;
256 }
257
SendVpnInterfaceFdToClient(int32_t clientFd,int32_t tunFd)258 int32_t VpnManager::SendVpnInterfaceFdToClient(int32_t clientFd, int32_t tunFd)
259 {
260 char buf[1] = {0};
261 iovec iov;
262 iov.iov_base = buf;
263 iov.iov_len = sizeof(buf);
264 union {
265 cmsghdr align;
266 char cmsg[CMSG_SPACE(sizeof(int32_t))];
267 } cmsgu;
268 if (memset_s(cmsgu.cmsg, sizeof(cmsgu.cmsg), 0, sizeof(cmsgu.cmsg)) != EOK) {
269 NETNATIVE_LOGE("memset_s cmsgu.cmsg failed!");
270 return NETMANAGER_ERROR;
271 }
272 msghdr message;
273 if (memset_s(&message, sizeof(message), 0, sizeof(message)) != EOK) {
274 NETNATIVE_LOGE("memset_s message failed!");
275 return NETMANAGER_ERROR;
276 }
277
278 message.msg_iov = &iov;
279 message.msg_iovlen = 1;
280 message.msg_control = cmsgu.cmsg;
281 message.msg_controllen = sizeof(cmsgu.cmsg);
282 cmsghdr *cmsgh = CMSG_FIRSTHDR(&message);
283 cmsgh->cmsg_len = CMSG_LEN(sizeof(tunFd));
284 cmsgh->cmsg_level = SOL_SOCKET;
285 cmsgh->cmsg_type = SCM_RIGHTS;
286 if (memcpy_s(CMSG_DATA(cmsgh), sizeof(tunFd), &tunFd, sizeof(tunFd)) != EOK) {
287 NETNATIVE_LOGE("memcpy_s cmsgu failed!");
288 return NETMANAGER_ERROR;
289 }
290 if (sendmsg(clientFd, &message, 0) < 0) {
291 NETNATIVE_LOGE("sendmsg error: %{public}d, clientfd[%{public}d], tunfd[%{public}d]", errno, clientFd, tunFd);
292 return NETMANAGER_ERROR;
293 }
294 return NETMANAGER_SUCCESS;
295 }
296
StartUnixSocketListen()297 void VpnManager::StartUnixSocketListen()
298 {
299 NETNATIVE_LOGI("StartUnixSocketListen...");
300 int32_t serverfd = GetControlSocket("tunfd");
301 if (listen(serverfd, MAX_UNIX_SOCKET_CLIENT) < 0) {
302 close(serverfd);
303 NETNATIVE_LOGE("listen socket error: %{public}d", errno);
304 return;
305 }
306
307 sockaddr_in clientAddr;
308 socklen_t len = sizeof(clientAddr);
309 while (true) {
310 int32_t clientFd = accept(serverfd, reinterpret_cast<sockaddr *>(&clientAddr), &len);
311 if (clientFd < 0) {
312 NETNATIVE_LOGE("accept socket error: %{public}d", errno);
313 continue;
314 }
315
316 SendVpnInterfaceFdToClient(clientFd, tunFd_);
317 close(clientFd);
318 }
319
320 close(serverfd);
321 listeningFlag_ = false;
322 }
323
StartVpnInterfaceFdListen()324 void VpnManager::StartVpnInterfaceFdListen()
325 {
326 if (listeningFlag_) {
327 NETNATIVE_LOGI("VpnInterface fd is listening...");
328 return;
329 }
330
331 NETNATIVE_LOGI("StartVpnInterfaceFdListen...");
332 std::thread t([sp = shared_from_this()]() { sp->StartUnixSocketListen(); });
333 t.detach();
334 pthread_setname_np(t.native_handle(), "unix_socket_tunfd");
335 listeningFlag_ = true;
336 }
337
338 } // namespace NetManagerStandard
339 } // namespace OHOS
340