1b1b8bc3fSopenharmony_ci/*
2b1b8bc3fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3b1b8bc3fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1b8bc3fSopenharmony_ci * you may not use this file except in compliance with the License.
5b1b8bc3fSopenharmony_ci * You may obtain a copy of the License at
6b1b8bc3fSopenharmony_ci *
7b1b8bc3fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8b1b8bc3fSopenharmony_ci *
9b1b8bc3fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1b8bc3fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1b8bc3fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1b8bc3fSopenharmony_ci * See the License for the specific language governing permissions and
13b1b8bc3fSopenharmony_ci * limitations under the License.
14b1b8bc3fSopenharmony_ci */
15b1b8bc3fSopenharmony_ci
16b1b8bc3fSopenharmony_ci#include "distributed_manager.h"
17b1b8bc3fSopenharmony_ci
18b1b8bc3fSopenharmony_ci#include <arpa/inet.h>
19b1b8bc3fSopenharmony_ci#include <fcntl.h>
20b1b8bc3fSopenharmony_ci#include <linux/if.h>
21b1b8bc3fSopenharmony_ci#include <linux/if_tun.h>
22b1b8bc3fSopenharmony_ci#include <linux/ipv6.h>
23b1b8bc3fSopenharmony_ci#include <netinet/in.h>
24b1b8bc3fSopenharmony_ci#include <sys/ioctl.h>
25b1b8bc3fSopenharmony_ci#include <sys/socket.h>
26b1b8bc3fSopenharmony_ci#include <sys/types.h>
27b1b8bc3fSopenharmony_ci#include <sys/un.h>
28b1b8bc3fSopenharmony_ci#include <thread>
29b1b8bc3fSopenharmony_ci#include <unistd.h>
30b1b8bc3fSopenharmony_ci
31b1b8bc3fSopenharmony_ci#include "init_socket.h"
32b1b8bc3fSopenharmony_ci#include "net_manager_constants.h"
33b1b8bc3fSopenharmony_ci#include "netmanager_base_common_utils.h"
34b1b8bc3fSopenharmony_ci#include "netnative_log_wrapper.h"
35b1b8bc3fSopenharmony_ci#include "securec.h"
36b1b8bc3fSopenharmony_ci
37b1b8bc3fSopenharmony_cinamespace OHOS {
38b1b8bc3fSopenharmony_cinamespace NetManagerStandard {
39b1b8bc3fSopenharmony_ci
40b1b8bc3fSopenharmony_cinamespace {
41b1b8bc3fSopenharmony_ciconstexpr const char *DISTRIBUTED_TUN_DEVICE_PATH = "/dev/tun";
42b1b8bc3fSopenharmony_ciconstexpr int32_t NET_MASK_MAX_LENGTH = 32;
43b1b8bc3fSopenharmony_ciconstexpr int32_t DISTRIBUTED_MTU = 1400;
44b1b8bc3fSopenharmony_ci} // namespace
45b1b8bc3fSopenharmony_ci
46b1b8bc3fSopenharmony_ciint32_t DistributedManager::CreateDistributedInterface(const std::string &ifName)
47b1b8bc3fSopenharmony_ci{
48b1b8bc3fSopenharmony_ci    net4Sock_ = socket(AF_INET, SOCK_DGRAM, 0);
49b1b8bc3fSopenharmony_ci    if (net4Sock_ < 0) {
50b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("create SOCK_DGRAM ipv4 failed: %{public}d", errno);
51b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
52b1b8bc3fSopenharmony_ci    }
53b1b8bc3fSopenharmony_ci
54b1b8bc3fSopenharmony_ci    if (tunFd_ != 0) {
55b1b8bc3fSopenharmony_ci        return NETMANAGER_SUCCESS;
56b1b8bc3fSopenharmony_ci    }
57b1b8bc3fSopenharmony_ci
58b1b8bc3fSopenharmony_ci    ifreq ifr{};
59b1b8bc3fSopenharmony_ci    if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
60b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
61b1b8bc3fSopenharmony_ci    }
62b1b8bc3fSopenharmony_ci
63b1b8bc3fSopenharmony_ci    int32_t tunfd = open(DISTRIBUTED_TUN_DEVICE_PATH, O_RDWR | O_NONBLOCK);
64b1b8bc3fSopenharmony_ci    if (tunfd <= 0) {
65b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("open virtual distributed nic failed: %{public}d", errno);
66b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
67b1b8bc3fSopenharmony_ci    }
68b1b8bc3fSopenharmony_ci
69b1b8bc3fSopenharmony_ci    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
70b1b8bc3fSopenharmony_ci    if (ioctl(tunfd, TUNSETIFF, &ifr) < 0) {
71b1b8bc3fSopenharmony_ci        close(tunfd);
72b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("tun set iff error: %{public}d", errno);
73b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
74b1b8bc3fSopenharmony_ci    }
75b1b8bc3fSopenharmony_ci
76b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("create virtual device successfully, [%{public}d]", tunfd);
77b1b8bc3fSopenharmony_ci    tunFd_ = tunfd;
78b1b8bc3fSopenharmony_ci
79b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
80b1b8bc3fSopenharmony_ci}
81b1b8bc3fSopenharmony_ci
82b1b8bc3fSopenharmony_ciint32_t DistributedManager::SetDistributedNicResult(std::atomic_int &fd, unsigned long cmd, ifreq &ifr)
83b1b8bc3fSopenharmony_ci{
84b1b8bc3fSopenharmony_ci    if (fd > 0) {
85b1b8bc3fSopenharmony_ci        if (ioctl(fd, cmd, &ifr) < 0) {
86b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("set virnic error, errno:%{public}d", errno);
87b1b8bc3fSopenharmony_ci            return NETMANAGER_ERROR;
88b1b8bc3fSopenharmony_ci        }
89b1b8bc3fSopenharmony_ci        return NETMANAGER_SUCCESS;
90b1b8bc3fSopenharmony_ci    }
91b1b8bc3fSopenharmony_ci    return NETMANAGER_ERROR;
92b1b8bc3fSopenharmony_ci}
93b1b8bc3fSopenharmony_ci
94b1b8bc3fSopenharmony_ciint32_t DistributedManager::InitIfreq(ifreq &ifr, const std::string &cardName)
95b1b8bc3fSopenharmony_ci{
96b1b8bc3fSopenharmony_ci    if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
97b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("memset_s ifr failed!");
98b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
99b1b8bc3fSopenharmony_ci    }
100b1b8bc3fSopenharmony_ci    if (strncpy_s(ifr.ifr_name, IFNAMSIZ, cardName.c_str(), strlen(cardName.c_str())) != EOK) {
101b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("strcpy_s ifr name fail");
102b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
103b1b8bc3fSopenharmony_ci    }
104b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
105b1b8bc3fSopenharmony_ci}
106b1b8bc3fSopenharmony_ci
107b1b8bc3fSopenharmony_ciint32_t DistributedManager::SetDistributedNicMtu(const std::string &ifName, int32_t mtu)
108b1b8bc3fSopenharmony_ci{
109b1b8bc3fSopenharmony_ci    if (mtu <= 0) {
110b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("invalid mtu value");
111b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
112b1b8bc3fSopenharmony_ci    }
113b1b8bc3fSopenharmony_ci
114b1b8bc3fSopenharmony_ci    ifreq ifr{};
115b1b8bc3fSopenharmony_ci    if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
116b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
117b1b8bc3fSopenharmony_ci    }
118b1b8bc3fSopenharmony_ci
119b1b8bc3fSopenharmony_ci    ifr.ifr_mtu = mtu;
120b1b8bc3fSopenharmony_ci    int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFMTU, ifr);
121b1b8bc3fSopenharmony_ci    if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
122b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("set MTU failed");
123b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
124b1b8bc3fSopenharmony_ci    } else {
125b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("set MTU success");
126b1b8bc3fSopenharmony_ci        return NETMANAGER_SUCCESS;
127b1b8bc3fSopenharmony_ci    }
128b1b8bc3fSopenharmony_ci}
129b1b8bc3fSopenharmony_ci
130b1b8bc3fSopenharmony_ciint32_t DistributedManager::SetDistributedNicAddress(const std::string &ifName, const std::string &tunAddr)
131b1b8bc3fSopenharmony_ci{
132b1b8bc3fSopenharmony_ci    ifreq ifr{};
133b1b8bc3fSopenharmony_ci    if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
134b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
135b1b8bc3fSopenharmony_ci    }
136b1b8bc3fSopenharmony_ci
137b1b8bc3fSopenharmony_ci    bool isIpv6 = CommonUtils::IsValidIPV6(tunAddr);
138b1b8bc3fSopenharmony_ci    if (isIpv6) {
139b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("distributed nic not support ipv6 by now");
140b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
141b1b8bc3fSopenharmony_ci    } else {
142b1b8bc3fSopenharmony_ci        in_addr ipv4Addr = {};
143b1b8bc3fSopenharmony_ci        if (inet_aton(tunAddr.c_str(), &ipv4Addr) == 0) {
144b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("addr inet_aton error");
145b1b8bc3fSopenharmony_ci            return NETMANAGER_ERROR;
146b1b8bc3fSopenharmony_ci        }
147b1b8bc3fSopenharmony_ci
148b1b8bc3fSopenharmony_ci        auto sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_addr);
149b1b8bc3fSopenharmony_ci        sin->sin_family = AF_INET;
150b1b8bc3fSopenharmony_ci        sin->sin_addr = ipv4Addr;
151b1b8bc3fSopenharmony_ci        if (ioctl(net4Sock_, SIOCSIFADDR, &ifr) < 0) {
152b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("ioctl set ipv4 address failed: %{public}d", errno);
153b1b8bc3fSopenharmony_ci            return NETMANAGER_ERROR;
154b1b8bc3fSopenharmony_ci        }
155b1b8bc3fSopenharmony_ci
156b1b8bc3fSopenharmony_ci        int32_t prefix = NET_MASK_MAX_LENGTH;
157b1b8bc3fSopenharmony_ci        in_addr_t mask = prefix ? (0xFFFFFFFF << (NET_MASK_MAX_LENGTH - prefix)) : 0;
158b1b8bc3fSopenharmony_ci        sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_netmask);
159b1b8bc3fSopenharmony_ci        sin->sin_family = AF_INET;
160b1b8bc3fSopenharmony_ci        sin->sin_addr.s_addr = htonl(mask);
161b1b8bc3fSopenharmony_ci        if (ioctl(net4Sock_, SIOCSIFNETMASK, &ifr) < 0) {
162b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("ioctl set ip mask failed: %{public}d", errno);
163b1b8bc3fSopenharmony_ci            return NETMANAGER_ERROR;
164b1b8bc3fSopenharmony_ci        }
165b1b8bc3fSopenharmony_ci    }
166b1b8bc3fSopenharmony_ci
167b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("set ip address success");
168b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
169b1b8bc3fSopenharmony_ci}
170b1b8bc3fSopenharmony_ci
171b1b8bc3fSopenharmony_ciint32_t DistributedManager::SetDistributedNicUp(const std::string &ifName)
172b1b8bc3fSopenharmony_ci{
173b1b8bc3fSopenharmony_ci    ifreq ifr{};
174b1b8bc3fSopenharmony_ci    if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
175b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
176b1b8bc3fSopenharmony_ci    }
177b1b8bc3fSopenharmony_ci
178b1b8bc3fSopenharmony_ci    ifr.ifr_flags = static_cast<uint16_t>(IFF_UP | IFF_NOARP);
179b1b8bc3fSopenharmony_ci
180b1b8bc3fSopenharmony_ci    int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFFLAGS, ifr);
181b1b8bc3fSopenharmony_ci    if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
182b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("set iff up failed");
183b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
184b1b8bc3fSopenharmony_ci    } else {
185b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("set iff up success");
186b1b8bc3fSopenharmony_ci        return NETMANAGER_SUCCESS;
187b1b8bc3fSopenharmony_ci    }
188b1b8bc3fSopenharmony_ci}
189b1b8bc3fSopenharmony_ci
190b1b8bc3fSopenharmony_ciint32_t DistributedManager::SetDistributedNicDown(const std::string &ifName)
191b1b8bc3fSopenharmony_ci{
192b1b8bc3fSopenharmony_ci    ifreq ifr{};
193b1b8bc3fSopenharmony_ci    if (InitIfreq(ifr, ifName) != NETMANAGER_SUCCESS) {
194b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
195b1b8bc3fSopenharmony_ci    }
196b1b8bc3fSopenharmony_ci
197b1b8bc3fSopenharmony_ci    ifr.ifr_flags = (uint16_t)ifr.ifr_flags & ~IFF_UP;
198b1b8bc3fSopenharmony_ci    int32_t ret4 = SetDistributedNicResult(net4Sock_, SIOCSIFFLAGS, ifr);
199b1b8bc3fSopenharmony_ci    if (ret4 == NETMANAGER_ERROR || (net4Sock_ < 0)) {
200b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("set iff down failed");
201b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
202b1b8bc3fSopenharmony_ci    } else {
203b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("set iff down success");
204b1b8bc3fSopenharmony_ci        return NETMANAGER_SUCCESS;
205b1b8bc3fSopenharmony_ci    }
206b1b8bc3fSopenharmony_ci}
207b1b8bc3fSopenharmony_ci
208b1b8bc3fSopenharmony_civoid DistributedManager::CloseDistributedSocket()
209b1b8bc3fSopenharmony_ci{
210b1b8bc3fSopenharmony_ci    if (net4Sock_ > 0) {
211b1b8bc3fSopenharmony_ci        close(net4Sock_);
212b1b8bc3fSopenharmony_ci        net4Sock_ = 0;
213b1b8bc3fSopenharmony_ci    }
214b1b8bc3fSopenharmony_ci}
215b1b8bc3fSopenharmony_ci
216b1b8bc3fSopenharmony_civoid DistributedManager::CloseDistributedTunFd()
217b1b8bc3fSopenharmony_ci{
218b1b8bc3fSopenharmony_ci    if (tunFd_ > 0) {
219b1b8bc3fSopenharmony_ci        close(tunFd_);
220b1b8bc3fSopenharmony_ci        tunFd_ = 0;
221b1b8bc3fSopenharmony_ci    }
222b1b8bc3fSopenharmony_ci}
223b1b8bc3fSopenharmony_ci
224b1b8bc3fSopenharmony_ciint32_t DistributedManager::CreateDistributedNic(const std::string &virNicAddr, const std::string &ifName)
225b1b8bc3fSopenharmony_ci{
226b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("CreateVirnic, mtu:%{public}d", DISTRIBUTED_MTU);
227b1b8bc3fSopenharmony_ci    if (CreateDistributedInterface(ifName) != NETMANAGER_SUCCESS) {
228b1b8bc3fSopenharmony_ci        CloseDistributedSocket();
229b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
230b1b8bc3fSopenharmony_ci    }
231b1b8bc3fSopenharmony_ci    if (SetDistributedNicMtu(ifName, DISTRIBUTED_MTU) != NETMANAGER_SUCCESS ||
232b1b8bc3fSopenharmony_ci        SetDistributedNicAddress(ifName, virNicAddr) != NETMANAGER_SUCCESS) {
233b1b8bc3fSopenharmony_ci        SetDistributedNicDown(ifName);
234b1b8bc3fSopenharmony_ci        CloseDistributedSocket();
235b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
236b1b8bc3fSopenharmony_ci    }
237b1b8bc3fSopenharmony_ci    if (SetDistributedNicUp(ifName) != NETMANAGER_SUCCESS) {
238b1b8bc3fSopenharmony_ci        CloseDistributedSocket();
239b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
240b1b8bc3fSopenharmony_ci    }
241b1b8bc3fSopenharmony_ci    CloseDistributedSocket();
242b1b8bc3fSopenharmony_ci
243b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
244b1b8bc3fSopenharmony_ci}
245b1b8bc3fSopenharmony_ci
246b1b8bc3fSopenharmony_ciint32_t DistributedManager::DestroyDistributedNic(const std::string &ifName)
247b1b8bc3fSopenharmony_ci{
248b1b8bc3fSopenharmony_ci    SetDistributedNicDown(ifName);
249b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
250b1b8bc3fSopenharmony_ci}
251b1b8bc3fSopenharmony_ci
252b1b8bc3fSopenharmony_civoid DistributedManager::SetServerNicInfo(const std::string &iif, const std::string &devIface)
253b1b8bc3fSopenharmony_ci{
254b1b8bc3fSopenharmony_ci    serverIif_ = iif;
255b1b8bc3fSopenharmony_ci    serverDevIface_ = devIface;
256b1b8bc3fSopenharmony_ci}
257b1b8bc3fSopenharmony_ci
258b1b8bc3fSopenharmony_cistd::string DistributedManager::GetServerIifNic()
259b1b8bc3fSopenharmony_ci{
260b1b8bc3fSopenharmony_ci    return serverIif_;
261b1b8bc3fSopenharmony_ci}
262b1b8bc3fSopenharmony_ci
263b1b8bc3fSopenharmony_cistd::string DistributedManager::GetServerDevIfaceNic()
264b1b8bc3fSopenharmony_ci{
265b1b8bc3fSopenharmony_ci    return serverDevIface_;
266b1b8bc3fSopenharmony_ci}
267b1b8bc3fSopenharmony_ci
268b1b8bc3fSopenharmony_ci} // namespace NetManagerStandard
269b1b8bc3fSopenharmony_ci} // namespace OHOS
270