diff --git a/doc/example.conf b/doc/example.conf index f31f0cc7b..d7ab7392f 100644 --- a/doc/example.conf +++ b/doc/example.conf @@ -238,6 +238,7 @@ oper bobsmith { J java s ssl * standard + N/A defer-accept */ /* NOTE ON SSL PORTS: SSL ports are pretty non-standardized, @@ -256,11 +257,18 @@ listen *:6697 { ssl; clientsonly; + defer-accept; }; }; listen *:8067; -listen *:6667; +listen *:6667 +{ + options + { + defer-accept; + } +}; /* NOTE: If you are on an IRCd shell with multiple IP's you are * likely to get 'Address already in use' errors in your log @@ -268,6 +276,11 @@ listen *:6667; * to a specific IP instead of '*', so for example: * listen 1.2.3.4:6667; * Obviously, replace the IP with the IP that was assigned to you. + * + * Also: The defer-accept option added in Unreal 3.4 will use kernel-based + * filtering to offload connect processing to the IRCd, this may + * provide additional resiliance under TCP synfloods. However, + * this option only works on Linux and FreeBSD. */ /* diff --git a/include/struct.h b/include/struct.h index e79600d36..fbf6b4964 100644 --- a/include/struct.h +++ b/include/struct.h @@ -969,6 +969,7 @@ typedef struct { #define LISTENER_MASK 0x000020 #define LISTENER_SSL 0x000040 #define LISTENER_BOUND 0x000080 +#define LISTENER_DEFER_ACCEPT 0x000100 #define IsServersOnlyListener(x) ((x) && ((x)->options & LISTENER_SERVERSONLY)) diff --git a/src/s_bsd.c b/src/s_bsd.c index a2d75ee92..b55f95641 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -337,7 +337,7 @@ static void listener_accept(int fd, int revents, void *data) int inetport(ConfigItem_listen *listener, char *name, int port) { static struct SOCKADDR_IN server; - int ad[4], len = sizeof(server); + int ad[4], len = sizeof(server), result; char ipname[64]; if (BadPtr(name)) @@ -441,7 +441,29 @@ int inetport(ConfigItem_listen *listener, char *name, int port) return -1; } - (void)listen(listener->fd, LISTEN_SIZE); + result = listen(listener->fd, LISTEN_SIZE); + +#ifdef TCP_DEFER_ACCEPT + if ((listener->flags & LISTENER_DEFER_ACCEPT) && !result) + { + int true = 1; + + setsockopt(listener->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &true, sizeof(int)); + } +#endif + +#ifdef SO_ACCEPTFILTER + if ((listener->flags & LISTENER_DEFER_ACCEPT) && !result) + { + struct accept_filter_arg afa; + + memset(&afa, '\0', sizeof afa); + strlcpy(afa.af_name, "dataready", sizeof afa.af_name); + (void) setsockopt(listener->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, + sizeof afa); + } +#endif + fd_setselect(listener->fd, FD_SELECT_READ, listener_accept, listener); return 0; diff --git a/src/s_conf.c b/src/s_conf.c index 832799442..18ad1c977 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -246,13 +246,14 @@ static OperFlag _OperFlags[] = { /* This MUST be alphabetized */ static OperFlag _ListenerFlags[] = { - { LISTENER_CLIENTSONLY, "clientsonly"}, - { LISTENER_JAVACLIENT, "java"}, - { LISTENER_MASK, "mask"}, - { LISTENER_REMOTEADMIN, "remoteadmin"}, - { LISTENER_SERVERSONLY, "serversonly"}, - { LISTENER_SSL, "ssl"}, - { LISTENER_NORMAL, "standard"}, + { LISTENER_CLIENTSONLY, "clientsonly"}, + { LISTENER_DEFER_ACCEPT, "defer-accept"}, + { LISTENER_JAVACLIENT, "java"}, + { LISTENER_MASK, "mask"}, + { LISTENER_REMOTEADMIN, "remoteadmin"}, + { LISTENER_SERVERSONLY, "serversonly"}, + { LISTENER_SSL, "ssl"}, + { LISTENER_NORMAL, "standard"}, }; /* This MUST be alphabetized */