diff options
Diffstat (limited to 'src/mongo/db/repl/isself.cpp')
-rw-r--r-- | src/mongo/db/repl/isself.cpp | 423 |
1 files changed, 206 insertions, 217 deletions
diff --git a/src/mongo/db/repl/isself.cpp b/src/mongo/db/repl/isself.cpp index d0b44858913..e34b1cc9660 100644 --- a/src/mongo/db/repl/isself.cpp +++ b/src/mongo/db/repl/isself.cpp @@ -47,7 +47,8 @@ #include "mongo/util/scopeguard.h" #include "mongo/util/log.h" -#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) +#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun) || \ + defined(__OpenBSD__) #define FASTPATH_UNIX 1 #endif @@ -75,281 +76,269 @@ namespace mongo { namespace repl { - OID instanceId; +OID instanceId; - MONGO_INITIALIZER(GenerateInstanceId)(InitializerContext*) { - instanceId = OID::gen(); - return Status::OK(); - } +MONGO_INITIALIZER(GenerateInstanceId)(InitializerContext*) { + instanceId = OID::gen(); + return Status::OK(); +} namespace { - /** - * Helper to convert a message from a networking function to a string. - * Needed because errnoWithDescription uses strerror on linux, when - * we need gai_strerror. - */ - std::string stringifyError(int code) { +/** + * Helper to convert a message from a networking function to a string. + * Needed because errnoWithDescription uses strerror on linux, when + * we need gai_strerror. + */ +std::string stringifyError(int code) { #if FASTPATH_UNIX - return gai_strerror(code); + return gai_strerror(code); #elif defined(_WIN32) - // FormatMessage in errnoWithDescription works here on windows - return errnoWithDescription(code); + // FormatMessage in errnoWithDescription works here on windows + return errnoWithDescription(code); #endif - } - - /** - * Resolves a host and port to a list of IP addresses. This requires a syscall. If the - * ipv6enabled parameter is true, both IPv6 and IPv4 addresses will be returned. - */ - std::vector<std::string> getAddrsForHost(const std::string& iporhost, - const int port, - const bool ipv6enabled) { - addrinfo* addrs = NULL; - addrinfo hints = {0}; - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = (ipv6enabled ? AF_UNSPEC : AF_INET); - - const std::string portNum = BSONObjBuilder::numStr(port); - - std::vector<std::string> out; - - int err = getaddrinfo(iporhost.c_str(), portNum.c_str(), &hints, &addrs); +} - if (err) { - warning() << "getaddrinfo(\"" << iporhost << "\") failed: " - << stringifyError(err) << std::endl; - return out; - } +/** + * Resolves a host and port to a list of IP addresses. This requires a syscall. If the + * ipv6enabled parameter is true, both IPv6 and IPv4 addresses will be returned. + */ +std::vector<std::string> getAddrsForHost(const std::string& iporhost, + const int port, + const bool ipv6enabled) { + addrinfo* addrs = NULL; + addrinfo hints = {0}; + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = (ipv6enabled ? AF_UNSPEC : AF_INET); + + const std::string portNum = BSONObjBuilder::numStr(port); + + std::vector<std::string> out; + + int err = getaddrinfo(iporhost.c_str(), portNum.c_str(), &hints, &addrs); + + if (err) { + warning() << "getaddrinfo(\"" << iporhost << "\") failed: " << stringifyError(err) + << std::endl; + return out; + } - ON_BLOCK_EXIT(freeaddrinfo, addrs); + ON_BLOCK_EXIT(freeaddrinfo, addrs); - for (addrinfo* addr = addrs; addr != NULL; addr = addr->ai_next) { - int family = addr->ai_family; - char host[NI_MAXHOST]; + for (addrinfo* addr = addrs; addr != NULL; addr = addr->ai_next) { + int family = addr->ai_family; + char host[NI_MAXHOST]; - if (family == AF_INET || family == AF_INET6) { - err = getnameinfo(addr->ai_addr, addr->ai_addrlen, host, - NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (err) { - warning() << "getnameinfo() failed: " << stringifyError(err) << std::endl; - continue; - } - out.push_back(host); + if (family == AF_INET || family == AF_INET6) { + err = getnameinfo( + addr->ai_addr, addr->ai_addrlen, host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if (err) { + warning() << "getnameinfo() failed: " << stringifyError(err) << std::endl; + continue; } - + out.push_back(host); } + } - if (shouldLog(logger::LogSeverity::Debug(2))) { - StringBuilder builder; - builder << "getAddrsForHost(\"" << iporhost << ":" << port << "\"):"; - for (std::vector<std::string>::const_iterator o = out.begin(); o != out.end(); ++o) { - builder << " [ " << *o << "]"; - } - LOG(2) << builder.str(); + if (shouldLog(logger::LogSeverity::Debug(2))) { + StringBuilder builder; + builder << "getAddrsForHost(\"" << iporhost << ":" << port << "\"):"; + for (std::vector<std::string>::const_iterator o = out.begin(); o != out.end(); ++o) { + builder << " [ " << *o << "]"; } - - return out; + LOG(2) << builder.str(); } -} // namespace + return out; +} - bool isSelf(const HostAndPort& hostAndPort) { +} // namespace - // Fastpath: check if the host&port in question is bound to one - // of the interfaces on this machine. - // No need for ip match if the ports do not match - if (hostAndPort.port() == serverGlobalParams.port) { - std::vector<std::string> myAddrs = serverGlobalParams.bind_ip.empty() ? - getBoundAddrs(IPv6Enabled()) : - std::vector<std::string>(); +bool isSelf(const HostAndPort& hostAndPort) { + // Fastpath: check if the host&port in question is bound to one + // of the interfaces on this machine. + // No need for ip match if the ports do not match + if (hostAndPort.port() == serverGlobalParams.port) { + std::vector<std::string> myAddrs = serverGlobalParams.bind_ip.empty() + ? getBoundAddrs(IPv6Enabled()) + : std::vector<std::string>(); + + if (!serverGlobalParams.bind_ip.empty()) { + boost::split(myAddrs, serverGlobalParams.bind_ip, boost::is_any_of(", ")); + } - if (!serverGlobalParams.bind_ip.empty()) { - boost::split(myAddrs, serverGlobalParams.bind_ip, boost::is_any_of(", ")); - } + const std::vector<std::string> hostAddrs = + getAddrsForHost(hostAndPort.host(), hostAndPort.port(), IPv6Enabled()); - const std::vector<std::string> hostAddrs = getAddrsForHost(hostAndPort.host(), - hostAndPort.port(), - IPv6Enabled()); - - for (std::vector<std::string>::const_iterator i = myAddrs.begin(); - i != myAddrs.end(); ++i) { - for (std::vector<std::string>::const_iterator j = hostAddrs.begin(); - j != hostAddrs.end(); ++j) { - if (*i == *j) { - return true; - } + for (std::vector<std::string>::const_iterator i = myAddrs.begin(); i != myAddrs.end(); + ++i) { + for (std::vector<std::string>::const_iterator j = hostAddrs.begin(); + j != hostAddrs.end(); + ++j) { + if (*i == *j) { + return true; } } } + } + + // Ensure that the server is up and ready to accept incoming network requests. + const Listener* listener = Listener::getTimeTracker(); + if (!listener) { + return false; + } + listener->waitUntilListening(); - // Ensure that the server is up and ready to accept incoming network requests. - const Listener* listener = Listener::getTimeTracker(); - if (!listener) { + try { + DBClientConnection conn; + std::string errmsg; + conn.setSoTimeout(30); // 30 second timeout + if (!conn.connect(hostAndPort, errmsg)) { return false; } - listener->waitUntilListening(); - try { - DBClientConnection conn; - std::string errmsg; - conn.setSoTimeout(30); // 30 second timeout - if (!conn.connect(hostAndPort, errmsg)) { + if (getGlobalAuthorizationManager()->isAuthEnabled() && isInternalAuthSet()) { + if (!authenticateInternalUser(&conn)) { return false; } - - if (getGlobalAuthorizationManager()->isAuthEnabled() && isInternalAuthSet()) { - if (!authenticateInternalUser(&conn)) { - return false; - } - } - BSONObj out; - bool ok = conn.simpleCommand("admin" , &out, "_isSelf"); - bool me = ok && out["id"].type() == jstOID && instanceId == out["id"].OID(); - - return me; - } - catch (const std::exception& e) { - warning() << "could't check isSelf (" << hostAndPort << ") " << e.what() << std::endl; } + BSONObj out; + bool ok = conn.simpleCommand("admin", &out, "_isSelf"); + bool me = ok && out["id"].type() == jstOID && instanceId == out["id"].OID(); - return false; + return me; + } catch (const std::exception& e) { + warning() << "could't check isSelf (" << hostAndPort << ") " << e.what() << std::endl; } - /** - * Returns all the IP addresses bound to the network interfaces of this machine. - * This requires a syscall. If the ipv6enabled parameter is true, both IPv6 AND IPv4 - * addresses will be returned. - */ - std::vector<std::string> getBoundAddrs(const bool ipv6enabled) { - std::vector<std::string> out; + return false; +} + +/** + * Returns all the IP addresses bound to the network interfaces of this machine. + * This requires a syscall. If the ipv6enabled parameter is true, both IPv6 AND IPv4 + * addresses will be returned. + */ +std::vector<std::string> getBoundAddrs(const bool ipv6enabled) { + std::vector<std::string> out; #ifdef FASTPATH_UNIX - ifaddrs* addrs; + ifaddrs* addrs; - int err = getifaddrs(&addrs); - if (err) { - warning() << "getifaddrs failure: " << errnoWithDescription(err) << std::endl; - return out; - } - ON_BLOCK_EXIT(freeifaddrs, addrs); - - // based on example code from linux getifaddrs manpage - for (ifaddrs* addr = addrs; addr != NULL; addr = addr->ifa_next) { - if (addr->ifa_addr == NULL) continue; - int family = addr->ifa_addr->sa_family; - char host[NI_MAXHOST]; - - if (family == AF_INET || (ipv6enabled && (family == AF_INET6))) { - err = getnameinfo(addr->ifa_addr, - (family == AF_INET ? sizeof(struct sockaddr_in) - : sizeof(struct sockaddr_in6)), - host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (err) { - warning() << "getnameinfo() failed: " << gai_strerror(err) << std::endl; - continue; - } - out.push_back(host); + int err = getifaddrs(&addrs); + if (err) { + warning() << "getifaddrs failure: " << errnoWithDescription(err) << std::endl; + return out; + } + ON_BLOCK_EXIT(freeifaddrs, addrs); + + // based on example code from linux getifaddrs manpage + for (ifaddrs* addr = addrs; addr != NULL; addr = addr->ifa_next) { + if (addr->ifa_addr == NULL) + continue; + int family = addr->ifa_addr->sa_family; + char host[NI_MAXHOST]; + + if (family == AF_INET || (ipv6enabled && (family == AF_INET6))) { + err = getnameinfo( + addr->ifa_addr, + (family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)), + host, + NI_MAXHOST, + NULL, + 0, + NI_NUMERICHOST); + if (err) { + warning() << "getnameinfo() failed: " << gai_strerror(err) << std::endl; + continue; } + out.push_back(host); } + } #elif defined(_WIN32) - // Start with the MS recommended 15KB buffer. Use multiple attempts - // for the rare case that the adapter config changes between calls + // Start with the MS recommended 15KB buffer. Use multiple attempts + // for the rare case that the adapter config changes between calls - ULONG adaptersLen = 15 * 1024; - std::unique_ptr<char[]> buf(new char[adaptersLen]); - IP_ADAPTER_ADDRESSES* adapters = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buf.get()); - DWORD err; + ULONG adaptersLen = 15 * 1024; + std::unique_ptr<char[]> buf(new char[adaptersLen]); + IP_ADAPTER_ADDRESSES* adapters = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buf.get()); + DWORD err; - ULONG family = ipv6enabled ? AF_UNSPEC : AF_INET; + ULONG family = ipv6enabled ? AF_UNSPEC : AF_INET; - for (int tries = 0; tries < 3; ++tries) { - err = GetAdaptersAddresses(family, - GAA_FLAG_SKIP_ANYCAST | // only want unicast addrs + for (int tries = 0; tries < 3; ++tries) { + err = GetAdaptersAddresses(family, + GAA_FLAG_SKIP_ANYCAST | // only want unicast addrs GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, - NULL, - adapters, - &adaptersLen); - - if (err == ERROR_BUFFER_OVERFLOW) { - // in this case, adaptersLen will be set to the size we need to allocate - buf.reset(new char[adaptersLen]); - adapters = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buf.get()); - } - else { - break; // only retry for incorrectly sized buffer - } + NULL, + adapters, + &adaptersLen); + + if (err == ERROR_BUFFER_OVERFLOW) { + // in this case, adaptersLen will be set to the size we need to allocate + buf.reset(new char[adaptersLen]); + adapters = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buf.get()); + } else { + break; // only retry for incorrectly sized buffer } + } - if (err != NO_ERROR) { - warning() << "GetAdaptersAddresses() failed: " << errnoWithDescription(err) - << std::endl; - return out; - } + if (err != NO_ERROR) { + warning() << "GetAdaptersAddresses() failed: " << errnoWithDescription(err) << std::endl; + return out; + } - for (IP_ADAPTER_ADDRESSES* adapter = adapters; - adapter != NULL; adapter = adapter->Next) { - for (IP_ADAPTER_UNICAST_ADDRESS* addr = adapter->FirstUnicastAddress; - addr != NULL; addr = addr->Next) { - - short family = - reinterpret_cast<SOCKADDR_STORAGE*>(addr->Address.lpSockaddr)->ss_family; - - if (family == AF_INET) { - // IPv4 - SOCKADDR_IN* sock = reinterpret_cast<SOCKADDR_IN*>(addr->Address.lpSockaddr); - char addrstr[INET_ADDRSTRLEN] = {0}; - boost::system::error_code ec; - // Not all windows versions have inet_ntop - boost::asio::detail::socket_ops::inet_ntop(AF_INET, - &(sock->sin_addr), - addrstr, - INET_ADDRSTRLEN, - 0, - ec); - if (ec) { - warning() << "inet_ntop failed during IPv4 address conversion: " - << ec.message() << std::endl; - continue; - } - out.push_back(addrstr); + for (IP_ADAPTER_ADDRESSES* adapter = adapters; adapter != NULL; adapter = adapter->Next) { + for (IP_ADAPTER_UNICAST_ADDRESS* addr = adapter->FirstUnicastAddress; addr != NULL; + addr = addr->Next) { + short family = reinterpret_cast<SOCKADDR_STORAGE*>(addr->Address.lpSockaddr)->ss_family; + + if (family == AF_INET) { + // IPv4 + SOCKADDR_IN* sock = reinterpret_cast<SOCKADDR_IN*>(addr->Address.lpSockaddr); + char addrstr[INET_ADDRSTRLEN] = {0}; + boost::system::error_code ec; + // Not all windows versions have inet_ntop + boost::asio::detail::socket_ops::inet_ntop( + AF_INET, &(sock->sin_addr), addrstr, INET_ADDRSTRLEN, 0, ec); + if (ec) { + warning() << "inet_ntop failed during IPv4 address conversion: " << ec.message() + << std::endl; + continue; } - else if (family == AF_INET6) { - // IPv6 - SOCKADDR_IN6* sock = reinterpret_cast<SOCKADDR_IN6*>(addr->Address.lpSockaddr); - char addrstr[INET6_ADDRSTRLEN] = {0}; - boost::system::error_code ec; - boost::asio::detail::socket_ops::inet_ntop(AF_INET6, - &(sock->sin6_addr), - addrstr, - INET6_ADDRSTRLEN, - 0, - ec); - if (ec) { - warning() << "inet_ntop failed during IPv6 address conversion: " - << ec.message() << std::endl; - continue; - } - out.push_back(addrstr); + out.push_back(addrstr); + } else if (family == AF_INET6) { + // IPv6 + SOCKADDR_IN6* sock = reinterpret_cast<SOCKADDR_IN6*>(addr->Address.lpSockaddr); + char addrstr[INET6_ADDRSTRLEN] = {0}; + boost::system::error_code ec; + boost::asio::detail::socket_ops::inet_ntop( + AF_INET6, &(sock->sin6_addr), addrstr, INET6_ADDRSTRLEN, 0, ec); + if (ec) { + warning() << "inet_ntop failed during IPv6 address conversion: " << ec.message() + << std::endl; + continue; } + out.push_back(addrstr); } } + } #endif // defined(_WIN32) - if (shouldLog(logger::LogSeverity::Debug(2))) { - StringBuilder builder; - builder << "getBoundAddrs():"; - for (std::vector<std::string>::const_iterator o = out.begin(); o != out.end(); ++o) { - builder << " [ " << *o << "]"; - } - LOG(2) << builder.str(); + if (shouldLog(logger::LogSeverity::Debug(2))) { + StringBuilder builder; + builder << "getBoundAddrs():"; + for (std::vector<std::string>::const_iterator o = out.begin(); o != out.end(); ++o) { + builder << " [ " << *o << "]"; } - return out; + LOG(2) << builder.str(); } + return out; +} } // namespace repl } // namespace mongo |