From 04b0f177fcda947aaefd71cf071ec55e79b1ca9e Mon Sep 17 00:00:00 2001 From: William Metcalf Date: Wed, 23 Sep 2009 09:50:04 -0500 Subject: [PATCH] native PF_RING support with fixes --- configure.in | 16 + oisf.yaml | 12 + src/Makefile.am | 1 + src/eidps.c | 34 +- src/eidps.h | 3 + src/runmodes.c | 765 ++++++++++++++++++++++++++++++++++++++++++++ src/runmodes.h | 4 + src/source-pfring.c | 343 ++++++++++++++++++++ src/source-pfring.h | 14 + src/tm-modules.h | 2 + 10 files changed, 1192 insertions(+), 2 deletions(-) create mode 100644 src/source-pfring.c create mode 100644 src/source-pfring.h diff --git a/configure.in b/configure.in index e703c86e57..c01b08b143 100644 --- a/configure.in +++ b/configure.in @@ -277,6 +277,13 @@ AC_INIT(configure.in) # libpfring (currently only supported for libpcap enabled pfring) # Error on the side of caution. If libpfring enabled pcap is being used and we don't link against -lpfring compilation will fail. + AC_ARG_ENABLE(pfring, + [ --enable-pfring Enable Native PF_RING support], + [ enable_pfring=yes + ]) + if test "$enable_pfring" = "yes"; then + CFLAGS="$CFLAGS -DHAVE_PFRING" + fi AC_ARG_WITH(libpfring_includes, [ --with-libpfring-includes=DIR libpfring include directory], [with_libpfring_includes="$withval"],[with_libpfring_includes=no]) @@ -294,6 +301,15 @@ AC_INIT(configure.in) LIBPFRING="" AC_CHECK_LIB(pfring, pfring_open,, LIBPFRING="no") + if test "$LIBPFRING" = "no"; then + if test "enable_pfring" = "yes"; then + echo + echo " ERROR! --enable-pfring was passed but the library was not found, go get it" + echo " from http://www.ntop.org/PF_RING.html" + echo + exit 1 + fi + fi # libpcap AC_ARG_WITH(libpcap_includes, diff --git a/oisf.yaml b/oisf.yaml index 761bcc7dda..a8fd13eb55 100644 --- a/oisf.yaml +++ b/oisf.yaml @@ -45,3 +45,15 @@ logging: - interface: syslog facility: local5 format: "%l" + +# PF_RING configuration. for use with native PF_RING support +# for more info see http://www.ntop.org/PF_RING.html +pfring: + + # Default interface we will listen on. + interface: eth0 + + # Default clusterid. PR_RING will load balance packets based on flow. + # All threads/processes that will participate need to have the same + # clusterid. + clusterid: 99 diff --git a/src/Makefile.am b/src/Makefile.am index 4405f62fce..bd005cab36 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,6 +6,7 @@ threads.c threads.h \ source-nfq.c source-nfq.h \ source-pcap.c source-pcap.h \ source-pcap-file.c source-pcap-file.h \ +source-pfring.c source-pfring.h \ decode.c decode.h \ decode-ethernet.c decode-ethernet.h \ decode-sll.c decode-sll.h \ diff --git a/src/eidps.c b/src/eidps.c index a90bd1af81..c3a00e52d9 100644 --- a/src/eidps.c +++ b/src/eidps.c @@ -46,6 +46,8 @@ #include "source-pcap.h" #include "source-pcap-file.h" +#include "source-pfring.h" + #include "respond-reject.h" #include "flow.h" @@ -85,6 +87,7 @@ enum { MODE_UNKNOWN = 0, MODE_PCAP_DEV, MODE_PCAP_FILE, + MODE_PFRING, MODE_NFQ, MODE_UNITTEST }; @@ -238,6 +241,7 @@ int main(int argc, char **argv) int mode = MODE_UNKNOWN; char *pcap_file = NULL; char *pcap_dev = NULL; + char *pfring_dev = NULL; char *sig_file = NULL; int nfq_id = 0; char *conf_filename = NULL; @@ -253,14 +257,33 @@ int main(int argc, char **argv) struct option long_opts[] = { {"dump-config", 0, &dump_config, 1}, + {"pfring-int", required_argument, 0, 0}, + {"pfring-clusterid", required_argument, 0, 0}, {NULL, 0, NULL, 0} }; + + /* getopt_long stores the option index here. */ + int option_index = 0; + char short_opts[] = "c:hi:l:q:r:us:"; - while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, short_opts, long_opts, &option_index)) != -1) { switch (opt) { case 0: - /* Long opt handler. */ + if(strcmp((long_opts[option_index]).name , "pfring-int") == 0){ + mode = MODE_PFRING; + if (ConfSet("pfring.interface", optarg, 0) != 1) { + fprintf(stderr, "ERROR: Failed to set pfring interface.\n"); + exit(EXIT_FAILURE); + } + } + else if(strcmp((long_opts[option_index]).name , "pfring-clusterid") == 0){ + printf ("clusterid %s\n",optarg); + if (ConfSet("pfring.clusterid", optarg, 0) != 1) { + fprintf(stderr, "ERROR: Failed to set pfring clusterid.\n"); + exit(EXIT_FAILURE); + } + } break; case 'c': conf_filename = optarg; @@ -350,6 +373,8 @@ int main(int argc, char **argv) TmModuleDecodeNFQRegister(); TmModuleReceivePcapRegister(); TmModuleDecodePcapRegister(); + TmModuleReceivePfringRegister(); + TmModuleDecodePfringRegister(); TmModuleReceivePcapFileRegister(); TmModuleDecodePcapFileRegister(); TmModuleDetectRegister(); @@ -447,6 +472,11 @@ int main(int argc, char **argv) RunModeFilePcap(de_ctx, pcap_file); //RunModeFilePcap2(de_ctx, pcap_file); } + else if (mode == MODE_PFRING) { + //RunModeIdsPfring(de_ctx, pfring_dev); + RunModeIdsPfring2(de_ctx, pfring_dev); + //RunModeIdsPfring3(de_ctx, pfring_dev); + } else if (mode == MODE_NFQ) { RunModeIpsNFQ(de_ctx); } diff --git a/src/eidps.h b/src/eidps.h index 5a328447ca..611c42cf01 100644 --- a/src/eidps.h +++ b/src/eidps.h @@ -12,6 +12,9 @@ #include "eidps-common.h" #include "packet-queue.h" +/* the name of our binary */ +#define PROG_NAME "eidps" + /* max packets processed simultaniously */ #define MAX_PENDING 50 diff --git a/src/runmodes.c b/src/runmodes.c index a3a76d5ace..028901d6a8 100644 --- a/src/runmodes.c +++ b/src/runmodes.c @@ -1267,3 +1267,768 @@ int RunModeFilePcap2(DetectEngineCtx *de_ctx, char *file) { return 0; } +int RunModeIdsPfring(DetectEngineCtx *de_ctx, char *iface) { + TimeModeSetLive(); + + /* create the threads */ + ThreadVars *tv_receivepfring = TmThreadCreatePacketHandler("ReceivePfring","packetpool","packetpool","pickup-queue1","simple","1slot"); + if (tv_receivepfring == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + TmModule *tm_module = TmModuleGetByName("ReceivePfring"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed for ReceivePfring\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_receivepfring,tm_module,(void *)iface); + + if (TmThreadSpawn(tv_receivepfring) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_receivepfring2 = TmThreadCreatePacketHandler("ReceivePfring2","packetpool","packetpool","pickup-queue2","simple","1slot"); + if (tv_receivepfring2 == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("ReceivePfring"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed for ReceivePfring\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_receivepfring2,tm_module,(void *)iface); + + if (TmThreadSpawn(tv_receivepfring2) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_decode1 = TmThreadCreatePacketHandler("Decode1","pickup-queue1","simple","decode-queue1","simple","1slot"); + if (tv_decode1 == NULL) { + printf("ERROR: TmThreadsCreate failed for Decode1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("DecodePfring"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName DecodePfring failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_decode1,tm_module,NULL); + + if (TmThreadSpawn(tv_decode1) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_decode2 = TmThreadCreatePacketHandler("Decode2","pickup-queue2","simple","decode-queue2","simple","1slot"); + if (tv_decode2 == NULL) { + printf("ERROR: TmThreadsCreate failed for Decode1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("DecodePfring"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName DecodePfring failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_decode2,tm_module,NULL); + + if (TmThreadSpawn(tv_decode2) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_stream1 = TmThreadCreatePacketHandler("Stream1","decode-queue1","simple","stream-queue1","simple","1slot"); + if (tv_stream1 == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_stream1,tm_module,NULL); + + if (TmThreadSpawn(tv_stream1) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_stream2 = TmThreadCreatePacketHandler("Stream2","decode-queue2","simple","stream-queue2","simple","1slot"); + if (tv_stream2 == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_stream2,tm_module,NULL); + + if (TmThreadSpawn(tv_stream2) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_detect1 = TmThreadCreatePacketHandler("Detect1","stream-queue1","simple","verdict-queue","simple","1slot"); + if (tv_detect1 == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("Detect"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName Detect failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_detect1,tm_module,(void *)de_ctx); + + if (TmThreadSpawn(tv_detect1) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_detect2 = TmThreadCreatePacketHandler("Detect2","stream-queue2","simple","verdict-queue","simple","1slot"); + if (tv_detect2 == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("Detect"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName Detect failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_detect2,tm_module,(void *)de_ctx); + + if (TmThreadSpawn(tv_detect2) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_rreject = TmThreadCreatePacketHandler("RespondReject","verdict-queue","simple","alert-queue1","simple","1slot"); + if (tv_rreject == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("RespondReject"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for RespondReject failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_rreject,tm_module,NULL); + + if (TmThreadSpawn(tv_rreject) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_alert = TmThreadCreatePacketHandler("AlertFastlog&Httplog","alert-queue1","simple","alert-queue2","simple","varslot"); + if (tv_alert == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("AlertFastlog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertFastlog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv_alert, tm_module, NULL); + + tm_module = TmModuleGetByName("LogHttplog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv_alert, tm_module, NULL); + + if (TmThreadSpawn(tv_alert) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_unified = TmThreadCreatePacketHandler("AlertUnifiedLog","alert-queue2","simple","alert-queue3","simple","varslot"); + if (tv_unified == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + + tm_module = TmModuleGetByName("AlertUnifiedLog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedLog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv_unified, tm_module, NULL); + + tm_module = TmModuleGetByName("AlertUnifiedAlert"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedAlert failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv_unified, tm_module, NULL); + + if (TmThreadSpawn(tv_unified) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_debugalert = TmThreadCreatePacketHandler("AlertDebuglog","alert-queue3","simple","packetpool","packetpool","1slot"); + if (tv_debugalert == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("AlertDebuglog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_debugalert,tm_module,NULL); + + if (TmThreadSpawn(tv_debugalert) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + return 0; +} + +/** \brief Live pfring mode with 4 stream tracking and reassembly threads, testing the flow queuehandler */ +int RunModeIdsPfring2(DetectEngineCtx *de_ctx, char *iface) { + TimeModeSetLive(); + + /* create the threads */ + ThreadVars *tv_receivepfring = TmThreadCreatePacketHandler("ReceivePfring","packetpool","packetpool","pickup-queue","simple","1slot"); + if (tv_receivepfring == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + TmModule *tm_module = TmModuleGetByName("ReceivePfring"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed for ReceivePfring\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_receivepfring,tm_module,(void *)iface); + + if (TmThreadSpawn(tv_receivepfring) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_decode1 = TmThreadCreatePacketHandler("Decode1","pickup-queue","simple","decode-queue1,decode-queue2,decode-queue3,decode-queue4","flow","1slot"); + if (tv_decode1 == NULL) { + printf("ERROR: TmThreadsCreate failed for Decode1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("DecodePfring"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName DecodePfring failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_decode1,tm_module,NULL); + + if (TmThreadSpawn(tv_decode1) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_stream1 = TmThreadCreatePacketHandler("Stream1","decode-queue1","simple","stream-queue1","simple","1slot"); + if (tv_stream1 == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_stream1,tm_module,NULL); + + if (TmThreadSpawn(tv_stream1) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_stream2 = TmThreadCreatePacketHandler("Stream2","decode-queue2","simple","stream-queue1","simple","1slot"); + if (tv_stream2 == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream2\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_stream2,tm_module,NULL); + + if (TmThreadSpawn(tv_stream2) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_stream3 = TmThreadCreatePacketHandler("Stream3","decode-queue3","simple","stream-queue2","simple","1slot"); + if (tv_stream3 == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_stream3,tm_module,NULL); + + if (TmThreadSpawn(tv_stream3) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_stream4 = TmThreadCreatePacketHandler("Stream4","decode-queue4","simple","stream-queue2","simple","1slot"); + if (tv_stream4 == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_stream4,tm_module,NULL); + + if (TmThreadSpawn(tv_stream4) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_detect1 = TmThreadCreatePacketHandler("Detect1","stream-queue1","simple","verdict-queue","simple","1slot"); + if (tv_detect1 == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("Detect"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName Detect failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_detect1,tm_module,(void *)de_ctx); + + if (TmThreadSpawn(tv_detect1) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_detect2 = TmThreadCreatePacketHandler("Detect2","stream-queue2","simple","verdict-queue","simple","1slot"); + if (tv_detect2 == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("Detect"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName Detect failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_detect2,tm_module,(void *)de_ctx); + + if (TmThreadSpawn(tv_detect2) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_rreject = TmThreadCreatePacketHandler("RespondReject","verdict-queue","simple","alert-queue1","simple","1slot"); + if (tv_rreject == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("RespondReject"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for RespondReject failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_rreject,tm_module,NULL); + + if (TmThreadSpawn(tv_rreject) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_alert = TmThreadCreatePacketHandler("AlertFastlog&Httplog","alert-queue1","simple","alert-queue2","simple","varslot"); + if (tv_alert == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("AlertFastlog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertFastlog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv_alert, tm_module, NULL); + + tm_module = TmModuleGetByName("LogHttplog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv_alert, tm_module, NULL); + + if (TmThreadSpawn(tv_alert) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_unified = TmThreadCreatePacketHandler("AlertUnifiedLog","alert-queue2","simple","alert-queue3","simple","varslot"); + if (tv_unified == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + + tm_module = TmModuleGetByName("AlertUnifiedLog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedLog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv_unified,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedAlert"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedAlert failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv_unified,tm_module,NULL); + + if (TmThreadSpawn(tv_unified) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_debugalert = TmThreadCreatePacketHandler("AlertDebuglog","alert-queue3","simple","packetpool","packetpool","1slot"); + if (tv_debugalert == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("AlertDebuglog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_debugalert,tm_module,NULL); + + if (TmThreadSpawn(tv_debugalert) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + return 0; +} +/** \brief Live pfring mode with 4 stream tracking and reassembly threads, testing the flow queuehandler */ +int RunModeIdsPfring3(DetectEngineCtx *de_ctx, char *iface) { + TimeModeSetLive(); + + /* create the threads */ + ThreadVars *tv_receivepfring = TmThreadCreatePacketHandler("ReceivePfring","packetpool","packetpool","pickup-queue","simple","1slot"); + if (tv_receivepfring == NULL) { + printf("ERROR: TmThreadsCreate failed\n"); + exit(EXIT_FAILURE); + } + TmModule *tm_module = TmModuleGetByName("ReceivePfring"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed for ReceivePfring\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_receivepfring,tm_module,(void *)iface); + + if (TmThreadSpawn(tv_receivepfring) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv_decode1 = TmThreadCreatePacketHandler("Decode1","pickup-queue","simple","decode-queue1,decode-queue2,decode-queue3,decode-queue4","flow","1slot"); + if (tv_decode1 == NULL) { + printf("ERROR: TmThreadsCreate failed for Decode1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("DecodePfring"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName DecodePfring failed\n"); + exit(EXIT_FAILURE); + } + Tm1SlotSetFunc(tv_decode1,tm_module,NULL); + + if (TmThreadSpawn(tv_decode1) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + ThreadVars *tv; + tv = TmThreadCreatePacketHandler("Stream1","decode-queue1","simple","packetpool","packetpool","varslot"); + if (tv == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("Detect"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,(void *)de_ctx); + + tm_module = TmModuleGetByName("RespondReject"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for RespondReject failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertFastlog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertFastlog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("LogHttplog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedLog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedLog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedAlert"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedAlert failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertDebuglog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + TmThreadSetCPUAffinity(tv, 0); + + if (TmThreadSpawn(tv) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + tv = TmThreadCreatePacketHandler("Stream2","decode-queue2","simple","packetpool","packetpool","varslot"); + if (tv == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("Detect"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,(void *)de_ctx); + + tm_module = TmModuleGetByName("RespondReject"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for RespondReject failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertFastlog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertFastlog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("LogHttplog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedLog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedLog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedAlert"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedAlert failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertDebuglog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + TmThreadSetCPUAffinity(tv, 0); + + if (TmThreadSpawn(tv) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + tv = TmThreadCreatePacketHandler("Stream3","decode-queue3","simple","packetpool","packetpool","varslot"); + if (tv == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("Detect"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,(void *)de_ctx); + + tm_module = TmModuleGetByName("RespondReject"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for RespondReject failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertFastlog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertFastlog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("LogHttplog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedLog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedLog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedAlert"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedAlert failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertDebuglog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + TmThreadSetCPUAffinity(tv, 1); + + if (TmThreadSpawn(tv) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + + tv = TmThreadCreatePacketHandler("Stream4","decode-queue4","simple","packetpool","packetpool","varslot"); + if (tv == NULL) { + printf("ERROR: TmThreadsCreate failed for Stream1\n"); + exit(EXIT_FAILURE); + } + tm_module = TmModuleGetByName("StreamTcp"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("Detect"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName StreamTcp failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,(void *)de_ctx); + + tm_module = TmModuleGetByName("RespondReject"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for RespondReject failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertFastlog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertFastlog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("LogHttplog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedLog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedLog failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertUnifiedAlert"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName for AlertUnifiedAlert failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + tm_module = TmModuleGetByName("AlertDebuglog"); + if (tm_module == NULL) { + printf("ERROR: TmModuleGetByName failed\n"); + exit(EXIT_FAILURE); + } + TmVarSlotSetFuncAppend(tv,tm_module,NULL); + + TmThreadSetCPUAffinity(tv, 1); + + if (TmThreadSpawn(tv) != 0) { + printf("ERROR: TmThreadSpawn failed\n"); + exit(EXIT_FAILURE); + } + return 0; +} diff --git a/src/runmodes.h b/src/runmodes.h index 02fb1f272c..e538c0839c 100644 --- a/src/runmodes.h +++ b/src/runmodes.h @@ -10,5 +10,9 @@ int RunModeIpsNFQ(DetectEngineCtx *); int RunModeFilePcap(DetectEngineCtx *, char *); int RunModeFilePcap2(DetectEngineCtx *, char *); +int RunModeIdsPfring(DetectEngineCtx *, char *); +int RunModeIdsPfring2(DetectEngineCtx *, char *); +int RunModeIdsPfring3(DetectEngineCtx *, char *); + #endif /* __RUNMODES_H__ */ diff --git a/src/source-pfring.c b/src/source-pfring.c new file mode 100644 index 0000000000..2a02c518c7 --- /dev/null +++ b/src/source-pfring.c @@ -0,0 +1,343 @@ +/* Copyright (c) 2009 Victor Julien */ + +#ifdef HAVE_PFRING +#include +#endif /* HAVE_PFRING */ + +#include "eidps-common.h" +#include "eidps.h" +#include "decode.h" +#include "packet-queue.h" +#include "threads.h" +#include "threadvars.h" +#include "tm-queuehandlers.h" +#include "tm-modules.h" +#include "tm-threads.h" +#include "source-pfring.h" + + +int ReceivePfring(ThreadVars *, Packet *, void *, PacketQueue *); +int ReceivePfringThreadInit(ThreadVars *, void *, void **); +void ReceivePfringThreadExitStats(ThreadVars *, void *); +int ReceivePfringThreadDeinit(ThreadVars *, void *); + +int DecodePfringThreadInit(ThreadVars *, void *, void **); +int DecodePfring(ThreadVars *, Packet *, void *, PacketQueue *); + +#ifndef HAVE_PFRING + +/*Handle cases where we don't have PF_RING support built-in*/ +int NoPfringSupportExit(ThreadVars *, void *, void **); + +void TmModuleReceivePfringRegister (void) { + tmm_modules[TMM_RECEIVEPFRING].name = "ReceivePfring"; + tmm_modules[TMM_RECEIVEPFRING].ThreadInit = NoPfringSupportExit; + tmm_modules[TMM_RECEIVEPFRING].Func = NULL; + tmm_modules[TMM_RECEIVEPFRING].ThreadExitPrintStats = NULL; + tmm_modules[TMM_RECEIVEPFRING].ThreadDeinit = NULL; + tmm_modules[TMM_RECEIVEPFRING].RegisterTests = NULL; +} + +void TmModuleDecodePfringRegister (void) { + tmm_modules[TMM_DECODEPFRING].name = "DecodePfring"; + tmm_modules[TMM_DECODEPFRING].ThreadInit = NoPfringSupportExit; + tmm_modules[TMM_DECODEPFRING].Func = NULL; + tmm_modules[TMM_DECODEPFRING].ThreadExitPrintStats = NULL; + tmm_modules[TMM_DECODEPFRING].ThreadDeinit = NULL; + tmm_modules[TMM_DECODEPFRING].RegisterTests = NULL; +} + +/** + * \brief this funciton prints an error message and exits. + * \param tv pointer to ThreadVars + * \param initdata pointer to the interface passed from the user + * \param data pointer gets populated with PfringThreadVars + */ +int NoPfringSupportExit(ThreadVars *tv, void *initdata, void **data) +{ + printf("Error creating thread %s: you do not have support for pfring " + "enabled please recompile with --enable-pfring\n", tv->name); + exit(EXIT_FAILURE); +} + +#else /* implied we do have PF_RING support */ + +/** + * \brief Structure to hold thread specific variables. + */ +typedef struct PfringThreadVars_ +{ + /* thread specific handle */ + pfring *pd; + + uint8_t cluster_id; + char *interface; + + /* counters */ + uint32_t pkts; + uint64_t bytes; + //uint32_t errs; + + ThreadVars *tv; +} PfringThreadVars; + +/** + * \brief Registration Function for RecievePfring. + * \todo Unit tests are needed for this module. + */ +void TmModuleReceivePfringRegister (void) { + tmm_modules[TMM_RECEIVEPFRING].name = "ReceivePfring"; + tmm_modules[TMM_RECEIVEPFRING].ThreadInit = ReceivePfringThreadInit; + tmm_modules[TMM_RECEIVEPFRING].Func = ReceivePfring; + tmm_modules[TMM_RECEIVEPFRING].ThreadExitPrintStats = ReceivePfringThreadExitStats; + tmm_modules[TMM_RECEIVEPFRING].ThreadDeinit = NULL; + tmm_modules[TMM_RECEIVEPFRING].RegisterTests = NULL; +} + +/** + * \brief Registration Function for DecodePfring. + * \todo Unit tests are needed for this module. + */ +void TmModuleDecodePfringRegister (void) { + tmm_modules[TMM_DECODEPFRING].name = "DecodePfring"; + tmm_modules[TMM_DECODEPFRING].ThreadInit = DecodePfringThreadInit; + tmm_modules[TMM_DECODEPFRING].Func = DecodePfring; + tmm_modules[TMM_DECODEPFRING].ThreadExitPrintStats = NULL; + tmm_modules[TMM_DECODEPFRING].ThreadDeinit = NULL; + tmm_modules[TMM_DECODEPFRING].RegisterTests = NULL; +} + +/** + * \brief Pfring Packet Process function. + * + * This function fills in our packet structure from libpfring. + * From here the packets are picked up by the DecodePfring thread. + * + * \param user pointer to PfringThreadVars + * \param h pointer to pfring packet header + * \param pkt pointer to raw packet data + * \param p pointer to the current packet + */ +void PfringProcessPacket(void *user, struct pfring_pkthdr *h, u_char *pkt, Packet *p) { + + PfringThreadVars *ptv = (PfringThreadVars *)user; + //printf("PfringProcessPacket: user %p, h %p, pkt %p, p %p\n", user, h, pkt, p); + //TmqDebugList(); + //printf("PfringProcessPacket: pending %" PRIu32 "\n", pending); + + p->ts.tv_sec = h->ts.tv_sec; + p->ts.tv_usec = h->ts.tv_usec; + + ptv->pkts++; + ptv->bytes += h->caplen; + + /* PF_RING all packets are marked as a link type of ethernet so that is what we do here. */ + p->datalink = LINKTYPE_ETHERNET; + + p->pktlen = h->caplen; + memcpy(p->pkt, pkt, p->pktlen); + +} + +/** + * \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 pq pointer to the PacketQueue (not used here but part of the api) + * \retval 0 on success + * \retval -1 on failure + */ +int ReceivePfring(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { + PfringThreadVars *ptv = (PfringThreadVars *)data; + + struct pfring_pkthdr hdr; + u_char buffer[MAX_CAPLEN]; + int r; + + if (TmThreadsCheckFlag(tv, THV_KILL) || TmThreadsCheckFlag(tv, THV_PAUSE)) { + printf("ReceivePfring: interrupted.\n"); + return 0; + } + + /* Depending on what compile time options are used for pfring we either return 0 or -1 on error and always 1 for success */ + r = pfring_recv(ptv->pd, (char *)buffer , sizeof(buffer), &hdr, LIBPFRING_WAIT_FOR_INCOMING); + 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, buffer,p); + }else{ + printf("RecievePfring: pfring_recv error %" PRId32 "\n", r); + return -1; + } + + return 0; +} + +/** + * \brief Init function for RecievePfring. + * + * This is a setup function for recieving packets + * via libpfring. + * + * \param tv pointer to ThreadVars + * \param initdata pointer to the interface passed from the user + * \param data pointer gets populated with PfringThreadVars + * \todo add a config option for setting cluster id + * \todo Create a general pfring setup function. + * \retval 0 on success + * \retval -1 on error + */ +int ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { + int rc; + u_int32_t version; + char *tmpclusterid; + + PfringThreadVars *ptv = malloc(sizeof(PfringThreadVars)); + if (ptv == NULL) { + return -1; + } + memset(ptv, 0, sizeof(PfringThreadVars)); + + ptv->tv = tv; + if (ConfGet("pfring.clusterid", &tmpclusterid) != 1){ + printf("could not get pfring.clusterid\n"); + return -1; + }else{ + ptv->cluster_id = (uint8_t)atoi(tmpclusterid); + printf("ReceivePfringThreadInit: going to use clusterid %" PRId32 "\n", ptv->cluster_id); + } + + if (ConfGet("pfring.interface", &ptv->interface) != 1){ + printf("ReceivePfringThreadInit: Could not get pfring.interface\n"); + return -1; + }else{ + printf("ReceivePfringThreadInit: going to use interface %s\n",ptv->interface); + } + + ptv->pd = pfring_open(ptv->interface, LIBPFRING_PROMISC, LIBPFRING_SNAPLEN, LIBPFRING_REENTRANT); + if(ptv->pd == NULL) { + printf("pfring_open error\n"); + return -1; + } else { + pfring_set_application_name(ptv->pd, PROG_NAME); + pfring_version(ptv->pd, &version); + + printf("Using PF_RING v.%d.%d.%d\n", + (version & 0xFFFF0000) >> 16, + (version & 0x0000FF00) >> 8, + version & 0x000000FF); + } + + rc = pfring_set_cluster(ptv->pd, ptv->cluster_id); + if(rc != 0){ + printf("pfring_set_cluster returned %d\n", rc); + return -1; + } + + *data = (void *)ptv; + return 0; +} + +/** + * \brief This function prints stats to the screen at exit. + * \param tv pointer to ThreadVars + * \param data pointer that gets cast into PfringThreadVars for ptv + */ +void ReceivePfringThreadExitStats(ThreadVars *tv, void *data) { + PfringThreadVars *ptv = (PfringThreadVars *)data; + + printf(" - (%s) Packets %" PRIu32 ", bytes %" PRIu64 ".\n", tv->name, ptv->pkts, ptv->bytes); + return; +} + +/** + * \brief DeInit function closes pd at exit. + * \param tv pointer to ThreadVars + * \param data pointer that gets cast into PfringThreadVars for ptvi + * \retval 0 is always returned + */ +int ReceivePfringThreadDeinit(ThreadVars *tv, void *data) { + PfringThreadVars *ptv = (PfringThreadVars *)data; + pfring_remove_from_cluster(ptv->pd); + pfring_close(ptv->pd); + return 0; +} + +/** + * \brief This function passes off to link type decoders. + * + * DecodePfring reads packets from the PacketQueue. Inside of libpcap version of + * PF_RING all packets are marked as a link type of ethernet so that is what we do here. + * + * \param tv pointer to ThreadVars + * \param p pointer to the current packet + * \param data pointer that gets cast into PfringThreadVars for ptv + * \param pq pointer to the current PacketQueue + * \todo Verify that PF_RING only deals with ethernet traffic + * \retval 0 is always returned + */ +int DecodePfring(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) +{ + DecodeThreadVars *dtv = (DecodeThreadVars *)data; + + /* update counters */ + PerfCounterIncr(dtv->counter_pkts, tv->pca); + PerfCounterAddUI64(dtv->counter_bytes, tv->pca, p->pktlen); + PerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->pca, p->pktlen); + PerfCounterSetUI64(dtv->counter_max_pkt_size, tv->pca, p->pktlen); + + DecodeEthernet(tv, dtv, p,p->pkt, p->pktlen, pq); + + return 0; +} + +/** + * \brief This an Init function for DecodePfring + * + * \param tv pointer to ThreadVars + * \param initdata pointer to initilization data. + * \param data pointer that gets cast into PfringThreadVars for ptv + * \retval 0 is returned on success + * \retval -1 is returned on error + */ +int DecodePfringThreadInit(ThreadVars *tv, void *initdata, void **data) +{ + DecodeThreadVars *dtv = NULL; + + if ( (dtv = malloc(sizeof(DecodeThreadVars))) == NULL) { + printf("Error Allocating memory\n"); + return -1; + } + memset(dtv, 0, sizeof(DecodeThreadVars)); + + /* register counters */ + dtv->counter_pkts = PerfTVRegisterCounter("decoder.pkts", tv, TYPE_UINT64, "NULL"); + dtv->counter_bytes = PerfTVRegisterCounter("decoder.bytes", tv, TYPE_UINT64, "NULL"); + dtv->counter_ipv4 = PerfTVRegisterCounter("decoder.ipv4", tv, TYPE_UINT64, "NULL"); + dtv->counter_ipv6 = PerfTVRegisterCounter("decoder.ipv6", tv, TYPE_UINT64, "NULL"); + dtv->counter_eth = PerfTVRegisterCounter("decoder.ethernet", tv, TYPE_UINT64, "NULL"); + dtv->counter_sll = PerfTVRegisterCounter("decoder.sll", tv, TYPE_UINT64, "NULL"); + dtv->counter_tcp = PerfTVRegisterCounter("decoder.tcp", tv, TYPE_UINT64, "NULL"); + dtv->counter_udp = PerfTVRegisterCounter("decoder.udp", tv, TYPE_UINT64, "NULL"); + dtv->counter_icmpv4 = PerfTVRegisterCounter("decoder.icmpv4", tv, TYPE_UINT64, "NULL"); + dtv->counter_icmpv6 = PerfTVRegisterCounter("decoder.icmpv6", tv, TYPE_UINT64, "NULL"); + dtv->counter_ppp = PerfTVRegisterCounter("decoder.ppp", tv, TYPE_UINT64, "NULL"); + dtv->counter_pppoe = PerfTVRegisterCounter("decoder.pppoe", tv, TYPE_UINT64, "NULL"); + dtv->counter_gre = PerfTVRegisterCounter("decoder.gre", tv, TYPE_UINT64, "NULL"); + dtv->counter_avg_pkt_size = PerfTVRegisterAvgCounter("decoder.avg_pkt_size", tv, + TYPE_DOUBLE, "NULL"); + dtv->counter_max_pkt_size = PerfTVRegisterMaxCounter("decoder.max_pkt_size", tv, + TYPE_UINT64, "NULL"); + + tv->pca = PerfGetAllCountersArray(&tv->pctx); + PerfAddToClubbedTMTable(tv->name, &tv->pctx); + + *data = (void *)dtv; + return 0; +} +#endif /* HAVE_PFRING */ +/* eof */ diff --git a/src/source-pfring.h b/src/source-pfring.h new file mode 100644 index 0000000000..e56f042448 --- /dev/null +++ b/src/source-pfring.h @@ -0,0 +1,14 @@ +/* Copyright (c) 2009 Victor Julien */ + +#ifndef __SOURCE_PFRING_H__ +#define __SOURCE_PFRING_H__ + +void TmModuleReceivePfringRegister (void); +void TmModuleDecodePfringRegister (void); + +/* XXX replace with user configurable options */ +#define LIBPFRING_SNAPLEN 1518 +#define LIBPFRING_PROMISC 1 +#define LIBPFRING_REENTRANT 0 +#define LIBPFRING_WAIT_FOR_INCOMING 1 +#endif /* __SOURCE_PFRING_H__ */ diff --git a/src/tm-modules.h b/src/tm-modules.h index 7299333e43..2b78854a52 100644 --- a/src/tm-modules.h +++ b/src/tm-modules.h @@ -25,6 +25,8 @@ enum { TMM_RECEIVEPCAPFILE, TMM_DECODEPCAP, TMM_DECODEPCAPFILE, + TMM_RECEIVEPFRING, + TMM_DECODEPFRING, TMM_DETECT, TMM_ALERTFASTLOG, TMM_ALERTFASTLOG4,