• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "multi_vpn_manager.h"
17 
18 #include <sys/ioctl.h>
19 #include <thread>
20 #include <linux/ppp_defs.h>
21 #include <linux/if_ppp.h>
22 #include <linux/if_tun.h>
23 #include "init_socket.h"
24 #include "net_manager_constants.h"
25 #include "netmanager_base_common_utils.h"
26 #include "netnative_log_wrapper.h"
27 #include "securec.h"
28 #include "netlink_socket.h"
29 #include "route_manager.h"
30 
31 namespace OHOS {
32 namespace NetManagerStandard {
33 
34 namespace {
35 constexpr uint32_t DEFAULT_MTU = 1500;
36 constexpr int32_t NET_MASK_MAX_LENGTH = 32;
37 constexpr int32_t MAX_UNIX_SOCKET_CLIENT = 5;
38 } // namespace
39 
SendVpnInterfaceFdToClient(int32_t clientFd,int32_t tunFd)40 int32_t MultiVpnManager::SendVpnInterfaceFdToClient(int32_t clientFd, int32_t tunFd)
41 {
42     char buf[1] = {0};
43     iovec iov;
44     iov.iov_base = buf;
45     iov.iov_len = sizeof(buf);
46     union {
47         cmsghdr align;
48         char cmsg[CMSG_SPACE(sizeof(int32_t))];
49     } cmsgu;
50     if (memset_s(cmsgu.cmsg, sizeof(cmsgu.cmsg), 0, sizeof(cmsgu.cmsg)) != EOK) {
51         NETNATIVE_LOGE("memset_s cmsgu.cmsg failed!");
52         return NETMANAGER_ERROR;
53     }
54     msghdr message;
55     if (memset_s(&message, sizeof(message), 0, sizeof(message)) != EOK) {
56         NETNATIVE_LOGE("memset_s message failed!");
57         return NETMANAGER_ERROR;
58     }
59 
60     message.msg_iov = &iov;
61     message.msg_iovlen = 1;
62     message.msg_control = cmsgu.cmsg;
63     message.msg_controllen = sizeof(cmsgu.cmsg);
64     cmsghdr *cmsgh = CMSG_FIRSTHDR(&message);
65     cmsgh->cmsg_len = CMSG_LEN(sizeof(tunFd));
66     cmsgh->cmsg_level = SOL_SOCKET;
67     cmsgh->cmsg_type = SCM_RIGHTS;
68     if (memcpy_s(CMSG_DATA(cmsgh), sizeof(tunFd), &tunFd, sizeof(tunFd)) != EOK) {
69         NETNATIVE_LOGE("memcpy_s cmsgu failed!");
70         return NETMANAGER_ERROR;
71     }
72     if (sendmsg(clientFd, &message, 0) < 0) {
73         NETNATIVE_LOGE("sendmsg error: %{public}d, clientfd[%{public}d], tunfd[%{public}d]", errno, clientFd, tunFd);
74         return NETMANAGER_ERROR;
75     }
76     return NETMANAGER_SUCCESS;
77 }
78 
InitIfreq(ifreq & ifr,const std::string & ifName)79 int32_t MultiVpnManager::InitIfreq(ifreq &ifr, const std::string &ifName)
80 {
81     if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
82         NETNATIVE_LOGE("memset_s ifr failed!");
83         return NETMANAGER_ERROR;
84     }
85     if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ifName.c_str(), strlen(ifName.c_str())) != EOK) {
86         NETNATIVE_LOGE("strcpy_s ifr name fail");
87         return NETMANAGER_ERROR;
88     }
89     return NETMANAGER_SUCCESS;
90 }
91 
SetVpnResult(std::atomic_int & fd,unsigned long cmd,ifreq & ifr)92 int32_t MultiVpnManager::SetVpnResult(std::atomic_int &fd, unsigned long cmd, ifreq &ifr)
93 {
94     if (fd > 0) {
95         if (ioctl(fd, cmd, &ifr) < 0) {
96             NETNATIVE_LOGE("set vpn error, errno:%{public}d", errno);
97             return NETMANAGER_ERROR;
98         }
99     }
100     return NETMANAGER_SUCCESS;
101 }
102 
SetVpnMtu(const std::string & ifName,int32_t mtu)103 int32_t MultiVpnManager::SetVpnMtu(const std::string &ifName, int32_t mtu)
104 {
105     if (mtu <= 0) {
106         NETNATIVE_LOGE("invalid mtu value");
107         return NETMANAGER_ERROR;
108     }
109 
110     ifreq ifr;
111     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
112         return NETMANAGER_ERROR;
113     }
114     ifr.ifr_mtu = mtu;
115 
116     std::atomic_int net4Sock = socket(AF_INET, SOCK_DGRAM, 0);
117     if (net4Sock < 0) {
118         NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
119         return NETMANAGER_ERROR;
120     }
121     int32_t ret4 = SetVpnResult(net4Sock, SIOCSIFMTU, ifr);
122     close(net4Sock);
123     if (ret4 == NETMANAGER_ERROR) {
124         NETNATIVE_LOGI("set MTU failed");
125         return NETMANAGER_ERROR;
126     }
127     return NETMANAGER_SUCCESS;
128 }
129 
AddVpnRemoteAddress(const std::string & ifName,std::atomic_int & net4Sock,ifreq & ifr)130 int32_t MultiVpnManager::AddVpnRemoteAddress(const std::string &ifName, std::atomic_int &net4Sock, ifreq &ifr)
131 {
132     /* ppp need set dst ip */
133     if (strstr(ifName.c_str(), PPP_CARD_NAME) != NULL) {
134         in_addr remoteIpv4Addr = {};
135         if (inet_aton(remoteIpv4Addr_.c_str(), &remoteIpv4Addr) == 0) {
136             NETNATIVE_LOGE("addr inet_aton error");
137             return NETMANAGER_ERROR;
138         }
139         auto remoteAddr = reinterpret_cast<sockaddr_in *>(&ifr.ifr_dstaddr);
140         remoteAddr->sin_family = AF_INET;
141         remoteAddr->sin_addr = remoteIpv4Addr;
142         if (ioctl(net4Sock, SIOCSIFDSTADDR, &ifr) < 0) {
143             NETNATIVE_LOGE("ioctl set ipv4 address failed: %{public}d", errno);
144             return NETMANAGER_ERROR;
145         }
146     }
147     return NETMANAGER_SUCCESS;
148 }
149 
SetVpnAddress(const std::string & ifName,const std::string & vpnAddr,int32_t prefix)150 int32_t MultiVpnManager::SetVpnAddress(const std::string &ifName, const std::string &vpnAddr, int32_t prefix)
151 {
152     ifreq ifr = {};
153     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
154         return NETMANAGER_ERROR;
155     }
156     std::atomic_int net4Sock = socket(AF_INET, SOCK_DGRAM, 0);
157     if (net4Sock < 0) {
158         NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
159         return NETMANAGER_ERROR;
160     }
161     in_addr ipv4Addr = {};
162     if (inet_aton(vpnAddr.c_str(), &ipv4Addr) == 0) {
163         NETNATIVE_LOGE("addr inet_aton error");
164         close(net4Sock);
165         return NETMANAGER_ERROR;
166     }
167 
168     auto sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_addr);
169     sin->sin_family = AF_INET;
170     sin->sin_addr = ipv4Addr;
171     if (ioctl(net4Sock, SIOCSIFADDR, &ifr) < 0) {
172         NETNATIVE_LOGE("ioctl set ipv4 address failed: %{public}d", errno);
173         close(net4Sock);
174         return NETMANAGER_ERROR;
175     }
176     /* ppp need set dst ip */
177     if (AddVpnRemoteAddress(ifName, net4Sock, ifr) != NETMANAGER_SUCCESS) {
178         close(net4Sock);
179         return NETMANAGER_ERROR;
180     }
181     if (prefix <= 0 || prefix > NET_MASK_MAX_LENGTH) {
182         NETNATIVE_LOGE("prefix: %{public}d error", prefix);
183         close(net4Sock);
184         return NETMANAGER_ERROR;
185     }
186     in_addr_t mask = prefix ? (~0 << (NET_MASK_MAX_LENGTH - prefix)) : 0;
187     sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_netmask);
188     sin->sin_family = AF_INET;
189     sin->sin_addr.s_addr = htonl(mask);
190     if (ioctl(net4Sock, SIOCSIFNETMASK, &ifr) < 0) {
191         NETNATIVE_LOGE("ioctl set ip mask failed: %{public}d", errno);
192         close(net4Sock);
193         return NETMANAGER_ERROR;
194     }
195 
196     SetVpnUp(ifName);
197     close(net4Sock);
198     NETNATIVE_LOGI("set ip address success");
199     return NETMANAGER_SUCCESS;
200 }
201 
SetVpnUp(const std::string & ifName)202 int32_t MultiVpnManager::SetVpnUp(const std::string &ifName)
203 {
204     ifreq ifr = {};
205     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
206         return NETMANAGER_ERROR;
207     }
208     ifr.ifr_flags = IFF_UP | IFF_NOARP;
209     std::atomic_int net4Sock = socket(AF_INET, SOCK_DGRAM, 0);
210     if (net4Sock < 0) {
211         NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
212         return NETMANAGER_ERROR;
213     }
214     int32_t ret4 = SetVpnResult(net4Sock, SIOCSIFFLAGS, ifr);
215     close(net4Sock);
216     if (ret4 == NETMANAGER_ERROR) {
217         NETNATIVE_LOGI("set iff up failed");
218         return NETMANAGER_ERROR;
219     }
220     return NETMANAGER_SUCCESS;
221 }
222 
SetVpnDown(const std::string & ifName)223 int32_t MultiVpnManager::SetVpnDown(const std::string &ifName)
224 {
225     ifreq ifr = {};
226     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
227         return NETMANAGER_ERROR;
228     }
229     ifr.ifr_flags &= ~IFF_UP;
230     std::atomic_int net4Sock = socket(AF_INET, SOCK_DGRAM, 0);
231     if (net4Sock < 0) {
232         NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
233         return NETMANAGER_ERROR;
234     }
235     int32_t ret4 = SetVpnResult(net4Sock, SIOCSIFFLAGS, ifr);
236     close(net4Sock);
237     if (ret4 == NETMANAGER_ERROR) {
238         NETNATIVE_LOGI("set iff down failed");
239         return NETMANAGER_ERROR;
240     }
241     return NETMANAGER_SUCCESS;
242 }
243 
CreateVpnInterface(const std::string & ifName)244 int32_t MultiVpnManager::CreateVpnInterface(const std::string &ifName)
245 {
246     int32_t ret = NETMANAGER_SUCCESS;
247     if (strstr(ifName.c_str(), XFRM_CARD_NAME) != NULL) {
248         uint32_t ifNameId = CommonUtils::StrToUint(ifName.substr(strlen(XFRM_CARD_NAME)));
249         ret = nmd::CreateVpnIfByNetlink(ifName.c_str(), ifNameId, phyName_.c_str(), DEFAULT_MTU);
250     } else if (strstr(ifName.c_str(), PPP_CARD_NAME) != NULL) {
251         ret = CreatePppInterface(ifName);
252     } else if (strstr(ifName.c_str(), MULTI_TUN_CARD_NAME) != NULL) {
253         ret = CreateMultiTunInterface(ifName);
254     } else {
255         NETNATIVE_LOGE("CreateVpnInterface failed, invalid ifName");
256         return NETMANAGER_ERROR;
257     }
258     return ret;
259 }
260 
DestroyVpnInterface(const std::string & ifName)261 int32_t MultiVpnManager::DestroyVpnInterface(const std::string &ifName)
262 {
263     NETNATIVE_LOGI("destroy vpn interface:%{public}s", ifName.c_str());
264     bool isXfrm = strstr(ifName.c_str(), XFRM_CARD_NAME) != NULL;
265     bool isPpp = strstr(ifName.c_str(), PPP_CARD_NAME) != NULL;
266     bool isMultiTun = strstr(ifName.c_str(), MULTI_TUN_CARD_NAME) != NULL;
267     if (!isXfrm && !isPpp && !isMultiTun) {
268         NETNATIVE_LOGE("DestroyVpnInterface failed, invalid ifName");
269         return NETMANAGER_ERROR;
270     }
271     SetVpnDown(ifName);
272     nmd::DeleteVpnIfByNetlink(ifName.c_str());
273     if (isPpp || isMultiTun) {
274         DestroyMultiVpnFd(ifName);
275     }
276     return NETMANAGER_SUCCESS;
277 }
278 
CreatePppInterface(const std::string & ifName)279 int32_t MultiVpnManager::CreatePppInterface(const std::string &ifName)
280 {
281     auto it = multiVpnFdMap_.find(ifName);
282     if (it == multiVpnFdMap_.end()) {
283         NETNATIVE_LOGE("ifName not exist");
284         return NETMANAGER_ERROR;
285     }
286     ifreq ifr = {};
287     if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
288         NETNATIVE_LOGE("memset_s ifr failed!");
289         return NETMANAGER_ERROR;
290     }
291     int32_t currentIfunit = 0;
292     if (ioctl(multiVpnFdMap_[ifName], PPPIOCGUNIT, &currentIfunit) < 0) {
293         NETNATIVE_LOGE("ioctl PPPIOCDISCONN failed errno: %{public}d", errno);
294     }
295     NETNATIVE_LOGI("Created PPP interface: currentIfunit:%{public}d\n", currentIfunit);
296     std::string oldName = "ppp" + std::to_string(currentIfunit);
297     SetVpnDown(oldName);
298     if (strncpy_s(ifr.ifr_name, IFNAMSIZ, oldName.c_str(), strlen(oldName.c_str())) != EOK) {
299         NETNATIVE_LOGE("strcpy_s ifr name fail");
300         return NETMANAGER_ERROR;
301     }
302     ifr.ifr_name[IFNAMSIZ - 1] = '\0';
303     if (strncpy_s(ifr.ifr_newname, IFNAMSIZ, ifName.c_str(), strlen(ifName.c_str())) != EOK) {
304         NETNATIVE_LOGE("strcpy_s ifr name fail");
305         return NETMANAGER_ERROR;
306     }
307     ifr.ifr_newname[IFNAMSIZ - 1] = '\0';
308     std::atomic_int net4Sock = socket(AF_INET, SOCK_DGRAM, 0);
309     if (net4Sock < 0) {
310         NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
311         return NETMANAGER_ERROR;
312     }
313     int32_t ioRet = ioctl(net4Sock, SIOCSIFNAME, &ifr);
314     close(net4Sock);
315     if (ioRet < 0) {
316         NETNATIVE_LOGE("ioctl failed errno: %{public}d", errno);
317         return NETMANAGER_ERROR;
318     }
319     NETNATIVE_LOGI("Created PPP interface");
320     return NETMANAGER_SUCCESS;
321 }
322 
CreatePppFd(const std::string & ifName)323 void MultiVpnManager::CreatePppFd(const std::string &ifName)
324 {
325     if (strstr(ifName.c_str(), PPP_CARD_NAME) == NULL) {
326         NETNATIVE_LOGE("CreatePppFd failed");
327         return;
328     }
329     multiVpnListeningName_ = ifName;
330     StartMultiVpnInterfaceFdListen();
331 }
332 
CreateMultiTunInterface(const std::string & ifName)333 int32_t MultiVpnManager::CreateMultiTunInterface(const std::string &ifName)
334 {
335     int32_t multiVpnFd = 0;
336     if (GetMultiVpnFd(ifName, multiVpnFd) != NETMANAGER_SUCCESS) {
337         return NETMANAGER_ERROR;
338     }
339 
340     ifreq ifr = {};
341     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
342         return NETMANAGER_ERROR;
343     }
344 
345     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
346     if (ioctl(multiVpnFd, TUNSETIFF, &ifr) < 0) {
347         NETNATIVE_LOGE("multi tun set iff error: %{public}d", errno);
348         return NETMANAGER_ERROR;
349     }
350     multiVpnListeningName_ = ifName;
351     StartMultiVpnInterfaceFdListen();
352     return NETMANAGER_SUCCESS;
353 }
354 
GetMultiVpnFd(const std::string & ifName,int32_t & multiVpnFd)355 int32_t MultiVpnManager::GetMultiVpnFd(const std::string &ifName, int32_t &multiVpnFd)
356 {
357     std::lock_guard<std::mutex> autoLock(mutex_);
358     auto it = multiVpnFdMap_.find(ifName);
359     if (it != multiVpnFdMap_.end()) {
360         NETNATIVE_LOGE("ifName already exist");
361         multiVpnFd = it->second.load();
362         return NETMANAGER_SUCCESS;
363     }
364     if (strstr(ifName.c_str(), PPP_CARD_NAME) != NULL) {
365         multiVpnFd = open(PPP_DEVICE_PATH, O_RDWR | O_NONBLOCK | O_CLOEXEC);
366     } else if (strstr(ifName.c_str(), MULTI_TUN_CARD_NAME) != NULL) {
367         multiVpnFd = open(TUN_DEVICE_PATH, O_RDWR | O_NONBLOCK | O_CLOEXEC);
368     } else {
369         NETNATIVE_LOGE("GetMultiVpnFd faild, IfName err");
370         return NETMANAGER_ERROR;
371     }
372     if (multiVpnFd <= 0) {
373         NETNATIVE_LOGE("open virtual device failed: %{public}d", errno);
374         return NETMANAGER_ERROR;
375     }
376     multiVpnFdMap_[ifName] = multiVpnFd;
377     return NETMANAGER_SUCCESS;
378 }
379 
SetVpnRemoteAddress(const std::string & remoteIp)380 void MultiVpnManager::SetVpnRemoteAddress(const std::string &remoteIp)
381 {
382     remoteIpv4Addr_ = remoteIp;
383 }
384 
DestroyMultiVpnFd(const std::string & ifName)385 int32_t MultiVpnManager::DestroyMultiVpnFd(const std::string &ifName)
386 {
387     std::lock_guard<std::mutex> autoLock(mutex_);
388     if (strstr(ifName.c_str(), PPP_CARD_NAME) == NULL && strstr(ifName.c_str(), MULTI_TUN_CARD_NAME) == NULL) {
389         NETNATIVE_LOGE("DestroyMultiVpnFd faild, IfName err");
390         return NETMANAGER_ERROR;
391     }
392     auto it = multiVpnFdMap_.find(ifName);
393     if (it == multiVpnFdMap_.end()) {
394         NETNATIVE_LOGE("ifName not exist");
395         return NETMANAGER_ERROR;
396     }
397     auto multiVpnFd = it->second.load();
398     if (multiVpnFd != 0) {
399         close(multiVpnFd);
400     }
401     multiVpnFdMap_.erase(it);
402     return NETMANAGER_SUCCESS;
403 }
404 
StartMultiVpnInterfaceFdListen()405 void MultiVpnManager::StartMultiVpnInterfaceFdListen()
406 {
407     if (multiVpnListeningFlag_) {
408         NETNATIVE_LOGI("MultiVpnInterface fd is listening...");
409         return;
410     }
411     NETNATIVE_LOGI("StartMultiVpnInterfaceFdListen...");
412     multiVpnListeningFlag_ = true;
413     std::thread t([sp = shared_from_this()]() { sp->StartMultiVpnSocketListen(); });
414     t.detach();
415     pthread_setname_np(t.native_handle(), "unix_socket_multivpnfd");
416 }
417 
StartMultiVpnSocketListen()418 void MultiVpnManager::StartMultiVpnSocketListen()
419 {
420     NETNATIVE_LOGI("StartMultiVpnSocketListen...");
421     int32_t serverfd = GetControlSocket("multivpnfd");
422     if (listen(serverfd, MAX_UNIX_SOCKET_CLIENT) < 0) {
423         multiVpnListeningFlag_ = false;
424         NETNATIVE_LOGE("listen socket error: %{public}d", errno);
425         return;
426     }
427 
428     sockaddr_in clientAddr;
429     socklen_t len = sizeof(clientAddr);
430     int32_t clientFd = accept(serverfd, reinterpret_cast<sockaddr *>(&clientAddr), &len);
431     if (clientFd < 0) {
432         NETNATIVE_LOGE("accept socket error: %{public}d", errno);
433         multiVpnListeningFlag_ = false;
434         return;
435     }
436     int32_t multiVpnFd = -1;
437     if (GetMultiVpnFd(multiVpnListeningName_, multiVpnFd) == NETMANAGER_SUCCESS) {
438         SendVpnInterfaceFdToClient(clientFd, multiVpnFd);
439     }
440     multiVpnListeningFlag_ = false;
441     close(clientFd);
442 }
443 
SetXfrmPhyIfName(const std::string & phyName)444 void MultiVpnManager::SetXfrmPhyIfName(const std::string &phyName)
445 {
446     phyName_ = phyName;
447 }
448 
SetVpnCallMode(const std::string & message)449 int32_t MultiVpnManager::SetVpnCallMode(const std::string &message)
450 {
451     if (message.empty()) {
452         NETNATIVE_LOGE("message is empty");
453         return NETMANAGER_ERROR;
454     }
455     return nmd::RouteManager::SetVpnCallMode(message);
456 }
457 } // namespace NetManagerStandard
458 } // namespace OHOS
459