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