]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Added net_listen_full() with a flag to set SO_REUSEPORT on the socket if available.
authorTimo Sirainen <tss@iki.fi>
Mon, 23 Sep 2013 01:06:08 +0000 (04:06 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 23 Sep 2013 01:06:08 +0000 (04:06 +0300)
src/lib/net.c
src/lib/net.h

index 573041eb30b6b64ddeb438a7ca2462f6e57ba765..7f4e906be42a9030d6ff7a3ada118e0b8ba690db 100644 (file)
@@ -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
index 2b21bde8fa735aeeb4c5f19d8d0b844f12f04f6a..dd74af10641aa7f2ea2274a126ad7929d4c70d52 100644 (file)
@@ -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.