summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--evutil.c11
-rw-r--r--include/event2/listener.h11
-rw-r--r--include/event2/util.h16
-rw-r--r--listener.c5
4 files changed, 42 insertions, 1 deletions
diff --git a/evutil.c b/evutil.c
index d46c997b..bbf908c0 100644
--- a/evutil.c
+++ b/evutil.c
@@ -604,6 +604,17 @@ evutil_make_listen_socket_ipv6only(evutil_socket_t sock)
}
int
+evutil_make_listen_socket_not_ipv6only(evutil_socket_t sock)
+{
+#if defined(IPV6_V6ONLY)
+ int zero = 0;
+ return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&zero,
+ (ev_socklen_t)sizeof(zero));
+#endif
+ return 0;
+}
+
+int
evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock)
{
#if defined(EVENT__HAVE_NETINET_TCP_H) && defined(TCP_DEFER_ACCEPT)
diff --git a/include/event2/listener.h b/include/event2/listener.h
index 53b734e7..8aa9e1f7 100644
--- a/include/event2/listener.h
+++ b/include/event2/listener.h
@@ -107,9 +107,18 @@ typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);
* code works as expected without affected by bindv6only sysctl setting in
* system.
*
- * This socket option also supported by Windows.
+ * This socket option on Windows is instead enabled by default.
*/
#define LEV_OPT_BIND_IPV6ONLY (1u<<8)
+/** Flag: Indicates that the listener wants to work only in both IPv4 and
+ * IPv6 socket.
+ *
+ * This flag exists as copmlement to LEV_OPT_BIND_IPV6ONLY to account for
+ * the different default behaviour on Windows so that the code can
+ * explicitly request the socket to support both modes without having
+ * to rely on the default option.
+ */
+#define LEV_OPT_BIND_IPV4_AND_IPV6 (1u<<9)
/**
Allocate a new evconnlistener object to listen for incoming TCP connections
diff --git a/include/event2/util.h b/include/event2/util.h
index 43955bf6..dc190426 100644
--- a/include/event2/util.h
+++ b/include/event2/util.h
@@ -429,12 +429,28 @@ int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock);
sockets is to work in IPv4-mapped mode. In IPv4-mapped mode, it is not possible
to bind same port from different IPv4 and IPv6 handlers.
+ On Windows the default value is instead to only work in IPv6 mode.
+
@param sock The socket to make in ipv6only working mode
@return 0 on success, -1 on failure
*/
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_ipv6only(evutil_socket_t sock);
+/** Set ipv6 only bind socket option to make listener work in both ipv4 and ipv6 sockets.
+
+ According to RFC3493 and most Linux distributions, default value for the
+ sockets is to work in IPv4-mapped mode. In IPv4-mapped mode, it is not possible
+ to bind same port from different IPv4 and IPv6 handlers.
+
+ On Windows the default value is instead to only work in IPv6 mode.
+
+ @param sock The socket to make in ipv6only working mode
+ @return 0 on success, -1 on failure
+ */
+EVENT2_EXPORT_SYMBOL
+int evutil_make_listen_socket_not_ipv6only(evutil_socket_t sock);
+
/** Do platform-specific operations as needed to close a socket upon a
successful execution of one of the exec*() functions.
diff --git a/listener.c b/listener.c
index fc7c2c58..ffbc4186 100644
--- a/listener.c
+++ b/listener.c
@@ -264,6 +264,11 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
goto err;
}
+ if (flags & LEV_OPT_BIND_IPV4_AND_IPV6) {
+ if (evutil_make_listen_socket_not_ipv6only(fd) < 0)
+ goto err;
+ }
+
if (sa) {
if (bind(fd, sa, socklen)<0)
goto err;