예제 #1
0
/**
 * *this SocketAddress was created from the numeric IP address of a
 *  connecting host.
 * The lo and hi addresses are the limit checks from the ACL file.
 * Return true if this address is in range of any of the address pairs
 * in the limit check range.
 *
 * This check is executed on every incoming connection.
 */
bool SocketAddress::inRange(const SocketAddress& lo,
                            const SocketAddress& hi) const
{
    (*this).firstAddress();
    lo.firstAddress();
    hi.firstAddress();
    const ::addrinfo& thisInfo = getAddrInfo(*this);
    const ::addrinfo& loInfo   = getAddrInfo(lo);
    const ::addrinfo& hiInfo   = getAddrInfo(hi);
    if (inRange(thisInfo, loInfo, hiInfo)) {
        return true;
    }
    while (lo.nextAddress()) {
        if (!hi.nextAddress()) {
            assert (false);
            throw(Exception(QPID_MSG("Comparison iteration fails: " +
                                     lo.asString() + hi.asString())));
        }
        const ::addrinfo& loInfo = getAddrInfo(lo);
        const ::addrinfo& hiInfo = getAddrInfo(hi);
        if (inRange(thisInfo, loInfo, hiInfo)) {
            return true;
        }
    }
    return false;
}
예제 #2
0
int Socket::listen(const SocketAddress& addr, int backlog) const
{
    createSocket(addr);

    const SOCKET& socket = impl->fd;
    BOOL yes=1;
    QPID_WINSOCK_CHECK(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)));

    if (::bind(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) == SOCKET_ERROR)
        throw Exception(QPID_MSG("Can't bind to " << addr.asString() << ": " << strError(WSAGetLastError())));
    if (::listen(socket, backlog) == SOCKET_ERROR)
        throw Exception(QPID_MSG("Can't listen on " <<addr.asString() << ": " << strError(WSAGetLastError())));

    return getLocalPort(socket);
}
예제 #3
0
void AsynchConnector::connComplete(DispatchHandle& h)
{
    int errCode = socket.getError();
    if (errCode == 0) {
        h.stopWatch();
        try {
            socket.finishConnect(sa);
        } catch (const std::exception& e) {
            failCallback(socket, 0, e.what());
            DispatchHandle::doDelete();
            return;
        }
        connCallback(socket);
    } else {
        // Retry while we cause an immediate exception
        // (asynch failure will be handled by re-entering here at the top)
        while (sa.nextAddress()) {
            try {
                // Try next address without deleting ourselves
                QPID_LOG(debug, "Ignored socket connect error: " << strError(errCode));
                QPID_LOG(info, "Retrying connect: " << sa.asString());
                socket.connect(sa);
                return;
            } catch (const std::exception& e) {
                QPID_LOG(debug, "Ignored socket connect exception: " << e.what());
            }
            errCode = socket.getError();
        }
        h.stopWatch();
        failCallback(socket, errCode, strError(errCode));
    }
    DispatchHandle::doDelete();
}
예제 #4
0
void
Socket::connect(const SocketAddress& addr) const
{
    peername = addr.asString(false);

    createSocket(addr);

    const SOCKET& socket = impl->fd;
    int err;
    WSASetLastError(0);
    if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) != 0) &&
        ((err = ::WSAGetLastError()) != WSAEWOULDBLOCK))
        throw qpid::Exception(QPID_MSG(strError(err) << ": " << peername));
}
예제 #5
0
/**
 * this represents the low address of an ACL address range.
 * Given rangeHi that represents the high address,
 * return a string showing the numeric comparisons that the
 * inRange checks will do for address pair.
 */
std::string SocketAddress::comparisonDetails(const SocketAddress& rangeHi) const
{
    std::ostringstream os;
    SocketAddress thisSa(*this);
    SocketAddress rangeHiSa(rangeHi);
    (void) getAddrInfo(thisSa);
    (void) getAddrInfo(rangeHiSa);
    os << "(" << thisSa.asString(true, true, false) <<
          "," << rangeHiSa.asString(true, true, false) << ")";
    while (thisSa.nextAddress()) {
        if (!rangeHiSa.nextAddress()) {
            throw(Exception(QPID_MSG("Comparison iteration fails: " + (*this).asString() +
                                      rangeHi.asString())));
        }
        os << ",(" << thisSa.asString(true, true, false) <<
            "," << rangeHiSa.asString(true, true, false) << ")";
    }
    if (rangeHiSa.nextAddress()) {
        throw(Exception(QPID_MSG("Comparison iteration fails: " + (*this).asString() +
                                    rangeHi.asString())));
    }
    std::string result = os.str();
    return result;
}
예제 #6
0
/**
 * For ACL address matching make sure that the two addresses, *this
 * which is the low address and hiPeer which is the high address, are
 * both numeric ip addresses of the same family and that hi > *this.
 *
 * Note that if the addresses resolve to more than one struct addrinfo
 * then this and the hiPeer must be equal. This avoids having to do
 * difficult range checks where the this and hiPeer both resolve to
 * multiple IPv4 or IPv6 addresses.
 *
 * This check is run at acl file load time and not at run tme.
 */
bool SocketAddress::isComparable(const SocketAddress& hiPeer) const {
    try {
        // May only compare if this socket is IPv4 or IPv6
        SocketAddress lo(*this);
        const ::addrinfo& peerLoInfo = getAddrInfo(lo);
        if (!(peerLoInfo.ai_family == AF_INET || peerLoInfo.ai_family == AF_INET6)) {
            return false;
        }
        try {
            // May only compare if peer socket is same family
            SocketAddress hi(hiPeer);
            const ::addrinfo& peerHiInfo = getAddrInfo(hi);
            if (peerLoInfo.ai_family != peerHiInfo.ai_family) {
                return false;
            }
            // Host names that resolve to lists are allowed if they are equal.
            // For example: localhost, or fjord.lab.example.com
            if ((*this).asString() == hiPeer.asString()) {
                return true;
            }
            // May only compare if this and peer resolve to single address.
            if (lo.nextAddress() || hi.nextAddress()) {
                return false;
            }
            // Make sure that the lo/hi relationship is ok
            int res;
            if (!compareAddresses(peerLoInfo, peerHiInfo, res) || res < 0) {
                return false;
            }
            return true;
        } catch (Exception) {
            // failed to resolve hi
            return false;
        }
    } catch (Exception) {
        // failed to resolve lo
        return false;
    }
}