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