]> git.ipfire.org Git - people/ms/suricata.git/blame - src/source-af-packet.c
drmemory: remove bug 978 suppression
[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 */
3ce39433 194 uint64_t pkts;
c45d8985 195 uint64_t bytes;
3ce39433 196 uint64_t errs;
c45d8985 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
919377d4
EL
455static int AFPPeersListStarted()
456{
457 return !peerslist.turn;
458}
459
a6457262
EL
460/**
461 * \brief Clean the global peers list.
462 */
662dccd8
EL
463void AFPPeersListClean()
464{
465 AFPPeer *pitem;
466
467 while ((pitem = TAILQ_FIRST(&peerslist.peers))) {
468 TAILQ_REMOVE(&peerslist.peers, pitem, next);
469 AFPPeerClean(pitem);
470 }
471}
472
a6457262
EL
473/**
474 * @}
475 */
476
c45d8985
EL
477/**
478 * \brief Registration Function for DecodeAFP.
479 * \todo Unit tests are needed for this module.
480 */
481void TmModuleDecodeAFPRegister (void) {
482 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
483 tmm_modules[TMM_DECODEAFP].ThreadInit = DecodeAFPThreadInit;
484 tmm_modules[TMM_DECODEAFP].Func = DecodeAFP;
485 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
486 tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
487 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
488 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
bc6cf438 489 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
c45d8985
EL
490}
491
662dccd8 492
e80b30c0
EL
493static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose);
494
e8a4a4c4 495static inline void AFPDumpCounters(AFPThreadVars *ptv)
6efd37a3 496{
6efd37a3 497#ifdef PACKET_STATISTICS
e8a4a4c4
EL
498 struct tpacket_stats kstats;
499 socklen_t len = sizeof (struct tpacket_stats);
500 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_STATISTICS,
501 &kstats, &len) > -1) {
502 SCLogDebug("(%s) Kernel: Packets %" PRIu32 ", dropped %" PRIu32 "",
503 ptv->tv->name,
504 kstats.tp_packets, kstats.tp_drops);
505 SCPerfCounterAddUI64(ptv->capture_kernel_packets, ptv->tv->sc_perf_pca, kstats.tp_packets);
506 SCPerfCounterAddUI64(ptv->capture_kernel_drops, ptv->tv->sc_perf_pca, kstats.tp_drops);
3ce39433
EL
507 (void) SC_ATOMIC_ADD(ptv->livedev->drop, (uint64_t) kstats.tp_drops);
508 (void) SC_ATOMIC_ADD(ptv->livedev->pkts, (uint64_t) kstats.tp_packets);
6efd37a3 509 }
e8a4a4c4 510#endif
6efd37a3 511}
c45d8985
EL
512
513/**
514 * \brief AF packet read function.
515 *
516 * This function fills
517 * From here the packets are picked up by the DecodeAFP thread.
518 *
519 * \param user pointer to AFPThreadVars
520 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
521 */
62e63e3f 522int AFPRead(AFPThreadVars *ptv)
c45d8985
EL
523{
524 Packet *p = NULL;
525 /* XXX should try to use read that get directly to packet */
c45d8985
EL
526 int offset = 0;
527 int caplen;
528 struct sockaddr_ll from;
529 struct iovec iov;
530 struct msghdr msg;
c45d8985
EL
531 struct cmsghdr *cmsg;
532 union {
533 struct cmsghdr cmsg;
534 char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
535 } cmsg_buf;
6efd37a3 536 unsigned char aux_checksum = 0;
c45d8985
EL
537
538 msg.msg_name = &from;
539 msg.msg_namelen = sizeof(from);
540 msg.msg_iov = &iov;
541 msg.msg_iovlen = 1;
c45d8985
EL
542 msg.msg_control = &cmsg_buf;
543 msg.msg_controllen = sizeof(cmsg_buf);
c45d8985
EL
544 msg.msg_flags = 0;
545
546 if (ptv->cooked)
547 offset = SLL_HEADER_LEN;
548 else
549 offset = 0;
e80b30c0
EL
550 iov.iov_len = ptv->datalen - offset;
551 iov.iov_base = ptv->data + offset;
c45d8985
EL
552
553 caplen = recvmsg(ptv->socket, &msg, MSG_TRUNC);
554
555 if (caplen < 0) {
556 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
557 errno);
62e63e3f 558 SCReturnInt(AFP_READ_FAILURE);
c45d8985 559 }
ff6365dd
EL
560
561 p = PacketGetFromQueueOrAlloc();
c45d8985 562 if (p == NULL) {
62e63e3f 563 SCReturnInt(AFP_FAILURE);
c45d8985 564 }
b33986c8 565 PKT_SET_SRC(p, PKT_SRC_WIRE);
c45d8985
EL
566
567 /* get timestamp of packet via ioctl */
568 if (ioctl(ptv->socket, SIOCGSTAMP, &p->ts) == -1) {
569 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
570 errno);
571 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 572 SCReturnInt(AFP_READ_FAILURE);
c45d8985
EL
573 }
574
575 ptv->pkts++;
576 ptv->bytes += caplen + offset;
51eb9605 577 p->livedev = ptv->livedev;
c45d8985
EL
578
579 /* add forged header */
580 if (ptv->cooked) {
e80b30c0 581 SllHdr * hdrp = (SllHdr *)ptv->data;
c45d8985
EL
582 /* XXX this is minimalist, but this seems enough */
583 hdrp->sll_protocol = from.sll_protocol;
584 }
585
586 p->datalink = ptv->datalink;
587 SET_PKT_LEN(p, caplen + offset);
e80b30c0 588 if (PacketCopyData(p, ptv->data, GET_PKT_LEN(p)) == -1) {
c45d8985 589 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 590 SCReturnInt(AFP_FAILURE);
c45d8985 591 }
e80b30c0
EL
592 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
593 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
594
6062e00c
EL
595 /* We only check for checksum disable */
596 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
51eb9605
EL
597 p->flags |= PKT_IGNORE_CHECKSUM;
598 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
599 if (ptv->livedev->ignore_checksum) {
600 p->flags |= PKT_IGNORE_CHECKSUM;
a565148f 601 } else if (ChecksumAutoModeCheck(ptv->pkts,
51eb9605
EL
602 SC_ATOMIC_GET(ptv->livedev->pkts),
603 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
604 ptv->livedev->ignore_checksum = 1;
6062e00c 605 p->flags |= PKT_IGNORE_CHECKSUM;
51eb9605 606 }
6062e00c 607 } else {
6efd37a3
EL
608 aux_checksum = 1;
609 }
6062e00c 610
6efd37a3
EL
611 /* List is NULL if we don't have activated auxiliary data */
612 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
613 struct tpacket_auxdata *aux;
f6ddaf33 614
6efd37a3
EL
615 if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
616 cmsg->cmsg_level != SOL_PACKET ||
617 cmsg->cmsg_type != PACKET_AUXDATA)
618 continue;
f6ddaf33 619
6efd37a3
EL
620 aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
621
622 if (aux_checksum && (aux->tp_status & TP_STATUS_CSUMNOTREADY)) {
623 p->flags |= PKT_IGNORE_CHECKSUM;
f6ddaf33 624 }
6efd37a3 625 break;
f6ddaf33
EL
626 }
627
c469824b
EL
628 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
629 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 630 SCReturnInt(AFP_FAILURE);
c469824b 631 }
62e63e3f 632 SCReturnInt(AFP_READ_OK);
c45d8985
EL
633}
634
662dccd8
EL
635TmEcode AFPWritePacket(Packet *p)
636{
637 struct sockaddr_ll socket_address;
638 int socket;
639
640 if (p->afp_v.copy_mode == AFP_COPY_MODE_IPS) {
3f107fa1 641 if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
662dccd8
EL
642 return TM_ECODE_OK;
643 }
644 }
645
646 if (SC_ATOMIC_GET(p->afp_v.peer->state) == AFP_STATE_DOWN)
647 return TM_ECODE_OK;
648
649 if (p->ethh == NULL) {
650 SCLogWarning(SC_ERR_INVALID_VALUE, "Should have an Ethernet header");
651 return TM_ECODE_FAILED;
652 }
653 /* Index of the network device */
654 socket_address.sll_ifindex = SC_ATOMIC_GET(p->afp_v.peer->if_idx);
655 /* Address length*/
656 socket_address.sll_halen = ETH_ALEN;
657 /* Destination MAC */
658 memcpy(socket_address.sll_addr, p->ethh, 6);
659
660 /* Send packet, locking the socket if necessary */
661 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
662 SCMutexLock(&p->afp_v.peer->sock_protect);
663 socket = SC_ATOMIC_GET(p->afp_v.peer->socket);
664 if (sendto(socket, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,
665 (struct sockaddr*) &socket_address,
666 sizeof(struct sockaddr_ll)) < 0) {
667 SCLogWarning(SC_ERR_SOCKET, "Sending packet failed on socket %d: %s",
668 socket,
669 strerror(errno));
670 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
671 SCMutexUnlock(&p->afp_v.peer->sock_protect);
672 return TM_ECODE_FAILED;
673 }
674 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
675 SCMutexUnlock(&p->afp_v.peer->sock_protect);
676
677 return TM_ECODE_OK;
678}
679
b076a26c 680void AFPReleaseDataFromRing(Packet *p)
2011a3f8 681{
662dccd8
EL
682 /* Need to be in copy mode and need to detect early release
683 where Ethernet header could not be set (and pseudo packet) */
684 if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
b076a26c 685 AFPWritePacket(p);
662dccd8 686 }
13f13b6d
EL
687
688 if (AFPDerefSocket(p->afp_v.mpeer) == 0)
680e941a 689 goto cleanup;
13f13b6d 690
2011a3f8
EL
691 if (p->afp_v.relptr) {
692 union thdr h;
693 h.raw = p->afp_v.relptr;
694 h.h2->tp_status = TP_STATUS_KERNEL;
2011a3f8 695 }
680e941a
EL
696
697cleanup:
698 AFPV_CLEANUP(&p->afp_v);
b076a26c
KS
699}
700
701void AFPReleasePacket(Packet *p)
702{
703 AFPReleaseDataFromRing(p);
704 PacketFreeOrRelease(p);
2011a3f8
EL
705}
706
49b7b00f
EL
707/**
708 * \brief AF packet read function for ring
709 *
710 * This function fills
711 * From here the packets are picked up by the DecodeAFP thread.
712 *
713 * \param user pointer to AFPThreadVars
714 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
715 */
716int AFPReadFromRing(AFPThreadVars *ptv)
717{
718 Packet *p = NULL;
719 union thdr h;
662dccd8 720 struct sockaddr_ll *from;
27b5136b 721 uint8_t emergency_flush = 0;
4d8f70c6 722 int read_pkts = 0;
b26ec603 723 int loop_start = -1;
4d8f70c6 724
49b7b00f 725
a369f8c3
EL
726 /* Loop till we have packets available */
727 while (1) {
53c02334
AS
728 if (unlikely(suricata_ctl_flags != 0)) {
729 break;
730 }
731
a369f8c3
EL
732 /* Read packet from ring */
733 h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
734 if (h.raw == NULL) {
34b3f194
EL
735 SCReturnInt(AFP_FAILURE);
736 }
662dccd8 737
82a2dd85 738 if ((! h.h2->tp_status) || (h.h2->tp_status & TP_STATUS_USER_BUSY)) {
4d8f70c6 739 if (read_pkts == 0) {
b26ec603
EL
740 if (loop_start == -1) {
741 loop_start = ptv->frame_offset;
742 } else if (unlikely(loop_start == (int)ptv->frame_offset)) {
743 SCReturnInt(AFP_READ_OK);
744 }
745 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
746 ptv->frame_offset = 0;
747 }
748 continue;
4d8f70c6 749 }
27b5136b
EL
750 if ((emergency_flush) && (ptv->flags & AFP_EMERGENCY_MODE)) {
751 SCReturnInt(AFP_KERNEL_DROP);
752 } else {
753 SCReturnInt(AFP_READ_OK);
754 }
755 }
4d8f70c6
EL
756
757 read_pkts++;
b26ec603 758 loop_start = -1;
4d8f70c6 759
4a1a0080
EL
760 /* Our packet is still used by suricata, we exit read loop to
761 * gain some time */
762 if (h.h2->tp_status & TP_STATUS_USER_BUSY) {
763 SCReturnInt(AFP_READ_OK);
764 }
765
27b5136b
EL
766 if ((ptv->flags & AFP_EMERGENCY_MODE) && (emergency_flush == 1)) {
767 h.h2->tp_status = TP_STATUS_KERNEL;
768 goto next_frame;
a369f8c3
EL
769 }
770
771 p = PacketGetFromQueueOrAlloc();
772 if (p == NULL) {
34b3f194
EL
773 SCReturnInt(AFP_FAILURE);
774 }
b33986c8 775 PKT_SET_SRC(p, PKT_SRC_WIRE);
49b7b00f 776
4a1a0080
EL
777 /* Suricata will treat packet so telling it is busy, this
778 * status will be reset to 0 (ie TP_STATUS_KERNEL) in the release
779 * function. */
780 h.h2->tp_status |= TP_STATUS_USER_BUSY;
781
662dccd8
EL
782 from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
783
a369f8c3
EL
784 ptv->pkts++;
785 ptv->bytes += h.h2->tp_len;
a369f8c3
EL
786 p->livedev = ptv->livedev;
787
788 /* add forged header */
789 if (ptv->cooked) {
790 SllHdr * hdrp = (SllHdr *)ptv->data;
a369f8c3
EL
791 /* XXX this is minimalist, but this seems enough */
792 hdrp->sll_protocol = from->sll_protocol;
49b7b00f 793 }
a369f8c3
EL
794
795 p->datalink = ptv->datalink;
796 if (h.h2->tp_len > h.h2->tp_snaplen) {
797 SCLogDebug("Packet length (%d) > snaplen (%d), truncating",
798 h.h2->tp_len, h.h2->tp_snaplen);
799 }
71e47868
EL
800
801 /* get vlan id from header */
e871f713
EL
802 if ((!ptv->vlan_disabled) &&
803 (h.h2->tp_status & TP_STATUS_VLAN_VALID || h.h2->tp_vlan_tci)) {
71e47868
EL
804 p->vlan_id[0] = h.h2->tp_vlan_tci;
805 p->vlan_idx = 1;
806 p->vlanh[0] = NULL;
807 }
808
a369f8c3
EL
809 if (ptv->flags & AFP_ZERO_COPY) {
810 if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
811 TmqhOutputPacketpool(ptv->tv, p);
812 SCReturnInt(AFP_FAILURE);
662dccd8 813 } else {
0f2b3406 814 p->afp_v.relptr = h.raw;
b076a26c 815 p->ReleasePacket = AFPReleasePacket;
5f12b234
EL
816 p->afp_v.mpeer = ptv->mpeer;
817 AFPRefSocket(ptv->mpeer);
0f2b3406
EL
818
819 p->afp_v.copy_mode = ptv->copy_mode;
820 if (p->afp_v.copy_mode != AFP_COPY_MODE_NONE) {
821 p->afp_v.peer = ptv->mpeer->peer;
822 } else {
823 p->afp_v.peer = NULL;
662dccd8 824 }
a369f8c3
EL
825 }
826 } else {
827 if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
828 TmqhOutputPacketpool(ptv->tv, p);
829 SCReturnInt(AFP_FAILURE);
830 }
831 }
832 /* Timestamp */
833 p->ts.tv_sec = h.h2->tp_sec;
834 p->ts.tv_usec = h.h2->tp_nsec/1000;
835 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
836 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
837
838 /* We only check for checksum disable */
839 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
840 p->flags |= PKT_IGNORE_CHECKSUM;
841 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
842 if (ptv->livedev->ignore_checksum) {
843 p->flags |= PKT_IGNORE_CHECKSUM;
844 } else if (ChecksumAutoModeCheck(ptv->pkts,
845 SC_ATOMIC_GET(ptv->livedev->pkts),
846 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
847 ptv->livedev->ignore_checksum = 1;
848 p->flags |= PKT_IGNORE_CHECKSUM;
849 }
850 } else {
851 if (h.h2->tp_status & TP_STATUS_CSUMNOTREADY) {
49b7b00f 852 p->flags |= PKT_IGNORE_CHECKSUM;
a369f8c3 853 }
ee6ba099
EL
854 }
855 if (h.h2->tp_status & TP_STATUS_LOSING) {
856 emergency_flush = 1;
e8a4a4c4 857 AFPDumpCounters(ptv);
a369f8c3
EL
858 }
859
5f12b234
EL
860 /* release frame if not in zero copy mode */
861 if (!(ptv->flags & AFP_ZERO_COPY)) {
862 h.h2->tp_status = TP_STATUS_KERNEL;
863 }
864
a369f8c3
EL
865 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
866 h.h2->tp_status = TP_STATUS_KERNEL;
867 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
868 ptv->frame_offset = 0;
869 }
870 TmqhOutputPacketpool(ptv->tv, p);
871 SCReturnInt(AFP_FAILURE);
49b7b00f 872 }
49b7b00f 873
27b5136b 874next_frame:
34b3f194
EL
875 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
876 ptv->frame_offset = 0;
350d7619
EL
877 /* Get out of loop to be sure we will reach maintenance tasks */
878 SCReturnInt(AFP_READ_OK);
34b3f194 879 }
34b3f194
EL
880 }
881
49b7b00f
EL
882 SCReturnInt(AFP_READ_OK);
883}
884
13f13b6d
EL
885/**
886 * \brief Reference socket
887 *
888 * \retval O in case of failure, 1 in case of success
889 */
890static int AFPRefSocket(AFPPeer* peer)
891{
892 if (unlikely(peer == NULL))
893 return 0;
894
895 (void)SC_ATOMIC_ADD(peer->sock_usage, 1);
896 return 1;
897}
898
899
900/**
901 * \brief Dereference socket
902 *
903 * \retval 1 if socket is still alive, 0 if not
904 */
905static int AFPDerefSocket(AFPPeer* peer)
906{
4424f5a2
EL
907 if (peer == NULL)
908 return 1;
909
13f13b6d
EL
910 if (SC_ATOMIC_SUB(peer->sock_usage, 1) == 0) {
911 if (SC_ATOMIC_GET(peer->state) == AFP_STATE_DOWN) {
912 SCLogInfo("Cleaning socket connected to '%s'", peer->iface);
913 close(SC_ATOMIC_GET(peer->socket));
914 return 0;
915 }
916 }
917 return 1;
918}
919
920void AFPSwitchState(AFPThreadVars *ptv, int state)
921{
922 ptv->afp_state = state;
923 ptv->down_count = 0;
49b7b00f 924
13f13b6d
EL
925 AFPPeerUpdate(ptv);
926
927 /* Do cleaning if switching to down state */
928 if (state == AFP_STATE_DOWN) {
929 if (ptv->frame_buf) {
930 /* only used in reading phase, we can free it */
931 SCFree(ptv->frame_buf);
932 ptv->frame_buf = NULL;
933 }
934 if (ptv->socket != -1) {
935 /* we need to wait for all packets to return data */
936 if (SC_ATOMIC_SUB(ptv->mpeer->sock_usage, 1) == 0) {
937 SCLogInfo("Cleaning socket connected to '%s'", ptv->iface);
938 close(ptv->socket);
939 ptv->socket = -1;
940 }
941 }
942 }
943 if (state == AFP_STATE_UP) {
944 (void)SC_ATOMIC_SET(ptv->mpeer->sock_usage, 1);
945 }
946}
49b7b00f 947
919377d4
EL
948static int AFPReadAndDiscard(AFPThreadVars *ptv, struct timeval *synctv)
949{
950 struct sockaddr_ll from;
951 struct iovec iov;
952 struct msghdr msg;
953 struct timeval ts;
954 union {
955 struct cmsghdr cmsg;
956 char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
957 } cmsg_buf;
958
959
960 if (unlikely(suricata_ctl_flags != 0)) {
961 return 1;
962 }
963
964 msg.msg_name = &from;
965 msg.msg_namelen = sizeof(from);
966 msg.msg_iov = &iov;
967 msg.msg_iovlen = 1;
968 msg.msg_control = &cmsg_buf;
969 msg.msg_controllen = sizeof(cmsg_buf);
970 msg.msg_flags = 0;
971
972 iov.iov_len = ptv->datalen;
973 iov.iov_base = ptv->data;
974
975 recvmsg(ptv->socket, &msg, MSG_TRUNC);
976
977 if (ioctl(ptv->socket, SIOCGSTAMP, &ts) == -1) {
978 /* FIXME */
979 return -1;
980 }
981
982 if ((ts.tv_sec > synctv->tv_sec) ||
983 (ts.tv_sec >= synctv->tv_sec &&
984 ts.tv_usec > synctv->tv_usec)) {
985 return 1;
986 }
987 return 0;
988}
989
990static int AFPReadAndDiscardFromRing(AFPThreadVars *ptv, struct timeval *synctv)
991{
992 union thdr h;
993
994 if (unlikely(suricata_ctl_flags != 0)) {
995 return 1;
996 }
997
998 /* Read packet from ring */
999 h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
1000 if (h.raw == NULL) {
1001 return -1;
1002 }
1003
1004 if (((time_t)h.h2->tp_sec > synctv->tv_sec) ||
1005 ((time_t)h.h2->tp_sec == synctv->tv_sec &&
1006 (suseconds_t) (h.h2->tp_nsec / 1000) > synctv->tv_usec)) {
1007 return 1;
1008 }
1009
1010 h.h2->tp_status = TP_STATUS_KERNEL;
1011 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
1012 ptv->frame_offset = 0;
1013 }
1014
1015
1016 return 0;
1017}
1018
806844d8
VJ
1019/** \brief wait for all afpacket threads to fully init
1020 *
1021 * Discard packets before all threads are ready, as the cluster
1022 * setup is not complete yet.
1023 *
1024 * if AFPPeersListStarted() returns true init is complete
1025 *
1026 * \retval r 1 = happy, otherwise unhappy
1027 */
919377d4
EL
1028static int AFPSynchronizeStart(AFPThreadVars *ptv)
1029{
1030 int r;
1031 struct timeval synctv;
806844d8
VJ
1032 struct pollfd fds;
1033
1034 fds.fd = ptv->socket;
1035 fds.events = POLLIN;
919377d4
EL
1036
1037 /* Set timeval to end of the world */
1038 synctv.tv_sec = 0xffffffff;
1039 synctv.tv_usec = 0xffffffff;
1040
1041 while (1) {
806844d8
VJ
1042 r = poll(&fds, 1, POLL_TIMEOUT);
1043 if (r > 0 &&
1044 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1045 SCLogWarning(SC_ERR_AFP_READ, "poll failed %02x",
1046 fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL));
1047 return 0;
1048 } else if (r > 0) {
1049 if (AFPPeersListStarted() && synctv.tv_sec == (time_t) 0xffffffff) {
1050 gettimeofday(&synctv, NULL);
1051 }
1052 if (ptv->flags & AFP_RING_MODE) {
1053 r = AFPReadAndDiscardFromRing(ptv, &synctv);
1054 } else {
1055 r = AFPReadAndDiscard(ptv, &synctv);
1056 }
1057 SCLogDebug("Discarding on %s", ptv->tv->name);
1058 switch (r) {
1059 case 1:
1060 SCLogInfo("Starting to read on %s", ptv->tv->name);
1061 return 1;
1062 case -1:
1063 return r;
1064 }
1065 /* no packets */
1066 } else if (r == 0 && AFPPeersListStarted()) {
1067 SCLogInfo("Starting to read on %s", ptv->tv->name);
1068 return 1;
919377d4 1069 } else {
806844d8
VJ
1070 SCLogWarning(SC_ERR_AFP_READ, "poll failed with retval %d", r);
1071 return 0;
919377d4
EL
1072 }
1073 }
1074 return 1;
1075}
1076
13f13b6d
EL
1077/**
1078 * \brief Try to reopen socket
1079 *
1080 * \retval 0 in case of success, negative if error occurs or a condition
1081 * is not met.
1082 */
c45d8985
EL
1083static int AFPTryReopen(AFPThreadVars *ptv)
1084{
1085 int afp_activate_r;
1086
13f13b6d
EL
1087 ptv->down_count++;
1088
1089
1090 /* Don't reconnect till we have packet that did not release data */
1091 if (SC_ATOMIC_GET(ptv->mpeer->sock_usage) != 0) {
1092 return -1;
1093 }
c45d8985 1094
e80b30c0 1095 afp_activate_r = AFPCreateSocket(ptv, ptv->iface, 0);
c45d8985 1096 if (afp_activate_r != 0) {
13f13b6d
EL
1097 if (ptv->down_count % AFP_DOWN_COUNTER_INTERVAL == 0) {
1098 SCLogWarning(SC_ERR_AFP_CREATE, "Can not open iface '%s'",
1099 ptv->iface);
1100 }
c45d8985
EL
1101 return afp_activate_r;
1102 }
1103
3bea3b39 1104 SCLogInfo("Interface '%s' is back", ptv->iface);
c45d8985
EL
1105 return 0;
1106}
1107
e80b30c0
EL
1108/**
1109 * \brief Main AF_PACKET reading Loop function
1110 */
1111TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
1112{
34581ce9
AS
1113 SCEnter();
1114
e80b30c0
EL
1115 uint16_t packet_q_len = 0;
1116 AFPThreadVars *ptv = (AFPThreadVars *)data;
e80b30c0
EL
1117 struct pollfd fds;
1118 int r;
34581ce9 1119 TmSlot *s = (TmSlot *)slot;
e8a4a4c4
EL
1120 time_t last_dump = 0;
1121 struct timeval current_time;
e80b30c0 1122
34581ce9 1123 ptv->slot = s->slot_next;
e80b30c0 1124
60400163
EL
1125 if (ptv->afp_state == AFP_STATE_DOWN) {
1126 /* Wait for our turn, threads before us must have opened the socket */
1127 while (AFPPeersListWaitTurn(ptv->mpeer)) {
1128 usleep(1000);
1129 }
1130 r = AFPCreateSocket(ptv, ptv->iface, 1);
1131 if (r < 0) {
1132 SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket");
1133 }
1134 AFPPeersListReachedInc();
1135 }
1136 if (ptv->afp_state == AFP_STATE_UP) {
1137 SCLogInfo("Thread %s using socket %d", tv->name, ptv->socket);
919377d4 1138 AFPSynchronizeStart(ptv);
60400163
EL
1139 }
1140
e80b30c0
EL
1141 fds.fd = ptv->socket;
1142 fds.events = POLLIN;
1143
1144 while (1) {
1145 /* Start by checking the state of our interface */
1146 if (unlikely(ptv->afp_state == AFP_STATE_DOWN)) {
1147 int dbreak = 0;
662dccd8 1148
e80b30c0
EL
1149 do {
1150 usleep(AFP_RECONNECT_TIMEOUT);
1151 if (suricata_ctl_flags != 0) {
1152 dbreak = 1;
1153 break;
1154 }
1155 r = AFPTryReopen(ptv);
09e709d1 1156 fds.fd = ptv->socket;
e80b30c0
EL
1157 } while (r < 0);
1158 if (dbreak == 1)
1159 break;
1160 }
1161
1162 /* make sure we have at least one packet in the packet pool, to prevent
1163 * us from alloc'ing packets at line rate */
1164 do {
1165 packet_q_len = PacketPoolSize();
1166 if (unlikely(packet_q_len == 0)) {
1167 PacketPoolWait();
1168 }
1169 } while (packet_q_len == 0);
1170
1171 r = poll(&fds, 1, POLL_TIMEOUT);
1172
1173 if (suricata_ctl_flags != 0) {
1174 break;
1175 }
1176
1177 if (r > 0 &&
1178 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1179 if (fds.revents & (POLLHUP | POLLRDHUP)) {
13f13b6d 1180 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0 1181 continue;
ff6365dd 1182 } else if (fds.revents & POLLERR) {
e80b30c0
EL
1183 char c;
1184 /* Do a recv to get errno */
1185 if (recv(ptv->socket, &c, sizeof c, MSG_PEEK) != -1)
1186 continue; /* what, no error? */
3bea3b39
EL
1187 SCLogError(SC_ERR_AFP_READ,
1188 "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1189 ptv->iface, errno, strerror(errno));
13f13b6d 1190 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0 1191 continue;
ff6365dd 1192 } else if (fds.revents & POLLNVAL) {
e80b30c0 1193 SCLogError(SC_ERR_AFP_READ, "Invalid polling request");
13f13b6d 1194 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0
EL
1195 continue;
1196 }
1197 } else if (r > 0) {
49b7b00f
EL
1198 if (ptv->flags & AFP_RING_MODE) {
1199 r = AFPReadFromRing(ptv);
1200 } else {
1201 /* AFPRead will call TmThreadsSlotProcessPkt on read packets */
1202 r = AFPRead(ptv);
1203 }
62e63e3f
EL
1204 switch (r) {
1205 case AFP_READ_FAILURE:
1206 /* AFPRead in error: best to reset the socket */
3bea3b39
EL
1207 SCLogError(SC_ERR_AFP_READ,
1208 "AFPRead error reading data from iface '%s': (%d" PRIu32 ") %s",
1209 ptv->iface, errno, strerror(errno));
13f13b6d 1210 AFPSwitchState(ptv, AFP_STATE_DOWN);
62e63e3f
EL
1211 continue;
1212 case AFP_FAILURE:
13f13b6d 1213 AFPSwitchState(ptv, AFP_STATE_DOWN);
62e63e3f
EL
1214 SCReturnInt(TM_ECODE_FAILED);
1215 break;
1216 case AFP_READ_OK:
e8a4a4c4
EL
1217 /* Trigger one dump of stats every second */
1218 TimeGet(&current_time);
1219 if (current_time.tv_sec != last_dump) {
1220 AFPDumpCounters(ptv);
1221 last_dump = current_time.tv_sec;
1222 }
62e63e3f 1223 break;
27b5136b 1224 case AFP_KERNEL_DROP:
e8a4a4c4 1225 AFPDumpCounters(ptv);
27b5136b 1226 break;
e80b30c0
EL
1227 }
1228 } else if ((r < 0) && (errno != EINTR)) {
3bea3b39
EL
1229 SCLogError(SC_ERR_AFP_READ, "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1230 ptv->iface,
e80b30c0 1231 errno, strerror(errno));
13f13b6d 1232 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0
EL
1233 continue;
1234 }
677cd03e 1235 SCPerfSyncCountersIfSignalled(tv);
e80b30c0
EL
1236 }
1237
4e561d6b
VJ
1238 AFPDumpCounters(ptv);
1239 SCPerfSyncCountersIfSignalled(tv);
e80b30c0
EL
1240 SCReturnInt(TM_ECODE_OK);
1241}
1242
13f13b6d
EL
1243static int AFPGetDevFlags(int fd, const char *ifname)
1244{
1245 struct ifreq ifr;
1246
1247 memset(&ifr, 0, sizeof(ifr));
1248 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1249
1250 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
1251 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1252 ifname, strerror(errno));
1253 return -1;
1254 }
1255
1256 return ifr.ifr_flags;
1257}
1258
1259
e80b30c0 1260static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose)
c45d8985
EL
1261{
1262 struct ifreq ifr;
1263
1264 memset(&ifr, 0, sizeof(ifr));
e80b30c0 1265 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
c45d8985
EL
1266
1267 if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
1268 if (verbose)
1269 SCLogError(SC_ERR_AFP_CREATE, "Unable to find iface %s: %s",
1270 ifname, strerror(errno));
1271 return -1;
1272 }
1273
1274 return ifr.ifr_ifindex;
1275}
1276
e80b30c0 1277static int AFPGetDevLinktype(int fd, const char *ifname)
c45d8985
EL
1278{
1279 struct ifreq ifr;
1280
1281 memset(&ifr, 0, sizeof(ifr));
e80b30c0 1282 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
c45d8985
EL
1283
1284 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
1285 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1286 ifname, strerror(errno));
1287 return -1;
1288 }
1289
e80b30c0
EL
1290 switch (ifr.ifr_hwaddr.sa_family) {
1291 case ARPHRD_LOOPBACK:
1292 return LINKTYPE_ETHERNET;
1293 case ARPHRD_PPP:
1294 return LINKTYPE_RAW;
1295 default:
1296 return ifr.ifr_hwaddr.sa_family;
1297 }
c45d8985
EL
1298}
1299
49b7b00f
EL
1300static int AFPComputeRingParams(AFPThreadVars *ptv, int order)
1301{
1302 /* Compute structure:
1303 Target is to store all pending packets
1304 with a size equal to MTU + auxdata
1305 And we keep a decent number of block
1306
1307 To do so:
1308 Compute frame_size (aligned to be able to fit in block
1309 Check which block size we need. Blocksize is a 2^n * pagesize
1310 We then need to get order, big enough to have
1311 frame_size < block size
1312 Find number of frame per block (divide)
1313 Fill in packet_req
1314
1315 Compute frame size:
1316 described in packet_mmap.txt
1317 dependant on snaplen (need to use a variable ?)
1318snaplen: MTU ?
1319tp_hdrlen determine_version in daq_afpacket
1320in V1: sizeof(struct tpacket_hdr);
1321in V2: val in getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len)
1322frame size: TPACKET_ALIGN(snaplen + TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1323
1324 */
1325 int tp_hdrlen = sizeof(struct tpacket_hdr);
1326 int snaplen = default_packet_size;
1327
1328 ptv->req.tp_frame_size = TPACKET_ALIGN(snaplen +TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1329 ptv->req.tp_block_size = getpagesize() << order;
1330 int frames_per_block = ptv->req.tp_block_size / ptv->req.tp_frame_size;
1331 if (frames_per_block == 0) {
1332 SCLogInfo("frame size to big");
1333 return -1;
1334 }
8879df80 1335 ptv->req.tp_frame_nr = ptv->ring_size;
d8d9b098 1336 ptv->req.tp_block_nr = ptv->req.tp_frame_nr / frames_per_block + 1;
49b7b00f
EL
1337 /* exact division */
1338 ptv->req.tp_frame_nr = ptv->req.tp_block_nr * frames_per_block;
1339 SCLogInfo("AF_PACKET RX Ring params: block_size=%d block_nr=%d frame_size=%d frame_nr=%d",
1340 ptv->req.tp_block_size, ptv->req.tp_block_nr,
1341 ptv->req.tp_frame_size, ptv->req.tp_frame_nr);
1342 return 1;
1343}
1344
e80b30c0 1345static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
c45d8985
EL
1346{
1347 int r;
1348 struct packet_mreq sock_params;
1349 struct sockaddr_ll bind_address;
49b7b00f
EL
1350 int order;
1351 unsigned int i;
662dccd8 1352 int if_idx;
49b7b00f 1353
c45d8985
EL
1354 /* open socket */
1355 ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1356 if (ptv->socket == -1) {
e80b30c0 1357 SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
13f13b6d 1358 goto error;
c45d8985 1359 }
662dccd8 1360 if_idx = AFPGetIfnumByDev(ptv->socket, devname, verbose);
c45d8985
EL
1361 /* bind socket */
1362 memset(&bind_address, 0, sizeof(bind_address));
1363 bind_address.sll_family = AF_PACKET;
1364 bind_address.sll_protocol = htons(ETH_P_ALL);
662dccd8 1365 bind_address.sll_ifindex = if_idx;
c45d8985
EL
1366 if (bind_address.sll_ifindex == -1) {
1367 if (verbose)
e80b30c0 1368 SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
13f13b6d
EL
1369 goto socket_err;
1370 }
1371
13f13b6d
EL
1372 if (ptv->promisc != 0) {
1373 /* Force promiscuous mode */
1374 memset(&sock_params, 0, sizeof(sock_params));
1375 sock_params.mr_type = PACKET_MR_PROMISC;
1376 sock_params.mr_ifindex = bind_address.sll_ifindex;
1377 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(void *)&sock_params, sizeof(sock_params));
1378 if (r < 0) {
1379 SCLogError(SC_ERR_AFP_CREATE,
1380 "Couldn't switch iface %s to promiscuous, error %s",
1381 devname, strerror(errno));
1382 goto frame_err;
1383 }
1384 }
1385
1386 if (ptv->checksum_mode == CHECKSUM_VALIDATION_KERNEL) {
1387 int val = 1;
1388 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_AUXDATA, &val,
1389 sizeof(val)) == -1 && errno != ENOPROTOOPT) {
1390 SCLogWarning(SC_ERR_NO_AF_PACKET,
1391 "'kernel' checksum mode not supported, failling back to full mode.");
1392 ptv->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
1393 }
1394 }
1395
1396 /* set socket recv buffer size */
1397 if (ptv->buffer_size != 0) {
1398 /*
1399 * Set the socket buffer size to the specified value.
1400 */
1401 SCLogInfo("Setting AF_PACKET socket buffer to %d", ptv->buffer_size);
1402 if (setsockopt(ptv->socket, SOL_SOCKET, SO_RCVBUF,
1403 &ptv->buffer_size,
1404 sizeof(ptv->buffer_size)) == -1) {
1405 SCLogError(SC_ERR_AFP_CREATE,
1406 "Couldn't set buffer size to %d on iface %s, error %s",
1407 ptv->buffer_size, devname, strerror(errno));
1408 goto frame_err;
1409 }
1410 }
1411
1412 r = bind(ptv->socket, (struct sockaddr *)&bind_address, sizeof(bind_address));
1413 if (r < 0) {
1414 if (verbose) {
1415 if (errno == ENETDOWN) {
1416 SCLogError(SC_ERR_AFP_CREATE,
1417 "Couldn't bind AF_PACKET socket, iface %s is down",
1418 devname);
1419 } else {
1420 SCLogError(SC_ERR_AFP_CREATE,
1421 "Couldn't bind AF_PACKET socket to iface %s, error %s",
1422 devname, strerror(errno));
1423 }
1424 }
1425 goto frame_err;
1426 }
1427
238ff231
EL
1428#ifdef HAVE_PACKET_FANOUT
1429 /* add binded socket to fanout group */
1430 if (ptv->threads > 1) {
1431 uint32_t option = 0;
1432 uint16_t mode = ptv->cluster_type;
1433 uint16_t id = ptv->cluster_id;
1434 option = (mode << 16) | (id & 0xffff);
1435 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
1436 if (r < 0) {
1437 SCLogError(SC_ERR_AFP_CREATE,
1438 "Coudn't set fanout mode, error %s",
1439 strerror(errno));
1440 goto frame_err;
1441 }
1442 }
1443#endif
1444
13f13b6d
EL
1445 int if_flags = AFPGetDevFlags(ptv->socket, ptv->iface);
1446 if (if_flags == -1) {
1447 if (verbose) {
1448 SCLogError(SC_ERR_AFP_READ,
1449 "Can not acces to interface '%s'",
1450 ptv->iface);
1451 }
1452 goto frame_err;
1453 }
1454 if ((if_flags & IFF_UP) == 0) {
1455 if (verbose) {
1456 SCLogError(SC_ERR_AFP_READ,
1457 "Interface '%s' is down",
1458 ptv->iface);
1459 }
1460 goto frame_err;
c45d8985 1461 }
49b7b00f
EL
1462
1463 if (ptv->flags & AFP_RING_MODE) {
1464 int val = TPACKET_V2;
1465 unsigned int len = sizeof(val);
1466 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
1467 if (errno == ENOPROTOOPT) {
1468 SCLogError(SC_ERR_AFP_CREATE,
1469 "Too old kernel giving up (need 2.6.27 at least)");
1470 }
1471 SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len");
13f13b6d 1472 goto socket_err;
49b7b00f
EL
1473 }
1474 ptv->tp_hdrlen = val;
1475
1476 val = TPACKET_V2;
1477 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val,
1478 sizeof(val)) < 0) {
1479 SCLogError(SC_ERR_AFP_CREATE,
1480 "Can't activate TPACKET_V2 on packet socket: %s",
1481 strerror(errno));
13f13b6d 1482 goto socket_err;
49b7b00f
EL
1483 }
1484
2855ee5a
EL
1485 if (GetIfaceOffloading(devname) == 1) {
1486 SCLogWarning(SC_ERR_AFP_CREATE,
1487 "Using mmap mode with GRO or LRO activated can lead to capture problems");
1488 }
1489
49b7b00f
EL
1490 /* Allocate RX ring */
1491#define DEFAULT_ORDER 3
1492 for (order = DEFAULT_ORDER; order >= 0; order--) {
1493 if (AFPComputeRingParams(ptv, order) != 1) {
1494 SCLogInfo("Ring parameter are incorrect. Please correct the devel");
1495 }
1496
1497 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, (void *) &ptv->req, sizeof(ptv->req));
1498 if (r < 0) {
1499 if (errno == ENOMEM) {
1500 SCLogInfo("Memory issue with ring parameters. Retrying.");
1501 continue;
1502 }
1503 SCLogError(SC_ERR_MEM_ALLOC,
1504 "Unable to allocate RX Ring for iface %s: (%d) %s",
1505 devname,
1506 errno,
1507 strerror(errno));
13f13b6d 1508 goto socket_err;
49b7b00f
EL
1509 } else {
1510 break;
1511 }
1512 }
1513
1514 if (order < 0) {
1515 SCLogError(SC_ERR_MEM_ALLOC,
1516 "Unable to allocate RX Ring for iface %s (order 0 failed)",
1517 devname);
13f13b6d 1518 goto socket_err;
49b7b00f
EL
1519 }
1520
1521 /* Allocate the Ring */
1522 ptv->ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
1523 ptv->ring_buf = mmap(0, ptv->ring_buflen, PROT_READ|PROT_WRITE,
1524 MAP_SHARED, ptv->socket, 0);
1525 if (ptv->ring_buf == MAP_FAILED) {
1526 SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap");
13f13b6d 1527 goto socket_err;
49b7b00f
EL
1528 }
1529 /* allocate a ring for each frame header pointer*/
1530 ptv->frame_buf = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *));
1531 if (ptv->frame_buf == NULL) {
1532 SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf");
13f13b6d 1533 goto mmap_err;
49b7b00f
EL
1534 }
1535 memset(ptv->frame_buf, 0, ptv->req.tp_frame_nr * sizeof (union thdr *));
1536 /* fill the header ring with proper frame ptr*/
1537 ptv->frame_offset = 0;
1538 for (i = 0; i < ptv->req.tp_block_nr; ++i) {
1539 void *base = &ptv->ring_buf[i * ptv->req.tp_block_size];
1540 unsigned int j;
1541 for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
1542 (((union thdr **)ptv->frame_buf)[ptv->frame_offset]) = base;
1543 base += ptv->req.tp_frame_size;
1544 }
1545 }
1546 ptv->frame_offset = 0;
1547 }
1548
13f13b6d 1549 SCLogInfo("Using interface '%s' via socket %d", (char *)devname, ptv->socket);
ec76742c 1550
c45d8985 1551
c85ee1e3
EL
1552 ptv->datalink = AFPGetDevLinktype(ptv->socket, ptv->iface);
1553 switch (ptv->datalink) {
1554 case ARPHRD_PPP:
1555 case ARPHRD_ATM:
1556 ptv->cooked = 1;
619414c5 1557 break;
c85ee1e3
EL
1558 }
1559
f2a6fb8a
EL
1560 TmEcode rc;
1561 rc = AFPSetBPFFilter(ptv);
1562 if (rc == TM_ECODE_FAILED) {
1563 SCLogError(SC_ERR_AFP_CREATE, "Set AF_PACKET bpf filter \"%s\" failed.", ptv->bpf_filter);
13f13b6d 1564 goto frame_err;
f2a6fb8a
EL
1565 }
1566
49b7b00f 1567 /* Init is ok */
13f13b6d 1568 AFPSwitchState(ptv, AFP_STATE_UP);
c45d8985 1569 return 0;
13f13b6d
EL
1570
1571frame_err:
1572 if (ptv->frame_buf)
1573 SCFree(ptv->frame_buf);
1574mmap_err:
1575 /* Packet mmap does the cleaning when socket is closed */
1576socket_err:
1577 close(ptv->socket);
1578 ptv->socket = -1;
1579error:
1580 return -1;
c45d8985
EL
1581}
1582
f2a6fb8a
EL
1583TmEcode AFPSetBPFFilter(AFPThreadVars *ptv)
1584{
1585 struct bpf_program filter;
1586 struct sock_fprog fcode;
1587 int rc;
1588
1589 if (!ptv->bpf_filter)
1590 return TM_ECODE_OK;
1591
1592 SCMutexLock(&afpacket_bpf_set_filter_lock);
1593
1594 SCLogInfo("Using BPF '%s' on iface '%s'",
1595 ptv->bpf_filter,
1596 ptv->iface);
1597 if (pcap_compile_nopcap(default_packet_size, /* snaplen_arg */
1598 ptv->datalink, /* linktype_arg */
1599 &filter, /* program */
1600 ptv->bpf_filter, /* const char *buf */
1601 0, /* optimize */
1602 0 /* mask */
1603 ) == -1) {
1604 SCLogError(SC_ERR_AFP_CREATE, "Filter compilation failed.");
1605 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1606 return TM_ECODE_FAILED;
1607 }
1608 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1609
1610 if (filter.bf_insns == NULL) {
1611 SCLogError(SC_ERR_AFP_CREATE, "Filter badly setup.");
1612 return TM_ECODE_FAILED;
1613 }
1614
1615 fcode.len = filter.bf_len;
1616 fcode.filter = (struct sock_filter*)filter.bf_insns;
1617
1618 rc = setsockopt(ptv->socket, SOL_SOCKET, SO_ATTACH_FILTER, &fcode, sizeof(fcode));
1619
1620 if(rc == -1) {
1621 SCLogError(SC_ERR_AFP_CREATE, "Failed to attach filter: %s", strerror(errno));
1622 return TM_ECODE_FAILED;
1623 }
1624
1625 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1626 return TM_ECODE_OK;
1627}
1628
c45d8985
EL
1629
1630/**
1631 * \brief Init function for ReceiveAFP.
1632 *
1633 * \param tv pointer to ThreadVars
1634 * \param initdata pointer to the interface passed from the user
1635 * \param data pointer gets populated with AFPThreadVars
1636 *
1637 * \todo Create a general AFP setup function.
1638 */
1639TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
1640 SCEnter();
fbca1a4e 1641 AFPIfaceConfig *afpconfig = initdata;
c45d8985 1642
c45d8985
EL
1643 if (initdata == NULL) {
1644 SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL");
1645 SCReturnInt(TM_ECODE_FAILED);
1646 }
1647
1648 AFPThreadVars *ptv = SCMalloc(sizeof(AFPThreadVars));
e176be6f 1649 if (unlikely(ptv == NULL)) {
45d5c3ca 1650 afpconfig->DerefFunc(afpconfig);
c45d8985 1651 SCReturnInt(TM_ECODE_FAILED);
45d5c3ca 1652 }
c45d8985
EL
1653 memset(ptv, 0, sizeof(AFPThreadVars));
1654
1655 ptv->tv = tv;
1656 ptv->cooked = 0;
1657
fbca1a4e 1658 strlcpy(ptv->iface, afpconfig->iface, AFP_IFACE_NAME_LENGTH);
c45d8985
EL
1659 ptv->iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
1660
51eb9605
EL
1661 ptv->livedev = LiveGetDevice(ptv->iface);
1662 if (ptv->livedev == NULL) {
1663 SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device");
11bdf483 1664 SCFree(ptv);
51eb9605
EL
1665 SCReturnInt(TM_ECODE_FAILED);
1666 }
1667
fbca1a4e 1668 ptv->buffer_size = afpconfig->buffer_size;
8879df80 1669 ptv->ring_size = afpconfig->ring_size;
e80b30c0 1670
df7dbe36 1671 ptv->promisc = afpconfig->promisc;
6062e00c 1672 ptv->checksum_mode = afpconfig->checksum_mode;
6efd37a3 1673 ptv->bpf_filter = NULL;
df7dbe36 1674
fbca1a4e 1675 ptv->threads = 1;
e80b30c0
EL
1676#ifdef HAVE_PACKET_FANOUT
1677 ptv->cluster_type = PACKET_FANOUT_LB;
1678 ptv->cluster_id = 1;
1679 /* We only set cluster info if the number of reader threads is greater than 1 */
fbca1a4e
EL
1680 if (afpconfig->threads > 1) {
1681 ptv->cluster_id = afpconfig->cluster_id;
1682 ptv->cluster_type = afpconfig->cluster_type;
1683 ptv->threads = afpconfig->threads;
e80b30c0
EL
1684 }
1685#endif
49b7b00f 1686 ptv->flags = afpconfig->flags;
e80b30c0 1687
f2a6fb8a
EL
1688 if (afpconfig->bpf_filter) {
1689 ptv->bpf_filter = afpconfig->bpf_filter;
1690 }
1691
6efd37a3
EL
1692#ifdef PACKET_STATISTICS
1693 ptv->capture_kernel_packets = SCPerfTVRegisterCounter("capture.kernel_packets",
1694 ptv->tv,
1695 SC_PERF_TYPE_UINT64,
1696 "NULL");
1697 ptv->capture_kernel_drops = SCPerfTVRegisterCounter("capture.kernel_drops",
1698 ptv->tv,
1699 SC_PERF_TYPE_UINT64,
1700 "NULL");
1701#endif
1702
34b3f194
EL
1703 char *active_runmode = RunmodeGetActive();
1704
1705 if (active_runmode && !strcmp("workers", active_runmode)) {
1706 ptv->flags |= AFP_ZERO_COPY;
1707 SCLogInfo("Enabling zero copy mode");
662dccd8
EL
1708 } else {
1709 /* If we are using copy mode we need a lock */
1710 ptv->flags |= AFP_SOCK_PROTECT;
34b3f194 1711 }
2011a3f8
EL
1712
1713 /* If we are in RING mode, then we can use ZERO copy
1714 * by using the data release mechanism */
1715 if (ptv->flags & AFP_RING_MODE) {
1716 ptv->flags |= AFP_ZERO_COPY;
1717 SCLogInfo("Enabling zero copy mode by using data release call");
1718 }
34b3f194 1719
662dccd8
EL
1720 ptv->copy_mode = afpconfig->copy_mode;
1721 if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
1722 strlcpy(ptv->out_iface, afpconfig->out_iface, AFP_IFACE_NAME_LENGTH);
1723 ptv->out_iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
b7e78d33
EL
1724 /* Warn about BPF filter consequence */
1725 if (ptv->bpf_filter) {
1726 SCLogWarning(SC_WARN_UNCOMMON, "Enabling a BPF filter in IPS mode result"
1727 " in dropping all non matching packets.");
1728 }
662dccd8 1729 }
c85ee1e3 1730
b7e78d33 1731
0581a23f
EL
1732 if (AFPPeersListAdd(ptv) == TM_ECODE_FAILED) {
1733 SCFree(ptv);
1734 afpconfig->DerefFunc(afpconfig);
1735 SCReturnInt(TM_ECODE_FAILED);
1736 }
1737
e80b30c0
EL
1738#define T_DATA_SIZE 70000
1739 ptv->data = SCMalloc(T_DATA_SIZE);
1740 if (ptv->data == NULL) {
45d5c3ca 1741 afpconfig->DerefFunc(afpconfig);
6019ae3d 1742 SCFree(ptv);
e80b30c0 1743 SCReturnInt(TM_ECODE_FAILED);
c45d8985 1744 }
e80b30c0
EL
1745 ptv->datalen = T_DATA_SIZE;
1746#undef T_DATA_SIZE
1747
c45d8985 1748 *data = (void *)ptv;
fbca1a4e 1749
45d5c3ca 1750 afpconfig->DerefFunc(afpconfig);
71e47868
EL
1751
1752 /* A bit strange to have this here but we only have vlan information
1753 * during reading so we need to know if we want to keep vlan during
1754 * the capture phase */
1755 int vlanbool = 0;
1756 if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
1757 ptv->vlan_disabled = 1;
1758 }
1759
2cd6e128
EL
1760 /* If kernel is older than 3.0, VLAN is not stripped so we don't
1761 * get the info from packet extended header but we will use a standard
1762 * parsing of packet data (See Linux commit bcc6d47903612c3861201cc3a866fb604f26b8b2) */
1763 if (! SCKernelVersionIsAtLeast(3, 0)) {
1764 ptv->vlan_disabled = 1;
1765 }
1766
c45d8985
EL
1767 SCReturnInt(TM_ECODE_OK);
1768}
1769
1770/**
1771 * \brief This function prints stats to the screen at exit.
1772 * \param tv pointer to ThreadVars
1773 * \param data pointer that gets cast into AFPThreadVars for ptv
1774 */
1775void ReceiveAFPThreadExitStats(ThreadVars *tv, void *data) {
1776 SCEnter();
1777 AFPThreadVars *ptv = (AFPThreadVars *)data;
9549faae
EL
1778
1779#ifdef PACKET_STATISTICS
e8a4a4c4 1780 AFPDumpCounters(ptv);
6efd37a3
EL
1781 SCLogInfo("(%s) Kernel: Packets %" PRIu64 ", dropped %" PRIu64 "",
1782 tv->name,
1783 (uint64_t) SCPerfGetLocalCounterValue(ptv->capture_kernel_packets, tv->sc_perf_pca),
1784 (uint64_t) SCPerfGetLocalCounterValue(ptv->capture_kernel_drops, tv->sc_perf_pca));
9549faae 1785#endif
e80b30c0 1786
3ce39433 1787 SCLogInfo("(%s) Packets %" PRIu64 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes);
c45d8985
EL
1788}
1789
1790/**
1791 * \brief DeInit function closes af packet socket at exit.
1792 * \param tv pointer to ThreadVars
1793 * \param data pointer that gets cast into AFPThreadVars for ptv
1794 */
1795TmEcode ReceiveAFPThreadDeinit(ThreadVars *tv, void *data) {
1796 AFPThreadVars *ptv = (AFPThreadVars *)data;
1797
13f13b6d
EL
1798 AFPSwitchState(ptv, AFP_STATE_DOWN);
1799
e80b30c0
EL
1800 if (ptv->data != NULL) {
1801 SCFree(ptv->data);
1802 ptv->data = NULL;
1803 }
1804 ptv->datalen = 0;
1805
f2a6fb8a
EL
1806 ptv->bpf_filter = NULL;
1807
c45d8985
EL
1808 SCReturnInt(TM_ECODE_OK);
1809}
1810
1811/**
1812 * \brief This function passes off to link type decoders.
1813 *
1814 * DecodeAFP reads packets from the PacketQueue and passes
1815 * them off to the proper link type decoder.
1816 *
1817 * \param t pointer to ThreadVars
1818 * \param p pointer to the current packet
1819 * \param data pointer that gets cast into AFPThreadVars for ptv
1820 * \param pq pointer to the current PacketQueue
1821 */
1822TmEcode DecodeAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
1823{
1824 SCEnter();
1825 DecodeThreadVars *dtv = (DecodeThreadVars *)data;
1826
f7b1aefa
VJ
1827 /* XXX HACK: flow timeout can call us for injected pseudo packets
1828 * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */
1829 if (p->flags & PKT_PSEUDO_STREAM_END)
1830 return TM_ECODE_OK;
1831
c45d8985
EL
1832 /* update counters */
1833 SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca);
698ff4e4 1834// SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca);
c45d8985
EL
1835
1836 SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p));
1837#if 0
1838 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p));
1839 SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca,
1840 (GET_PKT_LEN(p) * 8)/1000000.0);
1841#endif
1842
1843 SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
1844 SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
1845
1fb7c0dd
EL
1846 /* If suri has set vlan during reading, we increase vlan counter */
1847 if (p->vlan_idx) {
1848 SCPerfCounterIncr(dtv->counter_vlan, tv->sc_perf_pca);
1849 }
1850
c45d8985
EL
1851 /* call the decoder */
1852 switch(p->datalink) {
1853 case LINKTYPE_LINUX_SLL:
1854 DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1855 break;
1856 case LINKTYPE_ETHERNET:
1857 DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1858 break;
1859 case LINKTYPE_PPP:
1860 DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1861 break;
1862 case LINKTYPE_RAW:
1863 DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1864 break;
1865 default:
1866 SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeAFP", p->datalink);
1867 break;
1868 }
1869
3088b6ac 1870 PacketDecodeFinalize(tv, dtv, p);
e7f09f24 1871
c45d8985
EL
1872 SCReturnInt(TM_ECODE_OK);
1873}
1874
1875TmEcode DecodeAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
1876{
1877 SCEnter();
1878 DecodeThreadVars *dtv = NULL;
1879
5f307aca 1880 dtv = DecodeThreadVarsAlloc(tv);
c45d8985
EL
1881
1882 if (dtv == NULL)
1883 SCReturnInt(TM_ECODE_FAILED);
1884
1885 DecodeRegisterPerfCounters(dtv, tv);
1886
1887 *data = (void *)dtv;
1888
e7f09f24
AS
1889#ifdef __SC_CUDA_SUPPORT__
1890 if (CudaThreadVarsInit(&dtv->cuda_vars) < 0)
1891 SCReturnInt(TM_ECODE_FAILED);
1892#endif
1893
c45d8985
EL
1894 SCReturnInt(TM_ECODE_OK);
1895}
1896
e80b30c0 1897#endif /* HAVE_AF_PACKET */
c45d8985 1898/* eof */
a6457262
EL
1899/**
1900 * @}
1901 */