vector<SockAddr> ipToAddrs(const char* ips, int port, bool useUnixSockets) { vector<SockAddr> out; if (*ips == '\0') { out.push_back(SockAddr("0.0.0.0", port)); // IPv4 all if (IPv6Enabled()) out.push_back(SockAddr("::", port)); // IPv6 all #ifndef _WIN32 if (useUnixSockets) out.push_back(SockAddr(makeUnixSockPath(port).c_str(), port)); // Unix socket #endif return out; } while(*ips) { string ip; const char * comma = strchr(ips, ','); if (comma) { ip = string(ips, comma - ips); ips = comma + 1; } else { ip = string(ips); ips = ""; } SockAddr sa(ip.c_str(), port); out.push_back(sa); #ifndef _WIN32 if (useUnixSockets && (sa.getAddr() == "127.0.0.1" || sa.getAddr() == "0.0.0.0")) // only IPv4 out.push_back(SockAddr(makeUnixSockPath(port).c_str(), port)); #endif } return out; }
Status TransportLayerASIO::setup() { std::vector<std::string> listenAddrs; if (_listenerOptions.ipList.empty()) { listenAddrs = {"127.0.0.1"}; if (_listenerOptions.enableIPv6) { listenAddrs.emplace_back("::1"); } } else { boost::split( listenAddrs, _listenerOptions.ipList, boost::is_any_of(","), boost::token_compress_on); } #ifndef _WIN32 if (_listenerOptions.useUnixSockets) { listenAddrs.emplace_back(makeUnixSockPath(_listenerOptions.port)); } #endif for (auto& ip : listenAddrs) { std::error_code ec; if (ip.empty()) { warning() << "Skipping empty bind address"; continue; } SockAddr addr(StringData(ip), _listenerOptions.port, _listenerOptions.enableIPv6 ? AF_UNSPEC : AF_INET); asio::generic::stream_protocol::endpoint endpoint(addr.raw(), addr.addressSize); #ifndef _WIN32 if (addr.getType() == AF_UNIX) { if (::unlink(ip.c_str()) == -1 && errno != ENOENT) { error() << "Failed to unlink socket file " << ip << " " << errnoWithDescription(errno); fassertFailedNoTrace(40486); } } #endif if (addr.getType() == AF_INET6 && !_listenerOptions.enableIPv6) { error() << "Specified ipv6 bind address, but ipv6 is disabled"; fassertFailedNoTrace(40488); } GenericAcceptor acceptor(*_ioContext); acceptor.open(endpoint.protocol()); acceptor.set_option(GenericAcceptor::reuse_address(true)); acceptor.bind(endpoint, ec); if (ec) { return errorCodeToStatus(ec); } #ifndef _WIN32 if (addr.getType() == AF_UNIX) { if (::chmod(ip.c_str(), serverGlobalParams.unixSocketPermissions) == -1) { error() << "Failed to chmod socket file " << ip << " " << errnoWithDescription(errno); fassertFailedNoTrace(40487); } } #endif _acceptors.emplace_back(std::move(acceptor)); } invariant(!_acceptors.empty()); #ifdef MONGO_CONFIG_SSL const auto& sslParams = getSSLGlobalParams(); _sslMode = static_cast<SSLParams::SSLModes>(sslParams.sslMode.load()); if (_sslMode != SSLParams::SSLMode_disabled) { _sslContext = stdx::make_unique<asio::ssl::context>(asio::ssl::context::sslv23); const auto sslManager = getSSLManager(); sslManager ->initSSLContext(_sslContext->native_handle(), sslParams, SSLManagerInterface::ConnectionDirection::kOutgoing) .transitional_ignore(); } #endif return Status::OK(); }