From 241768836ddfb9e3609f987224cd821058fcc948 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 1 Dec 2015 16:08:40 +0100 Subject: Add the outgoing_bind option Lets the admin choose a local address to bind each outgoing (IRC) socket. --- louloulibs/network/tcp_socket_handler.cpp | 28 ++++++++++++++++++++++++++++ louloulibs/network/tcp_socket_handler.hpp | 6 ++++++ 2 files changed, 34 insertions(+) (limited to 'louloulibs/network') diff --git a/louloulibs/network/tcp_socket_handler.cpp b/louloulibs/network/tcp_socket_handler.cpp index 78efdce..e6901c8 100644 --- a/louloulibs/network/tcp_socket_handler.cpp +++ b/louloulibs/network/tcp_socket_handler.cpp @@ -56,6 +56,34 @@ void TCPSocketHandler::init_socket(const struct addrinfo* rp) ::close(this->socket); if ((this->socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1) throw std::runtime_error("Could not create socket: "s + strerror(errno)); + // Bind the socket to a specific address, if specified + if (!this->bind_addr.empty()) + { + // Convert the address from string format to a sockaddr that can be + // used in bind() + struct addrinfo* result; + int err = ::getaddrinfo(this->bind_addr.data(), nullptr, nullptr, &result); + if (err != 0) + log_error("Failed to bind socket to " << this->bind_addr << ": " + << gai_strerror(err)); + else + { + struct addrinfo* rp; + int bind_error; + for (rp = result; rp; rp = rp->ai_next) + { + if ((bind_error = ::bind(this->socket, + reinterpret_cast(rp->ai_addr), + rp->ai_addrlen)) == 0) + break; + } + if (!rp) + log_error("Failed to bind socket to " << this->bind_addr << ": " + << strerror(bind_error)); + else + log_info("Socket successfully bound to " << this->bind_addr); + } + } int optval = 1; if (::setsockopt(this->socket, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1) log_warning("Failed to enable TCP keepalive on socket: " << strerror(errno)); diff --git a/louloulibs/network/tcp_socket_handler.hpp b/louloulibs/network/tcp_socket_handler.hpp index d33b919..9f5caa3 100644 --- a/louloulibs/network/tcp_socket_handler.hpp +++ b/louloulibs/network/tcp_socket_handler.hpp @@ -224,6 +224,12 @@ protected: bool hostname_resolution_failed; + /** + * Address to bind the socket to, before calling connect(). + * If empty, it’s equivalent to binding to INADDR_ANY. + */ + std::string bind_addr; + private: TCPSocketHandler(const TCPSocketHandler&) = delete; TCPSocketHandler(TCPSocketHandler&&) = delete; -- cgit v1.2.3