From 42d81c03528d90808e3967a2a2ee6db40956e226 Mon Sep 17 00:00:00 2001 From: Takeshi Nakatani Date: Tue, 29 Oct 2024 16:03:46 +0900 Subject: [PATCH] Improved IPv6 support and support for launch host domains --- buildutils/APKBUILD.templ.in | 2 +- lib/chmconf.cc | 11 ++++- lib/chmnetdb.cc | 78 ++++++++++++++++++++++++++++++++---- lib/chmnetdb.h | 4 +- lib/chmstructure.tcc | 2 +- tests/chmpxlinetool.cc | 8 ++++ 6 files changed, 93 insertions(+), 12 deletions(-) diff --git a/buildutils/APKBUILD.templ.in b/buildutils/APKBUILD.templ.in index 926956c..e87dbf2 100644 --- a/buildutils/APKBUILD.templ.in +++ b/buildutils/APKBUILD.templ.in @@ -53,6 +53,7 @@ arch="x86_64" license="MIT" depends=" + procps k2hash " depends_dev=" @@ -66,7 +67,6 @@ makedepends=" groff util-linux-misc musl-locales - procps yaml-dev @ALP_DEPS_TLS_DEV_PKG@ " diff --git a/lib/chmconf.cc b/lib/chmconf.cc index 1b67f95..412e732 100644 --- a/lib/chmconf.cc +++ b/lib/chmconf.cc @@ -2302,10 +2302,13 @@ bool CHMIniConf::LoadConfiguration(CHMCFGINFO& chmcfginfo) const for(strlst_t::const_iterator svrnodeiter = expand_svrnodes.begin(); svrnodeiter != expand_svrnodes.end(); ++svrnodeiter){ strlst_t nodehost_list; nodehost_list.clear(); + nodehost_list.push_back(*svrnodeiter); + if(!ChmNetDb::Get()->GetAllHostList(svrnodeiter->c_str(), nodehost_list, true)){ // if not found hostname/IP addresses for server node, add the original hostname nodehost_list.push_back(*svrnodeiter); } + // set first hostname svrnode.name = nodehost_list.front(); chmcfginfo.servers.push_back(svrnode); @@ -2316,7 +2319,7 @@ bool CHMIniConf::LoadConfiguration(CHMCFGINFO& chmcfginfo) const for(strlst_t::const_iterator nodehostiter = nodehost_list.begin(); nodehost_list.end() != nodehostiter; ++nodehostiter){ for(strlst_t::const_iterator liter = localhost_list.begin(); localhost_list.end() != liter; ++liter){ if(0 == strcasecmp(nodehostiter->c_str(), liter->c_str())){ - MSG_CHMPRN("Found self host name(%s) in server node list.", nodehostiter->c_str()); + MSG_CHMPRN("Found self host name(%s) in server node list.", nodehostiter->c_str()); // FOUND ccvals.server_mode_by_comp = true; is_break_loop = true; break; @@ -2326,6 +2329,12 @@ bool CHMIniConf::LoadConfiguration(CHMCFGINFO& chmcfginfo) const break; } } + // Set self server node name in configuration to localhostname cache. + if(!ChmNetDb::Get()->ReplaceFullLocalName(svrnode.name.c_str())){ + ERR_CHMPRN("Failed to replace full local hostname(%s) in cache, but continue...", svrnode.name.c_str()); + }else{ + MSG_CHMPRN("Replaced full local hostname(%s) in cache.", svrnode.name.c_str()); + } } } } diff --git a/lib/chmnetdb.cc b/lib/chmnetdb.cc index 6796465..c6b0c31 100644 --- a/lib/chmnetdb.cc +++ b/lib/chmnetdb.cc @@ -334,6 +334,19 @@ const time_t ChmNetDb::ALIVE_TIME; int ChmNetDb::lockval = FLCK_NOSHARED_MUTEX_VAL_UNLOCKED; const size_t ChmNetDb::PORT_NMATCH; +// [NOTE] +// If INET6 (IPv6) does not exist in the local host interface, +// INET6(IPv6) name resolution will not be performed. +// +// When executing INET6 resolve on a HOST (Container) that does +// not have IPv6 in its interface, it may be forced to wait +// until a timeout occurs. +// This occurs with ALPINE's INET6 and takes a very long time. +// Therefore, we perform inspection from INET4 and also use a +// flag to bypass the allocation of INET6. +// +bool ChmNetDb::inet6 = true; // default true + //--------------------------------------------------------- // Class methods //--------------------------------------------------------- @@ -392,7 +405,7 @@ bool ChmNetDb::GetLocalHostList(strlst_t& hostinfo, bool remove_localhost) return true; } -bool ChmNetDb::GetAnyAddrInfo(short port, struct addrinfo** ppaddrinfo, bool is_inetv6) +bool ChmNetDb::GetAnyAddrInfo(short port, struct addrinfo** ppaddrinfo, bool is_inet6) { if(!ppaddrinfo){ ERR_CHMPRN("Parameter is wrong."); @@ -400,18 +413,23 @@ bool ChmNetDb::GetAnyAddrInfo(short port, struct addrinfo** ppaddrinfo, bool is_ } *ppaddrinfo = NULL; + if(is_inet6 && !ChmNetDb::inet6){ + // Not processing for INET6 + return false; + } + struct addrinfo hints; int result; string strPort = to_string(port); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; - hints.ai_family = is_inetv6 ? AF_INET6 : AF_INET; + hints.ai_family = is_inet6 ? AF_INET6 : AF_INET; hints.ai_socktype = SOCK_STREAM; // addrinfo if(0 != (result = getaddrinfo(NULL, strPort.c_str(), &hints, ppaddrinfo)) || !(*ppaddrinfo)){ - MSG_CHMPRN("Could not get %s addrinfo for %s, errno=%d.", (is_inetv6 ? "IN6ADDR_ANY_INIT" : "INADDR_ANY"), (is_inetv6 ? "AF_INET6" : "AF_INET"), result); + MSG_CHMPRN("Could not get %s addrinfo for %s, errno=%d.", (is_inet6 ? "IN6ADDR_ANY_INIT" : "INADDR_ANY"), (is_inet6 ? "AF_INET6" : "AF_INET"), result); return false; } return true; @@ -788,6 +806,7 @@ bool ChmNetDb::CheckHostnameInResolv(const char* hostname, bool is_default_domai return false; } MSG_CHMPRN("Found hostname(%s) %s in resolv(DNS).", hostname, is_default_domain ? "with default domain" : "strictly"); + return true; } @@ -829,6 +848,7 @@ bool ChmNetDb::InitializeLocalHostInfo(void) if(!InitializeLocalHostIpAddresses()){ WAN_CHMPRN("Obtaining the IP address of the local interfaces may have failed, but continue..."); } + if(!InitializeLocalHostnames()){ WAN_CHMPRN("Obtaining the local hostnames may have failed, but continue..."); } @@ -839,6 +859,7 @@ bool ChmNetDb::InitializeLocalHostIpAddresses() { struct ifaddrs* ifaddr; char ipaddr[NI_MAXHOST]; + bool found_inet6 = false; // get ip addresses on interface memset(&ipaddr, 0, sizeof(ipaddr)); @@ -852,6 +873,11 @@ bool ChmNetDb::InitializeLocalHostIpAddresses() if(NULL == tmp_ifaddr->ifa_addr){ continue; } + if(AF_INET6 == tmp_ifaddr->ifa_addr->sa_family){ + // found INET6(IPv6 interface) + found_inet6 = true; + } + if(AF_INET == tmp_ifaddr->ifa_addr->sa_family || AF_INET6 == tmp_ifaddr->ifa_addr->sa_family){ memset(ipaddr, 0, sizeof(ipaddr)); socklen_t salen = (AF_INET == tmp_ifaddr->ifa_addr->sa_family) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); @@ -892,6 +918,13 @@ bool ChmNetDb::InitializeLocalHostIpAddresses() } freeifaddrs(ifaddr); + // Check & set INET6 flag + if(found_inet6){ + ChmNetDb::inet6 = true; + }else{ + ChmNetDb::inet6 = false; + } + return true; } @@ -919,6 +952,9 @@ bool ChmNetDb::InitializeLocalHostnames() MSG_CHMPRN("Allowed hostname(%s) is full local hostname", buf.nodename); fulllocalname = buf.nodename; + // add localnames + AddUniqueStringToList(fulllocalname, localnames, false); + // add cache without ip addresses HostnammeAddCache(fulllocalname, string(""), true); }else{ @@ -930,7 +966,7 @@ bool ChmNetDb::InitializeLocalHostnames() // local hostname -> addrinfo memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_UNSPEC; + hints.ai_family = ChmNetDb::inet6 ? AF_UNSPEC : AF_INET; hints.ai_socktype = SOCK_STREAM; if(0 != (result = getaddrinfo(buf.nodename, NULL, &hints, &res_info)) || !res_info){ // port is NULL MSG_CHMPRN("Could not get addrinfo from %s, errno=%d.", buf.nodename, result); @@ -955,7 +991,6 @@ bool ChmNetDb::InitializeLocalHostnames() }else{ is_same_nodename = true; } - if(is_same_nodename && fulllocalname.empty()){ MSG_CHMPRN("Found another local hostname : %s -> But not add to localnames array", hostname); }else{ @@ -968,7 +1003,6 @@ bool ChmNetDb::InitializeLocalHostnames() memset(&ipaddr, 0, sizeof(ipaddr)); if(0 == getnameinfo(tmpaddrinfo->ai_addr, tmpaddrinfo->ai_addrlen, ipaddr, sizeof(ipaddr), NULL, 0, NI_NUMERICHOST)){ HostnammeAddCache(string(hostname), string(ipaddr), true); - if(is_same_nodename && !fulllocalname.empty()){ HostnammeAddCache(fulllocalname, string(ipaddr), true); } @@ -1297,7 +1331,7 @@ bool ChmNetDb::GetHostAddressInfo(const char* target, CHMNDBCACHE& data) // target -> addrinfo memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_UNSPEC; + hints.ai_family = ChmNetDb::inet6 ? AF_UNSPEC : AF_INET; hints.ai_socktype = SOCK_STREAM; if(0 != getaddrinfo(target, NULL, &hints, &res_info) || !res_info){ // port is NULL return false; @@ -1424,7 +1458,7 @@ bool ChmNetDb::GetAddrInfoList(const char* target, short port, addrinfolist_t& i struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_UNSPEC; + hints.ai_family = ChmNetDb::inet6 ? AF_UNSPEC : AF_INET; hints.ai_socktype = SOCK_STREAM; // ip addresses @@ -1486,6 +1520,34 @@ bool ChmNetDb::GetHostnameList(const char* target, strlst_t& hostnames, bool is_ return true; } +bool ChmNetDb::ReplaceFullLocalName(const char* localneme) +{ + if(CHMEMPTYSTR(localneme)){ + ERR_CHMPRN("Parameter is wrong."); + return false; + } + if(0 == strcmp(fulllocalname.c_str(), localneme)){ + MSG_CHMPRN("Already set fulllocalname(%s).", localneme); + return true; + } + + // overwrite fulllocalname + fulllocalname = localneme; + + // erase same name in localnames list + for(strlst_t::const_iterator iter = localnames.begin(); localnames.end() != iter; ++iter){ + if((*iter) == fulllocalname){ + localnames.erase(iter); + break; + } + } + + // add name to front of localnames list + localnames.push_front(fulllocalname); + + return true; +} + // {NOTE] // If the same hostname as localhost is detected, add full local hostname to the beginning. // (If it exists in the middle of the list, it moves to the top) diff --git a/lib/chmnetdb.h b/lib/chmnetdb.h index de43337..80e1be4 100644 --- a/lib/chmnetdb.h +++ b/lib/chmnetdb.h @@ -53,6 +53,7 @@ class ChmNetDb static const time_t ALIVE_TIME = 60; // default 60s static int lockval; // like mutex static const size_t PORT_NMATCH = 5; // maximum 3 matches + 2(reserve) + static bool inet6; // inet6 is allowed chmndbmap_t cachemap; time_t timeout; // 0 means no timeout @@ -91,7 +92,7 @@ class ChmNetDb static bool GetLocalHostname(std::string& hostname); static bool GetLocalHostnameList(strlst_t& hostnames); static bool GetLocalHostList(strlst_t& hostinfo, bool remove_localhost = false); - static bool GetAnyAddrInfo(short port, struct addrinfo** ppaddrinfo, bool is_inetv6); + static bool GetAnyAddrInfo(short port, struct addrinfo** ppaddrinfo, bool is_inet6); static bool CvtAddrInfoToIpAddress(struct sockaddr_storage* info, socklen_t infolen, std::string& stripaddress); static bool CvtSockToLocalPort(int sock, short& port); static bool CvtSockToPeerPort(int sock, short& port); @@ -109,6 +110,7 @@ class ChmNetDb bool GetHostnameList(const char* target, strlst_t& hostnames, bool is_cvt_localhost); bool GetIpAddressString(const char* target, std::string& ipaddress, bool is_cvt_localhost); bool GetIpAddressStringList(const char* target, strlst_t& ipaddrs, bool is_cvt_localhost); + bool ReplaceFullLocalName(const char* localneme); bool GetAllHostList(const char* target, strlst_t& expandlist, bool is_cvt_localhost); }; diff --git a/lib/chmstructure.tcc b/lib/chmstructure.tcc index 6f26f65..0ee43b6 100644 --- a/lib/chmstructure.tcc +++ b/lib/chmstructure.tcc @@ -470,7 +470,7 @@ class structure_lap st_ptr_type GetAbsPtr(void) const { return pAbsPtr; } st_ptr_type GetRelPtr(void) const { return CHM_REL(pShmBase, pAbsPtr, st_ptr_type); } - virtual void Reset(st_ptr_type ptr, const void* shmbase, bool is_abs = true); + void Reset(st_ptr_type ptr, const void* shmbase, bool is_abs = true); virtual bool Initialize(void); virtual bool Dump(std::stringstream& sstream, const char* spacer) const; virtual bool Clear(void); diff --git a/tests/chmpxlinetool.cc b/tests/chmpxlinetool.cc index 5094212..29e0641 100644 --- a/tests/chmpxlinetool.cc +++ b/tests/chmpxlinetool.cc @@ -6904,6 +6904,14 @@ int main(int argc, char** argv) // Initialize map HostnameMap::Initialize(); + // Initialize ChmNetDb + // + // [NOTE] + // We can initialize the ChmNetDb singleton by calling ChmNetDb::Get(). + // Initialization allows to configure INET6(Ipv6) in advance. + // + ChmNetDb::Get(); + //---------------------- // initialize nodes information //----------------------