From 84f469a20b7efc18ea7bb03f63aade9aa0a74b8a Mon Sep 17 00:00:00 2001 From: Andrew Stitcher Date: Fri, 16 Nov 2012 14:27:29 +0000 Subject: QPID-3351: Provide ability to specify the network interfaces Add listening to specific ports to SSL git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1410365 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/cpp/src/qpid/sys/SslPlugin.cpp | 108 +++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 38 deletions(-) (limited to 'qpid/cpp/src') diff --git a/qpid/cpp/src/qpid/sys/SslPlugin.cpp b/qpid/cpp/src/qpid/sys/SslPlugin.cpp index 3b56f9788b..0638b55db6 100644 --- a/qpid/cpp/src/qpid/sys/SslPlugin.cpp +++ b/qpid/cpp/src/qpid/sys/SslPlugin.cpp @@ -29,6 +29,7 @@ #include "qpid/sys/ssl/util.h" #include "qpid/sys/ssl/SslSocket.h" #include "qpid/sys/SocketAddress.h" +#include "qpid/sys/SystemInfo.h" #include "qpid/sys/Poller.h" #include @@ -72,10 +73,8 @@ class SslProtocolFactory : public ProtocolFactory { bool nodict; public: - SslProtocolFactory(const std::string& host, const std::string& port, - const SslServerOptions&, - int backlog, bool nodelay, - Timer& timer, uint32_t maxTime); + SslProtocolFactory(const qpid::broker::Broker::Options& opts, const SslServerOptions& options, + Timer& timer); void accept(Poller::shared_ptr, ConnectionCodec::Factory*); void connect(Poller::shared_ptr, const std::string& host, const std::string& port, ConnectionCodec::Factory*, @@ -133,15 +132,15 @@ static struct SslPlugin : public Plugin { const broker::Broker::Options& opts = broker->getOptions(); ProtocolFactory::shared_ptr protocol( - static_cast(new SslProtocolFactory("", boost::lexical_cast(options.port), - options, - opts.connectionBacklog, - opts.tcpNoDelay, - broker->getTimer(), opts.maxNegotiateTime))); - QPID_LOG(notice, "Listening for " << - (options.multiplex ? "SSL or TCP" : "SSL") << - " connections on TCP/TCP6 port " << - protocol->getPort()); + static_cast(new SslProtocolFactory(opts, options, broker->getTimer()))); + + if (protocol->getPort()!=0 ) { + QPID_LOG(notice, "Listening for " << + (options.multiplex ? "SSL or TCP" : "SSL") << + " connections on TCP/TCP6 port " << + protocol->getPort()); + } + broker->registerProtocolFactory("ssl", protocol); } catch (const std::exception& e) { QPID_LOG(error, "Failed to initialise SSL plugin: " << e.what()); @@ -151,41 +150,74 @@ static struct SslPlugin : public Plugin { } } sslPlugin; -SslProtocolFactory::SslProtocolFactory(const std::string& host, const std::string& port, - const SslServerOptions& options, - int backlog, bool nodelay, - Timer& timer, uint32_t maxTime) : +namespace { + // Expand list of Interfaces and addresses to a list of addresses + std::vector expandInterfaces(const std::vector& interfaces) { + std::vector addresses; + // If there are no specific interfaces listed use a single "" to listen on every interface + if (interfaces.empty()) { + addresses.push_back(""); + return addresses; + } + for (unsigned i = 0; i < interfaces.size(); ++i) { + const std::string& interface = interfaces[i]; + if (!(SystemInfo::getInterfaceAddresses(interface, addresses))) { + // We don't have an interface of that name - + // Check for IPv6 ('[' ']') brackets and remove them + // then pass to be looked up directly + if (interface[0]=='[' && interface[interface.size()-1]==']') { + addresses.push_back(interface.substr(1, interface.size()-2)); + } else { + addresses.push_back(interface); + } + } + } + return addresses; + } +} + +SslProtocolFactory::SslProtocolFactory(const qpid::broker::Broker::Options& opts, const SslServerOptions& options, + Timer& timer) : brokerTimer(timer), - maxNegotiateTime(maxTime), - tcpNoDelay(nodelay), + maxNegotiateTime(opts.maxNegotiateTime), + tcpNoDelay(opts.tcpNoDelay), nodict(options.nodict) { - SocketAddress sa(host, port); - - // We must have at least one resolved address - QPID_LOG(info, "Listening to: " << sa.asString()) - Socket* s = options.multiplex ? - new SslMuxSocket(options.certName, options.clientAuth) : - new SslSocket(options.certName, options.clientAuth); - uint16_t lport = s->listen(sa, backlog); - QPID_LOG(debug, "Listened to: " << lport); - listeners.push_back(s); - - listeningPort = lport; - - // Try any other resolved addresses - while (sa.nextAddress()) { - // Hack to ensure that all listening connections are on the same port - sa.setAddrInfoPort(listeningPort); + std::vector addresses = expandInterfaces(opts.listenInterfaces); + if (addresses.empty()) { + // We specified some interfaces, but couldn't find addresses for them + QPID_LOG(warning, "SSL: No specified network interfaces found: Not Listening"); + listeningPort = 0; + } + + for (unsigned i = 0; i(options.port)); + + // We must have at least one resolved address QPID_LOG(info, "Listening to: " << sa.asString()) Socket* s = options.multiplex ? new SslMuxSocket(options.certName, options.clientAuth) : new SslSocket(options.certName, options.clientAuth); - uint16_t lport = s->listen(sa, backlog); + uint16_t lport = s->listen(sa, opts.connectionBacklog); QPID_LOG(debug, "Listened to: " << lport); listeners.push_back(s); - } + listeningPort = lport; + + // Try any other resolved addresses + while (sa.nextAddress()) { + // Hack to ensure that all listening connections are on the same port + sa.setAddrInfoPort(listeningPort); + QPID_LOG(info, "Listening to: " << sa.asString()) + Socket* s = options.multiplex ? + new SslMuxSocket(options.certName, options.clientAuth) : + new SslSocket(options.certName, options.clientAuth); + uint16_t lport = s->listen(sa, opts.connectionBacklog); + QPID_LOG(debug, "Listened to: " << lport); + listeners.push_back(s); + } + } } -- cgit v1.2.1