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"
