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