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/as_core_type.hpp" 40 #include "common/callback.hpp" 41 #include "common/clearable.hpp" 42 #include "common/code_utils.hpp" 43 #include "common/const_cast.hpp" 44 #include "common/iterator_utils.hpp" 45 #include "common/linked_list.hpp" 46 #include "common/locator.hpp" 47 #include "common/message.hpp" 48 #include "common/non_copyable.hpp" 49 #include "common/tasklet.hpp" 50 #include "mac/mac_types.hpp" 51 #include "net/ip6_address.hpp" 52 #include "net/socket.hpp" 53 #include "thread/mlr_types.hpp" 54 55 namespace ot { 56 namespace Ip6 { 57 58 class Ip6; 59 60 /** 61 * @addtogroup core-ip6-netif 62 * 63 * @brief 64 * This module includes definitions for IPv6 network interfaces. 65 * 66 * @{ 67 * 68 */ 69 70 /** 71 * This class implements an IPv6 network interface. 72 * 73 */ 74 class Netif : public InstanceLocator, private NonCopyable 75 { 76 friend class Ip6; 77 friend class Address; 78 79 public: 80 /** 81 * This enumeration represent an address event (added or removed) 82 * 83 * The boolean values are used for `aIsAdded` parameter in the call of `otIp6AddressCallback`. 84 * 85 */ 86 enum AddressEvent : bool 87 { 88 kAddressRemoved = false, ///< Indicates that address was added. 89 kAddressAdded = true, ///< Indicates that address was removed. 90 }; 91 92 /** 93 * This enumeration represents the address origin. 94 * 95 */ 96 enum AddressOrigin : uint8_t 97 { 98 kOriginThread = OT_ADDRESS_ORIGIN_THREAD, ///< Thread assigned address (ALOC, RLOC, MLEID, etc) 99 kOriginSlaac = OT_ADDRESS_ORIGIN_SLAAC, ///< SLAAC assigned address 100 kOriginDhcp6 = OT_ADDRESS_ORIGIN_DHCPV6, ///< DHCPv6 assigned address 101 kOriginManual = OT_ADDRESS_ORIGIN_MANUAL, ///< Manually assigned address 102 }; 103 104 /** 105 * This class implements an IPv6 network interface unicast address. 106 * 107 */ 108 class UnicastAddress : public otNetifAddress, 109 public LinkedListEntry<UnicastAddress>, 110 public Clearable<UnicastAddress> 111 { 112 friend class LinkedList<UnicastAddress>; 113 114 public: 115 /** 116 * This method clears and initializes the unicast address as a preferred, valid, thread-origin address with 117 * 64-bit prefix length. 118 * 119 * @param[in] aPreferred Whether to initialize as a preferred address. 120 * 121 */ 122 void InitAsThreadOrigin(bool aPreferred = false); 123 124 /** 125 * This method clears and initializes the unicast address as a valid (but not preferred), thread-origin, 126 * realm-local scope (overridden) address with 64-bit prefix length. 127 * 128 */ 129 void InitAsThreadOriginRealmLocalScope(void); 130 131 /** 132 * This method clears and initializes the unicast address as a valid (but not preferred), thread-origin, global 133 * scope address. 134 * 135 */ 136 void InitAsThreadOriginGlobalScope(void); 137 138 /** 139 * This method clears and initializes the unicast address as a valid, SLAAC-origin address with a given 140 * preferred flag and a given prefix length. 141 * 142 * @param[in] aPrefixLength The prefix length (in bits). 143 * @param[in] aPreferred The preferred flag. 144 * 145 */ 146 void InitAsSlaacOrigin(uint8_t aPrefixLength, bool aPreferred); 147 148 /** 149 * This method returns the unicast address. 150 * 151 * @returns The unicast address. 152 * 153 */ GetAddress(void) const154 const Address &GetAddress(void) const { return AsCoreType(&mAddress); } 155 156 /** 157 * This method returns the unicast address. 158 * 159 * @returns The unicast address. 160 * 161 */ GetAddress(void)162 Address &GetAddress(void) { return AsCoreType(&mAddress); } 163 164 /** 165 * This method returns the address's prefix length (in bits). 166 * 167 * @returns The prefix length (in bits). 168 * 169 */ GetPrefixLength(void) const170 uint8_t GetPrefixLength(void) const { return mPrefixLength; } 171 172 /** 173 * This method indicates whether the address has a given prefix (i.e. same prefix length and matches the 174 * prefix). 175 * 176 * @param[in] aPrefix A prefix to check against. 177 * 178 * @retval TRUE The address has and fully matches the @p aPrefix. 179 * @retval FALSE The address does not contain or match the @p aPrefix. 180 * 181 */ HasPrefix(const Prefix & aPrefix) const182 bool HasPrefix(const Prefix &aPrefix) const 183 { 184 return (mPrefixLength == aPrefix.GetLength()) && GetAddress().MatchesPrefix(aPrefix); 185 } 186 187 /** 188 * This method returns the IPv6 scope value. 189 * 190 * @returns The IPv6 scope value. 191 * 192 */ GetScope(void) const193 uint8_t GetScope(void) const 194 { 195 return mScopeOverrideValid ? static_cast<uint8_t>(mScopeOverride) : GetAddress().GetScope(); 196 } 197 198 /** 199 * This method sets the IPv6 scope override value. 200 * 201 * @param[in] aScope The IPv6 scope value. 202 * 203 */ SetScopeOverride(uint8_t aScope)204 void SetScopeOverride(uint8_t aScope) 205 { 206 mScopeOverride = aScope; 207 mScopeOverrideValid = true; 208 } 209 210 /** 211 * This method gets the IPv6 address origin. 212 * 213 * @returns The address origin. 214 * 215 */ GetOrigin(void) const216 AddressOrigin GetOrigin(void) const { return static_cast<AddressOrigin>(mAddressOrigin); } 217 218 private: Matches(const Address & aAddress) const219 bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; } 220 }; 221 222 /** 223 * This class implements an IPv6 network interface multicast address. 224 * 225 */ 226 class MulticastAddress : public otNetifMulticastAddress, 227 public LinkedListEntry<MulticastAddress>, 228 public Clearable<MulticastAddress> 229 { 230 friend class LinkedList<MulticastAddress>; 231 232 public: 233 /** 234 * This method returns the multicast address. 235 * 236 * @returns The multicast address. 237 * 238 */ GetAddress(void) const239 const Address &GetAddress(void) const { return AsCoreType(&mAddress); } 240 241 /** 242 * This method returns the multicast address. 243 * 244 * @returns The multicast address. 245 * 246 */ GetAddress(void)247 Address &GetAddress(void) { return AsCoreType(&mAddress); } 248 249 /** 250 * This method returns the next multicast address subscribed to the interface. 251 * 252 * @returns A pointer to the next multicast address. 253 * 254 */ GetNext(void) const255 const MulticastAddress *GetNext(void) const { return static_cast<const MulticastAddress *>(mNext); } 256 257 /** 258 * This method returns the next multicast address subscribed to the interface. 259 * 260 * @returns A pointer to the next multicast address. 261 * 262 */ GetNext(void)263 MulticastAddress *GetNext(void) { return static_cast<MulticastAddress *>(AsNonConst(mNext)); } 264 265 private: Matches(const Address & aAddress) const266 bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; } 267 }; 268 269 class ExternalMulticastAddress : public MulticastAddress 270 { 271 friend class Netif; 272 friend class LinkedList<ExternalMulticastAddress>; 273 274 public: 275 /** 276 * This class represents an iterator for iterating external multicast addresses in a `Netif` instance. 277 * 278 */ 279 class Iterator : public ItemPtrIterator<ExternalMulticastAddress, Iterator> 280 { 281 friend class ItemPtrIterator<ExternalMulticastAddress, Iterator>; 282 friend class Netif; 283 284 public: 285 /** 286 * This constructor initializes an `Iterator` instance to start from the first external multicast address 287 * that matches a given IPv6 address type filter. 288 * 289 * @param[in] aNetif A reference to the `Netif` instance. 290 * @param[in] aFilter The IPv6 address type filter. 291 * 292 */ 293 explicit Iterator(const Netif &aNetif, Address::TypeFilter aFilter = Address::kTypeAny); 294 295 private: 296 class Builder 297 { 298 public: Builder(const Netif & aNetif,Address::TypeFilter aFilter)299 Builder(const Netif &aNetif, Address::TypeFilter aFilter) 300 : mNetif(aNetif) 301 , mFilter(aFilter) 302 { 303 } 304 begin(void)305 Iterator begin(void) { return Iterator(mNetif, mFilter); } end(void)306 Iterator end(void) { return Iterator(mNetif, Iterator::kEndIterator); } 307 308 private: 309 const Netif &mNetif; 310 Address::TypeFilter mFilter; 311 }; 312 313 enum IteratorType : uint8_t 314 { 315 kEndIterator, 316 }; 317 Iterator(const Netif & aNetif,IteratorType)318 Iterator(const Netif &aNetif, IteratorType) 319 : mNetif(aNetif) 320 { 321 } 322 323 void AdvanceFrom(const MulticastAddress *aAddr); Advance(void)324 void Advance(void) { AdvanceFrom(mItem->GetNext()); } 325 326 const Netif &mNetif; 327 Address::TypeFilter mFilter; 328 }; 329 330 #if OPENTHREAD_CONFIG_MLR_ENABLE 331 /** 332 * This method returns the current Multicast Listener Registration (MLR) state. 333 * 334 * @returns The current Multicast Listener Registration state. 335 * 336 */ GetMlrState(void) const337 MlrState GetMlrState(void) const { return mMlrState; } 338 339 /** 340 * This method sets the Multicast Listener Registration (MLR) state. 341 * 342 * @param[in] aState The new Multicast Listener Registration state. 343 * 344 */ SetMlrState(MlrState aState)345 void SetMlrState(MlrState aState) { mMlrState = aState; } 346 #endif 347 348 private: GetNext(void)349 ExternalMulticastAddress *GetNext(void) { return static_cast<ExternalMulticastAddress *>(AsNonConst(mNext)); } 350 351 #if OPENTHREAD_CONFIG_MLR_ENABLE 352 MlrState mMlrState; 353 #endif 354 }; 355 356 /** 357 * This constructor initializes the network interface. 358 * 359 * @param[in] aInstance A reference to the OpenThread instance. 360 * 361 */ 362 explicit Netif(Instance &aInstance); 363 364 /** 365 * This method registers a callback to notify internal IPv6 address changes. 366 * 367 * @param[in] aCallback A pointer to a function that is called when an IPv6 address is added or removed. 368 * @param[in] aCallbackContext A pointer to application-specific context. 369 * 370 */ SetAddressCallback(otIp6AddressCallback aCallback,void * aCallbackContext)371 void SetAddressCallback(otIp6AddressCallback aCallback, void *aCallbackContext) 372 { 373 mAddressCallback.Set(aCallback, aCallbackContext); 374 } 375 376 /** 377 * This method returns the linked list of unicast addresses. 378 * 379 * @returns The linked list of unicast addresses. 380 * 381 */ GetUnicastAddresses(void) const382 const LinkedList<UnicastAddress> &GetUnicastAddresses(void) const { return mUnicastAddresses; } 383 384 /** 385 * This method adds a unicast address to the network interface. 386 * 387 * This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly added in the 388 * unicast address linked list. 389 * 390 * If @p aAddress is already added, the call to `AddUnicastAddress()` with the same address will perform no action. 391 * 392 * @param[in] aAddress A reference to the unicast address. 393 * 394 */ 395 void AddUnicastAddress(UnicastAddress &aAddress); 396 397 /** 398 * This method removes a unicast address from the network interface. 399 * 400 * This method is intended for addresses internal to OpenThread. The @p aAddress instance is removed from the 401 * unicast address linked list. 402 * 403 * If @p aAddress is not in the list, the call to `RemoveUnicastAddress()` will perform no action. 404 * 405 * @param[in] aAddress A reference to the unicast address. 406 * 407 */ 408 void RemoveUnicastAddress(const UnicastAddress &aAddress); 409 410 /** 411 * This method indicates whether or not an address is assigned to the interface. 412 * 413 * @param[in] aAddress A reference to the unicast address. 414 * 415 * @retval TRUE If @p aAddress is assigned to the network interface, 416 * @retval FALSE If @p aAddress is not assigned to the network interface. 417 * 418 */ 419 bool HasUnicastAddress(const Address &aAddress) const; 420 421 /** 422 * This method indicates whether or not a unicast address is assigned to the network interface. 423 * 424 * @param[in] aAddress A reference to the unicast address. 425 * 426 * @retval TRUE If @p aAddress is assigned to the network interface, 427 * @retval FALSE If @p aAddress is not assigned to the network interface. 428 * 429 */ HasUnicastAddress(const UnicastAddress & aAddress) const430 bool HasUnicastAddress(const UnicastAddress &aAddress) const { return mUnicastAddresses.Contains(aAddress); } 431 432 /** 433 * This method indicates whether a unicast address is an external or internal address. 434 * 435 * @param[in] aAddress A reference to the unicast address. 436 * 437 * @retval TRUE The address is an external address. 438 * @retval FALSE The address is not an external address (it is an OpenThread internal address). 439 * 440 */ 441 bool IsUnicastAddressExternal(const UnicastAddress &aAddress) const; 442 443 /** 444 * This method adds an external (to OpenThread) unicast address to the network interface. 445 * 446 * For external address, the @p aAddress instance is not directly used (i.e., it can be temporary). It is copied 447 * into a local entry (allocated from an internal pool) before being added in the unicast address linked list. 448 * The maximum number of external addresses is specified by `OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS`. 449 * 450 * @param[in] aAddress A reference to the unicast address. 451 * 452 * @retval kErrorNone Successfully added (or updated) the unicast address. 453 * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address. 454 * @retval kErrorNoBufs The maximum number of allowed external addresses are already added. 455 * 456 */ 457 Error AddExternalUnicastAddress(const UnicastAddress &aAddress); 458 459 /** 460 * This method removes a external (to OpenThread) unicast address from the network interface. 461 * 462 * @param[in] aAddress A reference to the unicast address. 463 * 464 * @retval kErrorNone Successfully removed the unicast address. 465 * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address. 466 * @retval kErrorNotFound The unicast address was not found. 467 * 468 */ 469 Error RemoveExternalUnicastAddress(const Address &aAddress); 470 471 /** 472 * This method removes all the previously added external (to OpenThread) unicast addresses from the 473 * network interface. 474 * 475 */ 476 void RemoveAllExternalUnicastAddresses(void); 477 478 /** 479 * This method indicates whether or not the network interface is subscribed to a multicast address. 480 * 481 * @param[in] aAddress The multicast address to check. 482 * 483 * @retval TRUE If the network interface is subscribed to @p aAddress. 484 * @retval FALSE If the network interface is not subscribed to @p aAddress. 485 * 486 */ 487 bool IsMulticastSubscribed(const Address &aAddress) const; 488 489 /** 490 * This method subscribes the network interface to the link-local and realm-local all routers addresses. 491 * 492 * @note This method MUST be called after `SubscribeAllNodesMulticast()` or its behavior is undefined. 493 * 494 */ 495 void SubscribeAllRoutersMulticast(void); 496 497 /** 498 * This method unsubscribes the network interface to the link-local and realm-local all routers address. 499 * 500 */ 501 void UnsubscribeAllRoutersMulticast(void); 502 503 /** 504 * This method returns the linked list of multicast addresses. 505 * 506 * @returns The linked list of multicast addresses. 507 * 508 */ GetMulticastAddresses(void) const509 const LinkedList<MulticastAddress> &GetMulticastAddresses(void) const { return mMulticastAddresses; } 510 511 /** 512 * This method indicates whether a multicast address is an external or internal address. 513 * 514 * @param[in] aAddress A reference to the multicast address. 515 * 516 * @retval TRUE The address is an external address. 517 * @retval FALSE The address is not an external address (it is an OpenThread internal address). 518 * 519 */ 520 bool IsMulticastAddressExternal(const MulticastAddress &aAddress) const; 521 522 /** 523 * This method subscribes the network interface to a multicast address. 524 * 525 * This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly added in the 526 * multicast address linked list. 527 * 528 * @param[in] aAddress A reference to the multicast address. 529 * 530 */ 531 void SubscribeMulticast(MulticastAddress &aAddress); 532 533 /** 534 * This method unsubscribes the network interface to a multicast address. 535 * 536 * This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly removed from 537 * the multicast address linked list. 538 * 539 * @param[in] aAddress A reference to the multicast address. 540 * 541 */ 542 void UnsubscribeMulticast(const MulticastAddress &aAddress); 543 544 /** 545 * This method subscribes the network interface to the external (to OpenThread) multicast address. 546 * 547 * For external address, the @p aAddress instance is not directly used (i.e., it can be temporary). It is copied 548 * into a local entry (allocated from an internal pool) before being added in the multicast address linked list. 549 * The maximum number of external addresses is specified by `OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS`. 550 * 551 * @param[in] aAddress A reference to the multicast address. 552 * 553 * @retval kErrorNone Successfully subscribed to @p aAddress. 554 * @retval kErrorAlready The multicast address is already subscribed. 555 * @retval kErrorInvalidArgs The IP Address indicated by @p aAddress is an invalid multicast address. 556 * @retval kErrorRejected The IP Address indicated by @p aAddress is an internal multicast address. 557 * @retval kErrorNoBufs The maximum number of allowed external multicast addresses are already added. 558 * 559 */ 560 Error SubscribeExternalMulticast(const Address &aAddress); 561 562 /** 563 * This method unsubscribes the network interface to the external (to OpenThread) multicast address. 564 * 565 * @param[in] aAddress A reference to the multicast address. 566 * 567 * @retval kErrorNone Successfully unsubscribed to the unicast address. 568 * @retval kErrorRejected The address indicated by @p aAddress is an internal address. 569 * @retval kErrorNotFound The multicast address was not found. 570 * 571 */ 572 Error UnsubscribeExternalMulticast(const Address &aAddress); 573 574 /** 575 * This method unsubscribes the network interface from all previously added external (to OpenThread) multicast 576 * addresses. 577 * 578 */ 579 void UnsubscribeAllExternalMulticastAddresses(void); 580 581 /** 582 * This method checks if multicast promiscuous mode is enabled on the network interface. 583 * 584 * @retval TRUE If the multicast promiscuous mode is enabled. 585 * @retval FALSE If the multicast promiscuous mode is disabled. 586 * 587 */ IsMulticastPromiscuousEnabled(void) const588 bool IsMulticastPromiscuousEnabled(void) const { return mMulticastPromiscuous; } 589 590 /** 591 * This method enables multicast promiscuous mode on the network interface. 592 * 593 * @param[in] aEnabled TRUE if Multicast Promiscuous mode is enabled, FALSE otherwise. 594 * 595 */ SetMulticastPromiscuous(bool aEnabled)596 void SetMulticastPromiscuous(bool aEnabled) { mMulticastPromiscuous = aEnabled; } 597 598 /** 599 * This method enables range-based `for` loop iteration over external multicast addresses on the Netif that matches 600 * a given IPv6 address type filter. 601 * 602 * This method should be used like follows: to iterate over all external multicast addresses 603 * 604 * for (Ip6::Netif::ExternalMulticastAddress &addr : Get<ThreadNetif>().IterateExternalMulticastAddresses()) 605 * { ... } 606 * 607 * or to iterate over a subset of external multicast addresses determined by a given address type filter 608 * 609 * for (Ip6::Netif::ExternalMulticastAddress &addr : 610 * Get<ThreadNetif>().IterateExternalMulticastAddresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal)) 611 * { ... } 612 * 613 * @param[in] aFilter The IPv6 address type filter. 614 * 615 * @returns An `ExternalMulticastAddress::Iterator::Builder` instance. 616 * 617 */ IterateExternalMulticastAddresses(Address::TypeFilter aFilter=Address::kTypeAny)618 ExternalMulticastAddress::Iterator::Builder IterateExternalMulticastAddresses( 619 Address::TypeFilter aFilter = Address::kTypeAny) 620 { 621 return ExternalMulticastAddress::Iterator::Builder(*this, aFilter); 622 } 623 624 /** 625 * This method indicates whether or not the network interfaces is subscribed to any external multicast address. 626 * 627 * @retval TRUE The network interface is subscribed to at least one external multicast address. 628 * @retval FALSE The network interface is not subscribed to any external multicast address. 629 * 630 */ HasAnyExternalMulticastAddress(void) const631 bool HasAnyExternalMulticastAddress(void) const { return !ExternalMulticastAddress::Iterator(*this).IsDone(); } 632 633 protected: 634 /** 635 * This method subscribes the network interface to the realm-local all MPL forwarders, link-local, and realm-local 636 * all nodes address. 637 * 638 */ 639 void SubscribeAllNodesMulticast(void); 640 641 /** 642 * This method unsubscribes the network interface from the realm-local all MPL forwarders, link-local and 643 * realm-local all nodes address. 644 * 645 * @note This method MUST be called after `UnsubscribeAllRoutersMulticast()` or its behavior is undefined 646 * 647 */ 648 void UnsubscribeAllNodesMulticast(void); 649 650 private: 651 void SignalMulticastAddressChange(AddressEvent aAddressEvent, 652 const MulticastAddress *aStart, 653 const MulticastAddress *aEnd); 654 655 LinkedList<UnicastAddress> mUnicastAddresses; 656 LinkedList<MulticastAddress> mMulticastAddresses; 657 bool mMulticastPromiscuous; 658 659 Callback<otIp6AddressCallback> mAddressCallback; 660 661 Pool<UnicastAddress, OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS> mExtUnicastAddressPool; 662 Pool<ExternalMulticastAddress, OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS> mExtMulticastAddressPool; 663 664 static const otNetifMulticastAddress kRealmLocalAllMplForwardersMulticastAddress; 665 static const otNetifMulticastAddress kLinkLocalAllNodesMulticastAddress; 666 static const otNetifMulticastAddress kRealmLocalAllNodesMulticastAddress; 667 static const otNetifMulticastAddress kLinkLocalAllRoutersMulticastAddress; 668 static const otNetifMulticastAddress kRealmLocalAllRoutersMulticastAddress; 669 }; 670 671 /** 672 * @} 673 * 674 */ 675 676 } // namespace Ip6 677 678 DefineCoreType(otNetifAddress, Ip6::Netif::UnicastAddress); 679 DefineCoreType(otNetifMulticastAddress, Ip6::Netif::MulticastAddress); 680 681 } // namespace ot 682 683 #endif // NET_NETIF_HPP_ 684