1b1b8bc3fSopenharmony_ci/* 2b1b8bc3fSopenharmony_ci * Copyright (c) 2021-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 "clatd.h" 17b1b8bc3fSopenharmony_ci 18b1b8bc3fSopenharmony_ci#include <arpa/inet.h> 19b1b8bc3fSopenharmony_ci#include <cerrno> 20b1b8bc3fSopenharmony_ci#include <climits> 21b1b8bc3fSopenharmony_ci#include <cstdlib> 22b1b8bc3fSopenharmony_ci#include <linux/if_packet.h> 23b1b8bc3fSopenharmony_ci#include <net/if.h> 24b1b8bc3fSopenharmony_ci#include <netinet/icmp6.h> 25b1b8bc3fSopenharmony_ci#include <netinet/in.h> 26b1b8bc3fSopenharmony_ci#include <netinet/ip6.h> 27b1b8bc3fSopenharmony_ci#include <poll.h> 28b1b8bc3fSopenharmony_ci#include <string> 29b1b8bc3fSopenharmony_ci#include <sys/eventfd.h> 30b1b8bc3fSopenharmony_ci#include <sys/socket.h> 31b1b8bc3fSopenharmony_ci#include <thread> 32b1b8bc3fSopenharmony_ci#include <unistd.h> 33b1b8bc3fSopenharmony_ci#include <vector> 34b1b8bc3fSopenharmony_ci 35b1b8bc3fSopenharmony_ci#include "clat_constants.h" 36b1b8bc3fSopenharmony_ci#include "clat_utils.h" 37b1b8bc3fSopenharmony_ci#include "clatd_packet_converter.h" 38b1b8bc3fSopenharmony_ci#include "ffrt.h" 39b1b8bc3fSopenharmony_ci#include "ffrt_inner.h" 40b1b8bc3fSopenharmony_ci#include "ffrt_timer.h" 41b1b8bc3fSopenharmony_ci#include "net_manager_constants.h" 42b1b8bc3fSopenharmony_ci#include "netnative_log_wrapper.h" 43b1b8bc3fSopenharmony_ci 44b1b8bc3fSopenharmony_cinamespace OHOS { 45b1b8bc3fSopenharmony_cinamespace nmd { 46b1b8bc3fSopenharmony_ciusing namespace OHOS::NetManagerStandard; 47b1b8bc3fSopenharmony_ciClatd::Clatd(int tunFd, int readSock6, int writeSock6, const std::string &v6Iface, const std::string &prefixAddrStr, 48b1b8bc3fSopenharmony_ci const std::string &v4AddrStr, const std::string &v6AddrStr) 49b1b8bc3fSopenharmony_ci : tunFd_(tunFd), readSock6_(readSock6), writeSock6_(writeSock6), v6Iface_(v6Iface) 50b1b8bc3fSopenharmony_ci{ 51b1b8bc3fSopenharmony_ci stopFd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); 52b1b8bc3fSopenharmony_ci tunIface_ = std::string(CLAT_PREFIX) + v6Iface; 53b1b8bc3fSopenharmony_ci inet_pton(AF_INET6, v6AddrStr.c_str(), &v6Addr_); 54b1b8bc3fSopenharmony_ci inet_pton(AF_INET, v4AddrStr.c_str(), &v4Addr_.s_addr); 55b1b8bc3fSopenharmony_ci inet_pton(AF_INET6, prefixAddrStr.c_str(), &prefixAddr_); 56b1b8bc3fSopenharmony_ci isSocketClosed_ = false; 57b1b8bc3fSopenharmony_ci stopStatus_ = true; 58b1b8bc3fSopenharmony_ci} 59b1b8bc3fSopenharmony_ci 60b1b8bc3fSopenharmony_ciClatd::~Clatd() 61b1b8bc3fSopenharmony_ci{ 62b1b8bc3fSopenharmony_ci close(stopFd_); 63b1b8bc3fSopenharmony_ci} 64b1b8bc3fSopenharmony_ci 65b1b8bc3fSopenharmony_civoid Clatd::Start() 66b1b8bc3fSopenharmony_ci{ 67b1b8bc3fSopenharmony_ci if (!stopStatus_) { 68b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("fail to start clatd, clatd for %{public}s is already running", v6Iface_.c_str()); 69b1b8bc3fSopenharmony_ci return; 70b1b8bc3fSopenharmony_ci } 71b1b8bc3fSopenharmony_ci SendDadPacket(); 72b1b8bc3fSopenharmony_ci stopStatus_ = false; 73b1b8bc3fSopenharmony_ci std::thread([this]() { RunLoop(); }).detach(); 74b1b8bc3fSopenharmony_ci} 75b1b8bc3fSopenharmony_ci 76b1b8bc3fSopenharmony_civoid Clatd::Stop() 77b1b8bc3fSopenharmony_ci{ 78b1b8bc3fSopenharmony_ci if (stopStatus_) { 79b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("fail to stop clatd, clatd for %{public}s is not running", v6Iface_.c_str()); 80b1b8bc3fSopenharmony_ci return; 81b1b8bc3fSopenharmony_ci } 82b1b8bc3fSopenharmony_ci uint64_t one = 1; 83b1b8bc3fSopenharmony_ci write(stopFd_, &one, sizeof(one)); 84b1b8bc3fSopenharmony_ci 85b1b8bc3fSopenharmony_ci std::unique_lock<ffrt::mutex> lck(mutex_); 86b1b8bc3fSopenharmony_ci cv_.wait(lck, [this] { return stopStatus_ == true; }); 87b1b8bc3fSopenharmony_ci}; 88b1b8bc3fSopenharmony_ci 89b1b8bc3fSopenharmony_civoid Clatd::SendDadPacket() 90b1b8bc3fSopenharmony_ci{ 91b1b8bc3fSopenharmony_ci ClatdDadPacket dadPacket; 92b1b8bc3fSopenharmony_ci 93b1b8bc3fSopenharmony_ci dadPacket.v6Header.ip6_vfc = IPV6_VERSION_FLAG; 94b1b8bc3fSopenharmony_ci dadPacket.v6Header.ip6_plen = htons(sizeof(ClatdDadPacket) - sizeof(ip6_hdr)); 95b1b8bc3fSopenharmony_ci dadPacket.v6Header.ip6_nxt = IPPROTO_ICMPV6; 96b1b8bc3fSopenharmony_ci dadPacket.v6Header.ip6_hlim = 0xff; 97b1b8bc3fSopenharmony_ci inet_pton(AF_INET6, "::", &dadPacket.v6Header.ip6_src); 98b1b8bc3fSopenharmony_ci inet_pton(AF_INET6, SOLICITED_NODE_PREFIX, &dadPacket.v6Header.ip6_dst); 99b1b8bc3fSopenharmony_ci size_t v6AddrByteLen = V6ADDR_BIT_LEN / CHAR_BIT; 100b1b8bc3fSopenharmony_ci for (size_t i = SOLICITED_NODE_SUFFIX_OFFSET; i < v6AddrByteLen; i++) { 101b1b8bc3fSopenharmony_ci dadPacket.v6Header.ip6_dst.s6_addr[i] = v6Addr_.s6_addr[i]; 102b1b8bc3fSopenharmony_ci } 103b1b8bc3fSopenharmony_ci 104b1b8bc3fSopenharmony_ci dadPacket.ns.nd_ns_type = ND_NEIGHBOR_SOLICIT; 105b1b8bc3fSopenharmony_ci dadPacket.ns.nd_ns_code = 0; 106b1b8bc3fSopenharmony_ci dadPacket.ns.nd_ns_reserved = 0; 107b1b8bc3fSopenharmony_ci dadPacket.ns.nd_ns_target = v6Addr_; 108b1b8bc3fSopenharmony_ci uint32_t checkSum = dadPacket.v6Header.ip6_plen + htons(dadPacket.v6Header.ip6_nxt); 109b1b8bc3fSopenharmony_ci checkSum = AddChecksum(checkSum, &dadPacket.v6Header.ip6_src, sizeof(dadPacket) - IPV6_SRC_OFFSET); 110b1b8bc3fSopenharmony_ci dadPacket.ns.nd_ns_cksum = ~Checksum32To16(checkSum); 111b1b8bc3fSopenharmony_ci 112b1b8bc3fSopenharmony_ci dadPacket.nonceOptType = NDP_NOUNCE_OPT; 113b1b8bc3fSopenharmony_ci dadPacket.nonceOptLen = 1; 114b1b8bc3fSopenharmony_ci arc4random_buf(&dadPacket.nonce, sizeof(dadPacket.nonce)); 115b1b8bc3fSopenharmony_ci 116b1b8bc3fSopenharmony_ci sockaddr_in6 dstAddr; 117b1b8bc3fSopenharmony_ci dstAddr.sin6_family = AF_INET6; 118b1b8bc3fSopenharmony_ci dstAddr.sin6_addr = dadPacket.v6Header.ip6_dst; 119b1b8bc3fSopenharmony_ci dstAddr.sin6_scope_id = if_nametoindex(v6Iface_.c_str()); 120b1b8bc3fSopenharmony_ci 121b1b8bc3fSopenharmony_ci sendto(writeSock6_, &dadPacket, sizeof(dadPacket), 0, reinterpret_cast<const sockaddr *>(&dstAddr), 122b1b8bc3fSopenharmony_ci sizeof(dstAddr)); 123b1b8bc3fSopenharmony_ci} 124b1b8bc3fSopenharmony_ci 125b1b8bc3fSopenharmony_civoid Clatd::RunLoop() 126b1b8bc3fSopenharmony_ci{ 127b1b8bc3fSopenharmony_ci pollfd fds[] = { 128b1b8bc3fSopenharmony_ci {stopFd_, POLLIN, 0}, 129b1b8bc3fSopenharmony_ci {readSock6_, POLLIN, 0}, 130b1b8bc3fSopenharmony_ci {tunFd_, POLLIN, 0}, 131b1b8bc3fSopenharmony_ci }; 132b1b8bc3fSopenharmony_ci enum clatdFds { 133b1b8bc3fSopenharmony_ci EVENT_STOP, 134b1b8bc3fSopenharmony_ci READ_V6, 135b1b8bc3fSopenharmony_ci READ_V4, 136b1b8bc3fSopenharmony_ci }; 137b1b8bc3fSopenharmony_ci FfrtTimer timerClatdRunning; 138b1b8bc3fSopenharmony_ci timerClatdRunning.Start(CLATD_TIMER_CYCLE_MS, []() { NETNATIVE_LOGI("Clatd is running loop"); }); 139b1b8bc3fSopenharmony_ci while (!isSocketClosed_) { 140b1b8bc3fSopenharmony_ci if (poll(fds, sizeof(fds) / sizeof((fds)[0]), -1) == -1) { 141b1b8bc3fSopenharmony_ci if (errno != EINTR) { 142b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("event_loop/poll returned an error, errno: %{public}d", errno); 143b1b8bc3fSopenharmony_ci } 144b1b8bc3fSopenharmony_ci } else { 145b1b8bc3fSopenharmony_ci if (fds[EVENT_STOP].revents) { 146b1b8bc3fSopenharmony_ci uint64_t one = 1; 147b1b8bc3fSopenharmony_ci read(stopFd_, &one, sizeof one); 148b1b8bc3fSopenharmony_ci std::unique_lock<ffrt::mutex> lck(mutex_); 149b1b8bc3fSopenharmony_ci stopStatus_ = true; 150b1b8bc3fSopenharmony_ci cv_.notify_one(); 151b1b8bc3fSopenharmony_ci break; 152b1b8bc3fSopenharmony_ci } 153b1b8bc3fSopenharmony_ci if (fds[READ_V6].revents) { 154b1b8bc3fSopenharmony_ci ProcessV6Packet(); 155b1b8bc3fSopenharmony_ci } 156b1b8bc3fSopenharmony_ci if (fds[READ_V4].revents) { 157b1b8bc3fSopenharmony_ci ProcessV4Packet(); 158b1b8bc3fSopenharmony_ci } 159b1b8bc3fSopenharmony_ci } 160b1b8bc3fSopenharmony_ci } 161b1b8bc3fSopenharmony_ci timerClatdRunning.Stop(); 162b1b8bc3fSopenharmony_ci} 163b1b8bc3fSopenharmony_ci 164b1b8bc3fSopenharmony_ciint32_t Clatd::MaybeCalculateL4Checksum(int packetLen, ClatdReadV6Buf &readBuf) 165b1b8bc3fSopenharmony_ci{ 166b1b8bc3fSopenharmony_ci const int csumStart = readBuf.vnet.csumStart; 167b1b8bc3fSopenharmony_ci const int csumOffset = csumStart + readBuf.vnet.csumOffset; 168b1b8bc3fSopenharmony_ci if (csumOffset > packetLen) { 169b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("csum offset %{public}d larger than packet length %{public}d", csumOffset, packetLen); 170b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INVALID_PARAMETER; 171b1b8bc3fSopenharmony_ci } 172b1b8bc3fSopenharmony_ci uint16_t csum = CalChecksum(readBuf.payload, packetLen); // L4 checksum calculation required 173b1b8bc3fSopenharmony_ci if (csum == 0) { 174b1b8bc3fSopenharmony_ci csum = 0xFFFF; 175b1b8bc3fSopenharmony_ci } 176b1b8bc3fSopenharmony_ci readBuf.payload[csumOffset] = csum & 0xFF; 177b1b8bc3fSopenharmony_ci readBuf.payload[csumOffset + 1] = csum >> CHAR_BIT; 178b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 179b1b8bc3fSopenharmony_ci} 180b1b8bc3fSopenharmony_ci 181b1b8bc3fSopenharmony_civoid Clatd::ProcessV6Packet() 182b1b8bc3fSopenharmony_ci{ 183b1b8bc3fSopenharmony_ci ClatdReadV6Buf readBuf; 184b1b8bc3fSopenharmony_ci iovec iov; 185b1b8bc3fSopenharmony_ci iov.iov_base = &readBuf; 186b1b8bc3fSopenharmony_ci iov.iov_len = sizeof(readBuf); 187b1b8bc3fSopenharmony_ci 188b1b8bc3fSopenharmony_ci char cmsgBuf[CMSG_SPACE(sizeof(tpacket_auxdata))]; 189b1b8bc3fSopenharmony_ci msghdr msgHdr; 190b1b8bc3fSopenharmony_ci msgHdr.msg_iov = &iov; 191b1b8bc3fSopenharmony_ci msgHdr.msg_iovlen = 1; 192b1b8bc3fSopenharmony_ci msgHdr.msg_control = cmsgBuf; 193b1b8bc3fSopenharmony_ci msgHdr.msg_controllen = sizeof(cmsgBuf); 194b1b8bc3fSopenharmony_ci 195b1b8bc3fSopenharmony_ci ssize_t readLen; 196b1b8bc3fSopenharmony_ci if (ReadV6Packet(msgHdr, readLen) != NETMANAGER_SUCCESS) { 197b1b8bc3fSopenharmony_ci return; 198b1b8bc3fSopenharmony_ci } 199b1b8bc3fSopenharmony_ci 200b1b8bc3fSopenharmony_ci uint32_t tpStatus = 0; 201b1b8bc3fSopenharmony_ci uint16_t tpNet = 0; 202b1b8bc3fSopenharmony_ci for (cmsghdr *cmsgHdr = CMSG_FIRSTHDR(&msgHdr); cmsgHdr != NULL; cmsgHdr = CMSG_NXTHDR(&msgHdr, cmsgHdr)) { 203b1b8bc3fSopenharmony_ci if (cmsgHdr->cmsg_level == SOL_PACKET && cmsgHdr->cmsg_type == PACKET_AUXDATA) { 204b1b8bc3fSopenharmony_ci tpacket_auxdata *auxData = reinterpret_cast<tpacket_auxdata *>(CMSG_DATA(cmsgHdr)); 205b1b8bc3fSopenharmony_ci tpStatus = auxData->tp_status; 206b1b8bc3fSopenharmony_ci tpNet = auxData->tp_net; 207b1b8bc3fSopenharmony_ci break; 208b1b8bc3fSopenharmony_ci } 209b1b8bc3fSopenharmony_ci } 210b1b8bc3fSopenharmony_ci 211b1b8bc3fSopenharmony_ci if (static_cast<size_t>(readLen) < offsetof(ClatdReadV6Buf, payload) + tpNet) { 212b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("%{public}zd read packet len shorter than %{public}u L2 header", readLen, tpNet); 213b1b8bc3fSopenharmony_ci return; 214b1b8bc3fSopenharmony_ci } 215b1b8bc3fSopenharmony_ci 216b1b8bc3fSopenharmony_ci int packetLen = readLen - offsetof(ClatdReadV6Buf, payload); 217b1b8bc3fSopenharmony_ci bool skip_csum = false; 218b1b8bc3fSopenharmony_ci if ((tpStatus & TP_STATUS_CSUMNOTREADY) || (tpStatus & TP_STATUS_CSUM_VALID)) { 219b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("skip csum for packet which length is %{public}zd", readLen); 220b1b8bc3fSopenharmony_ci skip_csum = true; 221b1b8bc3fSopenharmony_ci } 222b1b8bc3fSopenharmony_ci 223b1b8bc3fSopenharmony_ci ClatdPacketConverter converter = ClatdPacketConverter(readBuf.payload + tpNet, packetLen - tpNet, 224b1b8bc3fSopenharmony_ci CONVERT_FROM_V6_TO_V4, v4Addr_, v6Addr_, prefixAddr_); 225b1b8bc3fSopenharmony_ci if (converter.ConvertPacket(skip_csum) != NETMANAGER_SUCCESS) { 226b1b8bc3fSopenharmony_ci return; 227b1b8bc3fSopenharmony_ci } 228b1b8bc3fSopenharmony_ci std::vector<iovec> iovPackets(CLATD_MAX); 229b1b8bc3fSopenharmony_ci int effectivePos = 0; 230b1b8bc3fSopenharmony_ci converter.GetConvertedPacket(iovPackets, effectivePos); 231b1b8bc3fSopenharmony_ci if (effectivePos > 0) { 232b1b8bc3fSopenharmony_ci writev(tunFd_, &iovPackets[0], effectivePos); 233b1b8bc3fSopenharmony_ci } 234b1b8bc3fSopenharmony_ci} 235b1b8bc3fSopenharmony_ci 236b1b8bc3fSopenharmony_civoid Clatd::ProcessV4Packet() 237b1b8bc3fSopenharmony_ci{ 238b1b8bc3fSopenharmony_ci ClatdReadTunBuf readBuf; 239b1b8bc3fSopenharmony_ci ssize_t readLen; 240b1b8bc3fSopenharmony_ci if (ReadV4Packet(readBuf, readLen) != NETMANAGER_SUCCESS) { 241b1b8bc3fSopenharmony_ci return; 242b1b8bc3fSopenharmony_ci } 243b1b8bc3fSopenharmony_ci 244b1b8bc3fSopenharmony_ci const int payloadOffset = offsetof(ClatdReadTunBuf, payload); 245b1b8bc3fSopenharmony_ci if (readLen < payloadOffset) { 246b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("%{public}zd read packet len shorter than %{public}d payload offset", readLen, payloadOffset); 247b1b8bc3fSopenharmony_ci return; 248b1b8bc3fSopenharmony_ci } 249b1b8bc3fSopenharmony_ci 250b1b8bc3fSopenharmony_ci const int packetLen = readLen - payloadOffset; 251b1b8bc3fSopenharmony_ci 252b1b8bc3fSopenharmony_ci uint16_t tunProtocol = ntohs(readBuf.tunProtocolInfo.proto); 253b1b8bc3fSopenharmony_ci if (tunProtocol != ETH_P_IP) { 254b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("unknown packet type = 0x%{public}x", tunProtocol); 255b1b8bc3fSopenharmony_ci return; 256b1b8bc3fSopenharmony_ci } 257b1b8bc3fSopenharmony_ci 258b1b8bc3fSopenharmony_ci if (readBuf.tunProtocolInfo.flags != 0) { 259b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("unexpected flags = %{public}d", readBuf.tunProtocolInfo.flags); 260b1b8bc3fSopenharmony_ci } 261b1b8bc3fSopenharmony_ci 262b1b8bc3fSopenharmony_ci ClatdPacketConverter converter = 263b1b8bc3fSopenharmony_ci ClatdPacketConverter(readBuf.payload, packetLen, CONVERT_FROM_V4_TO_V6, v4Addr_, v6Addr_, prefixAddr_); 264b1b8bc3fSopenharmony_ci bool skip_csum = false; 265b1b8bc3fSopenharmony_ci if (converter.ConvertPacket(skip_csum) != NETMANAGER_SUCCESS) { 266b1b8bc3fSopenharmony_ci return; 267b1b8bc3fSopenharmony_ci } 268b1b8bc3fSopenharmony_ci std::vector<iovec> iovPackets(CLATD_MAX); 269b1b8bc3fSopenharmony_ci int effectivePos = 0; 270b1b8bc3fSopenharmony_ci converter.GetConvertedPacket(iovPackets, effectivePos); 271b1b8bc3fSopenharmony_ci if (effectivePos > 0) { 272b1b8bc3fSopenharmony_ci SendV6OnRawSocket(writeSock6_, iovPackets, effectivePos); 273b1b8bc3fSopenharmony_ci } 274b1b8bc3fSopenharmony_ci} 275b1b8bc3fSopenharmony_ci 276b1b8bc3fSopenharmony_ciint32_t Clatd::ReadV6Packet(msghdr &msgHdr, ssize_t &readLen) 277b1b8bc3fSopenharmony_ci{ 278b1b8bc3fSopenharmony_ci readLen = recvmsg(readSock6_, &msgHdr, 0); 279b1b8bc3fSopenharmony_ci if (readLen < 0) { 280b1b8bc3fSopenharmony_ci if (errno != EAGAIN) { 281b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("recvmsg failed: %{public}s", strerror(errno)); 282b1b8bc3fSopenharmony_ci } 283b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 284b1b8bc3fSopenharmony_ci } else if (readLen == 0) { 285b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("recvmsg failed: socket closed"); 286b1b8bc3fSopenharmony_ci isSocketClosed_ = true; 287b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 288b1b8bc3fSopenharmony_ci } else if (static_cast<size_t>(readLen) >= sizeof(ClatdReadV6Buf)) { 289b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("recvmsg failed: packet oversize, readLen: %{public}zu, sizeof(ClatdReadV6Buf): %{public}zu", static_cast<size_t>(readLen), sizeof(ClatdReadV6Buf)); 290b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 291b1b8bc3fSopenharmony_ci } 292b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 293b1b8bc3fSopenharmony_ci} 294b1b8bc3fSopenharmony_ci 295b1b8bc3fSopenharmony_ciint32_t Clatd::ReadV4Packet(ClatdReadTunBuf &readBuf, ssize_t &readLen) 296b1b8bc3fSopenharmony_ci{ 297b1b8bc3fSopenharmony_ci readLen = read(tunFd_, reinterpret_cast<iovec *>(&readBuf), sizeof(readBuf)); 298b1b8bc3fSopenharmony_ci if (readLen < 0) { 299b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("read failed: %{public}s", strerror(errno)); 300b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 301b1b8bc3fSopenharmony_ci } else if (readLen == 0) { 302b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("read failed: socket closed"); 303b1b8bc3fSopenharmony_ci isSocketClosed_ = true; 304b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 305b1b8bc3fSopenharmony_ci } else if (static_cast<size_t>(readLen) >= sizeof(readBuf)) { 306b1b8bc3fSopenharmony_ci NETNATIVE_LOGW("read failed: packet oversize"); 307b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 308b1b8bc3fSopenharmony_ci } 309b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 310b1b8bc3fSopenharmony_ci} 311b1b8bc3fSopenharmony_ci 312b1b8bc3fSopenharmony_civoid Clatd::SendV6OnRawSocket(int fd, std::vector<iovec> &iovPackets, int effectivePos) 313b1b8bc3fSopenharmony_ci{ 314b1b8bc3fSopenharmony_ci static sockaddr_in6 sin6 = {AF_INET6, 0, 0, {{{0, 0, 0, 0}}}, 0}; 315b1b8bc3fSopenharmony_ci static msghdr msgHeader; 316b1b8bc3fSopenharmony_ci msgHeader.msg_name = &sin6; 317b1b8bc3fSopenharmony_ci msgHeader.msg_namelen = sizeof(sin6); 318b1b8bc3fSopenharmony_ci 319b1b8bc3fSopenharmony_ci msgHeader.msg_iov = &iovPackets[0]; 320b1b8bc3fSopenharmony_ci msgHeader.msg_iovlen = effectivePos; 321b1b8bc3fSopenharmony_ci sin6.sin6_addr = reinterpret_cast<struct ip6_hdr *>(iovPackets[CLATD_TPHDR].iov_base)->ip6_dst; 322b1b8bc3fSopenharmony_ci sendmsg(fd, &msgHeader, 0); 323b1b8bc3fSopenharmony_ci} 324b1b8bc3fSopenharmony_ci 325b1b8bc3fSopenharmony_ci} // namespace nmd 326b1b8bc3fSopenharmony_ci} // namespace OHOS