Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2022 Project CHIP Authors
4 : * Copyright (c) 2019 Google LLC.
5 : * Copyright (c) 2013-2017 Nest Labs, Inc.
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : /**
21 : * @file
22 : * Implementation of network interface abstraction layer.
23 : *
24 : */
25 :
26 : #ifndef __STDC_LIMIT_MACROS
27 : #define __STDC_LIMIT_MACROS
28 : #endif
29 :
30 : #include <inet/InetInterface.h>
31 :
32 : #include <inet/IPPrefix.h>
33 : #include <lib/support/CHIPMem.h>
34 : #include <lib/support/CHIPMemString.h>
35 : #include <lib/support/CodeUtils.h>
36 : #include <lib/support/DLLUtil.h>
37 : #include <lib/support/SafeInt.h>
38 :
39 : #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
40 : #include <lwip/netif.h>
41 : #include <lwip/sys.h>
42 : #include <lwip/tcpip.h>
43 : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
44 :
45 : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
46 : #include <errno.h>
47 : #include <fcntl.h>
48 : #include <sys/socket.h>
49 : #include <unistd.h>
50 : #ifdef HAVE_SYS_SOCKIO_H
51 : #include <sys/sockio.h>
52 : #endif /* HAVE_SYS_SOCKIO_H */
53 : #include "InetInterfaceImpl.h"
54 : #include <ifaddrs.h>
55 : #include <net/if.h>
56 : #include <sys/ioctl.h>
57 : #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
58 :
59 : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
60 : #include <zephyr/net/net_if.h>
61 : #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
62 :
63 : #if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
64 : #include <inet/UDPEndPointImplOpenThread.h>
65 : #endif
66 :
67 : #include <stdio.h>
68 : #include <string.h>
69 :
70 : namespace chip {
71 : namespace Inet {
72 :
73 : #if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
74 : CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
75 : {
76 : if (mPlatformInterface && nameBufSize >= kMaxIfNameLength)
77 : {
78 : nameBuf[0] = 'o';
79 : nameBuf[1] = 't';
80 : nameBuf[2] = 0;
81 : }
82 : else
83 : {
84 : nameBuf[0] = 0;
85 : }
86 :
87 : return CHIP_NO_ERROR;
88 : }
89 : CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
90 : {
91 : if (strlen(intfName) < 3)
92 : {
93 : return INET_ERROR_UNKNOWN_INTERFACE;
94 : }
95 : char * parseEnd = nullptr;
96 : unsigned long intfNum = strtoul(intfName + 2, &parseEnd, 10);
97 : if (*parseEnd != 0 || intfNum > UINT8_MAX)
98 : {
99 : return INET_ERROR_UNKNOWN_INTERFACE;
100 : }
101 :
102 : interface = InterfaceId(intfNum);
103 : if (intfNum == 0)
104 : {
105 : return INET_ERROR_UNKNOWN_INTERFACE;
106 : }
107 : return CHIP_NO_ERROR;
108 : }
109 :
110 : bool InterfaceIterator::Next()
111 : {
112 : // TODO : Cleanup #17346
113 : return false;
114 : }
115 :
116 : InterfaceAddressIterator::InterfaceAddressIterator()
117 : {
118 : mNetifAddrList = nullptr;
119 : mCurAddr = nullptr;
120 : }
121 :
122 : bool InterfaceAddressIterator::HasCurrent()
123 : {
124 : return (mNetifAddrList != nullptr) ? (mCurAddr != nullptr) : Next();
125 : }
126 :
127 : bool InterfaceAddressIterator::Next()
128 : {
129 : if (mNetifAddrList == nullptr)
130 : {
131 : mNetifAddrList = otIp6GetUnicastAddresses(Inet::globalOtInstance);
132 : mCurAddr = mNetifAddrList;
133 : }
134 : else if (mCurAddr != nullptr)
135 : {
136 : mCurAddr = mCurAddr->mNext;
137 : }
138 :
139 : return (mCurAddr != nullptr);
140 : }
141 : CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress)
142 : {
143 : if (!HasCurrent())
144 : {
145 : return CHIP_ERROR_SENTINEL;
146 : }
147 :
148 : outIPAddress = IPAddress(mCurAddr->mAddress);
149 : return CHIP_NO_ERROR;
150 : }
151 :
152 : uint8_t InterfaceAddressIterator::GetPrefixLength()
153 : {
154 : // Only 64 bits prefix are supported
155 : return 64;
156 : }
157 :
158 : #endif
159 :
160 : #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
161 :
162 : CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
163 : {
164 : if (mPlatformInterface)
165 : {
166 : int status = snprintf(nameBuf, nameBufSize, "%c%c%d", mPlatformInterface->name[0], mPlatformInterface->name[1],
167 : mPlatformInterface->num);
168 : if (status >= static_cast<int>(nameBufSize))
169 : return CHIP_ERROR_BUFFER_TOO_SMALL;
170 : return CHIP_NO_ERROR;
171 : }
172 : if (nameBufSize < 1)
173 : {
174 : return CHIP_ERROR_BUFFER_TOO_SMALL;
175 : }
176 : nameBuf[0] = 0;
177 : return CHIP_NO_ERROR;
178 : }
179 :
180 : CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
181 : {
182 : if (strlen(intfName) < 3)
183 : {
184 : return INET_ERROR_UNKNOWN_INTERFACE;
185 : }
186 : char * parseEnd;
187 : unsigned long intfNum = strtoul(intfName + 2, &parseEnd, 10);
188 : if (*parseEnd != 0 || intfNum > UINT8_MAX)
189 : {
190 : return INET_ERROR_UNKNOWN_INTERFACE;
191 : }
192 : struct netif * intf;
193 : #if defined(NETIF_FOREACH)
194 : NETIF_FOREACH(intf)
195 : #else
196 : for (intf = netif_list; intf != NULL; intf = intf->next)
197 : #endif
198 : {
199 : if (intf->name[0] == intfName[0] && intf->name[1] == intfName[1] && intf->num == (uint8_t) intfNum)
200 : {
201 : interface = InterfaceId(intf);
202 : return CHIP_NO_ERROR;
203 : }
204 : }
205 : interface = InterfaceId::Null();
206 : return INET_ERROR_UNKNOWN_INTERFACE;
207 : }
208 :
209 : bool InterfaceIterator::Next()
210 : {
211 : // Lock LwIP stack
212 : LOCK_TCPIP_CORE();
213 :
214 : // Verify the previous netif is still on the list if netifs. If so,
215 : // advance to the next nextif.
216 : struct netif * prevNetif = mCurNetif;
217 : #if defined(NETIF_FOREACH)
218 : NETIF_FOREACH(mCurNetif)
219 : #else
220 : for (mCurNetif = netif_list; mCurNetif != nullptr; mCurNetif = mCurNetif->next)
221 : #endif
222 : {
223 : if (mCurNetif == prevNetif)
224 : {
225 : mCurNetif = mCurNetif->next;
226 : break;
227 : }
228 : }
229 :
230 : // Unlock LwIP stack
231 : UNLOCK_TCPIP_CORE();
232 :
233 : return mCurNetif != nullptr;
234 : }
235 :
236 : CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
237 : {
238 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
239 : return InterfaceId(mCurNetif).GetInterfaceName(nameBuf, nameBufSize);
240 : }
241 :
242 : bool InterfaceIterator::IsUp()
243 : {
244 : return HasCurrent() && netif_is_up(mCurNetif);
245 : }
246 :
247 : bool InterfaceIterator::SupportsMulticast()
248 : {
249 : return HasCurrent() && (mCurNetif->flags & (NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_BROADCAST)) != 0;
250 : }
251 :
252 : bool InterfaceIterator::HasBroadcastAddress()
253 : {
254 : return HasCurrent() && (mCurNetif->flags & NETIF_FLAG_BROADCAST) != 0;
255 : }
256 :
257 : CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
258 : {
259 : return CHIP_ERROR_NOT_IMPLEMENTED;
260 : }
261 :
262 : CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
263 : {
264 : VerifyOrReturnError(addressBuffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
265 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
266 : VerifyOrReturnError(addressBufferSize >= mCurNetif->hwaddr_len, CHIP_ERROR_BUFFER_TOO_SMALL);
267 : addressSize = mCurNetif->hwaddr_len;
268 : memcpy(addressBuffer, mCurNetif->hwaddr, addressSize);
269 : return CHIP_NO_ERROR;
270 : }
271 :
272 : bool InterfaceAddressIterator::HasCurrent()
273 : {
274 : return mIntfIter.HasCurrent() && ((mCurAddrIndex != kBeforeStartIndex) || Next());
275 : }
276 :
277 : bool InterfaceAddressIterator::Next()
278 : {
279 : mCurAddrIndex++;
280 :
281 : while (mIntfIter.HasCurrent())
282 : {
283 : struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
284 :
285 : while (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES)
286 : {
287 : if (ip6_addr_isvalid(netif_ip6_addr_state(curIntf, mCurAddrIndex)))
288 : {
289 : return true;
290 : }
291 : mCurAddrIndex++;
292 : }
293 :
294 : #if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
295 : if (mCurAddrIndex == LWIP_IPV6_NUM_ADDRESSES)
296 : {
297 : if (!ip4_addr_isany(netif_ip4_addr(curIntf)))
298 : {
299 : return true;
300 : }
301 : }
302 : #endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
303 :
304 : mIntfIter.Next();
305 : mCurAddrIndex = 0;
306 : }
307 :
308 : return false;
309 : }
310 :
311 : CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress)
312 : {
313 : if (!HasCurrent())
314 : {
315 : return CHIP_ERROR_SENTINEL;
316 : }
317 :
318 : struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
319 :
320 : if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES)
321 : {
322 : outIPAddress = IPAddress(*netif_ip6_addr(curIntf, mCurAddrIndex));
323 : return CHIP_NO_ERROR;
324 : }
325 : #if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
326 : outIPAddress = IPAddress(*netif_ip4_addr(curIntf));
327 : return CHIP_NO_ERROR;
328 : #else
329 : return CHIP_ERROR_INTERNAL;
330 : #endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
331 : }
332 :
333 : uint8_t InterfaceAddressIterator::GetPrefixLength()
334 : {
335 : if (HasCurrent())
336 : {
337 : if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES)
338 : {
339 : return 64;
340 : }
341 : #if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
342 : struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
343 : return NetmaskToPrefixLength((const uint8_t *) netif_ip4_netmask(curIntf), 4);
344 : #endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
345 : }
346 : return 0;
347 : }
348 :
349 : InterfaceId InterfaceAddressIterator::GetInterfaceId()
350 : {
351 : return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null();
352 : }
353 :
354 : CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
355 : {
356 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
357 : return mIntfIter.GetInterfaceName(nameBuf, nameBufSize);
358 : }
359 :
360 : bool InterfaceAddressIterator::IsUp()
361 : {
362 : return HasCurrent() && mIntfIter.IsUp();
363 : }
364 :
365 : bool InterfaceAddressIterator::SupportsMulticast()
366 : {
367 : return HasCurrent() && mIntfIter.SupportsMulticast();
368 : }
369 :
370 : bool InterfaceAddressIterator::HasBroadcastAddress()
371 : {
372 : return HasCurrent() && mIntfIter.HasBroadcastAddress();
373 : }
374 :
375 : CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const
376 : {
377 : VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
378 :
379 : #if !LWIP_IPV6
380 : return CHIP_ERROR_NOT_IMPLEMENTED;
381 : #endif //! LWIP_IPV6
382 :
383 : for (struct netif * intf = netif_list; intf != nullptr; intf = intf->next)
384 : {
385 : if ((mPlatformInterface != nullptr) && (mPlatformInterface != intf))
386 : continue;
387 : for (int j = 0; j < LWIP_IPV6_NUM_ADDRESSES; ++j)
388 : {
389 : if (ip6_addr_isvalid(netif_ip6_addr_state(intf, j)) && ip6_addr_islinklocal(netif_ip6_addr(intf, j)))
390 : {
391 : (*llAddr) = IPAddress(*netif_ip6_addr(intf, j));
392 : return CHIP_NO_ERROR;
393 : }
394 : }
395 : if (mPlatformInterface != nullptr)
396 : {
397 : return INET_ERROR_ADDRESS_NOT_FOUND;
398 : }
399 : }
400 :
401 : return CHIP_NO_ERROR;
402 : }
403 :
404 : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
405 :
406 : #if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
407 :
408 2 : CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
409 : {
410 2 : if (mPlatformInterface)
411 : {
412 : char intfName[IF_NAMESIZE];
413 0 : if (if_indextoname(mPlatformInterface, intfName) == nullptr)
414 : {
415 0 : return CHIP_ERROR_POSIX(errno);
416 : }
417 0 : size_t nameLength = strlen(intfName);
418 0 : if (nameLength >= nameBufSize)
419 : {
420 0 : return CHIP_ERROR_BUFFER_TOO_SMALL;
421 : }
422 0 : Platform::CopyString(nameBuf, nameBufSize, intfName);
423 0 : return CHIP_NO_ERROR;
424 : }
425 2 : if (nameBufSize < 1)
426 : {
427 1 : return CHIP_ERROR_BUFFER_TOO_SMALL;
428 : }
429 1 : nameBuf[0] = 0;
430 1 : return CHIP_NO_ERROR;
431 : }
432 :
433 1 : CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
434 : {
435 : // First attempt to parse as a numeric ID:
436 : char * parseEnd;
437 1 : unsigned long intfNum = strtoul(intfName, &parseEnd, 10);
438 1 : if (*parseEnd == 0)
439 : {
440 1 : if (intfNum > 0 && intfNum < UINT8_MAX && CanCastTo<InterfaceId::PlatformType>(intfNum))
441 : {
442 0 : interface = InterfaceId(static_cast<InterfaceId::PlatformType>(intfNum));
443 0 : return CHIP_NO_ERROR;
444 : }
445 :
446 1 : return INET_ERROR_UNKNOWN_INTERFACE;
447 : }
448 :
449 : // Falling back to name -> ID lookup otherwise (e.g. wlan0)
450 0 : unsigned int intfId = if_nametoindex(intfName);
451 0 : interface = InterfaceId(intfId);
452 0 : if (intfId == 0)
453 : {
454 0 : return (errno == ENXIO) ? INET_ERROR_UNKNOWN_INTERFACE : CHIP_ERROR_POSIX(errno);
455 : }
456 0 : return CHIP_NO_ERROR;
457 : }
458 :
459 : static int sIOCTLSocket = -1;
460 :
461 : /**
462 : * @brief Returns a global general purpose socket useful for invoking certain network IOCTLs.
463 : *
464 : * This function is thread-safe on all platforms.
465 : */
466 152 : int GetIOCTLSocket()
467 : {
468 152 : if (sIOCTLSocket == -1)
469 : {
470 : int s;
471 : #ifdef SOCK_CLOEXEC
472 4 : s = socket(AF_INET, SOCK_STREAM, SOCK_CLOEXEC);
473 4 : if (s < 0)
474 : #endif
475 : {
476 4 : s = socket(AF_INET, SOCK_STREAM, 0);
477 4 : fcntl(s, O_CLOEXEC);
478 : }
479 :
480 4 : if (!__sync_bool_compare_and_swap(&sIOCTLSocket, -1, s))
481 : {
482 0 : close(s);
483 : }
484 : }
485 152 : return sIOCTLSocket;
486 : }
487 :
488 : /**
489 : * @brief Close the global socket created by \c GetIOCTLSocket.
490 : *
491 : * @details
492 : * This function is provided for cases were leaving the global IOCTL socket
493 : * open would register as a leak.
494 : *
495 : * NB: This function is NOT thread-safe with respect to \c GetIOCTLSocket.
496 : */
497 0 : void CloseIOCTLSocket()
498 : {
499 0 : if (sIOCTLSocket != -1)
500 : {
501 0 : close(sIOCTLSocket);
502 0 : sIOCTLSocket = -1;
503 : }
504 0 : }
505 :
506 76 : InterfaceIterator::InterfaceIterator()
507 : {
508 76 : mIntfArray = nullptr;
509 76 : mCurIntf = 0;
510 76 : mIntfFlags = 0;
511 76 : mIntfFlagsCached = false;
512 76 : }
513 :
514 76 : InterfaceIterator::~InterfaceIterator()
515 : {
516 76 : if (mIntfArray != nullptr)
517 : {
518 76 : if_freenameindexImpl(mIntfArray);
519 76 : mIntfArray = nullptr;
520 : }
521 76 : }
522 :
523 1054 : bool InterfaceIterator::HasCurrent()
524 : {
525 1054 : return (mIntfArray != nullptr) ? mIntfArray[mCurIntf].if_index != 0 : Next();
526 : }
527 :
528 229 : bool InterfaceIterator::Next()
529 : {
530 229 : if (mIntfArray == nullptr)
531 : {
532 76 : mIntfArray = if_nameindexImpl();
533 : }
534 153 : else if (mIntfArray[mCurIntf].if_index != 0)
535 : {
536 152 : mCurIntf++;
537 152 : mIntfFlags = 0;
538 152 : mIntfFlagsCached = false;
539 : }
540 229 : return (mIntfArray != nullptr && mIntfArray[mCurIntf].if_index != 0);
541 : }
542 :
543 300 : InterfaceId InterfaceIterator::GetInterfaceId()
544 : {
545 300 : return HasCurrent() ? InterfaceId(mIntfArray[mCurIntf].if_index) : InterfaceId::Null();
546 : }
547 :
548 153 : CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
549 : {
550 153 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
551 152 : VerifyOrReturnError(strlen(mIntfArray[mCurIntf].if_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL);
552 152 : Platform::CopyString(nameBuf, nameBufSize, mIntfArray[mCurIntf].if_name);
553 152 : return CHIP_NO_ERROR;
554 : }
555 :
556 151 : bool InterfaceIterator::IsUp()
557 : {
558 151 : return (GetFlags() & IFF_UP) != 0;
559 : }
560 :
561 0 : bool InterfaceIterator::IsLoopback()
562 : {
563 0 : return (GetFlags() & IFF_LOOPBACK) != 0;
564 : }
565 :
566 5 : bool InterfaceIterator::SupportsMulticast()
567 : {
568 5 : return (GetFlags() & IFF_MULTICAST) != 0;
569 : }
570 :
571 3 : bool InterfaceIterator::HasBroadcastAddress()
572 : {
573 3 : return (GetFlags() & IFF_BROADCAST) != 0;
574 : }
575 :
576 159 : short InterfaceIterator::GetFlags()
577 : {
578 : struct ifreq intfData;
579 :
580 159 : if (!mIntfFlagsCached && HasCurrent())
581 : {
582 152 : Platform::CopyString(intfData.ifr_name, mIntfArray[mCurIntf].if_name);
583 :
584 152 : int res = ioctl(GetIOCTLSocket(), SIOCGIFFLAGS, &intfData);
585 152 : if (res == 0)
586 : {
587 152 : mIntfFlags = intfData.ifr_flags;
588 152 : mIntfFlagsCached = true;
589 : }
590 : #ifdef __MBED__
591 : CloseIOCTLSocket();
592 : #endif
593 : }
594 :
595 159 : return mIntfFlags;
596 : }
597 :
598 3 : CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
599 : {
600 3 : return CHIP_ERROR_NOT_IMPLEMENTED;
601 : }
602 :
603 3 : CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
604 : {
605 3 : return CHIP_ERROR_NOT_IMPLEMENTED;
606 : }
607 :
608 567 : InterfaceAddressIterator::InterfaceAddressIterator()
609 : {
610 567 : mAddrsList = nullptr;
611 567 : mCurAddr = nullptr;
612 567 : }
613 :
614 567 : InterfaceAddressIterator::~InterfaceAddressIterator()
615 : {
616 567 : if (mAddrsList != nullptr)
617 : {
618 453 : freeifaddrs(mAddrsList);
619 453 : mAddrsList = mCurAddr = nullptr;
620 : }
621 567 : }
622 :
623 4211 : bool InterfaceAddressIterator::HasCurrent()
624 : {
625 4211 : return (mAddrsList != nullptr) ? (mCurAddr != nullptr) : Next();
626 : }
627 :
628 2966 : bool InterfaceAddressIterator::Next()
629 : {
630 : while (true)
631 : {
632 2966 : if (mAddrsList == nullptr)
633 : {
634 453 : int res = getifaddrs(&mAddrsList);
635 453 : if (res < 0)
636 : {
637 0 : return false;
638 : }
639 453 : mCurAddr = mAddrsList;
640 : }
641 2513 : else if (mCurAddr != nullptr)
642 : {
643 2512 : mCurAddr = mCurAddr->ifa_next;
644 : }
645 :
646 2966 : if (mCurAddr == nullptr)
647 : {
648 360 : return false;
649 : }
650 :
651 2606 : if (mCurAddr->ifa_addr != nullptr &&
652 2606 : (mCurAddr->ifa_addr->sa_family == AF_INET6
653 : #if INET_CONFIG_ENABLE_IPV4
654 1812 : || mCurAddr->ifa_addr->sa_family == AF_INET
655 : #endif // INET_CONFIG_ENABLE_IPV4
656 : ))
657 : {
658 1700 : return true;
659 : }
660 906 : }
661 : }
662 :
663 948 : CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress)
664 : {
665 948 : return HasCurrent() ? IPAddress::GetIPAddressFromSockAddr(*mCurAddr->ifa_addr, outIPAddress) : CHIP_ERROR_SENTINEL;
666 : }
667 :
668 103 : uint8_t InterfaceAddressIterator::GetPrefixLength()
669 : {
670 103 : if (HasCurrent())
671 : {
672 103 : if (mCurAddr->ifa_addr->sa_family == AF_INET6)
673 : {
674 : #ifndef __MBED__
675 101 : struct sockaddr_in6 & netmask = *reinterpret_cast<struct sockaddr_in6 *>(mCurAddr->ifa_netmask);
676 101 : return NetmaskToPrefixLength(netmask.sin6_addr.s6_addr, 16);
677 : #else // __MBED__
678 : // netmask is not available through an API for IPv6 interface in Mbed.
679 : // Default prefix length to 64.
680 : return 64;
681 : #endif // !__MBED__
682 : }
683 2 : if (mCurAddr->ifa_addr->sa_family == AF_INET)
684 : {
685 2 : struct sockaddr_in & netmask = *reinterpret_cast<struct sockaddr_in *>(mCurAddr->ifa_netmask);
686 2 : return NetmaskToPrefixLength(reinterpret_cast<const uint8_t *>(&netmask.sin_addr.s_addr), 4);
687 : }
688 : }
689 0 : return 0;
690 : }
691 :
692 1222 : InterfaceId InterfaceAddressIterator::GetInterfaceId()
693 : {
694 1222 : return HasCurrent() ? InterfaceId(if_nametoindex(mCurAddr->ifa_name)) : InterfaceId::Null();
695 : }
696 :
697 5 : CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
698 : {
699 5 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
700 4 : VerifyOrReturnError(strlen(mCurAddr->ifa_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL);
701 4 : Platform::CopyString(nameBuf, nameBufSize, mCurAddr->ifa_name);
702 4 : return CHIP_NO_ERROR;
703 : }
704 :
705 8 : bool InterfaceAddressIterator::IsUp()
706 : {
707 8 : return HasCurrent() && (mCurAddr->ifa_flags & IFF_UP) != 0;
708 : }
709 :
710 0 : bool InterfaceAddressIterator::IsLoopback()
711 : {
712 0 : return HasCurrent() && (mCurAddr->ifa_flags & IFF_LOOPBACK) != 0;
713 : }
714 :
715 5 : bool InterfaceAddressIterator::SupportsMulticast()
716 : {
717 5 : return HasCurrent() && (mCurAddr->ifa_flags & IFF_MULTICAST) != 0;
718 : }
719 :
720 9 : bool InterfaceAddressIterator::HasBroadcastAddress()
721 : {
722 9 : return HasCurrent() && (mCurAddr->ifa_flags & IFF_BROADCAST) != 0;
723 : }
724 :
725 5 : CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const
726 : {
727 5 : VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
728 :
729 : struct ifaddrs * ifaddr;
730 4 : const int rv = getifaddrs(&ifaddr);
731 4 : bool found = false;
732 :
733 4 : if (rv == -1)
734 : {
735 0 : return INET_ERROR_ADDRESS_NOT_FOUND;
736 : }
737 :
738 25 : for (struct ifaddrs * ifaddr_iter = ifaddr; ifaddr_iter != nullptr; ifaddr_iter = ifaddr_iter->ifa_next)
739 : {
740 24 : if (ifaddr_iter->ifa_addr != nullptr)
741 : {
742 32 : if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) &&
743 8 : ((mPlatformInterface == 0) || (mPlatformInterface == if_nametoindex(ifaddr_iter->ifa_name))))
744 : {
745 5 : struct in6_addr * sin6_addr = &(reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr;
746 5 : if ((sin6_addr->s6_addr[0] == 0xfe) && ((sin6_addr->s6_addr[1] & 0xc0) == 0x80)) // Link Local Address
747 : {
748 3 : (*llAddr) = IPAddress((reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr);
749 3 : found = true;
750 3 : break;
751 : }
752 : }
753 : }
754 : }
755 4 : freeifaddrs(ifaddr);
756 :
757 4 : return (found) ? CHIP_NO_ERROR : INET_ERROR_ADDRESS_NOT_FOUND;
758 : }
759 :
760 : #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
761 :
762 : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
763 :
764 : CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
765 : {
766 : if (mPlatformInterface)
767 : {
768 : net_if * currentInterface = net_if_get_by_index(mPlatformInterface);
769 : if (!currentInterface)
770 : {
771 : return CHIP_ERROR_INCORRECT_STATE;
772 : }
773 : const char * name = net_if_get_device(currentInterface)->name;
774 : size_t nameLength = strlen(name);
775 : if (nameLength >= nameBufSize)
776 : {
777 : return CHIP_ERROR_BUFFER_TOO_SMALL;
778 : }
779 : Platform::CopyString(nameBuf, nameBufSize, name);
780 : return CHIP_NO_ERROR;
781 : }
782 : if (nameBufSize < 1)
783 : {
784 : return CHIP_ERROR_BUFFER_TOO_SMALL;
785 : }
786 : nameBuf[0] = 0;
787 : return CHIP_NO_ERROR;
788 : }
789 :
790 : CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
791 : {
792 : int currentId = 0;
793 : net_if * currentInterface;
794 :
795 : while ((currentInterface = net_if_get_by_index(++currentId)) != nullptr)
796 : {
797 : if (strcmp(net_if_get_device(currentInterface)->name, intfName) == 0)
798 : {
799 : interface = InterfaceId(currentId);
800 : return CHIP_NO_ERROR;
801 : }
802 : }
803 : interface = InterfaceId::Null();
804 : return INET_ERROR_UNKNOWN_INTERFACE;
805 : }
806 :
807 : InterfaceIterator::InterfaceIterator() : mCurrentInterface(net_if_get_by_index(mCurrentId)) {}
808 :
809 : bool InterfaceIterator::HasCurrent(void)
810 : {
811 : return mCurrentInterface != nullptr;
812 : }
813 :
814 : bool InterfaceIterator::Next()
815 : {
816 : mCurrentInterface = net_if_get_by_index(++mCurrentId);
817 : return HasCurrent();
818 : }
819 :
820 : InterfaceId InterfaceIterator::GetInterfaceId(void)
821 : {
822 : return HasCurrent() ? InterfaceId(mCurrentId) : InterfaceId::Null();
823 : }
824 :
825 : CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
826 : {
827 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
828 : return InterfaceId(mCurrentId).GetInterfaceName(nameBuf, nameBufSize);
829 : }
830 :
831 : bool InterfaceIterator::IsUp()
832 : {
833 : return HasCurrent() && net_if_is_up(mCurrentInterface);
834 : }
835 :
836 : bool InterfaceIterator::SupportsMulticast()
837 : {
838 : return HasCurrent() && NET_IF_MAX_IPV6_MADDR > 0;
839 : }
840 :
841 : bool InterfaceIterator::HasBroadcastAddress()
842 : {
843 : // Zephyr seems to handle broadcast address for IPv4 implicitly
844 : return HasCurrent() && INET_CONFIG_ENABLE_IPV4;
845 : }
846 :
847 : CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
848 : {
849 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
850 :
851 : const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface);
852 : if (!linkAddr)
853 : return CHIP_ERROR_INCORRECT_STATE;
854 :
855 : // Do not consider other than WiFi and Thread for now.
856 : if (linkAddr->type == NET_LINK_IEEE802154)
857 : {
858 : type = InterfaceType::Thread;
859 : }
860 : // Zephyr doesn't define WiFi address type, so it shares the same type as Ethernet.
861 : else if (linkAddr->type == NET_LINK_ETHERNET)
862 : {
863 : type = InterfaceType::WiFi;
864 : }
865 : else
866 : {
867 : type = InterfaceType::Unknown;
868 : }
869 :
870 : return CHIP_NO_ERROR;
871 : }
872 :
873 : CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
874 : {
875 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
876 :
877 : if (!addressBuffer)
878 : return CHIP_ERROR_INVALID_ARGUMENT;
879 :
880 : const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface);
881 : if (!linkAddr)
882 : return CHIP_ERROR_INCORRECT_STATE;
883 :
884 : if (linkAddr->len > addressBufferSize)
885 : return CHIP_ERROR_BUFFER_TOO_SMALL;
886 :
887 : addressSize = linkAddr->len;
888 : memcpy(addressBuffer, linkAddr->addr, linkAddr->len);
889 :
890 : return CHIP_NO_ERROR;
891 : }
892 :
893 : InterfaceAddressIterator::InterfaceAddressIterator() = default;
894 :
895 : bool InterfaceAddressIterator::HasCurrent()
896 : {
897 : return mIntfIter.HasCurrent() && (mCurAddrIndex >= 0 || Next());
898 : }
899 :
900 : bool InterfaceAddressIterator::Next()
901 : {
902 : while (mIntfIter.HasCurrent())
903 : {
904 : if (mCurAddrIndex == -1) // first address for the current interface
905 : {
906 : const net_if_config * config =
907 : net_if_get_config(net_if_get_by_index(mIntfIter.GetInterfaceId().GetPlatformInterface()));
908 : mIpv6 = config->ip.ipv6;
909 : }
910 :
911 : while (++mCurAddrIndex < NET_IF_MAX_IPV6_ADDR)
912 : if (mIpv6->unicast[mCurAddrIndex].is_used)
913 : return true;
914 :
915 : mCurAddrIndex = -1;
916 : mIntfIter.Next();
917 : }
918 :
919 : return false;
920 : }
921 :
922 : CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress)
923 : {
924 : if (HasCurrent())
925 : {
926 : outIPAddress = IPAddress(mIpv6->unicast[mCurAddrIndex].address.in6_addr);
927 : return CHIP_NO_ERROR;
928 : }
929 : return CHIP_ERROR_SENTINEL;
930 : }
931 :
932 : uint8_t InterfaceAddressIterator::GetPrefixLength()
933 : {
934 : if (HasCurrent())
935 : {
936 : net_if * const iface = net_if_get_by_index(mIntfIter.GetInterfaceId().GetPlatformInterface());
937 : net_if_ipv6_prefix * const prefix = net_if_ipv6_prefix_get(iface, &mIpv6->unicast[mCurAddrIndex].address.in6_addr);
938 : return prefix ? prefix->len : 128;
939 : }
940 : return 0;
941 : }
942 :
943 : InterfaceId InterfaceAddressIterator::GetInterfaceId()
944 : {
945 : return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null();
946 : }
947 :
948 : CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
949 : {
950 : VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
951 : return mIntfIter.GetInterfaceName(nameBuf, nameBufSize);
952 : }
953 :
954 : bool InterfaceAddressIterator::IsUp()
955 : {
956 : return HasCurrent() && mIntfIter.IsUp();
957 : }
958 :
959 : bool InterfaceAddressIterator::SupportsMulticast()
960 : {
961 : return HasCurrent() && mIntfIter.SupportsMulticast();
962 : }
963 :
964 : bool InterfaceAddressIterator::HasBroadcastAddress()
965 : {
966 : return HasCurrent() && mIntfIter.HasBroadcastAddress();
967 : }
968 :
969 : CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const
970 : {
971 : VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
972 :
973 : net_if * const iface = mPlatformInterface ? net_if_get_by_index(mPlatformInterface) : net_if_get_default();
974 : VerifyOrReturnError(iface != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);
975 :
976 : in6_addr * const ip6_addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED);
977 : VerifyOrReturnError(ip6_addr != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);
978 :
979 : *llAddr = IPAddress(*ip6_addr);
980 :
981 : return CHIP_NO_ERROR;
982 : }
983 :
984 : #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
985 :
986 : // static
987 2 : InterfaceId InterfaceId::FromIPAddress(const IPAddress & addr)
988 : {
989 2 : InterfaceAddressIterator addrIter;
990 :
991 9 : for (; addrIter.HasCurrent(); addrIter.Next())
992 : {
993 : IPAddress curAddr;
994 8 : if ((addrIter.GetAddress(curAddr) == CHIP_NO_ERROR) && (addr == curAddr))
995 : {
996 1 : return addrIter.GetInterfaceId();
997 : }
998 : }
999 :
1000 1 : return InterfaceId::Null();
1001 2 : }
1002 :
1003 : // static
1004 100 : bool InterfaceId::MatchLocalIPv6Subnet(const IPAddress & addr)
1005 : {
1006 100 : if (addr.IsIPv6LinkLocal())
1007 1 : return true;
1008 :
1009 99 : InterfaceAddressIterator ifAddrIter;
1010 495 : for (; ifAddrIter.HasCurrent(); ifAddrIter.Next())
1011 : {
1012 : IPPrefix addrPrefix;
1013 396 : if (ifAddrIter.GetAddress(addrPrefix.IPAddr) != CHIP_NO_ERROR)
1014 297 : continue;
1015 : #if INET_CONFIG_ENABLE_IPV4
1016 396 : if (addrPrefix.IPAddr.IsIPv4())
1017 198 : continue;
1018 : #endif // INET_CONFIG_ENABLE_IPV4
1019 198 : if (addrPrefix.IPAddr.IsIPv6LinkLocal())
1020 99 : continue;
1021 99 : addrPrefix.Length = ifAddrIter.GetPrefixLength();
1022 99 : if (addrPrefix.MatchAddress(addr))
1023 0 : return true;
1024 : }
1025 :
1026 99 : return false;
1027 99 : }
1028 :
1029 103 : uint8_t NetmaskToPrefixLength(const uint8_t * netmask, uint16_t netmaskLen)
1030 : {
1031 103 : uint8_t prefixLen = 0;
1032 :
1033 1716 : for (uint16_t i = 0; i < netmaskLen; i++, prefixLen = static_cast<uint8_t>(prefixLen + 8u))
1034 : {
1035 1615 : uint8_t b = netmask[i];
1036 1615 : if (b != 0xFF)
1037 : {
1038 2 : if ((b & 0xF0) == 0xF0)
1039 0 : prefixLen = static_cast<uint8_t>(prefixLen + 4u);
1040 : else
1041 2 : b = static_cast<uint8_t>(b >> 4);
1042 :
1043 2 : if ((b & 0x0C) == 0x0C)
1044 0 : prefixLen = static_cast<uint8_t>(prefixLen + 2u);
1045 : else
1046 2 : b = static_cast<uint8_t>(b >> 2);
1047 :
1048 2 : if ((b & 0x02) == 0x02)
1049 0 : prefixLen++;
1050 :
1051 2 : break;
1052 : }
1053 : }
1054 :
1055 103 : return prefixLen;
1056 : }
1057 :
1058 : } // namespace Inet
1059 : } // namespace chip
|