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 <arpa/inet.h> 17b1b8bc3fSopenharmony_ci#include <cerrno> 18b1b8bc3fSopenharmony_ci#include <climits> 19b1b8bc3fSopenharmony_ci#include <cstdlib> 20b1b8bc3fSopenharmony_ci#include <cstring> 21b1b8bc3fSopenharmony_ci#include <fcntl.h> 22b1b8bc3fSopenharmony_ci#include <linux/filter.h> 23b1b8bc3fSopenharmony_ci#include <linux/if_packet.h> 24b1b8bc3fSopenharmony_ci#include <linux/if_tun.h> 25b1b8bc3fSopenharmony_ci#include <linux/ipv6.h> 26b1b8bc3fSopenharmony_ci#include <list> 27b1b8bc3fSopenharmony_ci#include <mutex> 28b1b8bc3fSopenharmony_ci#include <net/if.h> 29b1b8bc3fSopenharmony_ci#include <netinet/in.h> 30b1b8bc3fSopenharmony_ci#include <sys/ioctl.h> 31b1b8bc3fSopenharmony_ci#include <sys/socket.h> 32b1b8bc3fSopenharmony_ci#include <unistd.h> 33b1b8bc3fSopenharmony_ci 34b1b8bc3fSopenharmony_ci#include "clat_utils.h" 35b1b8bc3fSopenharmony_ci#include "ffrt.h" 36b1b8bc3fSopenharmony_ci#include "netmanager_base_common_utils.h" 37b1b8bc3fSopenharmony_ci#include "net_manager_constants.h" 38b1b8bc3fSopenharmony_ci#include "netnative_log_wrapper.h" 39b1b8bc3fSopenharmony_ci#include "securec.h" 40b1b8bc3fSopenharmony_ci 41b1b8bc3fSopenharmony_cinamespace OHOS { 42b1b8bc3fSopenharmony_cinamespace nmd { 43b1b8bc3fSopenharmony_ciusing namespace OHOS::NetManagerStandard; 44b1b8bc3fSopenharmony_ciffrt::mutex g_tunV4AddrMutex; 45b1b8bc3fSopenharmony_cistd::list<in_addr_t> g_tunV4AddrInUse; 46b1b8bc3fSopenharmony_ci 47b1b8bc3fSopenharmony_cibool IsIpv4AddressFree(const in_addr_t v4Addr) 48b1b8bc3fSopenharmony_ci{ 49b1b8bc3fSopenharmony_ci std::lock_guard<ffrt::mutex> lock(g_tunV4AddrMutex); 50b1b8bc3fSopenharmony_ci if (std::find(g_tunV4AddrInUse.begin(), g_tunV4AddrInUse.end(), v4Addr) != g_tunV4AddrInUse.end()) { 51b1b8bc3fSopenharmony_ci return false; 52b1b8bc3fSopenharmony_ci } 53b1b8bc3fSopenharmony_ci int s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); 54b1b8bc3fSopenharmony_ci if (s == -1) { 55b1b8bc3fSopenharmony_ci return false; 56b1b8bc3fSopenharmony_ci } 57b1b8bc3fSopenharmony_ci 58b1b8bc3fSopenharmony_ci // check if the address is available by trying to connect to it 59b1b8bc3fSopenharmony_ci sockaddr_in sin = { 60b1b8bc3fSopenharmony_ci .sin_family = AF_INET, 61b1b8bc3fSopenharmony_ci .sin_port = htons(WKN_DNS_PORT), 62b1b8bc3fSopenharmony_ci .sin_addr = {v4Addr}, 63b1b8bc3fSopenharmony_ci }; 64b1b8bc3fSopenharmony_ci socklen_t len = sizeof(sin); 65b1b8bc3fSopenharmony_ci const bool inuse = !connect(s, reinterpret_cast<sockaddr *>(&sin), sizeof(sin)) && 66b1b8bc3fSopenharmony_ci !getsockname(s, reinterpret_cast<sockaddr *>(&sin), &len) && 67b1b8bc3fSopenharmony_ci len == static_cast<socklen_t>(sizeof(sin)) && sin.sin_addr.s_addr == v4Addr; 68b1b8bc3fSopenharmony_ci 69b1b8bc3fSopenharmony_ci close(s); 70b1b8bc3fSopenharmony_ci g_tunV4AddrInUse.emplace_back(v4Addr); 71b1b8bc3fSopenharmony_ci return !inuse; 72b1b8bc3fSopenharmony_ci} 73b1b8bc3fSopenharmony_ci 74b1b8bc3fSopenharmony_civoid FreeTunV4Addr(const std::string &v4AddrStr) 75b1b8bc3fSopenharmony_ci{ 76b1b8bc3fSopenharmony_ci std::lock_guard<ffrt::mutex> lock(g_tunV4AddrMutex); 77b1b8bc3fSopenharmony_ci in_addr v4Addr; 78b1b8bc3fSopenharmony_ci if (inet_pton(AF_INET, v4AddrStr.c_str(), &v4Addr) != 1) { 79b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("fail to free tun v4 address, tun address invalid"); 80b1b8bc3fSopenharmony_ci return; 81b1b8bc3fSopenharmony_ci } 82b1b8bc3fSopenharmony_ci g_tunV4AddrInUse.remove(v4Addr.s_addr); 83b1b8bc3fSopenharmony_ci} 84b1b8bc3fSopenharmony_ci 85b1b8bc3fSopenharmony_ciin_addr_t GetAvailableIpv4Address(const in_addr initV4Addr, const int16_t prefixLen) 86b1b8bc3fSopenharmony_ci{ 87b1b8bc3fSopenharmony_ci if (prefixLen < 0 || prefixLen > V4ADDR_BIT_LEN) { 88b1b8bc3fSopenharmony_ci return INADDR_NONE; 89b1b8bc3fSopenharmony_ci } 90b1b8bc3fSopenharmony_ci const uint32_t mask = 0xffffffff >> (V4ADDR_BIT_LEN - prefixLen) << (V4ADDR_BIT_LEN - prefixLen); 91b1b8bc3fSopenharmony_ci uint32_t v4Num = ntohl(initV4Addr.s_addr); 92b1b8bc3fSopenharmony_ci const uint32_t initV4Num = v4Num; 93b1b8bc3fSopenharmony_ci const uint32_t prefix = v4Num & mask; 94b1b8bc3fSopenharmony_ci 95b1b8bc3fSopenharmony_ci do { 96b1b8bc3fSopenharmony_ci if (IsIpv4AddressFree(htonl(v4Num))) { 97b1b8bc3fSopenharmony_ci return htonl(v4Num); 98b1b8bc3fSopenharmony_ci } 99b1b8bc3fSopenharmony_ci v4Num = prefix | ((v4Num + 1) & ~mask); 100b1b8bc3fSopenharmony_ci } while (v4Num != initV4Num); 101b1b8bc3fSopenharmony_ci 102b1b8bc3fSopenharmony_ci return INADDR_NONE; 103b1b8bc3fSopenharmony_ci} 104b1b8bc3fSopenharmony_ci 105b1b8bc3fSopenharmony_ciint32_t SelectIpv4Address(const std::string &initV4AddrStr, int prefixLen, std::string &v4AddrStr) 106b1b8bc3fSopenharmony_ci{ 107b1b8bc3fSopenharmony_ci in_addr initV4Addr; 108b1b8bc3fSopenharmony_ci if (inet_pton(AF_INET, initV4AddrStr.c_str(), &initV4Addr) != 1) { 109b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("fail to select ipv4 address for tun, init address invalid"); 110b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INVALID_PARAMETER; 111b1b8bc3fSopenharmony_ci } 112b1b8bc3fSopenharmony_ci 113b1b8bc3fSopenharmony_ci in_addr v4Addr = {GetAvailableIpv4Address(initV4Addr, prefixLen)}; 114b1b8bc3fSopenharmony_ci if (v4Addr.s_addr == INADDR_NONE) { 115b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("No free IPv4 address in %{public}s/%{public}d", 116b1b8bc3fSopenharmony_ci CommonUtils::ToAnonymousIp(initV4AddrStr).c_str(), prefixLen); 117b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 118b1b8bc3fSopenharmony_ci } 119b1b8bc3fSopenharmony_ci 120b1b8bc3fSopenharmony_ci char addrstr[INET_ADDRSTRLEN]; 121b1b8bc3fSopenharmony_ci inet_ntop(AF_INET, reinterpret_cast<void *>(&v4Addr), addrstr, sizeof(addrstr)); 122b1b8bc3fSopenharmony_ci v4AddrStr = addrstr; 123b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 124b1b8bc3fSopenharmony_ci} 125b1b8bc3fSopenharmony_ci 126b1b8bc3fSopenharmony_ciuint16_t Checksum32To16(uint32_t sum32) 127b1b8bc3fSopenharmony_ci{ 128b1b8bc3fSopenharmony_ci while (sum32 >> (sizeof(uint16_t) * CHAR_BIT)) { 129b1b8bc3fSopenharmony_ci sum32 = (sum32 & 0xffff) + (sum32 >> (sizeof(uint16_t) * CHAR_BIT)); 130b1b8bc3fSopenharmony_ci } 131b1b8bc3fSopenharmony_ci return sum32; 132b1b8bc3fSopenharmony_ci} 133b1b8bc3fSopenharmony_ci 134b1b8bc3fSopenharmony_ciuint16_t AdjustChecksum(uint16_t oldSum16, uint32_t oldSumHdr, uint32_t newSumHdr) 135b1b8bc3fSopenharmony_ci{ 136b1b8bc3fSopenharmony_ci // More details in RFC 1624. 137b1b8bc3fSopenharmony_ci oldSum16 = ~oldSum16; 138b1b8bc3fSopenharmony_ci uint16_t sumFolded = Checksum32To16(newSumHdr + oldSum16); 139b1b8bc3fSopenharmony_ci uint16_t oldFolded = Checksum32To16(oldSumHdr); 140b1b8bc3fSopenharmony_ci if (sumFolded > oldFolded) { 141b1b8bc3fSopenharmony_ci return ~(sumFolded - oldFolded); 142b1b8bc3fSopenharmony_ci } 143b1b8bc3fSopenharmony_ci return ~(sumFolded - oldFolded - 1); 144b1b8bc3fSopenharmony_ci} 145b1b8bc3fSopenharmony_ci 146b1b8bc3fSopenharmony_ciuint32_t AddChecksum(uint32_t sum, const void *data, int len) 147b1b8bc3fSopenharmony_ci{ 148b1b8bc3fSopenharmony_ci const uint16_t *single16 = reinterpret_cast<const uint16_t *>(data); 149b1b8bc3fSopenharmony_ci int multiplier = sizeof(uint32_t) / sizeof(uint16_t); 150b1b8bc3fSopenharmony_ci while (len >= multiplier) { 151b1b8bc3fSopenharmony_ci sum += *single16; 152b1b8bc3fSopenharmony_ci single16++; 153b1b8bc3fSopenharmony_ci len -= multiplier; 154b1b8bc3fSopenharmony_ci } 155b1b8bc3fSopenharmony_ci if (len) { 156b1b8bc3fSopenharmony_ci sum += *reinterpret_cast<const uint8_t *>(single16); 157b1b8bc3fSopenharmony_ci } 158b1b8bc3fSopenharmony_ci 159b1b8bc3fSopenharmony_ci return sum; 160b1b8bc3fSopenharmony_ci} 161b1b8bc3fSopenharmony_ci 162b1b8bc3fSopenharmony_civoid MakeChecksumNeutral(in6_addr &v6Addr, const in_addr &v4Addr, const in6_addr &nat64Prefix) 163b1b8bc3fSopenharmony_ci{ 164b1b8bc3fSopenharmony_ci arc4random_buf(&v6Addr.s6_addr[CLAT_V6ADDR_RANDOMIZE_OFFSET], CLAT_V6ADDR_RANDOMIZE_BIT_LENGTH); 165b1b8bc3fSopenharmony_ci 166b1b8bc3fSopenharmony_ci size_t adjustOffset = CLAT_V6ADDR_RANDOMIZE_OFFSET + CLAT_V6ADDR_NEUTRALIZE_OFFSET; 167b1b8bc3fSopenharmony_ci uint16_t middleBytes = (v6Addr.s6_addr[adjustOffset] << CHAR_BIT) + v6Addr.s6_addr[adjustOffset + 1]; 168b1b8bc3fSopenharmony_ci 169b1b8bc3fSopenharmony_ci uint32_t v4Checksum = AddChecksum(0, &v4Addr, sizeof(v4Addr)); 170b1b8bc3fSopenharmony_ci uint32_t v6Checksum = AddChecksum(0, &nat64Prefix, sizeof(nat64Prefix)) + AddChecksum(0, &v6Addr, sizeof(v6Addr)); 171b1b8bc3fSopenharmony_ci 172b1b8bc3fSopenharmony_ci uint16_t delta = AdjustChecksum(middleBytes, v4Checksum, v6Checksum); 173b1b8bc3fSopenharmony_ci v6Addr.s6_addr[adjustOffset] = delta >> CHAR_BIT; 174b1b8bc3fSopenharmony_ci v6Addr.s6_addr[adjustOffset + 1] = delta & 0xff; 175b1b8bc3fSopenharmony_ci} 176b1b8bc3fSopenharmony_ci 177b1b8bc3fSopenharmony_ciint32_t GetSuitableIpv6Address(const std::string &v6IfaceStr, const in_addr v4Addr, const in6_addr &nat64Prefix, 178b1b8bc3fSopenharmony_ci in6_addr &v6Addr, const uint32_t mark) 179b1b8bc3fSopenharmony_ci{ 180b1b8bc3fSopenharmony_ci int s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); 181b1b8bc3fSopenharmony_ci if (s == -1) 182b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 183b1b8bc3fSopenharmony_ci 184b1b8bc3fSopenharmony_ci if (setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) { 185b1b8bc3fSopenharmony_ci auto err = errno; 186b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("setsockopt(SOL_SOCKET, SO_MARK) failed: %{public}s", strerror(err)); 187b1b8bc3fSopenharmony_ci close(s); 188b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 189b1b8bc3fSopenharmony_ci } 190b1b8bc3fSopenharmony_ci 191b1b8bc3fSopenharmony_ci if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, v6IfaceStr.c_str(), v6IfaceStr.length())) { 192b1b8bc3fSopenharmony_ci auto err = errno; 193b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("setsockopt(SOL_SOCKET, SO_BINDTODEVICE, '%{public}s') failed: %{public}s", v6IfaceStr.c_str(), 194b1b8bc3fSopenharmony_ci strerror(err)); 195b1b8bc3fSopenharmony_ci close(s); 196b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 197b1b8bc3fSopenharmony_ci } 198b1b8bc3fSopenharmony_ci 199b1b8bc3fSopenharmony_ci sockaddr_in6 sin6; 200b1b8bc3fSopenharmony_ci sin6.sin6_family = AF_INET6; 201b1b8bc3fSopenharmony_ci sin6.sin6_addr = nat64Prefix; 202b1b8bc3fSopenharmony_ci if (connect(s, reinterpret_cast<sockaddr *>(&sin6), sizeof(sin6))) { 203b1b8bc3fSopenharmony_ci close(s); 204b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 205b1b8bc3fSopenharmony_ci } 206b1b8bc3fSopenharmony_ci 207b1b8bc3fSopenharmony_ci socklen_t len = sizeof(sin6); 208b1b8bc3fSopenharmony_ci if (getsockname(s, reinterpret_cast<sockaddr *>(&sin6), &len)) { 209b1b8bc3fSopenharmony_ci close(s); 210b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 211b1b8bc3fSopenharmony_ci } 212b1b8bc3fSopenharmony_ci 213b1b8bc3fSopenharmony_ci v6Addr = sin6.sin6_addr; 214b1b8bc3fSopenharmony_ci 215b1b8bc3fSopenharmony_ci MakeChecksumNeutral(v6Addr, v4Addr, nat64Prefix); 216b1b8bc3fSopenharmony_ci close(s); 217b1b8bc3fSopenharmony_ci 218b1b8bc3fSopenharmony_ci return 0; 219b1b8bc3fSopenharmony_ci} 220b1b8bc3fSopenharmony_ci 221b1b8bc3fSopenharmony_ciint32_t GenerateIpv6Address(const std::string &v6IfaceStr, const std::string &v4AddrStr, const std::string &prefix64Str, 222b1b8bc3fSopenharmony_ci uint32_t mark, std::string &v6AddrStr) 223b1b8bc3fSopenharmony_ci{ 224b1b8bc3fSopenharmony_ci if (v6IfaceStr.empty()) { 225b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("fail to generate ipv6 address, ipv6 interface name null"); 226b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INVALID_PARAMETER; 227b1b8bc3fSopenharmony_ci } 228b1b8bc3fSopenharmony_ci 229b1b8bc3fSopenharmony_ci in_addr v4Addr; 230b1b8bc3fSopenharmony_ci if (inet_pton(AF_INET, v4AddrStr.c_str(), &v4Addr) != 1) { 231b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("fail to generate ipv6 address, ipv4 address invalid"); 232b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INVALID_PARAMETER; 233b1b8bc3fSopenharmony_ci } 234b1b8bc3fSopenharmony_ci 235b1b8bc3fSopenharmony_ci in6_addr prefix64; 236b1b8bc3fSopenharmony_ci if (inet_pton(AF_INET6, prefix64Str.c_str(), &prefix64) != 1) { 237b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("fail to generate ipv6 address, prefix invalid"); 238b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INVALID_PARAMETER; 239b1b8bc3fSopenharmony_ci } 240b1b8bc3fSopenharmony_ci 241b1b8bc3fSopenharmony_ci in6_addr v6Addr; 242b1b8bc3fSopenharmony_ci int32_t ret = GetSuitableIpv6Address(v6IfaceStr, v4Addr, prefix64, v6Addr, mark); 243b1b8bc3fSopenharmony_ci if (ret != NETMANAGER_SUCCESS) { 244b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("Unable to find global source address on %{public}s for %{public}s", v6IfaceStr.c_str(), 245b1b8bc3fSopenharmony_ci prefix64Str.c_str()); 246b1b8bc3fSopenharmony_ci return ret; 247b1b8bc3fSopenharmony_ci } 248b1b8bc3fSopenharmony_ci 249b1b8bc3fSopenharmony_ci char addrstr[INET6_ADDRSTRLEN]; 250b1b8bc3fSopenharmony_ci if (!inet_ntop(AF_INET6, reinterpret_cast<void *>(&v6Addr), addrstr, sizeof(addrstr))) { 251b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("fail to generate ipv6 address, ipv6 address invalid"); 252b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 253b1b8bc3fSopenharmony_ci } 254b1b8bc3fSopenharmony_ci v6AddrStr = addrstr; 255b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 256b1b8bc3fSopenharmony_ci} 257b1b8bc3fSopenharmony_ci 258b1b8bc3fSopenharmony_ciuint16_t CalChecksum(const void *data, int len) 259b1b8bc3fSopenharmony_ci{ 260b1b8bc3fSopenharmony_ci uint32_t tempSum = AddChecksum(0xffff, data, len); 261b1b8bc3fSopenharmony_ci return ~Checksum32To16(tempSum); 262b1b8bc3fSopenharmony_ci} 263b1b8bc3fSopenharmony_ci 264b1b8bc3fSopenharmony_ciint32_t CreateTunInterface(const std::string &tunIface, int &fd) 265b1b8bc3fSopenharmony_ci{ 266b1b8bc3fSopenharmony_ci fd = open("/dev/tun", O_RDWR | O_NONBLOCK | O_CLOEXEC); 267b1b8bc3fSopenharmony_ci if (fd == -1) { 268b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("open tun device failed, errno: %{public}d", errno); 269b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 270b1b8bc3fSopenharmony_ci } 271b1b8bc3fSopenharmony_ci 272b1b8bc3fSopenharmony_ci struct ifreq ifr = {}; 273b1b8bc3fSopenharmony_ci ifr.ifr_flags = static_cast<short>(IFF_TUN | IFF_TUN_EXCL); 274b1b8bc3fSopenharmony_ci 275b1b8bc3fSopenharmony_ci if (strncpy_s(ifr.ifr_name, IFNAMSIZ, tunIface.c_str(), tunIface.length()) != EOK) { 276b1b8bc3fSopenharmony_ci close(fd); 277b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 278b1b8bc3fSopenharmony_ci } 279b1b8bc3fSopenharmony_ci if (ioctl(fd, TUNSETIFF, &ifr, sizeof(ifr))) { 280b1b8bc3fSopenharmony_ci close(fd); 281b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("ioctl(TUNSETIFF) failed"); 282b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 283b1b8bc3fSopenharmony_ci } 284b1b8bc3fSopenharmony_ci 285b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 286b1b8bc3fSopenharmony_ci} 287b1b8bc3fSopenharmony_ci 288b1b8bc3fSopenharmony_ciint32_t OpenPacketSocket(int &readSock6) 289b1b8bc3fSopenharmony_ci{ 290b1b8bc3fSopenharmony_ci readSock6 = socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC, 0); 291b1b8bc3fSopenharmony_ci if (readSock6 < 0) { 292b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("packet socket failed"); 293b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 294b1b8bc3fSopenharmony_ci } 295b1b8bc3fSopenharmony_ci const int on = 1; 296b1b8bc3fSopenharmony_ci 297b1b8bc3fSopenharmony_ci if (setsockopt(readSock6, SOL_PACKET, PACKET_AUXDATA, &on, sizeof(on))) { 298b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("packet socket auxdata enablement failed"); 299b1b8bc3fSopenharmony_ci close(readSock6); 300b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 301b1b8bc3fSopenharmony_ci } 302b1b8bc3fSopenharmony_ci 303b1b8bc3fSopenharmony_ci if (setsockopt(readSock6, SOL_PACKET, PACKET_VNET_HDR, &on, sizeof(on))) { 304b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("packet socket vnet_hdr enablement failed"); 305b1b8bc3fSopenharmony_ci close(readSock6); 306b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 307b1b8bc3fSopenharmony_ci } 308b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 309b1b8bc3fSopenharmony_ci} 310b1b8bc3fSopenharmony_ci 311b1b8bc3fSopenharmony_ciint32_t OpenRawSocket6(const uint32_t mark, int &writeSock6) 312b1b8bc3fSopenharmony_ci{ 313b1b8bc3fSopenharmony_ci writeSock6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_RAW); 314b1b8bc3fSopenharmony_ci if (writeSock6 < 0) { 315b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("raw socket failed"); 316b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 317b1b8bc3fSopenharmony_ci } 318b1b8bc3fSopenharmony_ci 319b1b8bc3fSopenharmony_ci if (setsockopt(writeSock6, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) { 320b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("could not set mark on raw socket"); 321b1b8bc3fSopenharmony_ci close(writeSock6); 322b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 323b1b8bc3fSopenharmony_ci } 324b1b8bc3fSopenharmony_ci 325b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 326b1b8bc3fSopenharmony_ci} 327b1b8bc3fSopenharmony_ci 328b1b8bc3fSopenharmony_ciint32_t ConfigureWriteSocket(int sockFd, const std::string &v6Iface) 329b1b8bc3fSopenharmony_ci{ 330b1b8bc3fSopenharmony_ci if (sockFd < 0) { 331b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("Invalid file descriptor"); 332b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INVALID_PARAMETER; 333b1b8bc3fSopenharmony_ci } 334b1b8bc3fSopenharmony_ci 335b1b8bc3fSopenharmony_ci int ret = setsockopt(sockFd, SOL_SOCKET, SO_BINDTODEVICE, v6Iface.c_str(), 336b1b8bc3fSopenharmony_ci static_cast<socklen_t>(strlen(v6Iface.c_str()))); 337b1b8bc3fSopenharmony_ci if (ret) { 338b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("setsockopt SO_BINDTODEVICE failed: %{public}s", strerror(errno)); 339b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 340b1b8bc3fSopenharmony_ci } 341b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 342b1b8bc3fSopenharmony_ci} 343b1b8bc3fSopenharmony_ci 344b1b8bc3fSopenharmony_ciint AddFilterAndBindPacketSocket(const int sock, const in6_addr *const addr, const int ifIndex) 345b1b8bc3fSopenharmony_ci{ 346b1b8bc3fSopenharmony_ci sock_filter filter[] = { 347b1b8bc3fSopenharmony_ci BPF_STMT(BPF_LD | BPF_W | BPF_ABS, static_cast<__u32>(SKF_NET_OFF) + offsetof(ipv6hdr, daddr.s6_addr32[0])), 348b1b8bc3fSopenharmony_ci BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ntohl(addr->s6_addr32[0]), 1, 0), 349b1b8bc3fSopenharmony_ci BPF_STMT(BPF_RET | BPF_K, 0), 350b1b8bc3fSopenharmony_ci BPF_STMT(BPF_LD | BPF_W | BPF_ABS, static_cast<__u32>(SKF_NET_OFF) + offsetof(ipv6hdr, daddr.s6_addr32[1])), 351b1b8bc3fSopenharmony_ci BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ntohl(addr->s6_addr32[1]), 1, 0), 352b1b8bc3fSopenharmony_ci BPF_STMT(BPF_RET | BPF_K, 0), 353b1b8bc3fSopenharmony_ci BPF_STMT(BPF_LD | BPF_W | BPF_ABS, static_cast<__u32>(SKF_NET_OFF) + offsetof(ipv6hdr, daddr.s6_addr32[2])), 354b1b8bc3fSopenharmony_ci BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ntohl(addr->s6_addr32[2]), 1, 0), 355b1b8bc3fSopenharmony_ci BPF_STMT(BPF_RET | BPF_K, 0), 356b1b8bc3fSopenharmony_ci BPF_STMT(BPF_LD | BPF_W | BPF_ABS, static_cast<__u32>(SKF_NET_OFF) + offsetof(ipv6hdr, daddr.s6_addr32[3])), 357b1b8bc3fSopenharmony_ci BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ntohl(addr->s6_addr32[3]), 1, 0), 358b1b8bc3fSopenharmony_ci BPF_STMT(BPF_RET | BPF_K, 0), 359b1b8bc3fSopenharmony_ci BPF_STMT(BPF_RET | BPF_K, 0xFFFFFFFF), 360b1b8bc3fSopenharmony_ci }; 361b1b8bc3fSopenharmony_ci sock_fprog filterProg = {sizeof(filter) / sizeof(filter[0]), filter}; 362b1b8bc3fSopenharmony_ci 363b1b8bc3fSopenharmony_ci if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filterProg, sizeof(filterProg))) { 364b1b8bc3fSopenharmony_ci auto err = errno; 365b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("attach packet filter failed: %{public}s", strerror(err)); 366b1b8bc3fSopenharmony_ci return -err; 367b1b8bc3fSopenharmony_ci } 368b1b8bc3fSopenharmony_ci 369b1b8bc3fSopenharmony_ci sockaddr_ll sll = { 370b1b8bc3fSopenharmony_ci .sll_family = AF_PACKET, 371b1b8bc3fSopenharmony_ci .sll_protocol = htons(ETH_P_IPV6), 372b1b8bc3fSopenharmony_ci .sll_ifindex = ifIndex, 373b1b8bc3fSopenharmony_ci .sll_pkttype = PACKET_OTHERHOST, 374b1b8bc3fSopenharmony_ci }; 375b1b8bc3fSopenharmony_ci if (bind(sock, reinterpret_cast<sockaddr *>(&sll), sizeof(sll))) { 376b1b8bc3fSopenharmony_ci auto err = errno; 377b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("binding packet socket failed: %{public}s", strerror(err)); 378b1b8bc3fSopenharmony_ci return -err; 379b1b8bc3fSopenharmony_ci } 380b1b8bc3fSopenharmony_ci return 0; 381b1b8bc3fSopenharmony_ci} 382b1b8bc3fSopenharmony_ci 383b1b8bc3fSopenharmony_ciint32_t ConfigureReadSocket(int sockFd, const std::string &addrStr, int ifIndex) 384b1b8bc3fSopenharmony_ci{ 385b1b8bc3fSopenharmony_ci if (sockFd < 0) { 386b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("Invalid file descriptor"); 387b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INVALID_PARAMETER; 388b1b8bc3fSopenharmony_ci } 389b1b8bc3fSopenharmony_ci 390b1b8bc3fSopenharmony_ci in6_addr addr; 391b1b8bc3fSopenharmony_ci if (inet_pton(AF_INET6, addrStr.c_str(), &addr) != 1) { 392b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("Invalid IPv6 address %{public}s", CommonUtils::ToAnonymousIp(addrStr).c_str()); 393b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INVALID_PARAMETER; 394b1b8bc3fSopenharmony_ci } 395b1b8bc3fSopenharmony_ci 396b1b8bc3fSopenharmony_ci int ret = AddFilterAndBindPacketSocket(sockFd, &addr, ifIndex); 397b1b8bc3fSopenharmony_ci if (ret < 0) { 398b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("configure packet socket failed"); 399b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 400b1b8bc3fSopenharmony_ci } 401b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 402b1b8bc3fSopenharmony_ci} 403b1b8bc3fSopenharmony_ci 404b1b8bc3fSopenharmony_ciint32_t SetTunInterfaceAddress(const std::string &ifName, const std::string &tunAddr, int32_t prefix) 405b1b8bc3fSopenharmony_ci{ 406b1b8bc3fSopenharmony_ci ifreq ifr = {}; 407b1b8bc3fSopenharmony_ci if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) { 408b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("memset_s ifr failed!"); 409b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 410b1b8bc3fSopenharmony_ci } 411b1b8bc3fSopenharmony_ci if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ifName.c_str(), strlen(ifName.c_str())) != EOK) { 412b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("strcpy_s ifr name fail"); 413b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 414b1b8bc3fSopenharmony_ci } 415b1b8bc3fSopenharmony_ci 416b1b8bc3fSopenharmony_ci in_addr ipv4Addr = {}; 417b1b8bc3fSopenharmony_ci if (inet_aton(tunAddr.c_str(), &ipv4Addr) == 0) { 418b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("addr inet_aton error"); 419b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 420b1b8bc3fSopenharmony_ci } 421b1b8bc3fSopenharmony_ci 422b1b8bc3fSopenharmony_ci int socketfd = socket(AF_INET, SOCK_DGRAM, 0); 423b1b8bc3fSopenharmony_ci auto sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_addr); 424b1b8bc3fSopenharmony_ci sin->sin_family = AF_INET; 425b1b8bc3fSopenharmony_ci sin->sin_addr = ipv4Addr; 426b1b8bc3fSopenharmony_ci if (ioctl(socketfd, SIOCSIFADDR, &ifr) < 0) { 427b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("ioctl set ipv4 address failed: %{public}d", errno); 428b1b8bc3fSopenharmony_ci close(socketfd); 429b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 430b1b8bc3fSopenharmony_ci } 431b1b8bc3fSopenharmony_ci 432b1b8bc3fSopenharmony_ci if (prefix <= 0 || prefix > V4ADDR_BIT_LEN) { 433b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("prefix: %{public}d error", prefix); 434b1b8bc3fSopenharmony_ci close(socketfd); 435b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 436b1b8bc3fSopenharmony_ci } 437b1b8bc3fSopenharmony_ci in_addr_t mask = prefix ? (~0 << (V4ADDR_BIT_LEN - prefix)) : 0; 438b1b8bc3fSopenharmony_ci sin = reinterpret_cast<sockaddr_in *>(&ifr.ifr_netmask); 439b1b8bc3fSopenharmony_ci sin->sin_family = AF_INET; 440b1b8bc3fSopenharmony_ci sin->sin_addr.s_addr = htonl(mask); 441b1b8bc3fSopenharmony_ci if (ioctl(socketfd, SIOCSIFNETMASK, &ifr) < 0) { 442b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("ioctl set ip mask failed: %{public}d", errno); 443b1b8bc3fSopenharmony_ci close(socketfd); 444b1b8bc3fSopenharmony_ci return NETMANAGER_ERROR; 445b1b8bc3fSopenharmony_ci } 446b1b8bc3fSopenharmony_ci close(socketfd); 447b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 448b1b8bc3fSopenharmony_ci} 449b1b8bc3fSopenharmony_ci 450b1b8bc3fSopenharmony_ci} // namespace nmd 451b1b8bc3fSopenharmony_ci} // namespace OHOS