pcap: add "single" runmode

This patch adds support for the "single" mode to the pcap live
mode.
remotes/origin/master-1.1.x
Eric Leblond 14 years ago committed by Victor Julien
parent e13181496c
commit effa295489

@ -48,6 +48,9 @@ const char *RunModeIdsGetDefaultMode(void)
void RunModeIdsPcapRegister(void)
{
RunModeRegisterNewRunMode(RUNMODE_PCAP_DEV, "single",
"Single threaded pcap live mode",
RunModeIdsPcapSingle);
RunModeRegisterNewRunMode(RUNMODE_PCAP_DEV, "auto",
"Multi threaded pcap live mode",
RunModeIdsPcapAuto);
@ -56,6 +59,82 @@ void RunModeIdsPcapRegister(void)
return;
}
/**
* \brief Single thread version of the Pcap live processing.
*/
int RunModeIdsPcapSingle(DetectEngineCtx *de_ctx)
{
int npcap = LiveGetDeviceCount();
char *pcap_dev = NULL;
char *pcap_devc = NULL;
if (npcap > 1) {
SCLogError(SC_ERR_RUNMODE,
"Can't use single runmode with multiple device");
exit(EXIT_FAILURE);
}
RunModeInitialize();
TimeModeSetLive();
if (ConfGet("pcap.single_pcap_dev", &pcap_dev) == 0) {
SCLogError(SC_ERR_RUNMODE, "Failed retrieving "
"pcap.single_pcap_dev from Conf");
exit(EXIT_FAILURE);
}
SCLogDebug("pcap_dev %s", pcap_dev);
pcap_devc = SCStrdup(pcap_dev);
/* create the threads */
ThreadVars *tv = TmThreadCreatePacketHandler("PcapLive",
"packetpool", "packetpool",
"packetpool", "packetpool",
"pktacqloop");
if (tv == NULL) {
printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE);
}
TmModule *tm_module = TmModuleGetByName("ReceivePcap");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName failed for ReceivePcap\n");
exit(EXIT_FAILURE);
}
TmSlotSetFuncAppend(tv, tm_module, pcap_devc);
tm_module = TmModuleGetByName("DecodePcap");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName DecodePcap failed\n");
exit(EXIT_FAILURE);
}
TmSlotSetFuncAppend(tv, tm_module, NULL);
tm_module = TmModuleGetByName("StreamTcp");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName StreamTcp failed\n");
exit(EXIT_FAILURE);
}
TmSlotSetFuncAppend(tv, tm_module, NULL);
tm_module = TmModuleGetByName("Detect");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName Detect failed\n");
exit(EXIT_FAILURE);
}
TmSlotSetFuncAppend(tv, tm_module, (void *)de_ctx);
SetupOutputs(tv);
if (TmThreadSpawn(tv) != TM_ECODE_OK) {
printf("ERROR: TmThreadSpawn failed\n");
exit(EXIT_FAILURE);
}
return 0;
}
/**
* \brief RunModeIdsPcapAuto set up the following thread packet handlers:
* - Receive thread (from iface pcap)

@ -24,6 +24,7 @@
#define __RUNMODE_PCAP_H__
int RunModeIdsPcapAuto(DetectEngineCtx *);
int RunModeIdsPcapSingle(DetectEngineCtx *);
void RunModeIdsPcapRegister(void);
const char *RunModeIdsGetDefaultMode(void);

@ -43,6 +43,7 @@
#include "util-error.h"
#include "util-privs.h"
#include "util-device.h"
#include "util-optimize.h"
#include "tmqh-packetpool.h"
extern uint8_t suricata_ctl_flags;
@ -87,6 +88,7 @@ typedef struct PcapThreadVars_
int pcap_buffer_size;
ThreadVars *tv;
TmSlot *slot;
Packet *in_p;
@ -98,6 +100,7 @@ TmEcode ReceivePcap(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *
TmEcode ReceivePcapThreadInit(ThreadVars *, void *, void **);
void ReceivePcapThreadExitStats(ThreadVars *, void *);
TmEcode ReceivePcapThreadDeinit(ThreadVars *, void *);
TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot);
TmEcode DecodePcapThreadInit(ThreadVars *, void *, void **);
TmEcode DecodePcap(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
@ -110,6 +113,7 @@ void TmModuleReceivePcapRegister (void) {
tmm_modules[TMM_RECEIVEPCAP].name = "ReceivePcap";
tmm_modules[TMM_RECEIVEPCAP].ThreadInit = ReceivePcapThreadInit;
tmm_modules[TMM_RECEIVEPCAP].Func = ReceivePcap;
tmm_modules[TMM_RECEIVEPCAP].PktAcqLoop = ReceivePcapLoop;
tmm_modules[TMM_RECEIVEPCAP].ThreadExitPrintStats = ReceivePcapThreadExitStats;
tmm_modules[TMM_RECEIVEPCAP].ThreadDeinit = NULL;
tmm_modules[TMM_RECEIVEPCAP].RegisterTests = NULL;
@ -245,6 +249,88 @@ static int PcapTryReopen(PcapThreadVars *ptv)
#endif
void PcapCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt) {
SCEnter();
PcapThreadVars *ptv = (PcapThreadVars *)user;
Packet *p = PacketGetFromQueueOrAlloc();
if (unlikely(p == NULL)) {
SCReturn;
}
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;
if (unlikely(PacketCopyData(p, pkt, h->caplen))) {
TmqhOutputPacketpool(ptv->tv, p);
SCReturn;
}
TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p);
SCReturn;
}
/**
* \brief Main PCAP reading Loop function
*/
TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot)
{
uint16_t packet_q_len = 0;
PcapThreadVars *ptv = (PcapThreadVars *)data;
TmSlot *s = (TmSlot *)slot;
ptv->slot = s->slot_next;
int r;
SCEnter();
while (1) {
if (suricata_ctl_flags & SURICATA_STOP ||
suricata_ctl_flags & SURICATA_KILL)
{
SCReturnInt(TM_ECODE_FAILED);
}
/* 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);
/* Right now we just support reading packets one at a time. */
r = pcap_dispatch(ptv->pcap_handle, (int)packet_q_len,
(pcap_handler)PcapCallbackLoop, (u_char *)ptv);
if (unlikely(r < 0)) {
int dbreak = 0;
SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s",
r, pcap_geterr(ptv->pcap_handle));
do {
usleep(PCAP_RECONNECT_TIMEOUT);
if (suricata_ctl_flags != 0) {
dbreak = 1;
break;
}
r = PcapTryReopen(ptv);
} while (r < 0);
if (dbreak) {
r = 0;
break;
}
}
}
SCReturnInt(TM_ECODE_OK);
}
/**
* \brief Recieves packets from an interface via libpcap.
*

Loading…
Cancel
Save