Rename and bridge the wifi virtio interface

Test: WiFi still works the old way, bridge created for virtio

Change-Id: Ib3ffdd2611f866a2c46da257619a0ad2c27ada4d
diff --git a/guest/commands/wifi_setup/Android.bp b/guest/commands/wifi_setup/Android.bp
index 9df9660..b8fb83d 100644
--- a/guest/commands/wifi_setup/Android.bp
+++ b/guest/commands/wifi_setup/Android.bp
@@ -17,13 +17,15 @@
     name: "wifi_setup",
     srcs: [
         "cmd.cpp",
-	"mac80211_hwsim.cpp",
+        "guest_bridge.cpp",
+        "mac80211_hwsim.cpp",
         "nl_client.cpp",
         "wifi_relay.cpp",
     ],
     shared_libs: [
         "libbase",
         "vsoc_lib",
+        "cuttlefish_net",
         "libcuttlefish_fs",
         "cuttlefish_auto_resources",
         "liblog",
@@ -37,4 +39,3 @@
     ],
     defaults: ["cuttlefish_guest_only", "cuttlefish_native_isa"]
 }
-
diff --git a/guest/commands/wifi_setup/guest_bridge.cpp b/guest/commands/wifi_setup/guest_bridge.cpp
new file mode 100644
index 0000000..99a2b05
--- /dev/null
+++ b/guest/commands/wifi_setup/guest_bridge.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "wifi_setup"
+
+#include "guest_bridge.h"
+
+#include <net/if.h>
+#include <cstdio>
+#include <log/log.h>
+#include "common/libs/net/netlink_client.h"
+#include "common/libs/net/network_interface.h"
+#include "common/libs/net/network_interface_manager.h"
+#include "common/libs/fs/shared_fd.h"
+
+int bridge_interface(const cvd::SharedFD& bfd, const char* bridge_name,
+                     uint32_t slave_index, const char* name) {
+  struct ifreq ifr;
+  memset(&ifr, 0, sizeof(ifr));
+  strncpy(ifr.ifr_name, bridge_name, sizeof(ifr.ifr_name));
+  ifr.ifr_ifindex = slave_index;
+  if (bfd->Ioctl(SIOCBRADDIF, &ifr) == -1) {
+    ALOGE("unable to add %d (%s) to bridge (%s)", (int)slave_index, name,
+          bfd->StrError());
+    return -1;
+  }
+  return 0;
+}
+
+int make_bridge(const char* eth_name, const char* wifi_name) {
+  int32_t data_index = if_nametoindex(eth_name);
+  if (data_index == 0) {
+    ALOGE("invalid data interface name '%s'", eth_name);
+    return 2;
+  }
+  std::string ap_name(wifi_name);
+  ap_name+="_ap";
+  std::string data_name(wifi_name);
+  data_name+="_data";
+  auto factory = cvd::NetlinkClientFactory::Default();
+  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(data_name.c_str(),
+                                                     eth_name));
+  if (!ni) {
+    ALOGE("open interface '%s' failed", eth_name);
+    return 3;
+  }
+  ni->SetName(data_name.c_str());
+  if (!nm->ApplyChanges(*ni)) {
+    ALOGE("renaming interface '%s' failed", eth_name);
+    return 4;
+  }
+  ni->SetOperational(true);
+  if (!nm->ApplyChanges(*ni)) {
+    ALOGE("unable to ifup '%s'", eth_name);
+    return 5;
+  }
+  cvd::SharedFD bfd = cvd::SharedFD::Socket(AF_UNIX, SOCK_STREAM, 0);
+  if (!bfd->IsOpen()) {
+    ALOGE("unable to get socket (%s)", bfd->StrError());
+    return 6;
+  }
+  std::string bridge_name(wifi_name);
+  bridge_name += "_bridge";
+  if (bfd->Ioctl(SIOCBRADDBR, (void*)bridge_name.c_str()) == -1) {
+    ALOGE("unable create wlan0_bridge (%s)", bfd->StrError());
+    return 7;
+  }
+  bridge_interface(bfd, bridge_name.c_str(), data_index, data_name.c_str());
+  return 0;
+}
diff --git a/guest/commands/wifi_setup/guest_bridge.h b/guest/commands/wifi_setup/guest_bridge.h
new file mode 100644
index 0000000..b515163
--- /dev/null
+++ b/guest/commands/wifi_setup/guest_bridge.h
@@ -0,0 +1,18 @@
+#pragma once
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+int make_bridge(const char* eth_name, const char* wifi_name);
diff --git a/guest/commands/wifi_setup/wifi_relay.cpp b/guest/commands/wifi_setup/wifi_relay.cpp
index 99d1e8d..6312916 100644
--- a/guest/commands/wifi_setup/wifi_relay.cpp
+++ b/guest/commands/wifi_setup/wifi_relay.cpp
@@ -16,6 +16,7 @@
 
 #include "wifi_relay.h"
 
+#include "guest/commands/wifi_setup/guest_bridge.h"
 #include "guest/commands/wifi_setup/mac80211_hwsim_driver.h"
 #include "guest/commands/wifi_setup/nl_client.h"
 
@@ -241,6 +242,8 @@
     exit(1);
   }
 
+  make_bridge("eth1", FLAGS_iface_name.c_str());
+
   cvd::NlClient client(NETLINK_GENERIC);
   if (!client.Init()) {
       LOG(ERROR) << "Could not open Netlink Generic.";