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 <algorithm>
17b1b8bc3fSopenharmony_ci#include <map>
18b1b8bc3fSopenharmony_ci#include <net/if.h>
19b1b8bc3fSopenharmony_ci#include <sys/socket.h>
20b1b8bc3fSopenharmony_ci#include <tuple>
21b1b8bc3fSopenharmony_ci#include <utility>
22b1b8bc3fSopenharmony_ci
23b1b8bc3fSopenharmony_ci#include "clat_constants.h"
24b1b8bc3fSopenharmony_ci#include "clat_manager.h"
25b1b8bc3fSopenharmony_ci#include "clat_utils.h"
26b1b8bc3fSopenharmony_ci#include "clatd.h"
27b1b8bc3fSopenharmony_ci#include "fwmark.h"
28b1b8bc3fSopenharmony_ci#include "net_manager_constants.h"
29b1b8bc3fSopenharmony_ci#include "net_manager_native.h"
30b1b8bc3fSopenharmony_ci#include "netnative_log_wrapper.h"
31b1b8bc3fSopenharmony_ci#include "network_permission.h"
32b1b8bc3fSopenharmony_ci
33b1b8bc3fSopenharmony_cinamespace OHOS {
34b1b8bc3fSopenharmony_cinamespace nmd {
35b1b8bc3fSopenharmony_ciusing namespace OHOS::NetManagerStandard;
36b1b8bc3fSopenharmony_ciClatManager::ClatManager() = default;
37b1b8bc3fSopenharmony_ci
38b1b8bc3fSopenharmony_ciint32_t ClatManager::ClatStart(const std::string &v6Iface, int32_t netId, const std::string &nat64PrefixStr,
39b1b8bc3fSopenharmony_ci                               NetManagerNative *netsysService)
40b1b8bc3fSopenharmony_ci{
41b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("Start Clatd on %{public}s", v6Iface.c_str());
42b1b8bc3fSopenharmony_ci    if (clatdTrackers_.find(v6Iface) != clatdTrackers_.end()) {
43b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Clatd is already running on %{public}s", v6Iface.c_str());
44b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_OPERATION_FAILED;
45b1b8bc3fSopenharmony_ci    }
46b1b8bc3fSopenharmony_ci
47b1b8bc3fSopenharmony_ci    if (netsysService == nullptr) {
48b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("NetManagerNative pointer is null");
49b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_INVALID_PARAMETER;
50b1b8bc3fSopenharmony_ci    }
51b1b8bc3fSopenharmony_ci
52b1b8bc3fSopenharmony_ci    uint32_t fwmark = GetFwmark(netId);
53b1b8bc3fSopenharmony_ci    INetAddr v4Addr;
54b1b8bc3fSopenharmony_ci    INetAddr v6Addr;
55b1b8bc3fSopenharmony_ci    int32_t ret = GenerateClatSrcAddr(v6Iface, fwmark, nat64PrefixStr, v4Addr, v6Addr);
56b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
57b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Fail to get source addresses for clat");
58b1b8bc3fSopenharmony_ci        return ret;
59b1b8bc3fSopenharmony_ci    }
60b1b8bc3fSopenharmony_ci
61b1b8bc3fSopenharmony_ci    int tunFd = -1;
62b1b8bc3fSopenharmony_ci    std::string tunIface = std::string(CLAT_PREFIX) + v6Iface;
63b1b8bc3fSopenharmony_ci    ret = CreateAndConfigureTunIface(v6Iface, tunIface, v4Addr, netsysService, tunFd);
64b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
65b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Fail to create and configure tun interface for clat");
66b1b8bc3fSopenharmony_ci        return ret;
67b1b8bc3fSopenharmony_ci    }
68b1b8bc3fSopenharmony_ci
69b1b8bc3fSopenharmony_ci    int readSock6 = -1;
70b1b8bc3fSopenharmony_ci    int writeSock6 = -1;
71b1b8bc3fSopenharmony_ci    ret = CreateAndConfigureClatSocket(v6Iface, v6Addr, fwmark, readSock6, writeSock6);
72b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
73b1b8bc3fSopenharmony_ci        close(tunFd);
74b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Fail to create and configure read/write sockets for clat");
75b1b8bc3fSopenharmony_ci        return ret;
76b1b8bc3fSopenharmony_ci    }
77b1b8bc3fSopenharmony_ci
78b1b8bc3fSopenharmony_ci    clatds_.emplace(
79b1b8bc3fSopenharmony_ci        std::piecewise_construct, std::forward_as_tuple(v6Iface),
80b1b8bc3fSopenharmony_ci        std::forward_as_tuple(tunFd, readSock6, writeSock6, v6Iface, nat64PrefixStr, v4Addr.address_, v6Addr.address_));
81b1b8bc3fSopenharmony_ci    clatds_[v6Iface].Start();
82b1b8bc3fSopenharmony_ci
83b1b8bc3fSopenharmony_ci    ret = RouteManager::AddClatTunInterface(tunIface, DEFAULT_V4_ADDR, v4Addr.address_);
84b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
85b1b8bc3fSopenharmony_ci        close(tunFd);
86b1b8bc3fSopenharmony_ci        close(readSock6);
87b1b8bc3fSopenharmony_ci        close(writeSock6);
88b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Add route on %{public}s failed", tunIface.c_str());
89b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_OPERATION_FAILED;
90b1b8bc3fSopenharmony_ci    }
91b1b8bc3fSopenharmony_ci
92b1b8bc3fSopenharmony_ci    clatdTrackers_[v6Iface] = {v6Iface, tunIface, v4Addr, v6Addr, nat64PrefixStr, tunFd, readSock6, writeSock6};
93b1b8bc3fSopenharmony_ci
94b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
95b1b8bc3fSopenharmony_ci}
96b1b8bc3fSopenharmony_ci
97b1b8bc3fSopenharmony_ciint32_t ClatManager::ClatStop(const std::string &v6Iface)
98b1b8bc3fSopenharmony_ci{
99b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("Stop Clatd on %{public}s", v6Iface.c_str());
100b1b8bc3fSopenharmony_ci    if (clatdTrackers_.find(v6Iface) == clatdTrackers_.end()) {
101b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Clatd has not started on %{public}s", v6Iface.c_str());
102b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_OPERATION_FAILED;
103b1b8bc3fSopenharmony_ci    }
104b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("Stopping clatd on %{public}s", v6Iface.c_str());
105b1b8bc3fSopenharmony_ci
106b1b8bc3fSopenharmony_ci    RouteManager::RemoveClatTunInterface(clatdTrackers_[v6Iface].tunIface);
107b1b8bc3fSopenharmony_ci
108b1b8bc3fSopenharmony_ci    clatds_[v6Iface].Stop();
109b1b8bc3fSopenharmony_ci    clatds_.erase(v6Iface);
110b1b8bc3fSopenharmony_ci
111b1b8bc3fSopenharmony_ci    FreeTunV4Addr(clatdTrackers_[v6Iface].v4Addr.address_);
112b1b8bc3fSopenharmony_ci
113b1b8bc3fSopenharmony_ci    close(clatdTrackers_[v6Iface].tunFd);
114b1b8bc3fSopenharmony_ci    close(clatdTrackers_[v6Iface].readSock6);
115b1b8bc3fSopenharmony_ci    close(clatdTrackers_[v6Iface].writeSock6);
116b1b8bc3fSopenharmony_ci    clatdTrackers_.erase(v6Iface);
117b1b8bc3fSopenharmony_ci
118b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("clatd on %{public}s stopped", v6Iface.c_str());
119b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
120b1b8bc3fSopenharmony_ci}
121b1b8bc3fSopenharmony_ci
122b1b8bc3fSopenharmony_ciuint32_t ClatManager::GetFwmark(int32_t netId)
123b1b8bc3fSopenharmony_ci{
124b1b8bc3fSopenharmony_ci    Fwmark mark;
125b1b8bc3fSopenharmony_ci    mark.netId = static_cast<uint16_t>(netId);
126b1b8bc3fSopenharmony_ci    mark.explicitlySelected = true;
127b1b8bc3fSopenharmony_ci    mark.protectedFromVpn = true;
128b1b8bc3fSopenharmony_ci    NetworkPermission permission = NetworkPermission::PERMISSION_SYSTEM;
129b1b8bc3fSopenharmony_ci    mark.permission = permission;
130b1b8bc3fSopenharmony_ci    mark.uidBillingDone = false;
131b1b8bc3fSopenharmony_ci    return mark.intValue;
132b1b8bc3fSopenharmony_ci}
133b1b8bc3fSopenharmony_ci
134b1b8bc3fSopenharmony_ciint32_t ClatManager::GenerateClatSrcAddr(const std::string &v6Iface, uint32_t fwmark, const std::string &nat64PrefixStr,
135b1b8bc3fSopenharmony_ci                                         INetAddr &v4Addr, INetAddr &v6Addr)
136b1b8bc3fSopenharmony_ci{
137b1b8bc3fSopenharmony_ci    std::string v4AddrStr;
138b1b8bc3fSopenharmony_ci    int32_t ret = SelectIpv4Address(std::string(INIT_V4ADDR_STRING), INIT_V4ADDR_PREFIX_BIT_LEN, v4AddrStr);
139b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
140b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("no IPv4 addresses were available for clat");
141b1b8bc3fSopenharmony_ci        return ret;
142b1b8bc3fSopenharmony_ci    }
143b1b8bc3fSopenharmony_ci    v4Addr.type_ = INetAddr::IPV4;
144b1b8bc3fSopenharmony_ci    v4Addr.family_ = AF_INET;
145b1b8bc3fSopenharmony_ci    v4Addr.address_ = v4AddrStr;
146b1b8bc3fSopenharmony_ci
147b1b8bc3fSopenharmony_ci    std::string v6AddrStr;
148b1b8bc3fSopenharmony_ci    ret = GenerateIpv6Address(v6Iface, v4AddrStr, nat64PrefixStr, fwmark, v6AddrStr);
149b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
150b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("no IPv6 addresses were available for clat");
151b1b8bc3fSopenharmony_ci        return ret;
152b1b8bc3fSopenharmony_ci    }
153b1b8bc3fSopenharmony_ci    v6Addr.type_ = INetAddr::IPV6;
154b1b8bc3fSopenharmony_ci    v6Addr.family_ = AF_INET6;
155b1b8bc3fSopenharmony_ci    v6Addr.address_ = v6AddrStr;
156b1b8bc3fSopenharmony_ci
157b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
158b1b8bc3fSopenharmony_ci}
159b1b8bc3fSopenharmony_ci
160b1b8bc3fSopenharmony_ciint32_t ClatManager::CreateAndConfigureTunIface(const std::string &v6Iface, const std::string &tunIface,
161b1b8bc3fSopenharmony_ci                                                const INetAddr &v4Addr, NetManagerNative *netsysService, int &tunFd)
162b1b8bc3fSopenharmony_ci{
163b1b8bc3fSopenharmony_ci    int32_t ret = CreateTunInterface(tunIface, tunFd);
164b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
165b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Create tun interface %{public}s failed", tunIface.c_str());
166b1b8bc3fSopenharmony_ci        return ret;
167b1b8bc3fSopenharmony_ci    }
168b1b8bc3fSopenharmony_ci
169b1b8bc3fSopenharmony_ci    uint32_t tunIfIndex = if_nametoindex(tunIface.c_str());
170b1b8bc3fSopenharmony_ci    if (tunIfIndex == INVALID_IFINDEX) {
171b1b8bc3fSopenharmony_ci        close(tunFd);
172b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Fail to get interface index for interface %{public}s", tunIface.c_str());
173b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_OPERATION_FAILED;
174b1b8bc3fSopenharmony_ci    }
175b1b8bc3fSopenharmony_ci
176b1b8bc3fSopenharmony_ci    ret = netsysService->SetEnableIpv6(tunIface, 0);
177b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
178b1b8bc3fSopenharmony_ci        close(tunFd);
179b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("SetEnableIpv6 on %{public}s failed", tunIface.c_str());
180b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_OPERATION_FAILED;
181b1b8bc3fSopenharmony_ci    }
182b1b8bc3fSopenharmony_ci
183b1b8bc3fSopenharmony_ci    int mtu = CLAT_IPV6_MIN_MTU - MTU_DELTA;
184b1b8bc3fSopenharmony_ci    ret = netsysService->SetInterfaceMtu(tunIface, mtu);
185b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
186b1b8bc3fSopenharmony_ci        close(tunFd);
187b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Set MTU on %{public}s failed", tunIface.c_str());
188b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_OPERATION_FAILED;
189b1b8bc3fSopenharmony_ci    }
190b1b8bc3fSopenharmony_ci
191b1b8bc3fSopenharmony_ci    int v4AddrPrefixLen = V4ADDR_BIT_LEN;
192b1b8bc3fSopenharmony_ci
193b1b8bc3fSopenharmony_ci    OHOS::nmd::InterfaceConfigurationParcel ifConfig;
194b1b8bc3fSopenharmony_ci    ifConfig.ifName = tunIface;
195b1b8bc3fSopenharmony_ci    ifConfig.hwAddr = "";
196b1b8bc3fSopenharmony_ci    ifConfig.ipv4Addr = v4Addr.address_;
197b1b8bc3fSopenharmony_ci    ifConfig.prefixLength = v4AddrPrefixLen;
198b1b8bc3fSopenharmony_ci
199b1b8bc3fSopenharmony_ci    ifConfig.flags.emplace_back(IFACE_LINK_UP);
200b1b8bc3fSopenharmony_ci    netsysService->SetInterfaceConfig(ifConfig);
201b1b8bc3fSopenharmony_ci
202b1b8bc3fSopenharmony_ci    ret = SetTunInterfaceAddress(tunIface, v4Addr.address_, v4AddrPrefixLen);
203b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
204b1b8bc3fSopenharmony_ci        close(tunFd);
205b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Set tun interface address on %{public}s failed", tunIface.c_str());
206b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_OPERATION_FAILED;
207b1b8bc3fSopenharmony_ci    }
208b1b8bc3fSopenharmony_ci
209b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
210b1b8bc3fSopenharmony_ci}
211b1b8bc3fSopenharmony_ci
212b1b8bc3fSopenharmony_ciint32_t ClatManager::CreateAndConfigureClatSocket(const std::string &v6Iface, const INetAddr &v6Addr, uint32_t fwmark,
213b1b8bc3fSopenharmony_ci                                                  int &readSock6, int &writeSock6)
214b1b8bc3fSopenharmony_ci{
215b1b8bc3fSopenharmony_ci    int32_t ret = OpenPacketSocket(readSock6);
216b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
217b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Open packet socket failed");
218b1b8bc3fSopenharmony_ci        return ret;
219b1b8bc3fSopenharmony_ci    }
220b1b8bc3fSopenharmony_ci
221b1b8bc3fSopenharmony_ci    ret = OpenRawSocket6(fwmark, writeSock6);
222b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
223b1b8bc3fSopenharmony_ci        close(readSock6);
224b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Open raw socket failed");
225b1b8bc3fSopenharmony_ci        return ret;
226b1b8bc3fSopenharmony_ci    }
227b1b8bc3fSopenharmony_ci
228b1b8bc3fSopenharmony_ci    uint32_t v6IfIndex = if_nametoindex(v6Iface.c_str());
229b1b8bc3fSopenharmony_ci    if (v6IfIndex == INVALID_IFINDEX) {
230b1b8bc3fSopenharmony_ci        close(readSock6);
231b1b8bc3fSopenharmony_ci        close(writeSock6);
232b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Fail to get interface index for interface %{public}s", v6Iface.c_str());
233b1b8bc3fSopenharmony_ci        return NETMANAGER_ERR_OPERATION_FAILED;
234b1b8bc3fSopenharmony_ci    }
235b1b8bc3fSopenharmony_ci
236b1b8bc3fSopenharmony_ci    ret = ConfigureWriteSocket(writeSock6, v6Iface);
237b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
238b1b8bc3fSopenharmony_ci        close(readSock6);
239b1b8bc3fSopenharmony_ci        close(writeSock6);
240b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Configure write sockopt failed");
241b1b8bc3fSopenharmony_ci        return ret;
242b1b8bc3fSopenharmony_ci    }
243b1b8bc3fSopenharmony_ci
244b1b8bc3fSopenharmony_ci    ret = ConfigureReadSocket(readSock6, v6Addr.address_, v6IfIndex);
245b1b8bc3fSopenharmony_ci    if (ret != NETMANAGER_SUCCESS) {
246b1b8bc3fSopenharmony_ci        close(readSock6);
247b1b8bc3fSopenharmony_ci        close(writeSock6);
248b1b8bc3fSopenharmony_ci        NETNATIVE_LOGW("Configure read socket failed");
249b1b8bc3fSopenharmony_ci        return ret;
250b1b8bc3fSopenharmony_ci    }
251b1b8bc3fSopenharmony_ci
252b1b8bc3fSopenharmony_ci    return NETMANAGER_SUCCESS;
253b1b8bc3fSopenharmony_ci}
254b1b8bc3fSopenharmony_ci} // namespace nmd
255b1b8bc3fSopenharmony_ci} // namespace OHOS