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