ListenSocket::ListenSocket(ConfigTag* tag, const irc::sockets::sockaddrs& bind_to)
: bind_tag(tag)
+ , bind_sa(bind_to)
{
- irc::sockets::satoap(bind_to, bind_addr, bind_port);
- bind_desc = bind_to.str();
-
fd = socket(bind_to.sa.sa_family, SOCK_STREAM, 0);
if (this->fd == -1)
}
#endif
+ if (tag->getBool("free"))
+ {
+ socklen_t enable = 1;
+#if defined IP_FREEBIND // Linux 2.4+
+ setsockopt(fd, SOL_IP, IP_FREEBIND, &enable, sizeof(enable));
+#elif defined IP_BINDANY // FreeBSD
+ setsockopt(fd, IPPROTO_IP, IP_BINDANY, &enable, sizeof(enable));
+#elif defined SO_BINDANY // NetBSD/OpenBSD
+ setsockopt(fd, SOL_SOCKET, SO_BINDANY, &enable, sizeof(enable));
+#else
+ (void)enable;
+#endif
+ }
+
SocketEngine::SetReuse(fd);
int rv = SocketEngine::Bind(this->fd, bind_to);
if (rv >= 0)
rv = SocketEngine::Listen(this->fd, ServerInstance->Config->MaxConn);
- int timeout = tag->getInt("defer", 0);
+ // Default defer to on for TLS listeners because in TLS the client always speaks first
+ int timeout = tag->getDuration("defer", (tag->getString("ssl").empty() ? 0 : 3));
if (timeout && !rv)
{
#if defined TCP_DEFER_ACCEPT
void ListenSocket::OnEventHandlerRead()
{
irc::sockets::sockaddrs client;
- irc::sockets::sockaddrs server;
+ irc::sockets::sockaddrs server(bind_sa);
socklen_t length = sizeof(client);
int incomingSockfd = SocketEngine::Accept(this, &client.sa, &length);
- ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Accepting connection on socket %s fd %d", bind_desc.c_str(), incomingSockfd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Accepting connection on socket %s fd %d", bind_sa.str().c_str(), incomingSockfd);
if (incomingSockfd < 0)
{
ServerInstance->stats.Refused++;
if (getsockname(incomingSockfd, &server.sa, &sz))
{
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Can't get peername: %s", strerror(errno));
- irc::sockets::aptosa(bind_addr, bind_port, server);
}
if (client.sa.sa_family == AF_INET6)
{
ServerInstance->stats.Refused++;
ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Refusing connection on %s - %s",
- bind_desc.c_str(), res == MOD_RES_DENY ? "Connection refused by module" : "Module for this port not found");
+ bind_sa.str().c_str(), res == MOD_RES_DENY ? "Connection refused by module" : "Module for this port not found");
SocketEngine::Close(incomingSockfd);
}
}