1 /*
2  * Copyright (c) 2024 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 "vnic_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 <linux/ipv6.h>
23 #include <netinet/in.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <sys/un.h>
28 #include <thread>
29 #include <unistd.h>
30 
31 #include "init_socket.h"
32 #include "net_manager_constants.h"
33 #include "netmanager_base_common_utils.h"
34 #include "netnative_log_wrapper.h"
35 #include "route_manager.h"
36 #include "securec.h"
37 
38 #include "uid_range.h"
39 
40 namespace OHOS {
41 namespace NetManagerStandard {
42 
43 namespace {
44 constexpr const char *VNIC_TUN_CARD_NAME = "vnic-tun";
45 constexpr const char *VNIC_TUN_DEVICE_PATH = "/dev/tun";
46 constexpr int32_t NET_MASK_MAX_LENGTH = 32;
47 constexpr uint32_t MAX_VNIC_UID_ARRAY_SIZE = 20;
48 } // namespace
49 
50 
GetNetSock(bool ipv4)51 std::atomic_int& VnicManager::GetNetSock(bool ipv4)
52 {
53     if (ipv4) {
54         if (net4Sock_ < 0) {
55             net4Sock_ = socket(AF_INET, SOCK_DGRAM, 0);
56         }
57         return net4Sock_;
58     } else {
59         if (net6Sock_ < 0) {
60             net6Sock_ = socket(AF_INET6, SOCK_DGRAM, 0);
61         }
62         return net6Sock_;
63     }
64 }
65 
CreateVnicInterface()66 int32_t VnicManager::CreateVnicInterface()
67 {
68     if (tunFd_ != 0) {
69         return NETMANAGER_SUCCESS;
70     }
71 
72     ifreq ifr{};
73     if (InitIfreq(ifr, VNIC_TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
74         return NETMANAGER_ERROR;
75     }
76 
77     int32_t tunfd = open(VNIC_TUN_DEVICE_PATH, O_RDWR | O_NONBLOCK);
78     if (tunfd <= 0) {
79         NETNATIVE_LOGE("open virtual device failed: %{public}d", errno);
80         return NETMANAGER_ERROR;
81     }
82 
83     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
84     if (ioctl(tunfd, TUNSETIFF, &ifr) < 0) {
85         close(tunfd);
86         NETNATIVE_LOGE("tun set iff error: %{public}d", errno);
87         return NETMANAGER_ERROR;
88     }
89 
90     net4Sock_ = socket(AF_INET, SOCK_DGRAM, 0);
91     if (net4Sock_ < 0) {
92         NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
93     }
94     net6Sock_ = socket(AF_INET6, SOCK_DGRAM, 0);
95     if (net6Sock_ < 0) {
96         NETNATIVE_LOGE("create SOCK_DGRAM ipv6 failed: %{public}d", errno);
97     }
98     if (net4Sock_ < 0 && net6Sock_ < 0) {
99         close(tunfd);
100         NETNATIVE_LOGE("create SOCK_DGRAM ip failed");
101         return NETMANAGER_ERROR;
102     }
103 
104     NETNATIVE_LOGI("open virtual device successfully, [%{public}d]", tunfd);
105     tunFd_ = tunfd;
106     SetVnicUp();
107     return NETMANAGER_SUCCESS;
108 }
109 
DestroyVnicInterface()110 void VnicManager::DestroyVnicInterface()
111 {
112     SetVnicDown();
113     if (net4Sock_ != 0) {
114         close(net4Sock_);
115         net4Sock_ = 0;
116     }
117     if (net6Sock_ != 0) {
118         close(net6Sock_);
119         net6Sock_ = 0;
120     }
121     if (tunFd_ != 0) {
122         close(tunFd_);
123         tunFd_ = 0;
124     }
125 }
126 
SetVnicResult(std::atomic_int & fd,unsigned long cmd,ifreq & ifr)127 int32_t VnicManager::SetVnicResult(std::atomic_int &fd, unsigned long cmd, ifreq &ifr)
128 {
129     if (fd > 0) {
130         if (ioctl(fd, cmd, &ifr) < 0) {
131             NETNATIVE_LOGE("set vnic error, errno:%{public}d", errno);
132             return NETMANAGER_ERROR;
133         }
134     }
135     return NETMANAGER_SUCCESS;
136 }
137 
SetVnicMtu(const std::string & ifName,int32_t mtu)138 int32_t VnicManager::SetVnicMtu(const std::string &ifName, int32_t mtu)
139 {
140     if (mtu <= 0) {
141         NETNATIVE_LOGE("invalid mtu value");
142         return NETMANAGER_ERROR;
143     }
144 
145     ifreq ifr;
146     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
147         return NETMANAGER_ERROR;
148     }
149 
150     ifr.ifr_mtu = mtu;
151     int32_t ret4 = SetVnicResult(GetNetSock(true), SIOCSIFMTU, ifr);
152     int32_t ret6 = SetVnicResult(GetNetSock(false), SIOCSIFMTU, ifr);
153     if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (GetNetSock(true) < 0 && GetNetSock(false) < 0)) {
154         NETNATIVE_LOGI("set MTU failed");
155         return NETMANAGER_ERROR;
156     } else {
157         NETNATIVE_LOGI("set MTU success");
158         return NETMANAGER_SUCCESS;
159     }
160 }
161 
SetVnicAddress(const std::string & ifName,const std::string & tunAddr,int32_t prefix)162 int32_t VnicManager::SetVnicAddress(const std::string &ifName, const std::string &tunAddr, int32_t prefix)
163 {
164     ifreq ifr{};
165     if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
166         return NETMANAGER_ERROR;
167     }
168 
169     bool isIpv6 = CommonUtils::IsValidIPV6(tunAddr);
170     if (isIpv6) {
171         struct in6_ifreq ifr6 = {};
172         if (ioctl(GetNetSock(false), SIOCGIFINDEX, &ifr) <0) {
173             NETNATIVE_LOGE(" get network interface ipv6 failed: %{public}d", errno);
174             return NETMANAGER_ERROR;
175         }
176         if (inet_pton(AF_INET6, tunAddr.c_str(), &ifr6.ifr6_addr) == 0) {
177             NETNATIVE_LOGE("inet_pton ipv6 address failed: %{public}d", errno);
178         }
179         ifr6.ifr6_prefixlen = static_cast<uint32_t>(prefix);
180         ifr6.ifr6_ifindex = ifr.ifr_ifindex;
181         if (ioctl(GetNetSock(false), SIOCSIFADDR, &ifr6) < 0) {
182             NETNATIVE_LOGE("ioctl set ipv6 address failed: %{public}d", errno);
183             return NETMANAGER_ERROR;
184         }
185     } else {
186         in_addr ipv4Addr = {};
187         if (inet_aton(tunAddr.c_str(), &ipv4Addr) == 0) {
188             NETNATIVE_LOGE("addr inet_aton error");
189             return NETMANAGER_ERROR;
190         }
191 
192         auto sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_addr);
193         sin->sin_family = AF_INET;
194         sin->sin_addr = ipv4Addr;
195         if (ioctl(GetNetSock(true), SIOCSIFADDR, &ifr) < 0) {
196             NETNATIVE_LOGE("ioctl set ipv4 address failed: %{public}d", errno);
197             return NETMANAGER_ERROR;
198         }
199 
200         if (prefix <= 0 || prefix >= NET_MASK_MAX_LENGTH) {
201             NETNATIVE_LOGE("prefix: %{public}d error", prefix);
202             return NETMANAGER_ERROR;
203         }
204         in_addr_t mask = prefix ? (0xFFFFFFFF << (NET_MASK_MAX_LENGTH - prefix)) : 0;
205         sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_netmask);
206         sin->sin_family = AF_INET;
207         sin->sin_addr.s_addr = htonl(mask);
208         if (ioctl(GetNetSock(true), SIOCSIFNETMASK, &ifr) < 0) {
209             NETNATIVE_LOGE("ioctl set ip mask failed: %{public}d", errno);
210             return NETMANAGER_ERROR;
211         }
212     }
213 
214     NETNATIVE_LOGI("set ip address success");
215     return NETMANAGER_SUCCESS;
216 }
217 
SetVnicUp()218 int32_t VnicManager::SetVnicUp()
219 {
220     ifreq ifr{};
221     if (InitIfreq(ifr, VNIC_TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
222         return NETMANAGER_ERROR;
223     }
224 
225     ifr.ifr_flags = IFF_UP;
226     int32_t ret4 = SetVnicResult(GetNetSock(true), SIOCSIFFLAGS, ifr);
227     int32_t ret6 = SetVnicResult(GetNetSock(false), SIOCSIFFLAGS, ifr);
228     if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (GetNetSock(true) < 0 && GetNetSock(false) < 0)) {
229         NETNATIVE_LOGI("set iff up failed");
230         return NETMANAGER_ERROR;
231     } else {
232         NETNATIVE_LOGI("set iff up success");
233         return NETMANAGER_SUCCESS;
234     }
235 }
236 
SetVnicDown()237 int32_t VnicManager::SetVnicDown()
238 {
239     ifreq ifr{};
240     if (InitIfreq(ifr, VNIC_TUN_CARD_NAME) != NETMANAGER_SUCCESS) {
241         return NETMANAGER_ERROR;
242     }
243 
244     ifr.ifr_flags = (uint16_t)ifr.ifr_flags & ~IFF_UP;
245     int32_t ret4 = SetVnicResult(GetNetSock(true), SIOCSIFFLAGS, ifr);
246     int32_t ret6 = SetVnicResult(GetNetSock(false), SIOCSIFFLAGS, ifr);
247     if (ret4 == NETMANAGER_ERROR || ret6 == NETMANAGER_ERROR || (GetNetSock(true) < 0 && GetNetSock(false) < 0)) {
248         NETNATIVE_LOGI("set iff down failed");
249         return NETMANAGER_ERROR;
250     } else {
251         NETNATIVE_LOGI("set iff down success");
252         return NETMANAGER_SUCCESS;
253     }
254 }
255 
AddDefaultRoute()256 int32_t VnicManager::AddDefaultRoute()
257 {
258     const std::string interface = VNIC_TUN_CARD_NAME;
259     const std::string destinationName = "0.0.0.0/0";
260     const std::string nextHop = "0.0.0.0";
261     return nmd::RouteManager::UpdateVnicRoute(interface, destinationName, nextHop, true);
262 }
263 
DelDefaultRoute()264 int32_t VnicManager::DelDefaultRoute()
265 {
266     const std::string interface = VNIC_TUN_CARD_NAME;
267     const std::string destinationName = "0.0.0.0/0";
268     const std::string nextHop = "0.0.0.0";
269     return nmd::RouteManager::UpdateVnicRoute(interface, destinationName, nextHop, false);
270 }
271 
InitIfreq(ifreq & ifr,const std::string & cardName)272 int32_t VnicManager::InitIfreq(ifreq &ifr, const std::string &cardName)
273 {
274     if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
275         NETNATIVE_LOGE("memset_s ifr failed!");
276         return NETMANAGER_ERROR;
277     }
278     if (strncpy_s(ifr.ifr_name, IFNAMSIZ, cardName.c_str(), strlen(cardName.c_str())) != EOK) {
279         NETNATIVE_LOGE("strcpy_s ifr name fail");
280         return NETMANAGER_ERROR;
281     }
282     return NETMANAGER_SUCCESS;
283 }
284 
CreateVnic(uint16_t mtu,const std::string & tunAddr,int32_t prefix,const std::set<int32_t> & uids)285 int32_t VnicManager::CreateVnic(uint16_t mtu, const std::string &tunAddr, int32_t prefix,
286                                 const std::set<int32_t> &uids)
287 {
288     uidRanges.clear();
289     for (const auto &uid: uids) {
290         uidRanges.push_back({uid, uid});
291     }
292 
293     if (uidRanges.size() > MAX_VNIC_UID_ARRAY_SIZE) {
294         NETNATIVE_LOGE("vnic uidRanges's size is over the max size.");
295         uidRanges.clear();
296         return NETMANAGER_ERROR;
297     }
298 
299     if (CreateVnicInterface() != NETMANAGER_SUCCESS) {
300         return NETMANAGER_ERROR;
301     }
302     if (SetVnicMtu(VNIC_TUN_CARD_NAME, mtu) != NETMANAGER_SUCCESS ||
303         SetVnicAddress(VNIC_TUN_CARD_NAME, tunAddr, prefix) != NETMANAGER_SUCCESS ||
304         AddDefaultRoute() != NETMANAGER_SUCCESS) {
305         DestroyVnicInterface();
306         return NETMANAGER_ERROR;
307     }
308 
309     if (!uidRanges.empty() &&
310         nmd::RouteManager::UpdateVnicUidRangesRule(uidRanges, true) != NETMANAGER_SUCCESS) {
311         uidRanges.clear();
312         DelDefaultRoute();
313         DestroyVnicInterface();
314         return NETMANAGER_ERROR;
315     }
316 
317     return NETMANAGER_SUCCESS;
318 }
319 
DestroyVnic()320 int32_t VnicManager::DestroyVnic()
321 {
322     nmd::RouteManager::UpdateVnicUidRangesRule(uidRanges, false);
323     uidRanges.clear();
324     DelDefaultRoute();
325     DestroyVnicInterface();
326     return NETMANAGER_SUCCESS;
327 }
328 
329 } // namespace NetManagerStandard
330 } // namespace OHOS
331