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 diff --git a/src/rgw/rgw_asio_frontend.cc b/src/rgw/rgw_asio_frontend.cc index 17a1c38020a..d4ea4483e54 100644 --- a/src/rgw/rgw_asio_frontend.cc +++ b/src/rgw/rgw_asio_frontend.cc @@ -401,6 +401,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"); @@ -421,13 +424,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) { @@ -435,6 +456,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) { @@ -442,7 +464,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()); } @@ -507,6 +535,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");