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