Convert Inet::InterfaceId to a class (#10979)

* Convert Inet::InterfaceId to a class

#### Problem

The current `#if`+`typedef` requires the actual definition to be visible
at every appearance, rather than merely an opaque forward class declaration,
which is an obstace to #7715 _Virtualize System and Inet interfaces_.

#### Change overview

Convert `InterfaceId` to a class. Some free functions become class methods,
and `INET_NULL_INTERFACEID` is replaced by a default-constructed
`InterfaceId`.

#### Testing

CI; no changes to functionality intended.

* add InterfaceId::Null()

* replace strcpy()
diff --git a/examples/chip-tool/commands/common/Command.cpp b/examples/chip-tool/commands/common/Command.cpp
index 9b0b1bd..e1c9ba1 100644
--- a/examples/chip-tool/commands/common/Command.cpp
+++ b/examples/chip-tool/commands/common/Command.cpp
@@ -74,11 +74,11 @@
     if (result->ai_family == AF_INET6)
     {
         struct sockaddr_in6 * addr = reinterpret_cast<struct sockaddr_in6 *>(result->ai_addr);
-        address->interfaceId       = addr->sin6_scope_id;
+        address->interfaceId       = ::chip::Inet::InterfaceId(addr->sin6_scope_id);
     }
     else
     {
-        address->interfaceId = INET_NULL_INTERFACEID;
+        address->interfaceId = chip::Inet::InterfaceId::Null();
     }
 
     return true;
diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp
index bdf473d..8e7c3b6 100644
--- a/examples/chip-tool/commands/pairing/PairingCommand.cpp
+++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp
@@ -428,7 +428,7 @@
     // Stop Mdns discovery. Is it the right method ?
     mController.RegisterDeviceDiscoveryDelegate(nullptr);
 
-    Inet::InterfaceId interfaceId = nodeData.ipAddress[0].IsIPv6LinkLocal() ? nodeData.interfaceId[0] : INET_NULL_INTERFACEID;
+    Inet::InterfaceId interfaceId = nodeData.ipAddress[0].IsIPv6LinkLocal() ? nodeData.interfaceId[0] : Inet::InterfaceId::Null();
     PeerAddress peerAddress       = PeerAddress::UDP(nodeData.ipAddress[0], port, interfaceId);
     CHIP_ERROR err                = Pair(mNodeId, peerAddress);
     if (CHIP_NO_ERROR != err)
diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h
index e3fbd05..6fcf1a9 100644
--- a/examples/chip-tool/commands/pairing/PairingCommand.h
+++ b/examples/chip-tool/commands/pairing/PairingCommand.h
@@ -58,7 +58,7 @@
                    chip::Dnssd::DiscoveryFilterType filterType = chip::Dnssd::DiscoveryFilterType::kNone) :
         CHIPCommand(commandName),
         mPairingMode(mode), mNetworkType(networkType),
-        mFilterType(filterType), mRemoteAddr{ IPAddress::Any, INET_NULL_INTERFACEID },
+        mFilterType(filterType), mRemoteAddr{ IPAddress::Any, chip::Inet::InterfaceId::Null() },
         mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
     {
         AddArgument("node-id", 0, UINT64_MAX, &mNodeId);
diff --git a/examples/minimal-mdns/AllInterfaceListener.h b/examples/minimal-mdns/AllInterfaceListener.h
index 7a1b314..178c91b 100644
--- a/examples/minimal-mdns/AllInterfaceListener.h
+++ b/examples/minimal-mdns/AllInterfaceListener.h
@@ -39,7 +39,7 @@
         if (mState == State::kIpV4)
         {
 #if INET_CONFIG_ENABLE_IPV4
-            *id   = INET_NULL_INTERFACEID;
+            *id   = Inet::InterfaceId::Null();
             *type = chip::Inet::IPAddressType::kIPv4;
 #endif
             mState = State::kIpV6;
@@ -100,7 +100,7 @@
             return true; // not a usable interface
         }
 
-        char name[chip::Inet::InterfaceIterator::kMaxIfNameLength];
+        char name[chip::Inet::InterfaceId::kMaxIfNameLength];
         if (mIterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR)
         {
             printf("!!!! FAILED TO GET INTERFACE NAME\n");
diff --git a/examples/shell/shell_common/cmd_ping.cpp b/examples/shell/shell_common/cmd_ping.cpp
index f4a44af..2615c61 100644
--- a/examples/shell/shell_common/cmd_ping.cpp
+++ b/examples/shell/shell_common/cmd_ping.cpp
@@ -144,7 +144,7 @@
 #endif
     {
 
-        return Transport::PeerAddress::UDP(gDestAddr, gPingArguments.GetEchoPort(), INET_NULL_INTERFACEID);
+        return Transport::PeerAddress::UDP(gDestAddr, gPingArguments.GetEchoPort(), ::chip::Inet::InterfaceId::Null());
     }
 }
 
diff --git a/examples/shell/shell_common/cmd_send.cpp b/examples/shell/shell_common/cmd_send.cpp
index 4e79ab3..99b7bc1 100644
--- a/examples/shell/shell_common/cmd_send.cpp
+++ b/examples/shell/shell_common/cmd_send.cpp
@@ -232,7 +232,7 @@
     else
 #endif
     {
-        peerAddress = Transport::PeerAddress::UDP(gDestAddr, gSendArguments.GetPort(), INET_NULL_INTERFACEID);
+        peerAddress = Transport::PeerAddress::UDP(gDestAddr, gSendArguments.GetPort(), Inet::InterfaceId::Null());
 
         err = gSessionManager.Init(&DeviceLayer::SystemLayer(), &gUDPManager, &gMessageCounterManager);
         SuccessOrExit(err);
diff --git a/src/app/tests/integration/chip_im_initiator.cpp b/src/app/tests/integration/chip_im_initiator.cpp
index 247b294..61d7e20 100644
--- a/src/app/tests/integration/chip_im_initiator.cpp
+++ b/src/app/tests/integration/chip_im_initiator.cpp
@@ -429,7 +429,7 @@
 
     // Attempt to connect to the peer.
     err = gSessionManager.NewPairing(chip::Optional<chip::Transport::PeerAddress>::Value(
-                                         chip::Transport::PeerAddress::UDP(gDestAddr, CHIP_PORT, INET_NULL_INTERFACEID)),
+                                         chip::Transport::PeerAddress::UDP(gDestAddr, CHIP_PORT, chip::Inet::InterfaceId::Null())),
                                      chip::kTestDeviceNodeId, testSecurePairingSecret, chip::CryptoContext::SessionRole::kInitiator,
                                      gFabricIndex);
 
diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp
index 7cc1a44..684b2fb 100644
--- a/src/controller/CHIPDevice.cpp
+++ b/src/controller/CHIPDevice.cpp
@@ -142,8 +142,8 @@
 
     serializable.mDeviceTransport = to_underlying(mDeviceAddress.GetTransportType());
 
-    ReturnErrorOnFailure(Inet::GetInterfaceName(mDeviceAddress.GetInterface(), Uint8::to_char(serializable.mInterfaceName),
-                                                sizeof(serializable.mInterfaceName)));
+    ReturnErrorOnFailure(mDeviceAddress.GetInterface().GetInterfaceName(Uint8::to_char(serializable.mInterfaceName),
+                                                                        sizeof(serializable.mInterfaceName)));
     static_assert(sizeof(serializable.mDeviceAddr) <= INET6_ADDRSTRLEN, "Size of device address must fit within INET6_ADDRSTRLEN");
     mDeviceAddress.GetIPAddress().ToString(Uint8::to_char(serializable.mDeviceAddr), sizeof(serializable.mDeviceAddr));
 
@@ -202,13 +202,13 @@
 
     // The InterfaceNameToId() API requires initialization of mInterface, and lock/unlock of
     // LwIP stack.
-    Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;
+    Inet::InterfaceId interfaceId;
     if (serializable.mInterfaceName[0] != '\0')
     {
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
         LOCK_TCPIP_CORE();
 #endif
-        CHIP_ERROR inetErr = Inet::InterfaceNameToId(Uint8::to_const_char(serializable.mInterfaceName), interfaceId);
+        CHIP_ERROR inetErr = Inet::InterfaceId::InterfaceNameToId(Uint8::to_const_char(serializable.mInterfaceName), interfaceId);
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
         UNLOCK_TCPIP_CORE();
 #endif
diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp
index 6189c49..fc2c66f 100644
--- a/src/controller/CHIPDeviceController.cpp
+++ b/src/controller/CHIPDeviceController.cpp
@@ -543,9 +543,9 @@
 #if CHIP_DEVICE_CONFIG_ENABLE_DNSSD
 void DeviceController::OnNodeIdResolved(const chip::Dnssd::ResolvedNodeData & nodeData)
 {
-    CHIP_ERROR err                = CHIP_NO_ERROR;
-    Device * device               = nullptr;
-    Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;
+    CHIP_ERROR err  = CHIP_NO_ERROR;
+    Device * device = nullptr;
+    Inet::InterfaceId interfaceId;
 
     err = GetDevice(nodeData.mPeerId.GetNodeId(), &device);
     SuccessOrExit(err);
diff --git a/src/controller/SetUpCodePairer.cpp b/src/controller/SetUpCodePairer.cpp
index dd77636..f4b7ac3 100644
--- a/src/controller/SetUpCodePairer.cpp
+++ b/src/controller/SetUpCodePairer.cpp
@@ -167,7 +167,7 @@
     LogErrorOnFailure(StopConnectOverIP());
     LogErrorOnFailure(StopConnectOverSoftAP());
 
-    Inet::InterfaceId interfaceId      = nodeData.ipAddress[0].IsIPv6LinkLocal() ? nodeData.interfaceId[0] : INET_NULL_INTERFACEID;
+    Inet::InterfaceId interfaceId = nodeData.ipAddress[0].IsIPv6LinkLocal() ? nodeData.interfaceId[0] : Inet::InterfaceId::Null();
     Transport::PeerAddress peerAddress = Transport::PeerAddress::UDP(nodeData.ipAddress[0], nodeData.port, interfaceId);
     RendezvousParameters params        = RendezvousParameters().SetPeerAddress(peerAddress);
     OnDeviceDiscovered(params);
diff --git a/src/controller/python/chip/discovery/NodeResolution.cpp b/src/controller/python/chip/discovery/NodeResolution.cpp
index dcda6be..84f621f 100644
--- a/src/controller/python/chip/discovery/NodeResolution.cpp
+++ b/src/controller/python/chip/discovery/NodeResolution.cpp
@@ -45,7 +45,7 @@
             mSuccessCallback(                                                         //
                 nodeData.mPeerId.GetCompressedFabricId(),                             //
                 nodeData.mPeerId.GetNodeId(),                                         //
-                nodeData.mInterfaceId,                                                //
+                nodeData.mInterfaceId.GetPlatformInterface(),                         //
                 nodeData.mAddress.ToString(ipAddressBuffer, sizeof(ipAddressBuffer)), //
                 nodeData.mPort                                                        //
             );
diff --git a/src/inet/IPEndPointBasis.cpp b/src/inet/IPEndPointBasis.cpp
index f88841a..8ea3c07 100644
--- a/src/inet/IPEndPointBasis.cpp
+++ b/src/inet/IPEndPointBasis.cpp
@@ -118,12 +118,11 @@
 namespace Inet {
 
 #if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_SOCKETS
+
 static CHIP_ERROR CheckMulticastGroupArgs(InterfaceId aInterfaceId, const IPAddress & aAddress)
 {
-    VerifyOrReturnError(IsInterfaceIdPresent(aInterfaceId), INET_ERROR_UNKNOWN_INTERFACE);
-
+    VerifyOrReturnError(aInterfaceId.IsPresent(), INET_ERROR_UNKNOWN_INTERFACE);
     VerifyOrReturnError(aAddress.IsMulticast(), INET_ERROR_WRONG_ADDRESS_TYPE);
-
     return CHIP_NO_ERROR;
 }
 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_SOCKETS
@@ -244,11 +243,11 @@
 #if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 0 && defined(NETIF_FOREACH)
     NETIF_FOREACH(lRetval)
     {
-        if (lRetval == aInterfaceId)
+        if (lRetval == aInterfaceId.GetPlatformInterface())
             break;
     }
 #else  // LWIP_VERSION_MAJOR < 2 || !defined(NETIF_FOREACH)
-    for (lRetval = netif_list; lRetval != NULL && lRetval != aInterfaceId; lRetval = lRetval->next)
+    for (lRetval = netif_list; lRetval != NULL && lRetval != aInterfaceId.GetPlatformInterface(); lRetval = lRetval->next)
         ;
 #endif // LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 0 && defined(NETIF_FOREACH)
 
@@ -359,7 +358,7 @@
 
 void IPEndPointBasis::InitImpl()
 {
-    mBoundIntfId = INET_NULL_INTERFACEID;
+    mBoundIntfId = InterfaceId::Null();
 }
 
 #if INET_CONFIG_ENABLE_IPV4
@@ -374,7 +373,7 @@
     {
         const IPAddress lCurrentAddress = lAddressIterator.GetAddress();
 
-        if (lAddressIterator.GetInterface() == aInterfaceId)
+        if (lAddressIterator.GetInterfaceId() == aInterfaceId)
         {
             if (lCurrentAddress.IsIPv4())
             {
@@ -410,8 +409,7 @@
 static CHIP_ERROR SocketsIPv6JoinLeaveMulticastGroup(int aSocket, InterfaceId aInterfaceId, const IPAddress & aAddress,
                                                      int aCommand)
 {
-    VerifyOrReturnError(CanCastTo<unsigned int>(aInterfaceId), CHIP_ERROR_UNEXPECTED_EVENT);
-    const unsigned int lIfIndex = static_cast<unsigned int>(aInterfaceId);
+    const InterfaceId::PlatformType lIfIndex = aInterfaceId.GetPlatformInterface();
 
     struct ipv6_mreq lMulticastRequest;
     memset(&lMulticastRequest, 0, sizeof(lMulticastRequest));
@@ -455,14 +453,15 @@
 
         memset(&sa, 0, sizeof(sa));
 
-        sa.sin6_family = AF_INET6;
-        sa.sin6_port   = htons(aPort);
-        sa.sin6_addr   = aAddress.ToIPv6();
-        if (!CanCastTo<decltype(sa.sin6_scope_id)>(aInterfaceId))
+        sa.sin6_family                        = AF_INET6;
+        sa.sin6_port                          = htons(aPort);
+        sa.sin6_addr                          = aAddress.ToIPv6();
+        InterfaceId::PlatformType interfaceId = aInterfaceId.GetPlatformInterface();
+        if (!CanCastTo<decltype(sa.sin6_scope_id)>(interfaceId))
         {
             return CHIP_ERROR_INCORRECT_STATE;
         }
-        sa.sin6_scope_id = static_cast<decltype(sa.sin6_scope_id)>(aInterfaceId);
+        sa.sin6_scope_id = static_cast<decltype(sa.sin6_scope_id)>(interfaceId);
 
         if (bind(mSocket, reinterpret_cast<const sockaddr *>(&sa), static_cast<unsigned>(sizeof(sa))) != 0)
             lRetval = CHIP_ERROR_POSIX(errno);
@@ -526,7 +525,7 @@
     CHIP_ERROR lRetval = CHIP_NO_ERROR;
 
 #if HAVE_SO_BINDTODEVICE
-    if (aInterfaceId == INET_NULL_INTERFACEID)
+    if (!aInterfaceId.IsPresent())
     {
         // Stop interface-based filtering.
         if (setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE, "", 0) == -1)
@@ -539,7 +538,7 @@
         // Start filtering on the passed interface.
         char lInterfaceName[IF_NAMESIZE];
 
-        if (if_indextoname(aInterfaceId, lInterfaceName) == NULL)
+        if (if_indextoname(aInterfaceId.GetPlatformInterface(), lInterfaceName) == NULL)
         {
             lRetval = CHIP_ERROR_POSIX(errno);
         }
@@ -589,11 +588,12 @@
     msgHeader.msg_name = &peerSockAddr;
     if (mAddrType == IPAddressType::kIPv6)
     {
-        peerSockAddr.in6.sin6_family = AF_INET6;
-        peerSockAddr.in6.sin6_port   = htons(aPktInfo->DestPort);
-        peerSockAddr.in6.sin6_addr   = aPktInfo->DestAddress.ToIPv6();
-        VerifyOrReturnError(CanCastTo<decltype(peerSockAddr.in6.sin6_scope_id)>(aPktInfo->Interface), CHIP_ERROR_INCORRECT_STATE);
-        peerSockAddr.in6.sin6_scope_id = static_cast<decltype(peerSockAddr.in6.sin6_scope_id)>(aPktInfo->Interface);
+        peerSockAddr.in6.sin6_family     = AF_INET6;
+        peerSockAddr.in6.sin6_port       = htons(aPktInfo->DestPort);
+        peerSockAddr.in6.sin6_addr       = aPktInfo->DestAddress.ToIPv6();
+        InterfaceId::PlatformType intfId = aPktInfo->Interface.GetPlatformInterface();
+        VerifyOrReturnError(CanCastTo<decltype(peerSockAddr.in6.sin6_scope_id)>(intfId), CHIP_ERROR_INCORRECT_STATE);
+        peerSockAddr.in6.sin6_scope_id = static_cast<decltype(peerSockAddr.in6.sin6_scope_id)>(intfId);
         msgHeader.msg_namelen          = sizeof(sockaddr_in6);
     }
 #if INET_CONFIG_ENABLE_IPV4
@@ -612,21 +612,22 @@
     // for messages to multicast addresses, which under Linux
     // don't seem to get sent out the correct interface, despite
     // the socket being bound.
-    InterfaceId intfId = aPktInfo->Interface;
-    if (intfId == INET_NULL_INTERFACEID)
-        intfId = mBoundIntfId;
+    InterfaceId intf = aPktInfo->Interface;
+    if (!intf.IsPresent())
+        intf = mBoundIntfId;
 
     // If the packet should be sent over a specific interface, or with a specific source
     // address, construct an IP_PKTINFO/IPV6_PKTINFO "control message" to that effect
     // add add it to the message header.  If the local OS doesn't support IP_PKTINFO/IPV6_PKTINFO
     // fail with an error.
-    if (intfId != INET_NULL_INTERFACEID || aPktInfo->SrcAddress.Type() != IPAddressType::kAny)
+    if (intf.IsPresent() || aPktInfo->SrcAddress.Type() != IPAddressType::kAny)
     {
 #if defined(IP_PKTINFO) || defined(IPV6_PKTINFO)
         msgHeader.msg_control    = controlData;
         msgHeader.msg_controllen = sizeof(controlData);
 
-        struct cmsghdr * controlHdr = CMSG_FIRSTHDR(&msgHeader);
+        struct cmsghdr * controlHdr      = CMSG_FIRSTHDR(&msgHeader);
+        InterfaceId::PlatformType intfId = intf.GetPlatformInterface();
 
 #if INET_CONFIG_ENABLE_IPV4
 
@@ -874,12 +875,12 @@
                 if (controlHdr->cmsg_level == IPPROTO_IP && controlHdr->cmsg_type == IP_PKTINFO)
                 {
                     struct in_pktinfo * inPktInfo = reinterpret_cast<struct in_pktinfo *> CMSG_DATA(controlHdr);
-                    if (!CanCastTo<InterfaceId>(inPktInfo->ipi_ifindex))
+                    if (!CanCastTo<InterfaceId::PlatformType>(inPktInfo->ipi_ifindex))
                     {
                         lStatus = CHIP_ERROR_INCORRECT_STATE;
                         break;
                     }
-                    lPacketInfo.Interface   = static_cast<InterfaceId>(inPktInfo->ipi_ifindex);
+                    lPacketInfo.Interface   = InterfaceId(static_cast<InterfaceId::PlatformType>(inPktInfo->ipi_ifindex));
                     lPacketInfo.DestAddress = IPAddress(inPktInfo->ipi_addr);
                     continue;
                 }
@@ -890,12 +891,12 @@
                 if (controlHdr->cmsg_level == IPPROTO_IPV6 && controlHdr->cmsg_type == IPV6_PKTINFO)
                 {
                     struct in6_pktinfo * in6PktInfo = reinterpret_cast<struct in6_pktinfo *> CMSG_DATA(controlHdr);
-                    if (!CanCastTo<InterfaceId>(in6PktInfo->ipi6_ifindex))
+                    if (!CanCastTo<InterfaceId::PlatformType>(in6PktInfo->ipi6_ifindex))
                     {
                         lStatus = CHIP_ERROR_INCORRECT_STATE;
                         break;
                     }
-                    lPacketInfo.Interface   = static_cast<InterfaceId>(in6PktInfo->ipi6_ifindex);
+                    lPacketInfo.Interface   = InterfaceId(static_cast<InterfaceId::PlatformType>(in6PktInfo->ipi6_ifindex));
                     lPacketInfo.DestAddress = IPAddress(in6PktInfo->ipi6_addr);
                     continue;
                 }
diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp
index 204baa4..0cff70e 100644
--- a/src/inet/InetInterface.cpp
+++ b/src/inet/InetInterface.cpp
@@ -71,31 +71,36 @@
 
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
 
-DLL_EXPORT CHIP_ERROR GetInterfaceName(InterfaceId intfId, char * nameBuf, size_t nameBufSize)
+CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
 {
-    if (intfId != INET_NULL_INTERFACEID)
+    if (mPlatformInterface)
     {
-        int status = snprintf(nameBuf, nameBufSize, "%c%c%d", intfId->name[0], intfId->name[1], intfId->num);
+        int status = snprintf(nameBuf, nameBufSize, "%c%c%d", mPlatformInterface->name[0], mPlatformInterface->name[1],
+                              mPlatformInterface->num);
         if (status >= static_cast<int>(nameBufSize))
-            return CHIP_ERROR_NO_MEMORY;
+            return CHIP_ERROR_BUFFER_TOO_SMALL;
         return CHIP_NO_ERROR;
     }
-
     if (nameBufSize < 1)
-        return CHIP_ERROR_NO_MEMORY;
-
+    {
+        return CHIP_ERROR_BUFFER_TOO_SMALL;
+    }
     nameBuf[0] = 0;
     return CHIP_NO_ERROR;
 }
 
-DLL_EXPORT CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId)
+CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
 {
     if (strlen(intfName) < 3)
+    {
         return INET_ERROR_UNKNOWN_INTERFACE;
+    }
     char * parseEnd;
     unsigned long intfNum = strtoul(intfName + 2, &parseEnd, 10);
     if (*parseEnd != 0 || intfNum > UINT8_MAX)
+    {
         return INET_ERROR_UNKNOWN_INTERFACE;
+    }
     struct netif * intf;
 #if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 0 && defined(NETIF_FOREACH)
     NETIF_FOREACH(intf)
@@ -105,17 +110,16 @@
     {
         if (intf->name[0] == intfName[0] && intf->name[1] == intfName[1] && intf->num == (uint8_t) intfNum)
         {
-            intfId = intf;
+            interface = InterfaceId(intf);
             return CHIP_NO_ERROR;
         }
     }
-    intfId = INET_NULL_INTERFACEID;
+    interface = InterfaceId::Null();
     return INET_ERROR_UNKNOWN_INTERFACE;
 }
 
 bool InterfaceIterator::Next()
 {
-
     // Lock LwIP stack
     LOCK_TCPIP_CORE();
 
@@ -144,7 +148,7 @@
 CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
 {
     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
-    return ::chip::Inet::GetInterfaceName(mCurNetif, nameBuf, nameBufSize);
+    return InterfaceId(mCurNetif).GetInterfaceName(nameBuf, nameBufSize);
 }
 
 bool InterfaceIterator::IsUp()
@@ -178,7 +182,7 @@
 
     while (mIntfIter.HasCurrent())
     {
-        struct netif * curIntf = mIntfIter.GetInterfaceId();
+        struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
 
         while (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES)
         {
@@ -210,7 +214,7 @@
 {
     if (HasCurrent())
     {
-        struct netif * curIntf = mIntfIter.GetInterfaceId();
+        struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
 
         if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES)
         {
@@ -238,7 +242,7 @@
 #if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
         else
         {
-            struct netif * curIntf = mIntfIter.GetInterfaceId();
+            struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
             return NetmaskToPrefixLength((const uint8_t *) netif_ip4_netmask(curIntf), 4);
         }
 #endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
@@ -248,11 +252,7 @@
 
 InterfaceId InterfaceAddressIterator::GetInterfaceId()
 {
-    if (HasCurrent())
-    {
-        return mIntfIter.GetInterfaceId();
-    }
-    return INET_NULL_INTERFACEID;
+    return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null();
 }
 
 CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
@@ -263,60 +263,56 @@
 
 bool InterfaceAddressIterator::IsUp()
 {
-    if (HasCurrent())
-    {
-        return mIntfIter.IsUp();
-    }
-    return false;
+    return HasCurrent() && mIntfIter.IsUp();
 }
 
 bool InterfaceAddressIterator::SupportsMulticast()
 {
-    if (HasCurrent())
-    {
-        return mIntfIter.SupportsMulticast();
-    }
-    return false;
+    return HasCurrent() && mIntfIter.SupportsMulticast();
 }
 
 bool InterfaceAddressIterator::HasBroadcastAddress()
 {
-    if (HasCurrent())
-    {
-        return mIntfIter.HasBroadcastAddress();
-    }
-    return false;
+    return HasCurrent() && mIntfIter.HasBroadcastAddress();
 }
 
 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
 
 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
 
-DLL_EXPORT CHIP_ERROR GetInterfaceName(InterfaceId intfId, char * nameBuf, size_t nameBufSize)
+CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
 {
-    if (intfId != INET_NULL_INTERFACEID)
+    if (mPlatformInterface)
     {
         char intfName[IF_NAMESIZE];
-        if (if_indextoname(intfId, intfName) == nullptr)
+        if (if_indextoname(mPlatformInterface, intfName) == nullptr)
+        {
             return CHIP_ERROR_POSIX(errno);
-        if (strlen(intfName) >= nameBufSize)
-            return CHIP_ERROR_NO_MEMORY;
-        strcpy(nameBuf, intfName);
+        }
+        size_t nameLength = strlen(intfName);
+        if (nameLength >= nameBufSize)
+        {
+            return CHIP_ERROR_BUFFER_TOO_SMALL;
+        }
+        strncpy(nameBuf, intfName, nameLength + 1);
         return CHIP_NO_ERROR;
     }
-
     if (nameBufSize < 1)
-        return CHIP_ERROR_NO_MEMORY;
-
+    {
+        return CHIP_ERROR_BUFFER_TOO_SMALL;
+    }
     nameBuf[0] = 0;
     return CHIP_NO_ERROR;
 }
 
-DLL_EXPORT CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId)
+CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
 {
-    intfId = if_nametoindex(intfName);
+    unsigned int intfId = if_nametoindex(intfName);
+    interface           = InterfaceId(intfId);
     if (intfId == 0)
+    {
         return (errno == ENXIO) ? INET_ERROR_UNKNOWN_INTERFACE : CHIP_ERROR_POSIX(errno);
+    }
     return CHIP_NO_ERROR;
 }
 
@@ -532,7 +528,6 @@
 
 bool InterfaceIterator::Next()
 {
-
     if (mIntfArray == nullptr)
     {
 #if __ANDROID__ && __ANDROID_API__ < 24
@@ -552,13 +547,13 @@
 
 InterfaceId InterfaceIterator::GetInterfaceId()
 {
-    return (HasCurrent()) ? mIntfArray[mCurIntf].if_index : INET_NULL_INTERFACEID;
+    return HasCurrent() ? InterfaceId(mIntfArray[mCurIntf].if_index) : InterfaceId::Null();
 }
 
 CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
 {
     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
-    VerifyOrReturnError(strlen(mIntfArray[mCurIntf].if_name) < nameBufSize, CHIP_ERROR_NO_MEMORY);
+    VerifyOrReturnError(strlen(mIntfArray[mCurIntf].if_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL);
     strncpy(nameBuf, mIntfArray[mCurIntf].if_name, nameBufSize);
     return CHIP_NO_ERROR;
 }
@@ -593,7 +588,6 @@
             mIntfFlags       = intfData.ifr_flags;
             mIntfFlagsCached = true;
         }
-        CloseIOCTLSocket();
     }
 
     return mIntfFlags;
@@ -656,12 +650,7 @@
 
 IPAddress InterfaceAddressIterator::GetAddress()
 {
-    if (HasCurrent())
-    {
-        return IPAddress::FromSockAddr(*mCurAddr->ifa_addr);
-    }
-
-    return IPAddress::Any;
+    return HasCurrent() ? IPAddress::FromSockAddr(*mCurAddr->ifa_addr) : IPAddress::Any;
 }
 
 uint8_t InterfaceAddressIterator::GetPrefixLength()
@@ -690,73 +679,63 @@
 
 InterfaceId InterfaceAddressIterator::GetInterfaceId()
 {
-    if (HasCurrent())
-    {
-        return if_nametoindex(mCurAddr->ifa_name);
-    }
-    return INET_NULL_INTERFACEID;
+    return HasCurrent() ? InterfaceId(if_nametoindex(mCurAddr->ifa_name)) : InterfaceId::Null();
 }
 
 CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
 {
     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
-    VerifyOrReturnError(strlen(mCurAddr->ifa_name) < nameBufSize, CHIP_ERROR_NO_MEMORY);
+    VerifyOrReturnError(strlen(mCurAddr->ifa_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL);
     strncpy(nameBuf, mCurAddr->ifa_name, nameBufSize);
     return CHIP_NO_ERROR;
 }
 
 bool InterfaceAddressIterator::IsUp()
 {
-    if (HasCurrent())
-    {
-        return (mCurAddr->ifa_flags & IFF_UP) != 0;
-    }
-    return false;
+    return HasCurrent() && (mCurAddr->ifa_flags & IFF_UP) != 0;
 }
 
 bool InterfaceAddressIterator::SupportsMulticast()
 {
-    if (HasCurrent())
-    {
-        return (mCurAddr->ifa_flags & IFF_MULTICAST) != 0;
-    }
-    return false;
+    return HasCurrent() && (mCurAddr->ifa_flags & IFF_MULTICAST) != 0;
 }
 
 bool InterfaceAddressIterator::HasBroadcastAddress()
 {
-    if (HasCurrent())
-    {
-        return (mCurAddr->ifa_flags & IFF_BROADCAST) != 0;
-    }
-    return false;
+    return HasCurrent() && (mCurAddr->ifa_flags & IFF_BROADCAST) != 0;
 }
 
 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
 
 #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
 
-DLL_EXPORT CHIP_ERROR GetInterfaceName(InterfaceId intfId, char * nameBuf, size_t nameBufSize)
+CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
 {
-    if (intfId != INET_NULL_INTERFACEID)
+    if (mPlatformInterface)
     {
-        net_if * currentInterface = net_if_get_by_index(intfId);
+        net_if * currentInterface = net_if_get_by_index(mPlatformInterface);
         if (!currentInterface)
+        {
             return CHIP_ERROR_INCORRECT_STATE;
+        }
         const char * name = net_if_get_device(currentInterface)->name;
-        if (strlen(name) >= nameBufSize)
-            return CHIP_ERROR_NO_MEMORY;
-        strcpy(nameBuf, name);
+        size_t nameLength = strlen(name);
+        if (nameLength >= nameBufSize)
+        {
+            return CHIP_ERROR_BUFFER_TOO_SMALL;
+        }
+        strncpy(nameBuf, name, nameLength + 1);
         return CHIP_NO_ERROR;
     }
-
     if (nameBufSize < 1)
-        return CHIP_ERROR_NO_MEMORY;
-
+    {
+        return CHIP_ERROR_BUFFER_TOO_SMALL;
+    }
     nameBuf[0] = 0;
     return CHIP_NO_ERROR;
 }
-DLL_EXPORT CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId)
+
+CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
 {
     int currentId = 0;
     net_if * currentInterface;
@@ -765,10 +744,11 @@
     {
         if (strcmp(net_if_get_device(currentInterface)->name, intfName) == 0)
         {
-            intfId = currentId;
+            interface = InterfaceId(currentId);
             return CHIP_NO_ERROR;
         }
     }
+    interface = InterfaceId::Null();
     return INET_ERROR_UNKNOWN_INTERFACE;
 }
 
@@ -787,13 +767,13 @@
 
 InterfaceId InterfaceIterator::GetInterfaceId(void)
 {
-    return HasCurrent() ? mCurrentId : INET_NULL_INTERFACEID;
+    return HasCurrent() ? InterfaceId(mCurrentId) : InterfaceId::Null();
 }
 
 CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
 {
     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
-    return ::chip::Inet::GetInterfaceName(mCurrentId, nameBuf, nameBufSize);
+    return InterfaceId(mCurrentId).GetInterfaceName(nameBuf, nameBufSize);
 }
 
 bool InterfaceIterator::IsUp()
@@ -825,8 +805,9 @@
     {
         if (mCurAddrIndex == -1) // first address for the current interface
         {
-            const net_if_config * config = net_if_get_config(net_if_get_by_index(mIntfIter.GetInterfaceId()));
-            mIpv6                        = config->ip.ipv6;
+            const net_if_config * config =
+                net_if_get_config(net_if_get_by_index(mIntfIter.GetInterfaceId().GetPlatformInterface()));
+            mIpv6 = config->ip.ipv6;
         }
 
         while (++mCurAddrIndex < NET_IF_MAX_IPV6_ADDR)
@@ -842,19 +823,14 @@
 
 IPAddress InterfaceAddressIterator::GetAddress()
 {
-    if (HasCurrent())
-    {
-        return IPAddress(mIpv6->unicast[mCurAddrIndex].address.in6_addr);
-    }
-
-    return IPAddress::Any;
+    return HasCurrent() ? IPAddress(mIpv6->unicast[mCurAddrIndex].address.in6_addr) : IPAddress::Any;
 }
 
 uint8_t InterfaceAddressIterator::GetPrefixLength()
 {
     if (HasCurrent())
     {
-        net_if * const iface              = net_if_get_by_index(mIntfIter.GetInterfaceId());
+        net_if * const iface              = net_if_get_by_index(mIntfIter.GetInterfaceId().GetPlatformInterface());
         net_if_ipv6_prefix * const prefix = net_if_ipv6_prefix_get(iface, &mIpv6->unicast[mCurAddrIndex].address.in6_addr);
         return prefix ? prefix->len : 128;
     }
@@ -863,11 +839,7 @@
 
 InterfaceId InterfaceAddressIterator::GetInterfaceId()
 {
-    if (HasCurrent())
-    {
-        return mIntfIter.GetInterfaceId();
-    }
-    return INET_NULL_INTERFACEID;
+    return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null();
 }
 
 CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
@@ -878,29 +850,17 @@
 
 bool InterfaceAddressIterator::IsUp()
 {
-    if (HasCurrent())
-    {
-        return mIntfIter.IsUp();
-    }
-    return false;
+    return HasCurrent() && mIntfIter.IsUp();
 }
 
 bool InterfaceAddressIterator::SupportsMulticast()
 {
-    if (HasCurrent())
-    {
-        return mIntfIter.SupportsMulticast();
-    }
-    return false;
+    return HasCurrent() && mIntfIter.SupportsMulticast();
 }
 
 bool InterfaceAddressIterator::HasBroadcastAddress()
 {
-    if (HasCurrent())
-    {
-        return mIntfIter.HasBroadcastAddress();
-    }
-    return false;
+    return HasCurrent() && mIntfIter.HasBroadcastAddress();
 }
 
 #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
diff --git a/src/inet/InetInterface.h b/src/inet/InetInterface.h
index c5e512f..1de4b17 100644
--- a/src/inet/InetInterface.h
+++ b/src/inet/InetInterface.h
@@ -59,91 +59,98 @@
 class IPPrefix;
 
 /**
- * @typedef     InterfaceId
- *
- * @brief       Indicator for system network interfaces.
- *
- * @details
- *  Portability depends on never witnessing this alias. It may be replaced by a
- *  concrete opaque class in the future.
- *
- *  Note Well: The term "interface identifier" also conventionally refers to
- *  the lower 64 bits of an IPv6 address in all the relevant IETF standards
- *  documents, where the abbreviation "IID" is often used. In this text, the
- *  term "interface indicator" refers to values of this type alias.
+ * Indicator for system network interfaces.
  */
-
+class InterfaceId
+{
+public:
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
-typedef struct netif * InterfaceId;
-#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+    using PlatformType                       = struct netif *;
+    static constexpr size_t kMaxIfNameLength = 13; // Names are formatted as %c%c%d
+#endif                                             // CHIP_SYSTEM_CONFIG_USE_LWIP
 
-#if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
-typedef unsigned InterfaceId;
+#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
+    using PlatformType                       = unsigned int;
+    static constexpr size_t kMaxIfNameLength = IF_NAMESIZE;
 #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
 
 #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
-typedef int InterfaceId;
+    using PlatformType                       = int;
+    static constexpr size_t kMaxIfNameLength = Z_DEVICE_MAX_NAME_LEN;
 #endif
 
-/**
- * @def     INET_NULL_INTERFACEID
- *
- * @brief   The distinguished value indicating no network interface.
- *
- * @details
- *  Note Well: This is not the indicator of a "null" network interface. This
- *  value can be used to indicate the absence of a specific network interface,
- *  or to specify that any applicable network interface is acceptable. Usage
- *  varies depending on context.
- */
+public:
+    ~InterfaceId() = default;
 
+    constexpr InterfaceId() : mPlatformInterface(kPlatformNull) {}
+    explicit constexpr InterfaceId(PlatformType interface) : mPlatformInterface(interface) {}
+
+    constexpr InterfaceId(const InterfaceId & other) : mPlatformInterface(other.mPlatformInterface) {}
+    constexpr InterfaceId & operator=(const InterfaceId & other)
+    {
+        mPlatformInterface = other.mPlatformInterface;
+        return *this;
+    }
+
+    static constexpr InterfaceId Null() { return InterfaceId(); }
+
+    constexpr bool operator==(const InterfaceId & other) const { return mPlatformInterface == other.mPlatformInterface; }
+    constexpr bool operator!=(const InterfaceId & other) const { return mPlatformInterface != other.mPlatformInterface; }
+
+    /**
+     * Test for inequivalence with the null interface.
+     */
+    bool IsPresent() const { return mPlatformInterface != kPlatformNull; }
+
+    /**
+     * Get the underlying platform representation of the interface.
+     */
+    PlatformType GetPlatformInterface() const { return mPlatformInterface; }
+
+    /**
+     * Get the name of the network interface
+     *
+     * @param[in]   nameBuf     Region of memory to write the interface name.
+     * @param[in]   nameBufSize Size of the region denoted by \c nameBuf.
+     *
+     * @retval  CHIP_NO_ERROR               Successful result, interface name written.
+     * @retval  CHIP_ERROR_BUFFER_TOO_SMALL Buffer is too small for the interface name.
+     * @retval  other                       Another system or platform error.
+     *
+     *  Writes the name of the network interface as a \c NUL terminated text string at \c nameBuf.
+     *  The name of the unspecified network interface is the empty string.
+     */
+    CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) const;
+
+    /**
+     * Search the list of network interfaces for the indicated name.
+     *
+     * @param[in]   intfName    Name of the network interface to find.
+     * @param[out]  intfId      Indicator of the network interface to assign.
+     *
+     * @retval  CHIP_NO_ERROR                   Success, network interface indicated.
+     * @retval  INET_ERROR_UNKNOWN_INTERFACE    No network interface found.
+     * @retval  other                           Another system or platform error.
+     *
+     * @note
+     *  On LwIP, this function must be called with the LwIP stack lock acquired.
+     */
+    static CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId);
+
+private:
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
-#define INET_NULL_INTERFACEID NULL
+    static constexpr PlatformType kPlatformNull = nullptr;
 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
 
-#if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS || CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
-#define INET_NULL_INTERFACEID 0
-#endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS || CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
+#if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
+    static constexpr PlatformType kPlatformNull = 0;
+#endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
 
-/**
- * @brief   Test \c ID for inequivalence with \c INET_NULL_INTERFACEID
- *
- * @details
- *  This macro resolves to an expression that evaluates \c false if the
- *  argument is equivalent to \c INET_NULL_INTERFACEID and \c true otherwise.
- */
-#define IsInterfaceIdPresent(intfId) ((intfId) != INET_NULL_INTERFACEID)
-
-/**
- * Get the name of the network interface
- *
- * @param[in]   intfId      A network interface.
- * @param[in]   nameBuf     Region of memory to write the interface name.
- * @param[in]   nameBufSize Size of the region denoted by \c nameBuf.
- *
- * @retval  CHIP_NO_ERROR               Successful result, interface name written.
- * @retval  CHIP_ERROR_BUFFER_TOO_SMALL Buffer is too small for the interface name.
- * @retval  other                       Another system or platform error.
- *
- *  Writes the name of the network interface as a \c NUL terminated text string at \c nameBuf.
- *  The name of the unspecified network interface is the empty string.
- */
-extern CHIP_ERROR GetInterfaceName(InterfaceId intfId, char * nameBuf, size_t nameBufSize);
-
-/**
- * Search the list of network interfaces for the indicated name.
- *
- * @param[in]   intfName    Name of the network interface to find.
- * @param[out]  intfId      Indicator of the network interface to assign.
- *
- * @retval  CHIP_NO_ERROR                   Success, network interface indicated.
- * @retval  INET_ERROR_UNKNOWN_INTERFACE    No network interface found.
- * @retval  other                           Another system or platform error.
- *
- * @note
- *  On LwIP, this function must be called with the LwIP stack lock acquired.
- */
-extern CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId);
+#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
+    static constexpr PlatformType kPlatformNull = 0;
+#endif
+    PlatformType mPlatformInterface;
+};
 
 /**
  * Compute a prefix length from a variable-length netmask.
@@ -211,21 +218,16 @@
     bool Next();
 
     /**
-     * NetworkInterface InterfaceIterator::GetInterfaceId(void)
+     * InterfaceId InterfaceIterator::GetInterfaceId(void)
      *
      * Returns the network interface id at the current iterator position.
      *
      * @retval  id                   The current network interface id.
-     * @retval  NetworkInterface()   If advanced beyond the end of the list.
+     * @retval  InterfaceId()   If advanced beyond the end of the list.
      */
     InterfaceId GetInterfaceId();
 
     /**
-     * @brief    Deprecated alias for \c GetInterfaceId(void)
-     */
-    InterfaceId GetInterface() { return GetInterfaceId(); }
-
-    /**
      * Get the name of the current network interface
      *
      * @param[in]   nameBuf     Region of memory to write the interface name.
@@ -264,19 +266,6 @@
      */
     bool HasBroadcastAddress();
 
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
-    static constexpr size_t kMaxIfNameLength = 13; // Names are formatted as %c%c%d
-#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
-    static constexpr size_t kMaxIfNameLength = IF_NAMESIZE;
-#elif CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
-    static constexpr size_t kMaxIfNameLength = Z_DEVICE_MAX_NAME_LEN;
-#elif defined(IFNAMSIZ)
-    static constexpr size_t kMaxIfNameLength = IFNAMSIZ;
-#else
-    // No constant available here - set some reasonable size
-    static constexpr size_t kMaxIfNameLength = 33;
-#endif
-
 protected:
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
     struct netif * mCurNetif;
@@ -292,8 +281,8 @@
 #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
 
 #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
-    InterfaceId mCurrentId     = 1;
-    net_if * mCurrentInterface = nullptr;
+    InterfaceId::PlatformType mCurrentId = 1;
+    net_if * mCurrentInterface           = nullptr;
 #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
 };
 
@@ -393,11 +382,6 @@
     uint8_t GetPrefixLength();
 
     /**
-     * @brief    Deprecated alias for \c GetPrefixLength(void)
-     */
-    uint8_t GetIPv6PrefixLength() { return GetPrefixLength(); }
-
-    /**
      * @fn       void InterfaceAddressIterator::GetAddressWithPrefix(IPPrefix & addrWithPrefix)
      *
      * @brief    Returns an IPPrefix containing the address and prefix length
@@ -406,22 +390,17 @@
     void GetAddressWithPrefix(IPPrefix & addrWithPrefix);
 
     /**
-     * @fn      NetworkInterface InterfaceAddressIterator::GetInterfaceId(void)
+     * @fn      InterfaceId InterfaceAddressIterator::GetInterfaceId(void)
      *
      * @brief   Returns the network interface id associated with the current
      *          interface address.
      *
-     * @return  the interface id or \c NetworkInterface() if the iterator
+     * @return  the interface id or \c InterfaceId() if the iterator
      *          is positioned beyond the end of the address list.
      */
     InterfaceId GetInterfaceId();
 
     /**
-     * @brief    Deprecated alias for \c GetInterfaceId(void)
-     */
-    InterfaceId GetInterface() { return GetInterfaceId(); }
-
-    /**
      * @fn      CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
      *
      * @brief   Get the name of the network interface associated with the
@@ -506,7 +485,7 @@
 
 inline InterfaceId InterfaceIterator::GetInterfaceId(void)
 {
-    return mCurNetif;
+    return InterfaceId(mCurNetif);
 }
 
 inline InterfaceAddressIterator::InterfaceAddressIterator(void)
diff --git a/src/inet/InetLayer.cpp b/src/inet/InetLayer.cpp
index b07d14a..9cb196b 100644
--- a/src/inet/InetLayer.cpp
+++ b/src/inet/InetLayer.cpp
@@ -345,20 +345,20 @@
 /**
  *  Get the link local IPv6 address for a specified link or interface.
  *
- *  @param[in]    link    The interface for which the link local IPv6
- *                        address is being sought.
+ *  @param[in]    interface The interface for which the link local IPv6
+ *                          address is being sought.
  *
  *  @param[out]   llAddr  The link local IPv6 address for the link.
  *
  *  @retval    #CHIP_ERROR_NOT_IMPLEMENTED      If IPv6 is not supported.
  *  @retval    #CHIP_ERROR_INVALID_ARGUMENT     If the link local address
- *                                              is NULL.
+ *                                              is nullptr.
  *  @retval    #INET_ERROR_ADDRESS_NOT_FOUND    If the link does not have
  *                                              any address configured.
  *  @retval    #CHIP_NO_ERROR                   On success.
  *
  */
-CHIP_ERROR InetLayer::GetLinkLocalAddr(InterfaceId link, IPAddress * llAddr)
+CHIP_ERROR InetLayer::GetLinkLocalAddr(InterfaceId interface, IPAddress * llAddr)
 {
     VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
 
@@ -367,6 +367,7 @@
     return CHIP_ERROR_NOT_IMPLEMENTED;
 #endif //! LWIP_IPV6
 
+    struct netif * link = interface.GetPlatformInterface();
     for (struct netif * intf = netif_list; intf != NULL; intf = intf->next)
     {
         if ((link != NULL) && (link != intf))
@@ -399,7 +400,7 @@
         if (ifaddr_iter->ifa_addr != nullptr)
         {
             if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) &&
-                ((link == INET_NULL_INTERFACEID) || (if_nametoindex(ifaddr_iter->ifa_name) == link)))
+                (!interface.IsPresent() || (if_nametoindex(ifaddr_iter->ifa_name) == interface.GetPlatformInterface())))
             {
                 struct in6_addr * sin6_addr = &(reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr;
                 if (sin6_addr->s6_addr[0] == 0xfe && (sin6_addr->s6_addr[1] & 0xc0) == 0x80) // Link Local Address
@@ -414,7 +415,7 @@
 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
 
 #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
-    net_if * const iface = (link == INET_NULL_INTERFACEID) ? net_if_get_default() : net_if_get_by_index(link);
+    net_if * const iface = interface.IsPresent() ? net_if_get_by_index(interface.GetPlatformInterface()) : net_if_get_default();
     VerifyOrReturnError(iface != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);
 
     in6_addr * const ip6_addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED);
@@ -508,8 +509,8 @@
 
 /**
  *  Get the interface identifier for the specified IP address. If the
- *  interface identifier cannot be derived it is set to the
- *  #INET_NULL_INTERFACEID.
+ *  interface identifier cannot be derived it is set to the default
+ *  InterfaceId.
  *
  *  @note
  *    This function fetches the first interface (from the configured list
@@ -531,12 +532,12 @@
         IPAddress curAddr = addrIter.GetAddress();
         if (addr == curAddr)
         {
-            intfId = addrIter.GetInterface();
+            intfId = addrIter.GetInterfaceId();
             return CHIP_NO_ERROR;
         }
     }
 
-    intfId = INET_NULL_INTERFACEID;
+    intfId = InterfaceId::Null();
 
     return CHIP_NO_ERROR;
 }
@@ -566,7 +567,7 @@
 #endif // INET_CONFIG_ENABLE_IPV4
         if (addrPrefix.IPAddr.IsIPv6LinkLocal())
             continue;
-        addrPrefix.Length = ifAddrIter.GetIPv6PrefixLength();
+        addrPrefix.Length = ifAddrIter.GetPrefixLength();
         if (addrPrefix.MatchAddress(addr))
             return true;
     }
@@ -674,7 +675,7 @@
 {
     SrcAddress  = IPAddress::Any;
     DestAddress = IPAddress::Any;
-    Interface   = INET_NULL_INTERFACEID;
+    Interface   = InterfaceId::Null();
     SrcPort     = 0;
     DestPort    = 0;
 }
diff --git a/src/inet/TCPEndPoint.cpp b/src/inet/TCPEndPoint.cpp
index 5681619..91c70fd 100644
--- a/src/inet/TCPEndPoint.cpp
+++ b/src/inet/TCPEndPoint.cpp
@@ -192,7 +192,7 @@
     // As a work-around, if the destination is an IPv6 link-local address, we bind the PCB
     // to the link local address associated with the source interface; however this is only
     // viable if the endpoint hasn't already been bound.
-    if (intfId != INET_NULL_INTERFACEID)
+    if (intfId.IsPresent())
     {
         IPAddress intfLLAddr;
         InetLayer & lInetLayer = Layer();
@@ -328,7 +328,7 @@
     // TODO: Does netif_get_by_index(mTCP->netif_idx) do the right thing?  I
     // can't quite tell whether LwIP supports a specific interface id for TCP at
     // all.  For now just claim no particular interface id.
-    *retInterface = INET_NULL_INTERFACEID;
+    *retInterface = InterfaceId::Null();
     return CHIP_NO_ERROR;
 }
 
@@ -1258,7 +1258,7 @@
 
     ReturnErrorOnFailure(GetSocket(addrType));
 
-    if (intfId == INET_NULL_INTERFACEID)
+    if (!intfId.IsPresent())
     {
         // The behavior when connecting to an IPv6 link-local address without specifying an outbound
         // interface is ambiguous. So prevent it in all cases.
@@ -1280,7 +1280,7 @@
             struct ::ifreq ifr;
             memset(&ifr, 0, sizeof(ifr));
 
-            ReturnErrorOnFailure(GetInterfaceName(intfId, ifr.ifr_name, sizeof(ifr.ifr_name)));
+            ReturnErrorOnFailure(intfId.GetInterfaceName(ifr.ifr_name, sizeof(ifr.ifr_name)));
 
             // Attempt to bind to the interface using SO_BINDTODEVICE which requires privileged access.
             // If the permission is denied(EACCES) because CHIP is running in a context
@@ -1325,7 +1325,7 @@
         sa.in6.sin6_port     = htons(port);
         sa.in6.sin6_flowinfo = 0;
         sa.in6.sin6_addr     = addr.ToIPv6();
-        sa.in6.sin6_scope_id = intfId;
+        sa.in6.sin6_scope_id = intfId.GetPlatformInterface();
         sockaddrsize         = sizeof(sockaddr_in6);
         sockaddrptr          = reinterpret_cast<const sockaddr *>(&sa.in6);
     }
@@ -1439,12 +1439,12 @@
     {
         if (IPAddress(sa.in6.sin6_addr).IsIPv6LinkLocal())
         {
-            *retInterface = sa.in6.sin6_scope_id;
+            *retInterface = InterfaceId(sa.in6.sin6_scope_id);
         }
         else
         {
             // TODO: Is there still a meaningful interface id in this case?
-            *retInterface = INET_NULL_INTERFACEID;
+            *retInterface = InterfaceId::Null();
         }
         return CHIP_NO_ERROR;
     }
@@ -1453,12 +1453,12 @@
     if (sa.any.sa_family == AF_INET)
     {
         // No interface id available for IPv4 sockets.
-        *retInterface = INET_NULL_INTERFACEID;
+        *retInterface = InterfaceId::Null();
         return CHIP_NO_ERROR;
     }
 #endif // INET_CONFIG_ENABLE_IPV4
 
-    *retInterface = INET_NULL_INTERFACEID;
+    *retInterface = InterfaceId::Null();
     return INET_ERROR_WRONG_ADDRESS_TYPE;
 }
 
@@ -1832,7 +1832,7 @@
     for (InterfaceAddressIterator addrIter; addrIter.HasCurrent(); addrIter.Next())
     {
         const IPAddress curAddr     = addrIter.GetAddress();
-        const InterfaceId curIntfId = addrIter.GetInterface();
+        const InterfaceId curIntfId = addrIter.GetInterfaceId();
 
         if (curIntfId == intfId)
         {
diff --git a/src/inet/TCPEndPoint.h b/src/inet/TCPEndPoint.h
index 0dcad95..77eab74 100644
--- a/src/inet/TCPEndPoint.h
+++ b/src/inet/TCPEndPoint.h
@@ -140,7 +140,7 @@
      *      destination \c addr (with \c intfId used as the scope
      *      identifier for IPv6 link-local destinations) and \c port.
      */
-    CHIP_ERROR Connect(const IPAddress & addr, uint16_t port, InterfaceId intfId = INET_NULL_INTERFACEID);
+    CHIP_ERROR Connect(const IPAddress & addr, uint16_t port, InterfaceId intfId = InterfaceId::Null());
 
     /**
      * @brief   Extract IP address and TCP port of remote endpoint.
diff --git a/src/inet/UDPEndPoint.cpp b/src/inet/UDPEndPoint.cpp
index e6ff19e..39c3d94 100644
--- a/src/inet/UDPEndPoint.cpp
+++ b/src/inet/UDPEndPoint.cpp
@@ -93,7 +93,7 @@
     CHIP_ERROR res = CHIP_NO_ERROR;
 
 #if HAVE_LWIP_UDP_BIND_NETIF
-    if (!IsInterfaceIdPresent(intfId))
+    if (!intfId.IsPresent())
         udp_bind_netif(aUDP, NULL);
     else
     {
@@ -105,7 +105,7 @@
             udp_bind_netif(aUDP, netifp);
     }
 #else
-    if (!IsInterfaceIdPresent(intfId))
+    if (!intfId.IsPresent())
         aUDP->intf_filter = NULL;
     else
     {
@@ -202,9 +202,9 @@
 InterfaceId UDPEndPoint::GetBoundInterface()
 {
 #if HAVE_LWIP_UDP_BIND_NETIF
-    return netif_get_by_index(mUDP->netif_idx);
+    return InterfaceId(netif_get_by_index(mUDP->netif_idx));
 #else
-    return mUDP->intf_filter;
+    return InterfaceId(mUDP->intf_filter);
 #endif
 }
 
@@ -283,8 +283,9 @@
         ip_addr_copy(mUDP->local_ip, lwipSrcAddr);
     }
 
-    if (intfId != INET_NULL_INTERFACEID)
-        lwipErr = udp_sendto_if(mUDP, System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(msg), &lwipDestAddr, destPort, intfId);
+    if (intfId.IsPresent())
+        lwipErr = udp_sendto_if(mUDP, System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(msg), &lwipDestAddr, destPort,
+                                intfId.GetPlatformInterface());
     else
         lwipErr = udp_sendto(mUDP, System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(msg), &lwipDestAddr, destPort);
 
@@ -305,7 +306,7 @@
             ipX_addr_copy(mUDP->local_ip, *ip6_2_ipX(&lwipSrcAddr));
         }
 
-        if (intfId != INET_NULL_INTERFACEID)
+        if (intfId.IsPresent())
             lwipErr =
                 udp_sendto_if_ip6(mUDP, System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(msg), &lwipDestAddr, destPort, intfId);
         else
@@ -325,7 +326,7 @@
             ipX_addr_copy(mUDP->local_ip, *ip_2_ipX(&lwipSrcAddr));
         }
 
-        if (intfId != INET_NULL_INTERFACEID)
+        if (intfId.IsPresent())
             lwipErr = udp_sendto_if(mUDP, System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(msg), &lwipDestAddr, destPort, intfId);
         else
             lwipErr = udp_sendto(mUDP, System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(msg), &lwipDestAddr, destPort);
@@ -502,7 +503,7 @@
 #endif // INET_CONFIG_ENABLE_IPV4
 #endif // LWIP_VERSION_MAJOR <= 1
 
-        pktInfo->Interface = ip_current_netif();
+        pktInfo->Interface = InterfaceId(ip_current_netif());
         pktInfo->SrcPort   = port;
         pktInfo->DestPort  = pcb->local_port;
     }
@@ -658,7 +659,7 @@
     nw_parameters_configure_protocol_block_t configure_tls;
     nw_parameters_t parameters;
 
-    if (intfId != INET_NULL_INTERFACEID)
+    if (intfId.IsPresent())
     {
         return CHIP_ERROR_NOT_IMPLEMENTED;
     }
@@ -679,7 +680,7 @@
 
 InterfaceId UDPEndPoint::GetBoundInterface()
 {
-    return INET_NULL_INTERFACEID;
+    return InterfaceId::Null();
 }
 
 uint16_t UDPEndPoint::GetBoundPort()
diff --git a/src/inet/UDPEndPoint.h b/src/inet/UDPEndPoint.h
index c5b522f..a19a05b 100644
--- a/src/inet/UDPEndPoint.h
+++ b/src/inet/UDPEndPoint.h
@@ -78,7 +78,7 @@
      * @retval  INET_ERROR_WRONG_ADDRESS_TYPE   \c addrType is \c IPAddressType::kAny, or not equal to the type of \c addr.
      * @retval  other                           Another system or platform error
      */
-    CHIP_ERROR Bind(IPAddressType addrType, const IPAddress & addr, uint16_t port, InterfaceId intfId = INET_NULL_INTERFACEID);
+    CHIP_ERROR Bind(IPAddressType addrType, const IPAddress & addr, uint16_t port, InterfaceId intfId = InterfaceId::Null());
 
     /**
      * Bind the endpoint to a network interface.
@@ -146,7 +146,7 @@
      * @retval  other                               Another system or platform error.
      */
     CHIP_ERROR SendTo(const IPAddress & addr, uint16_t port, chip::System::PacketBufferHandle && msg,
-                      InterfaceId intfId = INET_NULL_INTERFACEID);
+                      InterfaceId intfId = InterfaceId::Null());
 
     /**
      * Send a UDP message to a specified destination.
diff --git a/src/inet/tests/TestInetCommonPosix.cpp b/src/inet/tests/TestInetCommonPosix.cpp
index 4895ac3..27b1555 100644
--- a/src/inet/tests/TestInetCommonPosix.cpp
+++ b/src/inet/tests/TestInetCommonPosix.cpp
@@ -174,7 +174,7 @@
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
 static void PrintNetworkState()
 {
-    char intfName[chip::Inet::InterfaceIterator::kMaxIfNameLength];
+    char intfName[chip::Inet::InterfaceId::kMaxIfNameLength];
 
     for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
     {
@@ -187,7 +187,7 @@
 
         TapInterface * tapIF = &(sTapIFs[j]);
 #endif // CHIP_TARGET_STYLE_UNIX
-        GetInterfaceName(netIF, intfName, sizeof(intfName));
+        InterfaceId(netIF).GetInterfaceName(intfName, sizeof(intfName));
 
         printf("LwIP interface ready\n");
         printf("  Interface Name: %s\n", intfName);
diff --git a/src/inet/tests/TestInetEndPoint.cpp b/src/inet/tests/TestInetEndPoint.cpp
index 8e8aa81..48bd065 100644
--- a/src/inet/tests/TestInetEndPoint.cpp
+++ b/src/inet/tests/TestInetEndPoint.cpp
@@ -127,23 +127,23 @@
 {
     InterfaceIterator intIterator;
     InterfaceAddressIterator addrIterator;
-    char intName[chip::Inet::InterfaceIterator::kMaxIfNameLength];
+    char intName[chip::Inet::InterfaceId::kMaxIfNameLength];
     InterfaceId intId;
     IPAddress addr;
     IPPrefix addrWithPrefix;
     CHIP_ERROR err;
 
-    err = InterfaceNameToId("0", intId);
+    err = InterfaceId::InterfaceNameToId("0", intId);
     NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
 
-    err = GetInterfaceName(INET_NULL_INTERFACEID, intName, 0);
-    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_NO_MEMORY);
+    err = InterfaceId::Null().GetInterfaceName(intName, 0);
+    NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
 
-    err = GetInterfaceName(INET_NULL_INTERFACEID, intName, sizeof(intName));
+    err = InterfaceId::Null().GetInterfaceName(intName, sizeof(intName));
     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR && intName[0] == '\0');
 
     err = gInet.GetInterfaceFromAddr(addr, intId);
-    NL_TEST_ASSERT(inSuite, intId == INET_NULL_INTERFACEID);
+    NL_TEST_ASSERT(inSuite, !intId.IsPresent());
 
     err = gInet.GetLinkLocalAddr(intId, nullptr);
     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INVALID_ARGUMENT);
@@ -151,16 +151,16 @@
     printf("    Interfaces:\n");
     for (; intIterator.HasCurrent(); intIterator.Next())
     {
-        intId = intIterator.GetInterface();
-        NL_TEST_ASSERT(inSuite, intId != INET_NULL_INTERFACEID);
+        intId = intIterator.GetInterfaceId();
+        NL_TEST_ASSERT(inSuite, intId.IsPresent());
         memset(intName, 42, sizeof(intName));
         err = intIterator.GetInterfaceName(intName, sizeof(intName));
         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
         printf("     interface id: 0x%" PRIxPTR ", interface name: %s, interface state: %s, %s multicast, %s broadcast addr\n",
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
-               reinterpret_cast<uintptr_t>(intId),
+               reinterpret_cast<uintptr_t>(intId.GetPlatformInterface()),
 #else
-               static_cast<uintptr_t>(intId),
+               static_cast<uintptr_t>(intId.GetPlatformInterface()),
 #endif
                intName, intIterator.IsUp() ? "UP" : "DOWN", intIterator.SupportsMulticast() ? "supports" : "no",
                intIterator.HasBroadcastAddress() ? "has" : "no");
@@ -169,7 +169,7 @@
         gInet.MatchLocalIPv6Subnet(addr);
     }
     NL_TEST_ASSERT(inSuite, !intIterator.Next());
-    NL_TEST_ASSERT(inSuite, intIterator.GetInterface() == INET_NULL_INTERFACEID);
+    NL_TEST_ASSERT(inSuite, intIterator.GetInterfaceId() == InterfaceId::Null());
     NL_TEST_ASSERT(inSuite, intIterator.GetInterfaceName(intName, sizeof(intName)) == CHIP_ERROR_INCORRECT_STATE);
     NL_TEST_ASSERT(inSuite, !intIterator.SupportsMulticast());
     NL_TEST_ASSERT(inSuite, !intIterator.HasBroadcastAddress());
@@ -182,7 +182,7 @@
         char addrStr[80];
         addrWithPrefix.IPAddr.ToString(addrStr);
         intId = addrIterator.GetInterfaceId();
-        NL_TEST_ASSERT(inSuite, intId != INET_NULL_INTERFACEID);
+        NL_TEST_ASSERT(inSuite, intId.IsPresent());
         memset(intName, 42, sizeof(intName));
         err = addrIterator.GetInterfaceName(intName, sizeof(intName));
         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
@@ -191,9 +191,9 @@
                ", interface name: %s, interface state: %s, %s multicast, %s broadcast addr\n",
                addrStr, addrWithPrefix.Length,
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
-               reinterpret_cast<uintptr_t>(intId),
+               reinterpret_cast<uintptr_t>(intId.GetPlatformInterface()),
 #else
-               static_cast<uintptr_t>(intId),
+               static_cast<uintptr_t>(intId.GetPlatformInterface()),
 #endif
                intName, addrIterator.IsUp() ? "UP" : "DOWN", addrIterator.SupportsMulticast() ? "supports" : "no",
                addrIterator.HasBroadcastAddress() ? "has" : "no");
@@ -201,7 +201,7 @@
     NL_TEST_ASSERT(inSuite, !addrIterator.Next());
     addrIterator.GetAddressWithPrefix(addrWithPrefix);
     NL_TEST_ASSERT(inSuite, addrWithPrefix.IsZero());
-    NL_TEST_ASSERT(inSuite, addrIterator.GetInterface() == INET_NULL_INTERFACEID);
+    NL_TEST_ASSERT(inSuite, addrIterator.GetInterfaceId() == InterfaceId::Null());
     NL_TEST_ASSERT(inSuite, addrIterator.GetInterfaceName(intName, sizeof(intName)) == CHIP_ERROR_INCORRECT_STATE);
     NL_TEST_ASSERT(inSuite, !addrIterator.SupportsMulticast());
     NL_TEST_ASSERT(inSuite, !addrIterator.HasBroadcastAddress());
@@ -229,7 +229,7 @@
     err = gInet.NewTCPEndPoint(&testTCPEP1);
     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
 
-    err = gInet.GetLinkLocalAddr(INET_NULL_INTERFACEID, &addr);
+    err = gInet.GetLinkLocalAddr(InterfaceId::Null(), &addr);
     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
     err = gInet.GetInterfaceFromAddr(addr, intId);
     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
diff --git a/src/inet/tests/TestInetLayer.cpp b/src/inet/tests/TestInetLayer.cpp
index ee3ff88..5a2ca21 100644
--- a/src/inet/tests/TestInetLayer.cpp
+++ b/src/inet/tests/TestInetLayer.cpp
@@ -277,7 +277,7 @@
 
     if (gInterfaceName != nullptr)
     {
-        lStatus = InterfaceNameToId(gInterfaceName, gInterfaceId);
+        lStatus = InterfaceId::InterfaceNameToId(gInterfaceName, gInterfaceId);
         if (lStatus != CHIP_NO_ERROR)
         {
             PrintArgError("%s: unknown network interface %s\n", kToolName, gInterfaceName);
@@ -823,7 +823,7 @@
         lStatus = gInet.NewUDPEndPoint(&sUDPIPEndPoint);
         INET_FAIL_ERROR(lStatus, "InetLayer::NewUDPEndPoint failed");
 
-        if (IsInterfaceIdPresent(gInterfaceId))
+        if (gInterfaceId.IsPresent())
         {
             lStatus = sUDPIPEndPoint->BindInterface(lIPAddressType, gInterfaceId);
             INET_FAIL_ERROR(lStatus, "UDPEndPoint::BindInterface failed");
diff --git a/src/inet/tests/TestInetLayerCommon.cpp b/src/inet/tests/TestInetLayerCommon.cpp
index fdbbfec..609acf9 100644
--- a/src/inet/tests/TestInetLayerCommon.cpp
+++ b/src/inet/tests/TestInetLayerCommon.cpp
@@ -85,7 +85,7 @@
 
 const char * gInterfaceName = nullptr;
 
-InterfaceId gInterfaceId = INET_NULL_INTERFACEID;
+InterfaceId gInterfaceId = InterfaceId::Null();
 
 uint16_t gSendSize = 59;
 
diff --git a/src/inet/tests/TestInetLayerMulticast.cpp b/src/inet/tests/TestInetLayerMulticast.cpp
index 7e2ad4d..eaaf6b4 100644
--- a/src/inet/tests/TestInetLayerMulticast.cpp
+++ b/src/inet/tests/TestInetLayerMulticast.cpp
@@ -288,7 +288,7 @@
 
     if (gInterfaceName != nullptr)
     {
-        lStatus = InterfaceNameToId(gInterfaceName, gInterfaceId);
+        lStatus = InterfaceId::InterfaceNameToId(gInterfaceName, gInterfaceId);
         if (lStatus != CHIP_NO_ERROR)
         {
             PrintArgError("%s: unknown network interface %s\n", kToolName, gInterfaceName);
@@ -300,7 +300,7 @@
     // If any multicast groups have been specified, ensure that a
     // network interface identifier has been specified and is valid.
 
-    if ((sGroupAddresses.mSize > 0) && !IsInterfaceIdPresent(gInterfaceId))
+    if ((sGroupAddresses.mSize > 0) && !gInterfaceId.IsPresent())
     {
         PrintArgError("%s: a network interface is required when specifying one or more multicast groups\n", kToolName);
         lSuccessful = false;
@@ -749,7 +749,7 @@
         lStatus = sUDPIPEndPoint->Bind(lIPAddressType, lAddress, kUDPPort);
         INET_FAIL_ERROR(lStatus, "UDPEndPoint::Bind failed");
 
-        if (IsInterfaceIdPresent(gInterfaceId))
+        if (gInterfaceId.IsPresent())
         {
             lStatus = sUDPIPEndPoint->BindInterface(lIPAddressType, gInterfaceId);
             INET_FAIL_ERROR(lStatus, "UDPEndPoint::BindInterface failed");
@@ -775,7 +775,7 @@
         GroupAddress & lGroupAddress  = sGroupAddresses.mAddresses[i];
         IPAddress & lMulticastAddress = lGroupAddress.mMulticastAddress;
 
-        if ((lEndPoint != nullptr) && IsInterfaceIdPresent(gInterfaceId))
+        if ((lEndPoint != nullptr) && gInterfaceId.IsPresent())
         {
             if (gOptFlags & kOptFlagUseIPv4)
             {
@@ -822,7 +822,7 @@
         GroupAddress & lGroupAddress  = sGroupAddresses.mAddresses[i];
         IPAddress & lMulticastAddress = lGroupAddress.mMulticastAddress;
 
-        if ((lEndPoint != nullptr) && IsInterfaceIdPresent(gInterfaceId))
+        if ((lEndPoint != nullptr) && gInterfaceId.IsPresent())
         {
             lMulticastAddress.ToString(lAddressBuffer, sizeof(lAddressBuffer));
 
diff --git a/src/lib/dnssd/AllInterfacesListenIterator.h b/src/lib/dnssd/AllInterfacesListenIterator.h
index f16a4ef..7366a3c 100644
--- a/src/lib/dnssd/AllInterfacesListenIterator.h
+++ b/src/lib/dnssd/AllInterfacesListenIterator.h
@@ -33,7 +33,7 @@
     {
         return false; // not a usable interface
     }
-    char name[chip::Inet::InterfaceIterator::kMaxIfNameLength];
+    char name[chip::Inet::InterfaceId::kMaxIfNameLength];
     if (iterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR)
     {
         ChipLogError(Discovery, "Failed to get interface name.");
diff --git a/src/lib/dnssd/Discovery_ImplPlatform.cpp b/src/lib/dnssd/Discovery_ImplPlatform.cpp
index 8280575..2402371 100644
--- a/src/lib/dnssd/Discovery_ImplPlatform.cpp
+++ b/src/lib/dnssd/Discovery_ImplPlatform.cpp
@@ -345,7 +345,7 @@
     service.mTextEntries   = textEntries;
     service.mTextEntrySize = textEntrySize;
     service.mPort          = params.GetPort();
-    service.mInterface     = INET_NULL_INTERFACEID;
+    service.mInterface     = Inet::InterfaceId::Null();
     service.mSubTypes      = subTypes;
     service.mSubTypeSize   = subTypeSize;
     service.mAddressType   = Inet::IPAddressType::kAny;
@@ -427,7 +427,7 @@
     service.mPort          = params.GetPort();
     service.mTextEntries   = txtEntries;
     service.mTextEntrySize = textEntrySize;
-    service.mInterface     = INET_NULL_INTERFACEID;
+    service.mInterface     = Inet::InterfaceId::Null();
     service.mAddressType   = Inet::IPAddressType::kAny;
     service.mSubTypes      = subTypes;
     service.mSubTypeSize   = subTypeSize;
@@ -489,7 +489,7 @@
     strncpy(service.mType, kOperationalServiceName, sizeof(service.mType));
     service.mProtocol    = DnssdServiceProtocol::kDnssdProtocolTcp;
     service.mAddressType = type;
-    return ChipDnssdResolve(&service, INET_NULL_INTERFACEID, HandleNodeIdResolve, this);
+    return ChipDnssdResolve(&service, Inet::InterfaceId::Null(), HandleNodeIdResolve, this);
 }
 
 void DiscoveryImplPlatform::HandleNodeBrowse(void * context, DnssdService * services, size_t servicesSize, CHIP_ERROR error)
@@ -542,8 +542,8 @@
     char serviceName[kMaxCommisisonableServiceNameSize];
     ReturnErrorOnFailure(MakeServiceTypeName(serviceName, sizeof(serviceName), filter, DiscoveryType::kCommissionableNode));
 
-    return ChipDnssdBrowse(serviceName, DnssdServiceProtocol::kDnssdProtocolUdp, Inet::IPAddressType::kAny, INET_NULL_INTERFACEID,
-                           HandleNodeBrowse, this);
+    return ChipDnssdBrowse(serviceName, DnssdServiceProtocol::kDnssdProtocolUdp, Inet::IPAddressType::kAny,
+                           Inet::InterfaceId::Null(), HandleNodeBrowse, this);
 }
 
 CHIP_ERROR DiscoveryImplPlatform::FindCommissioners(DiscoveryFilter filter)
@@ -552,8 +552,8 @@
     char serviceName[kMaxCommisisonerServiceNameSize];
     ReturnErrorOnFailure(MakeServiceTypeName(serviceName, sizeof(serviceName), filter, DiscoveryType::kCommissionerNode));
 
-    return ChipDnssdBrowse(serviceName, DnssdServiceProtocol::kDnssdProtocolUdp, Inet::IPAddressType::kAny, INET_NULL_INTERFACEID,
-                           HandleNodeBrowse, this);
+    return ChipDnssdBrowse(serviceName, DnssdServiceProtocol::kDnssdProtocolUdp, Inet::IPAddressType::kAny,
+                           Inet::InterfaceId::Null(), HandleNodeBrowse, this);
 }
 
 void DiscoveryImplPlatform::HandleNodeIdResolve(void * context, DnssdService * result, CHIP_ERROR error)
diff --git a/src/lib/dnssd/MinimalMdnsServer.h b/src/lib/dnssd/MinimalMdnsServer.h
index 7ef7508..8f80d0f 100644
--- a/src/lib/dnssd/MinimalMdnsServer.h
+++ b/src/lib/dnssd/MinimalMdnsServer.h
@@ -30,7 +30,7 @@
     {
         return false; // not a usable interface
     }
-    char name[chip::Inet::InterfaceIterator::kMaxIfNameLength];
+    char name[chip::Inet::InterfaceId::kMaxIfNameLength];
     if (iterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR)
     {
         ChipLogError(Discovery, "Failed to get interface name.");
diff --git a/src/lib/dnssd/Resolver.h b/src/lib/dnssd/Resolver.h
index 4102b6d..977ee0c 100644
--- a/src/lib/dnssd/Resolver.h
+++ b/src/lib/dnssd/Resolver.h
@@ -63,7 +63,7 @@
 
     PeerId mPeerId;
     Inet::IPAddress mAddress               = Inet::IPAddress::Any;
-    Inet::InterfaceId mInterfaceId         = INET_NULL_INTERFACEID;
+    Inet::InterfaceId mInterfaceId         = Inet::InterfaceId::Null();
     uint16_t mPort                         = 0;
     char mHostName[kHostNameMaxLength + 1] = {};
     bool mSupportsTcp                      = false;
diff --git a/src/lib/dnssd/minimal_mdns/Server.cpp b/src/lib/dnssd/minimal_mdns/Server.cpp
index 7dc2ba0..8e95b60 100644
--- a/src/lib/dnssd/minimal_mdns/Server.cpp
+++ b/src/lib/dnssd/minimal_mdns/Server.cpp
@@ -154,7 +154,7 @@
     Shutdown(); // ensure everything starts fresh
 
     size_t endpointIndex                = 0;
-    chip::Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;
+    chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId::Null();
     chip::Inet::IPAddressType addressType;
 
     ShutdownOnError autoShutdown(this);
@@ -176,8 +176,8 @@
         CHIP_ERROR err = JoinMulticastGroup(interfaceId, info->udp, addressType);
         if (err != CHIP_NO_ERROR)
         {
-            char interfaceName[chip::Inet::InterfaceIterator::kMaxIfNameLength];
-            chip::Inet::GetInterfaceName(interfaceId, interfaceName, sizeof(interfaceName));
+            char interfaceName[chip::Inet::InterfaceId::kMaxIfNameLength];
+            interfaceId.GetInterfaceName(interfaceName, sizeof(interfaceName));
 
             // Log only as non-fatal error. Failure to join will mean we reply to unicast queries only.
             ChipLogError(DeviceLayer, "MDNS failed to join multicast group on %s for address type %s: %s", interfaceName,
@@ -211,7 +211,7 @@
 
         chip::Inet::InterfaceId boundIf = info->udp->GetBoundInterface();
 
-        if ((boundIf != INET_NULL_INTERFACEID) && (boundIf != interface))
+        if ((boundIf.IsPresent()) && (boundIf != interface))
         {
             continue;
         }
@@ -234,7 +234,7 @@
             continue;
         }
 
-        if ((info->interfaceId != interface) && (info->interfaceId != INET_NULL_INTERFACEID))
+        if ((info->interfaceId != interface) && (info->interfaceId != chip::Inet::InterfaceId::Null()))
         {
             continue;
         }
diff --git a/src/lib/dnssd/minimal_mdns/Server.h b/src/lib/dnssd/minimal_mdns/Server.h
index b8ca2bc..3c5200d 100644
--- a/src/lib/dnssd/minimal_mdns/Server.h
+++ b/src/lib/dnssd/minimal_mdns/Server.h
@@ -44,7 +44,7 @@
 /// interface matters (e.g. FF02::FB will care over which IPv6 interface it is sent)
 ///
 /// For MDNS in particular, you may want:
-///  - IPv4 listen on INET_NULL_INTERFACEID
+///  - IPv4 listen on InterfaceId::Null()
 ///  - IPv6 listen on every specific interface id available (except local loopback and other
 ///    not usable interfaces like docker)
 class ListenIterator
@@ -77,7 +77,7 @@
 public:
     struct EndpointInfo
     {
-        chip::Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;
+        chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId::Null();
         chip::Inet::IPAddressType addressType;
         chip::Inet::UDPEndPoint * udp = nullptr;
     };
diff --git a/src/lib/dnssd/minimal_mdns/responders/tests/TestIPResponder.cpp b/src/lib/dnssd/minimal_mdns/responders/tests/TestIPResponder.cpp
index 4ed00d6..7cafa43 100644
--- a/src/lib/dnssd/minimal_mdns/responders/tests/TestIPResponder.cpp
+++ b/src/lib/dnssd/minimal_mdns/responders/tests/TestIPResponder.cpp
@@ -57,7 +57,7 @@
             return it.GetInterfaceId();
         }
     }
-    return INET_NULL_INTERFACEID;
+    return InterfaceId::Null();
 }
 
 #if INET_CONFIG_ENABLE_IPV4
diff --git a/src/lib/dnssd/minimal_mdns/responders/tests/TestPtrResponder.cpp b/src/lib/dnssd/minimal_mdns/responders/tests/TestPtrResponder.cpp
index be2135c..f0cdd7f 100644
--- a/src/lib/dnssd/minimal_mdns/responders/tests/TestPtrResponder.cpp
+++ b/src/lib/dnssd/minimal_mdns/responders/tests/TestPtrResponder.cpp
@@ -99,7 +99,7 @@
     packetInfo.DestAddress = ipAddress;
     packetInfo.SrcPort     = kMdnsPort;
     packetInfo.DestPort    = kMdnsPort;
-    packetInfo.Interface   = INET_NULL_INTERFACEID;
+    packetInfo.Interface   = InterfaceId::Null();
 
     responder.AddAllResponses(&packetInfo, &acc);
 }
diff --git a/src/lib/dnssd/tests/TestDnssdCache.cpp b/src/lib/dnssd/tests/TestDnssdCache.cpp
index d24a1e9..aaddc91 100644
--- a/src/lib/dnssd/tests/TestDnssdCache.cpp
+++ b/src/lib/dnssd/tests/TestDnssdCache.cpp
@@ -51,7 +51,7 @@
     PeerId peerId;
     int64_t id                        = 0x100;
     uint16_t port                     = 2000;
-    constexpr Inet::InterfaceId iface = INET_NULL_INTERFACEID;
+    constexpr Inet::InterfaceId iface = Inet::InterfaceId::Null();
 
     Inet::IPAddress addr;
     Inet::IPAddress addrV6;
diff --git a/src/messaging/tests/echo/echo_requester.cpp b/src/messaging/tests/echo/echo_requester.cpp
index b8977c6..7e2486e 100644
--- a/src/messaging/tests/echo/echo_requester.cpp
+++ b/src/messaging/tests/echo/echo_requester.cpp
@@ -162,7 +162,7 @@
     else
     {
         peerAddr = chip::Optional<chip::Transport::PeerAddress>::Value(
-            chip::Transport::PeerAddress::UDP(gDestAddr, CHIP_PORT, INET_NULL_INTERFACEID));
+            chip::Transport::PeerAddress::UDP(gDestAddr, CHIP_PORT, chip::Inet::InterfaceId::Null()));
     }
 
     // Attempt to connect to the peer.
diff --git a/src/platform/Darwin/DnssdImpl.cpp b/src/platform/Darwin/DnssdImpl.cpp
index c9e1857..6054575 100644
--- a/src/platform/Darwin/DnssdImpl.cpp
+++ b/src/platform/Darwin/DnssdImpl.cpp
@@ -45,7 +45,7 @@
 
 uint32_t GetInterfaceId(chip::Inet::InterfaceId interfaceId)
 {
-    return (interfaceId == INET_NULL_INTERFACEID) ? kDNSServiceInterfaceIndexAny : interfaceId;
+    return interfaceId.IsPresent() ? interfaceId.GetPlatformInterface() : kDNSServiceInterfaceIndexAny;
 }
 
 std::string GetFullType(const char * type, DnssdServiceProtocol protocol)
@@ -304,10 +304,11 @@
     return MdnsContexts::GetInstance().Add(sdCtx, sdRef);
 }
 
-void OnBrowseAdd(BrowseContext * context, const char * name, const char * type, const char * domain, uint32_t interfaceId)
+void OnBrowseAdd(BrowseContext * context, const char * name, const char * type, const char * domain,
+                 chip::Inet::InterfaceId interfaceId)
 {
     ChipLogDetail(DeviceLayer, "Mdns: %s  name: %s, type: %s, domain: %s, interface: %d", __func__, name, type, domain,
-                  interfaceId);
+                  interfaceId.GetPlatformInterface());
 
     VerifyOrReturn(strcmp(kLocalDot, domain) == 0);
 
@@ -328,10 +329,11 @@
     context->services.push_back(service);
 }
 
-void OnBrowseRemove(BrowseContext * context, const char * name, const char * type, const char * domain, uint32_t interfaceId)
+void OnBrowseRemove(BrowseContext * context, const char * name, const char * type, const char * domain,
+                    chip::Inet::InterfaceId interfaceId)
 {
     ChipLogDetail(DeviceLayer, "Mdns: %s  name: %s, type: %s, domain: %s, interface: %d", __func__, name, type, domain,
-                  interfaceId);
+                  interfaceId.GetPlatformInterface());
 
     VerifyOrReturn(strcmp(kLocalDot, domain) == 0);
 
@@ -347,8 +349,8 @@
     BrowseContext * sdCtx = reinterpret_cast<BrowseContext *>(context);
     VerifyOrReturn(CheckForSuccess(sdCtx, __func__, err, true));
 
-    (flags & kDNSServiceFlagsAdd) ? OnBrowseAdd(sdCtx, name, type, domain, interfaceId)
-                                  : OnBrowseRemove(sdCtx, name, type, domain, interfaceId);
+    (flags & kDNSServiceFlagsAdd) ? OnBrowseAdd(sdCtx, name, type, domain, Inet::InterfaceId(interfaceId))
+                                  : OnBrowseRemove(sdCtx, name, type, domain, Inet::InterfaceId(interfaceId));
 
     if (!(flags & kDNSServiceFlagsMoreComing))
     {
@@ -397,7 +399,7 @@
     service.mAddress.SetValue(chip::Inet::IPAddress::FromSockAddr(*address));
     Platform::CopyString(service.mName, sdCtx->name);
     Platform::CopyString(service.mHostName, hostname);
-    service.mInterface = sdCtx->interfaceId;
+    service.mInterface = Inet::InterfaceId(sdCtx->interfaceId);
 
     sdCtx->callback(sdCtx->context, &service, CHIP_NO_ERROR);
     MdnsContexts::GetInstance().Remove(sdCtx);
diff --git a/src/platform/ESP32/ConnectivityManagerImpl.h b/src/platform/ESP32/ConnectivityManagerImpl.h
index e39c3b6..efa0b6b 100644
--- a/src/platform/ESP32/ConnectivityManagerImpl.h
+++ b/src/platform/ESP32/ConnectivityManagerImpl.h
@@ -46,11 +46,12 @@
 
 #include "esp_event.h"
 
+namespace chip {
+
 namespace Inet {
 class IPAddress;
 } // namespace Inet
 
-namespace chip {
 namespace DeviceLayer {
 
 class PlatformManagerImpl;
diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp
index eba6b1c..03f4f2e 100644
--- a/src/platform/Linux/ConnectivityManagerImpl.cpp
+++ b/src/platform/Linux/ConnectivityManagerImpl.cpp
@@ -967,7 +967,7 @@
             // This should be removed or find a better place once we depercate the rendezvous session.
             for (chip::Inet::InterfaceAddressIterator it; it.HasCurrent(); it.Next())
             {
-                char ifName[chip::Inet::InterfaceIterator::kMaxIfNameLength];
+                char ifName[chip::Inet::InterfaceId::kMaxIfNameLength];
                 if (it.IsUp() && CHIP_NO_ERROR == it.GetInterfaceName(ifName, sizeof(ifName)) &&
                     strncmp(ifName, sWiFiIfName, sizeof(ifName)) == 0)
                 {
diff --git a/src/platform/Linux/DnssdImpl.cpp b/src/platform/Linux/DnssdImpl.cpp
index 4452ee7..b1d8589 100644
--- a/src/platform/Linux/DnssdImpl.cpp
+++ b/src/platform/Linux/DnssdImpl.cpp
@@ -461,7 +461,7 @@
     CHIP_ERROR error       = CHIP_NO_ERROR;
     AvahiStringList * text = nullptr;
     AvahiIfIndex interface =
-        service.mInterface == INET_NULL_INTERFACEID ? AVAHI_IF_UNSPEC : static_cast<AvahiIfIndex>(service.mInterface);
+        service.mInterface.IsPresent() ? static_cast<AvahiIfIndex>(service.mInterface.GetPlatformInterface()) : AVAHI_IF_UNSPEC;
 
     keyBuilder << service.mName << "." << type << service.mPort << "." << interface;
     key = keyBuilder.str();
@@ -530,12 +530,12 @@
 {
     AvahiServiceBrowser * browser;
     BrowseContext * browseContext = chip::Platform::New<BrowseContext>();
-    AvahiIfIndex avahiInterface   = static_cast<AvahiIfIndex>(interface);
+    AvahiIfIndex avahiInterface   = static_cast<AvahiIfIndex>(interface.GetPlatformInterface());
 
     browseContext->mInstance = this;
     browseContext->mContext  = context;
     browseContext->mCallback = callback;
-    if (interface == INET_NULL_INTERFACEID)
+    if (!interface.IsPresent())
     {
         avahiInterface = AVAHI_IF_UNSPEC;
     }
@@ -615,7 +615,7 @@
             CopyTypeWithoutProtocol(service.mType, type);
             service.mProtocol    = GetProtocolInType(type);
             service.mAddressType = ToAddressType(protocol);
-            service.mInterface   = INET_NULL_INTERFACEID;
+            service.mInterface   = Inet::InterfaceId::Null();
             if (interface != AVAHI_IF_UNSPEC)
             {
                 service.mInterface = static_cast<chip::Inet::InterfaceId>(interface);
@@ -650,14 +650,14 @@
                               DnssdResolveCallback callback, void * context)
 {
     AvahiServiceResolver * resolver;
-    AvahiIfIndex avahiInterface     = static_cast<AvahiIfIndex>(interface);
+    AvahiIfIndex avahiInterface     = static_cast<AvahiIfIndex>(interface.GetPlatformInterface());
     ResolveContext * resolveContext = chip::Platform::New<ResolveContext>();
     CHIP_ERROR error                = CHIP_NO_ERROR;
 
     resolveContext->mInstance = this;
     resolveContext->mCallback = callback;
     resolveContext->mContext  = context;
-    if (interface == INET_NULL_INTERFACEID)
+    if (!interface.IsPresent())
     {
         avahiInterface = AVAHI_IF_UNSPEC;
     }
@@ -700,7 +700,7 @@
         result.mProtocol    = GetProtocolInType(type);
         result.mPort        = port;
         result.mAddressType = ToAddressType(protocol);
-        result.mInterface   = INET_NULL_INTERFACEID;
+        result.mInterface   = Inet::InterfaceId::Null();
         if (interface != AVAHI_IF_UNSPEC)
         {
             result.mInterface = static_cast<chip::Inet::InterfaceId>(interface);
diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp
index ff0d80f..ecb0454 100644
--- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp
+++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp
@@ -1918,7 +1918,7 @@
         mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUnknown;
     }
     mdnsService.mPort        = serviceInfo.mPort;
-    mdnsService.mInterface   = INET_NULL_INTERFACEID;
+    mdnsService.mInterface   = Inet::InterfaceId::Null();
     mdnsService.mAddressType = Inet::IPAddressType::kIPv6;
     mdnsService.mAddress     = chip::Optional<chip::Inet::IPAddress>(ToIPAddress(serviceInfo.mHostAddress));
 
diff --git a/src/platform/tests/TestDnssd.cpp b/src/platform/tests/TestDnssd.cpp
index fe08c6c..6baa99c 100644
--- a/src/platform/tests/TestDnssd.cpp
+++ b/src/platform/tests/TestDnssd.cpp
@@ -42,7 +42,7 @@
         printf("Mdns service size %zu\n", servicesSize);
         printf("Service name %s\n", services->mName);
         printf("Service type %s\n", services->mType);
-        NL_TEST_ASSERT(suite, ChipDnssdResolve(services, INET_NULL_INTERFACEID, HandleResolve, suite) == CHIP_NO_ERROR);
+        NL_TEST_ASSERT(suite, ChipDnssdResolve(services, chip::Inet::InterfaceId::Null(), HandleResolve, suite) == CHIP_NO_ERROR);
     }
 }
 
@@ -56,7 +56,7 @@
 
     NL_TEST_ASSERT(suite, error == CHIP_NO_ERROR);
 
-    service.mInterface = INET_NULL_INTERFACEID;
+    service.mInterface = chip::Inet::InterfaceId::Null();
     service.mPort      = 80;
     strcpy(service.mName, "test");
     strcpy(service.mType, "_mock");
@@ -71,8 +71,8 @@
     service.mSubTypeSize   = 0;
 
     NL_TEST_ASSERT(suite, ChipDnssdPublishService(&service) == CHIP_NO_ERROR);
-    ChipDnssdBrowse("_mock", DnssdServiceProtocol::kDnssdProtocolTcp, chip::Inet::IPAddressType::kAny, INET_NULL_INTERFACEID,
-                    HandleBrowse, suite);
+    ChipDnssdBrowse("_mock", DnssdServiceProtocol::kDnssdProtocolTcp, chip::Inet::IPAddressType::kAny,
+                    chip::Inet::InterfaceId::Null(), HandleBrowse, suite);
 }
 
 static void ErrorCallback(void * context, CHIP_ERROR error)
diff --git a/src/transport/raw/PeerAddress.h b/src/transport/raw/PeerAddress.h
index b730c33..60fbec7 100644
--- a/src/transport/raw/PeerAddress.h
+++ b/src/transport/raw/PeerAddress.h
@@ -61,9 +61,8 @@
 class PeerAddress
 {
 public:
-    PeerAddress() : mIPAddress(Inet::IPAddress::Any), mTransportType(Type::kUndefined), mInterface(INET_NULL_INTERFACEID) {}
-    PeerAddress(const Inet::IPAddress & addr, Type type) : mIPAddress(addr), mTransportType(type), mInterface(INET_NULL_INTERFACEID)
-    {}
+    PeerAddress() : mIPAddress(Inet::IPAddress::Any), mTransportType(Type::kUndefined) {}
+    PeerAddress(const Inet::IPAddress & addr, Type type) : mIPAddress(addr), mTransportType(type) {}
     PeerAddress(Type type) : mTransportType(type) {}
 
     PeerAddress(PeerAddress &&)      = default;
@@ -179,7 +178,7 @@
     Inet::IPAddress mIPAddress   = {};
     Type mTransportType          = Type::kUndefined;
     uint16_t mPort               = CHIP_PORT; ///< Relevant for UDP data sending.
-    Inet::InterfaceId mInterface = INET_NULL_INTERFACEID;
+    Inet::InterfaceId mInterface = Inet::InterfaceId::Null();
 };
 
 } // namespace Transport
diff --git a/src/transport/raw/TCP.cpp b/src/transport/raw/TCP.cpp
index 3789e73..4319b87 100644
--- a/src/transport/raw/TCP.cpp
+++ b/src/transport/raw/TCP.cpp
@@ -91,7 +91,8 @@
 #endif
     SuccessOrExit(err);
 
-    err = mListenSocket->Bind(params.GetAddressType(), Inet::IPAddress::Any, params.GetListenPort(), params.GetInterfaceId());
+    err = mListenSocket->Bind(params.GetAddressType(), Inet::IPAddress::Any, params.GetListenPort(),
+                              params.GetInterfaceId().IsPresent());
     SuccessOrExit(err);
 
     err = mListenSocket->Listen(kListenBacklogSize);
@@ -357,7 +358,7 @@
 {
     Inet::IPAddress ipAddress;
     uint16_t port;
-    Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;
+    Inet::InterfaceId interfaceId;
 
     endPoint->GetPeerInfo(&ipAddress, &port);
     endPoint->GetInterfaceId(&interfaceId);
@@ -382,7 +383,7 @@
     TCPBase * tcp           = reinterpret_cast<TCPBase *>(endPoint->AppState);
     Inet::IPAddress ipAddress;
     uint16_t port;
-    Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;
+    Inet::InterfaceId interfaceId;
 
     endPoint->GetPeerInfo(&ipAddress, &port);
     endPoint->GetInterfaceId(&interfaceId);
@@ -512,7 +513,7 @@
         {
             Inet::IPAddress ipAddress;
             uint16_t port;
-            Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;
+            Inet::InterfaceId interfaceId;
 
             mActiveConnections[i].mEndPoint->GetPeerInfo(&ipAddress, &port);
             mActiveConnections[i].mEndPoint->GetInterfaceId(&interfaceId);
diff --git a/src/transport/raw/TCP.h b/src/transport/raw/TCP.h
index c09a7f6..3b48aaf 100644
--- a/src/transport/raw/TCP.h
+++ b/src/transport/raw/TCP.h
@@ -77,7 +77,7 @@
     Inet::InetLayer * mLayer         = nullptr;                    ///< Associated inet layer
     Inet::IPAddressType mAddressType = Inet::IPAddressType::kIPv6; ///< type of listening socket
     uint16_t mListenPort             = CHIP_PORT;                  ///< TCP listen port
-    Inet::InterfaceId mInterfaceId   = INET_NULL_INTERFACEID;      ///< Interface to listen on
+    Inet::InterfaceId mInterfaceId   = Inet::InterfaceId::Null();  ///< Interface to listen on
 };
 
 /**
diff --git a/src/transport/raw/UDP.h b/src/transport/raw/UDP.h
index 710300c..e4ed2fb 100644
--- a/src/transport/raw/UDP.h
+++ b/src/transport/raw/UDP.h
@@ -74,7 +74,7 @@
     Inet::InetLayer * mLayer         = nullptr;                    ///< Associated inet layer
     Inet::IPAddressType mAddressType = Inet::IPAddressType::kIPv6; ///< type of listening socket
     uint16_t mListenPort             = CHIP_PORT;                  ///< UDP listen port
-    Inet::InterfaceId mInterfaceId   = INET_NULL_INTERFACEID;      ///< Interface to listen on
+    Inet::InterfaceId mInterfaceId   = Inet::InterfaceId::Null();  ///< Interface to listen on
 };
 
 /** Implements a transport using UDP. */