Esempio n. 1
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: " <<
                      getAddrInfoStrError(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);
        }
    }
}
Esempio n. 2
0
 static SockAddr getLocalAddrForBoundSocketFd(int fd) {
     SockAddr result;
     int rc = getsockname(fd, result.raw(), &result.addressSize);
     if (rc != 0) {
         warning() << "Could not resolve local address for socket with fd " << fd << ": " <<
             getAddrInfoStrError(socketGetLastError());
         result = SockAddr();
     }
     return result;
 }
Esempio n. 3
0
 std::string SockAddr::getAddr() const {
     switch (getType()) {
     case AF_INET:
     case AF_INET6: {
         const int buflen=128;
         char buffer[buflen];
         int ret = getnameinfo(raw(), addressSize, buffer, buflen, NULL, 0, NI_NUMERICHOST);
         massert(13082, mongoutils::str::stream() << "getnameinfo error " << getAddrInfoStrError(ret), ret == 0);
         return buffer;
     }
         
     case AF_UNIX:  return (addressSize > 2 ? as<sockaddr_un>().sun_path : "anonymous unix socket");
     case AF_UNSPEC: return "(NONE)";
     default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); return "";
     }
 }
std::vector<std::string> getHostFQDNs(std::string hostName, HostnameCanonicalizationMode mode) {
#ifndef _WIN32
    using shim_char = char;
    using shim_addrinfo = struct addrinfo;
    const auto& shim_getaddrinfo = getaddrinfo;
    const auto& shim_freeaddrinfo = freeaddrinfo;
    const auto& shim_getnameinfo = getnameinfo;
    const auto& shim_toNativeString = [](const char* str) { return std::string(str); };
    const auto& shim_fromNativeString = [](const std::string& str) { return str; };
#else
    using shim_char = wchar_t;
    using shim_addrinfo = struct addrinfoW;
    const auto& shim_getaddrinfo = GetAddrInfoW;
    const auto& shim_freeaddrinfo = FreeAddrInfoW;
    const auto& shim_getnameinfo = GetNameInfoW;
    const auto& shim_toNativeString = toWideString;
    const auto& shim_fromNativeString = toUtf8String;
#endif

    std::vector<std::string> results;

    if (hostName.empty())
        return results;

    if (mode == HostnameCanonicalizationMode::kNone) {
        results.emplace_back(std::move(hostName));
        return results;
    }

    shim_addrinfo hints = {};
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = 0;
    hints.ai_protocol = 0;
    if (mode == HostnameCanonicalizationMode::kForward) {
        hints.ai_flags = AI_CANONNAME;
    }

    int err;
    shim_addrinfo* info;
    auto nativeHostName = shim_toNativeString(hostName.c_str());
    if ((err = shim_getaddrinfo(nativeHostName.c_str(), nullptr, &hints, &info)) != 0) {
        ONCE {
            warning() << "Failed to obtain address information for hostname " << hostName << ": "
                      << getAddrInfoStrError(err);
        }
        return results;
    }
std::vector<std::string> getHostFQDNs(std::string hostName, HostnameCanonicalizationMode mode) {
#ifndef _WIN32
    using shim_char = char;
    using shim_addrinfo = struct addrinfo;
    const auto& shim_getaddrinfo = getaddrinfo;
    const auto& shim_freeaddrinfo = freeaddrinfo;
    const auto& shim_getnameinfo = getnameinfo;
    const auto& shim_toNativeString = [](const char* str) { return std::string(str); };
    const auto& shim_fromNativeString = [](const std::string& str) { return str; };
#else
    using shim_char = wchar_t;
    using shim_addrinfo = struct addrinfoW;
    const auto& shim_getaddrinfo = GetAddrInfoW;
    const auto& shim_freeaddrinfo = FreeAddrInfoW;
    const auto& shim_getnameinfo = GetNameInfoW;
    const auto& shim_toNativeString = toWideString;
    const auto& shim_fromNativeString = toUtf8String;
#endif

    std::vector<std::string> results;

    if (hostName.empty())
        return results;

    if (mode == HostnameCanonicalizationMode::kNone) {
        results.emplace_back(std::move(hostName));
        return results;
    }

    shim_addrinfo hints = {};
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = 0;
    hints.ai_protocol = 0;
    if (mode == HostnameCanonicalizationMode::kForward) {
        hints.ai_flags = AI_CANONNAME;
    }

    int err;
    shim_addrinfo* info;
    auto nativeHostName = shim_toNativeString(hostName.c_str());
    if ((err = shim_getaddrinfo(nativeHostName.c_str(), nullptr, &hints, &info)) != 0) {
        LOG(3) << "Failed to obtain address information for hostname " << hostName << ": "
               << getAddrInfoStrError(err);
        return results;
    }
    const auto guard = MakeGuard([&shim_freeaddrinfo, &info] { shim_freeaddrinfo(info); });

    if (mode == HostnameCanonicalizationMode::kForward) {
        results.emplace_back(shim_fromNativeString(info->ai_canonname));
        return results;
    }

    bool encounteredErrors = false;
    std::stringstream getNameInfoErrors;
    getNameInfoErrors << "Failed to obtain name info for: [ ";
    for (shim_addrinfo* p = info; p; p = p->ai_next) {
        shim_char host[NI_MAXHOST] = {};
        if ((err = shim_getnameinfo(
                 p->ai_addr, p->ai_addrlen, host, sizeof(host), nullptr, 0, NI_NAMEREQD)) == 0) {
            results.emplace_back(shim_fromNativeString(host));
        } else {
            if (encounteredErrors) {
                getNameInfoErrors << ", ";
            }
            encounteredErrors = true;

            // Format the addrinfo structure we have into a string for reporting
            char ip_str[INET6_ADDRSTRLEN];
            struct sockaddr* addr = p->ai_addr;
            void* sin_addr = nullptr;

            if (p->ai_family == AF_INET) {
                struct sockaddr_in* addr_in = reinterpret_cast<struct sockaddr_in*>(addr);
                sin_addr = reinterpret_cast<void*>(&addr_in->sin_addr);
            } else if (p->ai_family == AF_INET6) {
                struct sockaddr_in6* addr_in6 = reinterpret_cast<struct sockaddr_in6*>(addr);
                sin_addr = reinterpret_cast<void*>(&addr_in6->sin6_addr);
            }

            getNameInfoErrors << "(";
            if (sin_addr) {
                invariant(inet_ntop(p->ai_family, sin_addr, ip_str, sizeof(ip_str)) != nullptr);
                getNameInfoErrors << ip_str;
            } else {
                getNameInfoErrors << "Unknown address family: " << p->ai_family;
            }

            getNameInfoErrors << ", \"" << getAddrInfoStrError(err) << "\")";
        }
    }

    if (encounteredErrors) {
        LOG(3) << getNameInfoErrors.str() << " ]";
    }

    // Deduplicate the results list
    std::sort(results.begin(), results.end());
    results.erase(std::unique(results.begin(), results.end()), results.end());

    // Remove any name that doesn't have a '.', since A records are illegal in TLDs
    results.erase(
        std::remove_if(results.begin(),
                       results.end(),
                       [](const std::string& str) { return str.find('.') == std::string::npos; }),
        results.end());

    return results;
}