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