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