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 
36 namespace OHOS {
37 namespace DHCP {
38 DEFINE_DHCPLOG_DHCP_LABEL("DhcpIpv6Client");
39 
40 const char *DEFAULUT_BAK_DNS = "240e:4c:4008::1";
41 const char *DEFAULT_ROUTE = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
42 const char *DEFAULT_IPV6_ANY_INIT_ADDR = "::";
43 const int IPV6_ADDR_ANY = 0x0000U;
44 const int IPV6_ADDR_UNICAST = 0x0001U;
45 const int IPV6_ADDR_MULTICAST = 0x0002U;
46 const int IPV6_ADDR_SCOPE_MASK = 0x00F0U;
47 const int IPV6_ADDR_LOOPBACK = 0x0010U;
48 const int IPV6_ADDR_LINKLOCAL = 0x0020U;
49 const int IPV6_ADDR_SITELOCAL = 0x0040U;
50 const int IPV6_ADDR_COMPATV4 = 0x0080U;
51 const int IPV6_ADDR_MAPPED = 0x1000U;
52 const unsigned int IPV6_ADDR_SCOPE_NODELOCAL = 0X01;
53 const unsigned int  IPV6_ADDR_SCOPE_LINKLOCAL = 0X02;
54 const unsigned int  IPV6_ADDR_SCOPE_SITELOCAL = 0X05;
55 const int  IPV6_ADDR_SCOPE_GLOBAL = 0X0E;
56 const int S6_ADDR_INDEX_ZERO = 0;
57 const int S6_ADDR_INDEX_FIRST = 1;
58 const int S6_ADDR_INDEX_SECOND = 2;
59 const int S6_ADDR_INDEX_THIRD = 3;
60 const int ADDRTYPE_FLAG_ZERO = 0x00000000;
61 const int ADDRTYPE_FLAG_ONE = 0x00000001;
62 const int ADDRTYPE_FLAG_LOWF = 0x0000ffff;
63 const int ADDRTYPE_FLAG_HIGHE = 0xE0000000;
64 const int ADDRTYPE_FLAG_HIGHFF = 0xFF000000;
65 const int ADDRTYPE_FLAG_HIGHFFC = 0xFFC00000;
66 const int ADDRTYPE_FLAG_HIGHFE8 = 0xFE800000;
67 const int ADDRTYPE_FLAG_HIGHFEC = 0xFEC00000;
68 const int ADDRTYPE_FLAG_HIGHFE = 0xFE000000;
69 const int ADDRTYPE_FLAG_HIGHFC = 0xFC000000;
70 const int MASK_FILTER = 0x7;
71 const int KERNEL_BUFF_SIZE = (8 * 1024);
72 const int ND_OPT_MIN_LEN = 3;
73 const int ROUTE_BUFF_SIZE = 1024;
74 const int IPV6_TIMEOUT_USEC = 500000;
75 const int POSITION_OFFSET_1 = 1;
76 const int POSITION_OFFSET_2 = 2;
77 const int POSITION_OFFSET_3 = 3;
78 const 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
84 struct 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 
DhcpIpv6Client(std::string ifname)92 DhcpIpv6Client::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 
~DhcpIpv6Client()101 DhcpIpv6Client::~DhcpIpv6Client()
102 {
103     DHCP_LOGI("~DhcpIpv6Client()");
104     if (ipv6Thread_ != nullptr) {
105         ipv6Thread_.reset();
106     }
107 }
108 
IsRunning()109 bool DhcpIpv6Client::IsRunning()
110 {
111     DHCP_LOGI("IsRunning()");
112     return runFlag;
113 }
SetCallback(std::function<void(const std::string ifname, DhcpIpv6Info &info)> callback)114 void DhcpIpv6Client::SetCallback(std::function<void(const std::string ifname, DhcpIpv6Info &info)> callback)
115 {
116     DHCP_LOGI("SetCallback()");
117     onIpv6AddressChanged = callback;
118 }
119 
RunIpv6ThreadFunc()120 void DhcpIpv6Client::RunIpv6ThreadFunc()
121 {
122     DhcpIpv6Start();
123 }
124 
StartIpv6Thread(const std::string &ifname, bool isIpv6)125 int 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 
ipv6AddrScope2Type(unsigned int scope)146 unsigned 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 
getAddrType(const struct in6_addr *addr)171 int 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 
getAddrScope(const struct in6_addr *addr)221 int 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 
GetIpv6Prefix(const char* ipv6Addr, char* ipv6PrefixBuf, uint8_t prefixLen)230 void 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 
GetIpFromS6Address(void* addr, int family, char* buf, int buflen)263 int 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 
onIpv6AddressAddEvent(void* data, int prefixLen, int ifaIndex)272 void 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 
AddIpv6Address(char *ipv6addr, int len)312 void 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 
IsEui64ModeIpv6Address(char *ipv6addr, int len)358 bool 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 
onIpv6DnsAddEvent(void* data, int len, int ifaIndex)394 void 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 
onIpv6RouteAddEvent(char* gateway, char* dst, int ifaIndex)444 void 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 
createKernelSocket(void)467 int32_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 
Reset()506 void DhcpIpv6Client::Reset()
507 {
508     (void)memset_s(&dhcpIpv6Info, sizeof(dhcpIpv6Info), 0, sizeof(dhcpIpv6Info));
509 }
510 
getIpv6RouteAddr()511 void 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 
StartIpv6()522 int 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 
DhcpIpv6Start()583 void *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 
DhcpIPV6Stop(void)596 void 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
603 using TimeOutCallback = std::function<void()>;
Ipv6TimerCallback()604 void DhcpIpv6Client::Ipv6TimerCallback()
605 {
606     DHCP_LOGI("enter Ipv6TimerCallback, ipv6TimerId:%{public}u", ipv6TimerId);
607     StopIpv6Timer();
608     DhcpIpv6TimerCallbackEvent(interfaceName.c_str());
609 }
610 
StartIpv6Timer()611 void 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 
StopIpv6Timer()623 void 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