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