1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for IPv6 network interfaces. 32 */ 33 34 #ifndef NET_NETIF_HPP_ 35 #define NET_NETIF_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/clearable.hpp" 40 #include "common/code_utils.hpp" 41 #include "common/iterator_utils.hpp" 42 #include "common/linked_list.hpp" 43 #include "common/locator.hpp" 44 #include "common/message.hpp" 45 #include "common/non_copyable.hpp" 46 #include "common/tasklet.hpp" 47 #include "mac/mac_types.hpp" 48 #include "net/ip6_address.hpp" 49 #include "net/socket.hpp" 50 #include "thread/mlr_types.hpp" 51 52 namespace ot { 53 namespace Ip6 { 54 55 class Ip6; 56 57 /** 58 * @addtogroup core-ip6-netif 59 * 60 * @brief 61 * This module includes definitions for IPv6 network interfaces. 62 * 63 * @{ 64 * 65 */ 66 67 /** 68 * This class implements an IPv6 network interface. 69 * 70 */ 71 class Netif : public InstanceLocator, private NonCopyable 72 { 73 friend class Ip6; 74 friend class Address; 75 76 public: 77 /** 78 * This class implements an IPv6 network interface unicast address. 79 * 80 */ 81 class UnicastAddress : public otNetifAddress, 82 public LinkedListEntry<UnicastAddress>, 83 public Clearable<UnicastAddress> 84 { 85 friend class LinkedList<UnicastAddress>; 86 87 public: 88 /** 89 * This method clears and initializes the unicast address as a preferred, valid, thread-origin address with 90 * 64-bit prefix length. 91 * 92 * @param[in] aPreferred Whether to initialize as a preferred address. 93 * 94 */ 95 void InitAsThreadOrigin(bool aPreferred = false); 96 97 /** 98 * This method clears and initializes the unicast address as a valid (but not preferred), thread-origin, 99 * realm-local scope (overridden) address with 64-bit prefix length. 100 * 101 */ 102 void InitAsThreadOriginRealmLocalScope(void); 103 104 /** 105 * This method clears and initializes the unicast address as a valid (but not preferred), thread-origin, global 106 * scope address. 107 * 108 */ 109 void InitAsThreadOriginGlobalScope(void); 110 111 /** 112 * This method clears and initializes the unicast address as a valid, SLAAC-origin address with a given 113 * preferred flag and a given prefix length. 114 * 115 * @param[in] aPrefixLength The prefix length (in bits). 116 * @param[in] aPreferred The preferred flag. 117 * 118 */ 119 void InitAsSlaacOrigin(uint8_t aPrefixLength, bool aPreferred); 120 121 /** 122 * This method returns the unicast address. 123 * 124 * @returns The unicast address. 125 * 126 */ GetAddress(void) const127 const Address &GetAddress(void) const { return static_cast<const Address &>(mAddress); } 128 129 /** 130 * This method returns the unicast address. 131 * 132 * @returns The unicast address. 133 * 134 */ GetAddress(void)135 Address &GetAddress(void) { return static_cast<Address &>(mAddress); } 136 137 /** 138 * This method returns the address's prefix length (in bits). 139 * 140 * @returns The prefix length (in bits). 141 * 142 */ GetPrefixLength(void) const143 uint8_t GetPrefixLength(void) const { return mPrefixLength; } 144 145 /** 146 * This method indicates whether the address has a given prefix (i.e. same prefix length and matches the 147 * prefix). 148 * 149 * @param[in] aPrefix A prefix to check against. 150 * 151 * @retval TRUE The address has and fully matches the @p aPrefix. 152 * @retval FALSE The address does not contain or match the @p aPrefix. 153 * 154 */ HasPrefix(const Prefix & aPrefix) const155 bool HasPrefix(const Prefix &aPrefix) const 156 { 157 return (mPrefixLength == aPrefix.GetLength()) && GetAddress().MatchesPrefix(aPrefix); 158 } 159 160 /** 161 * This method returns the IPv6 scope value. 162 * 163 * @returns The IPv6 scope value. 164 * 165 */ GetScope(void) const166 uint8_t GetScope(void) const 167 { 168 return mScopeOverrideValid ? static_cast<uint8_t>(mScopeOverride) : GetAddress().GetScope(); 169 } 170 171 /** 172 * This method sets the IPv6 scope override value. 173 * 174 * @param[in] aScope The IPv6 scope value. 175 * 176 */ SetScopeOverride(uint8_t aScope)177 void SetScopeOverride(uint8_t aScope) 178 { 179 mScopeOverride = aScope; 180 mScopeOverrideValid = true; 181 } 182 183 private: Matches(const Address & aAddress) const184 bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; } 185 }; 186 187 /** 188 * This class implements an IPv6 network interface multicast address. 189 * 190 */ 191 class MulticastAddress : public otNetifMulticastAddress, 192 public LinkedListEntry<MulticastAddress>, 193 public Clearable<MulticastAddress> 194 { 195 friend class LinkedList<MulticastAddress>; 196 197 public: 198 /** 199 * This method returns the multicast address. 200 * 201 * @returns The multicast address. 202 * 203 */ GetAddress(void) const204 const Address &GetAddress(void) const { return static_cast<const Address &>(mAddress); } 205 206 /** 207 * This method returns the multicast address. 208 * 209 * @returns The multicast address. 210 * 211 */ GetAddress(void)212 Address &GetAddress(void) { return static_cast<Address &>(mAddress); } 213 214 /** 215 * This method returns the next multicast address subscribed to the interface. 216 * 217 * @returns A pointer to the next multicast address. 218 * 219 */ GetNext(void) const220 const MulticastAddress *GetNext(void) const { return static_cast<const MulticastAddress *>(mNext); } 221 222 /** 223 * This method returns the next multicast address subscribed to the interface. 224 * 225 * @returns A pointer to the next multicast address. 226 * 227 */ GetNext(void)228 MulticastAddress *GetNext(void) 229 { 230 return static_cast<MulticastAddress *>(const_cast<otNetifMulticastAddress *>(mNext)); 231 } 232 233 private: Matches(const Address & aAddress) const234 bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; } 235 }; 236 237 class ExternalMulticastAddress : public MulticastAddress 238 { 239 friend class Netif; 240 friend class LinkedList<ExternalMulticastAddress>; 241 242 public: 243 /** 244 * This class represents an iterator for iterating external multicast addresses in a `Netif` instance. 245 * 246 */ 247 class Iterator : public ItemPtrIterator<ExternalMulticastAddress, Iterator> 248 { 249 friend class ItemPtrIterator<ExternalMulticastAddress, Iterator>; 250 friend class Netif; 251 252 public: 253 /** 254 * This constructor initializes an `Iterator` instance to start from the first external multicast address 255 * that matches a given IPv6 address type filter. 256 * 257 * @param[in] aNetif A reference to the `Netif` instance. 258 * @param[in] aFilter The IPv6 address type filter. 259 * 260 */ 261 explicit Iterator(const Netif &aNetif, Address::TypeFilter aFilter = Address::kTypeAny); 262 263 private: 264 class Builder 265 { 266 public: Builder(const Netif & aNetif,Address::TypeFilter aFilter)267 Builder(const Netif &aNetif, Address::TypeFilter aFilter) 268 : mNetif(aNetif) 269 , mFilter(aFilter) 270 { 271 } 272 begin(void)273 Iterator begin(void) { return Iterator(mNetif, mFilter); } end(void)274 Iterator end(void) { return Iterator(mNetif, Iterator::kEndIterator); } 275 276 private: 277 const Netif & mNetif; 278 Address::TypeFilter mFilter; 279 }; 280 281 enum IteratorType : uint8_t 282 { 283 kEndIterator, 284 }; 285 Iterator(const Netif & aNetif,IteratorType)286 Iterator(const Netif &aNetif, IteratorType) 287 : mNetif(aNetif) 288 { 289 } 290 291 void AdvanceFrom(const MulticastAddress *aAddr); Advance(void)292 void Advance(void) { AdvanceFrom(mItem->GetNext()); } 293 294 const Netif & mNetif; 295 Address::TypeFilter mFilter; 296 }; 297 298 #if OPENTHREAD_CONFIG_MLR_ENABLE 299 /** 300 * This method returns the current Multicast Listener Registration (MLR) state. 301 * 302 * @returns The current Multicast Listener Registration state. 303 * 304 */ GetMlrState(void) const305 MlrState GetMlrState(void) const { return mMlrState; } 306 307 /** 308 * This method sets the Multicast Listener Registration (MLR) state. 309 * 310 * @param[in] aState The new Multicast Listener Registration state. 311 * 312 */ SetMlrState(MlrState aState)313 void SetMlrState(MlrState aState) { mMlrState = aState; } 314 #endif 315 316 private: GetNext(void)317 ExternalMulticastAddress *GetNext(void) 318 { 319 return static_cast<ExternalMulticastAddress *>(const_cast<otNetifMulticastAddress *>(mNext)); 320 } 321 322 #if OPENTHREAD_CONFIG_MLR_ENABLE 323 MlrState mMlrState; 324 #endif 325 }; 326 327 /** 328 * This constructor initializes the network interface. 329 * 330 * @param[in] aInstance A reference to the OpenThread instance. 331 * 332 */ 333 explicit Netif(Instance &aInstance); 334 335 /** 336 * This method registers a callback to notify internal IPv6 address changes. 337 * 338 * @param[in] aCallback A pointer to a function that is called when an IPv6 address is added or removed. 339 * @param[in] aCallbackContext A pointer to application-specific context. 340 * 341 */ 342 void SetAddressCallback(otIp6AddressCallback aCallback, void *aCallbackContext); 343 344 /** 345 * This method returns the linked list of unicast addresses. 346 * 347 * @returns The linked list of unicast addresses. 348 * 349 */ GetUnicastAddresses(void) const350 const LinkedList<UnicastAddress> &GetUnicastAddresses(void) const { return mUnicastAddresses; } 351 352 /** 353 * This method adds a unicast address to the network interface. 354 * 355 * This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly added in the 356 * unicast address linked list. 357 * 358 * If @p aAddress is already added, the call to `AddUnicastAddress()` with the same address will perform no action. 359 * 360 * @param[in] aAddress A reference to the unicast address. 361 * 362 */ 363 void AddUnicastAddress(UnicastAddress &aAddress); 364 365 /** 366 * This method removes a unicast address from the network interface. 367 * 368 * This method is intended for addresses internal to OpenThread. The @p aAddress instance is removed from the 369 * unicast address linked list. 370 * 371 * If @p aAddress is not in the list, the call to `RemoveUnicastAddress()` will perform no action. 372 * 373 * @param[in] aAddress A reference to the unicast address. 374 * 375 */ 376 void RemoveUnicastAddress(const UnicastAddress &aAddress); 377 378 /** 379 * This method indicates whether or not an address is assigned to the interface. 380 * 381 * @param[in] aAddress A reference to the unicast address. 382 * 383 * @retval TRUE If @p aAddress is assigned to the network interface, 384 * @retval FALSE If @p aAddress is not assigned to the network interface. 385 * 386 */ 387 bool HasUnicastAddress(const Address &aAddress) const; 388 389 /** 390 * This method indicates whether or not a unicast address is assigned to the network interface. 391 * 392 * @param[in] aAddress A reference to the unicast address. 393 * 394 * @retval TRUE If @p aAddress is assigned to the network interface, 395 * @retval FALSE If @p aAddress is not assigned to the network interface. 396 * 397 */ HasUnicastAddress(const UnicastAddress & aAddress) const398 bool HasUnicastAddress(const UnicastAddress &aAddress) const { return mUnicastAddresses.Contains(aAddress); } 399 400 /** 401 * This method indicates whether a unicast address is an external or internal address. 402 * 403 * @param[in] aAddress A reference to the unicast address. 404 * 405 * @retval TRUE The address is an external address. 406 * @retval FALSE The address is not an external address (it is an OpenThread internal address). 407 * 408 */ 409 bool IsUnicastAddressExternal(const UnicastAddress &aAddress) const; 410 411 /** 412 * This method adds an external (to OpenThread) unicast address to the network interface. 413 * 414 * For external address, the @p aAddress instance is not directly used (i.e., it can be temporary). It is copied 415 * into a local entry (allocated from an internal pool) before being added in the unicast address linked list. 416 * The maximum number of external addresses is specified by `OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS`. 417 * 418 * @param[in] aAddress A reference to the unicast address. 419 * 420 * @retval kErrorNone Successfully added (or updated) the unicast address. 421 * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address. 422 * @retval kErrorNoBufs The maximum number of allowed external addresses are already added. 423 * 424 */ 425 Error AddExternalUnicastAddress(const UnicastAddress &aAddress); 426 427 /** 428 * This method removes a external (to OpenThread) unicast address from the network interface. 429 * 430 * @param[in] aAddress A reference to the unicast address. 431 * 432 * @retval kErrorNone Successfully removed the unicast address. 433 * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address. 434 * @retval kErrorNotFound The unicast address was not found. 435 * 436 */ 437 Error RemoveExternalUnicastAddress(const Address &aAddress); 438 439 /** 440 * This method removes all the previously added external (to OpenThread) unicast addresses from the 441 * network interface. 442 * 443 */ 444 void RemoveAllExternalUnicastAddresses(void); 445 446 /** 447 * This method indicates whether or not the network interface is subscribed to a multicast address. 448 * 449 * @param[in] aAddress The multicast address to check. 450 * 451 * @retval TRUE If the network interface is subscribed to @p aAddress. 452 * @retval FALSE If the network interface is not subscribed to @p aAddress. 453 * 454 */ 455 bool IsMulticastSubscribed(const Address &aAddress) const; 456 457 /** 458 * This method subscribes the network interface to the link-local and realm-local all routers addresses. 459 * 460 * @note This method MUST be called after `SubscribeAllNodesMulticast()` or its behavior is undefined. 461 * 462 */ 463 void SubscribeAllRoutersMulticast(void); 464 465 /** 466 * This method unsubscribes the network interface to the link-local and realm-local all routers address. 467 * 468 */ 469 void UnsubscribeAllRoutersMulticast(void); 470 471 /** 472 * This method returns the linked list of multicast addresses. 473 * 474 * @returns The linked list of multicast addresses. 475 * 476 */ GetMulticastAddresses(void) const477 const LinkedList<MulticastAddress> &GetMulticastAddresses(void) const { return mMulticastAddresses; } 478 479 /** 480 * This method indicates whether a multicast address is an external or internal address. 481 * 482 * @param[in] aAddress A reference to the multicast address. 483 * 484 * @retval TRUE The address is an external address. 485 * @retval FALSE The address is not an external address (it is an OpenThread internal address). 486 * 487 */ 488 bool IsMulticastAddressExternal(const MulticastAddress &aAddress) const; 489 490 /** 491 * This method subscribes the network interface to a multicast address. 492 * 493 * This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly added in the 494 * multicast address linked list. 495 * 496 * @param[in] aAddress A reference to the multicast address. 497 * 498 */ 499 void SubscribeMulticast(MulticastAddress &aAddress); 500 501 /** 502 * This method unsubscribes the network interface to a multicast address. 503 * 504 * This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly removed from 505 * the multicast address linked list. 506 * 507 * @param[in] aAddress A reference to the multicast address. 508 * 509 */ 510 void UnsubscribeMulticast(const MulticastAddress &aAddress); 511 512 /** 513 * This method subscribes the network interface to the external (to OpenThread) multicast address. 514 * 515 * For external address, the @p aAddress instance is not directly used (i.e., it can be temporary). It is copied 516 * into a local entry (allocated from an internal pool) before being added in the multicast address linked list. 517 * The maximum number of external addresses is specified by `OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS`. 518 * 519 * @param[in] aAddress A reference to the multicast address. 520 * 521 * @retval kErrorNone Successfully subscribed to @p aAddress. 522 * @retval kErrorAlready The multicast address is already subscribed. 523 * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal multicast address. 524 * @retval kErrorNoBufs The maximum number of allowed external multicast addresses are already added. 525 * 526 */ 527 Error SubscribeExternalMulticast(const Address &aAddress); 528 529 /** 530 * This method unsubscribes the network interface to the external (to OpenThread) multicast address. 531 * 532 * @param[in] aAddress A reference to the multicast address. 533 * 534 * @retval kErrorNone Successfully unsubscribed to the unicast address. 535 * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address. 536 * @retval kErrorNotFound The multicast address was not found. 537 * 538 */ 539 Error UnsubscribeExternalMulticast(const Address &aAddress); 540 541 /** 542 * This method unsubscribes the network interface from all previously added external (to OpenThread) multicast 543 * addresses. 544 * 545 */ 546 void UnsubscribeAllExternalMulticastAddresses(void); 547 548 /** 549 * This method checks if multicast promiscuous mode is enabled on the network interface. 550 * 551 * @retval TRUE If the multicast promiscuous mode is enabled. 552 * @retval FALSE If the multicast promiscuous mode is disabled. 553 * 554 */ IsMulticastPromiscuousEnabled(void) const555 bool IsMulticastPromiscuousEnabled(void) const { return mMulticastPromiscuous; } 556 557 /** 558 * This method enables multicast promiscuous mode on the network interface. 559 * 560 * @param[in] aEnabled TRUE if Multicast Promiscuous mode is enabled, FALSE otherwise. 561 * 562 */ SetMulticastPromiscuous(bool aEnabled)563 void SetMulticastPromiscuous(bool aEnabled) { mMulticastPromiscuous = aEnabled; } 564 565 /** 566 * This method enables range-based `for` loop iteration over external multicast addresses on the Netif that matches 567 * a given IPv6 address type filter. 568 * 569 * This method should be used like follows: to iterate over all external multicast addresses 570 * 571 * for (Ip6::Netif::ExternalMulticastAddress &addr : Get<ThreadNetif>().IterateExternalMulticastAddresses()) 572 * { ... } 573 * 574 * or to iterate over a subset of external multicast addresses determined by a given address type filter 575 * 576 * for (Ip6::Netif::ExternalMulticastAddress &addr : 577 * Get<ThreadNetif>().IterateExternalMulticastAddresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal)) 578 * { ... } 579 * 580 * @param[in] aFilter The IPv6 address type filter. 581 * 582 * @returns An `ExternalMulticastAddress::Iterator::Builder` instance. 583 * 584 */ IterateExternalMulticastAddresses(Address::TypeFilter aFilter=Address::kTypeAny)585 ExternalMulticastAddress::Iterator::Builder IterateExternalMulticastAddresses( 586 Address::TypeFilter aFilter = Address::kTypeAny) 587 { 588 return ExternalMulticastAddress::Iterator::Builder(*this, aFilter); 589 } 590 591 /** 592 * This method indicates whether or not the network interfaces is subscribed to any external multicast address. 593 * 594 * @retval TRUE The network interface is subscribed to at least one external multicast address. 595 * @retval FALSE The network interface is not subscribed to any external multicast address. 596 * 597 */ HasAnyExternalMulticastAddress(void) const598 bool HasAnyExternalMulticastAddress(void) const { return !ExternalMulticastAddress::Iterator(*this).IsDone(); } 599 600 protected: 601 /** 602 * This method subscribes the network interface to the realm-local all MPL forwarders, link-local, and realm-local 603 * all nodes address. 604 * 605 */ 606 void SubscribeAllNodesMulticast(void); 607 608 /** 609 * This method unsubscribes the network interface from the realm-local all MPL forwarders, link-local and 610 * realm-local all nodes address. 611 * 612 * @note This method MUST be called after `UnsubscribeAllRoutersMulticast()` or its behavior is undefined 613 * 614 */ 615 void UnsubscribeAllNodesMulticast(void); 616 617 private: 618 LinkedList<UnicastAddress> mUnicastAddresses; 619 LinkedList<MulticastAddress> mMulticastAddresses; 620 bool mMulticastPromiscuous; 621 622 otIp6AddressCallback mAddressCallback; 623 void * mAddressCallbackContext; 624 625 Pool<UnicastAddress, OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS> mExtUnicastAddressPool; 626 Pool<ExternalMulticastAddress, OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS> mExtMulticastAddressPool; 627 628 static const otNetifMulticastAddress kRealmLocalAllMplForwardersMulticastAddress; 629 static const otNetifMulticastAddress kLinkLocalAllNodesMulticastAddress; 630 static const otNetifMulticastAddress kRealmLocalAllNodesMulticastAddress; 631 static const otNetifMulticastAddress kLinkLocalAllRoutersMulticastAddress; 632 static const otNetifMulticastAddress kRealmLocalAllRoutersMulticastAddress; 633 }; 634 635 /** 636 * @} 637 * 638 */ 639 640 } // namespace Ip6 641 } // namespace ot 642 643 #endif // NET_NETIF_HPP_ 644