From 3a57fcdd11ad8ad3cb903d48a5245e7f9d965f34 Mon Sep 17 00:00:00 2001 From: Abhishek Lekshmanan Date: Fri, 29 Mar 2019 17:37:44 +0100 Subject: [PATCH 1/2] rgw: beast: bind both v4 and v6 ports when using a port argument This commit adds binding to both v4 and v6 port when specifying a port argument, endpoint *only* binds to v4 or v6 depending on the address specified. Failure to bind when the protocol is not supported is not treated as an error and we warn and continue then. Fixes: http://tracker.ceph.com/issues/39038 Signed-off-by: Abhishek Lekshmanan --- src/rgw/rgw_asio_frontend.cc | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/rgw/rgw_asio_frontend.cc b/src/rgw/rgw_asio_frontend.cc index e4be074ec74..58a7446db3c 100644 --- a/src/rgw/rgw_asio_frontend.cc +++ b/src/rgw/rgw_asio_frontend.cc @@ -397,6 +397,9 @@ int AsioFrontend::init() } listeners.emplace_back(context); listeners.back().endpoint.port(port); + + listeners.emplace_back(context); + listeners.back().endpoint = tcp::endpoint(tcp::v6(), port); } auto endpoints = config.equal_range("endpoint"); @@ -417,13 +420,31 @@ int AsioFrontend::init() } } + + bool socket_bound = false; // start listeners for (auto& l : listeners) { l.acceptor.open(l.endpoint.protocol(), ec); if (ec) { + if (ec == boost::asio::error::address_family_not_supported) { + ldout(ctx(), 0) << "WARNING: cannot open socket for endpoint=" << l.endpoint + << ", " << ec.message() << dendl; + continue; + } + lderr(ctx()) << "failed to open socket: " << ec.message() << dendl; return -ec.value(); } + + if (l.endpoint.protocol() == tcp::v6()) { + l.acceptor.set_option(boost::asio::ip::v6_only(true), ec); + if (ec) { + lderr(ctx()) << "failed to set v6_only socket option: " + << ec.message() << dendl; + return -ec.value(); + } + } + l.acceptor.set_option(tcp::acceptor::reuse_address(true)); l.acceptor.bind(l.endpoint, ec); if (ec) { @@ -431,6 +452,7 @@ int AsioFrontend::init() << ": " << ec.message() << dendl; return -ec.value(); } + l.acceptor.listen(boost::asio::socket_base::max_connections); l.acceptor.async_accept(l.socket, [this, &l] (boost::system::error_code ec) { @@ -438,7 +460,13 @@ int AsioFrontend::init() }); ldout(ctx(), 4) << "frontend listening on " << l.endpoint << dendl; + socket_bound = true; } + if (!socket_bound) { + lderr(ctx()) << "Unable to listen at any endpoints" << dendl; + return -EINVAL; + } + return drop_privileges(ctx()); } @@ -503,6 +531,10 @@ int AsioFrontend::init_ssl() listeners.emplace_back(context); listeners.back().endpoint.port(port); listeners.back().use_ssl = true; + + listeners.emplace_back(context); + listeners.back().endpoint = tcp::endpoint(tcp::v6(), port); + listeners.back().use_ssl = true; } auto endpoints = config.equal_range("ssl_endpoint"); From 59c768713e67e45248a9caecec486f0038268d95 Mon Sep 17 00:00:00 2001 From: Abhishek Lekshmanan Date: Fri, 29 Mar 2019 18:13:52 +0100 Subject: [PATCH 2/2] doc: rgw: document v6 endpoint options document that v6 endpoints only binds to ipv6 Signed-off-by: Abhishek Lekshmanan --- doc/radosgw/frontends.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/radosgw/frontends.rst b/doc/radosgw/frontends.rst index 4b70114518c..1ab4ad73bc4 100644 --- a/doc/radosgw/frontends.rst +++ b/doc/radosgw/frontends.rst @@ -23,21 +23,21 @@ Options ``port`` and ``ssl_port`` -:Description: Sets the listening port number. Can be specified multiple +:Description: Sets the ipv4 & ipv6 listening port number. Can be specified multiple times as in ``port=80 port=8000``. - :Type: Integer :Default: ``80`` ``endpoint`` and ``ssl_endpoint`` -:Description: Sets the listening address in the form ``address[:port]``, - where the address is an IPv4 address string in dotted decimal - form, or an IPv6 address in hexadecimal notation surrounded - by square brackets. The optional port defaults to 80 for - ``endpoint`` and 443 for ``ssl_endpoint``. Can be specified - multiple times as in ``endpoint=[::1] endpoint=192.168.0.100:8000``. +:Description: Sets the listening address in the form ``address[:port]``, where + the address is an IPv4 address string in dotted decimal form, or + an IPv6 address in hexadecimal notation surrounded by square + brackets. Specifying a IPv6 endpoint would listen to v6 only. The + optional port defaults to 80 for ``endpoint`` and 443 for + ``ssl_endpoint``. Can be specified multiple times as in + ``endpoint=[::1] endpoint=192.168.0.100:8000``. :Type: Integer :Default: None