summaryrefslogtreecommitdiff
path: root/louloulibs
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2015-12-01 16:08:40 +0100
committerFlorent Le Coz <louiz@louiz.org>2015-12-01 16:08:40 +0100
commit241768836ddfb9e3609f987224cd821058fcc948 (patch)
tree8f7929225c3ef8dfb785ea0004d2ecf91db4dfe9 /louloulibs
parent6dcb21a032d47cd3a1f6f2d5d795a1c0f67b382e (diff)
downloadbiboumi-241768836ddfb9e3609f987224cd821058fcc948.tar.gz
biboumi-241768836ddfb9e3609f987224cd821058fcc948.tar.bz2
biboumi-241768836ddfb9e3609f987224cd821058fcc948.tar.xz
biboumi-241768836ddfb9e3609f987224cd821058fcc948.zip
Add the outgoing_bind option
Lets the admin choose a local address to bind each outgoing (IRC) socket.
Diffstat (limited to 'louloulibs')
-rw-r--r--louloulibs/network/tcp_socket_handler.cpp28
-rw-r--r--louloulibs/network/tcp_socket_handler.hpp6
2 files changed, 34 insertions, 0 deletions
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<const struct sockaddr*>(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;