1518678f8Sopenharmony_ci/*
2518678f8Sopenharmony_ci * Copyright (C) 2024 Huawei Device Co., Ltd.
3518678f8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4518678f8Sopenharmony_ci * you may not use this file except in compliance with the License.
5518678f8Sopenharmony_ci * You may obtain a copy of the License at
6518678f8Sopenharmony_ci *
7518678f8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8518678f8Sopenharmony_ci *
9518678f8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10518678f8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11518678f8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12518678f8Sopenharmony_ci * See the License for the specific language governing permissions and
13518678f8Sopenharmony_ci * limitations under the License.
14518678f8Sopenharmony_ci */
15518678f8Sopenharmony_ci
16518678f8Sopenharmony_ci#include "dhcp_arp_checker.h"
17518678f8Sopenharmony_ci
18518678f8Sopenharmony_ci#include <cerrno>
19518678f8Sopenharmony_ci#include <chrono>
20518678f8Sopenharmony_ci#include <fcntl.h>
21518678f8Sopenharmony_ci#include <net/if_arp.h>
22518678f8Sopenharmony_ci#include <net/if.h>
23518678f8Sopenharmony_ci#include <netpacket/packet.h>
24518678f8Sopenharmony_ci#include <poll.h>
25518678f8Sopenharmony_ci#include <sys/socket.h>
26518678f8Sopenharmony_ci#include <unistd.h>
27518678f8Sopenharmony_ci
28518678f8Sopenharmony_ci#include "securec.h"
29518678f8Sopenharmony_ci#include "dhcp_common_utils.h"
30518678f8Sopenharmony_ci#include "dhcp_logger.h"
31518678f8Sopenharmony_ci
32518678f8Sopenharmony_cinamespace OHOS {
33518678f8Sopenharmony_cinamespace DHCP {
34518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpArpChecker");
35518678f8Sopenharmony_ciconstexpr int32_t MAX_LENGTH = 1500;
36518678f8Sopenharmony_ciconstexpr int32_t OPT_SUCC = 0;
37518678f8Sopenharmony_ciconstexpr int32_t OPT_FAIL = -1;
38518678f8Sopenharmony_ci
39518678f8Sopenharmony_ciDhcpArpChecker::DhcpArpChecker() : m_isSocketCreated(false), m_socketFd(-1), m_ifaceIndex(0), m_protocol(0)
40518678f8Sopenharmony_ci{
41518678f8Sopenharmony_ci    DHCP_LOGI("DhcpArpChecker()");
42518678f8Sopenharmony_ci}
43518678f8Sopenharmony_ci
44518678f8Sopenharmony_ciDhcpArpChecker::~DhcpArpChecker()
45518678f8Sopenharmony_ci{
46518678f8Sopenharmony_ci    DHCP_LOGI("~DhcpArpChecker()");
47518678f8Sopenharmony_ci    Stop();
48518678f8Sopenharmony_ci}
49518678f8Sopenharmony_ci
50518678f8Sopenharmony_cibool DhcpArpChecker::Start(std::string& ifname, std::string& hwAddr, std::string& senderIp, std::string& targetIp)
51518678f8Sopenharmony_ci{
52518678f8Sopenharmony_ci    if (m_isSocketCreated) {
53518678f8Sopenharmony_ci        Stop();
54518678f8Sopenharmony_ci    }
55518678f8Sopenharmony_ci    uint8_t mac[ETH_ALEN + sizeof(uint32_t)];
56518678f8Sopenharmony_ci    if (sscanf_s(hwAddr.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x",
57518678f8Sopenharmony_ci        &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != ETH_ALEN) {  // mac address
58518678f8Sopenharmony_ci        DHCP_LOGE("invalid hwAddr:%{private}s", hwAddr.c_str());
59518678f8Sopenharmony_ci        if (memset_s(mac, sizeof(mac), 0, sizeof(mac)) != EOK) {
60518678f8Sopenharmony_ci            DHCP_LOGE("ArpChecker memset fail");
61518678f8Sopenharmony_ci        }
62518678f8Sopenharmony_ci    }
63518678f8Sopenharmony_ci
64518678f8Sopenharmony_ci    if (CreateSocket(ifname.c_str(), ETH_P_ARP) != 0) {
65518678f8Sopenharmony_ci        DHCP_LOGE("DhcpArpChecker CreateSocket failed");
66518678f8Sopenharmony_ci        m_isSocketCreated = false;
67518678f8Sopenharmony_ci        return false;
68518678f8Sopenharmony_ci    }
69518678f8Sopenharmony_ci    inet_aton(senderIp.c_str(), &m_localIpAddr);
70518678f8Sopenharmony_ci    if (memcpy_s(m_localMacAddr, ETH_ALEN, mac, ETH_ALEN) != EOK) {
71518678f8Sopenharmony_ci        DHCP_LOGE("DhcpArpChecker memcpy fail");
72518678f8Sopenharmony_ci        return false;
73518678f8Sopenharmony_ci    }
74518678f8Sopenharmony_ci    if (memset_s(m_l2Broadcast, ETH_ALEN, 0xFF, ETH_ALEN) != EOK) {
75518678f8Sopenharmony_ci        DHCP_LOGE("DhcpArpChecker memset fail");
76518678f8Sopenharmony_ci        return false;
77518678f8Sopenharmony_ci    }
78518678f8Sopenharmony_ci    inet_aton(targetIp.c_str(), &m_targetIpAddr);
79518678f8Sopenharmony_ci    m_isSocketCreated = true;
80518678f8Sopenharmony_ci    return true;
81518678f8Sopenharmony_ci}
82518678f8Sopenharmony_ci
83518678f8Sopenharmony_civoid DhcpArpChecker::Stop()
84518678f8Sopenharmony_ci{
85518678f8Sopenharmony_ci    if (!m_isSocketCreated) {
86518678f8Sopenharmony_ci        return;
87518678f8Sopenharmony_ci    }
88518678f8Sopenharmony_ci    CloseSocket();
89518678f8Sopenharmony_ci    m_isSocketCreated = false;
90518678f8Sopenharmony_ci}
91518678f8Sopenharmony_ci
92518678f8Sopenharmony_cibool DhcpArpChecker::SetArpPacket(ArpPacket& arpPacket, bool isFillSenderIp)
93518678f8Sopenharmony_ci{
94518678f8Sopenharmony_ci    arpPacket.ar_hrd = htons(ARPHRD_ETHER);
95518678f8Sopenharmony_ci    arpPacket.ar_pro = htons(ETH_P_IP);
96518678f8Sopenharmony_ci    arpPacket.ar_hln = ETH_ALEN;
97518678f8Sopenharmony_ci    arpPacket.ar_pln = IPV4_ALEN;
98518678f8Sopenharmony_ci    arpPacket.ar_op = htons(ARPOP_REQUEST);
99518678f8Sopenharmony_ci    if (memcpy_s(arpPacket.ar_sha, ETH_ALEN, m_localMacAddr, ETH_ALEN) != EOK) {
100518678f8Sopenharmony_ci        DHCP_LOGE("DoArpCheck memcpy fail");
101518678f8Sopenharmony_ci        return false;
102518678f8Sopenharmony_ci    }
103518678f8Sopenharmony_ci    if (isFillSenderIp) {
104518678f8Sopenharmony_ci        if (memcpy_s(arpPacket.ar_spa, IPV4_ALEN, &m_localIpAddr, sizeof(m_localIpAddr)) != EOK) {
105518678f8Sopenharmony_ci            DHCP_LOGE("DoArpCheck memcpy fail");
106518678f8Sopenharmony_ci            return false;
107518678f8Sopenharmony_ci        }
108518678f8Sopenharmony_ci    } else {
109518678f8Sopenharmony_ci        if (memset_s(arpPacket.ar_spa, IPV4_ALEN, 0, IPV4_ALEN) != EOK) {
110518678f8Sopenharmony_ci            DHCP_LOGE("DoArpCheck memset fail");
111518678f8Sopenharmony_ci            return false;
112518678f8Sopenharmony_ci        }
113518678f8Sopenharmony_ci    }
114518678f8Sopenharmony_ci    if (memset_s(arpPacket.ar_tha, ETH_ALEN, 0, ETH_ALEN) != EOK) {
115518678f8Sopenharmony_ci        DHCP_LOGE("DoArpCheck memset fail");
116518678f8Sopenharmony_ci        return false;
117518678f8Sopenharmony_ci    }
118518678f8Sopenharmony_ci    if (memcpy_s(arpPacket.ar_tpa, IPV4_ALEN, &m_targetIpAddr, sizeof(m_targetIpAddr)) != EOK) {
119518678f8Sopenharmony_ci        DHCP_LOGE("DoArpCheck memcpy fail");
120518678f8Sopenharmony_ci        return false;
121518678f8Sopenharmony_ci    }
122518678f8Sopenharmony_ci    return true;
123518678f8Sopenharmony_ci}
124518678f8Sopenharmony_ci
125518678f8Sopenharmony_cibool DhcpArpChecker::DoArpCheck(int32_t timeoutMillis, bool isFillSenderIp, uint64_t &timeCost)
126518678f8Sopenharmony_ci{
127518678f8Sopenharmony_ci    if (!m_isSocketCreated) {
128518678f8Sopenharmony_ci        DHCP_LOGE("DoArpCheck failed, socket not created");
129518678f8Sopenharmony_ci        return false;
130518678f8Sopenharmony_ci    }
131518678f8Sopenharmony_ci    struct ArpPacket arpPacket;
132518678f8Sopenharmony_ci    if (!SetArpPacket(arpPacket, isFillSenderIp)) {
133518678f8Sopenharmony_ci        DHCP_LOGE("SetArpPacket failed");
134518678f8Sopenharmony_ci        return false;
135518678f8Sopenharmony_ci    }
136518678f8Sopenharmony_ci
137518678f8Sopenharmony_ci    if (SendData(reinterpret_cast<uint8_t *>(&arpPacket), sizeof(arpPacket), m_l2Broadcast) != 0) {
138518678f8Sopenharmony_ci        return false;
139518678f8Sopenharmony_ci    }
140518678f8Sopenharmony_ci    timeCost = 0;
141518678f8Sopenharmony_ci    int32_t readLen = 0;
142518678f8Sopenharmony_ci    int64_t elapsed = 0;
143518678f8Sopenharmony_ci    int32_t leftMillis = timeoutMillis;
144518678f8Sopenharmony_ci    uint8_t recvBuff[MAX_LENGTH];
145518678f8Sopenharmony_ci    std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
146518678f8Sopenharmony_ci    while (leftMillis > 0) {
147518678f8Sopenharmony_ci        readLen = RecvData(recvBuff, sizeof(recvBuff), leftMillis);
148518678f8Sopenharmony_ci        if (readLen >= static_cast<int32_t>(sizeof(struct ArpPacket))) {
149518678f8Sopenharmony_ci            struct ArpPacket *respPacket = reinterpret_cast<struct ArpPacket*>(recvBuff);
150518678f8Sopenharmony_ci            if (ntohs(respPacket->ar_hrd) == ARPHRD_ETHER &&
151518678f8Sopenharmony_ci                ntohs(respPacket->ar_pro) == ETH_P_IP &&
152518678f8Sopenharmony_ci                respPacket->ar_hln == ETH_ALEN &&
153518678f8Sopenharmony_ci                respPacket->ar_pln == IPV4_ALEN &&
154518678f8Sopenharmony_ci                ntohs(respPacket->ar_op) == ARPOP_REPLY &&
155518678f8Sopenharmony_ci                memcmp(respPacket->ar_sha, m_localMacAddr, ETH_ALEN) != 0 &&
156518678f8Sopenharmony_ci                memcmp(respPacket->ar_spa, &m_targetIpAddr, IPV4_ALEN) == 0) {
157518678f8Sopenharmony_ci                std::chrono::steady_clock::time_point current = std::chrono::steady_clock::now();
158518678f8Sopenharmony_ci                timeCost = static_cast<uint64_t>(
159518678f8Sopenharmony_ci                    std::chrono::duration_cast<std::chrono::milliseconds>(current - startTime).count());
160518678f8Sopenharmony_ci                return true;
161518678f8Sopenharmony_ci            }
162518678f8Sopenharmony_ci        } else if (readLen < 0) {
163518678f8Sopenharmony_ci            DHCP_LOGE("readLen < 0, stop arp");
164518678f8Sopenharmony_ci            return false;
165518678f8Sopenharmony_ci        }
166518678f8Sopenharmony_ci        std::chrono::steady_clock::time_point current = std::chrono::steady_clock::now();
167518678f8Sopenharmony_ci        elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(current - startTime).count();
168518678f8Sopenharmony_ci        leftMillis -= static_cast<int32_t>(elapsed);
169518678f8Sopenharmony_ci    }
170518678f8Sopenharmony_ci    return false;
171518678f8Sopenharmony_ci}
172518678f8Sopenharmony_ci
173518678f8Sopenharmony_civoid DhcpArpChecker::GetGwMacAddrList(int32_t timeoutMillis, bool isFillSenderIp, std::vector<std::string>& gwMacLists)
174518678f8Sopenharmony_ci{
175518678f8Sopenharmony_ci    gwMacLists.clear();
176518678f8Sopenharmony_ci    if (!m_isSocketCreated) {
177518678f8Sopenharmony_ci        DHCP_LOGE("GetGwMacAddrList failed, socket not created");
178518678f8Sopenharmony_ci        return;
179518678f8Sopenharmony_ci    }
180518678f8Sopenharmony_ci    struct ArpPacket arpPacket;
181518678f8Sopenharmony_ci    if (!SetArpPacket(arpPacket, isFillSenderIp)) {
182518678f8Sopenharmony_ci        DHCP_LOGE("GetGwMacAddrList SetArpPacket failed");
183518678f8Sopenharmony_ci        return;
184518678f8Sopenharmony_ci    }
185518678f8Sopenharmony_ci
186518678f8Sopenharmony_ci    if (SendData(reinterpret_cast<uint8_t *>(&arpPacket), sizeof(arpPacket), m_l2Broadcast) != 0) {
187518678f8Sopenharmony_ci        DHCP_LOGE("GetGwMacAddrList SendData failed");
188518678f8Sopenharmony_ci        return;
189518678f8Sopenharmony_ci    }
190518678f8Sopenharmony_ci    int32_t readLen = 0;
191518678f8Sopenharmony_ci    int32_t leftMillis = timeoutMillis;
192518678f8Sopenharmony_ci    uint8_t recvBuff[MAX_LENGTH];
193518678f8Sopenharmony_ci    std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
194518678f8Sopenharmony_ci    while (leftMillis > 0) {
195518678f8Sopenharmony_ci        readLen = RecvData(recvBuff, sizeof(recvBuff), leftMillis);
196518678f8Sopenharmony_ci        if (readLen >= static_cast<int32_t>(sizeof(struct ArpPacket))) {
197518678f8Sopenharmony_ci            struct ArpPacket *respPacket = reinterpret_cast<struct ArpPacket*>(recvBuff);
198518678f8Sopenharmony_ci            if (ntohs(respPacket->ar_hrd) == ARPHRD_ETHER &&
199518678f8Sopenharmony_ci                ntohs(respPacket->ar_pro) == ETH_P_IP &&
200518678f8Sopenharmony_ci                respPacket->ar_hln == ETH_ALEN &&
201518678f8Sopenharmony_ci                respPacket->ar_pln == IPV4_ALEN &&
202518678f8Sopenharmony_ci                ntohs(respPacket->ar_op) == ARPOP_REPLY &&
203518678f8Sopenharmony_ci                memcmp(respPacket->ar_sha, m_localMacAddr, ETH_ALEN) != 0 &&
204518678f8Sopenharmony_ci                memcmp(respPacket->ar_spa, &m_targetIpAddr, IPV4_ALEN) == 0) {
205518678f8Sopenharmony_ci                std::string gwMacAddr = MacArray2Str(respPacket->ar_sha, ETH_ALEN);
206518678f8Sopenharmony_ci                SaveGwMacAddr(gwMacAddr, gwMacLists);
207518678f8Sopenharmony_ci            }
208518678f8Sopenharmony_ci        }
209518678f8Sopenharmony_ci        std::chrono::steady_clock::time_point current = std::chrono::steady_clock::now();
210518678f8Sopenharmony_ci        int64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(current - startTime).count();
211518678f8Sopenharmony_ci        leftMillis -= static_cast<int32_t>(elapsed);
212518678f8Sopenharmony_ci    }
213518678f8Sopenharmony_ci}
214518678f8Sopenharmony_ci
215518678f8Sopenharmony_civoid DhcpArpChecker::SaveGwMacAddr(std::string gwMacAddr, std::vector<std::string>& gwMacLists)
216518678f8Sopenharmony_ci{
217518678f8Sopenharmony_ci    auto it = std::find(gwMacLists.begin(), gwMacLists.end(), gwMacAddr);
218518678f8Sopenharmony_ci    if (!gwMacAddr.empty() && (it == gwMacLists.end())) {
219518678f8Sopenharmony_ci        gwMacLists.push_back(gwMacAddr);
220518678f8Sopenharmony_ci    }
221518678f8Sopenharmony_ci}
222518678f8Sopenharmony_ci
223518678f8Sopenharmony_ciint32_t DhcpArpChecker::CreateSocket(const char *iface, uint16_t protocol)
224518678f8Sopenharmony_ci{
225518678f8Sopenharmony_ci    if (iface == nullptr) {
226518678f8Sopenharmony_ci        DHCP_LOGE("iface is null");
227518678f8Sopenharmony_ci        return OPT_FAIL;
228518678f8Sopenharmony_ci    }
229518678f8Sopenharmony_ci
230518678f8Sopenharmony_ci    int32_t ifaceIndex = static_cast<int32_t>(if_nametoindex(iface));
231518678f8Sopenharmony_ci    if (ifaceIndex == 0) {
232518678f8Sopenharmony_ci        DHCP_LOGE("get iface index fail: %{public}s", iface);
233518678f8Sopenharmony_ci        return OPT_FAIL;
234518678f8Sopenharmony_ci    }
235518678f8Sopenharmony_ci    if (ifaceIndex > INTEGER_MAX) {
236518678f8Sopenharmony_ci        DHCP_LOGE("ifaceIndex > max interger, fail:%{public}s ifaceIndex:%{public}d", iface, ifaceIndex);
237518678f8Sopenharmony_ci        return OPT_FAIL;
238518678f8Sopenharmony_ci    }
239518678f8Sopenharmony_ci    int32_t socketFd = socket(PF_PACKET, SOCK_DGRAM, htons(protocol));
240518678f8Sopenharmony_ci    if (socketFd < 0) {
241518678f8Sopenharmony_ci        DHCP_LOGE("create socket fail");
242518678f8Sopenharmony_ci        return OPT_FAIL;
243518678f8Sopenharmony_ci    }
244518678f8Sopenharmony_ci
245518678f8Sopenharmony_ci    if (SetNonBlock(socketFd)) {
246518678f8Sopenharmony_ci        DHCP_LOGE("set non block fail");
247518678f8Sopenharmony_ci        (void)close(socketFd);
248518678f8Sopenharmony_ci        return OPT_FAIL;
249518678f8Sopenharmony_ci    }
250518678f8Sopenharmony_ci
251518678f8Sopenharmony_ci    struct sockaddr_ll rawAddr;
252518678f8Sopenharmony_ci    rawAddr.sll_ifindex = ifaceIndex;
253518678f8Sopenharmony_ci    rawAddr.sll_protocol = htons(protocol);
254518678f8Sopenharmony_ci    rawAddr.sll_family = AF_PACKET;
255518678f8Sopenharmony_ci
256518678f8Sopenharmony_ci    int32_t ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&rawAddr), sizeof(rawAddr));
257518678f8Sopenharmony_ci    if (ret != 0) {
258518678f8Sopenharmony_ci        DHCP_LOGE("bind fail");
259518678f8Sopenharmony_ci        (void)close(socketFd);
260518678f8Sopenharmony_ci        return OPT_FAIL;
261518678f8Sopenharmony_ci    }
262518678f8Sopenharmony_ci    m_socketFd = socketFd;
263518678f8Sopenharmony_ci    m_ifaceIndex = ifaceIndex;
264518678f8Sopenharmony_ci    m_protocol = protocol;
265518678f8Sopenharmony_ci    return OPT_SUCC;
266518678f8Sopenharmony_ci}
267518678f8Sopenharmony_ci
268518678f8Sopenharmony_ciint32_t DhcpArpChecker::SendData(uint8_t *buff, int32_t count, uint8_t *destHwaddr)
269518678f8Sopenharmony_ci{
270518678f8Sopenharmony_ci    if (buff == nullptr || destHwaddr == nullptr) {
271518678f8Sopenharmony_ci        DHCP_LOGE("buff or dest hwaddr is null");
272518678f8Sopenharmony_ci        return OPT_FAIL;
273518678f8Sopenharmony_ci    }
274518678f8Sopenharmony_ci
275518678f8Sopenharmony_ci    if (m_socketFd < 0 || m_ifaceIndex == 0) {
276518678f8Sopenharmony_ci        DHCP_LOGE("invalid socket fd");
277518678f8Sopenharmony_ci        return OPT_FAIL;
278518678f8Sopenharmony_ci    }
279518678f8Sopenharmony_ci
280518678f8Sopenharmony_ci    struct sockaddr_ll rawAddr;
281518678f8Sopenharmony_ci    (void)memset_s(&rawAddr, sizeof(rawAddr), 0, sizeof(rawAddr));
282518678f8Sopenharmony_ci    rawAddr.sll_ifindex = m_ifaceIndex;
283518678f8Sopenharmony_ci    rawAddr.sll_protocol = htons(m_protocol);
284518678f8Sopenharmony_ci    rawAddr.sll_family = AF_PACKET;
285518678f8Sopenharmony_ci    if (memcpy_s(rawAddr.sll_addr, sizeof(rawAddr.sll_addr), destHwaddr, ETH_ALEN) != EOK) {
286518678f8Sopenharmony_ci        DHCP_LOGE("Send: memcpy fail");
287518678f8Sopenharmony_ci        return OPT_FAIL;
288518678f8Sopenharmony_ci    }
289518678f8Sopenharmony_ci
290518678f8Sopenharmony_ci    int32_t ret;
291518678f8Sopenharmony_ci    do {
292518678f8Sopenharmony_ci        ret = sendto(m_socketFd, buff, count, 0, reinterpret_cast<struct sockaddr *>(&rawAddr), sizeof(rawAddr));
293518678f8Sopenharmony_ci        if (ret == -1) {
294518678f8Sopenharmony_ci            DHCP_LOGE("Send: sendto fail");
295518678f8Sopenharmony_ci            if (errno != EINTR) {
296518678f8Sopenharmony_ci                break;
297518678f8Sopenharmony_ci            }
298518678f8Sopenharmony_ci        }
299518678f8Sopenharmony_ci    } while (ret == -1);
300518678f8Sopenharmony_ci    return ret > 0 ? OPT_SUCC : OPT_FAIL;
301518678f8Sopenharmony_ci}
302518678f8Sopenharmony_ci
303518678f8Sopenharmony_ciint32_t DhcpArpChecker::RecvData(uint8_t *buff, int32_t count, int32_t timeoutMillis)
304518678f8Sopenharmony_ci{
305518678f8Sopenharmony_ci    DHCP_LOGI("RecvData poll start");
306518678f8Sopenharmony_ci    if (m_socketFd < 0) {
307518678f8Sopenharmony_ci        DHCP_LOGE("invalid socket fd");
308518678f8Sopenharmony_ci        return -1;
309518678f8Sopenharmony_ci    }
310518678f8Sopenharmony_ci
311518678f8Sopenharmony_ci    pollfd fds[1];
312518678f8Sopenharmony_ci    fds[0].fd = m_socketFd;
313518678f8Sopenharmony_ci    fds[0].events = POLLIN;
314518678f8Sopenharmony_ci    if (poll(fds, 1, timeoutMillis) <= 0) {
315518678f8Sopenharmony_ci        DHCP_LOGW("RecvData poll timeout");
316518678f8Sopenharmony_ci        return 0;
317518678f8Sopenharmony_ci    }
318518678f8Sopenharmony_ci    DHCP_LOGI("RecvData poll end");
319518678f8Sopenharmony_ci    int32_t nBytes;
320518678f8Sopenharmony_ci    do {
321518678f8Sopenharmony_ci        nBytes = read(m_socketFd, buff, count);
322518678f8Sopenharmony_ci        if (nBytes == -1) {
323518678f8Sopenharmony_ci            if (errno != EINTR) {
324518678f8Sopenharmony_ci                break;
325518678f8Sopenharmony_ci            }
326518678f8Sopenharmony_ci        }
327518678f8Sopenharmony_ci    } while (nBytes == -1);
328518678f8Sopenharmony_ci
329518678f8Sopenharmony_ci    return nBytes < 0 ? 0 : nBytes;
330518678f8Sopenharmony_ci}
331518678f8Sopenharmony_ci
332518678f8Sopenharmony_ciint32_t DhcpArpChecker::CloseSocket(void)
333518678f8Sopenharmony_ci{
334518678f8Sopenharmony_ci    int32_t ret = OPT_FAIL;
335518678f8Sopenharmony_ci
336518678f8Sopenharmony_ci    if (m_socketFd >= 0) {
337518678f8Sopenharmony_ci        ret = close(m_socketFd);
338518678f8Sopenharmony_ci        if (ret != OPT_SUCC) {
339518678f8Sopenharmony_ci            DHCP_LOGE("close fail.");
340518678f8Sopenharmony_ci        }
341518678f8Sopenharmony_ci    }
342518678f8Sopenharmony_ci    m_socketFd = -1;
343518678f8Sopenharmony_ci    m_ifaceIndex = 0;
344518678f8Sopenharmony_ci    m_protocol = 0;
345518678f8Sopenharmony_ci    return ret;
346518678f8Sopenharmony_ci}
347518678f8Sopenharmony_ci
348518678f8Sopenharmony_cibool DhcpArpChecker::SetNonBlock(int32_t fd)
349518678f8Sopenharmony_ci{
350518678f8Sopenharmony_ci    int32_t ret = fcntl(fd, F_GETFL);
351518678f8Sopenharmony_ci    if (ret < 0) {
352518678f8Sopenharmony_ci        return false;
353518678f8Sopenharmony_ci    }
354518678f8Sopenharmony_ci
355518678f8Sopenharmony_ci    uint32_t flags = (static_cast<uint32_t>(ret) | O_NONBLOCK);
356518678f8Sopenharmony_ci    return fcntl(fd, F_SETFL, flags);
357518678f8Sopenharmony_ci}
358518678f8Sopenharmony_ci}
359518678f8Sopenharmony_ci}