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