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