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 implements IPv6 network interfaces.
32  */
33 
34 #include "netif.hpp"
35 
36 #include "common/as_core_type.hpp"
37 #include "common/debug.hpp"
38 #include "common/locator_getters.hpp"
39 #include "common/message.hpp"
40 #include "instance/instance.hpp"
41 #include "net/ip6.hpp"
42 
43 namespace ot {
44 namespace Ip6 {
45 
46 /*
47  * Certain fixed multicast addresses are defined as a set of chained (linked-list) constant `otNetifMulticastAddress`
48  * entries:
49  *
50  * LinkLocalAllRouters -> RealmLocalAllRouters -> LinkLocalAll -> RealmLocalAll -> RealmLocalAllMplForwarders.
51  *
52  * All or a portion of the chain is appended to the end of `mMulticastAddresses` linked-list. If the interface is
53  * subscribed to all-routers multicast addresses (using `SubscribeAllRoutersMulticast()`) then all the five entries
54  * are appended. Otherwise only the last three are appended.
55  *
56  */
57 
58 // "ff03::fc"
59 const otNetifMulticastAddress Netif::kRealmLocalAllMplForwardersMulticastAddress = {
60     {{{0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc}}},
61     nullptr};
62 
63 // "ff03::01"
64 const otNetifMulticastAddress Netif::kRealmLocalAllNodesMulticastAddress = {
65     {{{0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}},
66     &Netif::kRealmLocalAllMplForwardersMulticastAddress};
67 
68 // "ff02::01"
69 const otNetifMulticastAddress Netif::kLinkLocalAllNodesMulticastAddress = {
70     {{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}},
71     &Netif::kRealmLocalAllNodesMulticastAddress};
72 
73 // "ff03::02"
74 const otNetifMulticastAddress Netif::kRealmLocalAllRoutersMulticastAddress = {
75     {{{0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}},
76     &Netif::kLinkLocalAllNodesMulticastAddress};
77 
78 // "ff02::02"
79 const otNetifMulticastAddress Netif::kLinkLocalAllRoutersMulticastAddress = {
80     {{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}},
81     &Netif::kRealmLocalAllRoutersMulticastAddress};
82 
83 //---------------------------------------------------------------------------------------------------------------------
84 // Netif
85 
Netif(Instance & aInstance)86 Netif::Netif(Instance &aInstance)
87     : InstanceLocator(aInstance)
88     , mMulticastPromiscuous(false)
89 {
90 }
91 
IsMulticastSubscribed(const Address & aAddress) const92 bool Netif::IsMulticastSubscribed(const Address &aAddress) const
93 {
94     return mMulticastAddresses.ContainsMatching(aAddress);
95 }
96 
SubscribeAllNodesMulticast(void)97 void Netif::SubscribeAllNodesMulticast(void)
98 {
99     MulticastAddress *tail;
100     MulticastAddress &linkLocalAllNodesAddress = AsCoreType(&AsNonConst(kLinkLocalAllNodesMulticastAddress));
101 
102     VerifyOrExit(!mMulticastAddresses.Contains(linkLocalAllNodesAddress));
103 
104     // Append the fixed chain of three multicast addresses to the
105     // tail of the list:
106     //
107     //    LinkLocalAll -> RealmLocalAll -> RealmLocalAllMpl.
108 
109     tail = mMulticastAddresses.GetTail();
110 
111     if (tail == nullptr)
112     {
113         mMulticastAddresses.SetHead(&linkLocalAllNodesAddress);
114     }
115     else
116     {
117         tail->SetNext(&linkLocalAllNodesAddress);
118     }
119 
120     SignalMulticastAddressesChange(kAddressAdded, &linkLocalAllNodesAddress, nullptr);
121 
122 exit:
123     return;
124 }
125 
UnsubscribeAllNodesMulticast(void)126 void Netif::UnsubscribeAllNodesMulticast(void)
127 {
128     MulticastAddress       *prev;
129     const MulticastAddress &linkLocalAllNodesAddress = AsCoreType(&AsNonConst(kLinkLocalAllNodesMulticastAddress));
130 
131     // The tail of multicast address linked list contains the
132     // fixed addresses. Search if LinkLocalAll is present
133     // in the list and find entry before it.
134     //
135     //    LinkLocalAll -> RealmLocalAll -> RealmLocalAllMpl.
136 
137     SuccessOrExit(mMulticastAddresses.Find(linkLocalAllNodesAddress, prev));
138 
139     // This method MUST be called after `UnsubscribeAllRoutersMulticast().
140     // Verify this by checking the chain at the end of the list only
141     // contains three entries and not the five fixed addresses (check that
142     // `prev` entry before `LinkLocalAll` is not `RealmLocalRouters`):
143     //
144     //    LinkLocalAllRouters -> RealmLocalAllRouters -> LinkLocalAll
145     //         -> RealmLocalAll -> RealmLocalAllMpl.
146 
147     OT_ASSERT(prev != AsCoreTypePtr(AsNonConst(&kRealmLocalAllRoutersMulticastAddress)));
148 
149     if (prev == nullptr)
150     {
151         mMulticastAddresses.Clear();
152     }
153     else
154     {
155         prev->SetNext(nullptr);
156     }
157 
158     SignalMulticastAddressesChange(kAddressRemoved, &linkLocalAllNodesAddress, nullptr);
159 
160 exit:
161     return;
162 }
163 
SubscribeAllRoutersMulticast(void)164 void Netif::SubscribeAllRoutersMulticast(void)
165 {
166     MulticastAddress *prev                        = nullptr;
167     MulticastAddress &linkLocalAllRoutersAddress  = AsCoreType(&AsNonConst(kLinkLocalAllRoutersMulticastAddress));
168     MulticastAddress &linkLocalAllNodesAddress    = AsCoreType(&AsNonConst(kLinkLocalAllNodesMulticastAddress));
169     MulticastAddress &realmLocalAllRoutersAddress = AsCoreType(&AsNonConst(kRealmLocalAllRoutersMulticastAddress));
170 
171     // This method MUST be called after `SubscribeAllNodesMulticast()`
172     // Ensure that the `LinkLocalAll` was found on the list.
173 
174     SuccessOrAssert(mMulticastAddresses.Find(linkLocalAllNodesAddress, prev));
175 
176     // The tail of multicast address linked list contains the
177     // fixed addresses. We either have a chain of five addresses
178     //
179     //    LinkLocalAllRouters -> RealmLocalAllRouters ->
180     //        LinkLocalAll -> RealmLocalAll -> RealmLocalAllMpl.
181     //
182     // or just the last three addresses
183     //
184     //    LinkLocalAll -> RealmLocalAll -> RealmLocalAllMpl.
185     //
186     // If the previous entry behind `LinkLocalAll` is
187     // `RealmLocalAllRouters` then all five addresses are on
188     // the list already.
189 
190     VerifyOrExit(prev != &realmLocalAllRoutersAddress);
191 
192     if (prev == nullptr)
193     {
194         mMulticastAddresses.SetHead(&linkLocalAllRoutersAddress);
195     }
196     else
197     {
198         prev->SetNext(&linkLocalAllRoutersAddress);
199     }
200 
201     SignalMulticastAddressesChange(kAddressAdded, &linkLocalAllRoutersAddress, &linkLocalAllNodesAddress);
202 
203 exit:
204     return;
205 }
206 
UnsubscribeAllRoutersMulticast(void)207 void Netif::UnsubscribeAllRoutersMulticast(void)
208 {
209     MulticastAddress *prev;
210     MulticastAddress &linkLocalAllRoutersAddress = AsCoreType(&AsNonConst(kLinkLocalAllRoutersMulticastAddress));
211     MulticastAddress &linkLocalAllNodesAddress   = AsCoreType(&AsNonConst(kLinkLocalAllNodesMulticastAddress));
212 
213     // The tail of multicast address linked list contains the
214     // fixed addresses. We check for the chain of five addresses:
215     //
216     //    LinkLocalAllRouters -> RealmLocalAllRouters ->
217     //        LinkLocalAll -> RealmLocalAll -> RealmLocalAllMpl.
218     //
219     // If found, we then replace the entry behind `LinkLocalAllRouters`
220     // to point to `LinkLocalAll` instead (so that tail contains the
221     // three fixed addresses at end of the chain).
222 
223     SuccessOrExit(mMulticastAddresses.Find(linkLocalAllRoutersAddress, prev));
224 
225     if (prev == nullptr)
226     {
227         mMulticastAddresses.SetHead(&linkLocalAllNodesAddress);
228     }
229     else
230     {
231         prev->SetNext(&linkLocalAllNodesAddress);
232     }
233 
234     SignalMulticastAddressesChange(kAddressRemoved, &linkLocalAllRoutersAddress, &linkLocalAllNodesAddress);
235 
236 exit:
237     return;
238 }
239 
SignalMulticastAddressChange(AddressEvent aEvent,const MulticastAddress & aAddress,AddressOrigin aOrigin)240 void Netif::SignalMulticastAddressChange(AddressEvent aEvent, const MulticastAddress &aAddress, AddressOrigin aOrigin)
241 {
242     Get<Notifier>().Signal(aEvent == kAddressAdded ? kEventIp6MulticastSubscribed : kEventIp6MulticastUnsubscribed);
243 
244 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
245     Get<Utils::HistoryTracker>().RecordAddressEvent(aEvent, aAddress, aOrigin);
246 #endif
247 
248     if ((aOrigin == kOriginThread) && mAddressCallback.IsSet())
249     {
250         AddressInfo info;
251 
252         info.mAddress      = &aAddress.GetAddress();
253         info.mPrefixLength = kMulticastPrefixLength;
254         info.mScope        = aAddress.GetAddress().GetScope();
255         info.mPreferred    = false;
256         info.mMeshLocal    = false;
257 
258         mAddressCallback.Invoke(&info, aEvent);
259     }
260 }
261 
SignalMulticastAddressesChange(AddressEvent aEvent,const MulticastAddress * aStart,const MulticastAddress * aEnd)262 void Netif::SignalMulticastAddressesChange(AddressEvent            aEvent,
263                                            const MulticastAddress *aStart,
264                                            const MulticastAddress *aEnd)
265 {
266     // Signal changes to fixed multicast addresses from `aStart` up to
267     // (not including) `aEnd`.
268 
269     for (const MulticastAddress *entry = aStart; entry != aEnd; entry = entry->GetNext())
270     {
271         SignalMulticastAddressChange(aEvent, *entry, kOriginThread);
272     }
273 }
274 
IsMulticastAddressExternal(const MulticastAddress & aAddress) const275 bool Netif::IsMulticastAddressExternal(const MulticastAddress &aAddress) const
276 {
277     return mExtMulticastAddressPool.IsPoolEntry(static_cast<const ExternalMulticastAddress &>(aAddress));
278 }
279 
SubscribeMulticast(MulticastAddress & aAddress)280 void Netif::SubscribeMulticast(MulticastAddress &aAddress)
281 {
282     SuccessOrExit(mMulticastAddresses.Add(aAddress));
283     SignalMulticastAddressChange(kAddressAdded, aAddress, kOriginThread);
284 
285 exit:
286     return;
287 }
288 
UnsubscribeMulticast(const MulticastAddress & aAddress)289 void Netif::UnsubscribeMulticast(const MulticastAddress &aAddress)
290 {
291     SuccessOrExit(mMulticastAddresses.Remove(aAddress));
292     SignalMulticastAddressChange(kAddressRemoved, aAddress, kOriginThread);
293 
294 exit:
295     return;
296 }
297 
SubscribeExternalMulticast(const Address & aAddress)298 Error Netif::SubscribeExternalMulticast(const Address &aAddress)
299 {
300     Error             error                      = kErrorNone;
301     MulticastAddress &linkLocalAllRoutersAddress = AsCoreType(&AsNonConst(kLinkLocalAllRoutersMulticastAddress));
302     ExternalMulticastAddress *entry;
303 
304     VerifyOrExit(aAddress.IsMulticast(), error = kErrorInvalidArgs);
305     VerifyOrExit(!IsMulticastSubscribed(aAddress), error = kErrorAlready);
306 
307     // Check that the address is not one of the fixed addresses:
308     // LinkLocalAllRouters -> RealmLocalAllRouters -> LinkLocalAllNodes
309     // -> RealmLocalAllNodes -> RealmLocalAllMpl.
310 
311     for (const MulticastAddress *cur = &linkLocalAllRoutersAddress; cur; cur = cur->GetNext())
312     {
313         VerifyOrExit(cur->GetAddress() != aAddress, error = kErrorRejected);
314     }
315 
316     entry = mExtMulticastAddressPool.Allocate();
317     VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
318 
319     entry->mAddress = aAddress;
320 #if OPENTHREAD_CONFIG_MLR_ENABLE
321     entry->mMlrState = kMlrStateToRegister;
322 #endif
323     mMulticastAddresses.Push(*entry);
324 
325     SignalMulticastAddressChange(kAddressAdded, *entry, kOriginManual);
326 
327 exit:
328     return error;
329 }
330 
UnsubscribeExternalMulticast(const Address & aAddress)331 Error Netif::UnsubscribeExternalMulticast(const Address &aAddress)
332 {
333     Error             error = kErrorNone;
334     MulticastAddress *entry;
335     MulticastAddress *prev;
336 
337     entry = mMulticastAddresses.FindMatching(aAddress, prev);
338     VerifyOrExit(entry != nullptr, error = kErrorNotFound);
339 
340     VerifyOrExit(IsMulticastAddressExternal(*entry), error = kErrorRejected);
341 
342     mMulticastAddresses.PopAfter(prev);
343 
344     SignalMulticastAddressChange(kAddressRemoved, *entry, kOriginManual);
345 
346     mExtMulticastAddressPool.Free(static_cast<ExternalMulticastAddress &>(*entry));
347 
348 exit:
349     return error;
350 }
351 
UnsubscribeAllExternalMulticastAddresses(void)352 void Netif::UnsubscribeAllExternalMulticastAddresses(void)
353 {
354     MulticastAddress *next;
355 
356     for (MulticastAddress *entry = mMulticastAddresses.GetHead(); entry != nullptr; entry = next)
357     {
358         next = entry->GetNext();
359 
360         if (IsMulticastAddressExternal(*entry))
361         {
362             IgnoreError(UnsubscribeExternalMulticast(entry->GetAddress()));
363         }
364     }
365 }
366 
AddUnicastAddress(UnicastAddress & aAddress)367 void Netif::AddUnicastAddress(UnicastAddress &aAddress)
368 {
369     if (aAddress.mMeshLocal)
370     {
371         aAddress.GetAddress().SetPrefix(Get<Mle::Mle>().GetMeshLocalPrefix());
372     }
373 
374     SuccessOrExit(mUnicastAddresses.Add(aAddress));
375     SignalUnicastAddressChange(kAddressAdded, aAddress);
376 
377 exit:
378     return;
379 }
380 
RemoveUnicastAddress(UnicastAddress & aAddress)381 void Netif::RemoveUnicastAddress(UnicastAddress &aAddress)
382 {
383     SuccessOrExit(mUnicastAddresses.Remove(aAddress));
384     aAddress.mSrpRegistered = false;
385     SignalUnicastAddressChange(kAddressRemoved, aAddress);
386 
387 exit:
388     return;
389 }
390 
UpdatePreferredFlagOn(UnicastAddress & aAddress,bool aPreferred)391 void Netif::UpdatePreferredFlagOn(UnicastAddress &aAddress, bool aPreferred)
392 {
393     VerifyOrExit(HasUnicastAddress(aAddress));
394     VerifyOrExit(aAddress.mPreferred != aPreferred);
395 
396     SignalUnicastAddressChange(kAddressRemoved, aAddress);
397     aAddress.mPreferred = aPreferred;
398     SignalUnicastAddressChange(kAddressAdded, aAddress);
399 
400 exit:
401     return;
402 }
403 
SignalUnicastAddressChange(AddressEvent aEvent,const UnicastAddress & aAddress)404 void Netif::SignalUnicastAddressChange(AddressEvent aEvent, const UnicastAddress &aAddress)
405 {
406     Event event;
407 
408     if (aAddress.mRloc)
409     {
410         event = (aEvent == kAddressAdded) ? kEventThreadRlocAdded : kEventThreadRlocRemoved;
411     }
412     else
413     {
414         event = (aEvent == kAddressAdded) ? kEventIp6AddressAdded : kEventIp6AddressRemoved;
415     }
416 
417     Get<Notifier>().Signal(event);
418 
419 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
420     Get<Utils::HistoryTracker>().RecordAddressEvent(aEvent, aAddress);
421 #endif
422 
423     if (!IsUnicastAddressExternal(aAddress) && mAddressCallback.IsSet())
424     {
425         AddressInfo info;
426 
427         info.mAddress      = &aAddress.mAddress;
428         info.mPrefixLength = aAddress.mPrefixLength;
429         info.mScope        = aAddress.GetScope();
430         info.mPreferred    = aAddress.mPreferred;
431         info.mMeshLocal    = aAddress.mMeshLocal;
432 
433         mAddressCallback.Invoke(&info, aEvent);
434     }
435 }
436 
AddExternalUnicastAddress(const UnicastAddress & aAddress)437 Error Netif::AddExternalUnicastAddress(const UnicastAddress &aAddress)
438 {
439     Error           error = kErrorNone;
440     UnicastAddress *entry;
441 
442     VerifyOrExit(!aAddress.GetAddress().IsMulticast(), error = kErrorInvalidArgs);
443 
444     entry = mUnicastAddresses.FindMatching(aAddress.GetAddress());
445 
446     if (entry != nullptr)
447     {
448         VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorInvalidArgs);
449 
450         entry->mPrefixLength  = aAddress.mPrefixLength;
451         entry->mAddressOrigin = aAddress.mAddressOrigin;
452         entry->mPreferred     = aAddress.mPreferred;
453         entry->mValid         = aAddress.mValid;
454         ExitNow();
455     }
456 
457     VerifyOrExit(!aAddress.GetAddress().IsLinkLocal(), error = kErrorInvalidArgs);
458 
459     entry = mExtUnicastAddressPool.Allocate();
460     VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
461 
462     *entry                = aAddress;
463     entry->mRloc          = false;
464     entry->mMeshLocal     = false;
465     entry->mSrpRegistered = false;
466 
467     mUnicastAddresses.Push(*entry);
468     SignalUnicastAddressChange(kAddressAdded, *entry);
469 
470 exit:
471     return error;
472 }
473 
RemoveExternalUnicastAddress(const Address & aAddress)474 Error Netif::RemoveExternalUnicastAddress(const Address &aAddress)
475 {
476     Error           error = kErrorNone;
477     UnicastAddress *entry;
478     UnicastAddress *prev;
479 
480     entry = mUnicastAddresses.FindMatching(aAddress, prev);
481     VerifyOrExit(entry != nullptr, error = kErrorNotFound);
482 
483     VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorRejected);
484 
485     mUnicastAddresses.PopAfter(prev);
486 
487     SignalUnicastAddressChange(kAddressRemoved, *entry);
488 
489     mExtUnicastAddressPool.Free(*entry);
490 
491 exit:
492     return error;
493 }
494 
RemoveAllExternalUnicastAddresses(void)495 void Netif::RemoveAllExternalUnicastAddresses(void)
496 {
497     UnicastAddress *next;
498 
499     for (UnicastAddress *entry = mUnicastAddresses.GetHead(); entry != nullptr; entry = next)
500     {
501         next = entry->GetNext();
502 
503         if (IsUnicastAddressExternal(*entry))
504         {
505             IgnoreError(RemoveExternalUnicastAddress(entry->GetAddress()));
506         }
507     }
508 }
509 
HasUnicastAddress(const Address & aAddress) const510 bool Netif::HasUnicastAddress(const Address &aAddress) const { return mUnicastAddresses.ContainsMatching(aAddress); }
511 
IsUnicastAddressExternal(const UnicastAddress & aAddress) const512 bool Netif::IsUnicastAddressExternal(const UnicastAddress &aAddress) const
513 {
514     return mExtUnicastAddressPool.IsPoolEntry(aAddress);
515 }
516 
ApplyNewMeshLocalPrefix(void)517 void Netif::ApplyNewMeshLocalPrefix(void)
518 {
519     for (UnicastAddress &address : mUnicastAddresses)
520     {
521         if (address.mMeshLocal)
522         {
523             SignalUnicastAddressChange(kAddressRemoved, address);
524             address.mSrpRegistered = false;
525             address.GetAddress().SetPrefix(Get<Mle::Mle>().GetMeshLocalPrefix());
526             SignalUnicastAddressChange(kAddressAdded, address);
527         }
528     }
529 
530     for (MulticastAddress &address : mMulticastAddresses)
531     {
532         if (Get<Mle::Mle>().IsMulticastAddressMeshLocalPrefixBased(address))
533         {
534             SignalMulticastAddressChange(kAddressRemoved, address, kOriginThread);
535             address.GetAddress().SetMulticastNetworkPrefix(Get<Mle::Mle>().GetMeshLocalPrefix());
536             SignalMulticastAddressChange(kAddressAdded, address, kOriginThread);
537         }
538     }
539 }
540 
541 //---------------------------------------------------------------------------------------------------------------------
542 // Netif::UnicastAddress
543 
InitAsThreadOrigin(void)544 void Netif::UnicastAddress::InitAsThreadOrigin(void)
545 {
546     Clear();
547     mPrefixLength  = NetworkPrefix::kLength;
548     mAddressOrigin = kOriginThread;
549     mPreferred     = true;
550     mValid         = true;
551 }
552 
InitAsThreadOriginMeshLocal(void)553 void Netif::UnicastAddress::InitAsThreadOriginMeshLocal(void)
554 {
555     InitAsThreadOrigin();
556     SetScopeOverride(Address::kRealmLocalScope);
557     mMeshLocal = true;
558 }
559 
InitAsThreadOriginGlobalScope(void)560 void Netif::UnicastAddress::InitAsThreadOriginGlobalScope(void)
561 {
562     Clear();
563     mAddressOrigin = kOriginThread;
564     mValid         = true;
565     SetScopeOverride(Address::kGlobalScope);
566 }
567 
InitAsSlaacOrigin(uint8_t aPrefixLength,bool aPreferred)568 void Netif::UnicastAddress::InitAsSlaacOrigin(uint8_t aPrefixLength, bool aPreferred)
569 {
570     Clear();
571     mPrefixLength  = aPrefixLength;
572     mAddressOrigin = kOriginSlaac;
573     mPreferred     = aPreferred;
574     mValid         = true;
575 }
576 
577 //---------------------------------------------------------------------------------------------------------------------
578 // Netif::ExternalMulticastAddress::Iterator
579 
Iterator(const Netif & aNetif,Address::TypeFilter aFilter)580 Netif::ExternalMulticastAddress::Iterator::Iterator(const Netif &aNetif, Address::TypeFilter aFilter)
581     : ItemPtrIterator(nullptr)
582     , mNetif(aNetif)
583     , mFilter(aFilter)
584 {
585     AdvanceFrom(mNetif.GetMulticastAddresses().GetHead());
586 }
587 
AdvanceFrom(const MulticastAddress * aAddr)588 void Netif::ExternalMulticastAddress::Iterator::AdvanceFrom(const MulticastAddress *aAddr)
589 {
590     while (aAddr != nullptr &&
591            !(mNetif.IsMulticastAddressExternal(*aAddr) && aAddr->GetAddress().MatchesFilter(mFilter)))
592     {
593         aAddr = aAddr->GetNext();
594     }
595 
596     mItem = AsNonConst(static_cast<const ExternalMulticastAddress *>(aAddr));
597 }
598 
599 } // namespace Ip6
600 } // namespace ot
601