1 /* Copyright (C) 2011-2014 Open Information Security Foundation
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * \defgroup afppacket AF_PACKET running mode
27 * \author Eric Leblond <eric@regit.org>
29 * AF_PACKET socket acquisition support
31 * \todo watch other interface event to detect suppression of the monitored
35 #include "suricata-common.h"
39 #include "packet-queue.h"
41 #include "threadvars.h"
42 #include "tm-queuehandlers.h"
43 #include "tm-modules.h"
44 #include "tm-threads.h"
45 #include "tm-threads-common.h"
47 #include "util-debug.h"
48 #include "util-device.h"
49 #include "util-error.h"
50 #include "util-privs.h"
51 #include "util-optimize.h"
52 #include "util-checksum.h"
53 #include "util-ioctl.h"
54 #include "util-host-info.h"
55 #include "tmqh-packetpool.h"
56 #include "source-af-packet.h"
59 #ifdef __SC_CUDA_SUPPORT__
61 #include "util-cuda.h"
62 #include "util-cuda-buffer.h"
63 #include "util-mpm-ac.h"
64 #include "util-cuda-handlers.h"
65 #include "detect-engine.h"
66 #include "detect-engine-mpm.h"
67 #include "util-cuda-vars.h"
69 #endif /* __SC_CUDA_SUPPORT__ */
74 #include <sys/ioctl.h>
77 #if HAVE_LINUX_IF_ETHER_H
78 #include <linux/if_ether.h>
81 #if HAVE_LINUX_IF_PACKET_H
82 #include <linux/if_packet.h>
85 #if HAVE_LINUX_IF_ARP_H
86 #include <linux/if_arp.h>
89 #if HAVE_LINUX_FILTER_H
90 #include <linux/filter.h>
97 #endif /* HAVE_AF_PACKET */
99 extern int max_pending_packets;
101 #ifndef HAVE_AF_PACKET
103 TmEcode NoAFPSupportExit(ThreadVars *, void *, void **);
105 void TmModuleReceiveAFPRegister (void)
107 tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
108 tmm_modules[TMM_RECEIVEAFP].ThreadInit = NoAFPSupportExit;
109 tmm_modules[TMM_RECEIVEAFP].Func = NULL;
110 tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = NULL;
111 tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
112 tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
113 tmm_modules[TMM_RECEIVEAFP].cap_flags = 0;
114 tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
118 * \brief Registration Function for DecodeAFP.
119 * \todo Unit tests are needed for this module.
121 void TmModuleDecodeAFPRegister (void)
123 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
124 tmm_modules[TMM_DECODEAFP].ThreadInit = NoAFPSupportExit;
125 tmm_modules[TMM_DECODEAFP].Func = NULL;
126 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
127 tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
128 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
129 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
130 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
134 * \brief this function prints an error message and exits.
136 TmEcode NoAFPSupportExit(ThreadVars *tv, void *initdata, void **data)
138 SCLogError(SC_ERR_NO_AF_PACKET,"Error creating thread %s: you do not have "
139 "support for AF_PACKET enabled, on Linux host please recompile "
140 "with --enable-af-packet", tv->name);
144 #else /* We have AF_PACKET support */
146 #define AFP_IFACE_NAME_LENGTH 48
148 #define AFP_STATE_DOWN 0
149 #define AFP_STATE_UP 1
151 #define AFP_RECONNECT_TIMEOUT 500000
152 #define AFP_DOWN_COUNTER_INTERVAL 40
154 #define POLL_TIMEOUT 100
156 #ifndef TP_STATUS_USER_BUSY
157 /* for new use latest bit available in tp_status */
158 #define TP_STATUS_USER_BUSY (1 << 31)
161 #ifndef TP_STATUS_VLAN_VALID
162 #define TP_STATUS_VLAN_VALID (1 << 4)
165 /** protect pfring_set_bpf_filter, as it is not thread safe */
166 static SCMutex afpacket_bpf_set_filter_lock = SCMUTEX_INITIALIZER;
177 AFP_RECOVERABLE_ERROR,
181 struct tpacket2_hdr *h2;
186 * \brief Structure to hold thread specific variables.
188 typedef struct AFPThreadVars_
190 /* thread specific socket */
193 unsigned char afp_state;
195 /* data link type for the thread */
207 uint8_t *data; /** Per function and thread data */
208 int datalen; /** Length of per function and thread data */
212 char iface[AFP_IFACE_NAME_LENGTH];
219 /* socket buffer size */
222 ChecksumValidationMode checksum_mode;
225 char out_iface[AFP_IFACE_NAME_LENGTH];
229 uint16_t capture_kernel_packets;
230 uint16_t capture_kernel_drops;
238 struct tpacket_req req;
239 unsigned int tp_hdrlen;
240 unsigned int ring_buflen;
243 unsigned int frame_offset;
248 TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
249 TmEcode ReceiveAFPThreadInit(ThreadVars *, void *, void **);
250 void ReceiveAFPThreadExitStats(ThreadVars *, void *);
251 TmEcode ReceiveAFPThreadDeinit(ThreadVars *, void *);
252 TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot);
254 TmEcode DecodeAFPThreadInit(ThreadVars *, void *, void **);
255 TmEcode DecodeAFPThreadDeinit(ThreadVars *tv, void *data);
256 TmEcode DecodeAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
258 TmEcode AFPSetBPFFilter(AFPThreadVars *ptv);
259 static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose);
260 static int AFPGetDevFlags(int fd, const char *ifname);
261 static int AFPDerefSocket(AFPPeer* peer);
262 static int AFPRefSocket(AFPPeer* peer);
265 * \brief Registration Function for RecieveAFP.
266 * \todo Unit tests are needed for this module.
268 void TmModuleReceiveAFPRegister (void)
270 tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
271 tmm_modules[TMM_RECEIVEAFP].ThreadInit = ReceiveAFPThreadInit;
272 tmm_modules[TMM_RECEIVEAFP].Func = NULL;
273 tmm_modules[TMM_RECEIVEAFP].PktAcqLoop = ReceiveAFPLoop;
274 tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = ReceiveAFPThreadExitStats;
275 tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
276 tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
277 tmm_modules[TMM_RECEIVEAFP].cap_flags = SC_CAP_NET_RAW;
278 tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
283 * \defgroup afppeers AFP peers list
285 * AF_PACKET has an IPS mode were interface are peered: packet from
286 * on interface are sent the peered interface and the other way. The ::AFPPeer
287 * list is maitaining the list of peers. Each ::AFPPeer is storing the needed
288 * information to be able to send packet on the interface.
289 * A element of the list must not be destroyed during the run of Suricata as it
290 * is used by ::Packet and other threads.
295 typedef struct AFPPeersList_ {
296 TAILQ_HEAD(, AFPPeer_) peers; /**< Head of list of fragments. */
299 int turn; /**< Next value for initialisation order */
300 SC_ATOMIC_DECLARE(int, reached); /**< Counter used to synchronize start */
304 * \brief Update the peer.
306 * Update the AFPPeer of a thread ie set new state, socket number
310 void AFPPeerUpdate(AFPThreadVars *ptv)
312 if (ptv->mpeer == NULL) {
315 (void)SC_ATOMIC_SET(ptv->mpeer->if_idx, AFPGetIfnumByDev(ptv->socket, ptv->iface, 0));
316 (void)SC_ATOMIC_SET(ptv->mpeer->socket, ptv->socket);
317 (void)SC_ATOMIC_SET(ptv->mpeer->state, ptv->afp_state);
321 * \brief Clean and free ressource used by an ::AFPPeer
323 void AFPPeerClean(AFPPeer *peer)
325 if (peer->flags & AFP_SOCK_PROTECT)
326 SCMutexDestroy(&peer->sock_protect);
327 SC_ATOMIC_DESTROY(peer->socket);
328 SC_ATOMIC_DESTROY(peer->if_idx);
329 SC_ATOMIC_DESTROY(peer->state);
333 AFPPeersList peerslist;
337 * \brief Init the global list of ::AFPPeer
339 TmEcode AFPPeersListInit()
342 TAILQ_INIT(&peerslist.peers);
343 peerslist.peered = 0;
346 SC_ATOMIC_INIT(peerslist.reached);
347 (void) SC_ATOMIC_SET(peerslist.reached, 0);
348 SCReturnInt(TM_ECODE_OK);
352 * \brief Check that all ::AFPPeer got a peer
354 * \retval TM_ECODE_FAILED if some threads are not peered or TM_ECODE_OK else.
356 TmEcode AFPPeersListCheck()
358 #define AFP_PEERS_MAX_TRY 4
359 #define AFP_PEERS_WAIT 20000
362 while (try < AFP_PEERS_MAX_TRY) {
363 if (peerslist.cnt != peerslist.peered) {
364 usleep(AFP_PEERS_WAIT);
366 SCReturnInt(TM_ECODE_OK);
370 SCLogError(SC_ERR_AFP_CREATE, "Threads number not equals");
371 SCReturnInt(TM_ECODE_FAILED);
375 * \brief Declare a new AFP thread to AFP peers list.
377 TmEcode AFPPeersListAdd(AFPThreadVars *ptv)
380 AFPPeer *peer = SCMalloc(sizeof(AFPPeer));
384 if (unlikely(peer == NULL)) {
385 SCReturnInt(TM_ECODE_FAILED);
387 memset(peer, 0, sizeof(AFPPeer));
388 SC_ATOMIC_INIT(peer->socket);
389 SC_ATOMIC_INIT(peer->sock_usage);
390 SC_ATOMIC_INIT(peer->if_idx);
391 SC_ATOMIC_INIT(peer->state);
392 peer->flags = ptv->flags;
393 peer->turn = peerslist.turn++;
395 if (peer->flags & AFP_SOCK_PROTECT) {
396 SCMutexInit(&peer->sock_protect, NULL);
399 (void)SC_ATOMIC_SET(peer->sock_usage, 0);
400 (void)SC_ATOMIC_SET(peer->state, AFP_STATE_DOWN);
401 strlcpy(peer->iface, ptv->iface, AFP_IFACE_NAME_LENGTH);
403 /* add element to iface list */
404 TAILQ_INSERT_TAIL(&peerslist.peers, peer, next);
406 if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
409 /* Iter to find a peer */
410 TAILQ_FOREACH(pitem, &peerslist.peers, next) {
413 if (strcmp(pitem->iface, ptv->out_iface))
417 mtu = GetIfaceMTU(ptv->iface);
418 out_mtu = GetIfaceMTU(ptv->out_iface);
419 if (mtu != out_mtu) {
420 SCLogError(SC_ERR_AFP_CREATE,
421 "MTU on %s (%d) and %s (%d) are not equal, "
422 "transmission of packets bigger than %d will fail.",
424 ptv->out_iface, out_mtu,
425 (out_mtu > mtu) ? mtu : out_mtu);
427 peerslist.peered += 2;
434 SCReturnInt(TM_ECODE_OK);
437 int AFPPeersListWaitTurn(AFPPeer *peer)
439 /* If turn is zero, we already have started threads once */
440 if (peerslist.turn == 0)
443 if (peer->turn == SC_ATOMIC_GET(peerslist.reached))
448 void AFPPeersListReachedInc()
450 if (peerslist.turn == 0)
453 if (SC_ATOMIC_ADD(peerslist.reached, 1) == peerslist.turn) {
454 SCLogInfo("All AFP capture threads are running.");
455 (void)SC_ATOMIC_SET(peerslist.reached, 0);
456 /* Set turn to 0 to skip syncrhonization when ReceiveAFPLoop is
463 static int AFPPeersListStarted()
465 return !peerslist.turn;
469 * \brief Clean the global peers list.
471 void AFPPeersListClean()
475 while ((pitem = TAILQ_FIRST(&peerslist.peers))) {
476 TAILQ_REMOVE(&peerslist.peers, pitem, next);
486 * \brief Registration Function for DecodeAFP.
487 * \todo Unit tests are needed for this module.
489 void TmModuleDecodeAFPRegister (void)
491 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
492 tmm_modules[TMM_DECODEAFP].ThreadInit = DecodeAFPThreadInit;
493 tmm_modules[TMM_DECODEAFP].Func = DecodeAFP;
494 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
495 tmm_modules[TMM_DECODEAFP].ThreadDeinit = DecodeAFPThreadDeinit;
496 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
497 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
498 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
502 static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose);
504 static inline void AFPDumpCounters(AFPThreadVars *ptv)
506 #ifdef PACKET_STATISTICS
507 struct tpacket_stats kstats;
508 socklen_t len = sizeof (struct tpacket_stats);
509 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_STATISTICS,
510 &kstats, &len) > -1) {
511 SCLogDebug("(%s) Kernel: Packets %" PRIu32 ", dropped %" PRIu32 "",
513 kstats.tp_packets, kstats.tp_drops);
514 StatsAddUI64(ptv->tv, ptv->capture_kernel_packets, kstats.tp_packets);
515 StatsAddUI64(ptv->tv, ptv->capture_kernel_drops, kstats.tp_drops);
516 (void) SC_ATOMIC_ADD(ptv->livedev->drop, (uint64_t) kstats.tp_drops);
517 (void) SC_ATOMIC_ADD(ptv->livedev->pkts, (uint64_t) kstats.tp_packets);
523 * \brief AF packet read function.
525 * This function fills
526 * From here the packets are picked up by the DecodeAFP thread.
528 * \param user pointer to AFPThreadVars
529 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
531 int AFPRead(AFPThreadVars *ptv)
534 /* XXX should try to use read that get directly to packet */
537 struct sockaddr_ll from;
540 struct cmsghdr *cmsg;
543 char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
545 unsigned char aux_checksum = 0;
547 msg.msg_name = &from;
548 msg.msg_namelen = sizeof(from);
551 msg.msg_control = &cmsg_buf;
552 msg.msg_controllen = sizeof(cmsg_buf);
556 offset = SLL_HEADER_LEN;
559 iov.iov_len = ptv->datalen - offset;
560 iov.iov_base = ptv->data + offset;
562 caplen = recvmsg(ptv->socket, &msg, MSG_TRUNC);
565 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
567 SCReturnInt(AFP_READ_FAILURE);
570 p = PacketGetFromQueueOrAlloc();
572 SCReturnInt(AFP_FAILURE);
574 PKT_SET_SRC(p, PKT_SRC_WIRE);
576 /* get timestamp of packet via ioctl */
577 if (ioctl(ptv->socket, SIOCGSTAMP, &p->ts) == -1) {
578 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
580 TmqhOutputPacketpool(ptv->tv, p);
581 SCReturnInt(AFP_READ_FAILURE);
585 ptv->bytes += caplen + offset;
586 p->livedev = ptv->livedev;
588 /* add forged header */
590 SllHdr * hdrp = (SllHdr *)ptv->data;
591 /* XXX this is minimalist, but this seems enough */
592 hdrp->sll_protocol = from.sll_protocol;
595 p->datalink = ptv->datalink;
596 SET_PKT_LEN(p, caplen + offset);
597 if (PacketCopyData(p, ptv->data, GET_PKT_LEN(p)) == -1) {
598 TmqhOutputPacketpool(ptv->tv, p);
599 SCReturnInt(AFP_FAILURE);
601 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
602 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
604 /* We only check for checksum disable */
605 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
606 p->flags |= PKT_IGNORE_CHECKSUM;
607 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
608 if (ptv->livedev->ignore_checksum) {
609 p->flags |= PKT_IGNORE_CHECKSUM;
610 } else if (ChecksumAutoModeCheck(ptv->pkts,
611 SC_ATOMIC_GET(ptv->livedev->pkts),
612 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
613 ptv->livedev->ignore_checksum = 1;
614 p->flags |= PKT_IGNORE_CHECKSUM;
620 /* List is NULL if we don't have activated auxiliary data */
621 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
622 struct tpacket_auxdata *aux;
624 if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
625 cmsg->cmsg_level != SOL_PACKET ||
626 cmsg->cmsg_type != PACKET_AUXDATA)
629 aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
631 if (aux_checksum && (aux->tp_status & TP_STATUS_CSUMNOTREADY)) {
632 p->flags |= PKT_IGNORE_CHECKSUM;
637 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
638 TmqhOutputPacketpool(ptv->tv, p);
639 SCReturnInt(AFP_FAILURE);
641 SCReturnInt(AFP_READ_OK);
644 TmEcode AFPWritePacket(Packet *p)
646 struct sockaddr_ll socket_address;
649 if (p->afp_v.copy_mode == AFP_COPY_MODE_IPS) {
650 if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
655 if (SC_ATOMIC_GET(p->afp_v.peer->state) == AFP_STATE_DOWN)
658 if (p->ethh == NULL) {
659 SCLogWarning(SC_ERR_INVALID_VALUE, "Should have an Ethernet header");
660 return TM_ECODE_FAILED;
662 /* Index of the network device */
663 socket_address.sll_ifindex = SC_ATOMIC_GET(p->afp_v.peer->if_idx);
665 socket_address.sll_halen = ETH_ALEN;
666 /* Destination MAC */
667 memcpy(socket_address.sll_addr, p->ethh, 6);
669 /* Send packet, locking the socket if necessary */
670 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
671 SCMutexLock(&p->afp_v.peer->sock_protect);
672 socket = SC_ATOMIC_GET(p->afp_v.peer->socket);
673 if (sendto(socket, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,
674 (struct sockaddr*) &socket_address,
675 sizeof(struct sockaddr_ll)) < 0) {
676 SCLogWarning(SC_ERR_SOCKET, "Sending packet failed on socket %d: %s",
679 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
680 SCMutexUnlock(&p->afp_v.peer->sock_protect);
681 return TM_ECODE_FAILED;
683 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
684 SCMutexUnlock(&p->afp_v.peer->sock_protect);
689 void AFPReleaseDataFromRing(Packet *p)
691 /* Need to be in copy mode and need to detect early release
692 where Ethernet header could not be set (and pseudo packet) */
693 if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
697 if (AFPDerefSocket(p->afp_v.mpeer) == 0)
700 if (p->afp_v.relptr) {
702 h.raw = p->afp_v.relptr;
703 h.h2->tp_status = TP_STATUS_KERNEL;
707 AFPV_CLEANUP(&p->afp_v);
710 void AFPReleasePacket(Packet *p)
712 AFPReleaseDataFromRing(p);
713 PacketFreeOrRelease(p);
717 * \brief AF packet read function for ring
719 * This function fills
720 * From here the packets are picked up by the DecodeAFP thread.
722 * \param user pointer to AFPThreadVars
723 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
725 int AFPReadFromRing(AFPThreadVars *ptv)
729 struct sockaddr_ll *from;
730 uint8_t emergency_flush = 0;
735 /* Loop till we have packets available */
737 if (unlikely(suricata_ctl_flags != 0)) {
741 /* Read packet from ring */
742 h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
744 SCReturnInt(AFP_FAILURE);
747 if ((! h.h2->tp_status) || (h.h2->tp_status & TP_STATUS_USER_BUSY)) {
748 if (read_pkts == 0) {
749 if (loop_start == -1) {
750 loop_start = ptv->frame_offset;
751 } else if (unlikely(loop_start == (int)ptv->frame_offset)) {
752 SCReturnInt(AFP_READ_OK);
754 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
755 ptv->frame_offset = 0;
759 if ((emergency_flush) && (ptv->flags & AFP_EMERGENCY_MODE)) {
760 SCReturnInt(AFP_KERNEL_DROP);
762 SCReturnInt(AFP_READ_OK);
769 /* Our packet is still used by suricata, we exit read loop to
771 if (h.h2->tp_status & TP_STATUS_USER_BUSY) {
772 SCReturnInt(AFP_READ_OK);
775 if ((ptv->flags & AFP_EMERGENCY_MODE) && (emergency_flush == 1)) {
776 h.h2->tp_status = TP_STATUS_KERNEL;
780 p = PacketGetFromQueueOrAlloc();
782 SCReturnInt(AFP_FAILURE);
784 PKT_SET_SRC(p, PKT_SRC_WIRE);
786 /* Suricata will treat packet so telling it is busy, this
787 * status will be reset to 0 (ie TP_STATUS_KERNEL) in the release
789 h.h2->tp_status |= TP_STATUS_USER_BUSY;
791 from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
794 ptv->bytes += h.h2->tp_len;
795 p->livedev = ptv->livedev;
797 /* add forged header */
799 SllHdr * hdrp = (SllHdr *)ptv->data;
800 /* XXX this is minimalist, but this seems enough */
801 hdrp->sll_protocol = from->sll_protocol;
804 p->datalink = ptv->datalink;
805 if (h.h2->tp_len > h.h2->tp_snaplen) {
806 SCLogDebug("Packet length (%d) > snaplen (%d), truncating",
807 h.h2->tp_len, h.h2->tp_snaplen);
810 /* get vlan id from header */
811 if ((!ptv->vlan_disabled) &&
812 (h.h2->tp_status & TP_STATUS_VLAN_VALID || h.h2->tp_vlan_tci)) {
813 p->vlan_id[0] = h.h2->tp_vlan_tci;
818 if (ptv->flags & AFP_ZERO_COPY) {
819 if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
820 TmqhOutputPacketpool(ptv->tv, p);
821 SCReturnInt(AFP_FAILURE);
823 p->afp_v.relptr = h.raw;
824 p->ReleasePacket = AFPReleasePacket;
825 p->afp_v.mpeer = ptv->mpeer;
826 AFPRefSocket(ptv->mpeer);
828 p->afp_v.copy_mode = ptv->copy_mode;
829 if (p->afp_v.copy_mode != AFP_COPY_MODE_NONE) {
830 p->afp_v.peer = ptv->mpeer->peer;
832 p->afp_v.peer = NULL;
836 if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
837 TmqhOutputPacketpool(ptv->tv, p);
838 SCReturnInt(AFP_FAILURE);
842 p->ts.tv_sec = h.h2->tp_sec;
843 p->ts.tv_usec = h.h2->tp_nsec/1000;
844 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
845 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
847 /* We only check for checksum disable */
848 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
849 p->flags |= PKT_IGNORE_CHECKSUM;
850 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
851 if (ptv->livedev->ignore_checksum) {
852 p->flags |= PKT_IGNORE_CHECKSUM;
853 } else if (ChecksumAutoModeCheck(ptv->pkts,
854 SC_ATOMIC_GET(ptv->livedev->pkts),
855 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
856 ptv->livedev->ignore_checksum = 1;
857 p->flags |= PKT_IGNORE_CHECKSUM;
860 if (h.h2->tp_status & TP_STATUS_CSUMNOTREADY) {
861 p->flags |= PKT_IGNORE_CHECKSUM;
864 if (h.h2->tp_status & TP_STATUS_LOSING) {
866 AFPDumpCounters(ptv);
869 /* release frame if not in zero copy mode */
870 if (!(ptv->flags & AFP_ZERO_COPY)) {
871 h.h2->tp_status = TP_STATUS_KERNEL;
874 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
875 h.h2->tp_status = TP_STATUS_KERNEL;
876 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
877 ptv->frame_offset = 0;
879 TmqhOutputPacketpool(ptv->tv, p);
880 SCReturnInt(AFP_FAILURE);
884 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
885 ptv->frame_offset = 0;
886 /* Get out of loop to be sure we will reach maintenance tasks */
887 SCReturnInt(AFP_READ_OK);
891 SCReturnInt(AFP_READ_OK);
895 * \brief Reference socket
897 * \retval O in case of failure, 1 in case of success
899 static int AFPRefSocket(AFPPeer* peer)
901 if (unlikely(peer == NULL))
904 (void)SC_ATOMIC_ADD(peer->sock_usage, 1);
910 * \brief Dereference socket
912 * \retval 1 if socket is still alive, 0 if not
914 static int AFPDerefSocket(AFPPeer* peer)
919 if (SC_ATOMIC_SUB(peer->sock_usage, 1) == 0) {
920 if (SC_ATOMIC_GET(peer->state) == AFP_STATE_DOWN) {
921 SCLogInfo("Cleaning socket connected to '%s'", peer->iface);
922 close(SC_ATOMIC_GET(peer->socket));
929 void AFPSwitchState(AFPThreadVars *ptv, int state)
931 ptv->afp_state = state;
936 /* Do cleaning if switching to down state */
937 if (state == AFP_STATE_DOWN) {
938 if (ptv->frame_buf) {
939 /* only used in reading phase, we can free it */
940 SCFree(ptv->frame_buf);
941 ptv->frame_buf = NULL;
943 if (ptv->socket != -1) {
944 /* we need to wait for all packets to return data */
945 if (SC_ATOMIC_SUB(ptv->mpeer->sock_usage, 1) == 0) {
946 SCLogInfo("Cleaning socket connected to '%s'", ptv->iface);
952 if (state == AFP_STATE_UP) {
953 (void)SC_ATOMIC_SET(ptv->mpeer->sock_usage, 1);
957 static int AFPReadAndDiscard(AFPThreadVars *ptv, struct timeval *synctv)
959 struct sockaddr_ll from;
965 char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
969 if (unlikely(suricata_ctl_flags != 0)) {
973 msg.msg_name = &from;
974 msg.msg_namelen = sizeof(from);
977 msg.msg_control = &cmsg_buf;
978 msg.msg_controllen = sizeof(cmsg_buf);
981 iov.iov_len = ptv->datalen;
982 iov.iov_base = ptv->data;
984 recvmsg(ptv->socket, &msg, MSG_TRUNC);
986 if (ioctl(ptv->socket, SIOCGSTAMP, &ts) == -1) {
991 if ((ts.tv_sec > synctv->tv_sec) ||
992 (ts.tv_sec >= synctv->tv_sec &&
993 ts.tv_usec > synctv->tv_usec)) {
999 static int AFPReadAndDiscardFromRing(AFPThreadVars *ptv, struct timeval *synctv)
1003 if (unlikely(suricata_ctl_flags != 0)) {
1007 /* Read packet from ring */
1008 h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
1009 if (h.raw == NULL) {
1013 if (((time_t)h.h2->tp_sec > synctv->tv_sec) ||
1014 ((time_t)h.h2->tp_sec == synctv->tv_sec &&
1015 (suseconds_t) (h.h2->tp_nsec / 1000) > synctv->tv_usec)) {
1019 h.h2->tp_status = TP_STATUS_KERNEL;
1020 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
1021 ptv->frame_offset = 0;
1028 /** \brief wait for all afpacket threads to fully init
1030 * Discard packets before all threads are ready, as the cluster
1031 * setup is not complete yet.
1033 * if AFPPeersListStarted() returns true init is complete
1035 * \retval r 1 = happy, otherwise unhappy
1037 static int AFPSynchronizeStart(AFPThreadVars *ptv)
1040 struct timeval synctv;
1043 fds.fd = ptv->socket;
1044 fds.events = POLLIN;
1046 /* Set timeval to end of the world */
1047 synctv.tv_sec = 0xffffffff;
1048 synctv.tv_usec = 0xffffffff;
1051 r = poll(&fds, 1, POLL_TIMEOUT);
1053 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1054 SCLogWarning(SC_ERR_AFP_READ, "poll failed %02x",
1055 fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL));
1058 if (AFPPeersListStarted() && synctv.tv_sec == (time_t) 0xffffffff) {
1059 gettimeofday(&synctv, NULL);
1061 if (ptv->flags & AFP_RING_MODE) {
1062 r = AFPReadAndDiscardFromRing(ptv, &synctv);
1064 r = AFPReadAndDiscard(ptv, &synctv);
1066 SCLogDebug("Discarding on %s", ptv->tv->name);
1069 SCLogInfo("Starting to read on %s", ptv->tv->name);
1075 } else if (r == 0 && AFPPeersListStarted()) {
1076 SCLogDebug("Starting to read on %s", ptv->tv->name);
1078 } else if (r < 0) { /* only exit on error */
1079 SCLogWarning(SC_ERR_AFP_READ, "poll failed with retval %d", r);
1087 * \brief Try to reopen socket
1089 * \retval 0 in case of success, negative if error occurs or a condition
1092 static int AFPTryReopen(AFPThreadVars *ptv)
1099 /* Don't reconnect till we have packet that did not release data */
1100 if (SC_ATOMIC_GET(ptv->mpeer->sock_usage) != 0) {
1104 afp_activate_r = AFPCreateSocket(ptv, ptv->iface, 0);
1105 if (afp_activate_r != 0) {
1106 if (ptv->down_count % AFP_DOWN_COUNTER_INTERVAL == 0) {
1107 SCLogWarning(SC_ERR_AFP_CREATE, "Can not open iface '%s'",
1110 return afp_activate_r;
1113 SCLogInfo("Interface '%s' is back", ptv->iface);
1118 * \brief Main AF_PACKET reading Loop function
1120 TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
1124 AFPThreadVars *ptv = (AFPThreadVars *)data;
1127 TmSlot *s = (TmSlot *)slot;
1128 time_t last_dump = 0;
1129 struct timeval current_time;
1131 ptv->slot = s->slot_next;
1133 if (ptv->afp_state == AFP_STATE_DOWN) {
1134 /* Wait for our turn, threads before us must have opened the socket */
1135 while (AFPPeersListWaitTurn(ptv->mpeer)) {
1137 if (suricata_ctl_flags != 0) {
1141 r = AFPCreateSocket(ptv, ptv->iface, 1);
1144 case AFP_FATAL_ERROR:
1145 SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket, fatal error");
1146 /* fatal is fatal, we want suri to exit */
1148 //tv->aof = THV_ENGINE_EXIT;
1149 SCReturnInt(TM_ECODE_FAILED);
1150 case AFP_RECOVERABLE_ERROR:
1151 SCLogWarning(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket, retrying soon");
1154 AFPPeersListReachedInc();
1156 if (ptv->afp_state == AFP_STATE_UP) {
1157 SCLogDebug("Thread %s using socket %d", tv->name, ptv->socket);
1158 AFPSynchronizeStart(ptv);
1161 fds.fd = ptv->socket;
1162 fds.events = POLLIN;
1165 /* Start by checking the state of our interface */
1166 if (unlikely(ptv->afp_state == AFP_STATE_DOWN)) {
1170 usleep(AFP_RECONNECT_TIMEOUT);
1171 if (suricata_ctl_flags != 0) {
1175 r = AFPTryReopen(ptv);
1176 fds.fd = ptv->socket;
1182 /* make sure we have at least one packet in the packet pool, to prevent
1183 * us from alloc'ing packets at line rate */
1186 r = poll(&fds, 1, POLL_TIMEOUT);
1188 if (suricata_ctl_flags != 0) {
1193 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1194 if (fds.revents & (POLLHUP | POLLRDHUP)) {
1195 AFPSwitchState(ptv, AFP_STATE_DOWN);
1197 } else if (fds.revents & POLLERR) {
1199 /* Do a recv to get errno */
1200 if (recv(ptv->socket, &c, sizeof c, MSG_PEEK) != -1)
1201 continue; /* what, no error? */
1202 SCLogError(SC_ERR_AFP_READ,
1203 "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1204 ptv->iface, errno, strerror(errno));
1205 AFPSwitchState(ptv, AFP_STATE_DOWN);
1207 } else if (fds.revents & POLLNVAL) {
1208 SCLogError(SC_ERR_AFP_READ, "Invalid polling request");
1209 AFPSwitchState(ptv, AFP_STATE_DOWN);
1213 if (ptv->flags & AFP_RING_MODE) {
1214 r = AFPReadFromRing(ptv);
1216 /* AFPRead will call TmThreadsSlotProcessPkt on read packets */
1220 case AFP_READ_FAILURE:
1221 /* AFPRead in error: best to reset the socket */
1222 SCLogError(SC_ERR_AFP_READ,
1223 "AFPRead error reading data from iface '%s': (%d" PRIu32 ") %s",
1224 ptv->iface, errno, strerror(errno));
1225 AFPSwitchState(ptv, AFP_STATE_DOWN);
1228 AFPSwitchState(ptv, AFP_STATE_DOWN);
1229 SCReturnInt(TM_ECODE_FAILED);
1232 /* Trigger one dump of stats every second */
1233 TimeGet(¤t_time);
1234 if (current_time.tv_sec != last_dump) {
1235 AFPDumpCounters(ptv);
1236 last_dump = current_time.tv_sec;
1239 case AFP_KERNEL_DROP:
1240 AFPDumpCounters(ptv);
1243 } else if ((r < 0) && (errno != EINTR)) {
1244 SCLogError(SC_ERR_AFP_READ, "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1246 errno, strerror(errno));
1247 AFPSwitchState(ptv, AFP_STATE_DOWN);
1250 StatsSyncCountersIfSignalled(tv);
1253 AFPDumpCounters(ptv);
1254 StatsSyncCountersIfSignalled(tv);
1255 SCReturnInt(TM_ECODE_OK);
1258 static int AFPGetDevFlags(int fd, const char *ifname)
1262 memset(&ifr, 0, sizeof(ifr));
1263 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1265 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
1266 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1267 ifname, strerror(errno));
1271 return ifr.ifr_flags;
1275 static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose)
1279 memset(&ifr, 0, sizeof(ifr));
1280 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1282 if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
1284 SCLogError(SC_ERR_AFP_CREATE, "Unable to find iface %s: %s",
1285 ifname, strerror(errno));
1289 return ifr.ifr_ifindex;
1292 static int AFPGetDevLinktype(int fd, const char *ifname)
1296 memset(&ifr, 0, sizeof(ifr));
1297 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1299 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
1300 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1301 ifname, strerror(errno));
1305 switch (ifr.ifr_hwaddr.sa_family) {
1306 case ARPHRD_LOOPBACK:
1307 return LINKTYPE_ETHERNET;
1309 return LINKTYPE_RAW;
1311 return ifr.ifr_hwaddr.sa_family;
1315 static int AFPComputeRingParams(AFPThreadVars *ptv, int order)
1317 /* Compute structure:
1318 Target is to store all pending packets
1319 with a size equal to MTU + auxdata
1320 And we keep a decent number of block
1323 Compute frame_size (aligned to be able to fit in block
1324 Check which block size we need. Blocksize is a 2^n * pagesize
1325 We then need to get order, big enough to have
1326 frame_size < block size
1327 Find number of frame per block (divide)
1331 described in packet_mmap.txt
1332 dependant on snaplen (need to use a variable ?)
1334 tp_hdrlen determine_version in daq_afpacket
1335 in V1: sizeof(struct tpacket_hdr);
1336 in V2: val in getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len)
1337 frame size: TPACKET_ALIGN(snaplen + TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1340 int tp_hdrlen = sizeof(struct tpacket_hdr);
1341 int snaplen = default_packet_size;
1344 snaplen = GetIfaceMaxPacketSize(ptv->iface);
1346 SCLogWarning(SC_ERR_INVALID_VALUE,
1347 "Unable to get MTU, setting snaplen to sane default of 1514");
1352 ptv->req.tp_frame_size = TPACKET_ALIGN(snaplen +TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1353 ptv->req.tp_block_size = getpagesize() << order;
1354 int frames_per_block = ptv->req.tp_block_size / ptv->req.tp_frame_size;
1355 if (frames_per_block == 0) {
1356 SCLogInfo("frame size to big");
1359 ptv->req.tp_frame_nr = ptv->ring_size;
1360 ptv->req.tp_block_nr = ptv->req.tp_frame_nr / frames_per_block + 1;
1361 /* exact division */
1362 ptv->req.tp_frame_nr = ptv->req.tp_block_nr * frames_per_block;
1363 SCLogInfo("AF_PACKET RX Ring params: block_size=%d block_nr=%d frame_size=%d frame_nr=%d",
1364 ptv->req.tp_block_size, ptv->req.tp_block_nr,
1365 ptv->req.tp_frame_size, ptv->req.tp_frame_nr);
1369 static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
1372 int ret = AFP_FATAL_ERROR;
1373 struct packet_mreq sock_params;
1374 struct sockaddr_ll bind_address;
1380 ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1381 if (ptv->socket == -1) {
1382 SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
1385 if_idx = AFPGetIfnumByDev(ptv->socket, devname, verbose);
1387 memset(&bind_address, 0, sizeof(bind_address));
1388 bind_address.sll_family = AF_PACKET;
1389 bind_address.sll_protocol = htons(ETH_P_ALL);
1390 bind_address.sll_ifindex = if_idx;
1391 if (bind_address.sll_ifindex == -1) {
1393 SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
1394 ret = AFP_RECOVERABLE_ERROR;
1398 if (ptv->promisc != 0) {
1399 /* Force promiscuous mode */
1400 memset(&sock_params, 0, sizeof(sock_params));
1401 sock_params.mr_type = PACKET_MR_PROMISC;
1402 sock_params.mr_ifindex = bind_address.sll_ifindex;
1403 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(void *)&sock_params, sizeof(sock_params));
1405 SCLogError(SC_ERR_AFP_CREATE,
1406 "Couldn't switch iface %s to promiscuous, error %s",
1407 devname, strerror(errno));
1412 if (ptv->checksum_mode == CHECKSUM_VALIDATION_KERNEL) {
1414 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_AUXDATA, &val,
1415 sizeof(val)) == -1 && errno != ENOPROTOOPT) {
1416 SCLogWarning(SC_ERR_NO_AF_PACKET,
1417 "'kernel' checksum mode not supported, failling back to full mode.");
1418 ptv->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
1422 /* set socket recv buffer size */
1423 if (ptv->buffer_size != 0) {
1425 * Set the socket buffer size to the specified value.
1427 SCLogInfo("Setting AF_PACKET socket buffer to %d", ptv->buffer_size);
1428 if (setsockopt(ptv->socket, SOL_SOCKET, SO_RCVBUF,
1430 sizeof(ptv->buffer_size)) == -1) {
1431 SCLogError(SC_ERR_AFP_CREATE,
1432 "Couldn't set buffer size to %d on iface %s, error %s",
1433 ptv->buffer_size, devname, strerror(errno));
1438 r = bind(ptv->socket, (struct sockaddr *)&bind_address, sizeof(bind_address));
1441 if (errno == ENETDOWN) {
1442 SCLogError(SC_ERR_AFP_CREATE,
1443 "Couldn't bind AF_PACKET socket, iface %s is down",
1446 SCLogError(SC_ERR_AFP_CREATE,
1447 "Couldn't bind AF_PACKET socket to iface %s, error %s",
1448 devname, strerror(errno));
1451 ret = AFP_RECOVERABLE_ERROR;
1455 #ifdef HAVE_PACKET_FANOUT
1456 /* add binded socket to fanout group */
1457 if (ptv->threads > 1) {
1458 uint32_t option = 0;
1459 uint16_t mode = ptv->cluster_type;
1460 uint16_t id = ptv->cluster_id;
1461 option = (mode << 16) | (id & 0xffff);
1462 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
1464 SCLogError(SC_ERR_AFP_CREATE,
1465 "Coudn't set fanout mode, error %s",
1472 int if_flags = AFPGetDevFlags(ptv->socket, ptv->iface);
1473 if (if_flags == -1) {
1475 SCLogError(SC_ERR_AFP_READ,
1476 "Can not acces to interface '%s'",
1479 ret = AFP_RECOVERABLE_ERROR;
1482 if ((if_flags & IFF_UP) == 0) {
1484 SCLogError(SC_ERR_AFP_READ,
1485 "Interface '%s' is down",
1488 ret = AFP_RECOVERABLE_ERROR;
1492 if (ptv->flags & AFP_RING_MODE) {
1493 int val = TPACKET_V2;
1494 unsigned int len = sizeof(val);
1495 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
1496 if (errno == ENOPROTOOPT) {
1497 SCLogError(SC_ERR_AFP_CREATE,
1498 "Too old kernel giving up (need 2.6.27 at least)");
1500 SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len");
1503 ptv->tp_hdrlen = val;
1506 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val,
1508 SCLogError(SC_ERR_AFP_CREATE,
1509 "Can't activate TPACKET_V2 on packet socket: %s",
1514 /* Allocate RX ring */
1515 #define DEFAULT_ORDER 3
1516 for (order = DEFAULT_ORDER; order >= 0; order--) {
1517 if (AFPComputeRingParams(ptv, order) != 1) {
1518 SCLogInfo("Ring parameter are incorrect. Please correct the devel");
1521 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, (void *) &ptv->req, sizeof(ptv->req));
1523 if (errno == ENOMEM) {
1524 SCLogInfo("Memory issue with ring parameters. Retrying.");
1527 SCLogError(SC_ERR_MEM_ALLOC,
1528 "Unable to allocate RX Ring for iface %s: (%d) %s",
1539 SCLogError(SC_ERR_MEM_ALLOC,
1540 "Unable to allocate RX Ring for iface %s (order 0 failed)",
1545 /* Allocate the Ring */
1546 ptv->ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
1547 ptv->ring_buf = mmap(0, ptv->ring_buflen, PROT_READ|PROT_WRITE,
1548 MAP_SHARED, ptv->socket, 0);
1549 if (ptv->ring_buf == MAP_FAILED) {
1550 SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap");
1553 /* allocate a ring for each frame header pointer*/
1554 ptv->frame_buf = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *));
1555 if (ptv->frame_buf == NULL) {
1556 SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf");
1559 memset(ptv->frame_buf, 0, ptv->req.tp_frame_nr * sizeof (union thdr *));
1560 /* fill the header ring with proper frame ptr*/
1561 ptv->frame_offset = 0;
1562 for (i = 0; i < ptv->req.tp_block_nr; ++i) {
1563 void *base = &ptv->ring_buf[i * ptv->req.tp_block_size];
1565 for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
1566 (((union thdr **)ptv->frame_buf)[ptv->frame_offset]) = base;
1567 base += ptv->req.tp_frame_size;
1570 ptv->frame_offset = 0;
1573 SCLogDebug("Using interface '%s' via socket %d", (char *)devname, ptv->socket);
1575 ptv->datalink = AFPGetDevLinktype(ptv->socket, ptv->iface);
1576 switch (ptv->datalink) {
1584 rc = AFPSetBPFFilter(ptv);
1585 if (rc == TM_ECODE_FAILED) {
1586 SCLogError(SC_ERR_AFP_CREATE, "Set AF_PACKET bpf filter \"%s\" failed.", ptv->bpf_filter);
1591 AFPSwitchState(ptv, AFP_STATE_UP);
1596 SCFree(ptv->frame_buf);
1598 /* Packet mmap does the cleaning when socket is closed */
1606 TmEcode AFPSetBPFFilter(AFPThreadVars *ptv)
1608 struct bpf_program filter;
1609 struct sock_fprog fcode;
1612 if (!ptv->bpf_filter)
1615 SCMutexLock(&afpacket_bpf_set_filter_lock);
1617 SCLogInfo("Using BPF '%s' on iface '%s'",
1620 if (pcap_compile_nopcap(default_packet_size, /* snaplen_arg */
1621 ptv->datalink, /* linktype_arg */
1622 &filter, /* program */
1623 ptv->bpf_filter, /* const char *buf */
1627 SCLogError(SC_ERR_AFP_CREATE, "Filter compilation failed.");
1628 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1629 return TM_ECODE_FAILED;
1631 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1633 if (filter.bf_insns == NULL) {
1634 SCLogError(SC_ERR_AFP_CREATE, "Filter badly setup.");
1635 return TM_ECODE_FAILED;
1638 fcode.len = filter.bf_len;
1639 fcode.filter = (struct sock_filter*)filter.bf_insns;
1641 rc = setsockopt(ptv->socket, SOL_SOCKET, SO_ATTACH_FILTER, &fcode, sizeof(fcode));
1644 SCLogError(SC_ERR_AFP_CREATE, "Failed to attach filter: %s", strerror(errno));
1645 return TM_ECODE_FAILED;
1653 * \brief Init function for ReceiveAFP.
1655 * \param tv pointer to ThreadVars
1656 * \param initdata pointer to the interface passed from the user
1657 * \param data pointer gets populated with AFPThreadVars
1659 * \todo Create a general AFP setup function.
1661 TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
1664 AFPIfaceConfig *afpconfig = initdata;
1666 if (initdata == NULL) {
1667 SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL");
1668 SCReturnInt(TM_ECODE_FAILED);
1671 AFPThreadVars *ptv = SCMalloc(sizeof(AFPThreadVars));
1672 if (unlikely(ptv == NULL)) {
1673 afpconfig->DerefFunc(afpconfig);
1674 SCReturnInt(TM_ECODE_FAILED);
1676 memset(ptv, 0, sizeof(AFPThreadVars));
1681 strlcpy(ptv->iface, afpconfig->iface, AFP_IFACE_NAME_LENGTH);
1682 ptv->iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
1684 ptv->livedev = LiveGetDevice(ptv->iface);
1685 if (ptv->livedev == NULL) {
1686 SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device");
1688 SCReturnInt(TM_ECODE_FAILED);
1691 ptv->buffer_size = afpconfig->buffer_size;
1692 ptv->ring_size = afpconfig->ring_size;
1694 ptv->promisc = afpconfig->promisc;
1695 ptv->checksum_mode = afpconfig->checksum_mode;
1696 ptv->bpf_filter = NULL;
1699 #ifdef HAVE_PACKET_FANOUT
1700 ptv->cluster_type = PACKET_FANOUT_LB;
1701 ptv->cluster_id = 1;
1702 /* We only set cluster info if the number of reader threads is greater than 1 */
1703 if (afpconfig->threads > 1) {
1704 ptv->cluster_id = afpconfig->cluster_id;
1705 ptv->cluster_type = afpconfig->cluster_type;
1706 ptv->threads = afpconfig->threads;
1709 ptv->flags = afpconfig->flags;
1711 if (afpconfig->bpf_filter) {
1712 ptv->bpf_filter = afpconfig->bpf_filter;
1715 #ifdef PACKET_STATISTICS
1716 ptv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets",
1718 ptv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops",
1722 ptv->copy_mode = afpconfig->copy_mode;
1723 if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
1724 strlcpy(ptv->out_iface, afpconfig->out_iface, AFP_IFACE_NAME_LENGTH);
1725 ptv->out_iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
1726 /* Warn about BPF filter consequence */
1727 if (ptv->bpf_filter) {
1728 SCLogWarning(SC_WARN_UNCOMMON, "Enabling a BPF filter in IPS mode result"
1729 " in dropping all non matching packets.");
1734 if (AFPPeersListAdd(ptv) == TM_ECODE_FAILED) {
1736 afpconfig->DerefFunc(afpconfig);
1737 SCReturnInt(TM_ECODE_FAILED);
1740 #define T_DATA_SIZE 70000
1741 ptv->data = SCMalloc(T_DATA_SIZE);
1742 if (ptv->data == NULL) {
1743 afpconfig->DerefFunc(afpconfig);
1745 SCReturnInt(TM_ECODE_FAILED);
1747 ptv->datalen = T_DATA_SIZE;
1750 *data = (void *)ptv;
1752 afpconfig->DerefFunc(afpconfig);
1754 /* A bit strange to have this here but we only have vlan information
1755 * during reading so we need to know if we want to keep vlan during
1756 * the capture phase */
1758 if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
1759 ptv->vlan_disabled = 1;
1762 /* If kernel is older than 3.0, VLAN is not stripped so we don't
1763 * get the info from packet extended header but we will use a standard
1764 * parsing of packet data (See Linux commit bcc6d47903612c3861201cc3a866fb604f26b8b2) */
1765 if (! SCKernelVersionIsAtLeast(3, 0)) {
1766 ptv->vlan_disabled = 1;
1769 SCReturnInt(TM_ECODE_OK);
1773 * \brief This function prints stats to the screen at exit.
1774 * \param tv pointer to ThreadVars
1775 * \param data pointer that gets cast into AFPThreadVars for ptv
1777 void ReceiveAFPThreadExitStats(ThreadVars *tv, void *data)
1780 AFPThreadVars *ptv = (AFPThreadVars *)data;
1782 #ifdef PACKET_STATISTICS
1783 AFPDumpCounters(ptv);
1784 SCLogInfo("(%s) Kernel: Packets %" PRIu64 ", dropped %" PRIu64 "",
1786 StatsGetLocalCounterValue(tv, ptv->capture_kernel_packets),
1787 StatsGetLocalCounterValue(tv, ptv->capture_kernel_drops));
1790 SCLogInfo("(%s) Packets %" PRIu64 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes);
1794 * \brief DeInit function closes af packet socket at exit.
1795 * \param tv pointer to ThreadVars
1796 * \param data pointer that gets cast into AFPThreadVars for ptv
1798 TmEcode ReceiveAFPThreadDeinit(ThreadVars *tv, void *data)
1800 AFPThreadVars *ptv = (AFPThreadVars *)data;
1802 AFPSwitchState(ptv, AFP_STATE_DOWN);
1804 if (ptv->data != NULL) {
1810 ptv->bpf_filter = NULL;
1812 SCReturnInt(TM_ECODE_OK);
1816 * \brief This function passes off to link type decoders.
1818 * DecodeAFP reads packets from the PacketQueue and passes
1819 * them off to the proper link type decoder.
1821 * \param t pointer to ThreadVars
1822 * \param p pointer to the current packet
1823 * \param data pointer that gets cast into AFPThreadVars for ptv
1824 * \param pq pointer to the current PacketQueue
1826 TmEcode DecodeAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
1829 DecodeThreadVars *dtv = (DecodeThreadVars *)data;
1831 /* XXX HACK: flow timeout can call us for injected pseudo packets
1832 * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */
1833 if (p->flags & PKT_PSEUDO_STREAM_END)
1836 /* update counters */
1837 DecodeUpdatePacketCounters(tv, dtv, p);
1839 /* If suri has set vlan during reading, we increase vlan counter */
1841 StatsIncr(tv, dtv->counter_vlan);
1844 /* call the decoder */
1845 switch (p->datalink) {
1846 case LINKTYPE_ETHERNET:
1847 DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1849 case LINKTYPE_LINUX_SLL:
1850 DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1853 DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1856 DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1859 DecodeNull(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1862 SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeAFP", p->datalink);
1866 PacketDecodeFinalize(tv, dtv, p);
1868 SCReturnInt(TM_ECODE_OK);
1871 TmEcode DecodeAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
1874 DecodeThreadVars *dtv = NULL;
1876 dtv = DecodeThreadVarsAlloc(tv);
1879 SCReturnInt(TM_ECODE_FAILED);
1881 DecodeRegisterPerfCounters(dtv, tv);
1883 *data = (void *)dtv;
1885 #ifdef __SC_CUDA_SUPPORT__
1886 if (CudaThreadVarsInit(&dtv->cuda_vars) < 0)
1887 SCReturnInt(TM_ECODE_FAILED);
1890 SCReturnInt(TM_ECODE_OK);
1893 TmEcode DecodeAFPThreadDeinit(ThreadVars *tv, void *data)
1896 DecodeThreadVarsFree(tv, data);
1897 SCReturnInt(TM_ECODE_OK);
1900 #endif /* HAVE_AF_PACKET */