[fix](fqdn)Fqdn with ipv6 (#22454)
now,`hostname_to_ip` only can resolve `ipv4`,Therefore, a method is provided to parse ipv4 or ipv6 based on parameters。 when `_heartbeat` call `hostname_to_ip`,Resolve to ipv4 or ipv6, determined by `BackendOptions.is_bind_ipv6` Decision Additionally, a method is provided to first attempt to parse the host into ipv4, and then try ipv6 if it fails
This commit is contained in:
@ -118,14 +118,16 @@ Status HeartbeatServer::_heartbeat(const TMasterInfo& master_info) {
|
||||
if (!is_valid_ip(master_info.backend_ip)) {
|
||||
//step2: resolve FQDN to IP
|
||||
std::string ip;
|
||||
Status status = hostname_to_ip(master_info.backend_ip, ip);
|
||||
Status status =
|
||||
hostname_to_ip(master_info.backend_ip, ip, BackendOptions::is_bind_ipv6());
|
||||
if (!status.ok()) {
|
||||
std::stringstream ss;
|
||||
ss << "can not get ip from fqdn: " << status.to_string();
|
||||
LOG(WARNING) << ss.str();
|
||||
return status;
|
||||
}
|
||||
|
||||
LOG(INFO) << "master_info.backend_ip: " << master_info.backend_ip
|
||||
<< ", hostname_to_ip: " << ip;
|
||||
//step3: get all ips of the interfaces on this machine
|
||||
std::vector<InetAddress> hosts;
|
||||
status = get_hosts(&hosts);
|
||||
|
||||
@ -72,70 +72,69 @@ Status get_hostname(std::string* hostname) {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status hostname_to_ip_addrs(const std::string& name, std::vector<std::string>* addresses) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_INET; // IPv4 addresses only
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
struct addrinfo* addr_info;
|
||||
|
||||
if (getaddrinfo(name.c_str(), nullptr, &hints, &addr_info) != 0) {
|
||||
return Status::InternalError("Could not find IPv4 address for: {}", name);
|
||||
}
|
||||
|
||||
addrinfo* it = addr_info;
|
||||
|
||||
while (it != nullptr) {
|
||||
char addr_buf[64];
|
||||
const char* result =
|
||||
inet_ntop(AF_INET, &((sockaddr_in*)it->ai_addr)->sin_addr, addr_buf, 64);
|
||||
|
||||
if (result == nullptr) {
|
||||
freeaddrinfo(addr_info);
|
||||
return Status::InternalError("Could not convert IPv4 address for: {}", name);
|
||||
}
|
||||
|
||||
// add address if not exists
|
||||
std::string address = std::string(addr_buf);
|
||||
if (std::find(addresses->begin(), addresses->end(), address) != addresses->end()) {
|
||||
LOG(WARNING) << "Repeated ip addresses has been found for host: " << name
|
||||
<< ", ip address:" << address
|
||||
<< ", please check your network configuration";
|
||||
} else {
|
||||
addresses->push_back(address);
|
||||
}
|
||||
it = it->ai_next;
|
||||
}
|
||||
|
||||
freeaddrinfo(addr_info);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
bool is_valid_ip(const std::string& ip) {
|
||||
unsigned char buf[sizeof(struct in6_addr)];
|
||||
return (inet_pton(AF_INET6, ip.data(), buf) > 0) || (inet_pton(AF_INET, ip.data(), buf) > 0);
|
||||
}
|
||||
|
||||
Status hostname_to_ip(const std::string& host, std::string& ip) {
|
||||
std::vector<std::string> addresses;
|
||||
Status status = hostname_to_ip_addrs(host, &addresses);
|
||||
if (!status.ok()) {
|
||||
LOG(WARNING) << "status of hostname_to_ip_addrs was not ok, err is " << status.to_string();
|
||||
Status status = hostname_to_ipv4(host, ip);
|
||||
if (status.ok()) {
|
||||
return status;
|
||||
}
|
||||
if (addresses.size() != 1) {
|
||||
std::stringstream ss;
|
||||
std::copy(addresses.begin(), addresses.end(), std::ostream_iterator<std::string>(ss, ","));
|
||||
LOG(WARNING)
|
||||
<< "the number of addresses could only be equal to 1, failed to get ip from host:"
|
||||
<< host << ", addresses:" << ss.str();
|
||||
return Status::InternalError(
|
||||
"the number of addresses could only be equal to 1, failed to get ip from host: "
|
||||
"{}, addresses:{}",
|
||||
host, ss.str());
|
||||
return hostname_to_ipv6(host, ip);
|
||||
}
|
||||
|
||||
Status hostname_to_ip(const std::string& host, std::string& ip, bool ipv6) {
|
||||
if (ipv6) {
|
||||
return hostname_to_ipv6(host, ip);
|
||||
} else {
|
||||
return hostname_to_ipv4(host, ip);
|
||||
}
|
||||
ip = addresses[0];
|
||||
}
|
||||
|
||||
Status hostname_to_ipv4(const std::string& host, std::string& ip) {
|
||||
addrinfo hints, *res;
|
||||
in_addr addr;
|
||||
|
||||
memset(&hints, 0, sizeof(addrinfo));
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = AF_INET;
|
||||
int err = getaddrinfo(host.c_str(), NULL, &hints, &res);
|
||||
if (err != 0) {
|
||||
LOG(WARNING) << "failed to get ip from host: " << host << "err:" << gai_strerror(err);
|
||||
return Status::InternalError("failed to get ip from host: {}, err: {}", host,
|
||||
gai_strerror(err));
|
||||
}
|
||||
|
||||
addr.s_addr = ((sockaddr_in*)(res->ai_addr))->sin_addr.s_addr;
|
||||
ip = inet_ntoa(addr);
|
||||
|
||||
freeaddrinfo(res);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status hostname_to_ipv6(const std::string& host, std::string& ip) {
|
||||
char ipstr2[128];
|
||||
struct sockaddr_in6* sockaddr_ipv6;
|
||||
|
||||
struct addrinfo *answer, hint;
|
||||
bzero(&hint, sizeof(hint));
|
||||
hint.ai_family = AF_INET6;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
int err = getaddrinfo(host.c_str(), NULL, &hint, &answer);
|
||||
if (err != 0) {
|
||||
LOG(WARNING) << "failed to get ip from host: " << host << "err:" << gai_strerror(err);
|
||||
return Status::InternalError("failed to get ip from host: {}, err: {}", host,
|
||||
gai_strerror(err));
|
||||
}
|
||||
|
||||
sockaddr_ipv6 = reinterpret_cast<struct sockaddr_in6*>(answer->ai_addr);
|
||||
inet_ntop(AF_INET6, &sockaddr_ipv6->sin6_addr, ipstr2, sizeof(ipstr2));
|
||||
ip = ipstr2;
|
||||
fflush(NULL);
|
||||
freeaddrinfo(answer);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
|
||||
@ -43,15 +43,16 @@ private:
|
||||
bool _is_loopback;
|
||||
};
|
||||
|
||||
// Looks up all IP addresses associated with a given hostname. Returns
|
||||
// an error status if any system call failed, otherwise OK. Even if OK
|
||||
// is returned, addresses may still be of zero length.
|
||||
Status hostname_to_ip_addrs(const std::string& name, std::vector<std::string>* addresses);
|
||||
|
||||
bool is_valid_ip(const std::string& ip);
|
||||
|
||||
Status hostname_to_ip(const std::string& host, std::string& ip);
|
||||
|
||||
Status hostname_to_ipv4(const std::string& host, std::string& ip);
|
||||
|
||||
Status hostname_to_ipv6(const std::string& host, std::string& ip);
|
||||
|
||||
Status hostname_to_ip(const std::string& host, std::string& ip, bool ipv6);
|
||||
|
||||
// Finds the first non-localhost IP address in the given list. Returns
|
||||
// true if such an address was found, false otherwise.
|
||||
bool find_first_non_localhost(const std::vector<std::string>& addresses, std::string* addr);
|
||||
|
||||
Reference in New Issue
Block a user