[tun] Migrate away from Stack.AddInterface

Use fuchsia.net.interfaces.admin/Installer & friends instead.

Use methods from fuchsia.net.interfaces.admin/Control where possible to
control the interface.

Bug: 85061
Change-Id: Ifaa7f82a9020442ee0ce726e1fd69442c52e06da
diff --git a/src/include/BUILD.gn b/src/include/BUILD.gn
index ec128ae..2d718d6 100644
--- a/src/include/BUILD.gn
+++ b/src/include/BUILD.gn
@@ -785,6 +785,7 @@
 group("common") {
   public_deps = [
     ":public_headers",
+    "//sdk/fidl/fuchsia.net.interfaces.admin",
     "//sdk/fidl/fuchsia.net.stack",
     "//sdk/fidl/fuchsia.net.tun",
     "//sdk/fidl/fuchsia.netstack",
diff --git a/src/inet/BUILD.gn b/src/inet/BUILD.gn
index ded2e6d..9b34b28 100644
--- a/src/inet/BUILD.gn
+++ b/src/inet/BUILD.gn
@@ -44,6 +44,7 @@
   configs += [ "//third_party/openweave-core/src/include:fuchsia" ]
   configs += [ "//build/config:Wno-extra-semi" ]
   public_deps = [
+    "//sdk/fidl/fuchsia.net.interfaces.admin",
     "//sdk/fidl/fuchsia.net.stack",
     "//sdk/fidl/fuchsia.net.tun",
     "//sdk/fidl/fuchsia.netstack",
diff --git a/src/inet/TunEndPoint.cpp b/src/inet/TunEndPoint.cpp
index 866e422..8656867 100644
--- a/src/inet/TunEndPoint.cpp
+++ b/src/inet/TunEndPoint.cpp
@@ -132,12 +132,9 @@
 }
 
 // Add the tun interface to netstack. If successful the tun interface shows up in "net if list".
-INET_ERROR TunEndPoint::AddInterfaceToNetstack(fuchsia::hardware::network::DeviceHandle & device, const char *intfName) {
+INET_ERROR TunEndPoint::AddInterfaceToNetstack(const char *intfName) {
   zx_status_t err;
-  fuchsia::net::stack::DeviceDefinition deviceDefinition;
-  fuchsia::net::stack::InterfaceConfig config;
-  config.set_name(intfName);
-  deviceDefinition.set_ip(std::move(device));
+
   InetLayer::FuchsiaPlatformData *platformData = static_cast<InetLayer::FuchsiaPlatformData*>(Layer().GetPlatformData());
   if (platformData == NULL || platformData->ctx == NULL) {
     WeaveLogError(Inet, "PlatformData is NULL");
@@ -145,25 +142,64 @@
   }
   err = platformData->ctx->svc()->Connect(mStackPtr.NewRequest());
   if (err != ZX_OK) {
-    WeaveLogError(Inet,"connect to stack fidl failed");
+    WeaveLogError(Inet, "connect to stack fidl failed");
     return err;
   }
 
-  fuchsia::net::stack::Stack_AddInterface_Result result;
-  err = mStackPtr->AddInterface(std::move(config), std::move(deviceDefinition), &result);
-  if (err != ZX_OK || result.is_err()) {
-    WeaveLogError(Inet,"AddInterface failed %d:%s", err, zx_status_get_string(err));
-    return err;
+  fuchsia::hardware::network::DeviceHandle device;
+  err = mTunDevice->GetDevice(device.NewRequest());
+  if (err != ZX_OK) {
+      WeaveLogError(Inet, "get device failed: %s", zx_status_get_string(err));
+      return err;
+  }
+  fuchsia::hardware::network::PortSyncPtr port;
+  err = mTunPort->GetPort(port.NewRequest());
+  if (err != ZX_OK) {
+      WeaveLogError(Inet, "get port failed: %s", zx_status_get_string(err));
+      return err;
+  }
+  fuchsia::hardware::network::PortInfo port_info;
+  err = port->GetInfo(&port_info);
+  if (err != ZX_OK) {
+      WeaveLogError(Inet, "port GetInfo failed: %s", zx_status_get_string(err));
+      return err;
+  }
+  if (!port_info.has_id()) {
+      WeaveLogError(Inet, "missing port id");
+      return ZX_ERR_INTERNAL;
+  }
+  const fuchsia::hardware::network::PortId& port_id = port_info.id();
+
+  fuchsia::net::interfaces::admin::InstallerSyncPtr installer;
+  err = platformData->ctx->svc()->Connect(installer.NewRequest());
+  if (err != ZX_OK) {
+      WeaveLogError(Inet, "connect to installer fidl failed");
+      return err;
+  }
+  err = installer->InstallDevice(std::move(device), mDeviceControlPtr.NewRequest());
+  if (err != ZX_OK) {
+      WeaveLogError(Inet, "InstallDevice failed: %s", zx_status_get_string(err));
+      return err;
+  }
+  fuchsia::net::interfaces::admin::Options options;
+  options.set_name(intfName);
+  err = mDeviceControlPtr->CreateInterface(port_id, mControlPtr.NewRequest(), std::move(options));
+  if (err != ZX_OK) {
+      WeaveLogError(Inet, "CreateInterface failed: %s", zx_status_get_string(err));
+      return err;
   }
 
-  mInterfaceId = result.response().id;
+  err = mControlPtr->GetId(&mInterfaceId);
+  if (err != ZX_OK) {
+      WeaveLogError(Inet, "GetId failed: %s", zx_status_get_string(err));
+      return err;
+  }
+
   return INET_NO_ERROR;
 }
 
 INET_ERROR TunEndPoint::CreateHostDevice(const char *intfName) {
-  fuchsia::hardware::network::DeviceHandle device;
-  mTunDevice->GetDevice(device.NewRequest());
-  return AddInterfaceToNetstack(device, intfName);
+  return AddInterfaceToNetstack(intfName);
 }
 
 /* Read packets from TUN device in Linux */
@@ -356,8 +392,11 @@
 #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
 
 #if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
+    // TODO(https://fxbug.dev/80064): Migrate away from stack.GetInterfaceInfo.
+    // NOTE: This is the last use of mStackPtr (fuchsia.net.stack/Stack) in this
+    // class.
     if (!mStackPtr.is_bound()) {
-      WeaveLogError(Inet, "mStackPtr is not bound");
+      WeaveLogError(Inet, "mControlPtr is not bound");
       ExitNow(ret = false);
     }
     else {
@@ -437,18 +476,26 @@
 
 #if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
     // Set tun device to online.
-    fuchsia::net::stack::Stack_EnableInterface_Result result;
+    fuchsia::net::interfaces::admin::Control_Enable_Result result;
     err = mTunPort->SetOnline(true);
     if (err != ZX_OK) {
       WeaveLogError(Inet, "InterfaceUp failed due to SetOnline error: %s", zx_status_get_string(err));
       ExitNow();
     }
-    if (!mStackPtr.is_bound()) {
+    if (!mControlPtr.is_bound()) {
       ExitNow(err = ZX_ERR_BAD_STATE);
     }
 
     // Enable the tun interface.
-    err = mStackPtr->EnableInterface(mInterfaceId, &result);
+    err = mControlPtr->Enable(&result);
+    if (err != ZX_OK) {
+        WeaveLogError(Inet, "InterfaceUp failed due to Enable FIDL error: %s", zx_status_get_string(err));
+        ExitNow();
+    }
+    if (result.is_err()) {
+        WeaveLogError(Inet, "InterfaceUp failed due to Enable error: %d", result.err());
+        ExitNow(err = ZX_ERR_INTERNAL);
+    }
 #elif WEAVE_SYSTEM_CONFIG_USE_SOCKETS
     int sockfd = INET_INVALID_SOCKET_FD;
     struct ::ifreq ifr;
@@ -526,9 +573,9 @@
 #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
 
 #if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
-    fuchsia::net::stack::Stack_DisableInterface_Result result;
-    if (!mStackPtr.is_bound()) {
-      WeaveLogError(Inet, "InterfaceDown failed as mStackPtr is not bound");
+    fuchsia::net::interfaces::admin::Control_Disable_Result result;
+    if (!mControlPtr.is_bound()) {
+      WeaveLogError(Inet, "InterfaceDown failed as mControlPtr is not bound");
       ExitNow(err = ZX_ERR_BAD_STATE);
     }
     // Set offline and disable the interface.
@@ -538,10 +585,14 @@
       ExitNow();
     }
 
-    err = mStackPtr->DisableInterface(mInterfaceId, &result);
+    err = mControlPtr->Disable(&result);
     if (err != ZX_OK) {
-      WeaveLogError(Inet, "DisableInterface failed: %s", zx_status_get_string(err));
-      return err;
+        WeaveLogError(Inet, "InterfaceDown failed due to Disable FIDL error: %s", zx_status_get_string(err));
+        ExitNow();
+    }
+    if (result.is_err()) {
+        WeaveLogError(Inet, "InterfaceDown failed due to Disable error: %d", result.err());
+        ExitNow(err = ZX_ERR_INTERNAL);
     }
 
 #elif WEAVE_SYSTEM_CONFIG_USE_SOCKETS
@@ -950,16 +1001,14 @@
 void TunEndPoint::TunDevClose (void)
 {
 #if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
-  INET_ERROR err = INET_NO_ERROR;
   fuchsia::net::stack::Stack_DelEthernetInterface_Result result;
-  if (!mStackPtr.is_bound()) {
-    WeaveLogError(Inet, "TunDevClose failed as mStackPtr is not bound to service");
+  if (!mControlPtr.is_bound()) {
+    WeaveLogError(Inet, "TunDevClose failed as mControlPtr is not bound");
     return;
   }
-  err = mStackPtr->DelEthernetInterface(mInterfaceId, &result);
-  if (err != ZX_OK) {
-    WeaveLogError(Inet, "DelInterface failed %d: %s", err, zx_status_get_string(err));
-  }
+  // Dropping the control handles will cause the interface to be removed.
+  mControlPtr.Unbind();
+  mDeviceControlPtr.Unbind();
   mInterfaceId = 0;
 #else
     if (mSocket >= 0)
diff --git a/src/inet/TunEndPoint.h b/src/inet/TunEndPoint.h
index 9a6f9e5..c2af2f6 100644
--- a/src/inet/TunEndPoint.h
+++ b/src/inet/TunEndPoint.h
@@ -33,6 +33,7 @@
 #include <SystemLayer/SystemPacketBuffer.h>
 
 #if WEAVE_SYSTEM_CONFIG_USE_FUCHSIA_TUN
+#include <fuchsia/net/interfaces/admin/cpp/fidl.h>
 #include <fuchsia/net/tun/cpp/fidl.h>
 #include <fuchsia/net/stack/cpp/fidl.h>
 #include <lib/sys/cpp/component_context.h>
@@ -208,6 +209,8 @@
     fuchsia::net::tun::DeviceSyncPtr mTunDevice;
     fuchsia::net::tun::PortSyncPtr mTunPort;
     fuchsia::net::stack::StackSyncPtr mStackPtr;
+    fuchsia::net::interfaces::admin::ControlSyncPtr mControlPtr;
+    fuchsia::net::interfaces::admin::DeviceControlSyncPtr mDeviceControlPtr;
     uint64_t mInterfaceId;
 
     /**
@@ -221,7 +224,7 @@
      * @param[in] intfName     interface name provided by WeaveTunnelAgent, defaults to TUN_DEFAULT_INTF_NAME.
      * @return                 INET_OK on success and INET_ERROR on failure.
      */
-    INET_ERROR AddInterfaceToNetstack(fuchsia::hardware::network::DeviceHandle& device, const char *intfName);
+    INET_ERROR AddInterfaceToNetstack(const char *intfName);
 
     /**
      * @brief   Create tun device.