[netif] use newly added linked-list helper methods (#5179)

This commit simplifies the `Netif` implementation by using newly added
`LinkedList::FindMatching()` methods to search in unicast/multicast
address list for an entry matching a given IPv6 address.
diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp
index 23f20ad..93de21f 100644
--- a/src/core/net/netif.cpp
+++ b/src/core/net/netif.cpp
@@ -100,18 +100,9 @@
 
 bool Netif::IsMulticastSubscribed(const Address &aAddress) const
 {
-    bool rval = false;
+    const NetifMulticastAddress *prev;
 
-    for (const NetifMulticastAddress *cur = mMulticastAddresses.GetHead(); cur; cur = cur->GetNext())
-    {
-        if (cur->GetAddress() == aAddress)
-        {
-            ExitNow(rval = true);
-        }
-    }
-
-exit:
-    return rval;
+    return mMulticastAddresses.FindMatching(aAddress, prev) != nullptr;
 }
 
 void Netif::SubscribeAllNodesMulticast(void)
@@ -363,23 +354,15 @@
 {
     otError                error = OT_ERROR_NONE;
     NetifMulticastAddress *entry;
-    NetifMulticastAddress *last = nullptr;
+    NetifMulticastAddress *prev;
 
-    for (entry = mMulticastAddresses.GetHead(); entry; entry = entry->GetNext())
-    {
-        if (entry->GetAddress() == aAddress)
-        {
-            VerifyOrExit(IsMulticastAddressExternal(*entry), error = OT_ERROR_INVALID_ARGS);
-
-            mMulticastAddresses.PopAfter(last);
-            break;
-        }
-
-        last = entry;
-    }
-
+    entry = mMulticastAddresses.FindMatching(aAddress, prev);
     VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND);
 
+    VerifyOrExit(IsMulticastAddressExternal(*entry), error = OT_ERROR_INVALID_ARGS);
+
+    mMulticastAddresses.PopAfter(prev);
+
     entry->MarkAsNotInUse();
 
     Get<Notifier>().Signal(kEventIp6MulticastUnsubscribed);
@@ -433,20 +416,21 @@
 
 otError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress)
 {
-    otError error = OT_ERROR_NONE;
+    otError              error = OT_ERROR_NONE;
+    NetifUnicastAddress *existingEntry;
+    NetifUnicastAddress *prev;
 
-    for (NetifUnicastAddress *entry = mUnicastAddresses.GetHead(); entry; entry = entry->GetNext())
+    existingEntry = mUnicastAddresses.FindMatching(aAddress.GetAddress(), prev);
+
+    if (existingEntry != nullptr)
     {
-        if (entry->GetAddress() == aAddress.GetAddress())
-        {
-            VerifyOrExit(IsUnicastAddressExternal(*entry), error = OT_ERROR_ALREADY);
+        VerifyOrExit(IsUnicastAddressExternal(*existingEntry), error = OT_ERROR_ALREADY);
 
-            entry->mPrefixLength  = aAddress.mPrefixLength;
-            entry->mAddressOrigin = aAddress.mAddressOrigin;
-            entry->mPreferred     = aAddress.mPreferred;
-            entry->mValid         = aAddress.mValid;
-            ExitNow();
-        }
+        existingEntry->mPrefixLength  = aAddress.mPrefixLength;
+        existingEntry->mAddressOrigin = aAddress.mAddressOrigin;
+        existingEntry->mPreferred     = aAddress.mPreferred;
+        existingEntry->mValid         = aAddress.mValid;
+        ExitNow();
     }
 
     VerifyOrExit(!aAddress.GetAddress().IsLinkLocal(), error = OT_ERROR_INVALID_ARGS);
@@ -472,25 +456,16 @@
 {
     otError              error = OT_ERROR_NONE;
     NetifUnicastAddress *entry;
-    NetifUnicastAddress *last = nullptr;
+    NetifUnicastAddress *prev;
 
-    for (entry = mUnicastAddresses.GetHead(); entry; entry = entry->GetNext())
-    {
-        if (entry->GetAddress() == aAddress)
-        {
-            VerifyOrExit(IsUnicastAddressExternal(*entry), error = OT_ERROR_INVALID_ARGS);
-
-            mUnicastAddresses.PopAfter(last);
-            break;
-        }
-
-        last = entry;
-    }
-
+    entry = mUnicastAddresses.FindMatching(aAddress, prev);
     VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND);
 
-    entry->MarkAsNotInUse();
+    VerifyOrExit(IsUnicastAddressExternal(*entry), error = OT_ERROR_INVALID_ARGS);
 
+    mUnicastAddresses.PopAfter(prev);
+
+    entry->MarkAsNotInUse();
     Get<Notifier>().Signal(kEventIp6AddressRemoved);
 
 exit:
@@ -510,18 +485,9 @@
 
 bool Netif::HasUnicastAddress(const Address &aAddress) const
 {
-    bool rval = false;
+    const NetifUnicastAddress *prev;
 
-    for (const NetifUnicastAddress *cur = mUnicastAddresses.GetHead(); cur; cur = cur->GetNext())
-    {
-        if (cur->GetAddress() == aAddress)
-        {
-            ExitNow(rval = true);
-        }
-    }
-
-exit:
-    return rval;
+    return mUnicastAddresses.FindMatching(aAddress, prev) != nullptr;
 }
 
 } // namespace Ip6
diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp
index 3561358..7df7312 100644
--- a/src/core/net/netif.hpp
+++ b/src/core/net/netif.hpp
@@ -71,6 +71,7 @@
                             public Clearable<NetifUnicastAddress>
 {
     friend class Netif;
+    friend class LinkedList<NetifUnicastAddress>;
 
 public:
     /**
@@ -101,6 +102,8 @@
     }
 
 private:
+    bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; }
+
     // In an unused/available entry (i.e., entry not present in a linked
     // list), the next pointer is set to point back to the entry itself.
     bool IsInUse(void) const { return GetNext() != this; }
@@ -116,6 +119,7 @@
                               public Clearable<NetifMulticastAddress>
 {
     friend class Netif;
+    friend class LinkedList<NetifMulticastAddress>;
 
 public:
     /**
@@ -154,6 +158,8 @@
     }
 
 private:
+    bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; }
+
     // In an unused/available entry (i.e., entry not present in a linked
     // list), the next pointer is set to point back to the entry itself.
     bool IsInUse(void) const { return GetNext() != this; }