1/* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0ys/socket.h 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include <signal.h> 16#include <pthread.h> 17#include <ifaddrs.h> 18#include <netdb.h> 19#include <netinet/icmp6.h> 20#include <arpa/inet.h> 21#include <netinet/in.h> 22#include <stdio.h> 23#include <unistd.h> 24#include <dlfcn.h> 25#include <sys/time.h> 26#include <net/if.h> 27#include <errno.h> 28#include <thread> 29#include "securec.h" 30#include "dhcp_logger.h" 31#include "dhcp_ipv6_client.h" 32#include "dhcp_result.h" 33#include "dhcp_thread.h" 34#include "dhcp_function.h" 35 36namespace OHOS { 37namespace DHCP { 38DEFINE_DHCPLOG_DHCP_LABEL("DhcpIpv6Client"); 39 40const char *DEFAULUT_BAK_DNS = "240e:4c:4008::1"; 41const char *DEFAULT_ROUTE = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; 42const char *DEFAULT_IPV6_ANY_INIT_ADDR = "::"; 43const int IPV6_ADDR_ANY = 0x0000U; 44const int IPV6_ADDR_UNICAST = 0x0001U; 45const int IPV6_ADDR_MULTICAST = 0x0002U; 46const int IPV6_ADDR_SCOPE_MASK = 0x00F0U; 47const int IPV6_ADDR_LOOPBACK = 0x0010U; 48const int IPV6_ADDR_LINKLOCAL = 0x0020U; 49const int IPV6_ADDR_SITELOCAL = 0x0040U; 50const int IPV6_ADDR_COMPATV4 = 0x0080U; 51const int IPV6_ADDR_MAPPED = 0x1000U; 52const unsigned int IPV6_ADDR_SCOPE_NODELOCAL = 0X01; 53const unsigned int IPV6_ADDR_SCOPE_LINKLOCAL = 0X02; 54const unsigned int IPV6_ADDR_SCOPE_SITELOCAL = 0X05; 55const int IPV6_ADDR_SCOPE_GLOBAL = 0X0E; 56const int S6_ADDR_INDEX_ZERO = 0; 57const int S6_ADDR_INDEX_FIRST = 1; 58const int S6_ADDR_INDEX_SECOND = 2; 59const int S6_ADDR_INDEX_THIRD = 3; 60const int ADDRTYPE_FLAG_ZERO = 0x00000000; 61const int ADDRTYPE_FLAG_ONE = 0x00000001; 62const int ADDRTYPE_FLAG_LOWF = 0x0000ffff; 63const int ADDRTYPE_FLAG_HIGHE = 0xE0000000; 64const int ADDRTYPE_FLAG_HIGHFF = 0xFF000000; 65const int ADDRTYPE_FLAG_HIGHFFC = 0xFFC00000; 66const int ADDRTYPE_FLAG_HIGHFE8 = 0xFE800000; 67const int ADDRTYPE_FLAG_HIGHFEC = 0xFEC00000; 68const int ADDRTYPE_FLAG_HIGHFE = 0xFE000000; 69const int ADDRTYPE_FLAG_HIGHFC = 0xFC000000; 70const int MASK_FILTER = 0x7; 71const int KERNEL_BUFF_SIZE = (8 * 1024); 72const int ND_OPT_MIN_LEN = 3; 73const int ROUTE_BUFF_SIZE = 1024; 74const int IPV6_TIMEOUT_USEC = 500000; 75const int POSITION_OFFSET_1 = 1; 76const int POSITION_OFFSET_2 = 2; 77const int POSITION_OFFSET_3 = 3; 78const int POSITION_OFFSET_4 = 4; 79 80#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) 81#define IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f) 82#ifndef ND_OPT_RDNSS 83#define ND_OPT_RDNSS 25 84struct nd_opt_rdnss { 85 uint8_t nd_opt_rdnss_type; 86 uint8_t nd_opt_rdnss_len; 87 uint16_t nd_opt_rdnss_reserved; 88 uint32_t nd_opt_rdnss_lifetime; 89} _packed; 90#endif 91 92DhcpIpv6Client::DhcpIpv6Client(std::string ifname) : interfaceName(ifname), runFlag(false) 93{ 94#ifndef OHOS_ARCH_LITE 95 ipv6TimerId = 0; 96#endif 97 ipv6Thread_ = std::make_unique<DhcpThread>("InnerIpv6Thread"); 98 DHCP_LOGI("DhcpIpv6Client()"); 99} 100 101DhcpIpv6Client::~DhcpIpv6Client() 102{ 103 DHCP_LOGI("~DhcpIpv6Client()"); 104 if (ipv6Thread_ != nullptr) { 105 ipv6Thread_.reset(); 106 } 107} 108 109bool DhcpIpv6Client::IsRunning() 110{ 111 DHCP_LOGI("IsRunning()"); 112 return runFlag; 113} 114void DhcpIpv6Client::SetCallback(std::function<void(const std::string ifname, DhcpIpv6Info &info)> callback) 115{ 116 DHCP_LOGI("SetCallback()"); 117 onIpv6AddressChanged = callback; 118} 119 120void DhcpIpv6Client::RunIpv6ThreadFunc() 121{ 122 DhcpIpv6Start(); 123} 124 125int DhcpIpv6Client::StartIpv6Thread(const std::string &ifname, bool isIpv6) 126{ 127 DHCP_LOGI("StartIpv6Thread ifname:%{public}s bIpv6:%{public}d,runFlag:%{public}d", ifname.c_str(), isIpv6, runFlag); 128 if (!runFlag) { 129 interfaceName = ifname; 130 if (ipv6Thread_ == nullptr) { 131 ipv6Thread_ = std::make_unique<DhcpThread>("InnerIpv6Thread"); 132 } 133 std::function<void()> func = [this]() { this->RunIpv6ThreadFunc(); }; 134 int delayTime = 0; 135 bool result = ipv6Thread_->PostAsyncTask(func, delayTime); 136 if (!result) { 137 DHCP_LOGE("StartIpv6Thread PostAsyncTask failed!"); 138 } 139 DHCP_LOGI("StartIpv6Thread RunIpv6ThreadFunc ok!"); 140 } else { 141 DHCP_LOGI("StartIpv6Thread RunIpv6ThreadFunc!"); 142 } 143 return 0; 144} 145 146unsigned int DhcpIpv6Client::ipv6AddrScope2Type(unsigned int scope) 147{ 148 switch (scope) { 149 case IPV6_ADDR_SCOPE_NODELOCAL: 150 return IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | 151 IPV6_ADDR_LOOPBACK; 152 break; 153 154 case IPV6_ADDR_SCOPE_LINKLOCAL: 155 return IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | 156 IPV6_ADDR_LINKLOCAL; 157 break; 158 159 case IPV6_ADDR_SCOPE_SITELOCAL: 160 return IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | 161 IPV6_ADDR_SITELOCAL; 162 break; 163 164 default: 165 break; 166 } 167 168 return IPV6_ADDR_SCOPE_TYPE(scope); 169} 170 171int DhcpIpv6Client::getAddrType(const struct in6_addr *addr) 172{ 173 if (!addr) { 174 DHCP_LOGE("getAddrType failed, data invalid."); 175 return IPV6_ADDR_LINKLOCAL; 176 } 177 unsigned int st = addr->s6_addr32[0]; 178 if ((st & htonl(ADDRTYPE_FLAG_HIGHE)) != htonl(ADDRTYPE_FLAG_ZERO) && 179 (st & htonl(ADDRTYPE_FLAG_HIGHE)) != htonl(ADDRTYPE_FLAG_HIGHE)) { 180 return (IPV6_ADDR_UNICAST | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); 181 } 182 183 if ((st & htonl(ADDRTYPE_FLAG_HIGHFF)) == htonl(ADDRTYPE_FLAG_HIGHFF)) { 184 return (IPV6_ADDR_MULTICAST | ipv6AddrScope2Type(IPV6_ADDR_MC_SCOPE(addr))); 185 } 186 187 if ((st & htonl(ADDRTYPE_FLAG_HIGHFFC)) == htonl(ADDRTYPE_FLAG_HIGHFE8)) { 188 return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | 189 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); 190 } 191 192 if ((st & htonl(ADDRTYPE_FLAG_HIGHFFC)) == htonl(ADDRTYPE_FLAG_HIGHFEC)) { 193 return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | 194 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); 195 } 196 197 if ((st & htonl(ADDRTYPE_FLAG_HIGHFE)) == htonl(ADDRTYPE_FLAG_HIGHFC)) { 198 return (IPV6_ADDR_UNICAST | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); 199 } 200 201 if ((addr->s6_addr32[S6_ADDR_INDEX_ZERO] | addr->s6_addr32[S6_ADDR_INDEX_FIRST]) == 0) { 202 if (addr->s6_addr32[S6_ADDR_INDEX_SECOND] == 0) { 203 if (addr->s6_addr32[S6_ADDR_INDEX_THIRD] == 0) { 204 return IPV6_ADDR_ANY; 205 } 206 if (addr->s6_addr32[S6_ADDR_INDEX_THIRD] == htonl(ADDRTYPE_FLAG_ONE)) { 207 return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | 208 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); 209 } 210 return (IPV6_ADDR_COMPATV4 | IPV6_ADDR_UNICAST | 211 IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); 212 } 213 if (addr->s6_addr32[S6_ADDR_INDEX_THIRD] == htonl(ADDRTYPE_FLAG_LOWF)) { 214 return (IPV6_ADDR_MAPPED | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); 215 } 216 } 217 218 return (IPV6_ADDR_UNICAST | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); 219} 220 221int DhcpIpv6Client::getAddrScope(const struct in6_addr *addr) 222{ 223 if (!addr) { 224 DHCP_LOGE("getAddrType failed, data invalid."); 225 return IPV6_ADDR_LINKLOCAL; 226 } 227 return static_cast<unsigned int>(getAddrType(addr)) & IPV6_ADDR_SCOPE_MASK; 228} 229 230void DhcpIpv6Client::GetIpv6Prefix(const char* ipv6Addr, char* ipv6PrefixBuf, uint8_t prefixLen) 231{ 232 if (!ipv6Addr || !ipv6PrefixBuf) { 233 DHCP_LOGE("GetIpv6Prefix failed, input invalid."); 234 return; 235 } 236 if (prefixLen >= DHCP_INET6_ADDRSTRLEN) { 237 strlcpy(ipv6PrefixBuf, ipv6Addr, DHCP_INET6_ADDRSTRLEN); 238 return; 239 } 240 241 struct in6_addr ipv6AddrBuf = IN6ADDR_ANY_INIT; 242 inet_pton(AF_INET6, ipv6Addr, &ipv6AddrBuf); 243 244 char buf[INET6_ADDRSTRLEN] = {0}; 245 if (inet_ntop(AF_INET6, &ipv6AddrBuf, buf, INET6_ADDRSTRLEN) == NULL) { 246 strlcpy(ipv6PrefixBuf, ipv6Addr, DHCP_INET6_ADDRSTRLEN); 247 return; 248 } 249 250 struct in6_addr ipv6Prefix = IN6ADDR_ANY_INIT; 251 uint32_t byteIndex = prefixLen / CHAR_BIT; 252 if (memset_s(ipv6Prefix.s6_addr, sizeof(ipv6Prefix.s6_addr), 0, sizeof(ipv6Prefix.s6_addr)) != EOK || 253 memcpy_s(ipv6Prefix.s6_addr, sizeof(ipv6Prefix.s6_addr), &ipv6AddrBuf, byteIndex) != EOK) { 254 return; 255 } 256 uint32_t bitOffset = prefixLen & MASK_FILTER; 257 if ((bitOffset != 0) && (byteIndex < INET_ADDRSTRLEN)) { 258 ipv6Prefix.s6_addr[byteIndex] = ipv6AddrBuf.s6_addr[byteIndex] & (0xff00 >> bitOffset); 259 } 260 inet_ntop(AF_INET6, &ipv6Prefix, ipv6PrefixBuf, INET6_ADDRSTRLEN); 261} 262 263int DhcpIpv6Client::GetIpFromS6Address(void* addr, int family, char* buf, int buflen) 264{ 265 if (!inet_ntop(family, (struct in6_addr*)addr, buf, buflen)) { 266 DHCP_LOGE("GetIpFromS6Address failed"); 267 return -1; 268 } 269 return 0; 270} 271 272void DhcpIpv6Client::onIpv6AddressAddEvent(void* data, int prefixLen, int ifaIndex) 273{ 274 int currIndex = static_cast<int>(if_nametoindex(interfaceName.c_str())); 275 if (currIndex != ifaIndex) { 276 DHCP_LOGE("address ifaindex invalid, %{public}d != %{public}d", currIndex, ifaIndex); 277 return; 278 } 279 if (!data) { 280 DHCP_LOGE("onIpv6AddressAddEvent failed, data invalid."); 281 return; 282 } 283 struct in6_addr *addr = (struct in6_addr*)data; 284 char addr_str[INET6_ADDRSTRLEN] = {0}; 285 inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN); 286 int scope = getAddrScope(addr); 287 if (scope == 0) { 288 getIpv6RouteAddr(); 289 if (memset_s(dhcpIpv6Info.ipv6SubnetAddr, DHCP_INET6_ADDRSTRLEN, 290 0, DHCP_INET6_ADDRSTRLEN) != EOK) { 291 DHCP_LOGE("onIpv6AddressAddEvent memset_s failed"); 292 return; 293 } 294 dhcpIpv6Info.status |= 1; 295 GetIpv6Prefix(DEFAULT_ROUTE, dhcpIpv6Info.ipv6SubnetAddr, prefixLen); 296 DHCP_LOGD("onIpv6AddressAddEvent addr:%{private}s, subaddr:%{public}s, route:%{public}s, scope:%{public}d", 297 addr_str, dhcpIpv6Info.ipv6SubnetAddr, dhcpIpv6Info.routeAddr, scope); 298 AddIpv6Address(addr_str, INET6_ADDRSTRLEN); 299 } else if (scope == IPV6_ADDR_LINKLOCAL) { 300 if (memset_s(dhcpIpv6Info.linkIpv6Addr, DHCP_INET6_ADDRSTRLEN, 0, DHCP_INET6_ADDRSTRLEN) != EOK || 301 memcpy_s(dhcpIpv6Info.linkIpv6Addr, INET6_ADDRSTRLEN, addr_str, INET6_ADDRSTRLEN) != EOK) { 302 DHCP_LOGE("onIpv6AddressAddEvent memset_s or memcpy_s failed"); 303 return; 304 } 305 DHCP_LOGD("onIpv6AddressAddEvent addr:%{public}s, subaddr:%{public}s, route:%{public}s, scope:%{public}d", 306 addr_str, dhcpIpv6Info.ipv6SubnetAddr, dhcpIpv6Info.routeAddr, scope); 307 } else { 308 DHCP_LOGD("onIpv6AddressAddEvent other scope:%{public}d", scope); 309 } 310} 311 312void DhcpIpv6Client::AddIpv6Address(char *ipv6addr, int len) 313{ 314 if (!ipv6addr) { 315 DHCP_LOGE("AddIpv6Address ipv6addr is nullptr!"); 316 return; 317 } 318 int first = ipv6addr[0]-'0'; 319 if (first == NUMBER_TWO || first == NUMBER_THREE) { // begin '2' '3' 320 if (IsEui64ModeIpv6Address(ipv6addr, len)) { 321 DHCP_LOGI("AddIpv6Address add globalIpv6Addr, first=%{public}d", first); 322 if (memcpy_s(dhcpIpv6Info.globalIpv6Addr, len, ipv6addr, len) != EOK) { 323 DHCP_LOGE("AddIpv6Address memcpy_s failed!"); 324 return; 325 } 326 } else { 327 DHCP_LOGI("AddIpv6Address add randIpv6Addr, first=%{public}d", first); 328 if (memcpy_s(dhcpIpv6Info.randIpv6Addr, len, ipv6addr, len) != EOK) { 329 DHCP_LOGE("onIpv6AddressAddEvent memcpy_s failed!"); 330 return; 331 } 332 } 333 if (strlen(dhcpIpv6Info.globalIpv6Addr) != 0 || strlen(dhcpIpv6Info.randIpv6Addr) != 0) { 334 onIpv6AddressChanged(interfaceName, dhcpIpv6Info); 335 } 336 } else if (first == NUMBER_FIFTY_FOUR) { // begin 'f'->54 337 if (IsEui64ModeIpv6Address(ipv6addr, len)) { 338 if (memcpy_s(dhcpIpv6Info.uniqueLocalAddr1, len, ipv6addr, len) != EOK) { 339 DHCP_LOGE("AddIpv6Address memcpy_s failed!"); 340 return; 341 } 342 DHCP_LOGI("AddIpv6Address add uniqueLocalAddr1, first=%{public}d", first); 343 } else { 344 if (memcpy_s(dhcpIpv6Info.uniqueLocalAddr2, len, ipv6addr, len) != EOK) { 345 DHCP_LOGE("AddIpv6Address uniqueLocalAddr2 memcpy_s failed!"); 346 return; 347 } 348 DHCP_LOGI("AddIpv6Address add uniqueLocalAddr2, first=%{public}d", first); 349 } 350 if (strlen(dhcpIpv6Info.uniqueLocalAddr1) != 0 || strlen(dhcpIpv6Info.uniqueLocalAddr2) != 0) { 351 onIpv6AddressChanged(interfaceName, dhcpIpv6Info); 352 } 353 } else { 354 DHCP_LOGI("AddIpv6Address other first=%{public}d", first); 355 } 356} 357 358bool DhcpIpv6Client::IsEui64ModeIpv6Address(char *ipv6addr, int len) 359{ 360 if (ipv6addr == nullptr) { 361 DHCP_LOGE("IsEui64ModeIpv6Address ipv6addr is nullptr!"); 362 return false; 363 } 364 int ifaceIndex = 0; 365 unsigned char ifaceMac[MAC_ADDR_LEN]; 366 if (GetLocalInterface(interfaceName.c_str(), &ifaceIndex, ifaceMac, NULL) != DHCP_OPT_SUCCESS) { 367 DHCP_LOGE("IsEui64ModeIpv6Address GetLocalInterface failed, ifaceName:%{public}s.", interfaceName.c_str()); 368 return false; 369 } 370 char macAddr[MAC_ADDR_LEN * MAC_ADDR_CHAR_NUM]; 371 if (memset_s(macAddr, sizeof(macAddr), 0, sizeof(macAddr)) != EOK) { 372 DHCP_LOGE("IsEui64ModeIpv6Address memset_s failed!"); 373 return false; 374 } 375 MacChConToMacStr(ifaceMac, MAC_ADDR_LEN, macAddr, sizeof(macAddr)); 376 std::string localMacString = macAddr; 377 std::string ipv6AddrString = ipv6addr; 378 size_t macPosition = localMacString.find_last_of(':'); 379 size_t ipv6position = ipv6AddrString.find_last_of(':'); 380 DHCP_LOGI("IsEui64ModeIpv6Address name:%{public}s index:%{public}d %{public}zu %{public}zu len:%{public}d", 381 interfaceName.c_str(), ifaceIndex, macPosition, ipv6position, len); 382 if ((macPosition != std::string::npos) && (ipv6position != std::string::npos)) { 383 if (macAddr[macPosition + POSITION_OFFSET_1] == ipv6addr[ipv6position + POSITION_OFFSET_3] && 384 macAddr[macPosition + POSITION_OFFSET_2] == ipv6addr[ipv6position + POSITION_OFFSET_4] && 385 macAddr[macPosition - POSITION_OFFSET_1] == ipv6addr[ipv6position + POSITION_OFFSET_2] && 386 macAddr[macPosition - POSITION_OFFSET_2] == ipv6addr[ipv6position + POSITION_OFFSET_1]) { 387 DHCP_LOGI("IsEui64ModeIpv6Address is true!"); 388 return true; 389 } 390 } 391 return false; 392} 393 394void DhcpIpv6Client::onIpv6DnsAddEvent(void* data, int len, int ifaIndex) 395{ 396 int currIndex = static_cast<int>(if_nametoindex(interfaceName.c_str())); 397 if (currIndex != ifaIndex) { 398 DHCP_LOGE("dnsevent ifaindex invalid, %{public}d != %{public}d", currIndex, ifaIndex); 399 return; 400 } 401 dhcpIpv6Info.status |= (1 << 1); 402 (void)strncpy_s(dhcpIpv6Info.dnsAddr, DHCP_INET6_ADDRSTRLEN, DEFAULUT_BAK_DNS, strlen(DEFAULUT_BAK_DNS)); 403 std::vector<std::string>::iterator iter = find(dhcpIpv6Info.vectorDnsAddr.begin(), 404 dhcpIpv6Info.vectorDnsAddr.end(), DEFAULUT_BAK_DNS); 405 if (iter == dhcpIpv6Info.vectorDnsAddr.end()) { 406 dhcpIpv6Info.vectorDnsAddr.push_back(DEFAULUT_BAK_DNS); 407 } 408 if (!data) { 409 DHCP_LOGE("onIpv6DnsAddEvent failed, data invalid."); 410 return; 411 } 412 struct nd_opt_hdr *opthdr = (struct nd_opt_hdr *)(data); 413 uint16_t optlen = opthdr->nd_opt_len; 414 if (optlen * CHAR_BIT > len) { 415 DHCP_LOGE("dns len invalid optlen:%{public}d > len:%{public}d", optlen, len); 416 return; 417 } 418 if (opthdr->nd_opt_type != ND_OPT_RDNSS) { 419 DHCP_LOGE("dns nd_opt_type invlid:%{public}d", opthdr->nd_opt_type); 420 return; 421 } 422 if ((optlen < ND_OPT_MIN_LEN) || !(optlen & 0x1)) { 423 DHCP_LOGE("dns optLen invlid:%{public}d", optlen); 424 return; 425 } 426 (void)memset_s(dhcpIpv6Info.dnsAddr2, DHCP_INET6_ADDRSTRLEN, 0, DHCP_INET6_ADDRSTRLEN); 427 int numaddrs = (optlen - 1) / 2; 428 struct nd_opt_rdnss *rndsopt = (struct nd_opt_rdnss *)opthdr; 429 struct in6_addr *addrs = (struct in6_addr *)(rndsopt + 1); 430 if (numaddrs > 0) { 431 inet_ntop(AF_INET6, addrs + 0, dhcpIpv6Info.dnsAddr2, DHCP_INET6_ADDRSTRLEN); 432 } 433 for (int i = 0; i < numaddrs; i++) { 434 char dnsAddr[DHCP_INET6_ADDRSTRLEN] = {0}; 435 inet_ntop(AF_INET6, addrs + i, dnsAddr, DHCP_INET6_ADDRSTRLEN); 436 iter = find(dhcpIpv6Info.vectorDnsAddr.begin(), dhcpIpv6Info.vectorDnsAddr.end(), dnsAddr); 437 if (iter == dhcpIpv6Info.vectorDnsAddr.end()) { 438 dhcpIpv6Info.vectorDnsAddr.push_back(dnsAddr); 439 DHCP_LOGI("onIpv6DnsAddEvent add dns:%{public}d", i); 440 } 441 } 442} 443 444void DhcpIpv6Client::onIpv6RouteAddEvent(char* gateway, char* dst, int ifaIndex) 445{ 446 int currIndex = static_cast<int>(if_nametoindex(interfaceName.c_str())); 447 if (currIndex != ifaIndex) { 448 DHCP_LOGE("route ifaindex invalid, %{public}d != %{public}d", currIndex, ifaIndex); 449 return; 450 } 451 DHCP_LOGI("onIpv6RouteAddEvent gateway:%{private}s, dst:%{private}s, ifindex:%{public}d", 452 gateway, dst, ifaIndex); 453 if (!gateway || !dst) { 454 DHCP_LOGE("onIpv6RouteAddEvent input invalid."); 455 return; 456 } 457 if (strlen(dst) == 0 && strlen(gateway) != 0) { 458 (void)memset_s(dhcpIpv6Info.routeAddr, DHCP_INET6_ADDRSTRLEN, 459 0, DHCP_INET6_ADDRSTRLEN); 460 if (strncpy_s(dhcpIpv6Info.routeAddr, DHCP_INET6_ADDRSTRLEN, gateway, strlen(gateway)) != EOK) { 461 DHCP_LOGE("onIpv6RouteAddEvent strncpy_s gateway failed"); 462 return; 463 } 464 } 465} 466 467int32_t DhcpIpv6Client::createKernelSocket(void) 468{ 469 int32_t sz = KERNEL_BUFF_SIZE; 470 int32_t on = 1; 471 int32_t sockFd = socket(AF_NETLINK, SOCK_RAW, 0); 472 if (sockFd < 0) { 473 DHCP_LOGE("dhcp6 create socket failed."); 474 return -1; 475 } 476 if (setsockopt(sockFd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) { 477 DHCP_LOGE("setsockopt socket SO_RCVBUFFORCE failed."); 478 close(sockFd); 479 return -1; 480 } 481 if (setsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0) { 482 DHCP_LOGE("setsockopt socket SO_RCVBUF failed."); 483 close(sockFd); 484 return -1; 485 } 486 if (setsockopt(sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { 487 DHCP_LOGE("setsockopt socket SO_PASSCRED failed."); 488 close(sockFd); 489 return -1; 490 } 491 struct timeval timeout = {1, 0}; 492 if (setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { 493 DHCP_LOGE("setsockopt socket SO_RCVTIMEO failed."); 494 } 495 struct sockaddr saddr; 496 (void)memset_s(&saddr, sizeof(saddr), 0, sizeof(saddr)); 497 setSocketFilter(&saddr); 498 if (bind(sockFd, &saddr, sizeof(saddr)) < 0) { 499 DHCP_LOGE("bind kernel socket failed."); 500 close(sockFd); 501 return -1; 502 } 503 return sockFd; 504} 505 506void DhcpIpv6Client::Reset() 507{ 508 (void)memset_s(&dhcpIpv6Info, sizeof(dhcpIpv6Info), 0, sizeof(dhcpIpv6Info)); 509} 510 511void DhcpIpv6Client::getIpv6RouteAddr() 512{ 513 int len = ROUTE_BUFF_SIZE; 514 char buffer[ROUTE_BUFF_SIZE] = {0}; 515 fillRouteData(buffer, len); 516 if (send(ipv6SocketFd, buffer, len, 0) < 0) { 517 DHCP_LOGE("getIpv6RouteAddr send route info failed."); 518 } 519 DHCP_LOGE("getIpv6RouteAddr send info ok"); 520} 521 522int DhcpIpv6Client::StartIpv6() 523{ 524 DHCP_LOGI("StartIpv6 enter. %{public}s", interfaceName.c_str()); 525 (void)memset_s(&dhcpIpv6Info, sizeof(dhcpIpv6Info), 0, sizeof(dhcpIpv6Info)); 526 runFlag = true; 527 ipv6SocketFd = createKernelSocket(); 528 if (ipv6SocketFd < 0) { 529 runFlag = false; 530 DHCP_LOGE("StartIpv6 ipv6SocketFd < 0 failed!"); 531 return -1; 532 } 533 uint8_t *buff = (uint8_t*)malloc(KERNEL_BUFF_SIZE * sizeof(uint8_t)); 534 if (buff == NULL) { 535 DHCP_LOGE("StartIpv6 ipv6 malloc buff failed."); 536 close(ipv6SocketFd); 537 runFlag = false; 538 return -1; 539 } 540 struct timeval timeout = {0}; 541 fd_set rSet; 542 timeout.tv_sec = 0; 543 timeout.tv_usec = IPV6_TIMEOUT_USEC; 544 while (runFlag) { 545 (void)memset_s(buff, KERNEL_BUFF_SIZE * sizeof(uint8_t), 0, KERNEL_BUFF_SIZE * sizeof(uint8_t)); 546 FD_ZERO(&rSet); 547 if (ipv6SocketFd < 0) { 548 DHCP_LOGE("error: ipv6SocketFd < 0"); 549 break; 550 } 551 FD_SET(ipv6SocketFd, &rSet); 552 int iRet = select(ipv6SocketFd + 1, &rSet, NULL, NULL, &timeout); 553 if (iRet < 0) { 554 DHCP_LOGE("StartIpv6 select failed."); 555 break; 556 } else if (iRet == 0) { 557 continue; 558 } 559 if (!FD_ISSET(ipv6SocketFd, &rSet)) { 560 continue; 561 } 562 int32_t len = recv(ipv6SocketFd, buff, 8 *1024, 0); 563 if (len < 0) { 564 if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { 565 continue; 566 } 567 DHCP_LOGE("StartIpv6 recv kernel socket failed %{public}d.", errno); 568 break; 569 } else if (len == 0) { 570 continue; 571 } 572 handleKernelEvent(buff, len); 573 } 574 close(ipv6SocketFd); 575 ipv6SocketFd = 0; 576 runFlag = false; 577 free(buff); 578 buff = NULL; 579 DHCP_LOGI("DhcpIpv6Client thread exit."); 580 return 0; 581} 582 583void *DhcpIpv6Client::DhcpIpv6Start() 584{ 585 if (runFlag) { 586 DHCP_LOGI("DhcpIpv6Client already started."); 587 return NULL; 588 } 589 int result = StartIpv6(); 590 if (result < 0) { 591 DHCP_LOGE("dhcp6 run failed."); 592 } 593 return NULL; 594} 595 596void DhcpIpv6Client::DhcpIPV6Stop(void) 597{ 598 DHCP_LOGI("DhcpIPV6Stop exit ipv6 thread, runFlag:%{public}d", runFlag); 599 runFlag = false; 600} 601 602#ifndef OHOS_ARCH_LITE 603using TimeOutCallback = std::function<void()>; 604void DhcpIpv6Client::Ipv6TimerCallback() 605{ 606 DHCP_LOGI("enter Ipv6TimerCallback, ipv6TimerId:%{public}u", ipv6TimerId); 607 StopIpv6Timer(); 608 DhcpIpv6TimerCallbackEvent(interfaceName.c_str()); 609} 610 611void DhcpIpv6Client::StartIpv6Timer() 612{ 613 DHCP_LOGI("StartIpv6Timer ipv6TimerId:%{public}u", ipv6TimerId); 614 std::unique_lock<std::mutex> lock(ipv6TimerMutex); 615 if (ipv6TimerId == 0) { 616 TimeOutCallback timeoutCallback = [this] { this->Ipv6TimerCallback(); }; 617 DhcpTimer::GetInstance()->Register(timeoutCallback, ipv6TimerId, DhcpTimer::DEFAULT_TIMEROUT); 618 DHCP_LOGI("StartIpv6Timer success! ipv6TimerId:%{public}u", ipv6TimerId); 619 } 620 return; 621} 622 623void DhcpIpv6Client::StopIpv6Timer() 624{ 625 DHCP_LOGI("StopIpv6Timer ipv6TimerId:%{public}u", ipv6TimerId); 626 std::unique_lock<std::mutex> lock(ipv6TimerMutex); 627 DhcpTimer::GetInstance()->UnRegister(ipv6TimerId); 628 ipv6TimerId = 0; 629 return; 630} 631#endif 632} // namespace DHCP 633} // namespace OHOS