Push virtio-net interface renaming into userspace.

By default, the virtio-net driver will name its interface 'ethX', which
causes the Android framework to consider this interface to be an
Ethernet device, even though it is being managed by rild and should
instead be considered a cellular network.

This change alters the NetworkInterfaceManager class to accept another
'alternate' name for the network interface at Open() time. It tries the
primary name first, and falls back to the secondary name. However,
VSoCRil now always sets up the IFLA_IFNAME field to the primary name,
which causes the SETLINK nl command to rename the interface at open
time, without needing to use the banned network(7) interface.

(This was previously worked around by detecting a magic MAC address on
the interface and renaming it with a change to the kernel. We are trying
to get rid of such hacks.)

Bug: 77634962
Change-Id: Ic0d66465c29856df74681f8be6df37bd0bc264cc
diff --git a/common/libs/net/network_interface_manager.cpp b/common/libs/net/network_interface_manager.cpp
index 32d5583..4ee96b7 100644
--- a/common/libs/net/network_interface_manager.cpp
+++ b/common/libs/net/network_interface_manager.cpp
@@ -75,15 +75,22 @@
     : nl_client_(std::move(nl_client)) {}
 
 std::unique_ptr<NetworkInterface> NetworkInterfaceManager::Open(
-    const std::string& if_name) {
+    const std::string& if_name, const std::string& if_name_alt) {
   std::unique_ptr<NetworkInterface> iface;
   // NOTE: do not replace this code with an IOCTL call.
   // On SELinux enabled Androids, RILD is not permitted to execute an IOCTL
   // and this call will fail.
-  const int32_t index = if_nametoindex(if_name.c_str());
-  if (index < 0) {
-    LOG(ERROR) << "Failed to get interface (" << if_name << ") index.";
-    return iface;
+  int32_t index = if_nametoindex(if_name.c_str());
+  if (index == 0) {
+    // Try the alternate name. This will be renamed to our preferred name
+    // by the kernel, because we specify IFLA_IFNAME, but open by index.
+    LOG(ERROR) << "Failed to get interface (" << if_name << ") index, "
+               << "trying alternate.";
+    index = if_nametoindex(if_name_alt.c_str());
+    if (index == 0) {
+      LOG(ERROR) << "Failed to get interface (" << if_name_alt << ") index.";
+      return iface;
+    }
   }
 
   iface.reset(new NetworkInterface(index));
diff --git a/common/libs/net/network_interface_manager.h b/common/libs/net/network_interface_manager.h
index 3d6ccc5..f28b0ff 100644
--- a/common/libs/net/network_interface_manager.h
+++ b/common/libs/net/network_interface_manager.h
@@ -32,14 +32,15 @@
 //
 //   std::unique_ptr<NetlinkClient> client(NetlinkClient::GetDefault());
 //   NetworkInterfaceManager manager(client.get());
-//   std::unique_ptr<NetworkInterface> iface(manager.Open("eth0"));
+//   std::unique_ptr<NetworkInterface> iface(manager.Open("eth0", "em0"));
 //
 class NetworkInterfaceManager {
  public:
   // Open existing network interface.
   //
   // NOTE: this method does not fill in any NetworkInterface details yet.
-  std::unique_ptr<NetworkInterface> Open(const std::string& if_name);
+  std::unique_ptr<NetworkInterface> Open(const std::string& if_name,
+                                         const std::string& if_name_alt);
 
   // Apply changes made to existing network interface.
   // This method cannot be used to instantiate new network interfaces.
diff --git a/guest/hals/ril/vsoc_ril.cpp b/guest/hals/ril/vsoc_ril.cpp
index b60ad8d..0d33dd9 100644
--- a/guest/hals/ril/vsoc_ril.cpp
+++ b/guest/hals/ril/vsoc_ril.cpp
@@ -114,9 +114,10 @@
   std::unique_ptr<cvd::NetlinkClient> nl(factory->New(NETLINK_ROUTE));
   std::unique_ptr<cvd::NetworkInterfaceManager> nm(
       cvd::NetworkInterfaceManager::New(factory));
-  std::unique_ptr<cvd::NetworkInterface> ni(nm->Open("rmnet0"));
+  std::unique_ptr<cvd::NetworkInterface> ni(nm->Open("rmnet0", "eth0"));
 
   if (ni) {
+    ni->SetName("rmnet0");
     ni->SetAddress(ipaddr);
     ni->SetBroadcastAddress(bcaddr);
     ni->SetPrefixLength(prefixlen);
@@ -132,7 +133,7 @@
 // This call returns true, if operation was successful.
 bool TearDownNetworkInterface() {
   auto nm(cvd::NetworkInterfaceManager::New(nullptr));
-  auto ni(nm->Open("rmnet0"));
+  auto ni(nm->Open("rmnet0", "eth0"));
 
   if (ni) {
     ni->SetOperational(false);