af-packet: finalize code

This patch handles the end of AF_PACKET socket support work. It
provides conditional compilation, autofp and single runmode.

It also adds a 'defrag' option which is used to activate defrag
support in kernel to avoid rx_hash computation in flow mode to fail
due to fragmentation.

This patch contains some fixes by Anoop Saldanha, and incorporate
change following review by Anoop Saldanha and Victor Julien.

AF_PACKET support is only build if the --enable-af-packet flag is
given to the configure command line. Detection of code availability
is also done: a check of the existence of AF_PACKET in standard
header is done. It seems this variable is Linux specific and it
should be enough to avoid compilation of AF_PACKET support on other
OSes.
Compilation does not depend on up-to-date headers on the system. If
none are present, wemake our own declaration of FANOUT variables. This
will permit compilation of the feature for system where only the kernel
has been updated to a version superior to 3.1.
remotes/origin/master-1.1.x
Eric Leblond 13 years ago committed by Victor Julien
parent 871b21892a
commit e80b30c082

@ -748,10 +748,21 @@ AC_CHECK_HEADER(pcap.h,,[AC_ERROR(pcap.h not found ...)])
AM_CONDITIONAL([BUILD_UNITTESTS], [test "x$enable_unittests" = "xyes"])
# AF_PACKET support
AC_CHECK_DECL([PACKET_FANOUT],
AC_DEFINE([HAVE_PACKET_FANOUT],[1],[Packet fanout support is available]),
[],
[[#include <linux/if_packet.h>]])
AC_ARG_ENABLE(af-packet,
AS_HELP_STRING([--enable-af-packet], [Enable AF_PACKET support]),
,[enable_af_packet=no])
AS_IF([test "x$enable_af_packet" = "xyes"], [
AC_CHECK_DECL([AF_PACKET],
AC_DEFINE([HAVE_AF_PACKET],[1],[AF_PACKET support is available]),
[enable_af_packet=no],
[[#include <sys/socket.h>]])
AC_CHECK_DECL([PACKET_FANOUT],
AC_DEFINE([HAVE_PACKET_FANOUT],[1],[Packet fanout support is available]),
[],
[[#include <linux/if_packet.h>]])
CFLAGS="${CFLAGS} -DUNITTESTS"
])
# enable native timeval for unified alert output
AC_ARG_ENABLE(unified-native-timeval,
@ -1001,6 +1012,7 @@ Suricata Configuration:
NFQueue support: ${enable_nfqueue}
IPFW support: ${enable_ipfw}
PF_RING support: ${enable_pfring}
AF_PACKET support: ${enable_af_packet}
Prelude support: ${enable_prelude}
Unit tests enabled: ${enable_unittests}
Debug output enabled: ${enable_debug}

@ -15,7 +15,18 @@
* 02110-1301, USA.
*/
/**
* \file
*
* \author Eric Leblond <eric@regit.org>
*
* AF_PACKET socket runmode
*
*/
#include "suricata-common.h"
#include "config.h"
#include "tm-threads.h"
#include "conf.h"
#include "runmodes.h"
@ -23,7 +34,6 @@
#include "log-httplog.h"
#include "output.h"
#include "cuda-packet-batcher.h"
#include "source-pfring.h"
#include "detect-engine-mpm.h"
#include "alert-fastlog.h"
@ -39,26 +49,49 @@
#include "util-affinity.h"
#include "util-device.h"
static const char *default_mode = NULL;
#include "source-af-packet.h"
static const char *default_mode_auto = NULL;
static const char *default_mode_autofp = NULL;
const char *RunModeAFPGetDefaultMode(void)
{
return default_mode;
#ifdef HAVE_AF_PACKET
#ifdef HAVE_PACKET_FANOUT
if (AFPConfGetThreads() <= 1) {
return default_mode_auto;
} else {
return default_mode_autofp;
}
#else
return default_mode_auto;
#endif
#else
return NULL;
#endif
}
void RunModeIdsAFPRegister(void)
{
default_mode_auto = "auto";
RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "auto",
"Multi threaded af-packet mode",
RunModeIdsAFPAuto);
default_mode = "auto";
RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "single",
"Single threaded af-packet mode",
RunModeIdsAFPSingle);
default_mode_autofp = "autofp";
RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "autofp",
"Multi socket AF_PACKET mode. Packets from "
"each flow are assigned to a single detect "
"thread.",
RunModeIdsAFPAutoFp);
return;
}
/**
* \brief RunModeIdsAFPAuto set up the following thread packet handlers:
* - Receive thread (from iface pcap)
* - Receive thread (from live iface)
* - Decode thread
* - Stream thread
* - Detect: If we have only 1 cpu, it will setup one Detect thread
@ -77,6 +110,8 @@ void RunModeIdsAFPRegister(void)
int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
{
SCEnter();
#ifdef HAVE_AF_PACKET
/* tname = Detect + cpuid, this is 11bytes length as max */
char tname[16];
uint16_t cpu = 0;
@ -88,28 +123,27 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
/* Available cpus */
uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
/* TODO must not use PCAP function */
/** \todo fix parasiting of pcap mode */
int npcap = LiveGetDeviceCount();
int nlive = LiveGetDeviceCount();
if (npcap == 1) {
char *pcap_dev = NULL;
if (ConfGet("pcap.single_pcap_dev", &pcap_dev) == 0) {
if (nlive == 1) {
char *live_dev = NULL;
char *live_devc = NULL;
if (ConfGet("af-packet.interface", &live_dev) == 0) {
SCLogError(SC_ERR_RUNMODE, "Failed retrieving "
"pcap.single_pcap_dev from Conf");
"af-packet.interface from Conf");
exit(EXIT_FAILURE);
}
SCLogDebug("pcap_dev %s", pcap_dev);
SCLogDebug("live_dev %s", live_dev);
char *pcap_devc = SCStrdup(pcap_dev);
live_devc = SCStrdup(live_dev);
/* create the threads */
ThreadVars *tv_receivepcap =
ThreadVars *tv_receiveafp =
TmThreadCreatePacketHandler("ReceiveAFP",
"packetpool", "packetpool",
"pickup-queue", "simple",
"1slot");
if (tv_receivepcap == NULL) {
if (tv_receiveafp == NULL) {
printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE);
}
@ -118,28 +152,30 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
printf("ERROR: TmModuleGetByName failed for ReceiveAFP\n");
exit(EXIT_FAILURE);
}
Tm1SlotSetFunc(tv_receivepcap, tm_module, (void *)pcap_devc);
TmSlotSetFuncAppend(tv_receiveafp, tm_module, (void *)live_devc);
TmThreadSetCPU(tv_receivepcap, RECEIVE_CPU_SET);
TmThreadSetCPU(tv_receiveafp, RECEIVE_CPU_SET);
if (TmThreadSpawn(tv_receivepcap) != TM_ECODE_OK) {
if (TmThreadSpawn(tv_receiveafp) != TM_ECODE_OK) {
printf("ERROR: TmThreadSpawn failed\n");
exit(EXIT_FAILURE);
}
} else {
SCLogInfo("Using %d pcap device(s).", npcap);
for (thread = 0; thread < npcap; thread++) {
char *pcap_dev = LiveGetDevice(thread);
if (pcap_dev == NULL) {
printf("Failed to lookup pcap dev %d\n", thread);
SCLogInfo("Using %d live device(s).", nlive);
for (thread = 0; thread < nlive; thread++) {
char *live_dev = LiveGetDevice(thread);
char *tnamec = NULL;
char *live_devc = NULL;
if (live_dev == NULL) {
printf("Failed to lookup live dev %d\n", thread);
exit(EXIT_FAILURE);
}
SCLogDebug("pcap_dev %s", pcap_dev);
SCLogDebug("live_dev %s", live_dev);
snprintf(tname, sizeof(tname),"RecvPcap-%s", pcap_dev);
char *tnamec = SCStrdup(tname);
char *pcap_devc = SCStrdup(pcap_dev);
snprintf(tname, sizeof(tname),"RecvAFP-%s", live_dev);
tnamec = SCStrdup(tname);
live_devc = SCStrdup(live_dev);
/* create the threads */
ThreadVars *tv_receiveafp =
@ -156,7 +192,7 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
printf("ERROR: TmModuleGetByName failed for ReceiveAFP\n");
exit(EXIT_FAILURE);
}
Tm1SlotSetFunc(tv_receiveafp, tm_module, (void *)pcap_devc);
TmSlotSetFuncAppend(tv_receiveafp, tm_module, (void *)live_devc);
TmThreadSetCPU(tv_receiveafp, RECEIVE_CPU_SET);
@ -286,14 +322,14 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
printf("ERROR: TmModuleGetByName DecodeAFP failed\n");
exit(EXIT_FAILURE);
}
TmVarSlotSetFuncAppend(tv_decode1, tm_module, NULL);
TmSlotSetFuncAppend(tv_decode1, tm_module, NULL);
tm_module = TmModuleGetByName("StreamTcp");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName StreamTcp failed\n");
exit(EXIT_FAILURE);
}
TmVarSlotSetFuncAppend(tv_decode1, tm_module, NULL);
TmSlotSetFuncAppend(tv_decode1, tm_module, NULL);
TmThreadSetCPU(tv_decode1, DECODE_CPU_SET);
@ -335,7 +371,7 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
printf("ERROR: TmModuleGetByName Detect failed\n");
exit(EXIT_FAILURE);
}
Tm1SlotSetFunc(tv_detect_ncpu, tm_module, (void *)de_ctx);
TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, (void *)de_ctx);
TmThreadSetCPU(tv_detect_ncpu, DETECT_CPU_SET);
@ -371,7 +407,7 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
printf("ERROR: TmModuleGetByName for RespondReject failed\n");
exit(EXIT_FAILURE);
}
Tm1SlotSetFunc(tv_rreject, tm_module, NULL);
TmSlotSetFuncAppend(tv_rreject, tm_module, NULL);
TmThreadSetCPU(tv_rreject, REJECT_CPU_SET);
@ -399,5 +435,224 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
return 0;
#endif
SCReturnInt(0);
}
int RunModeIdsAFPAutoFp(DetectEngineCtx *de_ctx)
{
SCEnter();
/* We include only if AF_PACKET is enabled */
#ifdef HAVE_AF_PACKET
char tname[12];
char qname[12];
char queues[2048] = "";
int afp_threads;
char *live_dev = NULL;
char *live_devc = NULL;
RunModeInitialize();
TimeModeSetLive();
/* Available cpus */
uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
/* always create at least one thread */
int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET);
if (thread_max == 0)
thread_max = ncpus * threading_detect_ratio;
if (thread_max < 1)
thread_max = 1;
int thread;
for (thread = 0; thread < thread_max; thread++) {
if (strlen(queues) > 0)
strlcat(queues, ",", sizeof(queues));
snprintf(qname, sizeof(qname),"pickup%"PRIu16, thread+1);
strlcat(queues, qname, sizeof(queues));
}
SCLogDebug("queues %s", queues);
if (ConfGet("af-packet.interface", &live_dev) == 0) {
SCLogError(SC_ERR_RUNMODE, "Failed retrieving "
"af-packet.interface from Conf");
exit(EXIT_FAILURE);
}
SCLogDebug("live_dev %s", live_dev);
afp_threads = AFPConfGetThreads();
SCLogInfo("Going to use %" PRId32 " AF_PACKET receive thread(s)",
afp_threads);
/* create the threads */
for (thread = 0; thread < afp_threads; thread++) {
snprintf(tname, sizeof(tname), "RxAFP%"PRIu16, thread+1);
char *thread_name = SCStrdup(tname);
ThreadVars *tv_receive =
TmThreadCreatePacketHandler(thread_name,
"packetpool", "packetpool",
queues, "flow", "varslot");
if (tv_receive == NULL) {
printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE);
}
TmModule *tm_module = TmModuleGetByName("ReceiveAFP");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName failed for ReceiveAFP\n");
exit(EXIT_FAILURE);
}
live_devc = SCStrdup(live_dev);
TmSlotSetFuncAppend(tv_receive, tm_module, live_devc);
tm_module = TmModuleGetByName("DecodeAFP");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName DecodeAFP failed\n");
exit(EXIT_FAILURE);
}
TmSlotSetFuncAppend(tv_receive, tm_module, NULL);
TmThreadSetCPU(tv_receive, RECEIVE_CPU_SET);
if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) {
printf("ERROR: TmThreadSpawn failed\n");
exit(EXIT_FAILURE);
}
}
for (thread = 0; thread < thread_max; thread++) {
snprintf(tname, sizeof(tname), "Detect%"PRIu16, thread+1);
snprintf(qname, sizeof(qname), "pickup%"PRIu16, thread+1);
SCLogDebug("tname %s, qname %s", tname, qname);
char *thread_name = SCStrdup(tname);
ThreadVars *tv_detect_ncpu =
TmThreadCreatePacketHandler(thread_name,
qname, "flow",
"packetpool", "packetpool",
"varslot");
if (tv_detect_ncpu == NULL) {
printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE);
}
TmModule *tm_module = TmModuleGetByName("StreamTcp");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName StreamTcp failed\n");
exit(EXIT_FAILURE);
}
TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL);
tm_module = TmModuleGetByName("Detect");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName Detect failed\n");
exit(EXIT_FAILURE);
}
TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, (void *)de_ctx);
TmThreadSetCPU(tv_detect_ncpu, DETECT_CPU_SET);
char *thread_group_name = SCStrdup("Detect");
if (thread_group_name == NULL) {
printf("Error allocating memory\n");
exit(EXIT_FAILURE);
}
tv_detect_ncpu->thread_group_name = thread_group_name;
/* add outputs as well */
SetupOutputs(tv_detect_ncpu);
if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) {
printf("ERROR: TmThreadSpawn failed\n");
exit(EXIT_FAILURE);
}
}
#endif /* HAVE_AF_PACKET */
SCReturnInt(0);
}
/**
* \brief Single thread version of the AF_PACKET processing.
*/
int RunModeIdsAFPSingle(DetectEngineCtx *de_ctx)
{
int nafp = LiveGetDeviceCount();
char *afp_dev = NULL;
char *afp_devc = NULL;
SCEnter();
#ifdef HAVE_AF_PACKET
if (nafp > 1) {
SCLogError(SC_ERR_RUNMODE,
"Can't use single runmode with multiple device");
exit(EXIT_FAILURE);
}
RunModeInitialize();
TimeModeSetLive();
if (ConfGet("af-packet.interface", &afp_dev) == 0) {
SCLogError(SC_ERR_RUNMODE, "Failed retrieving "
"af-packet.interface from Conf");
exit(EXIT_FAILURE);
}
SCLogDebug("afp_dev %s", afp_dev);
afp_devc = SCStrdup(afp_dev);
/* create the threads */
ThreadVars *tv = TmThreadCreatePacketHandler("AFPacket",
"packetpool", "packetpool",
"packetpool", "packetpool",
"pktacqloop");
if (tv == NULL) {
printf("ERROR: TmThreadsCreate failed\n");
exit(EXIT_FAILURE);
}
TmModule *tm_module = TmModuleGetByName("ReceiveAFP");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName failed for ReceiveAFP\n");
exit(EXIT_FAILURE);
}
TmSlotSetFuncAppend(tv, tm_module, afp_devc);
tm_module = TmModuleGetByName("DecodeAFP");
if (tm_module == NULL) {
printf("ERROR: TmModuleGetByName DecodeAFP 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);
}
#endif /* HAVE_AF_PACKET */
SCReturnInt(0);
}

@ -20,11 +20,13 @@
* \author Eric Leblond <eric@regit.org>
*/
#ifndef __RUNMODE_AFP_H__
#define __RUNMODE_AFP_H__
#ifndef __RUNMODE_AF_PACKET_H__
#define __RUNMODE_AF_PACKET_H__
int RunModeIdsAFPAuto(DetectEngineCtx *);
int RunModeIdsAFPSingle(DetectEngineCtx *);
int RunModeIdsAFPAutoFp(DetectEngineCtx *);
void RunModeIdsAFPRegister(void);
const char *RunModeAFPGetDefaultMode(void);
#endif /* __RUNMODE_AFP_H__ */
#endif /* __RUNMODE_AF_PACKET_H__ */

@ -25,12 +25,13 @@
* Fanouts socket from David Miller:
* we need to support the split of flow in different socket
* option:
- packet_fanout type
- fanout ID ?? seems it could be useful
- protocol is the IEEE 802.3 protocol number in network order (filtering is great)
- runmode -> family of threads in parallel (acccount)
- add a new ratio or threads number (overwritten by cpu_affinity)
- add af_max_read_packets for batched reading
* - packet_fanout type
* - fanout ID ?? seems it could be useful
* - protocol is the IEEE 802.3 protocol number in network order (filtering
* is great)
* - runmode -> family of threads in parallel (acccount)
* - add a new ratio or threads number (overwritten by cpu_affinity)
* - add af_max_read_packets for batched reading
*
* architecture
* loop with read
@ -40,10 +41,12 @@
* bind
* must switch to promiscous mode -> use PACKET_MR_PROMISC socket option
*
* \todo watch other interface event to detect suppression of the monitored interface
* \todo watch other interface event to detect suppression of the monitored
* interface
*/
#include "suricata-common.h"
#include "config.h"
#include "suricata.h"
#include "decode.h"
#include "packet-queue.h"
@ -57,17 +60,64 @@
#include "util-debug.h"
#include "util-error.h"
#include "util-privs.h"
#include "util-optimize.h"
#include "tmqh-packetpool.h"
#include "source-af-packet.h"
#include <sys/ioctl.h>
#ifdef HAVE_AF_PACKET
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_arp.h>
#endif
extern uint8_t suricata_ctl_flags;
extern int max_pending_packets;
#define AFP_WORKER_MODE 0
#define AFP_LOOP_MODE 1
#ifndef HAVE_AF_PACKET
TmEcode NoAFPSupportExit(ThreadVars *, void *, void **);
void TmModuleReceiveAFPRegister (void) {
tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
tmm_modules[TMM_RECEIVEAFP].ThreadInit = NoAFPSupportExit;
tmm_modules[TMM_RECEIVEAFP].Func = NULL;
tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = NULL;
tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
tmm_modules[TMM_RECEIVEAFP].cap_flags = 0;
}
/**
* \brief Registration Function for DecodeAFP.
* \todo Unit tests are needed for this module.
*/
void TmModuleDecodeAFPRegister (void) {
tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
tmm_modules[TMM_DECODEAFP].ThreadInit = NoAFPSupportExit;
tmm_modules[TMM_DECODEAFP].Func = NULL;
tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
tmm_modules[TMM_DECODEAFP].cap_flags = 0;
}
/**
* \brief this function prints an error message and exits.
*/
TmEcode NoAFPSupportExit(ThreadVars *tv, void *initdata, void **data)
{
SCLogError(SC_ERR_NO_AF_PACKET,"Error creating thread %s: you do not have "
"support for AF_PACKET enabled, on Linux host please recompile "
"with --enable-af-packet", tv->name);
exit(EXIT_FAILURE);
}
#else /* We have AF_PACKET support */
/** control how many packets we may read in one go */
static int afp_max_read_packets = 0;
/** max packets < 65536 */
@ -81,8 +131,6 @@ static int afp_max_read_packets = 0;
#define POLL_TIMEOUT 100
#define AFP_BUFSIZE 4096
/**
* \brief Structure to hold thread specific variables.
*/
@ -103,19 +151,21 @@ typedef struct AFPThreadVars_
uint64_t bytes;
uint32_t errs;
/* AFP buffer size */
int AFP_buffer_size;
/* socket buffer size */
int buffer_size;
int cluster_id;
int cluster_type;
ThreadVars *tv;
TmSlot *slot;
Packet *in_p;
Packet *array[AFP_FILE_MAX_PKTS];
uint16_t array_idx;
int fanout;
char *data; /** Per function and thread data */
uint8_t *data; /** Per function and thread data */
int datalen; /** Length of per function and thread data */
} AFPThreadVars;
@ -123,6 +173,7 @@ TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
TmEcode ReceiveAFPThreadInit(ThreadVars *, void *, void **);
void ReceiveAFPThreadExitStats(ThreadVars *, void *);
TmEcode ReceiveAFPThreadDeinit(ThreadVars *, void *);
TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot);
TmEcode DecodeAFPThreadInit(ThreadVars *, void *, void **);
TmEcode DecodeAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
@ -135,6 +186,7 @@ void TmModuleReceiveAFPRegister (void) {
tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
tmm_modules[TMM_RECEIVEAFP].ThreadInit = ReceiveAFPThreadInit;
tmm_modules[TMM_RECEIVEAFP].Func = ReceiveAFP;
tmm_modules[TMM_RECEIVEAFP].PktAcqLoop = ReceiveAFPLoop;
tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = ReceiveAFPThreadExitStats;
tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
@ -155,7 +207,26 @@ void TmModuleDecodeAFPRegister (void) {
tmm_modules[TMM_DECODEAFP].cap_flags = 0;
}
static int createsocket(AFPThreadVars *ptv, char *devname, int verbose);
static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose);
int AFPConfGetThreads()
{
int afp_threads = 1;
char *threadsstr = NULL;
if (ConfGet("af-packet.threads", &threadsstr) != 1) {
afp_threads = 1;
} else {
if (threadsstr != NULL) {
afp_threads = (uint8_t)atoi(threadsstr);
}
}
if (afp_threads == 0) {
afp_threads = 1;
}
return afp_threads;
}
/**
* \brief AF packet read function.
@ -166,11 +237,10 @@ static int createsocket(AFPThreadVars *ptv, char *devname, int verbose);
* \param user pointer to AFPThreadVars
* \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
*/
TmEcode AFPRead(AFPThreadVars *ptv)
TmEcode AFPRead(AFPThreadVars *ptv, int mode)
{
Packet *p = NULL;
/* XXX should try to use read that get directly to packet */
uint8_t buf[AFP_BUFSIZE];
int offset = 0;
int caplen;
struct sockaddr_ll from;
@ -198,8 +268,8 @@ TmEcode AFPRead(AFPThreadVars *ptv)
offset = SLL_HEADER_LEN;
else
offset = 0;
iov.iov_len = AFP_BUFSIZE - offset;
iov.iov_base = buf + offset;
iov.iov_len = ptv->datalen - offset;
iov.iov_base = ptv->data + offset;
caplen = recvmsg(ptv->socket, &msg, MSG_TRUNC);
@ -208,14 +278,21 @@ TmEcode AFPRead(AFPThreadVars *ptv)
errno);
SCReturnInt(TM_ECODE_FAILED);
}
if (ptv->array_idx == 0) {
p = ptv->in_p;
} else {
p = PacketGetFromQueueOrAlloc();
switch(mode) {
case AFP_WORKER_MODE:
if (ptv->array_idx == 0) {
p = ptv->in_p;
} else {
p = PacketGetFromQueueOrAlloc();
}
break;
case AFP_LOOP_MODE:
p = PacketGetFromQueueOrAlloc();
break;
default:
SCLogError(SC_ERR_INVALID_VALUE, "AFPRread does not support this mode");
}
if (p == NULL) {
TmqhOutputPacketpool(ptv->tv, p);
SCReturnInt(TM_ECODE_FAILED);
}
@ -232,23 +309,33 @@ TmEcode AFPRead(AFPThreadVars *ptv)
/* add forged header */
if (ptv->cooked) {
SllHdr * hdrp = (SllHdr *)buf;
SllHdr * hdrp = (SllHdr *)ptv->data;
/* XXX this is minimalist, but this seems enough */
hdrp->sll_protocol = from.sll_protocol;
}
p->datalink = ptv->datalink;
SET_PKT_LEN(p, caplen + offset);
if (PacketCopyData(p, buf, GET_PKT_LEN(p)) == -1) {
if (PacketCopyData(p, ptv->data, GET_PKT_LEN(p)) == -1) {
TmqhOutputPacketpool(ptv->tv, p);
SCReturnInt(TM_ECODE_FAILED);
}
SCLogDebug("pktlen: %" PRIu32 " (pkt %02x, pkt data %02x)",
GET_PKT_LEN(p), *pkt, *GET_PKT_DATA(p));
/* store the packet in our array */
ptv->array[ptv->array_idx] = p;
ptv->array_idx++;
SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
GET_PKT_LEN(p), p, GET_PKT_DATA(p));
switch(mode) {
case AFP_WORKER_MODE:
/* store the packet in our array */
ptv->array[ptv->array_idx] = p;
ptv->array_idx++;
break;
case AFP_LOOP_MODE:
TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p);
break;
default:
SCLogError(SC_ERR_INVALID_VALUE, "AFPRread does not support this mode");
TmqhOutputPacketpool(ptv->tv, p);
}
SCReturnInt(TM_ECODE_OK);
}
@ -258,7 +345,7 @@ static int AFPTryReopen(AFPThreadVars *ptv)
ptv->afp_state = AFP_STATE_DOWN;
afp_activate_r = createsocket(ptv, ptv->iface, 0);
afp_activate_r = AFPCreateSocket(ptv, ptv->iface, 0);
if (afp_activate_r != 0) {
return afp_activate_r;
}
@ -268,6 +355,101 @@ static int AFPTryReopen(AFPThreadVars *ptv)
return 0;
}
/**
* \brief Main AF_PACKET reading Loop function
*/
TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
{
uint16_t packet_q_len = 0;
AFPThreadVars *ptv = (AFPThreadVars *)data;
TmSlot *s = (TmSlot *)slot;
ptv->slot = s->slot_next;
struct pollfd fds;
int r;
SCEnter();
fds.fd = ptv->socket;
fds.events = POLLIN;
while (1) {
/* Start by checking the state of our interface */
if (unlikely(ptv->afp_state == AFP_STATE_DOWN)) {
int dbreak = 0;
do {
usleep(AFP_RECONNECT_TIMEOUT);
if (suricata_ctl_flags != 0) {
dbreak = 1;
break;
}
r = AFPTryReopen(ptv);
} while (r < 0);
if (dbreak == 1)
break;
}
/* 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);
r = poll(&fds, 1, POLL_TIMEOUT);
if (suricata_ctl_flags != 0) {
break;
}
if (r > 0 &&
(fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
if (fds.revents & (POLLHUP | POLLRDHUP)) {
close(ptv->socket);
ptv->afp_state = AFP_STATE_DOWN;
continue;
}
if (fds.revents & POLLERR) {
char c;
/* Do a recv to get errno */
if (recv(ptv->socket, &c, sizeof c, MSG_PEEK) != -1)
continue; /* what, no error? */
SCLogError(SC_ERR_AFP_READ, "Error reading data from socket: (%d" PRIu32 ") %s",
errno, strerror(errno));
close(ptv->socket);
ptv->afp_state = AFP_STATE_DOWN;
continue;
}
if (fds.revents & POLLNVAL) {
SCLogError(SC_ERR_AFP_READ, "Invalid polling request");
close(ptv->socket);
ptv->afp_state = AFP_STATE_DOWN;
continue;
}
} else if (r > 0) {
/* AFPRead will call TmThreadsSlotProcessPkt on read packets */
r = AFPRead(ptv, AFP_LOOP_MODE);
if (r != TM_ECODE_OK) {
SCReturnInt(TM_ECODE_FAILED);
}
} else if ((r < 0) && (errno != EINTR)) {
SCLogError(SC_ERR_AFP_READ, "Error reading data from socket: (%d" PRIu32 ") %s",
errno, strerror(errno));
close(ptv->socket);
ptv->afp_state = AFP_STATE_DOWN;
continue;
}
}
if (suricata_ctl_flags & SURICATA_STOP ||
suricata_ctl_flags & SURICATA_KILL) {
SCReturnInt(TM_ECODE_FAILED);
}
SCReturnInt(TM_ECODE_OK);
}
/**
* \brief Recieves packets from an interface via AF_PACKET socket
*
@ -322,19 +504,42 @@ TmEcode ReceiveAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, Packe
while (r >= 0) {
r = poll(&fds, 1, POLL_TIMEOUT);
if (r > 0) {
if (suricata_ctl_flags != 0) {
break;
}
ret = AFPRead(ptv);
if (ret != TM_ECODE_OK) {
SCReturnInt(TM_ECODE_FAILED);
if (r > 0 &&
(fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
if (fds.revents & (POLLHUP | POLLRDHUP)) {
close(ptv->socket);
ptv->afp_state = AFP_STATE_DOWN;
break;
}
if (suricata_ctl_flags != 0) {
if (fds.revents & POLLERR) {
char c;
/* Do a recv to get errno */
if (recv(ptv->socket, &c, sizeof c, MSG_PEEK) != -1)
continue; /* what, no error? */
SCLogError(SC_ERR_AFP_READ, "Error reading data from socket: (%d" PRIu32 ") %s",
errno, strerror(errno));
close(ptv->socket);
ptv->afp_state = AFP_STATE_DOWN;
break;
}
if (fds.revents & POLLNVAL) {
SCLogError(SC_ERR_AFP_READ, "Invalid polling request");
close(ptv->socket);
ptv->afp_state = AFP_STATE_DOWN;
break;
}
} else if (r > 0) {
ret = AFPRead(ptv, AFP_WORKER_MODE);
if (ret != TM_ECODE_OK) {
SCReturnInt(TM_ECODE_FAILED);
}
if (cnt++ >= afp_max_read_packets)
break;
}
if (r < 0) {
} else if ((r < 0) && (errno != EINTR)) {
int dbreak = 0;
SCLogError(SC_ERR_AFP_READ, "Error reading data from socket: (%d" PRIu32 ") %s",
errno, strerror(errno));
@ -350,11 +555,8 @@ TmEcode ReceiveAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, Packe
r = 0;
break;
}
}
if ( r == 0) {
if (suricata_ctl_flags != 0) {
break;
}
} else if (r == 0) {
/* timeout condition */
if (cnt > 0)
break;
}
@ -371,9 +573,7 @@ TmEcode ReceiveAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, Packe
}
if (r < 0) {
SCLogError(SC_ERR_AFP_DISPATCH, "error code %" PRId32,
r);
SCLogError(SC_ERR_AFP_DISPATCH, "error code %" PRId32, r);
SCReturnInt(TM_ECODE_OK);
}
@ -384,12 +584,12 @@ TmEcode ReceiveAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, Packe
SCReturnInt(TM_ECODE_OK);
}
static int getifnumbydev(int fd, const char *ifname, int verbose)
static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
if (verbose)
@ -401,12 +601,12 @@ static int getifnumbydev(int fd, const char *ifname, int verbose)
return ifr.ifr_ifindex;
}
static int getdevlinktype(int fd, const char *ifname)
static int AFPGetDevLinktype(int fd, const char *ifname)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
@ -414,10 +614,17 @@ static int getdevlinktype(int fd, const char *ifname)
return -1;
}
return ifr.ifr_hwaddr.sa_family;
switch (ifr.ifr_hwaddr.sa_family) {
case ARPHRD_LOOPBACK:
return LINKTYPE_ETHERNET;
case ARPHRD_PPP:
return LINKTYPE_RAW;
default:
return ifr.ifr_hwaddr.sa_family;
}
}
static int createsocket(AFPThreadVars *ptv, char *devname, int verbose)
static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
{
int r;
struct packet_mreq sock_params;
@ -425,7 +632,7 @@ static int createsocket(AFPThreadVars *ptv, char *devname, int verbose)
/* open socket */
ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (ptv->socket == -1) {
SCLogError(SC_ERR_AFP_CREATE, "Coudn't create a AF_PACKET socket, error %s", strerror(errno));
SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
return -1;
}
SCLogInfo("using interface %s", (char *)devname);
@ -433,10 +640,10 @@ static int createsocket(AFPThreadVars *ptv, char *devname, int verbose)
memset(&bind_address, 0, sizeof(bind_address));
bind_address.sll_family = AF_PACKET;
bind_address.sll_protocol = htons(ETH_P_ALL);
bind_address.sll_ifindex = getifnumbydev(ptv->socket, devname, verbose);
bind_address.sll_ifindex = AFPGetIfnumByDev(ptv->socket, devname, verbose);
if (bind_address.sll_ifindex == -1) {
if (verbose)
SCLogError(SC_ERR_AFP_CREATE, "Coudn't find iface %s", devname);
SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
return -1;
}
r = bind(ptv->socket, (struct sockaddr *)&bind_address, sizeof(bind_address));
@ -463,23 +670,44 @@ static int createsocket(AFPThreadVars *ptv, char *devname, int verbose)
r = setsockopt(ptv->socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(void *)&sock_params, sizeof(sock_params));
if (r < 0) {
SCLogError(SC_ERR_AFP_CREATE,
"Coudn't switch iface %s to promiscuous, error %s",
"Couldn't switch iface %s to promiscuous, error %s",
devname,
strerror(errno));
close(ptv->socket);
return -1;
}
/* set socket recv buffer size */
if (ptv->buffer_size != 0) {
/*
* Set the socket buffer size to the specified value.
*/
SCLogInfo("Setting AF_PACKET socket buffer to %d", ptv->buffer_size);
if (setsockopt(ptv->socket, SOL_SOCKET, SO_RCVBUF,
&ptv->buffer_size,
sizeof(ptv->buffer_size)) == -1) {
SCLogError(SC_ERR_AFP_CREATE,
"Couldn't set buffer size to %d on iface %s, error %s",
ptv->buffer_size,
devname,
strerror(errno));
close(ptv->socket);
return -1;
}
}
#ifdef HAVE_PACKET_FANOUT
/* add binded socket to fanout group */
if (ptv->fanout) {
if (AFPConfGetThreads() > 1) {
uint32_t option = 0;
uint16_t mode = PACKET_FANOUT_HASH;
uint16_t id = 1;
uint16_t mode = ptv->cluster_type;
uint16_t id = ptv->cluster_id;
option = (mode << 16) | (id & 0xffff);
r = setsockopt(ptv->socket, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
if (r < 0) {
SCLogError(SC_ERR_AFP_CREATE,
"Coudn't set fanout mode, error %s",
strerror(errno));
close(ptv->socket);
return -1;
}
}
@ -502,7 +730,11 @@ static int createsocket(AFPThreadVars *ptv, char *devname, int verbose)
TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
SCEnter();
int r;
int value;
intmax_t value;
#ifdef HAVE_PACKET_FANOUT
char *tmpclusterid;
char *tmpctype;
#endif
/* use max_pending_packets as AFP read size unless it's bigger than
* our size limit */
@ -522,28 +754,81 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
ptv->tv = tv;
ptv->cooked = 0;
strncpy(ptv->iface, initdata, AFP_IFACE_NAME_LENGTH);
strlcpy(ptv->iface, initdata, AFP_IFACE_NAME_LENGTH);
ptv->iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
r = createsocket(ptv, initdata, 1);
if ((ConfGetInt("af-packet.buffer-size", &value)) == 1) {
ptv->buffer_size = value;
} else {
ptv->buffer_size = 0;
}
#ifdef HAVE_PACKET_FANOUT
ptv->cluster_type = PACKET_FANOUT_LB;
ptv->cluster_id = 1;
/* We only set cluster info if the number of reader threads is greater than 1 */
if (AFPConfGetThreads() > 1) {
if (ConfGet("af-packet.cluster-id", &tmpclusterid) != 1) {
SCLogError(SC_ERR_INVALID_ARGUMENT,"could not get af-packet.cluster-id");
return TM_ECODE_FAILED;
} else {
ptv->cluster_id = (uint16_t)atoi(tmpclusterid);
SCLogDebug("Going to use cluster-id %" PRId32, ptv->cluster_id);
}
if (ConfGet("af-packet.cluster-type", &tmpctype) != 1) {
SCLogError(SC_ERR_GET_CLUSTER_TYPE_FAILED,"Could not get af-packet.cluster-type");
return TM_ECODE_FAILED;
} else if (strcmp(tmpctype, "cluster_round_robin") == 0) {
SCLogInfo("Using round-robin cluster mode for AF_PACKET (thread %s)",
ptv->tv->name);
ptv->cluster_type = PACKET_FANOUT_LB;
} else if (strcmp(tmpctype, "cluster_flow") == 0) {
/* In hash mode, we also ask for defragmentation needed to
* compute the hash */
uint16_t defrag = 0;
SCLogInfo("Using flow cluster mode for AF_PACKET (thread %s)",
ptv->tv->name);
ConfGetBool("af-packet.defrag", (int *)&defrag);
if (defrag) {
SCLogInfo("Using defrag kernel functionnality for AF_PACKET (thread %s)",
ptv->tv->name);
defrag = PACKET_FANOUT_FLAG_DEFRAG;
}
ptv->cluster_type = PACKET_FANOUT_HASH | defrag;
} else if (strcmp(tmpctype, "cluster_cpu") == 0) {
SCLogInfo("Using cpu cluster mode for AF_PACKET (thread %s)",
ptv->tv->name);
ptv->cluster_type = PACKET_FANOUT_CPU;
} else {
SCLogError(SC_ERR_INVALID_CLUSTER_TYPE,"invalid cluster-type %s",tmpctype);
return TM_ECODE_FAILED;
}
}
#endif
r = AFPCreateSocket(ptv, initdata, 1);
if (r < 0) {
SCLogError(SC_ERR_AFP_CREATE, "Coudn't init AF_PACKET socket");
SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket");
SCFree(ptv);
SCReturnInt(TM_ECODE_FAILED);
}
ptv->datalink = getdevlinktype(ptv->socket, ptv->iface);
ptv->datalink = AFPGetDevLinktype(ptv->socket, ptv->iface);
switch (ptv->datalink) {
case ARPHRD_PPP:
case ARPHRD_ATM:
ptv->cooked = 1;
}
if ((ConfGetBool("af-packet.fanout", &value)) == 1) {
ptv->fanout = value;
} else {
ptv->fanout = 0;
#define T_DATA_SIZE 70000
ptv->data = SCMalloc(T_DATA_SIZE);
if (ptv->data == NULL) {
SCReturnInt(TM_ECODE_FAILED);
}
ptv->datalen = T_DATA_SIZE;
#undef T_DATA_SIZE
*data = (void *)ptv;
SCReturnInt(TM_ECODE_OK);
@ -557,9 +842,8 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
void ReceiveAFPThreadExitStats(ThreadVars *tv, void *data) {
SCEnter();
AFPThreadVars *ptv = (AFPThreadVars *)data;
/**
* \todo Counter output
*/
SCLogInfo("(%s) Packets %" PRIu32 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes);
}
/**
@ -570,6 +854,12 @@ void ReceiveAFPThreadExitStats(ThreadVars *tv, void *data) {
TmEcode ReceiveAFPThreadDeinit(ThreadVars *tv, void *data) {
AFPThreadVars *ptv = (AFPThreadVars *)data;
if (ptv->data != NULL) {
SCFree(ptv->data);
ptv->data = NULL;
}
ptv->datalen = 0;
close(ptv->socket);
SCReturnInt(TM_ECODE_OK);
}
@ -643,4 +933,5 @@ TmEcode DecodeAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
SCReturnInt(TM_ECODE_OK);
}
#endif /* HAVE_AF_PACKET */
/* eof */

@ -24,7 +24,20 @@
#ifndef __SOURCE_AFP_H__
#define __SOURCE_AFP_H__
#ifndef HAVE_PACKET_FANOUT /* not defined if linux/if_packet.h trying to force */
#define HAVE_PACKET_FANOUT 1
#define PACKET_FANOUT 18
#define PACKET_FANOUT_HASH 0
#define PACKET_FANOUT_LB 1
#define PACKET_FANOUT_CPU 2
#define PACKET_FANOUT_FLAG_DEFRAG 0x8000
#endif /* HAVE_PACKET_FANOUT */
void TmModuleReceiveAFPRegister (void);
void TmModuleDecodeAFPRegister (void);
int AFPConfGetThreads();
#endif /* __SOURCE_AFP_H__ */

@ -22,6 +22,7 @@
*/
#include "suricata-common.h"
#include "config.h"
#include <getopt.h>
#include <signal.h>
@ -393,8 +394,9 @@ void usage(const char *progname)
printf("USAGE: %s\n\n", progname);
printf("\t-c <path> : path to configuration file\n");
printf("\t-i <dev or ip> : run in pcap live mode\n");
/* TODO add condition ifdef for af_packet */
#ifdef HAVE_AF_PACKET
printf("\t-a <dev> : run in af-packet mode\n");
#endif
printf("\t-F <bpf filter file> : bpf filter file\n");
printf("\t-r <path> : run in pcap file/offline mode\n");
#ifdef NFQ
@ -489,6 +491,9 @@ void SCPrintBuildInfo(void) {
#ifdef HAVE_PFRING
strlcat(features, "PF_RING ", sizeof(features));
#endif
#ifdef HAVE_AF_PACKET
strlcat(features, "AF_PACKET ", sizeof(features));
#endif
#ifdef HAVE_DAG
strlcat(features, "DAG ", sizeof(features));
#endif
@ -865,28 +870,30 @@ int main(int argc, char **argv)
strlcpy(pcap_dev, optarg, ((strlen(optarg) < sizeof(pcap_dev)) ? (strlen(optarg)+1) : (sizeof(pcap_dev))));
break;
case 'a':
/** \todo TODO fix parasiting of pcap mode */
#ifdef HAVE_AF_PACKET
if (run_mode == RUNMODE_UNKNOWN) {
run_mode = RUNMODE_AFP_DEV;
LiveRegisterDevice(optarg);
} else if (run_mode == RUNMODE_AFP_DEV) {
#ifdef OS_WIN32
SCLogError(SC_ERR_PCAP_MULTI_DEV_NO_SUPPORT, "pcap multi dev "
"support is not (yet) supported on Windows.");
exit(EXIT_FAILURE);
#else
SCLogWarning(SC_WARN_PCAP_MULTI_DEV_EXPERIMENTAL, "using "
"multiple pcap devices to get packets is experimental.");
"multiple devices to get packets is experimental.");
LiveRegisterDevice(optarg);
#endif
} else {
SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
"has been specified");
"has been specified");
usage(argv[0]);
exit(EXIT_FAILURE);
}
memset(pcap_dev, 0, sizeof(pcap_dev));
strlcpy(pcap_dev, optarg, ((strlen(optarg) < sizeof(pcap_dev)) ? (strlen(optarg)+1) : (sizeof(pcap_dev))));
strlcpy(pcap_dev, optarg,
((strlen(optarg) < sizeof(pcap_dev)) ?
(strlen(optarg) + 1) : sizeof(pcap_dev)));
#else
SCLogError(SC_ERR_NO_AF_PACKET,"AF_PACKET not enabled. On Linux "
"host, make sure to pass --enable-af-packet to "
"configure when building.");
exit(EXIT_FAILURE);
#endif
break;
case 'l':
if (ConfSet("default-log-dir", optarg, 0) != 1) {
@ -894,8 +901,8 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
if (stat(optarg, &buf) != 0) {
SCLogError(SC_ERR_LOGDIR_CMDLINE, "The logging directory \"%s\" "
"supplied at the commandline (-l %s) doesn't "
SCLogError(SC_ERR_LOGDIR_CMDLINE, "The logging directory \"%s\""
" supplied at the commandline (-l %s) doesn't "
"exist. Shutting down the engine.", optarg, optarg);
exit(EXIT_FAILURE);
}

@ -81,5 +81,6 @@ char *LiveGetDevice(int number) {
i++;
}
return NULL;
}

@ -15,8 +15,8 @@
* 02110-1301, USA.
*/
#ifndef _UTIL_DEVICE_H
#define _UTIL_DEVICE_H 1
#ifndef __UTIL_DEVICE_H__
#define __UTIL_DEVICE_H__
#include "queue.h"
@ -31,4 +31,4 @@ int LiveRegisterDevice(char *dev);
int LiveGetDeviceCount(void);
char *LiveGetDevice(int number);
#endif /* _UTIL_DEVICE_H */
#endif /* __UTIL_DEVICE_H__ */

@ -206,6 +206,9 @@ const char * SCErrorToString(SCError err)
CASE_CODE (SC_ERR_RUNMODE);
CASE_CODE (SC_ERR_SHUTDOWN);
CASE_CODE (SC_ERR_INVALID_DIRECTION);
CASE_CODE (SC_ERR_AFP_CREATE);
CASE_CODE (SC_ERR_AFP_READ);
CASE_CODE (SC_ERR_AFP_DISPATCH);
default:
return "UNKNOWN_ERROR";

@ -220,6 +220,7 @@ typedef enum {
SC_ERR_AFP_CREATE,
SC_ERR_AFP_READ,
SC_ERR_AFP_DISPATCH,
SC_ERR_NO_AF_PACKET,
} SCError;
const char *SCErrorToString(SCError);

@ -160,19 +160,24 @@ af-packet:
# Number of receive threads (>1 will enable experimental flow pinned
# runmode)
threads: 1
# Default interface we will listen on.
# default network interface
interface: eth0
# Default clusterid. AF_PACKET will load balance packets based on flow.
# All threads/processes that will participate need to have the same
# clusterid.
cluster-id: 99
# Default AF_PACKET cluster type. AF_PACKET can load balance per flow or per hash.
# This is only supported for Linux kernel > 3.1
# possible value are: "cluster_round_robin" and "cluster_flow"
# possible value are:
# * cluster_round_robin: round robin load balancing
# * cluster_flow: all packets of a given flow are send to the same socket
# * cluster_cpu: all packets treated in kernel by a CPU are send to the same socket
cluster-type: cluster_round_robin
# In some fragmentation case, the hash can not be computed. If "defrag" is set
# to yes, the kernel will do the needed defragmentation before sending the packets.
defrag: yes
# recv buffer size, increase value could improve performance
# buffer-size: 32768
defrag:
max-frags: 65535

Loading…
Cancel
Save