/**
 * \brief ERF file reading loop.
 */
TmEcode ReceiveErfFileLoop(ThreadVars *tv, void *data, void *slot)
{
    Packet *p = NULL;
    uint16_t packet_q_len = 0;
    ErfFileThreadVars *etv = (ErfFileThreadVars *)data;

    etv->slot = ((TmSlot *)slot)->slot_next;

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

        /* Make sure we have at least one packet in the packet pool,
         * to prevent us from alloc'ing packets at line rate. */
        do {
#ifdef __tile__
            packet_q_len = PacketPoolSize(0);
#else
            packet_q_len = PacketPoolSize();
#endif
            if (unlikely(packet_q_len == 0)) {
#ifdef __tile__
                PacketPoolWait(0);
#else
                PacketPoolWait();
#endif
            }
        } while (packet_q_len == 0);

#ifdef __tile__
        p = PacketGetFromQueueOrAlloc(0);
#else
        p = PacketGetFromQueueOrAlloc();
#endif
        if (unlikely(p == NULL)) {
            SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate a packet.");
            EngineStop();
            SCReturnInt(TM_ECODE_FAILED);
        }
        PKT_SET_SRC(p, PKT_SRC_WIRE);

        if (ReadErfRecord(tv, p, data) != TM_ECODE_OK) {
            TmqhOutputPacketpool(etv->tv, p);
            EngineStop();
            SCReturnInt(TM_ECODE_FAILED);
        }

        if (TmThreadsSlotProcessPkt(etv->tv, etv->slot, p) != TM_ECODE_OK) {
            EngineStop();
            SCReturnInt(TM_ECODE_FAILED);
        }
    }
    SCReturnInt(TM_ECODE_FAILED);
}
Exemple #2
0
static void PcapCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt)
{
    SCEnter();

    PcapThreadVars *ptv = (PcapThreadVars *)user;
    Packet *p = PacketGetFromQueueOrAlloc();
    struct timeval current_time;

    if (unlikely(p == NULL)) {
        SCReturn;
    }

    PKT_SET_SRC(p, PKT_SRC_WIRE);
    p->ts.tv_sec = h->ts.tv_sec;
    p->ts.tv_usec = h->ts.tv_usec;
    SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
    p->datalink = ptv->datalink;

    ptv->pkts++;
    ptv->bytes += h->caplen;
    (void) SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
    p->livedev = ptv->livedev;

    if (unlikely(PacketCopyData(p, pkt, h->caplen))) {
        TmqhOutputPacketpool(ptv->tv, p);
        SCReturn;
    }

    switch (ptv->checksum_mode) {
        case CHECKSUM_VALIDATION_AUTO:
            if (ptv->livedev->ignore_checksum) {
                p->flags |= PKT_IGNORE_CHECKSUM;
            } else if (ChecksumAutoModeCheck(ptv->pkts,
                        SC_ATOMIC_GET(ptv->livedev->pkts),
                        SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
                ptv->livedev->ignore_checksum = 1;
                p->flags |= PKT_IGNORE_CHECKSUM;
            }
            break;
        case CHECKSUM_VALIDATION_DISABLE:
            p->flags |= PKT_IGNORE_CHECKSUM;
            break;
        default:
            break;
    }

    if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
        pcap_breakloop(ptv->pcap_handle);
        ptv->cb_result = TM_ECODE_FAILED;
    }

    /* Trigger one dump of stats every second */
    TimeGet(&current_time);
    if (current_time.tv_sec != ptv->last_stats_dump) {
        PcapDumpCounters(ptv);
        ptv->last_stats_dump = current_time.tv_sec;
    }

    SCReturn;
}
Exemple #3
0
void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt) {
    SCEnter();

    PcapFileThreadVars *ptv = (PcapFileThreadVars *)user;
    Packet *p = PacketGetFromQueueOrAlloc();

    if (unlikely(p == NULL)) {
        SCReturn;
    }
    PACKET_PROFILING_TMM_START(p, TMM_RECEIVEPCAPFILE);

    p->ts.tv_sec = h->ts.tv_sec;
    p->ts.tv_usec = h->ts.tv_usec;
    SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
    p->datalink = pcap_g.datalink;
    p->pcap_cnt = ++pcap_g.cnt;

    ptv->pkts++;
    ptv->bytes += h->caplen;

    if (unlikely(PacketCopyData(p, pkt, h->caplen))) {
        TmqhOutputPacketpool(ptv->tv, p);
        PACKET_PROFILING_TMM_END(p, TMM_RECEIVEPCAPFILE);
        SCReturn;
    }
    PACKET_PROFILING_TMM_END(p, TMM_RECEIVEPCAPFILE);

    if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
        pcap_breakloop(pcap_g.pcap_handle);
        ptv->cb_result = TM_ECODE_FAILED;
    }

    SCReturn;
}
Exemple #4
0
/**
 *  \brief Setup a pseudo packet (reassembled frags)
 *
 *  Difference with PacketPseudoPktSetup is that this func doesn't increment
 *  the recursion level. It needs to be on the same level as the frags because
 *  we run the flow engine against this and we need to get the same flow.
 *
 *  \param parent parent packet for this pseudo pkt
 *  \param pkt raw packet data
 *  \param len packet data length
 *  \param proto protocol of the tunneled packet
 *
 *  \retval p the pseudo packet or NULL if out of memory
 */
Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto)
{
    SCEnter();

    /* get us a packet */
    Packet *p = PacketGetFromQueueOrAlloc();
    if (unlikely(p == NULL)) {
        SCReturnPtr(NULL, "Packet");
    }

    /* set the root ptr to the lowest layer */
    if (parent->root != NULL)
        p->root = parent->root;
    else
        p->root = parent;

    /* copy packet and set lenght, proto */
    PacketCopyData(p, pkt, len);
    p->recursion_level = parent->recursion_level; /* NOT incremented */
    p->ts.tv_sec = parent->ts.tv_sec;
    p->ts.tv_usec = parent->ts.tv_usec;
    p->datalink = DLT_RAW;
    /* tell new packet it's part of a tunnel */
    SET_TUNNEL_PKT(p);
    p->vlan_id[0] = parent->vlan_id[0];
    p->vlan_id[1] = parent->vlan_id[1];
    p->vlan_idx = parent->vlan_idx;

    SCReturnPtr(p, "Packet");
}
Exemple #5
0
static int NFQCallBack(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
                       struct nfq_data *nfa, void *data)
{
    NFQThreadVars *ntv = (NFQThreadVars *)data;
    ThreadVars *tv = ntv->tv;
    int ret;

    /* grab a packet */
    Packet *p = PacketGetFromQueueOrAlloc();
    if (p == NULL) {
        return -1;
    }
    PKT_SET_SRC(p, PKT_SRC_WIRE);

    p->nfq_v.nfq_index = ntv->nfq_index;
    /* if bypass mask is set then we may want to bypass so set pointer */
    if (nfq_config.bypass_mask) {
        p->BypassPacketsFlow = NFQBypassCallback;
    }
    ret = NFQSetupPkt(p, qh, (void *)nfa);
    if (ret == -1) {
#ifdef COUNTERS
        NFQQueueVars *q = NFQGetQueue(ntv->nfq_index);
        q->errs++;
        q->pkts++;
        q->bytes += GET_PKT_LEN(p);
#endif /* COUNTERS */
        (void) SC_ATOMIC_ADD(ntv->livedev->pkts, 1);

        /* NFQSetupPkt is issuing a verdict
           so we only recycle Packet and leave */
        TmqhOutputPacketpool(tv, p);
        return 0;
    }

    p->ReleasePacket = NFQReleasePacket;

#ifdef COUNTERS
    NFQQueueVars *q = NFQGetQueue(ntv->nfq_index);
    q->pkts++;
    q->bytes += GET_PKT_LEN(p);
#endif /* COUNTERS */
    (void) SC_ATOMIC_ADD(ntv->livedev->pkts, 1);

    if (ntv->slot) {
        if (TmThreadsSlotProcessPkt(tv, ntv->slot, p) != TM_ECODE_OK) {
            TmqhOutputPacketpool(ntv->tv, p);
            return -1;
        }
    } else {
        /* pass on... */
        tv->tmqh_out(tv, p);
    }

    return 0;
}
Exemple #6
0
/**
 *  \brief Setup a pseudo packet (tunnel)
 *
 *  \param parent parent packet for this pseudo pkt
 *  \param pkt raw packet data
 *  \param len packet data length
 *  \param proto protocol of the tunneled packet
 *
 *  \retval p the pseudo packet or NULL if out of memory
 */
Packet *PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent,
                             uint8_t *pkt, uint16_t len, enum DecodeTunnelProto proto,
                             PacketQueue *pq)
{
    int ret;

    SCEnter();

    /* get us a packet */
    Packet *p = PacketGetFromQueueOrAlloc();
    if (unlikely(p == NULL)) {
        SCReturnPtr(NULL, "Packet");
    }

    /* copy packet and set lenght, proto */
    PacketCopyData(p, pkt, len);
    p->recursion_level = parent->recursion_level + 1;
    p->ts.tv_sec = parent->ts.tv_sec;
    p->ts.tv_usec = parent->ts.tv_usec;
    p->datalink = DLT_RAW;
    p->tenant_id = parent->tenant_id;

    /* set the root ptr to the lowest layer */
    if (parent->root != NULL)
        p->root = parent->root;
    else
        p->root = parent;

    /* tell new packet it's part of a tunnel */
    SET_TUNNEL_PKT(p);

    ret = DecodeTunnel(tv, dtv, p, GET_PKT_DATA(p),
                       GET_PKT_LEN(p), pq, proto);

    if (unlikely(ret != TM_ECODE_OK)) {
        /* Not a tunnel packet, just a pseudo packet */
        p->root = NULL;
        UNSET_TUNNEL_PKT(p);
        TmqhOutputPacketpool(tv, p);
        SCReturnPtr(NULL, "Packet");
    }


    /* tell parent packet it's part of a tunnel */
    SET_TUNNEL_PKT(parent);

    /* increment tunnel packet refcnt in the root packet */
    TUNNEL_INCR_PKT_TPR(p);

    /* disable payload (not packet) inspection on the parent, as the payload
     * is the packet we will now run through the system separately. We do
     * check it against the ip/port/other header checks though */
    DecodeSetNoPayloadInspectionFlag(parent);
    SCReturnPtr(p, "Packet");
}
void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt)
{
    SCEnter();

    PcapFileFileVars *ptv = (PcapFileFileVars *)user;
    Packet *p = PacketGetFromQueueOrAlloc();

    if (unlikely(p == NULL)) {
        SCReturn;
    }
    PACKET_PROFILING_TMM_START(p, TMM_RECEIVEPCAPFILE);

    PKT_SET_SRC(p, PKT_SRC_WIRE);
    p->ts.tv_sec = h->ts.tv_sec;
    p->ts.tv_usec = h->ts.tv_usec;
    SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
    p->datalink = ptv->datalink;
    p->pcap_cnt = ++pcap_g.cnt;

    p->pcap_v.tenant_id = ptv->shared->tenant_id;
    ptv->shared->pkts++;
    ptv->shared->bytes += h->caplen;

    if (unlikely(PacketCopyData(p, pkt, h->caplen))) {
        TmqhOutputPacketpool(ptv->shared->tv, p);
        PACKET_PROFILING_TMM_END(p, TMM_RECEIVEPCAPFILE);
        SCReturn;
    }

    /* We only check for checksum disable */
    if (pcap_g.checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
        p->flags |= PKT_IGNORE_CHECKSUM;
    } else if (pcap_g.checksum_mode == CHECKSUM_VALIDATION_AUTO) {
        if (ChecksumAutoModeCheck(ptv->shared->pkts, p->pcap_cnt,
                                  SC_ATOMIC_GET(pcap_g.invalid_checksums))) {
            pcap_g.checksum_mode = CHECKSUM_VALIDATION_DISABLE;
            p->flags |= PKT_IGNORE_CHECKSUM;
        }
    }

    PACKET_PROFILING_TMM_END(p, TMM_RECEIVEPCAPFILE);

    if (TmThreadsSlotProcessPkt(ptv->shared->tv, ptv->shared->slot, p) != TM_ECODE_OK) {
        pcap_breakloop(ptv->pcap_handle);
        ptv->shared->cb_result = TM_ECODE_FAILED;
    }

    SCReturn;
}
Exemple #8
0
static int NFQCallBack(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
                       struct nfq_data *nfa, void *data)
{
    NFQThreadVars *ntv = (NFQThreadVars *)data;
    ThreadVars *tv = ntv->tv;
    int ret;

    /* grab a packet */
    Packet *p = PacketGetFromQueueOrAlloc();
    if (p == NULL) {
        return -1;
    }
    PKT_SET_SRC(p, PKT_SRC_WIRE);

    p->nfq_v.nfq_index = ntv->nfq_index;
    ret = NFQSetupPkt(p, qh, (void *)nfa);
    if (ret == -1) {
#ifdef COUNTERS
        NFQQueueVars *nfq_q = NFQGetQueue(ntv->nfq_index);
        nfq_q->errs++;
        nfq_q->pkts++;
        nfq_q->bytes += GET_PKT_LEN(p);
#endif /* COUNTERS */
        /* recycle Packet and leave */
        TmqhOutputPacketpool(tv, p);
        return 0;
    }

#ifdef COUNTERS
    NFQQueueVars *nfq_q = NFQGetQueue(ntv->nfq_index);
    nfq_q->pkts++;
    nfq_q->bytes += GET_PKT_LEN(p);
#endif /* COUNTERS */

    if (ntv->slot) {
        if (TmThreadsSlotProcessPkt(tv, ntv->slot, p) != TM_ECODE_OK) {
            TmqhOutputPacketpool(ntv->tv, p);
            return -1;
        }
    } else {
        /* pass on... */
        tv->tmqh_out(tv, p);
    }

    return 0;
}
Exemple #9
0
/**
 *  \brief Setup a pseudo packet (tunnel)
 *
 *  \param parent parent packet for this pseudo pkt
 *  \param pkt raw packet data
 *  \param len packet data length
 *  \param proto protocol of the tunneled packet
 *
 *  \retval p the pseudo packet or NULL if out of memory
 */
Packet *PacketPseudoPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto)
{
    SCEnter();

    /* get us a packet */
    Packet *p = PacketGetFromQueueOrAlloc();
    if (p == NULL) {
        SCReturnPtr(NULL, "Packet");
    }

    /* set the root ptr to the lowest layer */
    if (parent->root != NULL)
        p->root = parent->root;
    else
        p->root = parent;

    /* copy packet and set lenght, proto */
    PacketCopyData(p, pkt, len);
    p->recursion_level = parent->recursion_level + 1;
    p->ts.tv_sec = parent->ts.tv_sec;
    p->ts.tv_usec = parent->ts.tv_usec;
    p->datalink = DLT_RAW;

    /* set tunnel flags */

    /* tell new packet it's part of a tunnel */
    SET_TUNNEL_PKT(p);
    /* tell parent packet it's part of a tunnel */
    SET_TUNNEL_PKT(parent);

    /* increment tunnel packet refcnt in the root packet */
    TUNNEL_INCR_PKT_TPR(p);

    /* disable payload (not packet) inspection on the parent, as the payload
     * is the packet we will now run through the system separately. We do
     * check it against the ip/port/other header checks though */
    DecodeSetNoPayloadInspectionFlag(parent);
    SCReturnPtr(p, "Packet");
}
/**
 * \brief   Process a DAG record into a TM packet buffer.
 * \param   prec pointer to a DAG record.
 * \param
 */
static inline TmEcode ProcessErfDagRecord(ErfDagThreadVars *ewtn, char *prec)
{
    SCEnter();

    int wlen = 0;
    int rlen = 0;
    int hdr_num = 0;
    char hdr_type = 0;
    dag_record_t  *dr = (dag_record_t*)prec;
    erf_payload_t *pload;
    Packet *p;

    hdr_type = dr->type;
    wlen = ntohs(dr->wlen);
    rlen = ntohs(dr->rlen);

    /* count extension headers */
    while (hdr_type & 0x80) {
        if (rlen < (dag_record_size + (hdr_num * 8))) {
            SCLogError(SC_ERR_UNIMPLEMENTED,
                       "Insufficient captured packet length.");
            SCReturnInt(TM_ECODE_FAILED);
        }
        hdr_type = prec[(dag_record_size + (hdr_num * 8))];
        hdr_num++;
    }

    /* Check that the whole frame was captured */
    if (rlen < (dag_record_size + (8 * hdr_num) + 2 + wlen)) {
        SCLogInfo("Incomplete frame captured.");
        SCReturnInt(TM_ECODE_OK);
    }

    /* skip over extension headers */
    pload = (erf_payload_t *)(prec + dag_record_size + (8 * hdr_num));

    p = PacketGetFromQueueOrAlloc();
    if (p == NULL) {
        SCLogError(SC_ERR_MEM_ALLOC,
                   "Failed to allocate a Packet on stream: %d, DAG: %s",
                   ewtn->dagstream, ewtn->dagname);
        SCReturnInt(TM_ECODE_FAILED);
    }
    PKT_SET_SRC(p, PKT_SRC_WIRE);

    SET_PKT_LEN(p, wlen);
    p->datalink = LINKTYPE_ETHERNET;

    /* Take into account for link type Ethernet ETH frame starts
     * after ther ERF header + pad.
     */
    if (unlikely(PacketCopyData(p, pload->eth.dst, GET_PKT_LEN(p)))) {
        TmqhOutputPacketpool(ewtn->tv, p);
        SCReturnInt(TM_ECODE_FAILED);
    }

    /* Convert ERF time to timeval - from libpcap. */
    uint64_t ts = dr->ts;
    p->ts.tv_sec = ts >> 32;
    ts = (ts & 0xffffffffULL) * 1000000;
    ts += 0x80000000; /* rounding */
    p->ts.tv_usec = ts >> 32;
    if (p->ts.tv_usec >= 1000000) {
        p->ts.tv_usec -= 1000000;
        p->ts.tv_sec++;
    }

    SCPerfCounterIncr(ewtn->packets, ewtn->tv->sc_perf_pca);
    ewtn->bytes += wlen;

    if (TmThreadsSlotProcessPkt(ewtn->tv, ewtn->slot, p) != TM_ECODE_OK) {
        TmqhOutputPacketpool(ewtn->tv, p);
        SCReturnInt(TM_ECODE_FAILED);
    }

    SCReturnInt(TM_ECODE_OK);
}
Exemple #11
0
/**
 * \brief Recieves packets from an interface via libpfring.
 *
 *  This function recieves packets from an interface and passes
 *  the packet on to the pfring callback function.
 *
 * \param tv pointer to ThreadVars
 * \param data pointer that gets cast into PfringThreadVars for ptv
 * \param slot slot containing task information
 * \retval TM_ECODE_OK on success
 * \retval TM_ECODE_FAILED on failure
 */
TmEcode ReceivePfringLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    uint16_t packet_q_len = 0;
    PfringThreadVars *ptv = (PfringThreadVars *)data;
    Packet *p = NULL;
    struct pfring_pkthdr hdr;
    TmSlot *s = (TmSlot *)slot;
    time_t last_dump = 0;
    struct timeval current_time;

    ptv->slot = s->slot_next;

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

        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        do {
            packet_q_len = PacketPoolSize();
            if (unlikely(packet_q_len == 0)) {
                PacketPoolWait();
            }
        } while (packet_q_len == 0);

        p = PacketGetFromQueueOrAlloc();
        if (p == NULL) {
            SCReturnInt(TM_ECODE_FAILED);
        }
        PKT_SET_SRC(p, PKT_SRC_WIRE);

        /* Some flavours of PF_RING may fail to set timestamp - see PF-RING-enabled libpcap code*/
        hdr.ts.tv_sec = hdr.ts.tv_usec = 0;

        /* Depending on what compile time options are used for pfring we either return 0 or -1 on error and always 1 for success */
#ifdef HAVE_PFRING_RECV_UCHAR
        u_char *pkt_buffer = GET_PKT_DIRECT_DATA(p);
        u_int buffer_size = GET_PKT_DIRECT_MAX_SIZE(p);
        int r = pfring_recv(ptv->pd, &pkt_buffer,
                buffer_size,
                &hdr,
                LIBPFRING_WAIT_FOR_INCOMING);

        /* Check for Zero-copy if buffer size is zero */
        if (buffer_size == 0) {
            PacketSetData(p, pkt_buffer, hdr.caplen);
        }
#else
        int r = pfring_recv(ptv->pd, (char *)GET_PKT_DIRECT_DATA(p),
                (u_int)GET_PKT_DIRECT_MAX_SIZE(p),
                &hdr,
                LIBPFRING_WAIT_FOR_INCOMING);
#endif /* HAVE_PFRING_RECV_UCHAR */

        if (r == 1) {
            //printf("RecievePfring src %" PRIu32 " sport %" PRIu32 " dst %" PRIu32 " dstport %" PRIu32 "\n",
            //        hdr.parsed_pkt.ipv4_src,hdr.parsed_pkt.l4_src_port, hdr.parsed_pkt.ipv4_dst,hdr.parsed_pkt.l4_dst_port);

            PfringProcessPacket(ptv, &hdr, p);

            if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
                TmqhOutputPacketpool(ptv->tv, p);
                SCReturnInt(TM_ECODE_FAILED);
            }

            /* Trigger one dump of stats every second */
            TimeGet(&current_time);
            if (current_time.tv_sec != last_dump) {
                PfringDumpCounters(ptv);
                last_dump = current_time.tv_sec;
            }
        } else {
            SCLogError(SC_ERR_PF_RING_RECV,"pfring_recv error  %" PRId32 "", r);
            TmqhOutputPacketpool(ptv->tv, p);
            SCReturnInt(TM_ECODE_FAILED);
        }
        SCPerfSyncCountersIfSignalled(tv);
    }

    return TM_ECODE_OK;
}
Exemple #12
0
/**
 * \brief Recieves packets from an interface via libpfring.
 *
 *  This function recieves packets from an interface and passes
 *  the packet on to the pfring callback function.
 *
 * \param tv pointer to ThreadVars
 * \param data pointer that gets cast into PfringThreadVars for ptv
 * \param slot slot containing task information
 * \retval TM_ECODE_OK on success
 * \retval TM_ECODE_FAILED on failure
 */
TmEcode ReceivePfringLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    PfringThreadVars *ptv = (PfringThreadVars *)data;
    Packet *p = NULL;
    struct pfring_pkthdr hdr;
    TmSlot *s = (TmSlot *)slot;
    time_t last_dump = 0;
    u_int buffer_size;
    u_char *pkt_buffer;

    ptv->slot = s->slot_next;

    /* we have to enable the ring here as we need to do it after all
     * the threads have called pfring_set_cluster(). */
    int rc = pfring_enable_ring(ptv->pd);
    if (rc != 0) {
        SCLogError(SC_ERR_PF_RING_OPEN, "pfring_enable_ring failed returned %d ", rc);
        SCReturnInt(TM_ECODE_FAILED);
    }

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

        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        PacketPoolWait();

        p = PacketGetFromQueueOrAlloc();
        if (p == NULL) {
            SCReturnInt(TM_ECODE_FAILED);
        }
        PKT_SET_SRC(p, PKT_SRC_WIRE);

        /* Some flavours of PF_RING may fail to set timestamp - see PF-RING-enabled libpcap code*/
        hdr.ts.tv_sec = hdr.ts.tv_usec = 0;

        /* Check for Zero-copy mode */
        if (ptv->flags & PFRING_FLAGS_ZERO_COPY) {
            buffer_size = 0;
            pkt_buffer = NULL;
        } else {
            buffer_size = GET_PKT_DIRECT_MAX_SIZE(p);
            pkt_buffer = GET_PKT_DIRECT_DATA(p);
        }

        int r = pfring_recv(ptv->pd, &pkt_buffer,
                buffer_size,
                &hdr,
                LIBPFRING_WAIT_FOR_INCOMING);
        if (likely(r == 1)) {
            /* profiling started before blocking pfring_recv call, so
             * reset it here */
            PACKET_PROFILING_RESTART(p);

            /* Check for Zero-copy mode */
            if (ptv->flags & PFRING_FLAGS_ZERO_COPY) {
                PacketSetData(p, pkt_buffer, hdr.caplen);
            }

            //printf("RecievePfring src %" PRIu32 " sport %" PRIu32 " dst %" PRIu32 " dstport %" PRIu32 "\n",
            //        hdr.parsed_pkt.ipv4_src,hdr.parsed_pkt.l4_src_port, hdr.parsed_pkt.ipv4_dst,hdr.parsed_pkt.l4_dst_port);

            PfringProcessPacket(ptv, &hdr, p);

            if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
                TmqhOutputPacketpool(ptv->tv, p);
                SCReturnInt(TM_ECODE_FAILED);
            }

            /* Trigger one dump of stats every second */
            if (p->ts.tv_sec != last_dump) {
                PfringDumpCounters(ptv);
                last_dump = p->ts.tv_sec;
            }
        } else if (unlikely(r == 0)) {
            if (suricata_ctl_flags & (SURICATA_STOP | SURICATA_KILL)) {
                SCReturnInt(TM_ECODE_OK);
            }

            /* pfring didn't use the packet yet */
            TmThreadsCaptureInjectPacket(tv, ptv->slot, p);

        } else {
            SCLogError(SC_ERR_PF_RING_RECV,"pfring_recv error  %" PRId32 "", r);
            TmqhOutputPacketpool(ptv->tv, p);
            SCReturnInt(TM_ECODE_FAILED);
        }
        StatsSyncCountersIfSignalled(tv);
    }

    return TM_ECODE_OK;
}
Exemple #13
0
TmEcode ReceiveIPFWLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    IPFWThreadVars *ptv = (IPFWThreadVars *)data;
    IPFWQueueVars *nq = NULL;
    uint8_t pkt[IP_MAXPACKET];
    int pktlen=0;
    struct pollfd IPFWpoll;
    struct timeval IPFWts;
    Packet *p = NULL;
    uint16_t packet_q_len = 0;

    nq = IPFWGetQueue(ptv->ipfw_index);
    if (nq == NULL) {
        SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Can't get thread variable");
        SCReturnInt(TM_ECODE_FAILED);
    }

    SCLogInfo("Thread '%s' will run on port %d (item %d)",
              tv->name, nq->port_num, ptv->ipfw_index);
    while (1) {
        if (suricata_ctl_flags & (SURICATA_STOP || SURICATA_KILL)) {
            SCReturnInt(TM_ECODE_OK);
        }

        IPFWpoll.fd = nq->fd;
        IPFWpoll.events = POLLRDNORM;
        /* Poll the socket for status */
        if ( (poll(&IPFWpoll, 1, IPFW_SOCKET_POLL_MSEC)) > 0) {
            if (!(IPFWpoll.revents & (POLLRDNORM | POLLERR)))
                continue;
        }

        if ((pktlen = recvfrom(nq->fd, pkt, sizeof(pkt), 0,
                               (struct sockaddr *)&nq->ipfw_sin,
                               &nq->ipfw_sinlen)) == -1) {
            /* We received an error on socket read */
            if (errno == EINTR || errno == EWOULDBLOCK) {
                /* Nothing for us to process */
                continue;
            } else {
                SCLogWarning(SC_WARN_IPFW_RECV,
                             "Read from IPFW divert socket failed: %s",
                             strerror(errno));
                SCReturnInt(TM_ECODE_FAILED);
            }
        }
        /* We have a packet to process */
        memset (&IPFWts, 0, sizeof(struct timeval));
        gettimeofday(&IPFWts, NULL);

        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        do {
            packet_q_len = PacketPoolSize();
            if (unlikely(packet_q_len == 0)) {
                PacketPoolWait();
            }
        } while (packet_q_len == 0);

        p = PacketGetFromQueueOrAlloc();
        if (p == NULL) {
            SCReturnInt(TM_ECODE_FAILED);
        }
        PKT_SET_SRC(p, PKT_SRC_WIRE);

        SCLogDebug("Received Packet Len: %d", pktlen);

        p->ts.tv_sec = IPFWts.tv_sec;
        p->ts.tv_usec = IPFWts.tv_usec;

        ptv->pkts++;
        ptv->bytes += pktlen;

        p->datalink = ptv->datalink;

        p->ipfw_v.ipfw_index = ptv->ipfw_index;

        PacketCopyData(p, pkt, pktlen);
        SCLogDebug("Packet info: pkt_len: %" PRIu32 " (pkt %02x, pkt_data %02x)",
                   GET_PKT_LEN(p), *pkt, GET_PKT_DATA(p));

        if (TmThreadsSlotProcessPkt(tv, ((TmSlot *) slot)->slot_next, p)
                != TM_ECODE_OK) {
            TmqhOutputPacketpool(tv, p);
            SCReturnInt(TM_ECODE_FAILED);
        }

        SCPerfSyncCountersIfSignalled(tv, 0);
    }

    SCReturnInt(TM_ECODE_OK);
}
Exemple #14
0
/**
 *  \brief Main Napatech reading Loop function
 */
TmEcode NapatechStreamLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    int32_t status;
    char errbuf[100];
    uint16_t packet_q_len = 0;
    uint64_t pkt_ts;
    NtNetBuf_t packet_buffer;
    NapatechThreadVars *ntv = (NapatechThreadVars *)data;
    NtNetRx_t stat_cmd;

    SCLogInfo("Opening NAPATECH Stream: %lu for processing", ntv->stream_id);

    if ((status = NT_NetRxOpen(&(ntv->rx_stream), "SuricataStream", NT_NET_INTERFACE_PACKET, ntv->stream_id, ntv->hba)) != NT_SUCCESS) {
        NT_ExplainError(status, errbuf, sizeof(errbuf));
        SCLogError(SC_ERR_NAPATECH_OPEN_FAILED, "Failed to open NAPATECH Stream: %lu - %s", ntv->stream_id, errbuf);
        SCFree(ntv);
        SCReturnInt(TM_ECODE_FAILED);
    }

    stat_cmd.cmd = NT_NETRX_READ_CMD_STREAM_DROP;

    SCLogInfo("Napatech Packet Stream Loop Started for Stream ID: %lu", ntv->stream_id);

    TmSlot *s = (TmSlot *)slot;
    ntv->slot = s->slot_next;

    while (!(suricata_ctl_flags & (SURICATA_STOP | SURICATA_KILL))) {
        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        do {
            packet_q_len = PacketPoolSize();
            if (unlikely(packet_q_len == 0)) {
                PacketPoolWait();
            }
        } while (packet_q_len == 0);

        /*
         * Napatech returns packets 1 at a time
         */
        status = NT_NetRxGet(ntv->rx_stream, &packet_buffer, 1000);
        if (unlikely(status == NT_STATUS_TIMEOUT || status == NT_STATUS_TRYAGAIN)) {
            /*
             * no frames currently available
             */
            continue;
        } else if (unlikely(status != NT_SUCCESS)) {
            SCLogError(SC_ERR_NAPATECH_STREAM_NEXT_FAILED,
                       "Failed to read from Napatech Stream: %lu",
                       ntv->stream_id);
            SCReturnInt(TM_ECODE_FAILED);
        }

        Packet *p = PacketGetFromQueueOrAlloc();
        if (unlikely(p == NULL)) {
            NT_NetRxRelease(ntv->rx_stream, packet_buffer);
            SCReturnInt(TM_ECODE_FAILED);
        }

        pkt_ts = NT_NET_GET_PKT_TIMESTAMP(packet_buffer);

        /*
         * Handle the different timestamp forms that the napatech cards could use
         *   - NT_TIMESTAMP_TYPE_NATIVE is not supported due to having an base of 0 as opposed to NATIVE_UNIX which has a base of 1/1/1970
         */
        switch(NT_NET_GET_PKT_TIMESTAMP_TYPE(packet_buffer)) {
            case NT_TIMESTAMP_TYPE_NATIVE_UNIX:
                p->ts.tv_sec = pkt_ts / 100000000;
                p->ts.tv_usec = ((pkt_ts % 100000000) / 100) + (pkt_ts % 100) > 50 ? 1 : 0;
                break;
            case NT_TIMESTAMP_TYPE_PCAP:
                p->ts.tv_sec = pkt_ts >> 32;
                p->ts.tv_usec = pkt_ts & 0xFFFFFFFF;
                break;
            case NT_TIMESTAMP_TYPE_PCAP_NANOTIME:
                p->ts.tv_sec = pkt_ts >> 32;
                p->ts.tv_usec = ((pkt_ts & 0xFFFFFFFF) / 1000) + (pkt_ts % 1000) > 500 ? 1 : 0;
                break;
            case NT_TIMESTAMP_TYPE_NATIVE_NDIS:
                /* number of seconds between 1/1/1601 and 1/1/1970 */
                p->ts.tv_sec = (pkt_ts / 100000000) - 11644473600;
                p->ts.tv_usec = ((pkt_ts % 100000000) / 100) + (pkt_ts % 100) > 50 ? 1 : 0;
                break;
            default:
                SCLogError(SC_ERR_NAPATECH_TIMESTAMP_TYPE_NOT_SUPPORTED,
                           "Packet from Napatech Stream: %lu does not have a supported timestamp format",
                           ntv->stream_id);
                NT_NetRxRelease(ntv->rx_stream, packet_buffer);
                SCReturnInt(TM_ECODE_FAILED);
        }

        SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
        p->datalink = LINKTYPE_ETHERNET;

        ntv->pkts++;
        ntv->bytes += NT_NET_GET_PKT_WIRE_LENGTH(packet_buffer);

        // Update drop counter
        if (unlikely((status = NT_NetRxRead(ntv->rx_stream, &stat_cmd)) != NT_SUCCESS))
        {
            NT_ExplainError(status, errbuf, sizeof(errbuf));
            SCLogWarning(SC_ERR_NAPATECH_STAT_DROPS_FAILED, "Couldn't retrieve drop statistics from the RX stream: %lu - %s", ntv->stream_id, errbuf);
        }
        else
        {
            ntv->drops += stat_cmd.u.streamDrop.pktsDropped;
        }

        if (unlikely(PacketCopyData(p, (uint8_t *)NT_NET_GET_PKT_L2_PTR(packet_buffer), NT_NET_GET_PKT_WIRE_LENGTH(packet_buffer)))) {
            TmqhOutputPacketpool(ntv->tv, p);
            NT_NetRxRelease(ntv->rx_stream, packet_buffer);
            SCReturnInt(TM_ECODE_FAILED);
        }

        if (unlikely(TmThreadsSlotProcessPkt(ntv->tv, ntv->slot, p) != TM_ECODE_OK)) {
            TmqhOutputPacketpool(ntv->tv, p);
            NT_NetRxRelease(ntv->rx_stream, packet_buffer);
            SCReturnInt(TM_ECODE_FAILED);
        }

        NT_NetRxRelease(ntv->rx_stream, packet_buffer);
        SCPerfSyncCountersIfSignalled(tv);
    }

    SCReturnInt(TM_ECODE_OK);
}
Exemple #15
0
TmEcode ProcessErfDagRecords(ErfDagThreadVars *ewtn,
                             Packet *p,
                             uint8_t* top,
                             PacketQueue *postpq,
                             uint32_t *pkts_read)
{
    SCEnter();

    int     err = 0;
    dag_record_t* dr = NULL;
    char    *prec = NULL;
    int     rlen;

    *pkts_read = 0;

    while(((top-(ewtn->btm))>=dag_record_size) &&
          ((*pkts_read)<(ewtn->dag_max_read_packets)))
    {
        prec = (char*)ewtn->btm;
        dr = (dag_record_t*)prec;

        rlen = ntohs(dr->rlen);

        if (rlen == 20) {
            rlen = 28;
            SCLogWarning(SC_WARN_ERF_DAG_REC_LEN_CHANGED,
                "Warning, adjusted the length of ERF from 20 to 28 on stream: %d, DAG: %s",
                ewtn->dagstream, ewtn->dagname);
        }

        /* If we don't have enough data to finsih processing this ERF record
         * return and maybe next time we will.
         */
        if ((top-(ewtn->btm)) < rlen)
            SCReturnInt(TM_ECODE_OK);

        p = p ? p : PacketGetFromQueueOrAlloc();

        if (p == NULL) {
            SCLogError(SC_ERR_MEM_ALLOC,
                       "Failed to allocate a Packet on stream: %d, DAG: %s",
                       ewtn->dagstream, ewtn->dagname);
            SCReturnInt(TM_ECODE_FAILED);
        }

        err = ProcessErfDagRecord(ewtn, prec, p);

        if (err != TM_ECODE_OK)
            SCReturnInt(err);

        ewtn->btm += rlen;

        /* XXX/JNM: Hack to get around the fact that the first Packet from
         * Suricata is added explicitly by the Slot code and shouldn't go
         * onto the post queue -- else it is added twice to the next queue.
         */
        if (*pkts_read) {
            PacketEnqueue(postpq, p);
        }

        (*pkts_read)++;

        p = NULL;
    }

    SCReturnInt(TM_ECODE_OK);
}
Exemple #16
0
/**
 *  \brief Main Napatech reading Loop function
 */
TmEcode NapatechFeedLoop(ThreadVars *tv, void *data, void *slot)
{
    SCEnter();

    int32_t status;
    int32_t caplen;
    PCAP_HEADER *header;
    uint8_t *frame;
    uint16_t packet_q_len = 0;
    NapatechThreadVars *ntv = (NapatechThreadVars *)data;
    int r;
    TmSlot *s = (TmSlot *)slot;

    ntv->slot = s->slot_next;

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

        /* make sure we have at least one packet in the packet pool, to prevent
         * us from alloc'ing packets at line rate */
        do {
            packet_q_len = PacketPoolSize();
            if (unlikely(packet_q_len == 0)) {
                PacketPoolWait();
            }
        } while (packet_q_len == 0);

        /*
         * Napatech returns frames in segment chunks.  Function ntci_next_frame
         * returns 1 for a frame, 0 if the segment is empty, and -1 on error
         */
        status = napatech_next_frame (ntv->feed, &header, &frame);
        if (status == 0) {
            /*
             * no frames currently available
             */
            continue;
        } else if (status < 0) {
            SCLogError(SC_ERR_NAPATECH_FEED_NEXT_FAILED,
                       "Failed to read from Napatech feed %d:%d",
                       ntv->adapter_number, ntv->feed_number);
            SCReturnInt(TM_ECODE_FAILED);
        }
        // beware that storelen is aligned; therefore, it may be larger than "caplen"
        caplen = (header->wireLen < header->storeLen) ? header->wireLen : header->storeLen;
        Packet *p = PacketGetFromQueueOrAlloc();
        if (unlikely(p == NULL)) {
            SCReturnInt(TM_ECODE_FAILED);
        }

        p->ts.tv_sec = header->ts.tv_sec;
        p->ts.tv_usec = header->ts.tv_usec;
        SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
        p->datalink = LINKTYPE_ETHERNET;

        ntv->pkts++;
        ntv->bytes += caplen;

        if (unlikely(PacketCopyData(p, frame, caplen))) {
            TmqhOutputPacketpool(ntv->tv, p);
            SCReturnInt(TM_ECODE_FAILED);
        }

        if (TmThreadsSlotProcessPkt(ntv->tv, ntv->slot, p) != TM_ECODE_OK) {
            TmqhOutputPacketpool(ntv->tv, p);
            SCReturnInt(TM_ECODE_FAILED);
        }
    }

    SCReturnInt(TM_ECODE_OK);
}