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