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