diff options
author | Florent Le Coz <louiz@louiz.org> | 2015-12-01 16:08:40 +0100 |
---|---|---|
committer | Florent Le Coz <louiz@louiz.org> | 2015-12-01 16:08:40 +0100 |
commit | 241768836ddfb9e3609f987224cd821058fcc948 (patch) | |
tree | 8f7929225c3ef8dfb785ea0004d2ecf91db4dfe9 /louloulibs/network | |
parent | 6dcb21a032d47cd3a1f6f2d5d795a1c0f67b382e (diff) | |
download | biboumi-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/network')
-rw-r--r-- | louloulibs/network/tcp_socket_handler.cpp | 28 | ||||
-rw-r--r-- | louloulibs/network/tcp_socket_handler.hpp | 6 |
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; |