From 7f85d586b13e38095f0849432e86d75e97a52d58 Mon Sep 17 00:00:00 2001 From: Alex Landau Date: Tue, 24 Sep 2024 18:15:00 -0700 Subject: [PATCH] fboss2 cli: Canonicalize hostname Summary: Some commands work with short hostnames (e.g. `rsw026.p045.f01.frc1`) and some only with the FQDN (e.g. `rsw026.p045.f01.frc1.tfbnw.net`). Even the same command can work on some short hosts and not on others if it connects to the host using different clients, some of which support it and some don't. Specifically, `BmcClient` seems to require the FQDN (canonical name). Reviewed By: somasun Differential Revision: D63148545 fbshipit-source-id: 574815e8a15ad24ae33e741c7f3df3d6efe56054 --- fboss/cli/fboss2/utils/CmdUtilsCommon.cpp | 46 ++++++++++++++--------- fboss/cli/fboss2/utils/CmdUtilsCommon.h | 3 +- fboss/cli/fboss2/utils/HostInfo.h | 11 ++++-- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/fboss/cli/fboss2/utils/CmdUtilsCommon.cpp b/fboss/cli/fboss2/utils/CmdUtilsCommon.cpp index 19447fe3002df..f19163ab9da3f 100644 --- a/fboss/cli/fboss2/utils/CmdUtilsCommon.cpp +++ b/fboss/cli/fboss2/utils/CmdUtilsCommon.cpp @@ -30,38 +30,50 @@ using folly::IPAddressV6; namespace facebook::fboss::utils { -const folly::IPAddress getIPFromHost(const std::string& hostname) { +std::pair getCanonicalNameAndIPFromHost( + const std::string& hostname) { + std::string canonicalHostname = hostname; + if (IPAddress::validate(hostname)) { - return IPAddress(hostname); + return std::make_pair(canonicalHostname, IPAddress(hostname)); } struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - struct addrinfo* result = nullptr; - auto rv = getaddrinfo(hostname.c_str(), nullptr, &hints, &result); + hints.ai_flags = AI_CANONNAME; + struct addrinfo* info_orig = nullptr; + auto rv = getaddrinfo(hostname.c_str(), nullptr, &hints, &info_orig); SCOPE_EXIT { - freeaddrinfo(result); + freeaddrinfo(info_orig); }; if (rv < 0) { XLOG(ERR) << "Could not get an IP for: " << hostname; - return IPAddress(); + return std::make_pair(canonicalHostname, IPAddress()); + } + + struct addrinfo* info = info_orig; + if (info != nullptr) { + canonicalHostname = info->ai_canonname; } - struct addrinfo* res; - for (res = result; res != nullptr; res = res->ai_next) { - if (res->ai_addr->sa_family == AF_INET) { // IPV4 - struct sockaddr_in* sp = (struct sockaddr_in*)res->ai_addr; - return IPAddress::fromLong(sp->sin_addr.s_addr); - } else if (res->ai_addr->sa_family == AF_INET6) { // IPV6 - struct sockaddr_in6* sp = (struct sockaddr_in6*)res->ai_addr; - return IPAddress::fromBinary(ByteRange( - static_cast(&(sp->sin6_addr.s6_addr[0])), - IPAddressV6::byteCount())); + + for (; info != nullptr; info = info->ai_next) { + if (info->ai_addr->sa_family == AF_INET) { // IPV4 + struct sockaddr_in* sp = (struct sockaddr_in*)info->ai_addr; + return std::make_pair( + canonicalHostname, IPAddress::fromLong(sp->sin_addr.s_addr)); + } else if (info->ai_addr->sa_family == AF_INET6) { // IPV6 + struct sockaddr_in6* sp = (struct sockaddr_in6*)info->ai_addr; + return std::make_pair( + canonicalHostname, + IPAddress::fromBinary(ByteRange( + static_cast(&(sp->sin6_addr.s6_addr[0])), + IPAddressV6::byteCount()))); } } XLOG(ERR) << "Could not get an IP for: " << hostname; - return IPAddress(); + return std::make_pair(canonicalHostname, IPAddress()); } std::vector getHostsFromFile(const std::string& filename) { diff --git a/fboss/cli/fboss2/utils/CmdUtilsCommon.h b/fboss/cli/fboss2/utils/CmdUtilsCommon.h index 48fefdc0f3dbd..6e3529191aacd 100644 --- a/fboss/cli/fboss2/utils/CmdUtilsCommon.h +++ b/fboss/cli/fboss2/utils/CmdUtilsCommon.h @@ -166,7 +166,8 @@ auto filterTupleMonostates(Tuple tup) { void postAppInit(int argc, char* argv[], CLI::App& app); // API to retrieve host related information -const folly::IPAddress getIPFromHost(const std::string& hostname); +std::pair getCanonicalNameAndIPFromHost( + const std::string& hostname); const std::string getOobNameFromHost(const std::string& host); std::vector getHostsInSmcTier(const std::string& parentTierName); std::vector getHostsFromFile(const std::string& filename); diff --git a/fboss/cli/fboss2/utils/HostInfo.h b/fboss/cli/fboss2/utils/HostInfo.h index 945741372fcd3..380b0e17b1915 100644 --- a/fboss/cli/fboss2/utils/HostInfo.h +++ b/fboss/cli/fboss2/utils/HostInfo.h @@ -10,10 +10,7 @@ namespace facebook::fboss { class HostInfo { public: explicit HostInfo(const std::string& hostName) - : HostInfo( - hostName, - utils::getOobNameFromHost(hostName), - utils::getIPFromHost(hostName)) {} + : HostInfo(utils::getCanonicalNameAndIPFromHost(hostName)) {} HostInfo( const std::string& hostName, @@ -42,6 +39,12 @@ class HostInfo { } private: + explicit HostInfo(const std::pair& hostAndIp) + : HostInfo( + hostAndIp.first, + utils::getOobNameFromHost(hostAndIp.first), + hostAndIp.second) {} + const std::string name_; const std::string oob_; const folly::IPAddress ip_;