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