#include "ircd.h"
#include "ircd_defs.h"
#include "numeric.h"
-#include "commio.h"
#include "s_conf.h"
#include "s_newconf.h"
#include "s_stats.h"
#include "send.h"
-#include "memory.h"
#include "s_auth.h"
#include "reject.h"
#include "s_conf.h"
{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
#endif
-static PF accept_connection;
-
static listener_t *ListenerPollList = NULL;
+static int accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data);\r
+static void accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data);
static listener_t *
-make_listener(struct irc_sockaddr_storage *addr)
+make_listener(struct rb_sockaddr_storage *addr)
{
- listener_t *listener = (listener_t *) MyMalloc(sizeof(listener_t));
+ listener_t *listener = (listener_t *) rb_malloc(sizeof(listener_t));
s_assert(0 != listener);
-
listener->name = me.name;
- listener->fd = -1;
- memcpy(&listener->addr, addr, sizeof(struct irc_sockaddr_storage));
+ listener->F = NULL;
+
+ memcpy(&listener->addr, addr, sizeof(struct rb_sockaddr_storage));
listener->next = NULL;
return listener;
}
}
/* free */
- MyFree(listener);
+ rb_free(listener);
}
#define PORTNAMELEN 6 /* ":31337" */
#endif
port = ntohs(((const struct sockaddr_in *)&listener->addr)->sin_port);
- ircsnprintf(buf, sizeof(buf), "%s[%s/%u]", me.name, listener->name, port);
+ rb_snprintf(buf, sizeof(buf), "%s[%s/%u]", me.name, listener->name, port);
return buf;
}
static int
inetport(listener_t *listener)
{
- int fd;
+ rb_fde_t *F;
+ int ret;
int opt = 1;
/*
* At first, open a new socket
*/
- fd = comm_socket(listener->addr.ss_family, SOCK_STREAM, 0, "Listener socket");
+ F = rb_socket(GET_SS_FAMILY(&listener->addr), SOCK_STREAM, 0, "Listener socket");
#ifdef IPV6
if(listener->addr.ss_family == AF_INET6)
}
}
- /*
- * At one point, we enforced a strange arbitrary limit here.
- * We no longer do this, and just check if the fd is valid or not.
- * -nenolod
- */
- if(fd == -1)
- {
- report_error("opening listener socket %s:%s",
- get_listener_name(listener),
- get_listener_name(listener), errno);
- return 0;
+ if(F == NULL)\r
+ {\r
+ report_error("opening listener socket %s:%s",\r
+ get_listener_name(listener), \r
+ get_listener_name(listener), errno);\r
+ return 0;\r
+ }\r
+ else if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus*/\r
+ {\r
+ report_error("no more connections left for listener %s:%s",\r
+ get_listener_name(listener), \r
+ get_listener_name(listener), errno);\r
+ rb_close(F);\r
+ return 0;\r
}
- /*
- * XXX - we don't want to do all this crap for a listener
- * set_sock_opts(listener);
- */
- if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)))
- {
- report_error("setting SO_REUSEADDR for listener %s:%s",
- get_listener_name(listener),
- get_listener_name(listener), errno);
- comm_close(fd);
- return 0;
+ /*\r
+ * XXX - we don't want to do all this crap for a listener\r
+ * set_sock_opts(listener);\r
+ */\r
+ if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)))\r
+ {\r
+ report_error("setting SO_REUSEADDR for listener %s:%s",\r
+ get_listener_name(listener), \r
+ get_listener_name(listener), errno);\r
+ rb_close(F);\r
+ return 0;\r
}
- /*
- * Bind a port to listen for new connections if port is non-null,
- * else assume it is already open and try get something from it.
- */
-
- if(bind(fd, (struct sockaddr *) &listener->addr, GET_SS_LEN(listener->addr)))
- {
- report_error("binding listener socket %s:%s",
- get_listener_name(listener),
- get_listener_name(listener), errno);
- comm_close(fd);
- return 0;
+ /*\r
+ * Bind a port to listen for new connections if port is non-null,\r
+ * else assume it is already open and try get something from it.\r
+ */\r
+\r
+ if(bind(rb_get_fd(F), (struct sockaddr *) &listener->addr, GET_SS_LEN(&listener->addr)))\r
+ {\r
+ report_error("binding listener socket %s:%s",\r
+ get_listener_name(listener), \r
+ get_listener_name(listener), errno);\r
+ rb_close(F);\r
+ return 0;\r
}
- if(listen(fd, RATBOX_SOMAXCONN))
- {
- report_error("listen failed for %s:%s",
- get_listener_name(listener),
- get_listener_name(listener), errno);
- comm_close(fd);
- return 0;
+ if((ret = rb_listen(F, RATBOX_SOMAXCONN)))\r
+ {\r
+ report_error("listen failed for %s:%s", \r
+ get_listener_name(listener), \r
+ get_listener_name(listener), errno);\r
+ rb_close(F);\r
+ return 0;\r
}
- listener->fd = fd;
-
- /* Listen completion events are READ events .. */
-
- accept_connection(fd, listener);
+ listener->F = F;\r
+\r
+ rb_accept_tcp(listener->F, accept_precallback, accept_callback, listener);
return 1;
}
static listener_t *
-find_listener(struct irc_sockaddr_storage *addr)
+find_listener(struct rb_sockaddr_storage *addr)
{
listener_t *listener = NULL;
listener_t *last_closed = NULL;
if(in4->sin_addr.s_addr == lin4->sin_addr.s_addr &&
in4->sin_port == lin4->sin_port )
{
- if(listener->fd == -1)
- last_closed = listener;
- else
+ if(listener->F == NULL)\r
+ last_closed = listener;\r
+ else\r
return(listener);
}
break;
if(IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &lin6->sin6_addr) &&
in6->sin6_port == lin6->sin6_port)
{
- if(listener->fd == -1)
- last_closed = listener;
- else
+ if(listener->F == NULL)\r
+ last_closed = listener;\r
+ else\r
return(listener);
}
break;
add_listener(int port, const char *vhost_ip, int family)
{
listener_t *listener;
- struct irc_sockaddr_storage vaddr;
+ struct rb_sockaddr_storage vaddr;
/*
* if no port in conf line, don't bother
switch(family)
{
case AF_INET:
- SET_SS_LEN(vaddr, sizeof(struct sockaddr_in));
+ SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in));
((struct sockaddr_in *)&vaddr)->sin_port = htons(port);
break;
#ifdef IPV6
case AF_INET6:
- SET_SS_LEN(vaddr, sizeof(struct sockaddr_in6));
+ SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in6));
((struct sockaddr_in6 *)&vaddr)->sin6_port = htons(port);
break;
#endif
}
if((listener = find_listener(&vaddr)))
{
- if(listener->fd > -1)
+ if(listener->F != NULL)\r
return;
}
else
ListenerPollList = listener;
}
- listener->fd = -1;
+ listener->F = NULL;
if(inetport(listener))
listener->active = 1;
s_assert(listener != NULL);
if(listener == NULL)
return;
- if(listener->fd >= 0)
- {
- comm_close(listener->fd);
- listener->fd = -1;
+ if(listener->F != NULL)\r
+ {\r
+ rb_close(listener->F);\r
+ listener->F = NULL;\r
}
listener->active = 0;
* The client is sent to the auth module for verification, and not put in
* any client list yet.
*/
-static void
-add_connection(listener_t *listener, int fd, struct sockaddr *sai, int exempt)
+static void\r
+add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, int exempt)
{
struct Client *new_client;
s_assert(NULL != listener);
*/
new_client = make_client(NULL);
- memcpy(&new_client->localClient->ip, sai, sizeof(struct irc_sockaddr_storage));
+ memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage));
/*
* copy address to 'sockhost' as a string, copy it to host too
strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));
-#ifdef IPV6
- if(new_client->localClient->ip.ss_family == AF_INET6 && ConfigFileEntry.dot_in_ip6_addr == 1)
- {
- strlcat(new_client->host, ".", sizeof(new_client->host));
- }
-#endif
-
- new_client->localClient->fd = fd;
+ new_client->localClient->F = F;
new_client->localClient->listener = listener;
++listener->ref_count;
start_auth(new_client);
}
-
-static void
-accept_connection(int pfd, void *data)
-{
- static time_t last_oper_notice = 0;
- struct irc_sockaddr_storage sai;
- socklen_t addrlen = sizeof(sai);
- int fd;
- listener_t *listener = data;
- struct ConfItem *aconf;
- char buf[BUFSIZE];
-
- s_assert(listener != NULL);
- if(listener == NULL)
- return;
- /*
- * There may be many reasons for error return, but
- * in otherwise correctly working environment the
- * probable cause is running out of file descriptors
- * (EMFILE, ENFILE or others?). The man pages for
- * accept don't seem to list these as possible,
- * although it's obvious that it may happen here.
- * Thus no specific errors are tested at this
- * point, just assume that connections cannot
- * be accepted until some old is closed first.
- */
-
- fd = comm_accept(listener->fd, (struct sockaddr *)&sai, &addrlen);
- if(fd < 0)
- {
- /* Re-register a new IO request for the next accept .. */
- comm_setselect(listener->fd, FDLIST_SERVICE,
- COMM_SELECT_READ, accept_connection, listener, 0);
- return;
- }
-
- /* This needs to be done here, otherwise we break dlines */
- mangle_mapped_sockaddr((struct sockaddr *)&sai);
-
- /*
- * check for connection limit
- * TBD: this is stupid... either we have a socket or we don't. -nenolod
- */
- if((comm_get_maxconnections() - 10) < fd)
- {
- ++ServerStats->is_ref;
- /*
- * slow down the whining to opers bit
- */
- if((last_oper_notice + 20) <= CurrentTime)
- {
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
- "All connections in use. (%s)",
- get_listener_name(listener));
- last_oper_notice = CurrentTime;
- }
-
- write(fd, "ERROR :All connections in use\r\n", 32);
- comm_close(fd);
- /* Re-register a new IO request for the next accept .. */
- comm_setselect(listener->fd, FDLIST_SERVICE,
- COMM_SELECT_READ, accept_connection, listener, 0);
- return;
- }
-
- /* Do an initial check we aren't connecting too fast or with too many
- * from this IP... */
- aconf = find_dline((struct sockaddr *) &sai, sai.ss_family);
- /* check it wasn't an exempt */
- if (aconf != NULL && (aconf->status & CONF_EXEMPTDLINE) == 0)
- {
- ServerStats->is_ref++;
-
- if(ConfigFileEntry.dline_with_reason)
- {
- if (ircsnprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", aconf->passwd) >= (sizeof(buf)-1))
- {
- buf[sizeof(buf) - 3] = '\r';
- buf[sizeof(buf) - 2] = '\n';
- buf[sizeof(buf) - 1] = '\0';
- }
- }
- else
- ircsprintf(buf, "ERROR :You have been D-lined.\r\n");
-
- write(fd, buf, strlen(buf));
- comm_close(fd);
-
- /* Re-register a new IO request for the next accept .. */
- comm_setselect(listener->fd, FDLIST_SERVICE,
- COMM_SELECT_READ, accept_connection, listener, 0);
- return;
- }
-
- ServerStats->is_ac++;
- add_connection(listener, fd, (struct sockaddr *)&sai, aconf ? 1 : 0);
-
- /* Re-register a new IO request for the next accept .. */
- comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
- accept_connection, listener, 0);
+static int\r
+accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data)\r
+{\r
+ struct Listener *listener = (struct Listener *)data;\r
+ char buf[BUFSIZE];\r
+ struct ConfItem *aconf;\r
+ static time_t last_oper_notice = 0;\r
+\r
+ if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus */\r
+ {\r
+ ++ServerStats->is_ref;\r
+ /*\r
+ * slow down the whining to opers bit\r
+ */\r
+ if((last_oper_notice + 20) <= rb_current_time())\r
+ {\r
+ sendto_realops_flags(SNO_GENERAL, L_ALL,\r
+ "All connections in use. (%s)",\r
+ get_listener_name(listener));\r
+ last_oper_notice = rb_current_time();\r
+ }\r
+ \r
+ rb_write(F, "ERROR :All connections in use\r\n", 32);\r
+ rb_close(F);\r
+ /* Re-register a new IO request for the next accept .. */\r
+ return 0;\r
+ }\r
+\r
+ aconf = find_dline(addr, addr.ss_family);\r
+ if(aconf != NULL && (aconf->status & CONF_EXEMPTDLINE))\r
+ return 1;\r
+ \r
+ /* Do an initial check we aren't connecting too fast or with too many\r
+ * from this IP... */\r
+ if(aconf != NULL)\r
+ {\r
+ ServerStats->is_ref++;\r
+ \r
+ if(ConfigFileEntry.dline_with_reason)\r
+ {\r
+ if (rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", aconf->passwd) >= (int)(sizeof(buf)-1))\r
+ {\r
+ buf[sizeof(buf) - 3] = '\r';\r
+ buf[sizeof(buf) - 2] = '\n';\r
+ buf[sizeof(buf) - 1] = '\0';\r
+ }\r
+ }\r
+ else\r
+ strcpy(buf, "ERROR :You have been D-lined.\r\n");\r
+ \r
+ rb_write(F, buf, strlen(buf));\r
+ rb_close(F);\r
+ return 0;\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+static void\r
+accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data)\r
+{\r
+ struct Listener *listener = data;\r
+ struct rb_sockaddr_storage lip;\r
+ unsigned int locallen = sizeof(struct rb_sockaddr_storage);\r
+ \r
+ ServerStats->is_ac++;\r
+\r
+ if(getsockname(rb_get_fd(F), (struct sockaddr *) &lip, &locallen) < 0)\r
+ {\r
+ /* this shouldn't fail so... */\r
+ /* XXX add logging of this */\r
+ rb_close(F);\r
+ }\r
+ \r
+ add_connection(listener, F, addr, (struct sockaddr *)&lip, 1);\r
}