MASQUE: add tap bridging support for CONNECT-ETHERNET

The `--tap_bridge_interface` flag causes tap interfaces created by
`CreateTapInterface()` to be bridged to specified interface, if any.

PiperOrigin-RevId: 692976667
diff --git a/quiche/quic/masque/masque_utils.cc b/quiche/quic/masque/masque_utils.cc
index 0bfd5d1..6c4f7f1 100644
--- a/quiche/quic/masque/masque_utils.cc
+++ b/quiche/quic/masque/masque_utils.cc
@@ -13,22 +13,28 @@
 #include "absl/strings/escaping.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "quiche/quic/core/quic_config.h"
 #include "quiche/quic/core/quic_data_writer.h"
 #include "quiche/quic/core/quic_versions.h"
 #include "quiche/quic/platform/api/quic_ip_address.h"
 #include "quiche/quic/platform/api/quic_logging.h"
+#include "quiche/common/platform/api/quiche_command_line_flags.h"
 #include "quiche/common/platform/api/quiche_logging.h"
 
 #if defined(__linux__)
 #include <fcntl.h>
 #include <linux/if.h>
 #include <linux/if_tun.h>
+#include <linux/sockios.h>
 #include <sys/ioctl.h>
 #endif  // defined(__linux__)
 
 #include "absl/cleanup/cleanup.h"
 
+DEFINE_QUICHE_COMMAND_LINE_FLAG(
+    std::string, tap_bridge_interface, "",
+    "Bridge tap interfaces created by CONNECT-ETHERNET mode to be bridged to "
+    "the specified interface, if any.");
+
 namespace quic {
 
 ParsedQuicVersionVector MasqueSupportedVersions() {
@@ -186,6 +192,12 @@
   }
   absl::Cleanup sock_fd_closer = [sock_fd] { close(sock_fd); };
 
+  err = ioctl(sock_fd, SIOCGIFINDEX, &ifr);
+  if (err < 0) {
+    QUIC_PLOG(ERROR) << "SIOCGIFINDEX failed";
+  }
+  int tap_ifindex = ifr.ifr_ifindex;
+
   ifr.ifr_mtu = 1280;
   err = ioctl(sock_fd, SIOCSIFMTU, &ifr);
   if (err < 0) {
@@ -204,6 +216,25 @@
     QUIC_PLOG(ERROR) << "SIOCSIFFLAGS failed";
     return -1;
   }
+
+  const std::string tap_bridge_interface =
+      quiche::GetQuicheCommandLineFlag(FLAGS_tap_bridge_interface);
+
+  if (!tap_bridge_interface.empty()) {
+    if (tap_bridge_interface.size() >= IFNAMSIZ) {
+      QUIC_LOG(ERROR) << "tap bridge interface size too long: "
+                      << tap_bridge_interface.size();
+      return -1;
+    }
+    strncpy(ifr.ifr_name, tap_bridge_interface.c_str(), IFNAMSIZ);
+    ifr.ifr_ifindex = tap_ifindex;
+    err = ioctl(sock_fd, SIOCBRADDIF, &ifr);
+    if (err < 0) {
+      QUIC_PLOG(ERROR) << "SIOCBRADDIF failed";
+      return -1;
+    }
+  }
+
   std::move(tap_fd_closer).Cancel();
   return tap_fd;
 }