1518678f8Sopenharmony_ci/*
2518678f8Sopenharmony_ci * Copyright (C) 2023 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.0ys/socket.h
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#include <signal.h>
16518678f8Sopenharmony_ci#include <pthread.h>
17518678f8Sopenharmony_ci#include <ifaddrs.h>
18518678f8Sopenharmony_ci#include <netdb.h>
19518678f8Sopenharmony_ci#include <netinet/icmp6.h>
20518678f8Sopenharmony_ci#include <arpa/inet.h>
21518678f8Sopenharmony_ci#include <netinet/in.h>
22518678f8Sopenharmony_ci#include <stdio.h>
23518678f8Sopenharmony_ci#include <unistd.h>
24518678f8Sopenharmony_ci#include <dlfcn.h>
25518678f8Sopenharmony_ci#include <sys/time.h>
26518678f8Sopenharmony_ci#include <net/if.h>
27518678f8Sopenharmony_ci#include <errno.h>
28518678f8Sopenharmony_ci#include <thread>
29518678f8Sopenharmony_ci#include "securec.h"
30518678f8Sopenharmony_ci#include "dhcp_logger.h"
31518678f8Sopenharmony_ci#include "dhcp_ipv6_client.h"
32518678f8Sopenharmony_ci#include "dhcp_result.h"
33518678f8Sopenharmony_ci#include "dhcp_thread.h"
34518678f8Sopenharmony_ci#include "dhcp_function.h"
35518678f8Sopenharmony_ci
36518678f8Sopenharmony_cinamespace OHOS {
37518678f8Sopenharmony_cinamespace DHCP {
38518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpIpv6Client");
39518678f8Sopenharmony_ci
40518678f8Sopenharmony_ciconst char *DEFAULUT_BAK_DNS = "240e:4c:4008::1";
41518678f8Sopenharmony_ciconst char *DEFAULT_ROUTE = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
42518678f8Sopenharmony_ciconst char *DEFAULT_IPV6_ANY_INIT_ADDR = "::";
43518678f8Sopenharmony_ciconst int IPV6_ADDR_ANY = 0x0000U;
44518678f8Sopenharmony_ciconst int IPV6_ADDR_UNICAST = 0x0001U;
45518678f8Sopenharmony_ciconst int IPV6_ADDR_MULTICAST = 0x0002U;
46518678f8Sopenharmony_ciconst int IPV6_ADDR_SCOPE_MASK = 0x00F0U;
47518678f8Sopenharmony_ciconst int IPV6_ADDR_LOOPBACK = 0x0010U;
48518678f8Sopenharmony_ciconst int IPV6_ADDR_LINKLOCAL = 0x0020U;
49518678f8Sopenharmony_ciconst int IPV6_ADDR_SITELOCAL = 0x0040U;
50518678f8Sopenharmony_ciconst int IPV6_ADDR_COMPATV4 = 0x0080U;
51518678f8Sopenharmony_ciconst int IPV6_ADDR_MAPPED = 0x1000U;
52518678f8Sopenharmony_ciconst unsigned int IPV6_ADDR_SCOPE_NODELOCAL = 0X01;
53518678f8Sopenharmony_ciconst unsigned int  IPV6_ADDR_SCOPE_LINKLOCAL = 0X02;
54518678f8Sopenharmony_ciconst unsigned int  IPV6_ADDR_SCOPE_SITELOCAL = 0X05;
55518678f8Sopenharmony_ciconst int  IPV6_ADDR_SCOPE_GLOBAL = 0X0E;
56518678f8Sopenharmony_ciconst int S6_ADDR_INDEX_ZERO = 0;
57518678f8Sopenharmony_ciconst int S6_ADDR_INDEX_FIRST = 1;
58518678f8Sopenharmony_ciconst int S6_ADDR_INDEX_SECOND = 2;
59518678f8Sopenharmony_ciconst int S6_ADDR_INDEX_THIRD = 3;
60518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_ZERO = 0x00000000;
61518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_ONE = 0x00000001;
62518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_LOWF = 0x0000ffff;
63518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_HIGHE = 0xE0000000;
64518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_HIGHFF = 0xFF000000;
65518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_HIGHFFC = 0xFFC00000;
66518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_HIGHFE8 = 0xFE800000;
67518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_HIGHFEC = 0xFEC00000;
68518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_HIGHFE = 0xFE000000;
69518678f8Sopenharmony_ciconst int ADDRTYPE_FLAG_HIGHFC = 0xFC000000;
70518678f8Sopenharmony_ciconst int MASK_FILTER = 0x7;
71518678f8Sopenharmony_ciconst int KERNEL_BUFF_SIZE = (8 * 1024);
72518678f8Sopenharmony_ciconst int ND_OPT_MIN_LEN = 3;
73518678f8Sopenharmony_ciconst int ROUTE_BUFF_SIZE = 1024;
74518678f8Sopenharmony_ciconst int IPV6_TIMEOUT_USEC = 500000;
75518678f8Sopenharmony_ciconst int POSITION_OFFSET_1 = 1;
76518678f8Sopenharmony_ciconst int POSITION_OFFSET_2 = 2;
77518678f8Sopenharmony_ciconst int POSITION_OFFSET_3 = 3;
78518678f8Sopenharmony_ciconst int POSITION_OFFSET_4 = 4;
79518678f8Sopenharmony_ci
80518678f8Sopenharmony_ci#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16)
81518678f8Sopenharmony_ci#define IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
82518678f8Sopenharmony_ci#ifndef ND_OPT_RDNSS
83518678f8Sopenharmony_ci#define ND_OPT_RDNSS 25
84518678f8Sopenharmony_cistruct nd_opt_rdnss {
85518678f8Sopenharmony_ci    uint8_t nd_opt_rdnss_type;
86518678f8Sopenharmony_ci    uint8_t nd_opt_rdnss_len;
87518678f8Sopenharmony_ci    uint16_t nd_opt_rdnss_reserved;
88518678f8Sopenharmony_ci    uint32_t nd_opt_rdnss_lifetime;
89518678f8Sopenharmony_ci} _packed;
90518678f8Sopenharmony_ci#endif
91518678f8Sopenharmony_ci
92518678f8Sopenharmony_ciDhcpIpv6Client::DhcpIpv6Client(std::string ifname) : interfaceName(ifname), runFlag(false)
93518678f8Sopenharmony_ci{
94518678f8Sopenharmony_ci#ifndef OHOS_ARCH_LITE
95518678f8Sopenharmony_ci    ipv6TimerId = 0;
96518678f8Sopenharmony_ci#endif
97518678f8Sopenharmony_ci    ipv6Thread_ = std::make_unique<DhcpThread>("InnerIpv6Thread");
98518678f8Sopenharmony_ci    DHCP_LOGI("DhcpIpv6Client()");
99518678f8Sopenharmony_ci}
100518678f8Sopenharmony_ci
101518678f8Sopenharmony_ciDhcpIpv6Client::~DhcpIpv6Client()
102518678f8Sopenharmony_ci{
103518678f8Sopenharmony_ci    DHCP_LOGI("~DhcpIpv6Client()");
104518678f8Sopenharmony_ci    if (ipv6Thread_ != nullptr) {
105518678f8Sopenharmony_ci        ipv6Thread_.reset();
106518678f8Sopenharmony_ci    }
107518678f8Sopenharmony_ci}
108518678f8Sopenharmony_ci
109518678f8Sopenharmony_cibool DhcpIpv6Client::IsRunning()
110518678f8Sopenharmony_ci{
111518678f8Sopenharmony_ci    DHCP_LOGI("IsRunning()");
112518678f8Sopenharmony_ci    return runFlag;
113518678f8Sopenharmony_ci}
114518678f8Sopenharmony_civoid DhcpIpv6Client::SetCallback(std::function<void(const std::string ifname, DhcpIpv6Info &info)> callback)
115518678f8Sopenharmony_ci{
116518678f8Sopenharmony_ci    DHCP_LOGI("SetCallback()");
117518678f8Sopenharmony_ci    onIpv6AddressChanged = callback;
118518678f8Sopenharmony_ci}
119518678f8Sopenharmony_ci
120518678f8Sopenharmony_civoid DhcpIpv6Client::RunIpv6ThreadFunc()
121518678f8Sopenharmony_ci{
122518678f8Sopenharmony_ci    DhcpIpv6Start();
123518678f8Sopenharmony_ci}
124518678f8Sopenharmony_ci
125518678f8Sopenharmony_ciint DhcpIpv6Client::StartIpv6Thread(const std::string &ifname, bool isIpv6)
126518678f8Sopenharmony_ci{
127518678f8Sopenharmony_ci    DHCP_LOGI("StartIpv6Thread ifname:%{public}s bIpv6:%{public}d,runFlag:%{public}d", ifname.c_str(), isIpv6, runFlag);
128518678f8Sopenharmony_ci    if (!runFlag) {
129518678f8Sopenharmony_ci        interfaceName = ifname;
130518678f8Sopenharmony_ci        if (ipv6Thread_ == nullptr) {
131518678f8Sopenharmony_ci            ipv6Thread_ = std::make_unique<DhcpThread>("InnerIpv6Thread");
132518678f8Sopenharmony_ci        }
133518678f8Sopenharmony_ci        std::function<void()> func = [this]() { this->RunIpv6ThreadFunc(); };
134518678f8Sopenharmony_ci        int delayTime = 0;
135518678f8Sopenharmony_ci        bool result = ipv6Thread_->PostAsyncTask(func, delayTime);
136518678f8Sopenharmony_ci        if (!result) {
137518678f8Sopenharmony_ci            DHCP_LOGE("StartIpv6Thread PostAsyncTask failed!");
138518678f8Sopenharmony_ci        }
139518678f8Sopenharmony_ci        DHCP_LOGI("StartIpv6Thread RunIpv6ThreadFunc ok!");
140518678f8Sopenharmony_ci    } else {
141518678f8Sopenharmony_ci        DHCP_LOGI("StartIpv6Thread RunIpv6ThreadFunc!");
142518678f8Sopenharmony_ci    }
143518678f8Sopenharmony_ci    return 0;
144518678f8Sopenharmony_ci}
145518678f8Sopenharmony_ci
146518678f8Sopenharmony_ciunsigned int DhcpIpv6Client::ipv6AddrScope2Type(unsigned int scope)
147518678f8Sopenharmony_ci{
148518678f8Sopenharmony_ci    switch (scope) {
149518678f8Sopenharmony_ci        case IPV6_ADDR_SCOPE_NODELOCAL:
150518678f8Sopenharmony_ci            return IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
151518678f8Sopenharmony_ci                IPV6_ADDR_LOOPBACK;
152518678f8Sopenharmony_ci            break;
153518678f8Sopenharmony_ci
154518678f8Sopenharmony_ci        case IPV6_ADDR_SCOPE_LINKLOCAL:
155518678f8Sopenharmony_ci            return IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
156518678f8Sopenharmony_ci                IPV6_ADDR_LINKLOCAL;
157518678f8Sopenharmony_ci            break;
158518678f8Sopenharmony_ci
159518678f8Sopenharmony_ci        case IPV6_ADDR_SCOPE_SITELOCAL:
160518678f8Sopenharmony_ci            return IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
161518678f8Sopenharmony_ci                IPV6_ADDR_SITELOCAL;
162518678f8Sopenharmony_ci            break;
163518678f8Sopenharmony_ci
164518678f8Sopenharmony_ci        default:
165518678f8Sopenharmony_ci            break;
166518678f8Sopenharmony_ci    }
167518678f8Sopenharmony_ci
168518678f8Sopenharmony_ci    return IPV6_ADDR_SCOPE_TYPE(scope);
169518678f8Sopenharmony_ci}
170518678f8Sopenharmony_ci
171518678f8Sopenharmony_ciint DhcpIpv6Client::getAddrType(const struct in6_addr *addr)
172518678f8Sopenharmony_ci{
173518678f8Sopenharmony_ci    if (!addr) {
174518678f8Sopenharmony_ci        DHCP_LOGE("getAddrType failed, data invalid.");
175518678f8Sopenharmony_ci        return IPV6_ADDR_LINKLOCAL;
176518678f8Sopenharmony_ci    }
177518678f8Sopenharmony_ci    unsigned int st = addr->s6_addr32[0];
178518678f8Sopenharmony_ci    if ((st & htonl(ADDRTYPE_FLAG_HIGHE)) != htonl(ADDRTYPE_FLAG_ZERO) &&
179518678f8Sopenharmony_ci        (st & htonl(ADDRTYPE_FLAG_HIGHE)) != htonl(ADDRTYPE_FLAG_HIGHE)) {
180518678f8Sopenharmony_ci        return (IPV6_ADDR_UNICAST | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
181518678f8Sopenharmony_ci    }
182518678f8Sopenharmony_ci
183518678f8Sopenharmony_ci    if ((st & htonl(ADDRTYPE_FLAG_HIGHFF)) == htonl(ADDRTYPE_FLAG_HIGHFF)) {
184518678f8Sopenharmony_ci        return (IPV6_ADDR_MULTICAST | ipv6AddrScope2Type(IPV6_ADDR_MC_SCOPE(addr)));
185518678f8Sopenharmony_ci    }
186518678f8Sopenharmony_ci
187518678f8Sopenharmony_ci    if ((st & htonl(ADDRTYPE_FLAG_HIGHFFC)) == htonl(ADDRTYPE_FLAG_HIGHFE8)) {
188518678f8Sopenharmony_ci        return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
189518678f8Sopenharmony_ci            IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));
190518678f8Sopenharmony_ci    }
191518678f8Sopenharmony_ci
192518678f8Sopenharmony_ci    if ((st & htonl(ADDRTYPE_FLAG_HIGHFFC)) == htonl(ADDRTYPE_FLAG_HIGHFEC)) {
193518678f8Sopenharmony_ci        return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
194518678f8Sopenharmony_ci            IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL));
195518678f8Sopenharmony_ci    }
196518678f8Sopenharmony_ci
197518678f8Sopenharmony_ci    if ((st & htonl(ADDRTYPE_FLAG_HIGHFE)) == htonl(ADDRTYPE_FLAG_HIGHFC)) {
198518678f8Sopenharmony_ci        return (IPV6_ADDR_UNICAST | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
199518678f8Sopenharmony_ci    }
200518678f8Sopenharmony_ci
201518678f8Sopenharmony_ci    if ((addr->s6_addr32[S6_ADDR_INDEX_ZERO] | addr->s6_addr32[S6_ADDR_INDEX_FIRST]) == 0) {
202518678f8Sopenharmony_ci        if (addr->s6_addr32[S6_ADDR_INDEX_SECOND] == 0) {
203518678f8Sopenharmony_ci            if (addr->s6_addr32[S6_ADDR_INDEX_THIRD] == 0) {
204518678f8Sopenharmony_ci                return IPV6_ADDR_ANY;
205518678f8Sopenharmony_ci            }
206518678f8Sopenharmony_ci            if (addr->s6_addr32[S6_ADDR_INDEX_THIRD] == htonl(ADDRTYPE_FLAG_ONE)) {
207518678f8Sopenharmony_ci                return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
208518678f8Sopenharmony_ci                    IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));
209518678f8Sopenharmony_ci            }
210518678f8Sopenharmony_ci            return (IPV6_ADDR_COMPATV4 | IPV6_ADDR_UNICAST |
211518678f8Sopenharmony_ci                IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
212518678f8Sopenharmony_ci        }
213518678f8Sopenharmony_ci        if (addr->s6_addr32[S6_ADDR_INDEX_THIRD] == htonl(ADDRTYPE_FLAG_LOWF)) {
214518678f8Sopenharmony_ci            return (IPV6_ADDR_MAPPED | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
215518678f8Sopenharmony_ci        }
216518678f8Sopenharmony_ci    }
217518678f8Sopenharmony_ci
218518678f8Sopenharmony_ci    return (IPV6_ADDR_UNICAST | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
219518678f8Sopenharmony_ci}
220518678f8Sopenharmony_ci
221518678f8Sopenharmony_ciint DhcpIpv6Client::getAddrScope(const struct in6_addr *addr)
222518678f8Sopenharmony_ci{
223518678f8Sopenharmony_ci    if (!addr) {
224518678f8Sopenharmony_ci        DHCP_LOGE("getAddrType failed, data invalid.");
225518678f8Sopenharmony_ci        return IPV6_ADDR_LINKLOCAL;
226518678f8Sopenharmony_ci    }
227518678f8Sopenharmony_ci    return static_cast<unsigned int>(getAddrType(addr)) & IPV6_ADDR_SCOPE_MASK;
228518678f8Sopenharmony_ci}
229518678f8Sopenharmony_ci
230518678f8Sopenharmony_civoid DhcpIpv6Client::GetIpv6Prefix(const char* ipv6Addr, char* ipv6PrefixBuf, uint8_t prefixLen)
231518678f8Sopenharmony_ci{
232518678f8Sopenharmony_ci    if (!ipv6Addr || !ipv6PrefixBuf) {
233518678f8Sopenharmony_ci        DHCP_LOGE("GetIpv6Prefix failed, input invalid.");
234518678f8Sopenharmony_ci        return;
235518678f8Sopenharmony_ci    }
236518678f8Sopenharmony_ci    if (prefixLen >= DHCP_INET6_ADDRSTRLEN) {
237518678f8Sopenharmony_ci        strlcpy(ipv6PrefixBuf, ipv6Addr, DHCP_INET6_ADDRSTRLEN);
238518678f8Sopenharmony_ci        return;
239518678f8Sopenharmony_ci    }
240518678f8Sopenharmony_ci
241518678f8Sopenharmony_ci    struct in6_addr ipv6AddrBuf = IN6ADDR_ANY_INIT;
242518678f8Sopenharmony_ci    inet_pton(AF_INET6, ipv6Addr, &ipv6AddrBuf);
243518678f8Sopenharmony_ci
244518678f8Sopenharmony_ci    char buf[INET6_ADDRSTRLEN] = {0};
245518678f8Sopenharmony_ci    if (inet_ntop(AF_INET6, &ipv6AddrBuf, buf, INET6_ADDRSTRLEN) == NULL) {
246518678f8Sopenharmony_ci        strlcpy(ipv6PrefixBuf, ipv6Addr, DHCP_INET6_ADDRSTRLEN);
247518678f8Sopenharmony_ci        return;
248518678f8Sopenharmony_ci    }
249518678f8Sopenharmony_ci
250518678f8Sopenharmony_ci    struct in6_addr ipv6Prefix = IN6ADDR_ANY_INIT;
251518678f8Sopenharmony_ci    uint32_t byteIndex = prefixLen / CHAR_BIT;
252518678f8Sopenharmony_ci    if (memset_s(ipv6Prefix.s6_addr, sizeof(ipv6Prefix.s6_addr), 0, sizeof(ipv6Prefix.s6_addr)) != EOK ||
253518678f8Sopenharmony_ci        memcpy_s(ipv6Prefix.s6_addr, sizeof(ipv6Prefix.s6_addr), &ipv6AddrBuf, byteIndex) != EOK) {
254518678f8Sopenharmony_ci        return;
255518678f8Sopenharmony_ci    }
256518678f8Sopenharmony_ci    uint32_t bitOffset = prefixLen & MASK_FILTER;
257518678f8Sopenharmony_ci    if ((bitOffset != 0) && (byteIndex < INET_ADDRSTRLEN)) {
258518678f8Sopenharmony_ci        ipv6Prefix.s6_addr[byteIndex] = ipv6AddrBuf.s6_addr[byteIndex] & (0xff00 >> bitOffset);
259518678f8Sopenharmony_ci    }
260518678f8Sopenharmony_ci    inet_ntop(AF_INET6, &ipv6Prefix, ipv6PrefixBuf, INET6_ADDRSTRLEN);
261518678f8Sopenharmony_ci}
262518678f8Sopenharmony_ci
263518678f8Sopenharmony_ciint DhcpIpv6Client::GetIpFromS6Address(void* addr, int family, char* buf, int buflen)
264518678f8Sopenharmony_ci{
265518678f8Sopenharmony_ci    if (!inet_ntop(family, (struct in6_addr*)addr, buf, buflen)) {
266518678f8Sopenharmony_ci        DHCP_LOGE("GetIpFromS6Address failed");
267518678f8Sopenharmony_ci        return -1;
268518678f8Sopenharmony_ci    }
269518678f8Sopenharmony_ci    return 0;
270518678f8Sopenharmony_ci}
271518678f8Sopenharmony_ci
272518678f8Sopenharmony_civoid DhcpIpv6Client::onIpv6AddressAddEvent(void* data, int prefixLen, int ifaIndex)
273518678f8Sopenharmony_ci{
274518678f8Sopenharmony_ci    int currIndex = static_cast<int>(if_nametoindex(interfaceName.c_str()));
275518678f8Sopenharmony_ci    if (currIndex != ifaIndex) {
276518678f8Sopenharmony_ci        DHCP_LOGE("address ifaindex invalid, %{public}d != %{public}d", currIndex, ifaIndex);
277518678f8Sopenharmony_ci        return;
278518678f8Sopenharmony_ci    }
279518678f8Sopenharmony_ci    if (!data) {
280518678f8Sopenharmony_ci        DHCP_LOGE("onIpv6AddressAddEvent failed, data invalid.");
281518678f8Sopenharmony_ci        return;
282518678f8Sopenharmony_ci    }
283518678f8Sopenharmony_ci    struct in6_addr *addr = (struct in6_addr*)data;
284518678f8Sopenharmony_ci    char addr_str[INET6_ADDRSTRLEN] = {0};
285518678f8Sopenharmony_ci    inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN);
286518678f8Sopenharmony_ci    int scope = getAddrScope(addr);
287518678f8Sopenharmony_ci    if (scope == 0) {
288518678f8Sopenharmony_ci        getIpv6RouteAddr();
289518678f8Sopenharmony_ci        if (memset_s(dhcpIpv6Info.ipv6SubnetAddr, DHCP_INET6_ADDRSTRLEN,
290518678f8Sopenharmony_ci            0, DHCP_INET6_ADDRSTRLEN) != EOK) {
291518678f8Sopenharmony_ci            DHCP_LOGE("onIpv6AddressAddEvent memset_s failed");
292518678f8Sopenharmony_ci            return;
293518678f8Sopenharmony_ci        }
294518678f8Sopenharmony_ci        dhcpIpv6Info.status |= 1;
295518678f8Sopenharmony_ci        GetIpv6Prefix(DEFAULT_ROUTE, dhcpIpv6Info.ipv6SubnetAddr, prefixLen);
296518678f8Sopenharmony_ci        DHCP_LOGD("onIpv6AddressAddEvent addr:%{private}s, subaddr:%{public}s, route:%{public}s, scope:%{public}d",
297518678f8Sopenharmony_ci            addr_str, dhcpIpv6Info.ipv6SubnetAddr, dhcpIpv6Info.routeAddr, scope);
298518678f8Sopenharmony_ci        AddIpv6Address(addr_str, INET6_ADDRSTRLEN);
299518678f8Sopenharmony_ci    } else if (scope == IPV6_ADDR_LINKLOCAL) {
300518678f8Sopenharmony_ci        if (memset_s(dhcpIpv6Info.linkIpv6Addr, DHCP_INET6_ADDRSTRLEN, 0, DHCP_INET6_ADDRSTRLEN) != EOK ||
301518678f8Sopenharmony_ci            memcpy_s(dhcpIpv6Info.linkIpv6Addr, INET6_ADDRSTRLEN, addr_str, INET6_ADDRSTRLEN) != EOK) {
302518678f8Sopenharmony_ci            DHCP_LOGE("onIpv6AddressAddEvent memset_s or memcpy_s failed");
303518678f8Sopenharmony_ci            return;
304518678f8Sopenharmony_ci        }
305518678f8Sopenharmony_ci        DHCP_LOGD("onIpv6AddressAddEvent addr:%{public}s, subaddr:%{public}s, route:%{public}s, scope:%{public}d",
306518678f8Sopenharmony_ci            addr_str, dhcpIpv6Info.ipv6SubnetAddr, dhcpIpv6Info.routeAddr, scope);
307518678f8Sopenharmony_ci    } else {
308518678f8Sopenharmony_ci        DHCP_LOGD("onIpv6AddressAddEvent other scope:%{public}d", scope);
309518678f8Sopenharmony_ci    }
310518678f8Sopenharmony_ci}
311518678f8Sopenharmony_ci
312518678f8Sopenharmony_civoid DhcpIpv6Client::AddIpv6Address(char *ipv6addr, int len)
313518678f8Sopenharmony_ci{
314518678f8Sopenharmony_ci    if (!ipv6addr) {
315518678f8Sopenharmony_ci        DHCP_LOGE("AddIpv6Address ipv6addr is nullptr!");
316518678f8Sopenharmony_ci        return;
317518678f8Sopenharmony_ci    }
318518678f8Sopenharmony_ci    int first = ipv6addr[0]-'0';
319518678f8Sopenharmony_ci    if (first == NUMBER_TWO || first == NUMBER_THREE) { // begin '2' '3'
320518678f8Sopenharmony_ci        if (IsEui64ModeIpv6Address(ipv6addr, len)) {
321518678f8Sopenharmony_ci            DHCP_LOGI("AddIpv6Address add globalIpv6Addr, first=%{public}d", first);
322518678f8Sopenharmony_ci            if (memcpy_s(dhcpIpv6Info.globalIpv6Addr, len, ipv6addr, len) != EOK) {
323518678f8Sopenharmony_ci                DHCP_LOGE("AddIpv6Address memcpy_s failed!");
324518678f8Sopenharmony_ci                return;
325518678f8Sopenharmony_ci            }
326518678f8Sopenharmony_ci        }  else {
327518678f8Sopenharmony_ci            DHCP_LOGI("AddIpv6Address add randIpv6Addr, first=%{public}d", first);
328518678f8Sopenharmony_ci            if (memcpy_s(dhcpIpv6Info.randIpv6Addr, len, ipv6addr, len) != EOK) {
329518678f8Sopenharmony_ci                DHCP_LOGE("onIpv6AddressAddEvent memcpy_s failed!");
330518678f8Sopenharmony_ci                return;
331518678f8Sopenharmony_ci            }
332518678f8Sopenharmony_ci        }
333518678f8Sopenharmony_ci        if (strlen(dhcpIpv6Info.globalIpv6Addr) != 0 || strlen(dhcpIpv6Info.randIpv6Addr) != 0) {
334518678f8Sopenharmony_ci            onIpv6AddressChanged(interfaceName, dhcpIpv6Info);
335518678f8Sopenharmony_ci        }
336518678f8Sopenharmony_ci    } else if (first == NUMBER_FIFTY_FOUR) {  // begin 'f'->54
337518678f8Sopenharmony_ci        if (IsEui64ModeIpv6Address(ipv6addr, len)) {
338518678f8Sopenharmony_ci            if (memcpy_s(dhcpIpv6Info.uniqueLocalAddr1, len, ipv6addr, len) != EOK) {
339518678f8Sopenharmony_ci                DHCP_LOGE("AddIpv6Address memcpy_s failed!");
340518678f8Sopenharmony_ci                return;
341518678f8Sopenharmony_ci            }
342518678f8Sopenharmony_ci            DHCP_LOGI("AddIpv6Address add uniqueLocalAddr1, first=%{public}d", first);
343518678f8Sopenharmony_ci        }  else {
344518678f8Sopenharmony_ci            if (memcpy_s(dhcpIpv6Info.uniqueLocalAddr2, len, ipv6addr, len) != EOK) {
345518678f8Sopenharmony_ci                DHCP_LOGE("AddIpv6Address uniqueLocalAddr2 memcpy_s failed!");
346518678f8Sopenharmony_ci                return;
347518678f8Sopenharmony_ci            }
348518678f8Sopenharmony_ci            DHCP_LOGI("AddIpv6Address add uniqueLocalAddr2, first=%{public}d", first);
349518678f8Sopenharmony_ci        }
350518678f8Sopenharmony_ci        if (strlen(dhcpIpv6Info.uniqueLocalAddr1) != 0 || strlen(dhcpIpv6Info.uniqueLocalAddr2) != 0) {
351518678f8Sopenharmony_ci            onIpv6AddressChanged(interfaceName, dhcpIpv6Info);
352518678f8Sopenharmony_ci        }
353518678f8Sopenharmony_ci    } else {
354518678f8Sopenharmony_ci        DHCP_LOGI("AddIpv6Address other first=%{public}d", first);
355518678f8Sopenharmony_ci    }
356518678f8Sopenharmony_ci}
357518678f8Sopenharmony_ci
358518678f8Sopenharmony_cibool DhcpIpv6Client::IsEui64ModeIpv6Address(char *ipv6addr, int len)
359518678f8Sopenharmony_ci{
360518678f8Sopenharmony_ci    if (ipv6addr == nullptr) {
361518678f8Sopenharmony_ci        DHCP_LOGE("IsEui64ModeIpv6Address ipv6addr is nullptr!");
362518678f8Sopenharmony_ci        return false;
363518678f8Sopenharmony_ci    }
364518678f8Sopenharmony_ci    int ifaceIndex = 0;
365518678f8Sopenharmony_ci    unsigned char ifaceMac[MAC_ADDR_LEN];
366518678f8Sopenharmony_ci    if (GetLocalInterface(interfaceName.c_str(), &ifaceIndex, ifaceMac, NULL) != DHCP_OPT_SUCCESS) {
367518678f8Sopenharmony_ci        DHCP_LOGE("IsEui64ModeIpv6Address GetLocalInterface failed, ifaceName:%{public}s.", interfaceName.c_str());
368518678f8Sopenharmony_ci        return false;
369518678f8Sopenharmony_ci    }
370518678f8Sopenharmony_ci    char macAddr[MAC_ADDR_LEN * MAC_ADDR_CHAR_NUM];
371518678f8Sopenharmony_ci    if (memset_s(macAddr, sizeof(macAddr), 0, sizeof(macAddr)) != EOK) {
372518678f8Sopenharmony_ci        DHCP_LOGE("IsEui64ModeIpv6Address memset_s failed!");
373518678f8Sopenharmony_ci        return false;
374518678f8Sopenharmony_ci    }
375518678f8Sopenharmony_ci    MacChConToMacStr(ifaceMac, MAC_ADDR_LEN, macAddr, sizeof(macAddr));
376518678f8Sopenharmony_ci    std::string localMacString = macAddr;
377518678f8Sopenharmony_ci    std::string ipv6AddrString = ipv6addr;
378518678f8Sopenharmony_ci    size_t macPosition = localMacString.find_last_of(':');
379518678f8Sopenharmony_ci    size_t ipv6position = ipv6AddrString.find_last_of(':');
380518678f8Sopenharmony_ci    DHCP_LOGI("IsEui64ModeIpv6Address name:%{public}s index:%{public}d %{public}zu %{public}zu len:%{public}d",
381518678f8Sopenharmony_ci        interfaceName.c_str(), ifaceIndex, macPosition, ipv6position, len);
382518678f8Sopenharmony_ci    if ((macPosition != std::string::npos) && (ipv6position != std::string::npos)) {
383518678f8Sopenharmony_ci        if (macAddr[macPosition + POSITION_OFFSET_1] == ipv6addr[ipv6position + POSITION_OFFSET_3] &&
384518678f8Sopenharmony_ci            macAddr[macPosition + POSITION_OFFSET_2] == ipv6addr[ipv6position + POSITION_OFFSET_4] &&
385518678f8Sopenharmony_ci            macAddr[macPosition - POSITION_OFFSET_1] == ipv6addr[ipv6position + POSITION_OFFSET_2] &&
386518678f8Sopenharmony_ci            macAddr[macPosition - POSITION_OFFSET_2] == ipv6addr[ipv6position + POSITION_OFFSET_1]) {
387518678f8Sopenharmony_ci            DHCP_LOGI("IsEui64ModeIpv6Address is true!");
388518678f8Sopenharmony_ci            return true;
389518678f8Sopenharmony_ci        }
390518678f8Sopenharmony_ci    }
391518678f8Sopenharmony_ci    return false;
392518678f8Sopenharmony_ci}
393518678f8Sopenharmony_ci
394518678f8Sopenharmony_civoid DhcpIpv6Client::onIpv6DnsAddEvent(void* data, int len, int ifaIndex)
395518678f8Sopenharmony_ci{
396518678f8Sopenharmony_ci    int currIndex = static_cast<int>(if_nametoindex(interfaceName.c_str()));
397518678f8Sopenharmony_ci    if (currIndex != ifaIndex) {
398518678f8Sopenharmony_ci        DHCP_LOGE("dnsevent ifaindex invalid, %{public}d != %{public}d", currIndex, ifaIndex);
399518678f8Sopenharmony_ci        return;
400518678f8Sopenharmony_ci    }
401518678f8Sopenharmony_ci    dhcpIpv6Info.status |= (1 << 1);
402518678f8Sopenharmony_ci    (void)strncpy_s(dhcpIpv6Info.dnsAddr, DHCP_INET6_ADDRSTRLEN, DEFAULUT_BAK_DNS, strlen(DEFAULUT_BAK_DNS));
403518678f8Sopenharmony_ci    std::vector<std::string>::iterator iter = find(dhcpIpv6Info.vectorDnsAddr.begin(),
404518678f8Sopenharmony_ci        dhcpIpv6Info.vectorDnsAddr.end(), DEFAULUT_BAK_DNS);
405518678f8Sopenharmony_ci    if (iter == dhcpIpv6Info.vectorDnsAddr.end()) {
406518678f8Sopenharmony_ci        dhcpIpv6Info.vectorDnsAddr.push_back(DEFAULUT_BAK_DNS);
407518678f8Sopenharmony_ci    }
408518678f8Sopenharmony_ci    if (!data) {
409518678f8Sopenharmony_ci        DHCP_LOGE("onIpv6DnsAddEvent failed, data invalid.");
410518678f8Sopenharmony_ci        return;
411518678f8Sopenharmony_ci    }
412518678f8Sopenharmony_ci    struct nd_opt_hdr *opthdr = (struct nd_opt_hdr *)(data);
413518678f8Sopenharmony_ci    uint16_t optlen = opthdr->nd_opt_len;
414518678f8Sopenharmony_ci    if (optlen * CHAR_BIT > len) {
415518678f8Sopenharmony_ci        DHCP_LOGE("dns len invalid optlen:%{public}d > len:%{public}d", optlen, len);
416518678f8Sopenharmony_ci        return;
417518678f8Sopenharmony_ci    }
418518678f8Sopenharmony_ci    if (opthdr->nd_opt_type != ND_OPT_RDNSS) {
419518678f8Sopenharmony_ci        DHCP_LOGE("dns nd_opt_type invlid:%{public}d", opthdr->nd_opt_type);
420518678f8Sopenharmony_ci        return;
421518678f8Sopenharmony_ci    }
422518678f8Sopenharmony_ci    if ((optlen < ND_OPT_MIN_LEN) || !(optlen & 0x1)) {
423518678f8Sopenharmony_ci        DHCP_LOGE("dns optLen invlid:%{public}d", optlen);
424518678f8Sopenharmony_ci        return;
425518678f8Sopenharmony_ci    }
426518678f8Sopenharmony_ci    (void)memset_s(dhcpIpv6Info.dnsAddr2, DHCP_INET6_ADDRSTRLEN, 0, DHCP_INET6_ADDRSTRLEN);
427518678f8Sopenharmony_ci    int numaddrs = (optlen - 1) / 2;
428518678f8Sopenharmony_ci    struct nd_opt_rdnss *rndsopt = (struct nd_opt_rdnss *)opthdr;
429518678f8Sopenharmony_ci    struct in6_addr *addrs = (struct in6_addr *)(rndsopt + 1);
430518678f8Sopenharmony_ci    if (numaddrs > 0) {
431518678f8Sopenharmony_ci        inet_ntop(AF_INET6, addrs + 0, dhcpIpv6Info.dnsAddr2, DHCP_INET6_ADDRSTRLEN);
432518678f8Sopenharmony_ci    }
433518678f8Sopenharmony_ci    for (int i = 0; i < numaddrs; i++) {
434518678f8Sopenharmony_ci        char dnsAddr[DHCP_INET6_ADDRSTRLEN] = {0};
435518678f8Sopenharmony_ci        inet_ntop(AF_INET6, addrs + i, dnsAddr, DHCP_INET6_ADDRSTRLEN);
436518678f8Sopenharmony_ci        iter = find(dhcpIpv6Info.vectorDnsAddr.begin(), dhcpIpv6Info.vectorDnsAddr.end(), dnsAddr);
437518678f8Sopenharmony_ci        if (iter == dhcpIpv6Info.vectorDnsAddr.end()) {
438518678f8Sopenharmony_ci            dhcpIpv6Info.vectorDnsAddr.push_back(dnsAddr);
439518678f8Sopenharmony_ci            DHCP_LOGI("onIpv6DnsAddEvent add dns:%{public}d", i);
440518678f8Sopenharmony_ci        }
441518678f8Sopenharmony_ci    }
442518678f8Sopenharmony_ci}
443518678f8Sopenharmony_ci
444518678f8Sopenharmony_civoid DhcpIpv6Client::onIpv6RouteAddEvent(char* gateway, char* dst, int ifaIndex)
445518678f8Sopenharmony_ci{
446518678f8Sopenharmony_ci    int currIndex = static_cast<int>(if_nametoindex(interfaceName.c_str()));
447518678f8Sopenharmony_ci    if (currIndex != ifaIndex) {
448518678f8Sopenharmony_ci        DHCP_LOGE("route ifaindex invalid, %{public}d != %{public}d", currIndex, ifaIndex);
449518678f8Sopenharmony_ci        return;
450518678f8Sopenharmony_ci    }
451518678f8Sopenharmony_ci    DHCP_LOGI("onIpv6RouteAddEvent gateway:%{private}s, dst:%{private}s, ifindex:%{public}d",
452518678f8Sopenharmony_ci        gateway, dst, ifaIndex);
453518678f8Sopenharmony_ci    if (!gateway || !dst) {
454518678f8Sopenharmony_ci        DHCP_LOGE("onIpv6RouteAddEvent input invalid.");
455518678f8Sopenharmony_ci        return;
456518678f8Sopenharmony_ci    }
457518678f8Sopenharmony_ci    if (strlen(dst) == 0 && strlen(gateway) != 0) {
458518678f8Sopenharmony_ci        (void)memset_s(dhcpIpv6Info.routeAddr, DHCP_INET6_ADDRSTRLEN,
459518678f8Sopenharmony_ci            0, DHCP_INET6_ADDRSTRLEN);
460518678f8Sopenharmony_ci        if (strncpy_s(dhcpIpv6Info.routeAddr, DHCP_INET6_ADDRSTRLEN, gateway, strlen(gateway)) != EOK) {
461518678f8Sopenharmony_ci            DHCP_LOGE("onIpv6RouteAddEvent strncpy_s gateway failed");
462518678f8Sopenharmony_ci            return;
463518678f8Sopenharmony_ci        }
464518678f8Sopenharmony_ci    }
465518678f8Sopenharmony_ci}
466518678f8Sopenharmony_ci
467518678f8Sopenharmony_ciint32_t DhcpIpv6Client::createKernelSocket(void)
468518678f8Sopenharmony_ci{
469518678f8Sopenharmony_ci    int32_t sz = KERNEL_BUFF_SIZE;
470518678f8Sopenharmony_ci    int32_t on = 1;
471518678f8Sopenharmony_ci    int32_t sockFd = socket(AF_NETLINK, SOCK_RAW, 0);
472518678f8Sopenharmony_ci    if (sockFd < 0) {
473518678f8Sopenharmony_ci        DHCP_LOGE("dhcp6 create socket failed.");
474518678f8Sopenharmony_ci        return -1;
475518678f8Sopenharmony_ci    }
476518678f8Sopenharmony_ci    if (setsockopt(sockFd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
477518678f8Sopenharmony_ci        DHCP_LOGE("setsockopt socket SO_RCVBUFFORCE failed.");
478518678f8Sopenharmony_ci        close(sockFd);
479518678f8Sopenharmony_ci        return -1;
480518678f8Sopenharmony_ci    }
481518678f8Sopenharmony_ci    if (setsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0) {
482518678f8Sopenharmony_ci        DHCP_LOGE("setsockopt socket SO_RCVBUF failed.");
483518678f8Sopenharmony_ci        close(sockFd);
484518678f8Sopenharmony_ci        return -1;
485518678f8Sopenharmony_ci    }
486518678f8Sopenharmony_ci    if (setsockopt(sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
487518678f8Sopenharmony_ci        DHCP_LOGE("setsockopt socket SO_PASSCRED failed.");
488518678f8Sopenharmony_ci        close(sockFd);
489518678f8Sopenharmony_ci        return -1;
490518678f8Sopenharmony_ci    }
491518678f8Sopenharmony_ci    struct timeval timeout = {1, 0};
492518678f8Sopenharmony_ci    if (setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
493518678f8Sopenharmony_ci        DHCP_LOGE("setsockopt socket SO_RCVTIMEO failed.");
494518678f8Sopenharmony_ci    }
495518678f8Sopenharmony_ci    struct sockaddr saddr;
496518678f8Sopenharmony_ci    (void)memset_s(&saddr, sizeof(saddr), 0, sizeof(saddr));
497518678f8Sopenharmony_ci    setSocketFilter(&saddr);
498518678f8Sopenharmony_ci    if (bind(sockFd, &saddr, sizeof(saddr)) < 0) {
499518678f8Sopenharmony_ci        DHCP_LOGE("bind kernel socket failed.");
500518678f8Sopenharmony_ci        close(sockFd);
501518678f8Sopenharmony_ci        return -1;
502518678f8Sopenharmony_ci    }
503518678f8Sopenharmony_ci    return sockFd;
504518678f8Sopenharmony_ci}
505518678f8Sopenharmony_ci
506518678f8Sopenharmony_civoid DhcpIpv6Client::Reset()
507518678f8Sopenharmony_ci{
508518678f8Sopenharmony_ci    (void)memset_s(&dhcpIpv6Info, sizeof(dhcpIpv6Info), 0, sizeof(dhcpIpv6Info));
509518678f8Sopenharmony_ci}
510518678f8Sopenharmony_ci
511518678f8Sopenharmony_civoid DhcpIpv6Client::getIpv6RouteAddr()
512518678f8Sopenharmony_ci{
513518678f8Sopenharmony_ci    int len = ROUTE_BUFF_SIZE;
514518678f8Sopenharmony_ci    char buffer[ROUTE_BUFF_SIZE] = {0};
515518678f8Sopenharmony_ci    fillRouteData(buffer, len);
516518678f8Sopenharmony_ci    if (send(ipv6SocketFd, buffer, len, 0) < 0) {
517518678f8Sopenharmony_ci        DHCP_LOGE("getIpv6RouteAddr send route info failed.");
518518678f8Sopenharmony_ci    }
519518678f8Sopenharmony_ci    DHCP_LOGE("getIpv6RouteAddr send info ok");
520518678f8Sopenharmony_ci}
521518678f8Sopenharmony_ci
522518678f8Sopenharmony_ciint DhcpIpv6Client::StartIpv6()
523518678f8Sopenharmony_ci{
524518678f8Sopenharmony_ci    DHCP_LOGI("StartIpv6 enter. %{public}s", interfaceName.c_str());
525518678f8Sopenharmony_ci    (void)memset_s(&dhcpIpv6Info, sizeof(dhcpIpv6Info), 0, sizeof(dhcpIpv6Info));
526518678f8Sopenharmony_ci    runFlag = true;
527518678f8Sopenharmony_ci    ipv6SocketFd = createKernelSocket();
528518678f8Sopenharmony_ci    if (ipv6SocketFd < 0) {
529518678f8Sopenharmony_ci        runFlag = false;
530518678f8Sopenharmony_ci        DHCP_LOGE("StartIpv6 ipv6SocketFd < 0 failed!");
531518678f8Sopenharmony_ci        return -1;
532518678f8Sopenharmony_ci    }
533518678f8Sopenharmony_ci    uint8_t *buff = (uint8_t*)malloc(KERNEL_BUFF_SIZE * sizeof(uint8_t));
534518678f8Sopenharmony_ci    if (buff == NULL) {
535518678f8Sopenharmony_ci        DHCP_LOGE("StartIpv6 ipv6 malloc buff failed.");
536518678f8Sopenharmony_ci        close(ipv6SocketFd);
537518678f8Sopenharmony_ci        runFlag = false;
538518678f8Sopenharmony_ci        return -1;
539518678f8Sopenharmony_ci    }
540518678f8Sopenharmony_ci    struct timeval timeout = {0};
541518678f8Sopenharmony_ci    fd_set rSet;
542518678f8Sopenharmony_ci    timeout.tv_sec = 0;
543518678f8Sopenharmony_ci    timeout.tv_usec = IPV6_TIMEOUT_USEC;
544518678f8Sopenharmony_ci    while (runFlag) {
545518678f8Sopenharmony_ci        (void)memset_s(buff, KERNEL_BUFF_SIZE * sizeof(uint8_t), 0, KERNEL_BUFF_SIZE * sizeof(uint8_t));
546518678f8Sopenharmony_ci        FD_ZERO(&rSet);
547518678f8Sopenharmony_ci        if (ipv6SocketFd < 0) {
548518678f8Sopenharmony_ci            DHCP_LOGE("error: ipv6SocketFd < 0");
549518678f8Sopenharmony_ci            break;
550518678f8Sopenharmony_ci        }
551518678f8Sopenharmony_ci        FD_SET(ipv6SocketFd, &rSet);
552518678f8Sopenharmony_ci        int iRet = select(ipv6SocketFd + 1, &rSet, NULL, NULL, &timeout);
553518678f8Sopenharmony_ci        if (iRet < 0) {
554518678f8Sopenharmony_ci            DHCP_LOGE("StartIpv6 select failed.");
555518678f8Sopenharmony_ci            break;
556518678f8Sopenharmony_ci        } else if (iRet == 0) {
557518678f8Sopenharmony_ci            continue;
558518678f8Sopenharmony_ci        }
559518678f8Sopenharmony_ci        if (!FD_ISSET(ipv6SocketFd, &rSet)) {
560518678f8Sopenharmony_ci            continue;
561518678f8Sopenharmony_ci        }
562518678f8Sopenharmony_ci        int32_t len = recv(ipv6SocketFd, buff, 8 *1024, 0);
563518678f8Sopenharmony_ci        if (len < 0) {
564518678f8Sopenharmony_ci            if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
565518678f8Sopenharmony_ci                continue;
566518678f8Sopenharmony_ci            }
567518678f8Sopenharmony_ci            DHCP_LOGE("StartIpv6 recv kernel socket failed %{public}d.", errno);
568518678f8Sopenharmony_ci            break;
569518678f8Sopenharmony_ci        } else if (len == 0) {
570518678f8Sopenharmony_ci            continue;
571518678f8Sopenharmony_ci        }
572518678f8Sopenharmony_ci        handleKernelEvent(buff, len);
573518678f8Sopenharmony_ci    }
574518678f8Sopenharmony_ci    close(ipv6SocketFd);
575518678f8Sopenharmony_ci    ipv6SocketFd = 0;
576518678f8Sopenharmony_ci    runFlag = false;
577518678f8Sopenharmony_ci    free(buff);
578518678f8Sopenharmony_ci    buff = NULL;
579518678f8Sopenharmony_ci    DHCP_LOGI("DhcpIpv6Client thread exit.");
580518678f8Sopenharmony_ci    return 0;
581518678f8Sopenharmony_ci}
582518678f8Sopenharmony_ci
583518678f8Sopenharmony_civoid *DhcpIpv6Client::DhcpIpv6Start()
584518678f8Sopenharmony_ci{
585518678f8Sopenharmony_ci    if (runFlag) {
586518678f8Sopenharmony_ci        DHCP_LOGI("DhcpIpv6Client already started.");
587518678f8Sopenharmony_ci        return NULL;
588518678f8Sopenharmony_ci    }
589518678f8Sopenharmony_ci    int result = StartIpv6();
590518678f8Sopenharmony_ci    if (result < 0) {
591518678f8Sopenharmony_ci        DHCP_LOGE("dhcp6 run failed.");
592518678f8Sopenharmony_ci    }
593518678f8Sopenharmony_ci    return NULL;
594518678f8Sopenharmony_ci}
595518678f8Sopenharmony_ci
596518678f8Sopenharmony_civoid DhcpIpv6Client::DhcpIPV6Stop(void)
597518678f8Sopenharmony_ci{
598518678f8Sopenharmony_ci    DHCP_LOGI("DhcpIPV6Stop exit ipv6 thread, runFlag:%{public}d", runFlag);
599518678f8Sopenharmony_ci    runFlag = false;
600518678f8Sopenharmony_ci}
601518678f8Sopenharmony_ci
602518678f8Sopenharmony_ci#ifndef OHOS_ARCH_LITE
603518678f8Sopenharmony_ciusing TimeOutCallback = std::function<void()>;
604518678f8Sopenharmony_civoid DhcpIpv6Client::Ipv6TimerCallback()
605518678f8Sopenharmony_ci{
606518678f8Sopenharmony_ci    DHCP_LOGI("enter Ipv6TimerCallback, ipv6TimerId:%{public}u", ipv6TimerId);
607518678f8Sopenharmony_ci    StopIpv6Timer();
608518678f8Sopenharmony_ci    DhcpIpv6TimerCallbackEvent(interfaceName.c_str());
609518678f8Sopenharmony_ci}
610518678f8Sopenharmony_ci
611518678f8Sopenharmony_civoid DhcpIpv6Client::StartIpv6Timer()
612518678f8Sopenharmony_ci{
613518678f8Sopenharmony_ci    DHCP_LOGI("StartIpv6Timer ipv6TimerId:%{public}u", ipv6TimerId);
614518678f8Sopenharmony_ci    std::unique_lock<std::mutex> lock(ipv6TimerMutex);
615518678f8Sopenharmony_ci    if (ipv6TimerId == 0) {
616518678f8Sopenharmony_ci        TimeOutCallback timeoutCallback = [this] { this->Ipv6TimerCallback(); };
617518678f8Sopenharmony_ci        DhcpTimer::GetInstance()->Register(timeoutCallback, ipv6TimerId, DhcpTimer::DEFAULT_TIMEROUT);
618518678f8Sopenharmony_ci        DHCP_LOGI("StartIpv6Timer success! ipv6TimerId:%{public}u", ipv6TimerId);
619518678f8Sopenharmony_ci    }
620518678f8Sopenharmony_ci    return;
621518678f8Sopenharmony_ci}
622518678f8Sopenharmony_ci
623518678f8Sopenharmony_civoid DhcpIpv6Client::StopIpv6Timer()
624518678f8Sopenharmony_ci{
625518678f8Sopenharmony_ci    DHCP_LOGI("StopIpv6Timer ipv6TimerId:%{public}u", ipv6TimerId);
626518678f8Sopenharmony_ci    std::unique_lock<std::mutex> lock(ipv6TimerMutex);
627518678f8Sopenharmony_ci    DhcpTimer::GetInstance()->UnRegister(ipv6TimerId);
628518678f8Sopenharmony_ci    ipv6TimerId = 0;
629518678f8Sopenharmony_ci    return;
630518678f8Sopenharmony_ci}
631518678f8Sopenharmony_ci#endif
632518678f8Sopenharmony_ci}  // namespace DHCP
633518678f8Sopenharmony_ci}  // namespace OHOS