Add the outgoing_bind option

Lets the admin choose a local address to bind each outgoing (IRC) socket.
This commit is contained in:
Florent Le Coz
2015-12-01 16:08:40 +01:00
parent 6dcb21a032
commit 241768836d
4 changed files with 46 additions and 0 deletions
+9
View File
@@ -120,6 +120,15 @@ The configuration file uses a simple format of the form
negociating a TLS session. By default this value is unset and biboumi
tries a list of well-known paths.
`outgoing_bind`
An address (IPv4 or IPv6) to bind the outgoing sockets to. If no value is
specified, it will use the one assigned by the operating system. You can
for example use outgoing_bind=192.168.1.11 to force biboumi to use the
interface with this address. Note that this is only used for connections
to IRC servers, the connection to the XMPP server is always done locally
on 127.0.0.1.
The configuration can be re-read at runtime (you can for example change the
log level without having to restart biboumi) by sending SIGUSR1 or SIGUSR2
(see kill(1)) to the process.
+28
View File
@@ -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));
@@ -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;
+3
View File
@@ -86,6 +86,9 @@ void IrcClient::start()
this->bridge->send_xmpp_message(this->hostname, "", "Connecting to "s +
this->hostname + ":" + port + " (" +
(tls ? "encrypted" : "not encrypted") + ")");
this->bind_addr = Config::get("outgoing_bind", "");
this->connect(this->hostname, port, tls);
}