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