Example #1
0
/**
 * \brief NFQ function to get a packet from the kernel
 *
 * \note separate functions for Linux and Win32 for readability.
 */
static void NFQRecvPkt(NFQQueueVars *t, NFQThreadVars *tv)
{
    int rv, ret;
    int flag = NFQVerdictCacheLen(t) ? MSG_DONTWAIT : 0;

    /* XXX what happens on rv == 0? */
    rv = recv(t->fd, tv->data, tv->datalen, flag);

    if (rv < 0) {
        if (errno == EINTR || errno == EWOULDBLOCK) {
            /* no error on timeout */
            if (flag)
                NFQVerdictCacheFlush(t);

            /* inject a fake packet on timeout */
            TmThreadsCaptureInjectPacket(tv->tv, tv->slot, NULL);
        } else {
#ifdef COUNTERS
            NFQMutexLock(t);
            t->errs++;
            NFQMutexUnlock(t);
#endif /* COUNTERS */
        }
    } else if(rv == 0) {
        SCLogWarning(SC_ERR_NFQ_RECV, "recv got returncode 0");
    } else {
#ifdef DBG_PERF
        if (rv > t->dbg_maxreadsize)
            t->dbg_maxreadsize = rv;
#endif /* DBG_PERF */

        //printf("NFQRecvPkt: t %p, rv = %" PRId32 "\n", t, rv);

        NFQMutexLock(t);
        if (t->qh != NULL) {
            ret = nfq_handle_packet(t->h, tv->data, rv);
        } else {
            SCLogWarning(SC_ERR_NFQ_HANDLE_PKT, "NFQ handle has been destroyed");
            ret = -1;
        }
        NFQMutexUnlock(t);

        if (ret != 0) {
            SCLogWarning(SC_ERR_NFQ_HANDLE_PKT, "nfq_handle_packet error %"PRId32" %s",
                    ret, strerror(errno));
        }
    }
}
Example #2
0
static int NFQVerdictCacheAdd(NFQQueueVars *t, Packet *p, uint32_t verdict)
{
#ifdef HAVE_NFQ_SET_VERDICT_BATCH
    if (t->verdict_cache.maxlen == 0)
        return -1;

    if (p->flags & PKT_STREAM_MODIFIED || verdict == NF_DROP)
        goto flush;

    if (p->flags & PKT_MARK_MODIFIED) {
        if (!t->verdict_cache.mark_valid) {
            if (t->verdict_cache.len)
                goto flush;
            t->verdict_cache.mark_valid = 1;
            t->verdict_cache.mark = p->nfq_v.mark;
        } else if (t->verdict_cache.mark != p->nfq_v.mark) {
            goto flush;
        }
    } else if (t->verdict_cache.mark_valid) {
        goto flush;
    }

    if (t->verdict_cache.len == 0) {
        t->verdict_cache.verdict = verdict;
    } else if (t->verdict_cache.verdict != verdict)
        goto flush;

    /* same verdict, mark not set or identical -> can cache */
    t->verdict_cache.packet_id = p->nfq_v.id;

    if (t->verdict_cache.len >= t->verdict_cache.maxlen)
        NFQVerdictCacheFlush(t);
    else
        t->verdict_cache.len++;
    return 0;
 flush:
    /* can't cache. Flush current cache and signal caller it should send single verdict */
    if (NFQVerdictCacheLen(t) > 0)
        NFQVerdictCacheFlush(t);
#endif
    return -1;
}