af-packet: IPS and TAP feature

This patch adds a new feature to AF_PACKET capture mode. It is now
possible to use AF_PACKET in IPS and TAP mode: all traffic received
on a interface will be forwarded (at the Ethernet level) to an other
interface. To do so, Suricata create a raw socket and sends the receive
packets to a interface designed in the configuration file.

This patch adds two variables to the configuration of af-packet
interface:
 copy-mode: ips or tap
 copy-iface: eth1 #the interface where packet are copied
If copy-mode is set to ips then the packet wth action DROP are not
copied to the destination interface. If copy-mode is set to tap,
all packets are copied to the destination interface.
Any other value of copy-mode results in the feature to be unused.
There is no default interface for copy-iface and the variable has
to be set for the ids or tap mode to work.

For now, this feature depends of the release data system. This
implies you need to activate the ring mode and zero copy. Basically
use-mmap has to be set to yes.

This patch adds a peering of AF_PACKET sockets from the thread on
one interface to the threads on another interface. Peering is
necessary as if we use an other socket the capture socket receives
all emitted packets. This is made using a new AFPPeer structure to
avoid direct interaction between AFPTreadVars.

There is currently a bug in Linux kernel (prior to 3.6) and it is
not possible to use multiple threads.

You need to setup two interfaces with equality on the threads
variable. copy-mode variable must be set on the two interfaces
and use-mmap must be set to activated.

A valid configuration for an IPS using eth0 and vboxnet1 interfaces
will look like:

af-packet:
  - interface: eth0
    threads: 1
    defrag: yes
    cluster-type: cluster_flow
    cluster-id: 98
    copy-mode: ips
    copy-iface: vboxnet1
    buffer-size: 64535
    use-mmap: yes
  - interface: vboxnet1
    threads: 1
    cluster-id: 97
    defrag: yes
    cluster-type: cluster_flow
    copy-mode: ips
    copy-iface: eth0
    buffer-size: 64535
    use-mmap: yes
pull/48/merge
Eric Leblond 13 years ago committed by Victor Julien
parent 2011a3f87e
commit 662dccd8a5

@ -109,9 +109,11 @@ void *ParseAFPConfig(const char *iface)
AFPIfaceConfig *aconf = SCMalloc(sizeof(*aconf));
char *tmpclusterid;
char *tmpctype;
char *copymodestr;
intmax_t value;
int boolval;
char *bpf_filter = NULL;
char *out_iface = NULL;
if (aconf == NULL) {
return NULL;
@ -134,6 +136,7 @@ void *ParseAFPConfig(const char *iface)
aconf->DerefFunc = AFPDerefConfig;
aconf->flags = 0;
aconf->bpf_filter = NULL;
aconf->out_iface = NULL;
if (ConfGet("bpf-filter", &bpf_filter) == 1) {
if (strlen(bpf_filter) > 0) {
@ -169,6 +172,44 @@ void *ParseAFPConfig(const char *iface)
aconf->threads = 1;
}
if (ConfGetChildValue(if_root, "copy-iface", &out_iface) == 1) {
if (strlen(out_iface) > 0) {
aconf->out_iface = out_iface;
}
}
(void)ConfGetChildValueBool(if_root, "use-mmap", (int *)&boolval);
if (boolval) {
SCLogInfo("Enabling mmaped capture on iface %s",
aconf->iface);
aconf->flags |= AFP_RING_MODE;
}
aconf->copy_mode = AFP_COPY_MODE_NONE;
if (ConfGetChildValue(if_root, "copy-mode", &copymodestr) == 1) {
if (aconf->out_iface == NULL) {
SCLogInfo("Copy mode activated but no destination"
" iface. Disabling feature");
} else if (!(aconf->flags & AFP_RING_MODE)) {
SCLogInfo("Copy mode activated but use-mmap "
"set to no. Disabling feature");
} else if (strlen(copymodestr) <= 0) {
aconf->out_iface = NULL;
} else if (strcmp(copymodestr, "ips") == 0) {
SCLogInfo("AF_PACKET IPS mode activated %s->%s",
iface,
aconf->out_iface);
aconf->copy_mode = AFP_COPY_MODE_IPS;
} else if (strcmp(copymodestr, "tap") == 0) {
SCLogInfo("AF_PACKET TAP mode activated %s->%s",
iface,
aconf->out_iface);
aconf->copy_mode = AFP_COPY_MODE_TAP;
} else {
SCLogInfo("Invalid mode (not in tap, ips)");
}
}
SC_ATOMIC_RESET(aconf->ref);
(void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);
@ -246,13 +287,6 @@ void *ParseAFPConfig(const char *iface)
aconf->iface);
aconf->promisc = 0;
}
(void)ConfGetChildValueBool(if_root, "use-mmap", (int *)&boolval);
if (boolval) {
SCLogInfo("Enabling mmaped capture on iface %s",
aconf->iface);
aconf->flags |= AFP_RING_MODE;
}
if (ConfGetChildValue(if_root, "checksum-checks", &tmpctype) == 1) {
if (strcmp(tmpctype, "auto") == 0) {
@ -309,6 +343,11 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
(void)ConfGet("af-packet.live-interface", &live_dev);
if (AFPPeersListInit() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
exit(EXIT_FAILURE);
}
ret = RunModeSetLiveCaptureAuto(de_ctx,
ParseAFPConfig,
AFPConfigGeThreadsCount,
@ -320,6 +359,12 @@ int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
/* In IPS mode each threads must have a peer */
if (AFPPeersListCheck() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPAuto initialised");
#endif
SCReturnInt(0);
@ -342,6 +387,11 @@ int RunModeIdsAFPAutoFp(DetectEngineCtx *de_ctx)
SCLogDebug("live_dev %s", live_dev);
if (AFPPeersListInit() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
exit(EXIT_FAILURE);
}
ret = RunModeSetLiveCaptureAutoFp(de_ctx,
ParseAFPConfig,
AFPConfigGeThreadsCount,
@ -353,8 +403,13 @@ int RunModeIdsAFPAutoFp(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPAutoFp initialised");
/* In IPS mode each threads must have a peer */
if (AFPPeersListCheck() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPAutoFp initialised");
#endif /* HAVE_AF_PACKET */
SCReturnInt(0);
@ -377,6 +432,11 @@ int RunModeIdsAFPSingle(DetectEngineCtx *de_ctx)
(void)ConfGet("af-packet.live-interface", &live_dev);
if (AFPPeersListInit() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
exit(EXIT_FAILURE);
}
ret = RunModeSetLiveCaptureSingle(de_ctx,
ParseAFPConfig,
AFPConfigGeThreadsCount,
@ -388,6 +448,12 @@ int RunModeIdsAFPSingle(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
/* In IPS mode each threads must have a peer */
if (AFPPeersListCheck() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPSingle initialised");
#endif /* HAVE_AF_PACKET */
@ -414,6 +480,11 @@ int RunModeIdsAFPWorkers(DetectEngineCtx *de_ctx)
(void)ConfGet("af-packet.live-interface", &live_dev);
if (AFPPeersListInit() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
exit(EXIT_FAILURE);
}
ret = RunModeSetLiveCaptureWorkers(de_ctx,
ParseAFPConfig,
AFPConfigGeThreadsCount,
@ -425,6 +496,12 @@ int RunModeIdsAFPWorkers(DetectEngineCtx *de_ctx)
exit(EXIT_FAILURE);
}
/* In IPS mode each threads must have a peer */
if (AFPPeersListCheck() != TM_ECODE_OK) {
SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
exit(EXIT_FAILURE);
}
SCLogInfo("RunModeIdsAFPSingle initialised");
#endif /* HAVE_AF_PACKET */

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Open Information Security Foundation
/* Copyright (C) 2011,2012 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -166,6 +166,10 @@ typedef struct AFPThreadVars_
int promisc;
ChecksumValidationMode checksum_mode;
/* IPS stuff */
char out_iface[AFP_IFACE_NAME_LENGTH];
AFPPeer *mpeer;
int flags;
uint16_t capture_kernel_packets;
uint16_t capture_kernel_drops;
@ -174,6 +178,7 @@ typedef struct AFPThreadVars_
int cluster_type;
int threads;
int copy_mode;
struct tpacket_req req;
unsigned int tp_hdrlen;
@ -182,6 +187,7 @@ typedef struct AFPThreadVars_
char *frame_buf;
unsigned int frame_offset;
int ring_size;
} AFPThreadVars;
TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
@ -194,6 +200,7 @@ TmEcode DecodeAFPThreadInit(ThreadVars *, void *, void **);
TmEcode DecodeAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
TmEcode AFPSetBPFFilter(AFPThreadVars *ptv);
static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose);
/**
* \brief Registration Function for RecieveAFP.
@ -211,6 +218,119 @@ void TmModuleReceiveAFPRegister (void) {
tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
}
typedef struct AFPPeersList_ {
TAILQ_HEAD(, AFPPeer_) peers; /**< Head of list of fragments. */
int cnt;
int peered;
} AFPPeersList;
/**
* Update the peer.
*/
void AFPPeerUpdate(AFPThreadVars *ptv)
{
if (ptv->mpeer == NULL) {
return;
}
SCLogInfo("Updating AFP peer");
(void)SC_ATOMIC_SET(ptv->mpeer->if_idx, AFPGetIfnumByDev(ptv->socket, ptv->iface, 0));
(void)SC_ATOMIC_SET(ptv->mpeer->socket, ptv->socket);
(void)SC_ATOMIC_SET(ptv->mpeer->state, ptv->afp_state);
}
void AFPPeerClean(AFPPeer *peer)
{
if (peer->flags & AFP_SOCK_PROTECT)
SCMutexDestroy(&peer->sock_protect);
SC_ATOMIC_DESTROY(peer->socket);
SC_ATOMIC_DESTROY(peer->if_idx);
SC_ATOMIC_DESTROY(peer->state);
SCFree(peer);
}
AFPPeersList peerslist;
TmEcode AFPPeersListInit()
{
SCEnter();
TAILQ_INIT(&peerslist.peers);
peerslist.peered = 0;
peerslist.cnt = 0;
SCReturnInt(TM_ECODE_OK);
}
TmEcode AFPPeersListCheck()
{
#define AFP_PEERS_MAX_TRY 4
#define AFP_PEERS_WAIT 20000
int try = 0;
SCEnter();
while (try < AFP_PEERS_MAX_TRY) {
if (peerslist.cnt != peerslist.peered) {
usleep(AFP_PEERS_WAIT);
} else {
SCReturnInt(TM_ECODE_OK);
}
try++;
}
SCLogError(SC_ERR_AFP_CREATE, "Threads number not equals");
SCReturnInt(TM_ECODE_FAILED);
}
TmEcode AFPPeersListAdd(AFPThreadVars *ptv)
{
SCEnter();
AFPPeer *peer = SCMalloc(sizeof(AFPPeer));
AFPPeer *pitem;
if (peer == NULL) {
SCReturnInt(TM_ECODE_FAILED);
}
memset(peer, 0, sizeof(AFPPeer));
SC_ATOMIC_INIT(peer->socket);
SC_ATOMIC_INIT(peer->if_idx);
SC_ATOMIC_INIT(peer->state);
peer->flags = ptv->flags;
if (peer->flags & AFP_SOCK_PROTECT) {
SCMutexInit(&peer->sock_protect, NULL);
}
(void)SC_ATOMIC_SET(peer->state, AFP_STATE_DOWN);
strlcpy(peer->iface, ptv->iface, AFP_IFACE_NAME_LENGTH);
ptv->mpeer = peer;
/* add element to iface list */
TAILQ_INSERT_TAIL(&peerslist.peers, peer, next);
peerslist.cnt++;
/* Iter to find a peer */
TAILQ_FOREACH(pitem, &peerslist.peers, next) {
if (pitem->peer)
continue;
if (strcmp(pitem->iface, ptv->out_iface))
continue;
peer->peer = pitem;
pitem->peer = peer;
peerslist.peered += 2;
break;
}
AFPPeerUpdate(ptv);
SCReturnInt(TM_ECODE_OK);
}
void AFPPeersListClean()
{
AFPPeer *pitem;
while ((pitem = TAILQ_FIRST(&peerslist.peers))) {
TAILQ_REMOVE(&peerslist.peers, pitem, next);
AFPPeerClean(pitem);
}
}
/**
* \brief Registration Function for DecodeAFP.
* \todo Unit tests are needed for this module.
@ -226,6 +346,7 @@ void TmModuleDecodeAFPRegister (void) {
tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
}
static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose);
static inline void AFPDumpCounters(AFPThreadVars *ptv, int forced)
@ -368,13 +489,64 @@ int AFPRead(AFPThreadVars *ptv)
SCReturnInt(AFP_READ_OK);
}
TmEcode AFPWritePacket(Packet *p)
{
struct sockaddr_ll socket_address;
int socket;
if (p->afp_v.copy_mode == AFP_COPY_MODE_IPS) {
if (p->action & ACTION_DROP) {
return TM_ECODE_OK;
}
}
if (SC_ATOMIC_GET(p->afp_v.peer->state) == AFP_STATE_DOWN)
return TM_ECODE_OK;
if (p->ethh == NULL) {
SCLogWarning(SC_ERR_INVALID_VALUE, "Should have an Ethernet header");
return TM_ECODE_FAILED;
}
/* Index of the network device */
socket_address.sll_ifindex = SC_ATOMIC_GET(p->afp_v.peer->if_idx);
/* Address length*/
socket_address.sll_halen = ETH_ALEN;
/* Destination MAC */
memcpy(socket_address.sll_addr, p->ethh, 6);
/* Send packet, locking the socket if necessary */
if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
SCMutexLock(&p->afp_v.peer->sock_protect);
socket = SC_ATOMIC_GET(p->afp_v.peer->socket);
if (sendto(socket, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,
(struct sockaddr*) &socket_address,
sizeof(struct sockaddr_ll)) < 0) {
SCLogWarning(SC_ERR_SOCKET, "Sending packet failed on socket %d: %s",
socket,
strerror(errno));
if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
SCMutexUnlock(&p->afp_v.peer->sock_protect);
return TM_ECODE_FAILED;
}
if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
SCMutexUnlock(&p->afp_v.peer->sock_protect);
return TM_ECODE_OK;
}
TmEcode AFPReleaseDataFromRing(ThreadVars *t, Packet *p)
{
int ret = TM_ECODE_OK;
/* Need to be in copy mode and need to detect early release
where Ethernet header could not be set (and pseudo packet) */
if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
ret = AFPWritePacket(p);
}
if (p->afp_v.relptr) {
union thdr h;
h.raw = p->afp_v.relptr;
h.h2->tp_status = TP_STATUS_KERNEL;
return TM_ECODE_OK;
return ret;
}
return TM_ECODE_FAILED;
}
@ -392,6 +564,7 @@ int AFPReadFromRing(AFPThreadVars *ptv)
{
Packet *p = NULL;
union thdr h;
struct sockaddr_ll *from;
/* Loop till we have packets available */
while (1) {
@ -399,12 +572,8 @@ int AFPReadFromRing(AFPThreadVars *ptv)
h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
if (h.raw == NULL) {
SCReturnInt(AFP_FAILURE);
} else {
if (ptv->flags & AFP_RING_MODE) {
p->afp_v.relptr = h.raw;
p->ReleaseData = AFPReleaseDataFromRing;
}
}
if (h.h2->tp_status == TP_STATUS_KERNEL) {
SCReturnInt(AFP_READ_OK);
}
@ -414,6 +583,20 @@ int AFPReadFromRing(AFPThreadVars *ptv)
SCReturnInt(AFP_FAILURE);
}
if (ptv->flags & AFP_RING_MODE) {
p->afp_v.relptr = h.raw;
p->ReleaseData = AFPReleaseDataFromRing;
p->afp_v.copy_mode = ptv->copy_mode;
if (p->afp_v.copy_mode != AFP_COPY_MODE_NONE) {
p->afp_v.peer = ptv->mpeer->peer;
} else {
p->afp_v.peer = NULL;
}
}
from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
ptv->pkts++;
ptv->bytes += h.h2->tp_len;
(void) SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
@ -422,7 +605,6 @@ int AFPReadFromRing(AFPThreadVars *ptv)
/* add forged header */
if (ptv->cooked) {
SllHdr * hdrp = (SllHdr *)ptv->data;
struct sockaddr_ll *from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
/* XXX this is minimalist, but this seems enough */
hdrp->sll_protocol = from->sll_protocol;
}
@ -436,6 +618,18 @@ int AFPReadFromRing(AFPThreadVars *ptv)
if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
TmqhOutputPacketpool(ptv->tv, p);
SCReturnInt(AFP_FAILURE);
} else {
if (ptv->flags & AFP_RING_MODE) {
p->afp_v.relptr = h.raw;
p->afp_v.copy_mode = ptv->copy_mode;
if (p->afp_v.copy_mode != AFP_COPY_MODE_NONE) {
p->afp_v.peer = ptv->mpeer->peer;
} else {
p->afp_v.peer = NULL;
}
p->ReleaseData = AFPReleaseDataFromRing;
}
}
} else {
if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
@ -499,7 +693,6 @@ static int AFPTryReopen(AFPThreadVars *ptv)
}
SCLogInfo("Recovering interface listening");
ptv->afp_state = AFP_STATE_UP;
return 0;
}
@ -525,6 +718,9 @@ TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
/* Start by checking the state of our interface */
if (unlikely(ptv->afp_state == AFP_STATE_DOWN)) {
int dbreak = 0;
AFPPeerUpdate(ptv);
do {
usleep(AFP_RECONNECT_TIMEOUT);
if (suricata_ctl_flags != 0) {
@ -702,6 +898,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
struct sockaddr_ll bind_address;
int order;
unsigned int i;
int if_idx;
/* open socket */
ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
@ -709,12 +906,13 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
return -1;
}
SCLogDebug("using interface %s", (char *)devname);
SCLogInfo("Using interface '%s' via socket %d", (char *)devname, ptv->socket);
if_idx = AFPGetIfnumByDev(ptv->socket, devname, verbose);
/* bind socket */
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 = AFPGetIfnumByDev(ptv->socket, devname, verbose);
bind_address.sll_ifindex = if_idx;
if (bind_address.sll_ifindex == -1) {
if (verbose)
SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
@ -898,6 +1096,8 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
/* Init is ok */
ptv->afp_state = AFP_STATE_UP;
AFPPeerUpdate(ptv);
return 0;
}
@ -1027,6 +1227,9 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
if (active_runmode && !strcmp("workers", active_runmode)) {
ptv->flags |= AFP_ZERO_COPY;
SCLogInfo("Enabling zero copy mode");
} else {
/* If we are using copy mode we need a lock */
ptv->flags |= AFP_SOCK_PROTECT;
}
/* If we are in RING mode, then we can use ZERO copy
@ -1044,6 +1247,16 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
SCReturnInt(TM_ECODE_FAILED);
}
ptv->copy_mode = afpconfig->copy_mode;
if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
strlcpy(ptv->out_iface, afpconfig->out_iface, AFP_IFACE_NAME_LENGTH);
ptv->out_iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
if (AFPPeersListAdd(ptv) == TM_ECODE_FAILED) {
SCFree(ptv);
afpconfig->DerefFunc(afpconfig);
SCReturnInt(TM_ECODE_FAILED);
}
}
#define T_DATA_SIZE 70000
@ -1099,6 +1312,7 @@ TmEcode ReceiveAFPThreadDeinit(ThreadVars *tv, void *data) {
ptv->bpf_filter = NULL;
close(ptv->socket);
SCReturnInt(TM_ECODE_OK);
}

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Open Information Security Foundation
/* Copyright (C) 2011,2012 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -33,14 +33,19 @@
#define PACKET_FANOUT_LB 1
#define PACKET_FANOUT_CPU 2
#define PACKET_FANOUT_FLAG_DEFRAG 0x8000
#else /* HAVE_PACKET_FANOUT */
#include <linux/if_packet.h>
#endif /* HAVE_PACKET_FANOUT */
#include "queue.h"
/* value for flags */
#define AFP_RING_MODE (1<<0)
#define AFP_ZERO_COPY (1<<1)
#define AFP_SOCK_PROTECT (1<<2)
#define AFP_COPY_MODE_NONE 0
#define AFP_COPY_MODE_TAP 1
#define AFP_COPY_MODE_IPS 2
#define AFP_FILE_MAX_PKTS 256
#define AFP_IFACE_NAME_LENGTH 48
@ -61,20 +66,40 @@ typedef struct AFPIfaceConfig_
int promisc;
/* misc use flags including ring mode */
int flags;
int copy_mode;
ChecksumValidationMode checksum_mode;
char *bpf_filter;
char *out_iface;
SC_ATOMIC_DECLARE(unsigned int, ref);
void (*DerefFunc)(void *);
} AFPIfaceConfig;
typedef struct AFPPeer_ {
char iface[AFP_IFACE_NAME_LENGTH];
SC_ATOMIC_DECLARE(int, socket);
SC_ATOMIC_DECLARE(int, if_idx);
SC_ATOMIC_DECLARE(uint8_t, state);
SCMutex sock_protect;
int flags;
struct AFPPeer_ *peer;
TAILQ_ENTRY(AFPPeer_) next;
} AFPPeer;
/* per packet AF_PACKET vars */
typedef struct AFPPacketVars_
{
void *relptr;
int copy_mode;
AFPPeer *peer;
} AFPPacketVars;
void TmModuleReceiveAFPRegister (void);
void TmModuleDecodeAFPRegister (void);
TmEcode AFPPeersListInit();
TmEcode AFPPeersListCheck();
void AFPPeersListClean();
#endif /* __SOURCE_AFP_H__ */

@ -2015,6 +2015,8 @@ int main(int argc, char **argv)
TmqhCleanup();
TmModuleRunDeInit();
AFPPeersListClean();
#ifdef PROFILING
if (profiling_rules_enabled)
SCProfilingDump();

@ -253,6 +253,13 @@ af-packet:
#checksum-checks: kernel
# BPF filter to apply to this interface. The pcap filter syntax apply here.
#bpf-filter: port 80 or udp
# You can use the following variables to activate AF_PACKET tap od IPS mode.
# If copy-mode is set to ips or tap, the traffic coming to the current
# interface will be copied to the copy-iface interface. If 'tap' is set, the
# copy is complete. If 'ips' is set, the packet matching a 'drop' action
# will not be copied.
#copy-mode: ips
#copy-iface: eth1
- interface: eth1
threads: 1
cluster-id: 98

Loading…
Cancel
Save