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