mirror of https://github.com/Icinga/icinga2.git
Implemented IPv6 support.
This commit is contained in:
parent
3825e2902f
commit
c1a8576c5c
|
@ -25,31 +25,54 @@ void TCPClient::Start(void)
|
|||
|
||||
void TCPClient::Connect(const string& hostname, unsigned short port)
|
||||
{
|
||||
hostent *hent;
|
||||
sockaddr_in sin;
|
||||
m_Role = RoleOutbound;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(port);
|
||||
stringstream s;
|
||||
s << port;
|
||||
string strPort = s.str();
|
||||
|
||||
hent = gethostbyname(hostname.c_str());
|
||||
addrinfo hints;
|
||||
addrinfo *result;
|
||||
|
||||
if (hent != NULL)
|
||||
sin.sin_addr.s_addr = ((in_addr *)hent->h_addr_list[0])->s_addr;
|
||||
else
|
||||
sin.sin_addr.s_addr = inet_addr(hostname.c_str());
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
int rc = connect(GetFD(), (sockaddr *)&sin, sizeof(sin));
|
||||
int rc = getaddrinfo(hostname.c_str(), strPort.c_str(), &hints, &result);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (rc < 0 && WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||
#else /* _WIN32 */
|
||||
if (rc < 0 && errno != EINPROGRESS) {
|
||||
#endif /* _WIN32 */
|
||||
if (rc < 0) {
|
||||
HandleSocketError();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_Role = RoleOutbound;
|
||||
int fd = INVALID_SOCKET;
|
||||
|
||||
for (addrinfo *info = result; info != NULL; info = info->ai_next) {
|
||||
fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
|
||||
|
||||
if (fd == INVALID_SOCKET)
|
||||
continue;
|
||||
|
||||
SetFD(fd);
|
||||
|
||||
rc = connect(fd, info->ai_addr, info->ai_addrlen);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (rc < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
#else /* _WIN32 */
|
||||
if (rc < 0 && errno != EINPROGRESS)
|
||||
#endif /* _WIN32 */
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (fd == INVALID_SOCKET)
|
||||
HandleSocketError();
|
||||
|
||||
freeaddrinfo(result);
|
||||
}
|
||||
|
||||
FIFO::Ptr TCPClient::GetSendQueue(void)
|
||||
|
|
|
@ -37,7 +37,7 @@ void TCPServer::Listen(void)
|
|||
int TCPServer::ReadableEventHandler(const EventArgs& ea)
|
||||
{
|
||||
int fd;
|
||||
sockaddr_in addr;
|
||||
sockaddr_storage addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
|
||||
fd = accept(GetFD(), (sockaddr *)&addr, &addrlen);
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
void TCPSocket::MakeSocket(void)
|
||||
void TCPSocket::MakeSocket(int family)
|
||||
{
|
||||
assert(GetFD() == INVALID_SOCKET);
|
||||
|
||||
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
int fd = socket(family, SOCK_STREAM, 0);
|
||||
|
||||
if (fd == INVALID_SOCKET) {
|
||||
HandleSocketError();
|
||||
|
@ -17,118 +17,106 @@ void TCPSocket::MakeSocket(void)
|
|||
SetFD(fd);
|
||||
}
|
||||
|
||||
void TCPSocket::Bind(unsigned short port)
|
||||
void TCPSocket::Bind(unsigned short port, int family)
|
||||
{
|
||||
Bind(NULL, port);
|
||||
Bind(NULL, port, family);
|
||||
}
|
||||
|
||||
void TCPSocket::Bind(const char *hostname, unsigned short port)
|
||||
void TCPSocket::Bind(const char *hostname, unsigned short port, int family)
|
||||
{
|
||||
stringstream s;
|
||||
s << port;
|
||||
string strPort = s.str();
|
||||
|
||||
addrinfo hints;
|
||||
addrinfo *result;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
if (getaddrinfo(hostname, strPort.c_str(), &hints, &result) < 0) {
|
||||
HandleSocketError();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int fd = INVALID_SOCKET;
|
||||
|
||||
for (addrinfo *info = result; info != NULL; info = info->ai_next) {
|
||||
fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
|
||||
|
||||
if (fd == INVALID_SOCKET)
|
||||
continue;
|
||||
|
||||
SetFD(fd);
|
||||
|
||||
const int optFalse = 0;
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&optFalse, sizeof(optFalse));
|
||||
|
||||
#ifndef _WIN32
|
||||
const int optTrue = 1;
|
||||
setsockopt(GetFD(), SOL_SOCKET, SO_REUSEADDR, (char *)&optTrue, sizeof(optTrue));
|
||||
const int optTrue = 1;
|
||||
setsockopt(GetFD(), SOL_SOCKET, SO_REUSEADDR, (char *)&optTrue, sizeof(optTrue));
|
||||
#endif /* _WIN32 */
|
||||
|
||||
sockaddr_in sin;
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = hostname ? inet_addr(hostname) : htonl(INADDR_ANY);
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
if (::bind(GetFD(), (sockaddr *)&sin, sizeof(sin)) < 0)
|
||||
HandleSocketError();
|
||||
}
|
||||
|
||||
string TCPSocket::GetAddressFromSockaddr(sockaddr *address)
|
||||
{
|
||||
static char buffer[256];
|
||||
int rc = ::bind(fd, info->ai_addr, info->ai_addrlen);
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD BufferLength = sizeof(buffer);
|
||||
|
||||
socklen_t len;
|
||||
if (address->sa_family == AF_INET)
|
||||
len = sizeof(sockaddr_in);
|
||||
else if (address->sa_family == AF_INET6)
|
||||
len = sizeof(sockaddr_in6);
|
||||
else {
|
||||
assert(0);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
if (WSAAddressToString(address, len, NULL, buffer, &BufferLength) != 0)
|
||||
return string();
|
||||
if (rc < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
#else /* _WIN32 */
|
||||
void *IpAddress;
|
||||
|
||||
if (address->sa_family == AF_INET)
|
||||
IpAddress = &(((sockaddr_in *)address)->sin_addr);
|
||||
else
|
||||
IpAddress = &(((sockaddr_in6 *)address)->sin6_addr);
|
||||
|
||||
if (inet_ntop(address->sa_family, IpAddress, buffer, sizeof(buffer)) == NULL)
|
||||
return string();
|
||||
if (rc < 0 && errno != EINPROGRESS)
|
||||
#endif /* _WIN32 */
|
||||
continue;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
unsigned short TCPSocket::GetPortFromSockaddr(sockaddr *address)
|
||||
{
|
||||
if (address->sa_family == AF_INET)
|
||||
return htons(((sockaddr_in *)address)->sin_port);
|
||||
else if (address->sa_family == AF_INET6)
|
||||
return htons(((sockaddr_in6 *)address)->sin6_port);
|
||||
else {
|
||||
assert(0);
|
||||
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool TCPSocket::GetClientSockaddr(sockaddr_storage *address)
|
||||
{
|
||||
socklen_t len = sizeof(*address);
|
||||
|
||||
if (getsockname(GetFD(), (sockaddr *)address, &len) < 0) {
|
||||
if (fd == INVALID_SOCKET)
|
||||
HandleSocketError();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
freeaddrinfo(result);
|
||||
}
|
||||
|
||||
bool TCPSocket::GetPeerSockaddr(sockaddr_storage *address)
|
||||
|
||||
string TCPSocket::GetAddressFromSockaddr(sockaddr *address, socklen_t len)
|
||||
{
|
||||
socklen_t len = sizeof(*address);
|
||||
char host[NI_MAXHOST];
|
||||
char service[NI_MAXSERV];
|
||||
|
||||
if (getpeername(GetFD(), (sockaddr *)address, &len) < 0) {
|
||||
HandleSocketError();
|
||||
if (getnameinfo(address, len, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
|
||||
throw InvalidArgumentException(); /* TODO: throw proper exception */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
stringstream s;
|
||||
s << "[" << host << "]:" << service;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
string TCPSocket::GetClientAddress(void)
|
||||
{
|
||||
sockaddr_storage sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
|
||||
if (!GetClientSockaddr(&sin))
|
||||
return "";
|
||||
if (getsockname(GetFD(), (sockaddr *)&sin, &len) < 0) {
|
||||
HandleSocketError();
|
||||
|
||||
return GetAddressFromSockaddr((sockaddr *)&sin);
|
||||
return string();
|
||||
}
|
||||
|
||||
return GetAddressFromSockaddr((sockaddr *)&sin, len);
|
||||
}
|
||||
|
||||
string TCPSocket::GetPeerAddress(void)
|
||||
{
|
||||
sockaddr_storage sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
|
||||
if (!GetPeerSockaddr(&sin))
|
||||
return "";
|
||||
if (getpeername(GetFD(), (sockaddr *)&sin, &len) < 0) {
|
||||
HandleSocketError();
|
||||
|
||||
return GetAddressFromSockaddr((sockaddr *)&sin);
|
||||
return string();
|
||||
}
|
||||
|
||||
return GetAddressFromSockaddr((sockaddr *)&sin, len);
|
||||
}
|
||||
|
|
|
@ -7,17 +7,16 @@ namespace icinga
|
|||
class I2_BASE_API TCPSocket : public Socket
|
||||
{
|
||||
private:
|
||||
static string GetAddressFromSockaddr(sockaddr *address);
|
||||
static unsigned short GetPortFromSockaddr(sockaddr *address);
|
||||
static string GetAddressFromSockaddr(sockaddr *address, socklen_t len);
|
||||
|
||||
void MakeSocket(int family);
|
||||
|
||||
public:
|
||||
typedef shared_ptr<TCPSocket> Ptr;
|
||||
typedef weak_ptr<TCPSocket> WeakPtr;
|
||||
|
||||
void MakeSocket(void);
|
||||
|
||||
void Bind(unsigned short port);
|
||||
void Bind(const char *hostname, unsigned short port);
|
||||
void Bind(unsigned short port, int family);
|
||||
void Bind(const char *hostname, unsigned short port, int family);
|
||||
|
||||
bool GetClientSockaddr(sockaddr_storage *address);
|
||||
bool GetPeerSockaddr(sockaddr_storage *address);
|
||||
|
|
|
@ -16,8 +16,7 @@ void EndpointManager::AddListener(unsigned short port)
|
|||
JsonRpcServer::Ptr server = make_shared<JsonRpcServer>(m_SSLContext);
|
||||
RegisterServer(server);
|
||||
|
||||
server->MakeSocket();
|
||||
server->Bind(port);
|
||||
server->Bind(port, AF_INET6);
|
||||
server->Listen();
|
||||
server->Start();
|
||||
}
|
||||
|
@ -25,7 +24,7 @@ void EndpointManager::AddListener(unsigned short port)
|
|||
void EndpointManager::AddConnection(string host, unsigned short port)
|
||||
{
|
||||
stringstream s;
|
||||
s << "Adding new endpoint: " << host << ":" << port;
|
||||
s << "Adding new endpoint: [" << host << "]:" << port;
|
||||
Application::Log(s.str());
|
||||
|
||||
JsonRpcEndpoint::Ptr endpoint = make_shared<JsonRpcEndpoint>();
|
||||
|
|
|
@ -63,7 +63,6 @@ void JsonRpcEndpoint::Connect(string host, unsigned short port, shared_ptr<SSL_C
|
|||
m_PeerPort = port;
|
||||
|
||||
JsonRpcClient::Ptr client = make_shared<JsonRpcClient>(RoleOutbound, sslContext);
|
||||
client->MakeSocket();
|
||||
client->Connect(host, port);
|
||||
client->Start();
|
||||
|
||||
|
|
Loading…
Reference in New Issue