Esempio n. 1
0
/** \brief Get Flow for packet
 *
 * Hash retrieval function for flows. Looks up the hash bucket containing the
 * flow pointer. Then compares the packet with the found flow to see if it is
 * the flow we need. If it isn't, walk the list until the right flow is found.
 *
 * If the flow is not found or the bucket was emtpy, a new flow is taken from
 * the queue. FlowDequeue() will alloc new flows as long as we stay within our
 * memcap limit.
 *
 * The p->flow pointer is updated to point to the flow.
 *
 *  \param tv thread vars
 *  \param dtv decode thread vars (for flow log api thread data)
 *
 *  \retval f *LOCKED* flow or NULL
 */
Flow *FlowGetFlowFromHash(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p, Flow **dest)
{
    Flow *f = NULL;

    /* get our hash bucket and lock it */
    const uint32_t hash = p->flow_hash;
    FlowBucket *fb = &flow_hash[hash % flow_config.hash_size];
    FBLOCK_LOCK(fb);

    SCLogDebug("fb %p fb->head %p", fb, fb->head);

    /* see if the bucket already has a flow */
    if (fb->head == NULL) {
        f = FlowGetNew(tv, dtv, p);
        if (f == NULL) {
            FBLOCK_UNLOCK(fb);
            return NULL;
        }

        /* flow is locked */
        fb->head = f;
        fb->tail = f;

        /* got one, now lock, initialize and return */
        FlowInit(f, p);
        f->flow_hash = hash;
        f->fb = fb;
        FlowUpdateState(f, FLOW_STATE_NEW);

        FlowReference(dest, f);

        FBLOCK_UNLOCK(fb);
        return f;
    }

    /* ok, we have a flow in the bucket. Let's find out if it is our flow */
    f = fb->head;

    /* see if this is the flow we are looking for */
    if (FlowCompare(f, p) == 0) {
        Flow *pf = NULL; /* previous flow */

        while (f) {
            pf = f;
            f = f->hnext;

            if (f == NULL) {
                f = pf->hnext = FlowGetNew(tv, dtv, p);
                if (f == NULL) {
                    FBLOCK_UNLOCK(fb);
                    return NULL;
                }
                fb->tail = f;

                /* flow is locked */

                f->hprev = pf;

                /* initialize and return */
                FlowInit(f, p);
                f->flow_hash = hash;
                f->fb = fb;
                FlowUpdateState(f, FLOW_STATE_NEW);

                FlowReference(dest, f);

                FBLOCK_UNLOCK(fb);
                return f;
            }

            if (FlowCompare(f, p) != 0) {
                /* we found our flow, lets put it on top of the
                 * hash list -- this rewards active flows */
                if (f->hnext) {
                    f->hnext->hprev = f->hprev;
                }
                if (f->hprev) {
                    f->hprev->hnext = f->hnext;
                }
                if (f == fb->tail) {
                    fb->tail = f->hprev;
                }

                f->hnext = fb->head;
                f->hprev = NULL;
                fb->head->hprev = f;
                fb->head = f;

                /* found our flow, lock & return */
                FLOWLOCK_WRLOCK(f);
                if (unlikely(TcpSessionPacketSsnReuse(p, f, f->protoctx) == 1)) {
                    f = TcpReuseReplace(tv, dtv, fb, f, hash, p);
                    if (f == NULL) {
                        FBLOCK_UNLOCK(fb);
                        return NULL;
                    }
                }

                FlowReference(dest, f);

                FBLOCK_UNLOCK(fb);
                return f;
            }
        }
    }

    /* lock & return */
    FLOWLOCK_WRLOCK(f);
    if (unlikely(TcpSessionPacketSsnReuse(p, f, f->protoctx) == 1)) {
        f = TcpReuseReplace(tv, dtv, fb, f, hash, p);
        if (f == NULL) {
            FBLOCK_UNLOCK(fb);
            return NULL;
        }
    }

    FlowReference(dest, f);

    FBLOCK_UNLOCK(fb);
    return f;
}
Esempio n. 2
0
/* FlowGetFlowFromHash
 *
 * Hash retrieval function for flows. Looks up the hash bucket containing the
 * flow pointer. Then compares the packet with the found flow to see if it is
 * the flow we need. If it isn't, walk the list until the right flow is found.
 *
 * If the flow is not found or the bucket was emtpy, a new flow is taken from
 * the queue. FlowDequeue() will alloc new flows as long as we stay within our
 * memcap limit.
 *
 * The p->flow pointer is updated to point to the flow.
 *
 * returns a *LOCKED* flow or NULL
 */
Flow *FlowGetFlowFromHash(const Packet *p)
{
    Flow *f = NULL;
    FlowHashCountInit;

    /* get the key to our bucket */
    uint32_t key = FlowGetKey(p);
    /* get our hash bucket and lock it */
    FlowBucket *fb = &flow_hash[key];
    FBLOCK_LOCK(fb);

    SCLogDebug("fb %p fb->head %p", fb, fb->head);

    FlowHashCountIncr;

    /* see if the bucket already has a flow */
    if (fb->head == NULL) {
        f = FlowGetNew(p);
        if (f == NULL) {
            FBLOCK_UNLOCK(fb);
            FlowHashCountUpdate;
            return NULL;
        }

        /* flow is locked */
        fb->head = f;
        fb->tail = f;

        /* got one, now lock, initialize and return */
        FlowInit(f, p);
        f->fb = fb;

        FBLOCK_UNLOCK(fb);
        FlowHashCountUpdate;
        return f;
    }

    /* ok, we have a flow in the bucket. Let's find out if it is our flow */
    f = fb->head;

    /* see if this is the flow we are looking for */
    if (FlowCompare(f, p) == 0) {
        Flow *pf = NULL; /* previous flow */

        while (f) {
            FlowHashCountIncr;

            pf = f;
            f = f->hnext;

            if (f == NULL) {
                f = pf->hnext = FlowGetNew(p);
                if (f == NULL) {
                    FBLOCK_UNLOCK(fb);
                    FlowHashCountUpdate;
                    return NULL;
                }
                fb->tail = f;

                /* flow is locked */

                f->hprev = pf;

                /* initialize and return */
                FlowInit(f, p);
                f->fb = fb;

                FBLOCK_UNLOCK(fb);
                FlowHashCountUpdate;
                return f;
            }

            if (FlowCompare(f, p) != 0) {
                /* we found our flow, lets put it on top of the
                 * hash list -- this rewards active flows */
                if (f->hnext) {
                    f->hnext->hprev = f->hprev;
                }
                if (f->hprev) {
                    f->hprev->hnext = f->hnext;
                }
                if (f == fb->tail) {
                    fb->tail = f->hprev;
                }

                f->hnext = fb->head;
                f->hprev = NULL;
                fb->head->hprev = f;
                fb->head = f;

                /* found our flow, lock & return */
                FLOWLOCK_WRLOCK(f);
                FBLOCK_UNLOCK(fb);
                FlowHashCountUpdate;
                return f;
            }
        }
    }

    /* lock & return */
    FLOWLOCK_WRLOCK(f);
    FBLOCK_UNLOCK(fb);
    FlowHashCountUpdate;
    return f;
}
Esempio n. 3
0
int detection_option_key_compare_func(const void *k1, const void *k2, size_t n)
{
    int ret = DETECTION_OPTION_NOT_EQUAL;
    const detection_option_key_t *key1 = (detection_option_key_t*)k1;
    const detection_option_key_t *key2 = (detection_option_key_t*)k2;

#ifdef KEEP_THEM_ALLOCATED
    return DETECTION_OPTION_NOT_EQUAL;
#endif

    if (!key1 || !key2)
        return DETECTION_OPTION_NOT_EQUAL;

    if (key1->option_type != key2->option_type)
        return DETECTION_OPTION_NOT_EQUAL;

    switch (key1->option_type)
    {
        /* Call compare function specific to the key type */
        case RULE_OPTION_TYPE_LEAF_NODE:
            /* Leaf node always not equal. */
            break;
        case RULE_OPTION_TYPE_ASN1:
            ret = Asn1Compare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_BYTE_TEST:
            ret = ByteTestCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_BYTE_JUMP:
            ret = ByteJumpCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_FLOW:
            ret = FlowCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_CVS:
            ret = CvsCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_DSIZE:
            ret = DSizeCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_FLOWBIT:
            ret = FlowBitsCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_FTPBOUNCE:
            break;
        case RULE_OPTION_TYPE_ICMP_CODE:
            ret = IcmpCodeCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_ICMP_ID:
            ret = IcmpIdCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_ICMP_SEQ:
            ret = IcmpSeqCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_ICMP_TYPE:
            ret = IcmpTypeCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_IP_FRAGBITS:
            ret = IpFragBitsCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_IP_FRAG_OFFSET:
            ret = IpFragOffsetCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_IP_ID:
            ret = IpIdCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_IP_OPTION:
            ret = IpOptionCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_IP_PROTO:
            ret = IpProtoCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_IP_SAME:
            ret = IpSameCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_IP_TOS:
            ret = IpTosCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_IS_DATA_AT:
            ret = IsDataAtCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_CONTENT:
        case RULE_OPTION_TYPE_CONTENT_URI:
            ret = PatternMatchCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_PCRE:
            ret = PcreCompare(key1->option_data, key2->option_data);
            break;
#ifdef ENABLE_REACT
        case RULE_OPTION_TYPE_REACT:
            ret = ReactCompare(key1->option_data, key2->option_data);
            break;
#endif
#ifdef ENABLE_RESPOND
        case RULE_OPTION_TYPE_RESPOND:
            ret = RespondCompare(key1->option_data, key2->option_data);
            break;
#endif
        case RULE_OPTION_TYPE_RPC_CHECK:
            ret = RpcCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_SESSION:
            ret = SessionCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_TCP_ACK:
            ret = TcpAckCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_TCP_FLAG:
            ret = TcpFlagCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_TCP_SEQ:
            ret = TcpSeqCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_TCP_WIN:
            ret = TcpWinCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_TTL:
            ret = TtlCheckCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_URILEN:
            ret = UriLenCheckCompare(key1->option_data, key2->option_data);
            break;
#ifdef DYNAMIC_PLUGIN
        case RULE_OPTION_TYPE_HDR_OPT_CHECK:
            ret = HdrOptCheckCompare(key1->option_data, key2->option_data);
        case RULE_OPTION_TYPE_PREPROCESSOR:
            ret = PreprocessorRuleOptionCompare(key1->option_data, key2->option_data);
            break;
        case RULE_OPTION_TYPE_DYNAMIC:
            ret = DynamicRuleCompare(key1->option_data, key2->option_data);
            break;
#endif
    }

    return ret;
}