From: Timo Sirainen Date: Mon, 23 Sep 2013 01:06:08 +0000 (+0300) Subject: lib: Added net_listen_full() with a flag to set SO_REUSEPORT on the socket if available. X-Git-Tag: 2.2.6~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b270c58fc227c91a88b07316d680418ec75021e9;p=thirdparty%2Fdovecot%2Fcore.git lib: Added net_listen_full() with a flag to set SO_REUSEPORT on the socket if available. --- diff --git a/src/lib/net.c b/src/lib/net.c index 573041eb30..7f4e906be4 100644 --- a/src/lib/net.c +++ b/src/lib/net.c @@ -383,6 +383,14 @@ void net_get_ip_any6(struct ip_addr *ip) } int net_listen(const struct ip_addr *my_ip, unsigned int *port, int backlog) +{ + enum net_listen_flags flags = 0; + + return net_listen_full(my_ip, port, &flags, backlog); +} + +int net_listen_full(const struct ip_addr *my_ip, unsigned int *port, + enum net_listen_flags *flags, int backlog) { union sockaddr_union so; int ret, fd, opt = 1; @@ -413,6 +421,14 @@ int net_listen(const struct ip_addr *my_ip, unsigned int *port, int backlog) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)); + if ((*flags & NET_LISTEN_FLAG_REUSEPORT) != 0) { +#ifdef SO_REUSEPORT + if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, + &opt, sizeof(opt)) < 0) +#endif + *flags &= ~NET_LISTEN_FLAG_REUSEPORT; + } + /* If using IPv6, bind only to IPv6 if possible. This avoids ambiguities with IPv4-mapped IPv6 addresses. */ #ifdef IPV6_V6ONLY diff --git a/src/lib/net.h b/src/lib/net.h index 2b21bde8fa..dd74af1064 100644 --- a/src/lib/net.h +++ b/src/lib/net.h @@ -55,6 +55,12 @@ struct net_unix_cred { #define IPADDR_IS_V6(ip) ((ip)->family == AF_INET6) #define IPADDR_BITS(ip) (IPADDR_IS_V4(ip) ? 32 : 128) +enum net_listen_flags { + /* Try to use SO_REUSEPORT if available. If it's not, this flag is + cleared on return. */ + NET_LISTEN_FLAG_REUSEPORT = 0x01 +}; + /* Returns TRUE if IPs are the same */ bool net_ip_compare(const struct ip_addr *ip1, const struct ip_addr *ip2); /* Returns 0 if IPs are the same, -1 or 1 otherwise. */ @@ -91,6 +97,8 @@ void net_get_ip_any6(struct ip_addr *ip); /* Listen for connections on a socket */ int net_listen(const struct ip_addr *my_ip, unsigned int *port, int backlog); +int net_listen_full(const struct ip_addr *my_ip, unsigned int *port, + enum net_listen_flags *flags, int backlog); /* Listen for connections on an UNIX socket */ int net_listen_unix(const char *path, int backlog); /* Like net_listen_unix(), but if socket already exists, try to connect to it.