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