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