]> git.ipfire.org Git - people/ms/suricata.git/blame - src/source-af-packet.c
af-packet: fix livedev packets counter
[people/ms/suricata.git] / src / source-af-packet.c
CommitLineData
b076a26c 1/* Copyright (C) 2011-2013 Open Information Security Foundation
c45d8985
EL
2 *
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
5 * Software Foundation.
6 *
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.
11 *
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
15 * 02110-1301, USA.
16 */
17
a6457262
EL
18/**
19 * \defgroup afppacket AF_PACKET running mode
20 *
21 * @{
22 */
23
c45d8985
EL
24/**
25 * \file
26 *
27 * \author Eric Leblond <eric@regit.org>
28 *
29 * AF_PACKET socket acquisition support
30 *
e80b30c0
EL
31 * \todo watch other interface event to detect suppression of the monitored
32 * interface
c45d8985
EL
33 */
34
35#include "suricata-common.h"
e80b30c0 36#include "config.h"
c45d8985
EL
37#include "suricata.h"
38#include "decode.h"
39#include "packet-queue.h"
40#include "threads.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"
46#include "conf.h"
47#include "util-debug.h"
51eb9605 48#include "util-device.h"
c45d8985
EL
49#include "util-error.h"
50#include "util-privs.h"
e80b30c0 51#include "util-optimize.h"
51eb9605 52#include "util-checksum.h"
ac56b1bf 53#include "util-ioctl.h"
2cd6e128 54#include "util-host-info.h"
c45d8985
EL
55#include "tmqh-packetpool.h"
56#include "source-af-packet.h"
34b3f194 57#include "runmodes.h"
c45d8985 58
e7f09f24
AS
59#ifdef __SC_CUDA_SUPPORT__
60
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"
68
69#endif /* __SC_CUDA_SUPPORT__ */
70
e80b30c0 71#ifdef HAVE_AF_PACKET
472e061c
VJ
72
73#if HAVE_SYS_IOCTL_H
2bc0be6e 74#include <sys/ioctl.h>
472e061c
VJ
75#endif
76
77#if HAVE_LINUX_IF_ETHER_H
c45d8985 78#include <linux/if_ether.h>
472e061c
VJ
79#endif
80
81#if HAVE_LINUX_IF_PACKET_H
c45d8985 82#include <linux/if_packet.h>
472e061c
VJ
83#endif
84
85#if HAVE_LINUX_IF_ARP_H
c45d8985 86#include <linux/if_arp.h>
472e061c 87#endif
f2a6fb8a 88
472e061c 89#if HAVE_LINUX_FILTER_H
f2a6fb8a 90#include <linux/filter.h>
e80b30c0 91#endif
c45d8985 92
472e061c 93#if HAVE_SYS_MMAN_H
49b7b00f 94#include <sys/mman.h>
472e061c
VJ
95#endif
96
97#endif /* HAVE_AF_PACKET */
49b7b00f 98
c45d8985
EL
99extern uint8_t suricata_ctl_flags;
100extern int max_pending_packets;
101
e80b30c0
EL
102#ifndef HAVE_AF_PACKET
103
104TmEcode NoAFPSupportExit(ThreadVars *, void *, void **);
105
106void 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;
3f1c4efc 114 tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
e80b30c0
EL
115}
116
117/**
118 * \brief Registration Function for DecodeAFP.
119 * \todo Unit tests are needed for this module.
120 */
121void TmModuleDecodeAFPRegister (void) {
122 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
123 tmm_modules[TMM_DECODEAFP].ThreadInit = NoAFPSupportExit;
124 tmm_modules[TMM_DECODEAFP].Func = NULL;
125 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
126 tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
127 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
128 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
bc6cf438 129 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
e80b30c0
EL
130}
131
132/**
133 * \brief this function prints an error message and exits.
134 */
135TmEcode NoAFPSupportExit(ThreadVars *tv, void *initdata, void **data)
136{
137 SCLogError(SC_ERR_NO_AF_PACKET,"Error creating thread %s: you do not have "
138 "support for AF_PACKET enabled, on Linux host please recompile "
139 "with --enable-af-packet", tv->name);
140 exit(EXIT_FAILURE);
141}
142
143#else /* We have AF_PACKET support */
144
c45d8985
EL
145#define AFP_IFACE_NAME_LENGTH 48
146
147#define AFP_STATE_DOWN 0
148#define AFP_STATE_UP 1
149
150#define AFP_RECONNECT_TIMEOUT 500000
13f13b6d 151#define AFP_DOWN_COUNTER_INTERVAL 40
c45d8985
EL
152
153#define POLL_TIMEOUT 100
154
4a1a0080
EL
155#ifndef TP_STATUS_USER_BUSY
156/* for new use latest bit available in tp_status */
157#define TP_STATUS_USER_BUSY (1 << 31)
158#endif
159
b603ad62
EL
160#ifndef TP_STATUS_VLAN_VALID
161#define TP_STATUS_VLAN_VALID (1 << 4)
162#endif
163
f2a6fb8a 164/** protect pfring_set_bpf_filter, as it is not thread safe */
5532af46 165static SCMutex afpacket_bpf_set_filter_lock = SCMUTEX_INITIALIZER;
f2a6fb8a 166
62e63e3f
EL
167enum {
168 AFP_READ_OK,
169 AFP_READ_FAILURE,
170 AFP_FAILURE,
27b5136b 171 AFP_KERNEL_DROP,
62e63e3f
EL
172};
173
49b7b00f
EL
174union thdr {
175 struct tpacket2_hdr *h2;
176 void *raw;
177};
178
c45d8985
EL
179/**
180 * \brief Structure to hold thread specific variables.
181 */
182typedef struct AFPThreadVars_
183{
184 /* thread specific socket */
185 int socket;
186 /* handle state */
187 unsigned char afp_state;
c45d8985
EL
188
189 /* data link type for the thread */
190 int datalink;
191 int cooked;
192
193 /* counters */
194 uint32_t pkts;
195 uint64_t bytes;
196 uint32_t errs;
197
ff6365dd
EL
198 ThreadVars *tv;
199 TmSlot *slot;
200
201 uint8_t *data; /** Per function and thread data */
202 int datalen; /** Length of per function and thread data */
203
71e47868
EL
204 int vlan_disabled;
205
ff6365dd 206 char iface[AFP_IFACE_NAME_LENGTH];
51eb9605 207 LiveDevice *livedev;
13f13b6d 208 int down_count;
51eb9605 209
f2a6fb8a
EL
210 /* Filter */
211 char *bpf_filter;
212
e80b30c0
EL
213 /* socket buffer size */
214 int buffer_size;
df7dbe36 215 int promisc;
6062e00c 216 ChecksumValidationMode checksum_mode;
e80b30c0 217
662dccd8
EL
218 /* IPS stuff */
219 char out_iface[AFP_IFACE_NAME_LENGTH];
220 AFPPeer *mpeer;
221
49b7b00f 222 int flags;
6efd37a3
EL
223 uint16_t capture_kernel_packets;
224 uint16_t capture_kernel_drops;
49b7b00f 225
e80b30c0
EL
226 int cluster_id;
227 int cluster_type;
c45d8985 228
fbca1a4e 229 int threads;
662dccd8 230 int copy_mode;
fbca1a4e 231
49b7b00f
EL
232 struct tpacket_req req;
233 unsigned int tp_hdrlen;
234 unsigned int ring_buflen;
235 char *ring_buf;
236 char *frame_buf;
237 unsigned int frame_offset;
8879df80 238 int ring_size;
662dccd8 239
c45d8985
EL
240} AFPThreadVars;
241
242TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
243TmEcode ReceiveAFPThreadInit(ThreadVars *, void *, void **);
244void ReceiveAFPThreadExitStats(ThreadVars *, void *);
245TmEcode ReceiveAFPThreadDeinit(ThreadVars *, void *);
e80b30c0 246TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot);
c45d8985
EL
247
248TmEcode DecodeAFPThreadInit(ThreadVars *, void *, void **);
249TmEcode DecodeAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
250
f2a6fb8a 251TmEcode AFPSetBPFFilter(AFPThreadVars *ptv);
662dccd8 252static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose);
13f13b6d
EL
253static int AFPGetDevFlags(int fd, const char *ifname);
254static int AFPDerefSocket(AFPPeer* peer);
255static int AFPRefSocket(AFPPeer* peer);
f2a6fb8a 256
c45d8985
EL
257/**
258 * \brief Registration Function for RecieveAFP.
259 * \todo Unit tests are needed for this module.
260 */
261void TmModuleReceiveAFPRegister (void) {
262 tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
263 tmm_modules[TMM_RECEIVEAFP].ThreadInit = ReceiveAFPThreadInit;
ff6365dd 264 tmm_modules[TMM_RECEIVEAFP].Func = NULL;
e80b30c0 265 tmm_modules[TMM_RECEIVEAFP].PktAcqLoop = ReceiveAFPLoop;
c45d8985
EL
266 tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = ReceiveAFPThreadExitStats;
267 tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
268 tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
269 tmm_modules[TMM_RECEIVEAFP].cap_flags = SC_CAP_NET_RAW;
cd4705e6 270 tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
c45d8985
EL
271}
272
a6457262
EL
273
274/**
275 * \defgroup afppeers AFP peers list
276 *
277 * AF_PACKET has an IPS mode were interface are peered: packet from
278 * on interface are sent the peered interface and the other way. The ::AFPPeer
279 * list is maitaining the list of peers. Each ::AFPPeer is storing the needed
280 * information to be able to send packet on the interface.
281 * A element of the list must not be destroyed during the run of Suricata as it
282 * is used by ::Packet and other threads.
283 *
284 * @{
285 */
286
662dccd8
EL
287typedef struct AFPPeersList_ {
288 TAILQ_HEAD(, AFPPeer_) peers; /**< Head of list of fragments. */
289 int cnt;
290 int peered;
60400163
EL
291 int turn; /**< Next value for initialisation order */
292 SC_ATOMIC_DECLARE(int, reached); /**< Counter used to synchronize start */
662dccd8
EL
293} AFPPeersList;
294
295/**
a6457262
EL
296 * \brief Update the peer.
297 *
298 * Update the AFPPeer of a thread ie set new state, socket number
299 * or iface index.
300 *
662dccd8
EL
301 */
302void AFPPeerUpdate(AFPThreadVars *ptv)
303{
304 if (ptv->mpeer == NULL) {
305 return;
306 }
662dccd8
EL
307 (void)SC_ATOMIC_SET(ptv->mpeer->if_idx, AFPGetIfnumByDev(ptv->socket, ptv->iface, 0));
308 (void)SC_ATOMIC_SET(ptv->mpeer->socket, ptv->socket);
309 (void)SC_ATOMIC_SET(ptv->mpeer->state, ptv->afp_state);
310}
311
a6457262
EL
312/**
313 * \brief Clean and free ressource used by an ::AFPPeer
314 */
662dccd8
EL
315void AFPPeerClean(AFPPeer *peer)
316{
317 if (peer->flags & AFP_SOCK_PROTECT)
318 SCMutexDestroy(&peer->sock_protect);
319 SC_ATOMIC_DESTROY(peer->socket);
320 SC_ATOMIC_DESTROY(peer->if_idx);
321 SC_ATOMIC_DESTROY(peer->state);
322 SCFree(peer);
323}
324
325AFPPeersList peerslist;
326
327
a6457262
EL
328/**
329 * \brief Init the global list of ::AFPPeer
330 */
662dccd8
EL
331TmEcode AFPPeersListInit()
332{
333 SCEnter();
334 TAILQ_INIT(&peerslist.peers);
335 peerslist.peered = 0;
336 peerslist.cnt = 0;
60400163
EL
337 peerslist.turn = 0;
338 SC_ATOMIC_INIT(peerslist.reached);
339 (void) SC_ATOMIC_SET(peerslist.reached, 0);
662dccd8
EL
340 SCReturnInt(TM_ECODE_OK);
341}
342
a6457262
EL
343/**
344 * \brief Check that all ::AFPPeer got a peer
345 *
346 * \retval TM_ECODE_FAILED if some threads are not peered or TM_ECODE_OK else.
347 */
662dccd8
EL
348TmEcode AFPPeersListCheck()
349{
350#define AFP_PEERS_MAX_TRY 4
351#define AFP_PEERS_WAIT 20000
352 int try = 0;
353 SCEnter();
354 while (try < AFP_PEERS_MAX_TRY) {
355 if (peerslist.cnt != peerslist.peered) {
356 usleep(AFP_PEERS_WAIT);
357 } else {
358 SCReturnInt(TM_ECODE_OK);
359 }
360 try++;
361 }
362 SCLogError(SC_ERR_AFP_CREATE, "Threads number not equals");
363 SCReturnInt(TM_ECODE_FAILED);
364}
365
a6457262
EL
366/**
367 * \brief Declare a new AFP thread to AFP peers list.
368 */
662dccd8
EL
369TmEcode AFPPeersListAdd(AFPThreadVars *ptv)
370{
371 SCEnter();
372 AFPPeer *peer = SCMalloc(sizeof(AFPPeer));
373 AFPPeer *pitem;
ac56b1bf 374 int mtu, out_mtu;
662dccd8 375
e176be6f 376 if (unlikely(peer == NULL)) {
662dccd8
EL
377 SCReturnInt(TM_ECODE_FAILED);
378 }
379 memset(peer, 0, sizeof(AFPPeer));
380 SC_ATOMIC_INIT(peer->socket);
13f13b6d 381 SC_ATOMIC_INIT(peer->sock_usage);
662dccd8
EL
382 SC_ATOMIC_INIT(peer->if_idx);
383 SC_ATOMIC_INIT(peer->state);
384 peer->flags = ptv->flags;
60400163 385 peer->turn = peerslist.turn++;
662dccd8
EL
386
387 if (peer->flags & AFP_SOCK_PROTECT) {
388 SCMutexInit(&peer->sock_protect, NULL);
389 }
390
13f13b6d 391 (void)SC_ATOMIC_SET(peer->sock_usage, 0);
662dccd8
EL
392 (void)SC_ATOMIC_SET(peer->state, AFP_STATE_DOWN);
393 strlcpy(peer->iface, ptv->iface, AFP_IFACE_NAME_LENGTH);
394 ptv->mpeer = peer;
395 /* add element to iface list */
396 TAILQ_INSERT_TAIL(&peerslist.peers, peer, next);
662dccd8 397
13f13b6d
EL
398 if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
399 peerslist.cnt++;
400
401 /* Iter to find a peer */
402 TAILQ_FOREACH(pitem, &peerslist.peers, next) {
403 if (pitem->peer)
404 continue;
405 if (strcmp(pitem->iface, ptv->out_iface))
406 continue;
407 peer->peer = pitem;
408 pitem->peer = peer;
409 mtu = GetIfaceMTU(ptv->iface);
410 out_mtu = GetIfaceMTU(ptv->out_iface);
411 if (mtu != out_mtu) {
412 SCLogError(SC_ERR_AFP_CREATE,
413 "MTU on %s (%d) and %s (%d) are not equal, "
414 "transmission of packets bigger than %d will fail.",
415 ptv->iface, mtu,
416 ptv->out_iface, out_mtu,
417 (out_mtu > mtu) ? mtu : out_mtu);
418 }
419 peerslist.peered += 2;
420 break;
ac56b1bf 421 }
662dccd8
EL
422 }
423
424 AFPPeerUpdate(ptv);
425
426 SCReturnInt(TM_ECODE_OK);
427}
428
60400163
EL
429int AFPPeersListWaitTurn(AFPPeer *peer)
430{
b2691cbe
EL
431 /* If turn is zero, we already have started threads once */
432 if (peerslist.turn == 0)
433 return 0;
434
60400163
EL
435 if (peer->turn == SC_ATOMIC_GET(peerslist.reached))
436 return 0;
437 return 1;
438}
439
440void AFPPeersListReachedInc()
441{
b2691cbe
EL
442 if (peerslist.turn == 0)
443 return;
444
445 if (SC_ATOMIC_ADD(peerslist.reached, 1) == peerslist.turn) {
446 SCLogInfo("All AFP capture threads are running.");
447 (void)SC_ATOMIC_SET(peerslist.reached, 0);
448 /* Set turn to 0 to skip syncrhonization when ReceiveAFPLoop is
449 * restarted.
450 */
451 peerslist.turn = 0;
452 }
60400163
EL
453}
454
a6457262
EL
455/**
456 * \brief Clean the global peers list.
457 */
662dccd8
EL
458void AFPPeersListClean()
459{
460 AFPPeer *pitem;
461
462 while ((pitem = TAILQ_FIRST(&peerslist.peers))) {
463 TAILQ_REMOVE(&peerslist.peers, pitem, next);
464 AFPPeerClean(pitem);
465 }
466}
467
a6457262
EL
468/**
469 * @}
470 */
471
c45d8985
EL
472/**
473 * \brief Registration Function for DecodeAFP.
474 * \todo Unit tests are needed for this module.
475 */
476void TmModuleDecodeAFPRegister (void) {
477 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
478 tmm_modules[TMM_DECODEAFP].ThreadInit = DecodeAFPThreadInit;
479 tmm_modules[TMM_DECODEAFP].Func = DecodeAFP;
480 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
481 tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
482 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
483 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
bc6cf438 484 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
c45d8985
EL
485}
486
662dccd8 487
e80b30c0
EL
488static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose);
489
e8a4a4c4 490static inline void AFPDumpCounters(AFPThreadVars *ptv)
6efd37a3 491{
6efd37a3 492#ifdef PACKET_STATISTICS
e8a4a4c4
EL
493 struct tpacket_stats kstats;
494 socklen_t len = sizeof (struct tpacket_stats);
495 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_STATISTICS,
496 &kstats, &len) > -1) {
497 SCLogDebug("(%s) Kernel: Packets %" PRIu32 ", dropped %" PRIu32 "",
498 ptv->tv->name,
499 kstats.tp_packets, kstats.tp_drops);
500 SCPerfCounterAddUI64(ptv->capture_kernel_packets, ptv->tv->sc_perf_pca, kstats.tp_packets);
501 SCPerfCounterAddUI64(ptv->capture_kernel_drops, ptv->tv->sc_perf_pca, kstats.tp_drops);
8d0260b2 502 (void) SC_ATOMIC_ADD(ptv->livedev->drop, kstats.tp_drops);
1869688f 503 (void) SC_ATOMIC_ADD(ptv->livedev->pkts, kstats.tp_packets);
6efd37a3 504 }
e8a4a4c4 505#endif
6efd37a3 506}
c45d8985
EL
507
508/**
509 * \brief AF packet read function.
510 *
511 * This function fills
512 * From here the packets are picked up by the DecodeAFP thread.
513 *
514 * \param user pointer to AFPThreadVars
515 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
516 */
62e63e3f 517int AFPRead(AFPThreadVars *ptv)
c45d8985
EL
518{
519 Packet *p = NULL;
520 /* XXX should try to use read that get directly to packet */
c45d8985
EL
521 int offset = 0;
522 int caplen;
523 struct sockaddr_ll from;
524 struct iovec iov;
525 struct msghdr msg;
c45d8985
EL
526 struct cmsghdr *cmsg;
527 union {
528 struct cmsghdr cmsg;
529 char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
530 } cmsg_buf;
6efd37a3 531 unsigned char aux_checksum = 0;
c45d8985
EL
532
533 msg.msg_name = &from;
534 msg.msg_namelen = sizeof(from);
535 msg.msg_iov = &iov;
536 msg.msg_iovlen = 1;
c45d8985
EL
537 msg.msg_control = &cmsg_buf;
538 msg.msg_controllen = sizeof(cmsg_buf);
c45d8985
EL
539 msg.msg_flags = 0;
540
541 if (ptv->cooked)
542 offset = SLL_HEADER_LEN;
543 else
544 offset = 0;
e80b30c0
EL
545 iov.iov_len = ptv->datalen - offset;
546 iov.iov_base = ptv->data + offset;
c45d8985
EL
547
548 caplen = recvmsg(ptv->socket, &msg, MSG_TRUNC);
549
550 if (caplen < 0) {
551 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
552 errno);
62e63e3f 553 SCReturnInt(AFP_READ_FAILURE);
c45d8985 554 }
ff6365dd
EL
555
556 p = PacketGetFromQueueOrAlloc();
c45d8985 557 if (p == NULL) {
62e63e3f 558 SCReturnInt(AFP_FAILURE);
c45d8985 559 }
b33986c8 560 PKT_SET_SRC(p, PKT_SRC_WIRE);
c45d8985
EL
561
562 /* get timestamp of packet via ioctl */
563 if (ioctl(ptv->socket, SIOCGSTAMP, &p->ts) == -1) {
564 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
565 errno);
566 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 567 SCReturnInt(AFP_READ_FAILURE);
c45d8985
EL
568 }
569
570 ptv->pkts++;
571 ptv->bytes += caplen + offset;
51eb9605 572 p->livedev = ptv->livedev;
c45d8985
EL
573
574 /* add forged header */
575 if (ptv->cooked) {
e80b30c0 576 SllHdr * hdrp = (SllHdr *)ptv->data;
c45d8985
EL
577 /* XXX this is minimalist, but this seems enough */
578 hdrp->sll_protocol = from.sll_protocol;
579 }
580
581 p->datalink = ptv->datalink;
582 SET_PKT_LEN(p, caplen + offset);
e80b30c0 583 if (PacketCopyData(p, ptv->data, GET_PKT_LEN(p)) == -1) {
c45d8985 584 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 585 SCReturnInt(AFP_FAILURE);
c45d8985 586 }
e80b30c0
EL
587 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
588 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
589
6062e00c
EL
590 /* We only check for checksum disable */
591 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
51eb9605
EL
592 p->flags |= PKT_IGNORE_CHECKSUM;
593 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
594 if (ptv->livedev->ignore_checksum) {
595 p->flags |= PKT_IGNORE_CHECKSUM;
a565148f 596 } else if (ChecksumAutoModeCheck(ptv->pkts,
51eb9605
EL
597 SC_ATOMIC_GET(ptv->livedev->pkts),
598 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
599 ptv->livedev->ignore_checksum = 1;
6062e00c 600 p->flags |= PKT_IGNORE_CHECKSUM;
51eb9605 601 }
6062e00c 602 } else {
6efd37a3
EL
603 aux_checksum = 1;
604 }
6062e00c 605
6efd37a3
EL
606 /* List is NULL if we don't have activated auxiliary data */
607 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
608 struct tpacket_auxdata *aux;
f6ddaf33 609
6efd37a3
EL
610 if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
611 cmsg->cmsg_level != SOL_PACKET ||
612 cmsg->cmsg_type != PACKET_AUXDATA)
613 continue;
f6ddaf33 614
6efd37a3
EL
615 aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
616
617 if (aux_checksum && (aux->tp_status & TP_STATUS_CSUMNOTREADY)) {
618 p->flags |= PKT_IGNORE_CHECKSUM;
f6ddaf33 619 }
6efd37a3 620 break;
f6ddaf33
EL
621 }
622
c469824b
EL
623 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
624 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 625 SCReturnInt(AFP_FAILURE);
c469824b 626 }
62e63e3f 627 SCReturnInt(AFP_READ_OK);
c45d8985
EL
628}
629
662dccd8
EL
630TmEcode AFPWritePacket(Packet *p)
631{
632 struct sockaddr_ll socket_address;
633 int socket;
634
635 if (p->afp_v.copy_mode == AFP_COPY_MODE_IPS) {
3f107fa1 636 if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
662dccd8
EL
637 return TM_ECODE_OK;
638 }
639 }
640
641 if (SC_ATOMIC_GET(p->afp_v.peer->state) == AFP_STATE_DOWN)
642 return TM_ECODE_OK;
643
644 if (p->ethh == NULL) {
645 SCLogWarning(SC_ERR_INVALID_VALUE, "Should have an Ethernet header");
646 return TM_ECODE_FAILED;
647 }
648 /* Index of the network device */
649 socket_address.sll_ifindex = SC_ATOMIC_GET(p->afp_v.peer->if_idx);
650 /* Address length*/
651 socket_address.sll_halen = ETH_ALEN;
652 /* Destination MAC */
653 memcpy(socket_address.sll_addr, p->ethh, 6);
654
655 /* Send packet, locking the socket if necessary */
656 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
657 SCMutexLock(&p->afp_v.peer->sock_protect);
658 socket = SC_ATOMIC_GET(p->afp_v.peer->socket);
659 if (sendto(socket, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,
660 (struct sockaddr*) &socket_address,
661 sizeof(struct sockaddr_ll)) < 0) {
662 SCLogWarning(SC_ERR_SOCKET, "Sending packet failed on socket %d: %s",
663 socket,
664 strerror(errno));
665 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
666 SCMutexUnlock(&p->afp_v.peer->sock_protect);
667 return TM_ECODE_FAILED;
668 }
669 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
670 SCMutexUnlock(&p->afp_v.peer->sock_protect);
671
672 return TM_ECODE_OK;
673}
674
b076a26c 675void AFPReleaseDataFromRing(Packet *p)
2011a3f8 676{
662dccd8
EL
677 /* Need to be in copy mode and need to detect early release
678 where Ethernet header could not be set (and pseudo packet) */
679 if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
b076a26c 680 AFPWritePacket(p);
662dccd8 681 }
13f13b6d
EL
682
683 if (AFPDerefSocket(p->afp_v.mpeer) == 0)
680e941a 684 goto cleanup;
13f13b6d 685
2011a3f8
EL
686 if (p->afp_v.relptr) {
687 union thdr h;
688 h.raw = p->afp_v.relptr;
689 h.h2->tp_status = TP_STATUS_KERNEL;
2011a3f8 690 }
680e941a
EL
691
692cleanup:
693 AFPV_CLEANUP(&p->afp_v);
b076a26c
KS
694}
695
696void AFPReleasePacket(Packet *p)
697{
698 AFPReleaseDataFromRing(p);
699 PacketFreeOrRelease(p);
2011a3f8
EL
700}
701
49b7b00f
EL
702/**
703 * \brief AF packet read function for ring
704 *
705 * This function fills
706 * From here the packets are picked up by the DecodeAFP thread.
707 *
708 * \param user pointer to AFPThreadVars
709 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
710 */
711int AFPReadFromRing(AFPThreadVars *ptv)
712{
713 Packet *p = NULL;
714 union thdr h;
662dccd8 715 struct sockaddr_ll *from;
27b5136b 716 uint8_t emergency_flush = 0;
4d8f70c6 717 int read_pkts = 0;
b26ec603 718 int loop_start = -1;
4d8f70c6 719
49b7b00f 720
a369f8c3
EL
721 /* Loop till we have packets available */
722 while (1) {
53c02334
AS
723 if (unlikely(suricata_ctl_flags != 0)) {
724 break;
725 }
726
a369f8c3
EL
727 /* Read packet from ring */
728 h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
729 if (h.raw == NULL) {
34b3f194
EL
730 SCReturnInt(AFP_FAILURE);
731 }
662dccd8 732
82a2dd85 733 if ((! h.h2->tp_status) || (h.h2->tp_status & TP_STATUS_USER_BUSY)) {
4d8f70c6 734 if (read_pkts == 0) {
b26ec603
EL
735 if (loop_start == -1) {
736 loop_start = ptv->frame_offset;
737 } else if (unlikely(loop_start == (int)ptv->frame_offset)) {
738 SCReturnInt(AFP_READ_OK);
739 }
740 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
741 ptv->frame_offset = 0;
742 }
743 continue;
4d8f70c6 744 }
27b5136b
EL
745 if ((emergency_flush) && (ptv->flags & AFP_EMERGENCY_MODE)) {
746 SCReturnInt(AFP_KERNEL_DROP);
747 } else {
748 SCReturnInt(AFP_READ_OK);
749 }
750 }
4d8f70c6
EL
751
752 read_pkts++;
b26ec603 753 loop_start = -1;
4d8f70c6 754
4a1a0080
EL
755 /* Our packet is still used by suricata, we exit read loop to
756 * gain some time */
757 if (h.h2->tp_status & TP_STATUS_USER_BUSY) {
758 SCReturnInt(AFP_READ_OK);
759 }
760
27b5136b
EL
761 if ((ptv->flags & AFP_EMERGENCY_MODE) && (emergency_flush == 1)) {
762 h.h2->tp_status = TP_STATUS_KERNEL;
763 goto next_frame;
a369f8c3
EL
764 }
765
766 p = PacketGetFromQueueOrAlloc();
767 if (p == NULL) {
34b3f194
EL
768 SCReturnInt(AFP_FAILURE);
769 }
b33986c8 770 PKT_SET_SRC(p, PKT_SRC_WIRE);
49b7b00f 771
4a1a0080
EL
772 /* Suricata will treat packet so telling it is busy, this
773 * status will be reset to 0 (ie TP_STATUS_KERNEL) in the release
774 * function. */
775 h.h2->tp_status |= TP_STATUS_USER_BUSY;
776
662dccd8
EL
777 from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
778
a369f8c3
EL
779 ptv->pkts++;
780 ptv->bytes += h.h2->tp_len;
a369f8c3
EL
781 p->livedev = ptv->livedev;
782
783 /* add forged header */
784 if (ptv->cooked) {
785 SllHdr * hdrp = (SllHdr *)ptv->data;
a369f8c3
EL
786 /* XXX this is minimalist, but this seems enough */
787 hdrp->sll_protocol = from->sll_protocol;
49b7b00f 788 }
a369f8c3
EL
789
790 p->datalink = ptv->datalink;
791 if (h.h2->tp_len > h.h2->tp_snaplen) {
792 SCLogDebug("Packet length (%d) > snaplen (%d), truncating",
793 h.h2->tp_len, h.h2->tp_snaplen);
794 }
71e47868
EL
795
796 /* get vlan id from header */
e871f713
EL
797 if ((!ptv->vlan_disabled) &&
798 (h.h2->tp_status & TP_STATUS_VLAN_VALID || h.h2->tp_vlan_tci)) {
71e47868
EL
799 p->vlan_id[0] = h.h2->tp_vlan_tci;
800 p->vlan_idx = 1;
801 p->vlanh[0] = NULL;
802 }
803
a369f8c3
EL
804 if (ptv->flags & AFP_ZERO_COPY) {
805 if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
806 TmqhOutputPacketpool(ptv->tv, p);
807 SCReturnInt(AFP_FAILURE);
662dccd8 808 } else {
0f2b3406 809 p->afp_v.relptr = h.raw;
b076a26c 810 p->ReleasePacket = AFPReleasePacket;
5f12b234
EL
811 p->afp_v.mpeer = ptv->mpeer;
812 AFPRefSocket(ptv->mpeer);
0f2b3406
EL
813
814 p->afp_v.copy_mode = ptv->copy_mode;
815 if (p->afp_v.copy_mode != AFP_COPY_MODE_NONE) {
816 p->afp_v.peer = ptv->mpeer->peer;
817 } else {
818 p->afp_v.peer = NULL;
662dccd8 819 }
a369f8c3
EL
820 }
821 } else {
822 if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
823 TmqhOutputPacketpool(ptv->tv, p);
824 SCReturnInt(AFP_FAILURE);
825 }
826 }
827 /* Timestamp */
828 p->ts.tv_sec = h.h2->tp_sec;
829 p->ts.tv_usec = h.h2->tp_nsec/1000;
830 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
831 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
832
833 /* We only check for checksum disable */
834 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
835 p->flags |= PKT_IGNORE_CHECKSUM;
836 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
837 if (ptv->livedev->ignore_checksum) {
838 p->flags |= PKT_IGNORE_CHECKSUM;
839 } else if (ChecksumAutoModeCheck(ptv->pkts,
840 SC_ATOMIC_GET(ptv->livedev->pkts),
841 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
842 ptv->livedev->ignore_checksum = 1;
843 p->flags |= PKT_IGNORE_CHECKSUM;
844 }
845 } else {
846 if (h.h2->tp_status & TP_STATUS_CSUMNOTREADY) {
49b7b00f 847 p->flags |= PKT_IGNORE_CHECKSUM;
a369f8c3 848 }
ee6ba099
EL
849 }
850 if (h.h2->tp_status & TP_STATUS_LOSING) {
851 emergency_flush = 1;
e8a4a4c4 852 AFPDumpCounters(ptv);
a369f8c3
EL
853 }
854
5f12b234
EL
855 /* release frame if not in zero copy mode */
856 if (!(ptv->flags & AFP_ZERO_COPY)) {
857 h.h2->tp_status = TP_STATUS_KERNEL;
858 }
859
a369f8c3
EL
860 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
861 h.h2->tp_status = TP_STATUS_KERNEL;
862 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
863 ptv->frame_offset = 0;
864 }
865 TmqhOutputPacketpool(ptv->tv, p);
866 SCReturnInt(AFP_FAILURE);
49b7b00f 867 }
49b7b00f 868
27b5136b 869next_frame:
34b3f194
EL
870 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
871 ptv->frame_offset = 0;
350d7619
EL
872 /* Get out of loop to be sure we will reach maintenance tasks */
873 SCReturnInt(AFP_READ_OK);
34b3f194 874 }
34b3f194
EL
875 }
876
49b7b00f
EL
877 SCReturnInt(AFP_READ_OK);
878}
879
13f13b6d
EL
880/**
881 * \brief Reference socket
882 *
883 * \retval O in case of failure, 1 in case of success
884 */
885static int AFPRefSocket(AFPPeer* peer)
886{
887 if (unlikely(peer == NULL))
888 return 0;
889
890 (void)SC_ATOMIC_ADD(peer->sock_usage, 1);
891 return 1;
892}
893
894
895/**
896 * \brief Dereference socket
897 *
898 * \retval 1 if socket is still alive, 0 if not
899 */
900static int AFPDerefSocket(AFPPeer* peer)
901{
4424f5a2
EL
902 if (peer == NULL)
903 return 1;
904
13f13b6d
EL
905 if (SC_ATOMIC_SUB(peer->sock_usage, 1) == 0) {
906 if (SC_ATOMIC_GET(peer->state) == AFP_STATE_DOWN) {
907 SCLogInfo("Cleaning socket connected to '%s'", peer->iface);
908 close(SC_ATOMIC_GET(peer->socket));
909 return 0;
910 }
911 }
912 return 1;
913}
914
915void AFPSwitchState(AFPThreadVars *ptv, int state)
916{
917 ptv->afp_state = state;
918 ptv->down_count = 0;
49b7b00f 919
13f13b6d
EL
920 AFPPeerUpdate(ptv);
921
922 /* Do cleaning if switching to down state */
923 if (state == AFP_STATE_DOWN) {
924 if (ptv->frame_buf) {
925 /* only used in reading phase, we can free it */
926 SCFree(ptv->frame_buf);
927 ptv->frame_buf = NULL;
928 }
929 if (ptv->socket != -1) {
930 /* we need to wait for all packets to return data */
931 if (SC_ATOMIC_SUB(ptv->mpeer->sock_usage, 1) == 0) {
932 SCLogInfo("Cleaning socket connected to '%s'", ptv->iface);
933 close(ptv->socket);
934 ptv->socket = -1;
935 }
936 }
937 }
938 if (state == AFP_STATE_UP) {
939 (void)SC_ATOMIC_SET(ptv->mpeer->sock_usage, 1);
940 }
941}
49b7b00f 942
13f13b6d
EL
943/**
944 * \brief Try to reopen socket
945 *
946 * \retval 0 in case of success, negative if error occurs or a condition
947 * is not met.
948 */
c45d8985
EL
949static int AFPTryReopen(AFPThreadVars *ptv)
950{
951 int afp_activate_r;
952
13f13b6d
EL
953 ptv->down_count++;
954
955
956 /* Don't reconnect till we have packet that did not release data */
957 if (SC_ATOMIC_GET(ptv->mpeer->sock_usage) != 0) {
958 return -1;
959 }
c45d8985 960
e80b30c0 961 afp_activate_r = AFPCreateSocket(ptv, ptv->iface, 0);
c45d8985 962 if (afp_activate_r != 0) {
13f13b6d
EL
963 if (ptv->down_count % AFP_DOWN_COUNTER_INTERVAL == 0) {
964 SCLogWarning(SC_ERR_AFP_CREATE, "Can not open iface '%s'",
965 ptv->iface);
966 }
c45d8985
EL
967 return afp_activate_r;
968 }
969
3bea3b39 970 SCLogInfo("Interface '%s' is back", ptv->iface);
c45d8985
EL
971 return 0;
972}
973
e80b30c0
EL
974/**
975 * \brief Main AF_PACKET reading Loop function
976 */
977TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
978{
34581ce9
AS
979 SCEnter();
980
e80b30c0
EL
981 uint16_t packet_q_len = 0;
982 AFPThreadVars *ptv = (AFPThreadVars *)data;
e80b30c0
EL
983 struct pollfd fds;
984 int r;
34581ce9 985 TmSlot *s = (TmSlot *)slot;
e8a4a4c4
EL
986 time_t last_dump = 0;
987 struct timeval current_time;
e80b30c0 988
34581ce9 989 ptv->slot = s->slot_next;
e80b30c0 990
60400163
EL
991 if (ptv->afp_state == AFP_STATE_DOWN) {
992 /* Wait for our turn, threads before us must have opened the socket */
993 while (AFPPeersListWaitTurn(ptv->mpeer)) {
994 usleep(1000);
995 }
996 r = AFPCreateSocket(ptv, ptv->iface, 1);
997 if (r < 0) {
998 SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket");
999 }
1000 AFPPeersListReachedInc();
1001 }
1002 if (ptv->afp_state == AFP_STATE_UP) {
1003 SCLogInfo("Thread %s using socket %d", tv->name, ptv->socket);
1004 }
1005
e80b30c0
EL
1006 fds.fd = ptv->socket;
1007 fds.events = POLLIN;
1008
1009 while (1) {
1010 /* Start by checking the state of our interface */
1011 if (unlikely(ptv->afp_state == AFP_STATE_DOWN)) {
1012 int dbreak = 0;
662dccd8 1013
e80b30c0
EL
1014 do {
1015 usleep(AFP_RECONNECT_TIMEOUT);
1016 if (suricata_ctl_flags != 0) {
1017 dbreak = 1;
1018 break;
1019 }
1020 r = AFPTryReopen(ptv);
09e709d1 1021 fds.fd = ptv->socket;
e80b30c0
EL
1022 } while (r < 0);
1023 if (dbreak == 1)
1024 break;
1025 }
1026
1027 /* make sure we have at least one packet in the packet pool, to prevent
1028 * us from alloc'ing packets at line rate */
1029 do {
1030 packet_q_len = PacketPoolSize();
1031 if (unlikely(packet_q_len == 0)) {
1032 PacketPoolWait();
1033 }
1034 } while (packet_q_len == 0);
1035
1036 r = poll(&fds, 1, POLL_TIMEOUT);
1037
1038 if (suricata_ctl_flags != 0) {
1039 break;
1040 }
1041
1042 if (r > 0 &&
1043 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1044 if (fds.revents & (POLLHUP | POLLRDHUP)) {
13f13b6d 1045 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0 1046 continue;
ff6365dd 1047 } else if (fds.revents & POLLERR) {
e80b30c0
EL
1048 char c;
1049 /* Do a recv to get errno */
1050 if (recv(ptv->socket, &c, sizeof c, MSG_PEEK) != -1)
1051 continue; /* what, no error? */
3bea3b39
EL
1052 SCLogError(SC_ERR_AFP_READ,
1053 "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1054 ptv->iface, errno, strerror(errno));
13f13b6d 1055 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0 1056 continue;
ff6365dd 1057 } else if (fds.revents & POLLNVAL) {
e80b30c0 1058 SCLogError(SC_ERR_AFP_READ, "Invalid polling request");
13f13b6d 1059 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0
EL
1060 continue;
1061 }
1062 } else if (r > 0) {
49b7b00f
EL
1063 if (ptv->flags & AFP_RING_MODE) {
1064 r = AFPReadFromRing(ptv);
1065 } else {
1066 /* AFPRead will call TmThreadsSlotProcessPkt on read packets */
1067 r = AFPRead(ptv);
1068 }
62e63e3f
EL
1069 switch (r) {
1070 case AFP_READ_FAILURE:
1071 /* AFPRead in error: best to reset the socket */
3bea3b39
EL
1072 SCLogError(SC_ERR_AFP_READ,
1073 "AFPRead error reading data from iface '%s': (%d" PRIu32 ") %s",
1074 ptv->iface, errno, strerror(errno));
13f13b6d 1075 AFPSwitchState(ptv, AFP_STATE_DOWN);
62e63e3f
EL
1076 continue;
1077 case AFP_FAILURE:
13f13b6d 1078 AFPSwitchState(ptv, AFP_STATE_DOWN);
62e63e3f
EL
1079 SCReturnInt(TM_ECODE_FAILED);
1080 break;
1081 case AFP_READ_OK:
e8a4a4c4
EL
1082 /* Trigger one dump of stats every second */
1083 TimeGet(&current_time);
1084 if (current_time.tv_sec != last_dump) {
1085 AFPDumpCounters(ptv);
1086 last_dump = current_time.tv_sec;
1087 }
62e63e3f 1088 break;
27b5136b 1089 case AFP_KERNEL_DROP:
e8a4a4c4 1090 AFPDumpCounters(ptv);
27b5136b 1091 break;
e80b30c0
EL
1092 }
1093 } else if ((r < 0) && (errno != EINTR)) {
3bea3b39
EL
1094 SCLogError(SC_ERR_AFP_READ, "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1095 ptv->iface,
e80b30c0 1096 errno, strerror(errno));
13f13b6d 1097 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0
EL
1098 continue;
1099 }
677cd03e 1100 SCPerfSyncCountersIfSignalled(tv);
e80b30c0
EL
1101 }
1102
4e561d6b
VJ
1103 AFPDumpCounters(ptv);
1104 SCPerfSyncCountersIfSignalled(tv);
e80b30c0
EL
1105 SCReturnInt(TM_ECODE_OK);
1106}
1107
13f13b6d
EL
1108static int AFPGetDevFlags(int fd, const char *ifname)
1109{
1110 struct ifreq ifr;
1111
1112 memset(&ifr, 0, sizeof(ifr));
1113 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1114
1115 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
1116 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1117 ifname, strerror(errno));
1118 return -1;
1119 }
1120
1121 return ifr.ifr_flags;
1122}
1123
1124
e80b30c0 1125static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose)
c45d8985
EL
1126{
1127 struct ifreq ifr;
1128
1129 memset(&ifr, 0, sizeof(ifr));
e80b30c0 1130 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
c45d8985
EL
1131
1132 if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
1133 if (verbose)
1134 SCLogError(SC_ERR_AFP_CREATE, "Unable to find iface %s: %s",
1135 ifname, strerror(errno));
1136 return -1;
1137 }
1138
1139 return ifr.ifr_ifindex;
1140}
1141
e80b30c0 1142static int AFPGetDevLinktype(int fd, const char *ifname)
c45d8985
EL
1143{
1144 struct ifreq ifr;
1145
1146 memset(&ifr, 0, sizeof(ifr));
e80b30c0 1147 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
c45d8985
EL
1148
1149 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
1150 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1151 ifname, strerror(errno));
1152 return -1;
1153 }
1154
e80b30c0
EL
1155 switch (ifr.ifr_hwaddr.sa_family) {
1156 case ARPHRD_LOOPBACK:
1157 return LINKTYPE_ETHERNET;
1158 case ARPHRD_PPP:
1159 return LINKTYPE_RAW;
1160 default:
1161 return ifr.ifr_hwaddr.sa_family;
1162 }
c45d8985
EL
1163}
1164
49b7b00f
EL
1165static int AFPComputeRingParams(AFPThreadVars *ptv, int order)
1166{
1167 /* Compute structure:
1168 Target is to store all pending packets
1169 with a size equal to MTU + auxdata
1170 And we keep a decent number of block
1171
1172 To do so:
1173 Compute frame_size (aligned to be able to fit in block
1174 Check which block size we need. Blocksize is a 2^n * pagesize
1175 We then need to get order, big enough to have
1176 frame_size < block size
1177 Find number of frame per block (divide)
1178 Fill in packet_req
1179
1180 Compute frame size:
1181 described in packet_mmap.txt
1182 dependant on snaplen (need to use a variable ?)
1183snaplen: MTU ?
1184tp_hdrlen determine_version in daq_afpacket
1185in V1: sizeof(struct tpacket_hdr);
1186in V2: val in getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len)
1187frame size: TPACKET_ALIGN(snaplen + TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1188
1189 */
1190 int tp_hdrlen = sizeof(struct tpacket_hdr);
1191 int snaplen = default_packet_size;
1192
1193 ptv->req.tp_frame_size = TPACKET_ALIGN(snaplen +TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1194 ptv->req.tp_block_size = getpagesize() << order;
1195 int frames_per_block = ptv->req.tp_block_size / ptv->req.tp_frame_size;
1196 if (frames_per_block == 0) {
1197 SCLogInfo("frame size to big");
1198 return -1;
1199 }
8879df80 1200 ptv->req.tp_frame_nr = ptv->ring_size;
d8d9b098 1201 ptv->req.tp_block_nr = ptv->req.tp_frame_nr / frames_per_block + 1;
49b7b00f
EL
1202 /* exact division */
1203 ptv->req.tp_frame_nr = ptv->req.tp_block_nr * frames_per_block;
1204 SCLogInfo("AF_PACKET RX Ring params: block_size=%d block_nr=%d frame_size=%d frame_nr=%d",
1205 ptv->req.tp_block_size, ptv->req.tp_block_nr,
1206 ptv->req.tp_frame_size, ptv->req.tp_frame_nr);
1207 return 1;
1208}
1209
e80b30c0 1210static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
c45d8985
EL
1211{
1212 int r;
1213 struct packet_mreq sock_params;
1214 struct sockaddr_ll bind_address;
49b7b00f
EL
1215 int order;
1216 unsigned int i;
662dccd8 1217 int if_idx;
49b7b00f 1218
c45d8985
EL
1219 /* open socket */
1220 ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1221 if (ptv->socket == -1) {
e80b30c0 1222 SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
13f13b6d 1223 goto error;
c45d8985 1224 }
662dccd8 1225 if_idx = AFPGetIfnumByDev(ptv->socket, devname, verbose);
c45d8985
EL
1226 /* bind socket */
1227 memset(&bind_address, 0, sizeof(bind_address));
1228 bind_address.sll_family = AF_PACKET;
1229 bind_address.sll_protocol = htons(ETH_P_ALL);
662dccd8 1230 bind_address.sll_ifindex = if_idx;
c45d8985
EL
1231 if (bind_address.sll_ifindex == -1) {
1232 if (verbose)
e80b30c0 1233 SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
13f13b6d
EL
1234 goto socket_err;
1235 }
1236
13f13b6d
EL
1237 if (ptv->promisc != 0) {
1238 /* Force promiscuous mode */
1239 memset(&sock_params, 0, sizeof(sock_params));
1240 sock_params.mr_type = PACKET_MR_PROMISC;
1241 sock_params.mr_ifindex = bind_address.sll_ifindex;
1242 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(void *)&sock_params, sizeof(sock_params));
1243 if (r < 0) {
1244 SCLogError(SC_ERR_AFP_CREATE,
1245 "Couldn't switch iface %s to promiscuous, error %s",
1246 devname, strerror(errno));
1247 goto frame_err;
1248 }
1249 }
1250
1251 if (ptv->checksum_mode == CHECKSUM_VALIDATION_KERNEL) {
1252 int val = 1;
1253 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_AUXDATA, &val,
1254 sizeof(val)) == -1 && errno != ENOPROTOOPT) {
1255 SCLogWarning(SC_ERR_NO_AF_PACKET,
1256 "'kernel' checksum mode not supported, failling back to full mode.");
1257 ptv->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
1258 }
1259 }
1260
1261 /* set socket recv buffer size */
1262 if (ptv->buffer_size != 0) {
1263 /*
1264 * Set the socket buffer size to the specified value.
1265 */
1266 SCLogInfo("Setting AF_PACKET socket buffer to %d", ptv->buffer_size);
1267 if (setsockopt(ptv->socket, SOL_SOCKET, SO_RCVBUF,
1268 &ptv->buffer_size,
1269 sizeof(ptv->buffer_size)) == -1) {
1270 SCLogError(SC_ERR_AFP_CREATE,
1271 "Couldn't set buffer size to %d on iface %s, error %s",
1272 ptv->buffer_size, devname, strerror(errno));
1273 goto frame_err;
1274 }
1275 }
1276
1277 r = bind(ptv->socket, (struct sockaddr *)&bind_address, sizeof(bind_address));
1278 if (r < 0) {
1279 if (verbose) {
1280 if (errno == ENETDOWN) {
1281 SCLogError(SC_ERR_AFP_CREATE,
1282 "Couldn't bind AF_PACKET socket, iface %s is down",
1283 devname);
1284 } else {
1285 SCLogError(SC_ERR_AFP_CREATE,
1286 "Couldn't bind AF_PACKET socket to iface %s, error %s",
1287 devname, strerror(errno));
1288 }
1289 }
1290 goto frame_err;
1291 }
1292
1293 int if_flags = AFPGetDevFlags(ptv->socket, ptv->iface);
1294 if (if_flags == -1) {
1295 if (verbose) {
1296 SCLogError(SC_ERR_AFP_READ,
1297 "Can not acces to interface '%s'",
1298 ptv->iface);
1299 }
1300 goto frame_err;
1301 }
1302 if ((if_flags & IFF_UP) == 0) {
1303 if (verbose) {
1304 SCLogError(SC_ERR_AFP_READ,
1305 "Interface '%s' is down",
1306 ptv->iface);
1307 }
1308 goto frame_err;
c45d8985 1309 }
49b7b00f
EL
1310
1311 if (ptv->flags & AFP_RING_MODE) {
1312 int val = TPACKET_V2;
1313 unsigned int len = sizeof(val);
1314 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
1315 if (errno == ENOPROTOOPT) {
1316 SCLogError(SC_ERR_AFP_CREATE,
1317 "Too old kernel giving up (need 2.6.27 at least)");
1318 }
1319 SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len");
13f13b6d 1320 goto socket_err;
49b7b00f
EL
1321 }
1322 ptv->tp_hdrlen = val;
1323
1324 val = TPACKET_V2;
1325 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val,
1326 sizeof(val)) < 0) {
1327 SCLogError(SC_ERR_AFP_CREATE,
1328 "Can't activate TPACKET_V2 on packet socket: %s",
1329 strerror(errno));
13f13b6d 1330 goto socket_err;
49b7b00f
EL
1331 }
1332
2855ee5a
EL
1333 if (GetIfaceOffloading(devname) == 1) {
1334 SCLogWarning(SC_ERR_AFP_CREATE,
1335 "Using mmap mode with GRO or LRO activated can lead to capture problems");
1336 }
1337
49b7b00f
EL
1338 /* Allocate RX ring */
1339#define DEFAULT_ORDER 3
1340 for (order = DEFAULT_ORDER; order >= 0; order--) {
1341 if (AFPComputeRingParams(ptv, order) != 1) {
1342 SCLogInfo("Ring parameter are incorrect. Please correct the devel");
1343 }
1344
1345 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, (void *) &ptv->req, sizeof(ptv->req));
1346 if (r < 0) {
1347 if (errno == ENOMEM) {
1348 SCLogInfo("Memory issue with ring parameters. Retrying.");
1349 continue;
1350 }
1351 SCLogError(SC_ERR_MEM_ALLOC,
1352 "Unable to allocate RX Ring for iface %s: (%d) %s",
1353 devname,
1354 errno,
1355 strerror(errno));
13f13b6d 1356 goto socket_err;
49b7b00f
EL
1357 } else {
1358 break;
1359 }
1360 }
1361
1362 if (order < 0) {
1363 SCLogError(SC_ERR_MEM_ALLOC,
1364 "Unable to allocate RX Ring for iface %s (order 0 failed)",
1365 devname);
13f13b6d 1366 goto socket_err;
49b7b00f
EL
1367 }
1368
1369 /* Allocate the Ring */
1370 ptv->ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
1371 ptv->ring_buf = mmap(0, ptv->ring_buflen, PROT_READ|PROT_WRITE,
1372 MAP_SHARED, ptv->socket, 0);
1373 if (ptv->ring_buf == MAP_FAILED) {
1374 SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap");
13f13b6d 1375 goto socket_err;
49b7b00f
EL
1376 }
1377 /* allocate a ring for each frame header pointer*/
1378 ptv->frame_buf = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *));
1379 if (ptv->frame_buf == NULL) {
1380 SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf");
13f13b6d 1381 goto mmap_err;
49b7b00f
EL
1382 }
1383 memset(ptv->frame_buf, 0, ptv->req.tp_frame_nr * sizeof (union thdr *));
1384 /* fill the header ring with proper frame ptr*/
1385 ptv->frame_offset = 0;
1386 for (i = 0; i < ptv->req.tp_block_nr; ++i) {
1387 void *base = &ptv->ring_buf[i * ptv->req.tp_block_size];
1388 unsigned int j;
1389 for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
1390 (((union thdr **)ptv->frame_buf)[ptv->frame_offset]) = base;
1391 base += ptv->req.tp_frame_size;
1392 }
1393 }
1394 ptv->frame_offset = 0;
1395 }
1396
13f13b6d 1397 SCLogInfo("Using interface '%s' via socket %d", (char *)devname, ptv->socket);
ec76742c 1398
c45d8985
EL
1399#ifdef HAVE_PACKET_FANOUT
1400 /* add binded socket to fanout group */
fbca1a4e 1401 if (ptv->threads > 1) {
c45d8985 1402 uint32_t option = 0;
e80b30c0
EL
1403 uint16_t mode = ptv->cluster_type;
1404 uint16_t id = ptv->cluster_id;
c45d8985
EL
1405 option = (mode << 16) | (id & 0xffff);
1406 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
1407 if (r < 0) {
1408 SCLogError(SC_ERR_AFP_CREATE,
1409 "Coudn't set fanout mode, error %s",
1410 strerror(errno));
13f13b6d 1411 goto frame_err;
c45d8985
EL
1412 }
1413 }
1414#endif
1415
c85ee1e3
EL
1416 ptv->datalink = AFPGetDevLinktype(ptv->socket, ptv->iface);
1417 switch (ptv->datalink) {
1418 case ARPHRD_PPP:
1419 case ARPHRD_ATM:
1420 ptv->cooked = 1;
619414c5 1421 break;
c85ee1e3
EL
1422 }
1423
f2a6fb8a
EL
1424 TmEcode rc;
1425 rc = AFPSetBPFFilter(ptv);
1426 if (rc == TM_ECODE_FAILED) {
1427 SCLogError(SC_ERR_AFP_CREATE, "Set AF_PACKET bpf filter \"%s\" failed.", ptv->bpf_filter);
13f13b6d 1428 goto frame_err;
f2a6fb8a
EL
1429 }
1430
49b7b00f 1431 /* Init is ok */
13f13b6d 1432 AFPSwitchState(ptv, AFP_STATE_UP);
c45d8985 1433 return 0;
13f13b6d
EL
1434
1435frame_err:
1436 if (ptv->frame_buf)
1437 SCFree(ptv->frame_buf);
1438mmap_err:
1439 /* Packet mmap does the cleaning when socket is closed */
1440socket_err:
1441 close(ptv->socket);
1442 ptv->socket = -1;
1443error:
1444 return -1;
c45d8985
EL
1445}
1446
f2a6fb8a
EL
1447TmEcode AFPSetBPFFilter(AFPThreadVars *ptv)
1448{
1449 struct bpf_program filter;
1450 struct sock_fprog fcode;
1451 int rc;
1452
1453 if (!ptv->bpf_filter)
1454 return TM_ECODE_OK;
1455
1456 SCMutexLock(&afpacket_bpf_set_filter_lock);
1457
1458 SCLogInfo("Using BPF '%s' on iface '%s'",
1459 ptv->bpf_filter,
1460 ptv->iface);
1461 if (pcap_compile_nopcap(default_packet_size, /* snaplen_arg */
1462 ptv->datalink, /* linktype_arg */
1463 &filter, /* program */
1464 ptv->bpf_filter, /* const char *buf */
1465 0, /* optimize */
1466 0 /* mask */
1467 ) == -1) {
1468 SCLogError(SC_ERR_AFP_CREATE, "Filter compilation failed.");
1469 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1470 return TM_ECODE_FAILED;
1471 }
1472 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1473
1474 if (filter.bf_insns == NULL) {
1475 SCLogError(SC_ERR_AFP_CREATE, "Filter badly setup.");
1476 return TM_ECODE_FAILED;
1477 }
1478
1479 fcode.len = filter.bf_len;
1480 fcode.filter = (struct sock_filter*)filter.bf_insns;
1481
1482 rc = setsockopt(ptv->socket, SOL_SOCKET, SO_ATTACH_FILTER, &fcode, sizeof(fcode));
1483
1484 if(rc == -1) {
1485 SCLogError(SC_ERR_AFP_CREATE, "Failed to attach filter: %s", strerror(errno));
1486 return TM_ECODE_FAILED;
1487 }
1488
1489 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1490 return TM_ECODE_OK;
1491}
1492
c45d8985
EL
1493
1494/**
1495 * \brief Init function for ReceiveAFP.
1496 *
1497 * \param tv pointer to ThreadVars
1498 * \param initdata pointer to the interface passed from the user
1499 * \param data pointer gets populated with AFPThreadVars
1500 *
1501 * \todo Create a general AFP setup function.
1502 */
1503TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
1504 SCEnter();
fbca1a4e 1505 AFPIfaceConfig *afpconfig = initdata;
c45d8985 1506
c45d8985
EL
1507 if (initdata == NULL) {
1508 SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL");
1509 SCReturnInt(TM_ECODE_FAILED);
1510 }
1511
1512 AFPThreadVars *ptv = SCMalloc(sizeof(AFPThreadVars));
e176be6f 1513 if (unlikely(ptv == NULL)) {
45d5c3ca 1514 afpconfig->DerefFunc(afpconfig);
c45d8985 1515 SCReturnInt(TM_ECODE_FAILED);
45d5c3ca 1516 }
c45d8985
EL
1517 memset(ptv, 0, sizeof(AFPThreadVars));
1518
1519 ptv->tv = tv;
1520 ptv->cooked = 0;
1521
fbca1a4e 1522 strlcpy(ptv->iface, afpconfig->iface, AFP_IFACE_NAME_LENGTH);
c45d8985
EL
1523 ptv->iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
1524
51eb9605
EL
1525 ptv->livedev = LiveGetDevice(ptv->iface);
1526 if (ptv->livedev == NULL) {
1527 SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device");
11bdf483 1528 SCFree(ptv);
51eb9605
EL
1529 SCReturnInt(TM_ECODE_FAILED);
1530 }
1531
fbca1a4e 1532 ptv->buffer_size = afpconfig->buffer_size;
8879df80 1533 ptv->ring_size = afpconfig->ring_size;
e80b30c0 1534
df7dbe36 1535 ptv->promisc = afpconfig->promisc;
6062e00c 1536 ptv->checksum_mode = afpconfig->checksum_mode;
6efd37a3 1537 ptv->bpf_filter = NULL;
df7dbe36 1538
fbca1a4e 1539 ptv->threads = 1;
e80b30c0
EL
1540#ifdef HAVE_PACKET_FANOUT
1541 ptv->cluster_type = PACKET_FANOUT_LB;
1542 ptv->cluster_id = 1;
1543 /* We only set cluster info if the number of reader threads is greater than 1 */
fbca1a4e
EL
1544 if (afpconfig->threads > 1) {
1545 ptv->cluster_id = afpconfig->cluster_id;
1546 ptv->cluster_type = afpconfig->cluster_type;
1547 ptv->threads = afpconfig->threads;
e80b30c0
EL
1548 }
1549#endif
49b7b00f 1550 ptv->flags = afpconfig->flags;
e80b30c0 1551
f2a6fb8a
EL
1552 if (afpconfig->bpf_filter) {
1553 ptv->bpf_filter = afpconfig->bpf_filter;
1554 }
1555
6efd37a3
EL
1556#ifdef PACKET_STATISTICS
1557 ptv->capture_kernel_packets = SCPerfTVRegisterCounter("capture.kernel_packets",
1558 ptv->tv,
1559 SC_PERF_TYPE_UINT64,
1560 "NULL");
1561 ptv->capture_kernel_drops = SCPerfTVRegisterCounter("capture.kernel_drops",
1562 ptv->tv,
1563 SC_PERF_TYPE_UINT64,
1564 "NULL");
1565#endif
1566
34b3f194
EL
1567 char *active_runmode = RunmodeGetActive();
1568
1569 if (active_runmode && !strcmp("workers", active_runmode)) {
1570 ptv->flags |= AFP_ZERO_COPY;
1571 SCLogInfo("Enabling zero copy mode");
662dccd8
EL
1572 } else {
1573 /* If we are using copy mode we need a lock */
1574 ptv->flags |= AFP_SOCK_PROTECT;
34b3f194 1575 }
2011a3f8
EL
1576
1577 /* If we are in RING mode, then we can use ZERO copy
1578 * by using the data release mechanism */
1579 if (ptv->flags & AFP_RING_MODE) {
1580 ptv->flags |= AFP_ZERO_COPY;
1581 SCLogInfo("Enabling zero copy mode by using data release call");
1582 }
34b3f194 1583
662dccd8
EL
1584 ptv->copy_mode = afpconfig->copy_mode;
1585 if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
1586 strlcpy(ptv->out_iface, afpconfig->out_iface, AFP_IFACE_NAME_LENGTH);
1587 ptv->out_iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
b7e78d33
EL
1588 /* Warn about BPF filter consequence */
1589 if (ptv->bpf_filter) {
1590 SCLogWarning(SC_WARN_UNCOMMON, "Enabling a BPF filter in IPS mode result"
1591 " in dropping all non matching packets.");
1592 }
662dccd8 1593 }
c85ee1e3 1594
b7e78d33 1595
0581a23f
EL
1596 if (AFPPeersListAdd(ptv) == TM_ECODE_FAILED) {
1597 SCFree(ptv);
1598 afpconfig->DerefFunc(afpconfig);
1599 SCReturnInt(TM_ECODE_FAILED);
1600 }
1601
e80b30c0
EL
1602#define T_DATA_SIZE 70000
1603 ptv->data = SCMalloc(T_DATA_SIZE);
1604 if (ptv->data == NULL) {
45d5c3ca 1605 afpconfig->DerefFunc(afpconfig);
6019ae3d 1606 SCFree(ptv);
e80b30c0 1607 SCReturnInt(TM_ECODE_FAILED);
c45d8985 1608 }
e80b30c0
EL
1609 ptv->datalen = T_DATA_SIZE;
1610#undef T_DATA_SIZE
1611
c45d8985 1612 *data = (void *)ptv;
fbca1a4e 1613
45d5c3ca 1614 afpconfig->DerefFunc(afpconfig);
71e47868
EL
1615
1616 /* A bit strange to have this here but we only have vlan information
1617 * during reading so we need to know if we want to keep vlan during
1618 * the capture phase */
1619 int vlanbool = 0;
1620 if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
1621 ptv->vlan_disabled = 1;
1622 }
1623
2cd6e128
EL
1624 /* If kernel is older than 3.0, VLAN is not stripped so we don't
1625 * get the info from packet extended header but we will use a standard
1626 * parsing of packet data (See Linux commit bcc6d47903612c3861201cc3a866fb604f26b8b2) */
1627 if (! SCKernelVersionIsAtLeast(3, 0)) {
1628 ptv->vlan_disabled = 1;
1629 }
1630
c45d8985
EL
1631 SCReturnInt(TM_ECODE_OK);
1632}
1633
1634/**
1635 * \brief This function prints stats to the screen at exit.
1636 * \param tv pointer to ThreadVars
1637 * \param data pointer that gets cast into AFPThreadVars for ptv
1638 */
1639void ReceiveAFPThreadExitStats(ThreadVars *tv, void *data) {
1640 SCEnter();
1641 AFPThreadVars *ptv = (AFPThreadVars *)data;
9549faae
EL
1642
1643#ifdef PACKET_STATISTICS
e8a4a4c4 1644 AFPDumpCounters(ptv);
6efd37a3
EL
1645 SCLogInfo("(%s) Kernel: Packets %" PRIu64 ", dropped %" PRIu64 "",
1646 tv->name,
1647 (uint64_t) SCPerfGetLocalCounterValue(ptv->capture_kernel_packets, tv->sc_perf_pca),
1648 (uint64_t) SCPerfGetLocalCounterValue(ptv->capture_kernel_drops, tv->sc_perf_pca));
9549faae 1649#endif
e80b30c0
EL
1650
1651 SCLogInfo("(%s) Packets %" PRIu32 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes);
c45d8985
EL
1652}
1653
1654/**
1655 * \brief DeInit function closes af packet socket at exit.
1656 * \param tv pointer to ThreadVars
1657 * \param data pointer that gets cast into AFPThreadVars for ptv
1658 */
1659TmEcode ReceiveAFPThreadDeinit(ThreadVars *tv, void *data) {
1660 AFPThreadVars *ptv = (AFPThreadVars *)data;
1661
13f13b6d
EL
1662 AFPSwitchState(ptv, AFP_STATE_DOWN);
1663
e80b30c0
EL
1664 if (ptv->data != NULL) {
1665 SCFree(ptv->data);
1666 ptv->data = NULL;
1667 }
1668 ptv->datalen = 0;
1669
f2a6fb8a
EL
1670 ptv->bpf_filter = NULL;
1671
c45d8985
EL
1672 SCReturnInt(TM_ECODE_OK);
1673}
1674
1675/**
1676 * \brief This function passes off to link type decoders.
1677 *
1678 * DecodeAFP reads packets from the PacketQueue and passes
1679 * them off to the proper link type decoder.
1680 *
1681 * \param t pointer to ThreadVars
1682 * \param p pointer to the current packet
1683 * \param data pointer that gets cast into AFPThreadVars for ptv
1684 * \param pq pointer to the current PacketQueue
1685 */
1686TmEcode DecodeAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
1687{
1688 SCEnter();
1689 DecodeThreadVars *dtv = (DecodeThreadVars *)data;
1690
f7b1aefa
VJ
1691 /* XXX HACK: flow timeout can call us for injected pseudo packets
1692 * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */
1693 if (p->flags & PKT_PSEUDO_STREAM_END)
1694 return TM_ECODE_OK;
1695
c45d8985
EL
1696 /* update counters */
1697 SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca);
698ff4e4 1698// SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca);
c45d8985
EL
1699
1700 SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p));
1701#if 0
1702 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p));
1703 SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca,
1704 (GET_PKT_LEN(p) * 8)/1000000.0);
1705#endif
1706
1707 SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
1708 SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
1709
1fb7c0dd
EL
1710 /* If suri has set vlan during reading, we increase vlan counter */
1711 if (p->vlan_idx) {
1712 SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca);
1713 }
1714
c45d8985
EL
1715 /* call the decoder */
1716 switch(p->datalink) {
1717 case LINKTYPE_LINUX_SLL:
1718 DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1719 break;
1720 case LINKTYPE_ETHERNET:
1721 DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1722 break;
1723 case LINKTYPE_PPP:
1724 DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1725 break;
1726 case LINKTYPE_RAW:
1727 DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1728 break;
1729 default:
1730 SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeAFP", p->datalink);
1731 break;
1732 }
1733
3088b6ac 1734 PacketDecodeFinalize(tv, dtv, p);
e7f09f24 1735
c45d8985
EL
1736 SCReturnInt(TM_ECODE_OK);
1737}
1738
1739TmEcode DecodeAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
1740{
1741 SCEnter();
1742 DecodeThreadVars *dtv = NULL;
1743
5f307aca 1744 dtv = DecodeThreadVarsAlloc(tv);
c45d8985
EL
1745
1746 if (dtv == NULL)
1747 SCReturnInt(TM_ECODE_FAILED);
1748
1749 DecodeRegisterPerfCounters(dtv, tv);
1750
1751 *data = (void *)dtv;
1752
e7f09f24
AS
1753#ifdef __SC_CUDA_SUPPORT__
1754 if (CudaThreadVarsInit(&dtv->cuda_vars) < 0)
1755 SCReturnInt(TM_ECODE_FAILED);
1756#endif
1757
c45d8985
EL
1758 SCReturnInt(TM_ECODE_OK);
1759}
1760
e80b30c0 1761#endif /* HAVE_AF_PACKET */
c45d8985 1762/* eof */
a6457262
EL
1763/**
1764 * @}
1765 */