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