Skip to content

Commit

Permalink
listener: ipv6only socket bind support
Browse files Browse the repository at this point in the history
According to RFC3493 and most Linux distributions, default value is to
work in IPv4-mapped mode. If there is a requirement to bind same port
on same ip addresses but different handlers for both IPv4 and IPv6,
it is required to set IPV6_V6ONLY socket option to be sure that the
code works as expected without affected by bindv6only sysctl setting
in system.

See an example working with this patch:
https://gist.github.com/demirten/023008a63cd966e48b0ebcf9af7fc113

Closes: libevent#640 (cherry-pick)
  • Loading branch information
demirten authored and azat committed Oct 26, 2018
1 parent b2667b7 commit 387d91f
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 0 deletions.
8 changes: 8 additions & 0 deletions evutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,14 @@ evutil_make_listen_socket_reuseable_port(evutil_socket_t sock)
#endif
}

int
evutil_make_listen_socket_ipv6only(evutil_socket_t sock)
{
int one = 1;
return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &one,
(ev_socklen_t)sizeof(one));
}

int
evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock)
{
Expand Down
12 changes: 12 additions & 0 deletions include/event2/listener.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);
* This is only available on Linux and kernel 3.9+
*/
#define LEV_OPT_REUSEABLE_PORT (1u<<7)
/** Flag: Indicates that the listener wants to work only in IPv6 socket.
*
* According to RFC3493 and most Linux distributions, default value is to
* work in IPv4-mapped mode. If there is a requirement to bind same port
* on same ip addresses but different handlers for both IPv4 and IPv6,
* it is required to set IPV6_V6ONLY socket option to be sure that the
* code works as expected without affected by bindv6only sysctl setting in
* system.
*
* This socket option also supported by Windows.
*/
#define LEV_OPT_BIND_IPV6ONLY (1u<<8)

/**
Allocate a new evconnlistener object to listen for incoming TCP connections
Expand Down
12 changes: 12 additions & 0 deletions include/event2/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,18 @@ int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock);

/** Set ipv6 only bind socket option to make listener work only in 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.
@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);

/** Do platform-specific operations as needed to close a socket upon a
successful execution of one of the exec*() functions.
Expand Down
5 changes: 5 additions & 0 deletions listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
goto err;
}

if (flags & LEV_OPT_BIND_IPV6ONLY) {
if (evutil_make_listen_socket_ipv6only(fd) < 0)
goto err;
}

if (sa) {
if (bind(fd, sa, socklen)<0)
goto err;
Expand Down

0 comments on commit 387d91f

Please sign in to comment.