aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-03-22 10:52:04 -0400
committerJack Lloyd <[email protected]>2017-03-22 10:52:04 -0400
commitddb6aa92586bafda7a934c61bd7dab2f1b9ee079 (patch)
treeabecb6b5528b6fe5e23a65c45a696aebdb61dbc2 /src
parent1ef6a03bea07a24be164f2b0911fbe56cc2e0f69 (diff)
parentf44623208cf73022bdbfb987c1586b637b773594 (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.cpp46
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;
}