* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
+ * Copyright (C) 2021 Ariadne Conill
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "s_assert.h"
#include "logger.h"
-static struct Listener *ListenerPollList = NULL;
+static rb_dlink_list listener_list = {};
static int accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data);
static void accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data);
static SSL_OPEN_CB accept_sslcallback;
listener->F = NULL;
memcpy(&listener->addr, addr, sizeof(listener->addr));
- listener->next = NULL;
return listener;
}
s_assert(NULL != listener);
if(listener == NULL)
return;
- /*
- * remove from listener list
- */
- if(listener == ListenerPollList)
- ListenerPollList = listener->next;
- else
- {
- struct Listener *prev = ListenerPollList;
- for (; prev; prev = prev->next)
- {
- if(listener == prev->next)
- {
- prev->next = listener->next;
- break;
- }
- }
- }
- /* free */
+ rb_dlinkDelete(&listener->lnode, &listener_list);
rb_free(listener);
}
void
show_ports(struct Client *source_p)
{
- struct Listener *listener = 0;
+ rb_dlink_node *n;
- for (listener = ListenerPollList; listener; listener = listener->next)
+ RB_DLINK_FOREACH(n, listener_list.head)
{
+ struct Listener *listener = n->data;
+
sendto_one_numeric(source_p, RPL_STATSPLINE,
form_str(RPL_STATSPLINE), 'P',
get_listener_port(listener),
}
if (F == NULL) {
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Cannot open socket for listener on %s port %d",
listener->sctp ? "SCTP" : "TCP",
get_listener_port(listener));
if (ret) {
errstr = strerror(rb_get_sockerr(F));
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Cannot bind for listener on %s port %d: %s",
listener->sctp ? "SCTP" : "TCP",
get_listener_port(listener), errstr);
if(rb_listen(F, SOMAXCONN, listener->defer_accept))
{
errstr = strerror(rb_get_sockerr(F));
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Cannot listen() for listener on %s port %d: %s",
listener->sctp ? "SCTP" : "TCP",
get_listener_port(listener), errstr);
static struct Listener *
find_listener(struct rb_sockaddr_storage *addr, int sctp)
{
- struct Listener *listener = NULL;
+ rb_dlink_node *n;
struct Listener *last_closed = NULL;
- for (listener = ListenerPollList; listener; listener = listener->next) {
+ RB_DLINK_FOREACH(n, listener_list.head) {
+ struct Listener *listener = n->data;
+
if (listener->sctp != sctp)
continue;
return;
} else {
listener = make_listener(vaddr);
- listener->next = ListenerPollList;
- ListenerPollList = listener;
+ rb_dlinkAdd(listener, &listener->lnode, &listener_list);
}
listener->F = NULL;
return;
} else {
listener = make_listener(vaddr);
- listener->next = ListenerPollList;
- ListenerPollList = listener;
+ rb_dlinkAdd(listener, &listener->lnode, &listener_list);
}
listener->F = NULL;
* close_listeners - close and free all listeners that are not being used
*/
void
-close_listeners()
+close_listeners(void)
{
- struct Listener *listener;
- struct Listener *listener_next = 0;
+ rb_dlink_node *n, *tn;
+
/*
* close all 'extra' listening ports we have
*/
- for (listener = ListenerPollList; listener; listener = listener_next)
+ RB_DLINK_FOREACH_SAFE(n, tn, listener_list.head)
{
- listener_next = listener->next;
+ struct Listener *listener = n->data;
+
close_listener(listener);
}
+
+ rb_close_pending_fds();
}
/*
SetSSL(new_client);
SetSecure(new_client);
}
+ else
+ {
+ struct ConfItem *aconf;
+ aconf = find_conf_by_address(NULL, NULL, NULL, sai, CONF_SECURE | 1, sai->sa_family, NULL, NULL);
+
+ if (aconf != NULL)
+ SetSecure(new_client);
+ }
if (listener->wsock)
{
return 0; /* use default handler if status != RB_OK */
}
-static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n";
-
static int
accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data)
{
static time_t last_oper_notice = 0;
int len;
+ static const char *allinuse = "ERROR :All connections in use\r\n";
+ static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n";
+
+ static const unsigned char ssldeniederrcode[] = {
+ // SSLv3.0 Fatal Alert: Access Denied
+ 0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x31
+ };
+
+ static const unsigned char sslinternalerrcode[] = {
+ // SSLv3.0 Fatal Alert: Internal Error
+ 0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x50
+ };
+
if(listener->ssl && (!ircd_ssl_ok || !get_ssld_count()))
{
rb_close(F);
*/
if((last_oper_notice + 20) <= rb_current_time())
{
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"All connections in use. (%s)",
get_listener_name(listener));
last_oper_notice = rb_current_time();
}
- rb_write(F, "ERROR :All connections in use\r\n", 31);
+ if(listener->ssl)
+ rb_write(F, sslinternalerrcode, sizeof(sslinternalerrcode));
+ else
+ rb_write(F, allinuse, strlen(allinuse));
+
rb_close(F);
return 0;
}
{
ServerStats.is_ref++;
- if(ConfigFileEntry.dline_with_reason)
+ if(listener->ssl)
+ {
+ rb_write(F, ssldeniederrcode, sizeof(ssldeniederrcode));
+ }
+ else if(ConfigFileEntry.dline_with_reason)
{
len = snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf));
if (len >= (int)(sizeof(buf)-1))
buf[sizeof(buf) - 2] = '\n';
buf[sizeof(buf) - 1] = '\0';
}
+ rb_write(F, buf, strlen(buf));
}
else
+ {
strcpy(buf, "ERROR :You have been D-lined.\r\n");
+ rb_write(F, buf, strlen(buf));
+ }
- rb_write(F, buf, strlen(buf));
rb_close(F);
return 0;
}
- if(check_reject(F, addr)) {
+ if(check_reject(F, addr, listener->ssl)) {
/* Reject the connection without closing the socket
* because it is now on the delay_exit list. */
return 0;
if(throttle_add(addr))
{
- rb_write(F, toofast, strlen(toofast));
+ if(listener->ssl)
+ rb_write(F, ssldeniederrcode, sizeof(ssldeniederrcode));
+ else
+ rb_write(F, toofast, strlen(toofast));
+
rb_close(F);
return 0;
}