From 998dad52d13280508ff2704a7ef3f9af836b5a25 Mon Sep 17 00:00:00 2001 From: Andrew Stitcher Date: Thu, 26 May 2011 20:38:52 +0000 Subject: QPID-3282: Potential bug in circular connection detection: - make sure that we compare numeric addresses of both local and remote ends of the connection (previously the remote end could be an unresolved hostname) git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1128068 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/cpp/src/qpid/sys/SocketAddress.h | 2 +- qpid/cpp/src/qpid/sys/posix/Socket.cpp | 11 +++++++++-- qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp | 20 +++++++++++++++++--- qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp | 2 +- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/qpid/cpp/src/qpid/sys/SocketAddress.h b/qpid/cpp/src/qpid/sys/SocketAddress.h index 27b9642f2c..c2120338cf 100644 --- a/qpid/cpp/src/qpid/sys/SocketAddress.h +++ b/qpid/cpp/src/qpid/sys/SocketAddress.h @@ -41,7 +41,7 @@ public: QPID_COMMON_EXTERN SocketAddress& operator=(const SocketAddress&); QPID_COMMON_EXTERN ~SocketAddress(); - std::string asString() const; + std::string asString(bool numeric=true) const; private: std::string host; diff --git a/qpid/cpp/src/qpid/sys/posix/Socket.cpp b/qpid/cpp/src/qpid/sys/posix/Socket.cpp index be757ba00f..aa25f8062d 100644 --- a/qpid/cpp/src/qpid/sys/posix/Socket.cpp +++ b/qpid/cpp/src/qpid/sys/posix/Socket.cpp @@ -122,7 +122,14 @@ void Socket::connect(const std::string& host, const std::string& port) const void Socket::connect(const SocketAddress& addr) const { - peername = addr.asString(); + // The display name for an outbound connection needs to be the name that was specified + // for the address rather than a resolved IP address as we don't know which of + // the IP addresses is actually the one that will be connected to. + peername = addr.asString(false); + + // However the string we compare with the local port must be numeric or it might not + // match when it should as getLocalAddress() will always be numeric + std::string connectname = addr.asString(); createSocket(addr); @@ -145,7 +152,7 @@ void Socket::connect(const SocketAddress& addr) const // Raise an error if we see such a connection, since we know there is // no listener on the peer address. // - if (getLocalAddress() == getPeerAddress()) { + if (getLocalAddress() == connectname) { close(); throw Exception(QPID_MSG("Connection refused: " << peername)); } diff --git a/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp b/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp index 542c6f7691..10f1c8a563 100644 --- a/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp +++ b/qpid/cpp/src/qpid/sys/posix/SocketAddress.cpp @@ -61,9 +61,23 @@ SocketAddress::~SocketAddress() } } -std::string SocketAddress::asString() const +std::string SocketAddress::asString(bool numeric) const { - return host + ":" + port; + if (!numeric) + return host + ":" + port; + // Canonicalise into numeric id + const ::addrinfo& ai = getAddrInfo(*this); + char servName[NI_MAXSERV]; + char dispName[NI_MAXHOST]; + if (int rc=::getnameinfo(ai.ai_addr, ai.ai_addrlen, + dispName, sizeof(dispName), + servName, sizeof(servName), + NI_NUMERICHOST | NI_NUMERICSERV) != 0) + throw QPID_POSIX_ERROR(rc); + std::string s(dispName); + s += ":"; + s += servName; + return s; } const ::addrinfo& getAddrInfo(const SocketAddress& sa) @@ -84,7 +98,7 @@ const ::addrinfo& getAddrInfo(const SocketAddress& sa) int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo); if (n != 0) - throw Exception(QPID_MSG("Cannot resolve " << sa.asString() << ": " << ::gai_strerror(n))); + throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n))); } return *sa.addrInfo; diff --git a/qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp b/qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp index 5efdad0183..ac43cd2d23 100644 --- a/qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp +++ b/qpid/cpp/src/qpid/sys/windows/SocketAddress.cpp @@ -63,7 +63,7 @@ SocketAddress::~SocketAddress() ::freeaddrinfo(addrInfo); } -std::string SocketAddress::asString() const +std::string SocketAddress::asString(bool) const { return host + ":" + port; } -- cgit v1.2.1