• 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/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