Ejemplo n.º 1
0
bool isSelf(const HostAndPort& hostAndPort, ServiceContext* const ctx) {
    // 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_ips;

        // If any of the bound addresses is the default route (0.0.0.0 on IPv4) it means we are
        // listening on all network interfaces and need to check against any of them.
        if (myAddrs.empty() ||
            std::any_of(myAddrs.cbegin(), myAddrs.cend(), [](std::string const& addrStr) {
                return HostAndPort(addrStr, serverGlobalParams.port).isDefaultRoute();
            })) {
            myAddrs = getBoundAddrs(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;
                }
            }
        }
    }

    ctx->waitForStartupComplete();

    try {
        DBClientConnection conn;
        conn.setSoTimeout(30);  // 30 second timeout

        // We need to avoid the isMaster call triggered by a normal connect, which would
        // cause a deadlock. 'isSelf' is called by the Replication Coordinator when validating
        // a replica set configuration document, but the 'isMaster' command requires a lock on the
        // replication coordinator to execute. As such we call we call 'connectSocketOnly', which
        // does not call 'isMaster'.
        if (!conn.connectSocketOnly(hostAndPort).isOK()) {
            return false;
        }

        if (auth::isInternalAuthSet() && !conn.authenticateInternalUser().isOK()) {
            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() << "couldn't check isSelf (" << hostAndPort << ") " << e.what() << std::endl;
    }

    return false;
}
Ejemplo n.º 2
0
    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(", "));
            }

            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;
                    }
                }
            }
        }

        if (!Listener::getTimeTracker()) {
            // this ensures we are actually running a server
            // this may return true later, so may want to retry
            return false;
        }

        try {
            DBClientConnection conn;
            std::string errmsg;
            if (!conn.connect(hostAndPort, errmsg)) {
                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;
        }

        return false;
    }
Ejemplo n.º 3
0
// If an ip address is passed in, just return that.  If a hostname is passed
// in, look up its ip and return that.  Returns "" on failure.
std::string hostbyname(const char* hostname) {
    SockAddr sockAddr(hostname, 0, IPv6Enabled() ? AF_UNSPEC : AF_INET);
    if (!sockAddr.isValid() || sockAddr.getAddr() == "0.0.0.0")
        return "";
    else
        return sockAddr.getAddr();
}
Ejemplo n.º 4
0
    SockAddr::SockAddr(const char * _iporhost , int port) {
        string target = _iporhost;
        if( target == "localhost" ) {
            target = "127.0.0.1";
        }

        if( mongoutils::str::contains(target, '/') ) {
#ifdef _WIN32
            uassert(13080, "no unix socket support on windows", false);
#endif
            uassert(13079, "path to unix socket too long", 
                    target.size() < sizeof(as<sockaddr_un>().sun_path));
            as<sockaddr_un>().sun_family = AF_UNIX;
            strcpy(as<sockaddr_un>().sun_path, target.c_str());
            addressSize = sizeof(sockaddr_un);
        }
        else {
            addrinfo* addrs = NULL;
            addrinfo hints;
            memset(&hints, 0, sizeof(addrinfo));
            hints.ai_socktype = SOCK_STREAM;
            //hints.ai_flags = AI_ADDRCONFIG; // This is often recommended but don't do it. 
                                              // SERVER-1579
            hints.ai_flags |= AI_NUMERICHOST; // first pass tries w/o DNS lookup
            hints.ai_family = (IPv6Enabled() ? AF_UNSPEC : AF_INET);

            StringBuilder ss;
            ss << port;
            int ret = getaddrinfo(target.c_str(), ss.str().c_str(), &hints, &addrs);

            // old C compilers on IPv6-capable hosts return EAI_NODATA error
#ifdef EAI_NODATA
            int nodata = (ret == EAI_NODATA);
#else
            int nodata = false;
#endif
            if ( (ret == EAI_NONAME || nodata) ) {
                // iporhost isn't an IP address, allow DNS lookup
                hints.ai_flags &= ~AI_NUMERICHOST;
                ret = getaddrinfo(target.c_str(), ss.str().c_str(), &hints, &addrs);
            }

            if (ret) {
                // we were unsuccessful
                if( target != "0.0.0.0" ) { // don't log if this as it is a 
                                            // CRT construction and log() may not work yet.
                    log() << "getaddrinfo(\"" << target << "\") failed: " << 
                        gai_strerror(ret) << endl;
                }
                *this = SockAddr(port);
            }
            else {
                //TODO: handle other addresses in linked list;
                fassert(16501, addrs->ai_addrlen <= sizeof(sa));
                memcpy(&sa, addrs->ai_addr, addrs->ai_addrlen);
                addressSize = addrs->ai_addrlen;
                freeaddrinfo(addrs);
            }
        }
    }
Ejemplo n.º 5
0
    SockAddr::SockAddr(const char * iporhost , int port) {
        if (!strcmp(iporhost, "localhost"))
            iporhost = "127.0.0.1";

        if (strchr(iporhost, '/')) {
#ifdef _WIN32
            uassert(13080, "no unix socket support on windows", false);
#endif
            uassert(13079, "path to unix socket too long", strlen(iporhost) < sizeof(as<sockaddr_un>().sun_path));
            as<sockaddr_un>().sun_family = AF_UNIX;
            strcpy(as<sockaddr_un>().sun_path, iporhost);
            addressSize = sizeof(sockaddr_un);
        }
        else {
            addrinfo* addrs = NULL;
            addrinfo hints;
            memset(&hints, 0, sizeof(addrinfo));
            hints.ai_socktype = SOCK_STREAM;
            //hints.ai_flags = AI_ADDRCONFIG; // This is often recommended but don't do it. SERVER-1579
            hints.ai_flags |= AI_NUMERICHOST; // first pass tries w/o DNS lookup
            hints.ai_family = (IPv6Enabled() ? AF_UNSPEC : AF_INET);

            stringstream ss;
            ss << port;
            int ret = getaddrinfo(iporhost, ss.str().c_str(), &hints, &addrs);

            // old C compilers on IPv6-capable hosts return EAI_NODATA error
#ifdef EAI_NODATA
            int nodata = (ret == EAI_NODATA);
#else
            int nodata = false;
#endif
            if (ret == EAI_NONAME || nodata) {
                // iporhost isn't an IP address, allow DNS lookup
                hints.ai_flags &= ~AI_NUMERICHOST;
                ret = getaddrinfo(iporhost, ss.str().c_str(), &hints, &addrs);
            }

            if (ret) {
                log() << "getaddrinfo(\"" << iporhost << "\") failed: " << gai_strerror(ret) << endl;
                *this = SockAddr(port);
            }
            else {
                //TODO: handle other addresses in linked list;
                assert(addrs->ai_addrlen <= sizeof(sa));
                memcpy(&sa, addrs->ai_addr, addrs->ai_addrlen);
                addressSize = addrs->ai_addrlen;
                freeaddrinfo(addrs);
            }
        }
    }
Ejemplo n.º 6
0
    vector<string> getAllIPs(const string& iporhost) {
        addrinfo* addrs = NULL;
        addrinfo hints;
        memset(&hints, 0, sizeof(addrinfo));
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_family = (IPv6Enabled() ? AF_UNSPEC : AF_INET);

        static string portNum = BSONObjBuilder::numStr(serverGlobalParams.port);

        vector<string> out;

        int ret = getaddrinfo(iporhost.c_str(), portNum.c_str(), &hints, &addrs);
        if ( ret ) {
            warning() << "getaddrinfo(\"" << iporhost << "\") failed: " << gai_strerror(ret) << endl;
            return out;
        }

        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) {
                int status = getnameinfo(addr->ai_addr, addr->ai_addrlen, host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);

                massert(13472, string("getnameinfo() failed: ") + gai_strerror(status), status == 0);

                out.push_back(host);
            }

        }

        freeaddrinfo(addrs);

        if (logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(1))) {
            LogstreamBuilder builder(logger::globalLogDomain(),
                                     getThreadName(),
                                     logger::LogSeverity::Debug(1));
            builder << "getallIPs(\"" << iporhost << "\"):";
            for (vector<string>::const_iterator it=out.begin(), end=out.end(); it!=end; ++it) {
                builder << " [" << *it << ']';
            }
            builder << endl;
        }

        return out;
    }
Ejemplo n.º 7
0
vector<string> getAllIPs(StringData iporhost) {
    addrinfo* addrs = NULL;
    addrinfo hints;
    memset(&hints, 0, sizeof(addrinfo));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = (IPv6Enabled() ? AF_UNSPEC : AF_INET);

    static string portNum = BSONObjBuilder::numStr(cmdLine.port);

    vector<string> out;

    int ret = getaddrinfo(iporhost.data(), portNum.c_str(), &hints, &addrs);
    if ( ret ) {
        warning() << "getaddrinfo(\"" << iporhost.data() << "\") failed: " << gai_strerror(ret) << endl;
        return out;
    }

    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) {
            int status = getnameinfo(addr->ai_addr, addr->ai_addrlen, host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);

            massert(13472, string("getnameinfo() failed: ") + gai_strerror(status), status == 0);

            out.push_back(host);
        }

    }

    freeaddrinfo(addrs);

    if (logLevel >= 1) {
        log(1) << "getallIPs(\"" << iporhost << "\"):";
        for (vector<string>::const_iterator it=out.begin(), end=out.end(); it!=end; ++it) {
            log(1) << " [" << *it << ']';
        }
        log(1) << endl;
    }

    return out;
}
Ejemplo n.º 8
0
    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;

    }
Ejemplo n.º 9
0
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(", "));
        }

        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;
                }
            }
        }
    }

    // Ensure that the server is up and ready to accept incoming network requests.
    const Listener* listener = Listener::getTimeTracker();
    if (!listener) {
        return false;
    }
    listener->waitUntilListening();

    try {
        DBClientConnection conn;
        conn.setSoTimeout(30);  // 30 second timeout

        // We need to avoid the isMaster call triggered by a normal connect, which would
        // cause a deadlock. 'isSelf' is called by the Replication Coordinator when validating
        // a replica set configuration document, but the 'isMaster' command requires a lock on the
        // replication coordinator to execute. As such we call we call 'connectSocketOnly', which
        // does not call 'isMaster'.
        if (!conn.connectSocketOnly(hostAndPort).isOK()) {
            return false;
        }

        if (getGlobalAuthorizationManager()->isAuthEnabled() && isInternalAuthSet()) {
            if (!conn.authenticateInternalUser()) {
                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() << "couldn't check isSelf (" << hostAndPort << ") " << e.what() << std::endl;
    }

    return false;
}