From 02270e96020968fcefc6c2b2f847fe8912f129ae Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 17 Mar 2012 10:00:39 -0500 Subject: [PATCH] Add listen::defer_accept option for controlling usage of TCP_DEFER_ACCEPT option. --- doc/example.conf | 7 +++++++ doc/reference.conf | 7 +++++++ include/listener.h | 3 ++- src/listener.c | 5 +++-- src/newconf.c | 15 +++++++++++---- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/doc/example.conf b/doc/example.conf index 190bc4e4..c02b3c7d 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -135,6 +135,13 @@ class "server" { }; listen { + /* defer_accept: wait for clients to send IRC handshake data before + * accepting them. if you intend to use software which depends on the + * server replying first, such as BOPM, you should disable this feature. + * otherwise, you probably want to leave it on. + */ + defer_accept = yes; + /* If you want to listen on a specific IP only, specify host. * host definitions apply only to the following port line. */ diff --git a/doc/reference.conf b/doc/reference.conf index bf15bcf5..1e3e8996 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -281,6 +281,13 @@ class "server" { /* listen {}: contain information about the ports ircd listens on (OLD P:) */ listen { + /* defer_accept: wait for clients to send IRC handshake data before + * accepting them. if you intend to use software which depends on the + * server replying first, such as BOPM, you should disable this feature. + * otherwise, you probably want to leave it on. + */ + defer_accept = yes; + /* port: the specific port to listen on. if no host is specified * before, it will listen on all available IPs. * diff --git a/include/listener.h b/include/listener.h index c27e45f4..2b4e6d31 100644 --- a/include/listener.h +++ b/include/listener.h @@ -39,12 +39,13 @@ struct Listener int ref_count; /* number of connection references */ int active; /* current state of listener */ int ssl; /* ssl listener */ + int defer_accept; /* use TCP_DEFER_ACCEPT */ struct rb_sockaddr_storage addr; struct DNSQuery *dns_query; char vhost[HOSTLEN + 1]; /* virtual name of listener */ }; -extern void add_listener(int port, const char *vaddr_ip, int family, int ssl); +extern void add_listener(int port, const char *vaddr_ip, int family, int ssl, int defer_accept); extern void close_listener(struct Listener *listener); extern void close_listeners(void); extern const char *get_listener_name(const struct Listener *listener); diff --git a/src/listener.c b/src/listener.c index 7b528724..3e4965c3 100644 --- a/src/listener.c +++ b/src/listener.c @@ -231,7 +231,7 @@ inetport(struct Listener *listener) return 0; } - if(rb_listen(F, RATBOX_SOMAXCONN)) + if(rb_listen(F, RATBOX_SOMAXCONN, listener->defer_accept)) { ilog_error("listen()"); rb_close(F); @@ -304,7 +304,7 @@ find_listener(struct rb_sockaddr_storage *addr) * the format "255.255.255.255" */ void -add_listener(int port, const char *vhost_ip, int family, int ssl) +add_listener(int port, const char *vhost_ip, int family, int ssl, int defer_accept) { struct Listener *listener; struct rb_sockaddr_storage vaddr; @@ -377,6 +377,7 @@ add_listener(int port, const char *vhost_ip, int family, int ssl) listener->F = NULL; listener->ssl = ssl; + listener->defer_accept = defer_accept; if(inetport(listener)) listener->active = 1; diff --git a/src/newconf.c b/src/newconf.c index ccb1c151..ddc9f93b 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -32,6 +32,8 @@ #define CF_TYPE(x) ((x) & CF_MTYPE) +static int yy_defer_accept = 1; + struct TopConf *conf_cur_block; static char *conf_cur_block_name; @@ -844,7 +846,11 @@ conf_end_listen(struct TopConf *tc) return 0; } - +static void +conf_set_listen_defer_accept(void *data) +{ + yy_defer_accept = *(unsigned int *) data; +} static void conf_set_listen_port_both(void *data, int ssl) @@ -860,9 +866,9 @@ conf_set_listen_port_both(void *data, int ssl) } if(listener_address == NULL) { - add_listener(args->v.number, listener_address, AF_INET, ssl); + add_listener(args->v.number, listener_address, AF_INET, ssl, yy_defer_accept); #ifdef RB_IPV6 - add_listener(args->v.number, listener_address, AF_INET6, ssl); + add_listener(args->v.number, listener_address, AF_INET6, ssl, yy_defer_accept); #endif } else @@ -875,7 +881,7 @@ conf_set_listen_port_both(void *data, int ssl) #endif family = AF_INET; - add_listener(args->v.number, listener_address, family, ssl); + add_listener(args->v.number, listener_address, family, ssl, yy_defer_accept); } @@ -2331,6 +2337,7 @@ newconf_init() add_top_conf("privset", NULL, NULL, conf_privset_table); add_top_conf("listen", conf_begin_listen, conf_end_listen, NULL); + add_conf_item("listen", "defer_accept", CF_YESNO, conf_set_listen_defer_accept); add_conf_item("listen", "port", CF_INT | CF_FLIST, conf_set_listen_port); add_conf_item("listen", "sslport", CF_INT | CF_FLIST, conf_set_listen_sslport); add_conf_item("listen", "ip", CF_QSTRING, conf_set_listen_address);