}
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;
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
#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. */
/* 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.