summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/isself.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/repl/isself.cpp')
-rw-r--r--src/mongo/db/repl/isself.cpp423
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