*
* $Id$
*/
+#include "config.h"
+
#include "listener.h"
#include "client.h"
#include "ircd.h"
#include "ircd_alloc.h"
+#include "ircd_events.h"
+#include "ircd_features.h"
#include "ircd_osdep.h"
#include "ircd_reply.h"
+#include "ircd_snprintf.h"
#include "ircd_string.h"
#include "numeric.h"
#include "s_bsd.h"
#include "s_conf.h"
#include "s_misc.h"
#include "send.h"
-#include "sprintf_irc.h"
#include "sys.h" /* MAXCLIENTS */
#include <assert.h>
struct Listener* ListenerPollList = 0;
+static void accept_connection(struct Event* ev);
+
static struct Listener* make_listener(int port, struct in_addr addr)
{
struct Listener* listener =
{
static char buf[HOSTLEN + PORTNAMELEN + 4];
assert(0 != listener);
- sprintf_irc(buf, "%s:%u", me.name, listener->port);
+ ircd_snprintf(0, buf, sizeof(buf), "%s:%u", cli_name(&me), listener->port);
return buf;
}
close(fd);
return 0;
}
+ /*
+ * Set the TOS bits - this is nonfatal if it doesn't stick.
+ */
+ if (!os_set_tos(fd,feature_int((listener->server)?FEAT_TOS_SERVER : FEAT_TOS_CLIENT))) {
+ report_error(TOS_ERROR_MSG, get_listener_name(listener), errno);
+ }
+
+ if (!socket_add(&listener->socket, accept_connection, (void*) listener,
+ SS_LISTENING, 0, fd)) {
+ /* Error should already have been reported to the logs */
+ close(fd);
+ return 0;
+ }
+
listener->fd = fd;
return 1;
* easy conversion of "*" 0.0.0.0 or 134.* to 134.0.0.0 :-)
*/
sscanf(mask, "%d.%d.%d.%d", &ad[0], &ad[1], &ad[2], &ad[3]);
- sprintf_irc(ipname, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
+ ircd_snprintf(0, ipname, sizeof(ipname), "%d.%d.%d.%d", ad[0], ad[1], ad[2],
+ ad[3]);
listener->mask.s_addr = inet_addr(ipname);
}
}
if (-1 < listener->fd)
close(listener->fd);
- free_listener(listener);
+ socket_del(&listener->socket);
}
/*
/*
* accept_connection - accept a connection on a listener
*/
-void accept_connection(struct Listener* listener)
+static void accept_connection(struct Event* ev)
{
+ struct Listener* listener;
struct sockaddr_in addr = { 0 };
unsigned int addrlen = sizeof(struct sockaddr_in);
int fd;
- assert(0 != listener);
+ assert(0 != ev_socket(ev));
+ assert(0 != s_data(ev_socket(ev)));
- listener->last_accept = CurrentTime;
- /*
- * 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.
- */
- if (-1 == (fd = accept(listener->fd, (struct sockaddr*) &addr, &addrlen))) {
- /* Lotsa admins seem to have problems with not giving enough file descriptors
- * to their server so we'll add a generic warning mechanism here. If it
- * turns out too many messages are generated for meaningless reasons we
- * can filter them back.
- */
- sendto_op_mask(SNO_TCPCOMMON,"Unable to accept connection: %s", strerror(errno));
- return;
- }
- /*
- * check for connection limit
- */
- if (fd > MAXCLIENTS - 1) {
- ++ServerStats->is_ref;
- send(fd, "ERROR :All connections in use\r\n", 32, 0);
- close(fd);
- return;
- }
- /*
- * check to see if listener is shutting down
- */
- if (!listener->active) {
- ++ServerStats->is_ref;
- send(fd, "ERROR :Use another port\r\n", 25, 0);
- close(fd);
- return;
- }
- /*
- * check to see if connection is allowed for this address mask
- */
- if (!connection_allowed((const char*) &addr, (const char*) &listener->mask)) {
- ++ServerStats->is_ref;
- send(fd, "ERROR :Use another port\r\n", 25, 0);
- close(fd);
- return;
- }
-#if 0
- /*
- * check conf for ip address access
- */
- if (!conf_connect_allowed(addr.sin_addr)) {
- ++ServerStats->is_ref;
- send(fd, "ERROR :Not authorized\r\n", 23, 0);
- close(fd);
- return;
- }
-#endif
- ++ServerStats->is_ac;
- nextping = CurrentTime;
+ listener = s_data(ev_socket(ev));
- add_connection(listener, fd);
-}
+ if (ev_type(ev) == ET_DESTROY) /* being destroyed */
+ free_listener(listener);
+ else {
+ assert(ev_type(ev) == ET_ACCEPT);
+ listener->last_accept = CurrentTime;
+ /*
+ * 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.
+ */
+ if (-1 == (fd = accept(listener->fd, (struct sockaddr*) &addr,
+ &addrlen))) {
+ /* Lotsa admins seem to have problems with not giving enough file
+ * descriptors to their server so we'll add a generic warning mechanism
+ * here. If it turns out too many messages are generated for
+ * meaningless reasons we can filter them back.
+ */
+ sendto_opmask_butone(0, SNO_TCPCOMMON,
+ "Unable to accept connection: %m");
+ return;
+ }
+ /*
+ * check for connection limit
+ */
+ if (fd > MAXCLIENTS - 1) {
+ ++ServerStats->is_ref;
+ send(fd, "ERROR :All connections in use\r\n", 32, 0);
+ close(fd);
+ return;
+ }
+ /*
+ * check to see if listener is shutting down
+ */
+ if (!listener->active) {
+ ++ServerStats->is_ref;
+ send(fd, "ERROR :Use another port\r\n", 25, 0);
+ close(fd);
+ return;
+ }
+ /*
+ * check to see if connection is allowed for this address mask
+ */
+ if (!connection_allowed((const char*) &addr,
+ (const char*) &listener->mask)) {
+ ++ServerStats->is_ref;
+ send(fd, "ERROR :Use another port\r\n", 25, 0);
+ close(fd);
+ return;
+ }
+ ++ServerStats->is_ac;
+/* nextping = CurrentTime; */
+ add_connection(listener, fd);
+ }
+}