diff options
author | Jack Lloyd <[email protected]> | 2017-03-22 10:52:04 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-03-22 10:52:04 -0400 |
commit | ddb6aa92586bafda7a934c61bd7dab2f1b9ee079 (patch) | |
tree | abecb6b5528b6fe5e23a65c45a696aebdb61dbc2 /src | |
parent | 1ef6a03bea07a24be164f2b0911fbe56cc2e0f69 (diff) | |
parent | f44623208cf73022bdbfb987c1586b637b773594 (diff) |
Merge GH #931 Add support for reaching IPv6 hosts in the tls_client CLI
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/tls_client.cpp | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/src/cli/tls_client.cpp b/src/cli/tls_client.cpp index 30871791c..f3b3425a5 100644 --- a/src/cli/tls_client.cpp +++ b/src/cli/tls_client.cpp @@ -218,37 +218,43 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks private: int connect_to_host(const std::string& host, uint16_t port, bool tcp) { - hostent* host_addr = ::gethostbyname(host.c_str()); + addrinfo hints = {}; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = tcp ? SOCK_STREAM : SOCK_DGRAM; + addrinfo *res, *rp = nullptr; - if(!host_addr) - throw CLI_Error("gethostbyname failed for " + host); - - if(host_addr->h_addrtype != AF_INET) // FIXME - throw CLI_Error(host + " has IPv6 address, not supported"); + if(::getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res) != 0) + { + throw CLI_Error("getaddrinfo failed for " + host); + } - int type = tcp ? SOCK_STREAM : SOCK_DGRAM; + int fd = 0; - int fd = ::socket(PF_INET, type, 0); - if(fd == -1) - throw CLI_Error("Unable to acquire socket"); + for(rp = res; rp != nullptr; rp = rp->ai_next) + { + fd = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - sockaddr_in socket_info; - ::memset(&socket_info, 0, sizeof(socket_info)); - socket_info.sin_family = AF_INET; - socket_info.sin_port = htons(port); + if(fd == -1) + { + continue; + } - ::memcpy(&socket_info.sin_addr, - host_addr->h_addr, - host_addr->h_length); + if(::connect(fd, rp->ai_addr, rp->ai_addrlen) != 0) + { + close(fd); + continue; + } - socket_info.sin_addr = *reinterpret_cast<struct in_addr*>(host_addr->h_addr); // FIXME + break; + } - if(::connect(fd, reinterpret_cast<sockaddr*>(&socket_info), sizeof(struct sockaddr)) != 0) + if(rp == nullptr) // no address succeeded { - ::close(fd); throw CLI_Error("connect failed"); } + ::freeaddrinfo(res); + return fd; } |