diff options
-rw-r--r-- | evutil.c | 11 | ||||
-rw-r--r-- | include/event2/listener.h | 11 | ||||
-rw-r--r-- | include/event2/util.h | 16 | ||||
-rw-r--r-- | listener.c | 5 |
4 files changed, 42 insertions, 1 deletions
@@ -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. @@ -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; |