Snap for 11035523 from babf27770cc5850ba9319ccfd55707efe6be9cd9 to mainline-media-swcodec-release

Change-Id: I9c969b4807245f7ac0c3da35ab07ff5cceb6193b
diff --git a/src/core/border_router/infra_if.cpp b/src/core/border_router/infra_if.cpp
index 53e4fc2..011400c 100644
--- a/src/core/border_router/infra_if.cpp
+++ b/src/core/border_router/infra_if.cpp
@@ -60,7 +60,6 @@
     Error error = kErrorNone;
 
     VerifyOrExit(!mInitialized, error = kErrorInvalidState);
-    VerifyOrExit(aIfIndex > 0, error = kErrorInvalidArgs);
 
     mIfIndex     = aIfIndex;
     mInitialized = true;
diff --git a/src/lib/platform/exit_code.h b/src/lib/platform/exit_code.h
index c809eb1..4aef8bd 100644
--- a/src/lib/platform/exit_code.h
+++ b/src/lib/platform/exit_code.h
@@ -82,6 +82,12 @@
      * No response from radio spinel.
      */
     OT_EXIT_RADIO_SPINEL_NO_RESPONSE = 6,
+
+    /**
+     * Invalid state.
+     */
+    OT_EXIT_INVALID_STATE = 7,
+
 };
 
 /**
diff --git a/src/posix/platform/include/openthread/openthread-system.h b/src/posix/platform/include/openthread/openthread-system.h
index 7fe2e0e..820cf2b 100644
--- a/src/posix/platform/include/openthread/openthread-system.h
+++ b/src/posix/platform/include/openthread/openthread-system.h
@@ -226,6 +226,18 @@
  */
 void otSysCountInfraNetifAddresses(otSysInfraNetIfAddressCounters *aAddressCounters);
 
+/**
+ * Sets the infrastructure network interface and the ICMPv6 socket.
+ *
+ * This function specifies the network interface name and the ICMPv6 socket on that interface. After calling this
+ * function, the caller can call otBorderRoutingInit() to let Border Routing work on that interface.
+ *
+ * @param[in] aInfraNetifName  The name of the infrastructure network interface.
+ * @param[in] aIcmp6Socket     A SOCK_RAW socket running on the infrastructure network interface.
+ *
+ */
+void otSysSetInfraNetif(const char *aInfraNetifName, int aIcmp6Socket);
+
 #ifdef __cplusplus
 } // end of extern "C"
 #endif
diff --git a/src/posix/platform/infra_if.cpp b/src/posix/platform/infra_if.cpp
index 505d025..e86fdaf 100644
--- a/src/posix/platform/infra_if.cpp
+++ b/src/posix/platform/infra_if.cpp
@@ -123,9 +123,8 @@
 
 namespace ot {
 namespace Posix {
-namespace {
 
-int CreateIcmp6Socket(void)
+int InfraNetif::CreateIcmp6Socket(const char *aInfraIfName)
 {
     int                 sock;
     int                 rval;
@@ -168,6 +167,13 @@
     rval = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kHopLimit, sizeof(kHopLimit));
     VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
 
+#ifdef __linux__
+    rval = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, aInfraIfName, strlen(aInfraIfName));
+#else  // __NetBSD__ || __FreeBSD__ || __APPLE__
+    rval = setsockopt(mInfraIfIcmp6Socket, IPPROTO_IPV6, IPV6_BOUND_IF, &mInfraIfIndex, sizeof(mInfraIfIndex));
+#endif // __linux__
+    VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
     return sock;
 }
 
@@ -200,8 +206,6 @@
     return sock;
 }
 
-} // namespace
-
 otError InfraNetif::SendIcmp6Nd(uint32_t            aInfraIfIndex,
                                 const otIp6Address &aDestAddress,
                                 const uint8_t      *aBuffer,
@@ -276,7 +280,10 @@
     return error;
 }
 
-bool InfraNetif::IsRunning(void) const { return (GetFlags() & IFF_RUNNING) && HasLinkLocalAddress(); }
+bool InfraNetif::IsRunning(void) const
+{
+    return mInfraIfIndex ? ((GetFlags() & IFF_RUNNING) && HasLinkLocalAddress()) : false;
+}
 
 uint32_t InfraNetif::GetFlags(void) const
 {
@@ -368,10 +375,18 @@
     return hasLla;
 }
 
-void InfraNetif::Init(const char *aIfName)
+void InfraNetif::Init(void) { mNetLinkSocket = CreateNetLinkSocket(); }
+
+void InfraNetif::SetInfraNetif(const char *aIfName, int aIcmp6Socket)
 {
-    ssize_t  rval;
-    uint32_t ifIndex = 0;
+    uint32_t             ifIndex = 0;
+    otBorderRoutingState state   = otBorderRoutingGetState(gInstance);
+
+    OT_ASSERT(gInstance != nullptr);
+
+    VerifyOrDie(mNetLinkSocket != -1, OT_EXIT_INVALID_STATE);
+    VerifyOrDie(state == OT_BORDER_ROUTING_STATE_UNINITIALIZED || state == OT_BORDER_ROUTING_STATE_DISABLED,
+                OT_EXIT_INVALID_STATE);
 
     if (aIfName == nullptr || aIfName[0] == '\0')
     {
@@ -389,17 +404,14 @@
         otLogCritPlat("Failed to get the index for infra interface %s", aIfName);
         DieNow(OT_EXIT_INVALID_ARGUMENTS);
     }
+
     mInfraIfIndex = ifIndex;
 
-    mInfraIfIcmp6Socket = CreateIcmp6Socket();
-#ifdef __linux__
-    rval = setsockopt(mInfraIfIcmp6Socket, SOL_SOCKET, SO_BINDTODEVICE, mInfraIfName, strlen(mInfraIfName));
-#else  // __NetBSD__ || __FreeBSD__ || __APPLE__
-    rval = setsockopt(mInfraIfIcmp6Socket, IPPROTO_IPV6, IPV6_BOUND_IF, &mInfraIfIndex, sizeof(mInfraIfIndex));
-#endif // __linux__
-    VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
-
-    mNetLinkSocket = CreateNetLinkSocket();
+    if (mInfraIfIcmp6Socket != -1)
+    {
+        close(mInfraIfIcmp6Socket);
+    }
+    mInfraIfIcmp6Socket = aIcmp6Socket;
 
 exit:
     return;
@@ -408,7 +420,7 @@
 void InfraNetif::SetUp(void)
 {
     OT_ASSERT(gInstance != nullptr);
-    VerifyOrExit(mInfraIfIndex != 0);
+    VerifyOrExit(mNetLinkSocket != -1);
 
     SuccessOrDie(otBorderRoutingInit(gInstance, mInfraIfIndex, platformInfraIfIsRunning()));
     SuccessOrDie(otBorderRoutingSetEnabled(gInstance, /* aEnabled */ true));
@@ -419,12 +431,8 @@
 
 void InfraNetif::TearDown(void)
 {
-    VerifyOrExit(mInfraIfIndex != 0);
-
+    IgnoreError(otBorderRoutingSetEnabled(gInstance, false));
     Mainloop::Manager::Get().Remove(*this);
-
-exit:
-    return;
 }
 
 void InfraNetif::Deinit(void)
diff --git a/src/posix/platform/infra_if.hpp b/src/posix/platform/infra_if.hpp
index b0be452..b468e10 100644
--- a/src/posix/platform/infra_if.hpp
+++ b/src/posix/platform/infra_if.hpp
@@ -71,12 +71,21 @@
     /**
      * Initializes the infrastructure network interface.
      *
+     * To specify the infrastructure network interface, you need to call SetInfraNetif() after Init().
+     *
      * @note This method is called before OpenThread instance is created.
      *
-     * @param[in]  aIfName      A pointer to infrastructure network interface name.
+     */
+    void Init(void);
+
+    /**
+     * Sets the infrastructure network interface.
+     *
+     * @param[in]  aIfName       A pointer to infrastructure network interface name.
+     * @param[in]  aIcmp6Socket  A SOCK_RAW socket for sending/receiving ICMPv6 messages.
      *
      */
-    void Init(const char *aIfName);
+    void SetInfraNetif(const char *aIfName, int aIcmp6Socket);
 
     /**
      * Sets up the infrastructure network interface.
@@ -175,6 +184,16 @@
      */
     static InfraNetif &Get(void);
 
+    /**
+     * Creates a socket for sending/receiving ICMPv6 messages.
+     *
+     * @param[in] aInfraIfName  The infrastructure network interface name.
+     *
+     * @returns The file descriptor of the socket.
+     *
+     */
+    static int CreateIcmp6Socket(const char *aInfraIfName);
+
 private:
     static const char         kWellKnownIpv4OnlyName[];   // "ipv4only.arpa"
     static const otIp4Address kWellKnownIpv4OnlyAddress1; // 192.0.0.170
diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp
index c52dea1..a154ff8 100644
--- a/src/posix/platform/system.cpp
+++ b/src/posix/platform/system.cpp
@@ -121,6 +121,13 @@
 }
 #endif
 
+#if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
+void otSysSetInfraNetif(const char *aInfraNetifName, int aIcmp6Socket)
+{
+    ot::Posix::InfraNetif::Get().SetInfraNetif(aInfraNetifName, aIcmp6Socket);
+}
+#endif
+
 void platformInit(otPlatformConfig *aPlatformConfig)
 {
 #if OPENTHREAD_POSIX_CONFIG_BACKTRACE_ENABLE
@@ -143,7 +150,8 @@
 #endif
 
 #if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
-    ot::Posix::InfraNetif::Get().Init(aPlatformConfig->mBackboneInterfaceName);
+    ot::Posix::InfraNetif::Get().Init();
+
 #endif
 
     gNetifName[0] = '\0';
@@ -164,8 +172,10 @@
     return;
 }
 
-void platformSetUp(void)
+void platformSetUp(otPlatformConfig *aPlatformConfig)
 {
+    OT_UNUSED_VARIABLE(aPlatformConfig);
+
     VerifyOrExit(!gDryRun);
 
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
@@ -173,6 +183,11 @@
 #endif
 
 #if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
+    if (aPlatformConfig->mBackboneInterfaceName != nullptr && strlen(aPlatformConfig->mBackboneInterfaceName) > 0)
+    {
+        otSysSetInfraNetif(aPlatformConfig->mBackboneInterfaceName,
+                           ot::Posix::InfraNetif::CreateIcmp6Socket(aPlatformConfig->mBackboneInterfaceName));
+    }
     ot::Posix::InfraNetif::Get().SetUp();
 #endif
 
@@ -206,7 +221,7 @@
     gInstance = otInstanceInitSingle();
     OT_ASSERT(gInstance != nullptr);
 
-    platformSetUp();
+    platformSetUp(aPlatformConfig);
 
     return gInstance;
 }