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