This is an automated email from the ASF dual-hosted git repository.

alexey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git

commit d0734a1bf8bd45b016fbffa983fbb8c483ed94c9
Author: Alexey Serbin <[email protected]>
AuthorDate: Mon Jul 26 16:40:35 2021 -0700

    [net_util] workaround for VPN tunnel interfaces
    
    This patch addresses an issue in GetLocalNetworks() which surfaced
    when macOS client for GlobalProtect VPN created a tunnel interface entry
    like below on macOS laptop:
    
      utun2: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1400
              inet 10.xx.yy.zzz --> 10.xx.yy.zzz netmask 0xffffffff
    
    Before this patch, many tests on my macOS laptop would fail with stack
    traces like below when the list of network interfaces contained a tunnel
    interface mentioned above:
    
      F0726 16:40:54.328904 257036288 sockaddr.cc:86] Check failed: 2 == 
addr.sin_family (2 vs. unsigned char value 0)
      *** Check failure stack trace: ***
      *** Aborted at 1627342854 (unix time) try "date -d @1627342854" if you 
are using GNU date ***
      PC: @     0x7fff70c6833a __pthread_kill
      *** SIGABRT (@0x7fff70c6833a) received by PID 28695 (TID 0x70000f521000) 
stack trace: ***
          @     0x7fff70d195fd _sigtramp
          @                0x0 (unknown)
          @     0x7fff70bef808 abort
          @        0x116781259 google::logging_fail()
          @        0x116780121 google::LogMessage::SendToLog()
          @        0x116780815 google::LogMessage::Flush()
          @        0x11678476f google::LogMessageFatal::~LogMessageFatal()
          @        0x1167815f9 google::LogMessageFatal::~LogMessageFatal()
          @        0x115711216 kudu::Sockaddr::Sockaddr()
          @        0x1156fcabb kudu::GetLocalNetworks()
          @        0x1120cd337 
kudu::rpc::ServerNegotiation::IsTrustedConnection()::$_4::operator()()
    
    Change-Id: I4963806a709fe380b178d5f9fc633afcf9fb6184
    Reviewed-on: http://gerrit.cloudera.org:8080/17728
    Tested-by: Kudu Jenkins
    Reviewed-by: Andrew Wong <[email protected]>
---
 src/kudu/util/net/net_util.cc | 55 ++++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/src/kudu/util/net/net_util.cc b/src/kudu/util/net/net_util.cc
index ce5e156..2f1c671 100644
--- a/src/kudu/util/net/net_util.cc
+++ b/src/kudu/util/net/net_util.cc
@@ -360,7 +360,9 @@ Status ParseAddressList(const std::string& addr_list,
                         std::vector<Sockaddr>* addresses) {
   vector<HostPort> host_ports;
   RETURN_NOT_OK(HostPort::ParseStrings(addr_list, default_port, &host_ports));
-  if (host_ports.empty()) return Status::InvalidArgument("No address 
specified");
+  if (host_ports.empty()) {
+    return Status::InvalidArgument("No address specified");
+  }
   unordered_set<Sockaddr> uniqued;
   for (const HostPort& host_port : host_ports) {
     vector<Sockaddr> this_addresses;
@@ -383,39 +385,48 @@ Status ParseAddressList(const std::string& addr_list,
 Status GetHostname(string* hostname) {
   TRACE_EVENT0("net", "GetHostname");
   char name[HOST_NAME_MAX];
-  int ret = gethostname(name, HOST_NAME_MAX);
-  if (ret != 0) {
-    return Status::NetworkError("Unable to determine local hostname",
-                                ErrnoToString(errno),
-                                errno);
+  if (gethostname(name, HOST_NAME_MAX) != 0) {
+    const int err = errno;
+    return Status::NetworkError(
+        "Unable to determine local hostname", ErrnoToString(err), err);
   }
   *hostname = name;
   return Status::OK();
 }
 
 Status GetLocalNetworks(std::vector<Network>* net) {
-  struct ifaddrs *ifap = nullptr;
-
-  int ret = getifaddrs(&ifap);
+  struct ifaddrs* ifap = nullptr;
   SCOPED_CLEANUP({
-    if (ifap) freeifaddrs(ifap);
+    if (ifap) {
+      freeifaddrs(ifap);
+    }
   });
 
-  if (ret != 0) {
-    return Status::NetworkError("Unable to determine local network addresses",
-                                ErrnoToString(errno),
-                                errno);
+  if (getifaddrs(&ifap) != 0) {
+    const int err = errno;
+    return Status::NetworkError(
+        "Unable to determine local network addresses", ErrnoToString(err), 
err);
   }
 
   net->clear();
   for (struct ifaddrs *ifa = ifap; ifa; ifa = ifa->ifa_next) {
-    if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr) continue;
-
+    if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr) {
+      continue;
+    }
     if (ifa->ifa_addr->sa_family == AF_INET) {
-      Sockaddr addr(*reinterpret_cast<struct sockaddr_in*>(ifa->ifa_addr));
-      Sockaddr netmask(*reinterpret_cast<struct 
sockaddr_in*>(ifa->ifa_netmask));
-      Network network(addr.ipv4_addr().sin_addr.s_addr, 
netmask.ipv4_addr().sin_addr.s_addr);
-      net->push_back(network);
+      auto* ifa_address = reinterpret_cast<struct sockaddr_in*>(ifa->ifa_addr);
+      auto* ifa_netmask = reinterpret_cast<struct 
sockaddr_in*>(ifa->ifa_netmask);
+      if (ifa_netmask->sin_family == AF_UNSPEC) {
+        // Tunnel interfaces created by some VPN implementations do not have
+        // their network mask's address family (sin_family) properly set. If
+        // the address family for the network mask is left as AF_UNSPEC, this
+        // code sets the address family of the network mask to be the same as
+        // the family of the network address itself. This is to satisfy the
+        // constraints in the Sockaddr class.
+        ifa_netmask->sin_family = ifa_address->sin_family;
+      }
+      net->emplace_back(Sockaddr(*ifa_address).ipv4_addr().sin_addr.s_addr,
+                        Sockaddr(*ifa_netmask).ipv4_addr().sin_addr.s_addr);
     }
   }
 
@@ -485,7 +496,7 @@ Status GetRandomPort(const string& address, uint16_t* port) 
{
 
 void TryRunLsof(const Sockaddr& addr, vector<string>* log) {
 #if defined(__APPLE__)
-  string cmd = strings::Substitute(
+  string cmd = Substitute(
       "lsof -n -i 'TCP:$0' -sTCP:LISTEN ; "
       "for pid in $$(lsof -F p -n -i 'TCP:$0' -sTCP:LISTEN | cut -f 2 -dp) ; 
do"
       "  pstree $$pid || ps h -p $$pid;"
@@ -495,7 +506,7 @@ void TryRunLsof(const Sockaddr& addr, vector<string>* log) {
   // Little inline bash script prints the full ancestry of any pid listening
   // on the same port as 'addr'. We could use 'pstree -s', but that option
   // doesn't exist on el6.
-  string cmd = strings::Substitute(
+  string cmd = Substitute(
       "export PATH=$$PATH:/usr/sbin ; "
       "lsof -n -i 'TCP:$0' -sTCP:LISTEN ; "
       "for pid in $$(lsof -F p -n -i 'TCP:$0' -sTCP:LISTEN | grep p | cut -f 2 
-dp) ; do"

Reply via email to