Exemple #1
0
/**
 * \brief Receives packets from a DAG interface.
 *
 * \param tv pointer to ThreadVars
 * \param data pointer to ErfDagThreadVars
 * \param slot slot containing task information
 *
 * \retval TM_ECODE_OK on success
 * \retval TM_ECODE_FAILED on failure
 */
TmEcode ReceiveErfDagLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    ErfDagThreadVars *dtv = (ErfDagThreadVars *)data;
    uint32_t diff = 0;
    int      err;
    uint8_t  *top = NULL;
    uint32_t pkts_read = 0;
    TmSlot *s = (TmSlot *)slot;

    dtv->slot = s->slot_next;

    while (1)
    {
        if (suricata_ctl_flags & (SURICATA_STOP || SURICATA_KILL)) {
            SCReturnInt(TM_ECODE_OK);
        }

        top = dag_advance_stream(dtv->dagfd, dtv->dagstream, &(dtv->btm));
        if (top == NULL) {
            if (errno == EAGAIN) {
                if (dtv->dagstream & 0x1) {
                    usleep(10 * 1000);
                    dtv->btm = dtv->top;
                }
                continue;
            } else {
                SCLogError(SC_ERR_ERF_DAG_STREAM_READ_FAILED,
                           "Failed to read from stream: %d, DAG: %s when "
                           "using dag_advance_stream",
                           dtv->dagstream, dtv->dagname);
                SCReturnInt(TM_ECODE_FAILED);
            }
        }

        diff = top - dtv->btm;
        if (diff == 0) {
            continue;
        }

        assert(diff >= dag_record_size);

        err = ProcessErfDagRecords(dtv, top, &pkts_read);

        if (err == TM_ECODE_FAILED) {
            SCLogError(SC_ERR_ERF_DAG_STREAM_READ_FAILED,
                       "Failed to read from stream: %d, DAG: %s",
                       dtv->dagstream, dtv->dagname);
            ReceiveErfDagCloseStream(dtv->dagfd, dtv->dagstream);
            SCReturnInt(TM_ECODE_FAILED);
        }

        SCLogDebug("Read %d records from stream: %d, DAG: %s",
                   pkts_read, dtv->dagstream, dtv->dagname);
    }

    SCReturnInt(TM_ECODE_OK);
}
Exemple #2
0
/**
 * \brief   Thread entry function for reading ERF records from a DAG card.
 *
 *          Reads a new ERF record the DAG input buffer and copies it to
 *          an internal Suricata packet buffer -- similar to the way the
 *          pcap packet handler works.
 *
 *          We create new packet structures using PacketGetFromQueueOrAlloc
 *          for each packet between the top and btm pointers except for
 *          the first packet for which a Packet buffer is provided
 *          from the packetpool.
 *
 *          We always read up to dag_max_read_packets ERF packets from the
 *          DAG buffer, but we might read less. This differs from the
 *          ReceivePcap handler -- it will only read pkts up to a maximum
 *          of either the packetpool count or the pcap_max_read_packets.
 *
 * \param   tv pointer to ThreadVars
 * \param   p data pointer
 * \param   data
 * \param   pq pointer to the PacketQueue (not used here)
 * \param   postpq
 * \retval  TM_ECODE_FAILED on failure and TM_ECODE_OK on success.
 * \note    We also use the packetpool hack first used in the source-pcap
 *          handler so we don't keep producing packets without any dying.
 *          This implies that if we are in this situation we run the risk
 *          of dropping packets at the interface.
 */
TmEcode
ReceiveErfDag(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq,
               PacketQueue *postpq)
{
    SCEnter();

    uint16_t packet_q_len = 0;
    uint32_t diff = 0;
    int      err;
    uint8_t  *top = NULL;
    uint32_t pkts_read = 0;

    assert(p);
    assert(pq);
    assert(postpq);

    ErfDagThreadVars *ewtn = (ErfDagThreadVars *)data;

    /* NOTE/JNM: Hack copied from source-pcap.c
     *
     * Make sure we have at least one packet in the packet pool, to
     * prevent us from alloc'ing packets at line rate
     */
    while (packet_q_len == 0) {
        packet_q_len = PacketPoolSize();
        if (packet_q_len == 0) {
            PacketPoolWait();
        }
    }

    if (postpq == NULL) {
        ewtn->dag_max_read_packets = 1;
    }

    while(pkts_read == 0)
    {
	    if (suricata_ctl_flags != 0) {
            break;
        }

        /* NOTE/JNM: This might not work well if we start restricting the
	     * number of ERF records processed per call to a small number as
	     * the over head required here could exceed the time it takes to
	     * process a small number of ERF records.
	     *
	     * XXX/JNM: Possibly process the DAG stream buffer first if there
	     * are ERF packets or else call dag_advance_stream and then process
	     * the DAG stream buffer.
	     */
	    top = dag_advance_stream(ewtn->dagfd, ewtn->dagstream, &(ewtn->btm));

	    if (NULL == top)
	    {
	        if((ewtn->dagstream & 0x1) && (errno == EAGAIN)) {
	            usleep(10 * 1000);
	            ewtn->btm = ewtn->top;
                continue;
	        }
	        else {
	            SCLogError(SC_ERR_ERF_DAG_STREAM_READ_FAILED,
	                       "Failed to read from stream: %d, DAG: %s when using dag_advance_stream",
	                       ewtn->dagstream, ewtn->dagname);
	            SCReturnInt(TM_ECODE_FAILED);
	        }
	    }

	    diff = top - ewtn->btm;
	    if (diff == 0)
	    {
	        continue;
	    }

	    assert(diff >= dag_record_size);

	    err = ProcessErfDagRecords(ewtn, p, top, postpq, &pkts_read);

        if (err == TM_ECODE_FAILED) {
             SCLogError(SC_ERR_ERF_DAG_STREAM_READ_FAILED,
                   "Failed to read from stream: %d, DAG: %s",
                   ewtn->dagstream, ewtn->dagname);
            ReceiveErfDagCloseStream(ewtn->dagfd, ewtn->dagstream);
            SCReturnInt(err);
        }
    }

    SCLogDebug("Read %d records from stream: %d, DAG: %s",
        pkts_read, ewtn->dagstream, ewtn->dagname);

    if (suricata_ctl_flags != 0) {
        SCReturnInt(TM_ECODE_FAILED);
    }

    SCReturnInt(err);
}