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