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