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