]> git.ipfire.org Git - people/ms/suricata.git/blame - src/source-af-packet.c
af-packet: remove useless code
[people/ms/suricata.git] / src / source-af-packet.c
CommitLineData
3c6e01f6 1/* Copyright (C) 2011-2014 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 int max_pending_packets;
100
e80b30c0
EL
101#ifndef HAVE_AF_PACKET
102
103TmEcode NoAFPSupportExit(ThreadVars *, void *, void **);
104
8f1d7503
KS
105void TmModuleReceiveAFPRegister (void)
106{
e80b30c0
EL
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 */
8f1d7503
KS
121void TmModuleDecodeAFPRegister (void)
122{
e80b30c0
EL
123 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
124 tmm_modules[TMM_DECODEAFP].ThreadInit = NoAFPSupportExit;
125 tmm_modules[TMM_DECODEAFP].Func = NULL;
126 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
127 tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
128 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
129 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
bc6cf438 130 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
e80b30c0
EL
131}
132
133/**
134 * \brief this function prints an error message and exits.
135 */
136TmEcode NoAFPSupportExit(ThreadVars *tv, void *initdata, void **data)
137{
138 SCLogError(SC_ERR_NO_AF_PACKET,"Error creating thread %s: you do not have "
139 "support for AF_PACKET enabled, on Linux host please recompile "
140 "with --enable-af-packet", tv->name);
141 exit(EXIT_FAILURE);
142}
143
144#else /* We have AF_PACKET support */
145
c45d8985
EL
146#define AFP_IFACE_NAME_LENGTH 48
147
148#define AFP_STATE_DOWN 0
149#define AFP_STATE_UP 1
150
151#define AFP_RECONNECT_TIMEOUT 500000
13f13b6d 152#define AFP_DOWN_COUNTER_INTERVAL 40
c45d8985
EL
153
154#define POLL_TIMEOUT 100
155
4a1a0080
EL
156#ifndef TP_STATUS_USER_BUSY
157/* for new use latest bit available in tp_status */
158#define TP_STATUS_USER_BUSY (1 << 31)
159#endif
160
b603ad62
EL
161#ifndef TP_STATUS_VLAN_VALID
162#define TP_STATUS_VLAN_VALID (1 << 4)
163#endif
164
f2a6fb8a 165/** protect pfring_set_bpf_filter, as it is not thread safe */
5532af46 166static SCMutex afpacket_bpf_set_filter_lock = SCMUTEX_INITIALIZER;
f2a6fb8a 167
62e63e3f
EL
168enum {
169 AFP_READ_OK,
170 AFP_READ_FAILURE,
171 AFP_FAILURE,
27b5136b 172 AFP_KERNEL_DROP,
62e63e3f
EL
173};
174
1992a227
EL
175enum {
176 AFP_FATAL_ERROR = 1,
177 AFP_RECOVERABLE_ERROR,
178};
179
49b7b00f
EL
180union thdr {
181 struct tpacket2_hdr *h2;
182 void *raw;
183};
184
c45d8985
EL
185/**
186 * \brief Structure to hold thread specific variables.
187 */
188typedef struct AFPThreadVars_
189{
190 /* thread specific socket */
191 int socket;
192 /* handle state */
193 unsigned char afp_state;
c45d8985
EL
194
195 /* data link type for the thread */
196 int datalink;
197 int cooked;
198
199 /* counters */
3ce39433 200 uint64_t pkts;
c45d8985 201 uint64_t bytes;
3ce39433 202 uint64_t errs;
c45d8985 203
ff6365dd
EL
204 ThreadVars *tv;
205 TmSlot *slot;
206
207 uint8_t *data; /** Per function and thread data */
208 int datalen; /** Length of per function and thread data */
209
71e47868
EL
210 int vlan_disabled;
211
ff6365dd 212 char iface[AFP_IFACE_NAME_LENGTH];
51eb9605 213 LiveDevice *livedev;
13f13b6d 214 int down_count;
51eb9605 215
f2a6fb8a
EL
216 /* Filter */
217 char *bpf_filter;
218
e80b30c0
EL
219 /* socket buffer size */
220 int buffer_size;
df7dbe36 221 int promisc;
6062e00c 222 ChecksumValidationMode checksum_mode;
e80b30c0 223
662dccd8
EL
224 /* IPS stuff */
225 char out_iface[AFP_IFACE_NAME_LENGTH];
226 AFPPeer *mpeer;
227
49b7b00f 228 int flags;
6efd37a3
EL
229 uint16_t capture_kernel_packets;
230 uint16_t capture_kernel_drops;
49b7b00f 231
e80b30c0
EL
232 int cluster_id;
233 int cluster_type;
c45d8985 234
fbca1a4e 235 int threads;
662dccd8 236 int copy_mode;
fbca1a4e 237
49b7b00f
EL
238 struct tpacket_req req;
239 unsigned int tp_hdrlen;
240 unsigned int ring_buflen;
241 char *ring_buf;
242 char *frame_buf;
243 unsigned int frame_offset;
8879df80 244 int ring_size;
662dccd8 245
c45d8985
EL
246} AFPThreadVars;
247
248TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
249TmEcode ReceiveAFPThreadInit(ThreadVars *, void *, void **);
250void ReceiveAFPThreadExitStats(ThreadVars *, void *);
251TmEcode ReceiveAFPThreadDeinit(ThreadVars *, void *);
e80b30c0 252TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot);
c45d8985
EL
253
254TmEcode DecodeAFPThreadInit(ThreadVars *, void *, void **);
2864f9ee 255TmEcode DecodeAFPThreadDeinit(ThreadVars *tv, void *data);
c45d8985
EL
256TmEcode DecodeAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
257
f2a6fb8a 258TmEcode AFPSetBPFFilter(AFPThreadVars *ptv);
662dccd8 259static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose);
13f13b6d
EL
260static int AFPGetDevFlags(int fd, const char *ifname);
261static int AFPDerefSocket(AFPPeer* peer);
262static int AFPRefSocket(AFPPeer* peer);
f2a6fb8a 263
c45d8985
EL
264/**
265 * \brief Registration Function for RecieveAFP.
266 * \todo Unit tests are needed for this module.
267 */
8f1d7503
KS
268void TmModuleReceiveAFPRegister (void)
269{
c45d8985
EL
270 tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
271 tmm_modules[TMM_RECEIVEAFP].ThreadInit = ReceiveAFPThreadInit;
ff6365dd 272 tmm_modules[TMM_RECEIVEAFP].Func = NULL;
e80b30c0 273 tmm_modules[TMM_RECEIVEAFP].PktAcqLoop = ReceiveAFPLoop;
57e0bd39 274 tmm_modules[TMM_RECEIVEAFP].PktAcqBreakLoop = NULL;
c45d8985
EL
275 tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = ReceiveAFPThreadExitStats;
276 tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
277 tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
278 tmm_modules[TMM_RECEIVEAFP].cap_flags = SC_CAP_NET_RAW;
cd4705e6 279 tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
c45d8985
EL
280}
281
a6457262
EL
282
283/**
284 * \defgroup afppeers AFP peers list
285 *
286 * AF_PACKET has an IPS mode were interface are peered: packet from
287 * on interface are sent the peered interface and the other way. The ::AFPPeer
288 * list is maitaining the list of peers. Each ::AFPPeer is storing the needed
289 * information to be able to send packet on the interface.
290 * A element of the list must not be destroyed during the run of Suricata as it
291 * is used by ::Packet and other threads.
292 *
293 * @{
294 */
295
662dccd8
EL
296typedef struct AFPPeersList_ {
297 TAILQ_HEAD(, AFPPeer_) peers; /**< Head of list of fragments. */
298 int cnt;
299 int peered;
60400163
EL
300 int turn; /**< Next value for initialisation order */
301 SC_ATOMIC_DECLARE(int, reached); /**< Counter used to synchronize start */
662dccd8
EL
302} AFPPeersList;
303
304/**
a6457262
EL
305 * \brief Update the peer.
306 *
307 * Update the AFPPeer of a thread ie set new state, socket number
308 * or iface index.
309 *
662dccd8
EL
310 */
311void AFPPeerUpdate(AFPThreadVars *ptv)
312{
313 if (ptv->mpeer == NULL) {
314 return;
315 }
662dccd8
EL
316 (void)SC_ATOMIC_SET(ptv->mpeer->if_idx, AFPGetIfnumByDev(ptv->socket, ptv->iface, 0));
317 (void)SC_ATOMIC_SET(ptv->mpeer->socket, ptv->socket);
318 (void)SC_ATOMIC_SET(ptv->mpeer->state, ptv->afp_state);
319}
320
a6457262
EL
321/**
322 * \brief Clean and free ressource used by an ::AFPPeer
323 */
662dccd8
EL
324void AFPPeerClean(AFPPeer *peer)
325{
326 if (peer->flags & AFP_SOCK_PROTECT)
327 SCMutexDestroy(&peer->sock_protect);
328 SC_ATOMIC_DESTROY(peer->socket);
329 SC_ATOMIC_DESTROY(peer->if_idx);
330 SC_ATOMIC_DESTROY(peer->state);
331 SCFree(peer);
332}
333
334AFPPeersList peerslist;
335
336
a6457262
EL
337/**
338 * \brief Init the global list of ::AFPPeer
339 */
662dccd8
EL
340TmEcode AFPPeersListInit()
341{
342 SCEnter();
343 TAILQ_INIT(&peerslist.peers);
344 peerslist.peered = 0;
345 peerslist.cnt = 0;
60400163
EL
346 peerslist.turn = 0;
347 SC_ATOMIC_INIT(peerslist.reached);
348 (void) SC_ATOMIC_SET(peerslist.reached, 0);
662dccd8
EL
349 SCReturnInt(TM_ECODE_OK);
350}
351
a6457262
EL
352/**
353 * \brief Check that all ::AFPPeer got a peer
354 *
355 * \retval TM_ECODE_FAILED if some threads are not peered or TM_ECODE_OK else.
356 */
662dccd8
EL
357TmEcode AFPPeersListCheck()
358{
359#define AFP_PEERS_MAX_TRY 4
360#define AFP_PEERS_WAIT 20000
361 int try = 0;
362 SCEnter();
363 while (try < AFP_PEERS_MAX_TRY) {
364 if (peerslist.cnt != peerslist.peered) {
365 usleep(AFP_PEERS_WAIT);
366 } else {
367 SCReturnInt(TM_ECODE_OK);
368 }
369 try++;
370 }
371 SCLogError(SC_ERR_AFP_CREATE, "Threads number not equals");
372 SCReturnInt(TM_ECODE_FAILED);
373}
374
a6457262
EL
375/**
376 * \brief Declare a new AFP thread to AFP peers list.
377 */
662dccd8
EL
378TmEcode AFPPeersListAdd(AFPThreadVars *ptv)
379{
380 SCEnter();
381 AFPPeer *peer = SCMalloc(sizeof(AFPPeer));
382 AFPPeer *pitem;
ac56b1bf 383 int mtu, out_mtu;
662dccd8 384
e176be6f 385 if (unlikely(peer == NULL)) {
662dccd8
EL
386 SCReturnInt(TM_ECODE_FAILED);
387 }
388 memset(peer, 0, sizeof(AFPPeer));
389 SC_ATOMIC_INIT(peer->socket);
13f13b6d 390 SC_ATOMIC_INIT(peer->sock_usage);
662dccd8
EL
391 SC_ATOMIC_INIT(peer->if_idx);
392 SC_ATOMIC_INIT(peer->state);
393 peer->flags = ptv->flags;
60400163 394 peer->turn = peerslist.turn++;
662dccd8
EL
395
396 if (peer->flags & AFP_SOCK_PROTECT) {
397 SCMutexInit(&peer->sock_protect, NULL);
398 }
399
13f13b6d 400 (void)SC_ATOMIC_SET(peer->sock_usage, 0);
662dccd8
EL
401 (void)SC_ATOMIC_SET(peer->state, AFP_STATE_DOWN);
402 strlcpy(peer->iface, ptv->iface, AFP_IFACE_NAME_LENGTH);
403 ptv->mpeer = peer;
404 /* add element to iface list */
405 TAILQ_INSERT_TAIL(&peerslist.peers, peer, next);
662dccd8 406
13f13b6d
EL
407 if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
408 peerslist.cnt++;
409
410 /* Iter to find a peer */
411 TAILQ_FOREACH(pitem, &peerslist.peers, next) {
412 if (pitem->peer)
413 continue;
414 if (strcmp(pitem->iface, ptv->out_iface))
415 continue;
416 peer->peer = pitem;
417 pitem->peer = peer;
418 mtu = GetIfaceMTU(ptv->iface);
419 out_mtu = GetIfaceMTU(ptv->out_iface);
420 if (mtu != out_mtu) {
421 SCLogError(SC_ERR_AFP_CREATE,
422 "MTU on %s (%d) and %s (%d) are not equal, "
423 "transmission of packets bigger than %d will fail.",
424 ptv->iface, mtu,
425 ptv->out_iface, out_mtu,
426 (out_mtu > mtu) ? mtu : out_mtu);
427 }
428 peerslist.peered += 2;
429 break;
ac56b1bf 430 }
662dccd8
EL
431 }
432
433 AFPPeerUpdate(ptv);
434
435 SCReturnInt(TM_ECODE_OK);
436}
437
60400163
EL
438int AFPPeersListWaitTurn(AFPPeer *peer)
439{
b2691cbe
EL
440 /* If turn is zero, we already have started threads once */
441 if (peerslist.turn == 0)
442 return 0;
443
60400163
EL
444 if (peer->turn == SC_ATOMIC_GET(peerslist.reached))
445 return 0;
446 return 1;
447}
448
449void AFPPeersListReachedInc()
450{
b2691cbe
EL
451 if (peerslist.turn == 0)
452 return;
453
454 if (SC_ATOMIC_ADD(peerslist.reached, 1) == peerslist.turn) {
455 SCLogInfo("All AFP capture threads are running.");
456 (void)SC_ATOMIC_SET(peerslist.reached, 0);
457 /* Set turn to 0 to skip syncrhonization when ReceiveAFPLoop is
458 * restarted.
459 */
460 peerslist.turn = 0;
461 }
60400163
EL
462}
463
919377d4
EL
464static int AFPPeersListStarted()
465{
466 return !peerslist.turn;
467}
468
a6457262
EL
469/**
470 * \brief Clean the global peers list.
471 */
662dccd8
EL
472void AFPPeersListClean()
473{
474 AFPPeer *pitem;
475
476 while ((pitem = TAILQ_FIRST(&peerslist.peers))) {
477 TAILQ_REMOVE(&peerslist.peers, pitem, next);
478 AFPPeerClean(pitem);
479 }
480}
481
a6457262
EL
482/**
483 * @}
484 */
485
c45d8985
EL
486/**
487 * \brief Registration Function for DecodeAFP.
488 * \todo Unit tests are needed for this module.
489 */
8f1d7503
KS
490void TmModuleDecodeAFPRegister (void)
491{
c45d8985
EL
492 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
493 tmm_modules[TMM_DECODEAFP].ThreadInit = DecodeAFPThreadInit;
494 tmm_modules[TMM_DECODEAFP].Func = DecodeAFP;
495 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
2864f9ee 496 tmm_modules[TMM_DECODEAFP].ThreadDeinit = DecodeAFPThreadDeinit;
c45d8985
EL
497 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
498 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
bc6cf438 499 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
c45d8985
EL
500}
501
662dccd8 502
e80b30c0
EL
503static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose);
504
e8a4a4c4 505static inline void AFPDumpCounters(AFPThreadVars *ptv)
6efd37a3 506{
6efd37a3 507#ifdef PACKET_STATISTICS
e8a4a4c4
EL
508 struct tpacket_stats kstats;
509 socklen_t len = sizeof (struct tpacket_stats);
510 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_STATISTICS,
511 &kstats, &len) > -1) {
512 SCLogDebug("(%s) Kernel: Packets %" PRIu32 ", dropped %" PRIu32 "",
513 ptv->tv->name,
514 kstats.tp_packets, kstats.tp_drops);
8992275b
VJ
515 StatsAddUI64(ptv->tv, ptv->capture_kernel_packets, kstats.tp_packets);
516 StatsAddUI64(ptv->tv, ptv->capture_kernel_drops, kstats.tp_drops);
3ce39433
EL
517 (void) SC_ATOMIC_ADD(ptv->livedev->drop, (uint64_t) kstats.tp_drops);
518 (void) SC_ATOMIC_ADD(ptv->livedev->pkts, (uint64_t) kstats.tp_packets);
6efd37a3 519 }
e8a4a4c4 520#endif
6efd37a3 521}
c45d8985
EL
522
523/**
524 * \brief AF packet read function.
525 *
526 * This function fills
527 * From here the packets are picked up by the DecodeAFP thread.
528 *
529 * \param user pointer to AFPThreadVars
530 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
531 */
62e63e3f 532int AFPRead(AFPThreadVars *ptv)
c45d8985
EL
533{
534 Packet *p = NULL;
535 /* XXX should try to use read that get directly to packet */
c45d8985
EL
536 int offset = 0;
537 int caplen;
538 struct sockaddr_ll from;
539 struct iovec iov;
540 struct msghdr msg;
c45d8985
EL
541 struct cmsghdr *cmsg;
542 union {
543 struct cmsghdr cmsg;
544 char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
545 } cmsg_buf;
6efd37a3 546 unsigned char aux_checksum = 0;
c45d8985
EL
547
548 msg.msg_name = &from;
549 msg.msg_namelen = sizeof(from);
550 msg.msg_iov = &iov;
551 msg.msg_iovlen = 1;
c45d8985
EL
552 msg.msg_control = &cmsg_buf;
553 msg.msg_controllen = sizeof(cmsg_buf);
c45d8985
EL
554 msg.msg_flags = 0;
555
556 if (ptv->cooked)
557 offset = SLL_HEADER_LEN;
558 else
559 offset = 0;
e80b30c0
EL
560 iov.iov_len = ptv->datalen - offset;
561 iov.iov_base = ptv->data + offset;
c45d8985
EL
562
563 caplen = recvmsg(ptv->socket, &msg, MSG_TRUNC);
564
565 if (caplen < 0) {
566 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
567 errno);
62e63e3f 568 SCReturnInt(AFP_READ_FAILURE);
c45d8985 569 }
ff6365dd
EL
570
571 p = PacketGetFromQueueOrAlloc();
c45d8985 572 if (p == NULL) {
62e63e3f 573 SCReturnInt(AFP_FAILURE);
c45d8985 574 }
b33986c8 575 PKT_SET_SRC(p, PKT_SRC_WIRE);
c45d8985
EL
576
577 /* get timestamp of packet via ioctl */
578 if (ioctl(ptv->socket, SIOCGSTAMP, &p->ts) == -1) {
579 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
580 errno);
581 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 582 SCReturnInt(AFP_READ_FAILURE);
c45d8985
EL
583 }
584
585 ptv->pkts++;
586 ptv->bytes += caplen + offset;
51eb9605 587 p->livedev = ptv->livedev;
c45d8985
EL
588
589 /* add forged header */
590 if (ptv->cooked) {
e80b30c0 591 SllHdr * hdrp = (SllHdr *)ptv->data;
c45d8985
EL
592 /* XXX this is minimalist, but this seems enough */
593 hdrp->sll_protocol = from.sll_protocol;
594 }
595
596 p->datalink = ptv->datalink;
597 SET_PKT_LEN(p, caplen + offset);
e80b30c0 598 if (PacketCopyData(p, ptv->data, GET_PKT_LEN(p)) == -1) {
c45d8985 599 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 600 SCReturnInt(AFP_FAILURE);
c45d8985 601 }
e80b30c0
EL
602 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
603 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
604
6062e00c
EL
605 /* We only check for checksum disable */
606 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
51eb9605
EL
607 p->flags |= PKT_IGNORE_CHECKSUM;
608 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
609 if (ptv->livedev->ignore_checksum) {
610 p->flags |= PKT_IGNORE_CHECKSUM;
a565148f 611 } else if (ChecksumAutoModeCheck(ptv->pkts,
51eb9605
EL
612 SC_ATOMIC_GET(ptv->livedev->pkts),
613 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
614 ptv->livedev->ignore_checksum = 1;
6062e00c 615 p->flags |= PKT_IGNORE_CHECKSUM;
51eb9605 616 }
6062e00c 617 } else {
6efd37a3
EL
618 aux_checksum = 1;
619 }
6062e00c 620
6efd37a3
EL
621 /* List is NULL if we don't have activated auxiliary data */
622 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
623 struct tpacket_auxdata *aux;
f6ddaf33 624
6efd37a3
EL
625 if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
626 cmsg->cmsg_level != SOL_PACKET ||
627 cmsg->cmsg_type != PACKET_AUXDATA)
628 continue;
f6ddaf33 629
6efd37a3
EL
630 aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
631
632 if (aux_checksum && (aux->tp_status & TP_STATUS_CSUMNOTREADY)) {
633 p->flags |= PKT_IGNORE_CHECKSUM;
f6ddaf33 634 }
6efd37a3 635 break;
f6ddaf33
EL
636 }
637
c469824b
EL
638 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
639 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 640 SCReturnInt(AFP_FAILURE);
c469824b 641 }
62e63e3f 642 SCReturnInt(AFP_READ_OK);
c45d8985
EL
643}
644
662dccd8
EL
645TmEcode AFPWritePacket(Packet *p)
646{
647 struct sockaddr_ll socket_address;
648 int socket;
649
650 if (p->afp_v.copy_mode == AFP_COPY_MODE_IPS) {
3f107fa1 651 if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
662dccd8
EL
652 return TM_ECODE_OK;
653 }
654 }
655
656 if (SC_ATOMIC_GET(p->afp_v.peer->state) == AFP_STATE_DOWN)
657 return TM_ECODE_OK;
658
659 if (p->ethh == NULL) {
660 SCLogWarning(SC_ERR_INVALID_VALUE, "Should have an Ethernet header");
661 return TM_ECODE_FAILED;
662 }
663 /* Index of the network device */
664 socket_address.sll_ifindex = SC_ATOMIC_GET(p->afp_v.peer->if_idx);
665 /* Address length*/
666 socket_address.sll_halen = ETH_ALEN;
667 /* Destination MAC */
668 memcpy(socket_address.sll_addr, p->ethh, 6);
669
670 /* Send packet, locking the socket if necessary */
671 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
672 SCMutexLock(&p->afp_v.peer->sock_protect);
673 socket = SC_ATOMIC_GET(p->afp_v.peer->socket);
674 if (sendto(socket, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,
675 (struct sockaddr*) &socket_address,
676 sizeof(struct sockaddr_ll)) < 0) {
677 SCLogWarning(SC_ERR_SOCKET, "Sending packet failed on socket %d: %s",
678 socket,
679 strerror(errno));
680 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
681 SCMutexUnlock(&p->afp_v.peer->sock_protect);
682 return TM_ECODE_FAILED;
683 }
684 if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
685 SCMutexUnlock(&p->afp_v.peer->sock_protect);
686
687 return TM_ECODE_OK;
688}
689
b076a26c 690void AFPReleaseDataFromRing(Packet *p)
2011a3f8 691{
662dccd8
EL
692 /* Need to be in copy mode and need to detect early release
693 where Ethernet header could not be set (and pseudo packet) */
694 if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
b076a26c 695 AFPWritePacket(p);
662dccd8 696 }
13f13b6d
EL
697
698 if (AFPDerefSocket(p->afp_v.mpeer) == 0)
680e941a 699 goto cleanup;
13f13b6d 700
2011a3f8
EL
701 if (p->afp_v.relptr) {
702 union thdr h;
703 h.raw = p->afp_v.relptr;
704 h.h2->tp_status = TP_STATUS_KERNEL;
2011a3f8 705 }
680e941a
EL
706
707cleanup:
708 AFPV_CLEANUP(&p->afp_v);
b076a26c
KS
709}
710
711void AFPReleasePacket(Packet *p)
712{
713 AFPReleaseDataFromRing(p);
714 PacketFreeOrRelease(p);
2011a3f8
EL
715}
716
49b7b00f
EL
717/**
718 * \brief AF packet read function for ring
719 *
720 * This function fills
721 * From here the packets are picked up by the DecodeAFP thread.
722 *
723 * \param user pointer to AFPThreadVars
724 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
725 */
726int AFPReadFromRing(AFPThreadVars *ptv)
727{
728 Packet *p = NULL;
729 union thdr h;
27b5136b 730 uint8_t emergency_flush = 0;
4d8f70c6 731 int read_pkts = 0;
b26ec603 732 int loop_start = -1;
4d8f70c6 733
49b7b00f 734
a369f8c3
EL
735 /* Loop till we have packets available */
736 while (1) {
53c02334
AS
737 if (unlikely(suricata_ctl_flags != 0)) {
738 break;
739 }
740
a369f8c3
EL
741 /* Read packet from ring */
742 h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
743 if (h.raw == NULL) {
34b3f194
EL
744 SCReturnInt(AFP_FAILURE);
745 }
662dccd8 746
82a2dd85 747 if ((! h.h2->tp_status) || (h.h2->tp_status & TP_STATUS_USER_BUSY)) {
4d8f70c6 748 if (read_pkts == 0) {
b26ec603
EL
749 if (loop_start == -1) {
750 loop_start = ptv->frame_offset;
751 } else if (unlikely(loop_start == (int)ptv->frame_offset)) {
752 SCReturnInt(AFP_READ_OK);
753 }
754 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
755 ptv->frame_offset = 0;
756 }
757 continue;
4d8f70c6 758 }
27b5136b
EL
759 if ((emergency_flush) && (ptv->flags & AFP_EMERGENCY_MODE)) {
760 SCReturnInt(AFP_KERNEL_DROP);
761 } else {
762 SCReturnInt(AFP_READ_OK);
763 }
764 }
4d8f70c6
EL
765
766 read_pkts++;
b26ec603 767 loop_start = -1;
4d8f70c6 768
4a1a0080
EL
769 /* Our packet is still used by suricata, we exit read loop to
770 * gain some time */
771 if (h.h2->tp_status & TP_STATUS_USER_BUSY) {
772 SCReturnInt(AFP_READ_OK);
773 }
774
27b5136b
EL
775 if ((ptv->flags & AFP_EMERGENCY_MODE) && (emergency_flush == 1)) {
776 h.h2->tp_status = TP_STATUS_KERNEL;
777 goto next_frame;
a369f8c3
EL
778 }
779
780 p = PacketGetFromQueueOrAlloc();
781 if (p == NULL) {
34b3f194
EL
782 SCReturnInt(AFP_FAILURE);
783 }
b33986c8 784 PKT_SET_SRC(p, PKT_SRC_WIRE);
49b7b00f 785
4a1a0080
EL
786 /* Suricata will treat packet so telling it is busy, this
787 * status will be reset to 0 (ie TP_STATUS_KERNEL) in the release
788 * function. */
789 h.h2->tp_status |= TP_STATUS_USER_BUSY;
790
a369f8c3
EL
791 ptv->pkts++;
792 ptv->bytes += h.h2->tp_len;
a369f8c3 793 p->livedev = ptv->livedev;
a369f8c3 794 p->datalink = ptv->datalink;
d0940396 795
a369f8c3
EL
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)) {
01a8cc4e 804 p->vlan_id[0] = h.h2->tp_vlan_tci & 0x0fff;
71e47868
EL
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
339f0665 975 (void)recvmsg(ptv->socket, &msg, MSG_TRUNC);
919377d4
EL
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()) {
86a3f064 1067 SCLogDebug("Starting to read on %s", ptv->tv->name);
806844d8 1068 return 1;
43b6cbd4 1069 } else if (r < 0) { /* only exit on error */
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 1115 AFPThreadVars *ptv = (AFPThreadVars *)data;
e80b30c0
EL
1116 struct pollfd fds;
1117 int r;
34581ce9 1118 TmSlot *s = (TmSlot *)slot;
e8a4a4c4
EL
1119 time_t last_dump = 0;
1120 struct timeval current_time;
5f400785 1121 int (*AFPReadFunc) (AFPThreadVars *);
e80b30c0 1122
34581ce9 1123 ptv->slot = s->slot_next;
e80b30c0 1124
5f400785
EL
1125 if (ptv->flags & AFP_RING_MODE) {
1126 AFPReadFunc = AFPReadFromRing;
1127 } else {
1128 AFPReadFunc = AFPRead;
1129 }
1130
60400163
EL
1131 if (ptv->afp_state == AFP_STATE_DOWN) {
1132 /* Wait for our turn, threads before us must have opened the socket */
1133 while (AFPPeersListWaitTurn(ptv->mpeer)) {
1134 usleep(1000);
1992a227
EL
1135 if (suricata_ctl_flags != 0) {
1136 break;
1137 }
60400163
EL
1138 }
1139 r = AFPCreateSocket(ptv, ptv->iface, 1);
1140 if (r < 0) {
1992a227
EL
1141 switch (-r) {
1142 case AFP_FATAL_ERROR:
1143 SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket, fatal error");
1144 /* fatal is fatal, we want suri to exit */
1145 EngineKill();
1146 //tv->aof = THV_ENGINE_EXIT;
1147 SCReturnInt(TM_ECODE_FAILED);
1148 case AFP_RECOVERABLE_ERROR:
1149 SCLogWarning(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket, retrying soon");
1150 }
60400163
EL
1151 }
1152 AFPPeersListReachedInc();
1153 }
1154 if (ptv->afp_state == AFP_STATE_UP) {
86a3f064 1155 SCLogDebug("Thread %s using socket %d", tv->name, ptv->socket);
919377d4 1156 AFPSynchronizeStart(ptv);
60400163
EL
1157 }
1158
e80b30c0
EL
1159 fds.fd = ptv->socket;
1160 fds.events = POLLIN;
1161
1162 while (1) {
1163 /* Start by checking the state of our interface */
1164 if (unlikely(ptv->afp_state == AFP_STATE_DOWN)) {
1165 int dbreak = 0;
662dccd8 1166
e80b30c0
EL
1167 do {
1168 usleep(AFP_RECONNECT_TIMEOUT);
1169 if (suricata_ctl_flags != 0) {
1170 dbreak = 1;
1171 break;
1172 }
1173 r = AFPTryReopen(ptv);
09e709d1 1174 fds.fd = ptv->socket;
e80b30c0
EL
1175 } while (r < 0);
1176 if (dbreak == 1)
1177 break;
1178 }
1179
1180 /* make sure we have at least one packet in the packet pool, to prevent
1181 * us from alloc'ing packets at line rate */
3c6e01f6 1182 PacketPoolWait();
e80b30c0
EL
1183
1184 r = poll(&fds, 1, POLL_TIMEOUT);
1185
1186 if (suricata_ctl_flags != 0) {
1187 break;
1188 }
1189
1190 if (r > 0 &&
1191 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1192 if (fds.revents & (POLLHUP | POLLRDHUP)) {
13f13b6d 1193 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0 1194 continue;
ff6365dd 1195 } else if (fds.revents & POLLERR) {
e80b30c0
EL
1196 char c;
1197 /* Do a recv to get errno */
1198 if (recv(ptv->socket, &c, sizeof c, MSG_PEEK) != -1)
1199 continue; /* what, no error? */
3bea3b39
EL
1200 SCLogError(SC_ERR_AFP_READ,
1201 "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1202 ptv->iface, errno, strerror(errno));
13f13b6d 1203 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0 1204 continue;
ff6365dd 1205 } else if (fds.revents & POLLNVAL) {
e80b30c0 1206 SCLogError(SC_ERR_AFP_READ, "Invalid polling request");
13f13b6d 1207 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0
EL
1208 continue;
1209 }
1210 } else if (r > 0) {
5f400785 1211 r = AFPReadFunc(ptv);
62e63e3f 1212 switch (r) {
27adbfa8
EL
1213 case AFP_READ_OK:
1214 /* Trigger one dump of stats every second */
1215 TimeGet(&current_time);
1216 if (current_time.tv_sec != last_dump) {
1217 AFPDumpCounters(ptv);
1218 last_dump = current_time.tv_sec;
1219 }
1220 break;
62e63e3f
EL
1221 case AFP_READ_FAILURE:
1222 /* AFPRead in error: best to reset the socket */
3bea3b39
EL
1223 SCLogError(SC_ERR_AFP_READ,
1224 "AFPRead error reading data from iface '%s': (%d" PRIu32 ") %s",
1225 ptv->iface, errno, strerror(errno));
13f13b6d 1226 AFPSwitchState(ptv, AFP_STATE_DOWN);
62e63e3f
EL
1227 continue;
1228 case AFP_FAILURE:
13f13b6d 1229 AFPSwitchState(ptv, AFP_STATE_DOWN);
62e63e3f
EL
1230 SCReturnInt(TM_ECODE_FAILED);
1231 break;
27b5136b 1232 case AFP_KERNEL_DROP:
e8a4a4c4 1233 AFPDumpCounters(ptv);
27b5136b 1234 break;
e80b30c0 1235 }
11099cfa
VJ
1236 } else if (unlikely(r == 0)) {
1237 /* poll timed out, lets see if we need to inject a fake packet */
1238 TmThreadsCaptureInjectPacket(tv, ptv->slot, NULL);
1239
e80b30c0 1240 } else if ((r < 0) && (errno != EINTR)) {
3bea3b39
EL
1241 SCLogError(SC_ERR_AFP_READ, "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1242 ptv->iface,
e80b30c0 1243 errno, strerror(errno));
13f13b6d 1244 AFPSwitchState(ptv, AFP_STATE_DOWN);
e80b30c0
EL
1245 continue;
1246 }
752f03e7 1247 StatsSyncCountersIfSignalled(tv);
e80b30c0
EL
1248 }
1249
4e561d6b 1250 AFPDumpCounters(ptv);
752f03e7 1251 StatsSyncCountersIfSignalled(tv);
e80b30c0
EL
1252 SCReturnInt(TM_ECODE_OK);
1253}
1254
13f13b6d
EL
1255static int AFPGetDevFlags(int fd, const char *ifname)
1256{
1257 struct ifreq ifr;
1258
1259 memset(&ifr, 0, sizeof(ifr));
1260 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1261
1262 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
1263 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1264 ifname, strerror(errno));
1265 return -1;
1266 }
1267
1268 return ifr.ifr_flags;
1269}
1270
1271
e80b30c0 1272static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose)
c45d8985
EL
1273{
1274 struct ifreq ifr;
1275
1276 memset(&ifr, 0, sizeof(ifr));
e80b30c0 1277 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
c45d8985
EL
1278
1279 if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
1280 if (verbose)
1281 SCLogError(SC_ERR_AFP_CREATE, "Unable to find iface %s: %s",
1282 ifname, strerror(errno));
1283 return -1;
1284 }
1285
1286 return ifr.ifr_ifindex;
1287}
1288
e80b30c0 1289static int AFPGetDevLinktype(int fd, const char *ifname)
c45d8985
EL
1290{
1291 struct ifreq ifr;
1292
1293 memset(&ifr, 0, sizeof(ifr));
e80b30c0 1294 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
c45d8985
EL
1295
1296 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
1297 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1298 ifname, strerror(errno));
1299 return -1;
1300 }
1301
e80b30c0
EL
1302 switch (ifr.ifr_hwaddr.sa_family) {
1303 case ARPHRD_LOOPBACK:
1304 return LINKTYPE_ETHERNET;
1305 case ARPHRD_PPP:
11eb1d7c 1306 case ARPHRD_NONE:
e80b30c0
EL
1307 return LINKTYPE_RAW;
1308 default:
1309 return ifr.ifr_hwaddr.sa_family;
1310 }
c45d8985
EL
1311}
1312
b7bf299e
EL
1313int AFPGetLinkType(const char *ifname)
1314{
1315 int ltype;
1316
1317 int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1318 if (fd == -1) {
1319 SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
1320 return LINKTYPE_RAW;
1321 }
1322
1323 ltype = AFPGetDevLinktype(fd, ifname);
1324 close(fd);
1325
1326 return ltype;
1327}
1328
49b7b00f
EL
1329static int AFPComputeRingParams(AFPThreadVars *ptv, int order)
1330{
1331 /* Compute structure:
1332 Target is to store all pending packets
1333 with a size equal to MTU + auxdata
1334 And we keep a decent number of block
1335
1336 To do so:
1337 Compute frame_size (aligned to be able to fit in block
1338 Check which block size we need. Blocksize is a 2^n * pagesize
1339 We then need to get order, big enough to have
1340 frame_size < block size
1341 Find number of frame per block (divide)
1342 Fill in packet_req
1343
1344 Compute frame size:
1345 described in packet_mmap.txt
1346 dependant on snaplen (need to use a variable ?)
1347snaplen: MTU ?
1348tp_hdrlen determine_version in daq_afpacket
1349in V1: sizeof(struct tpacket_hdr);
1350in V2: val in getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len)
1351frame size: TPACKET_ALIGN(snaplen + TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1352
1353 */
1354 int tp_hdrlen = sizeof(struct tpacket_hdr);
1355 int snaplen = default_packet_size;
1356
03032457
EL
1357 if (snaplen == 0) {
1358 snaplen = GetIfaceMaxPacketSize(ptv->iface);
1359 if (snaplen <= 0) {
1360 SCLogWarning(SC_ERR_INVALID_VALUE,
1361 "Unable to get MTU, setting snaplen to sane default of 1514");
1362 snaplen = 1514;
1363 }
1364 }
1365
49b7b00f
EL
1366 ptv->req.tp_frame_size = TPACKET_ALIGN(snaplen +TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1367 ptv->req.tp_block_size = getpagesize() << order;
1368 int frames_per_block = ptv->req.tp_block_size / ptv->req.tp_frame_size;
1369 if (frames_per_block == 0) {
1370 SCLogInfo("frame size to big");
1371 return -1;
1372 }
8879df80 1373 ptv->req.tp_frame_nr = ptv->ring_size;
d8d9b098 1374 ptv->req.tp_block_nr = ptv->req.tp_frame_nr / frames_per_block + 1;
49b7b00f
EL
1375 /* exact division */
1376 ptv->req.tp_frame_nr = ptv->req.tp_block_nr * frames_per_block;
1377 SCLogInfo("AF_PACKET RX Ring params: block_size=%d block_nr=%d frame_size=%d frame_nr=%d",
1378 ptv->req.tp_block_size, ptv->req.tp_block_nr,
1379 ptv->req.tp_frame_size, ptv->req.tp_frame_nr);
1380 return 1;
1381}
1382
e80b30c0 1383static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
c45d8985
EL
1384{
1385 int r;
1992a227 1386 int ret = AFP_FATAL_ERROR;
c45d8985
EL
1387 struct packet_mreq sock_params;
1388 struct sockaddr_ll bind_address;
49b7b00f
EL
1389 int order;
1390 unsigned int i;
662dccd8 1391 int if_idx;
49b7b00f 1392
c45d8985
EL
1393 /* open socket */
1394 ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1395 if (ptv->socket == -1) {
e80b30c0 1396 SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
13f13b6d 1397 goto error;
c45d8985 1398 }
662dccd8 1399 if_idx = AFPGetIfnumByDev(ptv->socket, devname, verbose);
c45d8985
EL
1400 /* bind socket */
1401 memset(&bind_address, 0, sizeof(bind_address));
1402 bind_address.sll_family = AF_PACKET;
1403 bind_address.sll_protocol = htons(ETH_P_ALL);
662dccd8 1404 bind_address.sll_ifindex = if_idx;
c45d8985
EL
1405 if (bind_address.sll_ifindex == -1) {
1406 if (verbose)
e80b30c0 1407 SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
1992a227 1408 ret = AFP_RECOVERABLE_ERROR;
13f13b6d
EL
1409 goto socket_err;
1410 }
1411
13f13b6d
EL
1412 if (ptv->promisc != 0) {
1413 /* Force promiscuous mode */
1414 memset(&sock_params, 0, sizeof(sock_params));
1415 sock_params.mr_type = PACKET_MR_PROMISC;
1416 sock_params.mr_ifindex = bind_address.sll_ifindex;
1417 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(void *)&sock_params, sizeof(sock_params));
1418 if (r < 0) {
1419 SCLogError(SC_ERR_AFP_CREATE,
1420 "Couldn't switch iface %s to promiscuous, error %s",
1421 devname, strerror(errno));
1422 goto frame_err;
1423 }
1424 }
1425
1426 if (ptv->checksum_mode == CHECKSUM_VALIDATION_KERNEL) {
1427 int val = 1;
1428 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_AUXDATA, &val,
1429 sizeof(val)) == -1 && errno != ENOPROTOOPT) {
1430 SCLogWarning(SC_ERR_NO_AF_PACKET,
1431 "'kernel' checksum mode not supported, failling back to full mode.");
1432 ptv->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
1433 }
1434 }
1435
1436 /* set socket recv buffer size */
1437 if (ptv->buffer_size != 0) {
1438 /*
1439 * Set the socket buffer size to the specified value.
1440 */
1441 SCLogInfo("Setting AF_PACKET socket buffer to %d", ptv->buffer_size);
1442 if (setsockopt(ptv->socket, SOL_SOCKET, SO_RCVBUF,
1443 &ptv->buffer_size,
1444 sizeof(ptv->buffer_size)) == -1) {
1445 SCLogError(SC_ERR_AFP_CREATE,
1446 "Couldn't set buffer size to %d on iface %s, error %s",
1447 ptv->buffer_size, devname, strerror(errno));
1448 goto frame_err;
1449 }
1450 }
1451
1452 r = bind(ptv->socket, (struct sockaddr *)&bind_address, sizeof(bind_address));
1453 if (r < 0) {
1454 if (verbose) {
1455 if (errno == ENETDOWN) {
1456 SCLogError(SC_ERR_AFP_CREATE,
1457 "Couldn't bind AF_PACKET socket, iface %s is down",
1458 devname);
1459 } else {
1460 SCLogError(SC_ERR_AFP_CREATE,
1461 "Couldn't bind AF_PACKET socket to iface %s, error %s",
1462 devname, strerror(errno));
1463 }
1464 }
1992a227 1465 ret = AFP_RECOVERABLE_ERROR;
13f13b6d
EL
1466 goto frame_err;
1467 }
1468
238ff231
EL
1469#ifdef HAVE_PACKET_FANOUT
1470 /* add binded socket to fanout group */
1471 if (ptv->threads > 1) {
1472 uint32_t option = 0;
1473 uint16_t mode = ptv->cluster_type;
1474 uint16_t id = ptv->cluster_id;
1475 option = (mode << 16) | (id & 0xffff);
1476 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
1477 if (r < 0) {
1478 SCLogError(SC_ERR_AFP_CREATE,
1479 "Coudn't set fanout mode, error %s",
1480 strerror(errno));
1481 goto frame_err;
1482 }
1483 }
1484#endif
1485
13f13b6d
EL
1486 int if_flags = AFPGetDevFlags(ptv->socket, ptv->iface);
1487 if (if_flags == -1) {
1488 if (verbose) {
1489 SCLogError(SC_ERR_AFP_READ,
1490 "Can not acces to interface '%s'",
1491 ptv->iface);
1492 }
1992a227 1493 ret = AFP_RECOVERABLE_ERROR;
13f13b6d
EL
1494 goto frame_err;
1495 }
1496 if ((if_flags & IFF_UP) == 0) {
1497 if (verbose) {
1498 SCLogError(SC_ERR_AFP_READ,
1499 "Interface '%s' is down",
1500 ptv->iface);
1501 }
1992a227 1502 ret = AFP_RECOVERABLE_ERROR;
13f13b6d 1503 goto frame_err;
c45d8985 1504 }
49b7b00f
EL
1505
1506 if (ptv->flags & AFP_RING_MODE) {
1507 int val = TPACKET_V2;
1508 unsigned int len = sizeof(val);
1509 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
1510 if (errno == ENOPROTOOPT) {
1511 SCLogError(SC_ERR_AFP_CREATE,
1512 "Too old kernel giving up (need 2.6.27 at least)");
1513 }
1514 SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len");
13f13b6d 1515 goto socket_err;
49b7b00f
EL
1516 }
1517 ptv->tp_hdrlen = val;
1518
1519 val = TPACKET_V2;
1520 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val,
1521 sizeof(val)) < 0) {
1522 SCLogError(SC_ERR_AFP_CREATE,
1523 "Can't activate TPACKET_V2 on packet socket: %s",
1524 strerror(errno));
13f13b6d 1525 goto socket_err;
49b7b00f
EL
1526 }
1527
1528 /* Allocate RX ring */
1529#define DEFAULT_ORDER 3
1530 for (order = DEFAULT_ORDER; order >= 0; order--) {
1531 if (AFPComputeRingParams(ptv, order) != 1) {
1532 SCLogInfo("Ring parameter are incorrect. Please correct the devel");
1533 }
1534
1535 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, (void *) &ptv->req, sizeof(ptv->req));
1536 if (r < 0) {
1537 if (errno == ENOMEM) {
1538 SCLogInfo("Memory issue with ring parameters. Retrying.");
1539 continue;
1540 }
1541 SCLogError(SC_ERR_MEM_ALLOC,
1542 "Unable to allocate RX Ring for iface %s: (%d) %s",
1543 devname,
1544 errno,
1545 strerror(errno));
13f13b6d 1546 goto socket_err;
49b7b00f
EL
1547 } else {
1548 break;
1549 }
1550 }
1551
1552 if (order < 0) {
1553 SCLogError(SC_ERR_MEM_ALLOC,
1554 "Unable to allocate RX Ring for iface %s (order 0 failed)",
1555 devname);
13f13b6d 1556 goto socket_err;
49b7b00f
EL
1557 }
1558
1559 /* Allocate the Ring */
1560 ptv->ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
1561 ptv->ring_buf = mmap(0, ptv->ring_buflen, PROT_READ|PROT_WRITE,
1562 MAP_SHARED, ptv->socket, 0);
1563 if (ptv->ring_buf == MAP_FAILED) {
1564 SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap");
13f13b6d 1565 goto socket_err;
49b7b00f
EL
1566 }
1567 /* allocate a ring for each frame header pointer*/
1568 ptv->frame_buf = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *));
1569 if (ptv->frame_buf == NULL) {
1570 SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf");
13f13b6d 1571 goto mmap_err;
49b7b00f
EL
1572 }
1573 memset(ptv->frame_buf, 0, ptv->req.tp_frame_nr * sizeof (union thdr *));
1574 /* fill the header ring with proper frame ptr*/
1575 ptv->frame_offset = 0;
1576 for (i = 0; i < ptv->req.tp_block_nr; ++i) {
1577 void *base = &ptv->ring_buf[i * ptv->req.tp_block_size];
1578 unsigned int j;
1579 for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
1580 (((union thdr **)ptv->frame_buf)[ptv->frame_offset]) = base;
1581 base += ptv->req.tp_frame_size;
1582 }
1583 }
1584 ptv->frame_offset = 0;
1585 }
1586
86a3f064 1587 SCLogDebug("Using interface '%s' via socket %d", (char *)devname, ptv->socket);
c45d8985 1588
c85ee1e3
EL
1589 ptv->datalink = AFPGetDevLinktype(ptv->socket, ptv->iface);
1590 switch (ptv->datalink) {
1591 case ARPHRD_PPP:
1592 case ARPHRD_ATM:
1593 ptv->cooked = 1;
619414c5 1594 break;
c85ee1e3
EL
1595 }
1596
f2a6fb8a
EL
1597 TmEcode rc;
1598 rc = AFPSetBPFFilter(ptv);
1599 if (rc == TM_ECODE_FAILED) {
1600 SCLogError(SC_ERR_AFP_CREATE, "Set AF_PACKET bpf filter \"%s\" failed.", ptv->bpf_filter);
13f13b6d 1601 goto frame_err;
f2a6fb8a
EL
1602 }
1603
49b7b00f 1604 /* Init is ok */
13f13b6d 1605 AFPSwitchState(ptv, AFP_STATE_UP);
c45d8985 1606 return 0;
13f13b6d
EL
1607
1608frame_err:
1609 if (ptv->frame_buf)
1610 SCFree(ptv->frame_buf);
1611mmap_err:
1612 /* Packet mmap does the cleaning when socket is closed */
1613socket_err:
1614 close(ptv->socket);
1615 ptv->socket = -1;
1616error:
1992a227 1617 return -ret;
c45d8985
EL
1618}
1619
f2a6fb8a
EL
1620TmEcode AFPSetBPFFilter(AFPThreadVars *ptv)
1621{
1622 struct bpf_program filter;
1623 struct sock_fprog fcode;
1624 int rc;
1625
1626 if (!ptv->bpf_filter)
1627 return TM_ECODE_OK;
1628
1629 SCMutexLock(&afpacket_bpf_set_filter_lock);
1630
1631 SCLogInfo("Using BPF '%s' on iface '%s'",
1632 ptv->bpf_filter,
1633 ptv->iface);
1634 if (pcap_compile_nopcap(default_packet_size, /* snaplen_arg */
1635 ptv->datalink, /* linktype_arg */
1636 &filter, /* program */
1637 ptv->bpf_filter, /* const char *buf */
1638 0, /* optimize */
1639 0 /* mask */
1640 ) == -1) {
1641 SCLogError(SC_ERR_AFP_CREATE, "Filter compilation failed.");
1642 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1643 return TM_ECODE_FAILED;
1644 }
1645 SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1646
1647 if (filter.bf_insns == NULL) {
1648 SCLogError(SC_ERR_AFP_CREATE, "Filter badly setup.");
1649 return TM_ECODE_FAILED;
1650 }
1651
1652 fcode.len = filter.bf_len;
1653 fcode.filter = (struct sock_filter*)filter.bf_insns;
1654
1655 rc = setsockopt(ptv->socket, SOL_SOCKET, SO_ATTACH_FILTER, &fcode, sizeof(fcode));
1656
1657 if(rc == -1) {
1658 SCLogError(SC_ERR_AFP_CREATE, "Failed to attach filter: %s", strerror(errno));
1659 return TM_ECODE_FAILED;
1660 }
1661
f2a6fb8a
EL
1662 return TM_ECODE_OK;
1663}
1664
c45d8985
EL
1665
1666/**
1667 * \brief Init function for ReceiveAFP.
1668 *
1669 * \param tv pointer to ThreadVars
1670 * \param initdata pointer to the interface passed from the user
1671 * \param data pointer gets populated with AFPThreadVars
1672 *
1673 * \todo Create a general AFP setup function.
1674 */
8f1d7503
KS
1675TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
1676{
c45d8985 1677 SCEnter();
fbca1a4e 1678 AFPIfaceConfig *afpconfig = initdata;
c45d8985 1679
c45d8985
EL
1680 if (initdata == NULL) {
1681 SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL");
1682 SCReturnInt(TM_ECODE_FAILED);
1683 }
1684
1685 AFPThreadVars *ptv = SCMalloc(sizeof(AFPThreadVars));
e176be6f 1686 if (unlikely(ptv == NULL)) {
45d5c3ca 1687 afpconfig->DerefFunc(afpconfig);
c45d8985 1688 SCReturnInt(TM_ECODE_FAILED);
45d5c3ca 1689 }
c45d8985
EL
1690 memset(ptv, 0, sizeof(AFPThreadVars));
1691
1692 ptv->tv = tv;
1693 ptv->cooked = 0;
1694
fbca1a4e 1695 strlcpy(ptv->iface, afpconfig->iface, AFP_IFACE_NAME_LENGTH);
c45d8985
EL
1696 ptv->iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
1697
51eb9605
EL
1698 ptv->livedev = LiveGetDevice(ptv->iface);
1699 if (ptv->livedev == NULL) {
1700 SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device");
11bdf483 1701 SCFree(ptv);
51eb9605
EL
1702 SCReturnInt(TM_ECODE_FAILED);
1703 }
1704
fbca1a4e 1705 ptv->buffer_size = afpconfig->buffer_size;
8879df80 1706 ptv->ring_size = afpconfig->ring_size;
e80b30c0 1707
df7dbe36 1708 ptv->promisc = afpconfig->promisc;
6062e00c 1709 ptv->checksum_mode = afpconfig->checksum_mode;
6efd37a3 1710 ptv->bpf_filter = NULL;
df7dbe36 1711
fbca1a4e 1712 ptv->threads = 1;
e80b30c0
EL
1713#ifdef HAVE_PACKET_FANOUT
1714 ptv->cluster_type = PACKET_FANOUT_LB;
1715 ptv->cluster_id = 1;
1716 /* We only set cluster info if the number of reader threads is greater than 1 */
fbca1a4e 1717 if (afpconfig->threads > 1) {
9d882116
VJ
1718 ptv->cluster_id = afpconfig->cluster_id;
1719 ptv->cluster_type = afpconfig->cluster_type;
1720 ptv->threads = afpconfig->threads;
e80b30c0
EL
1721 }
1722#endif
49b7b00f 1723 ptv->flags = afpconfig->flags;
e80b30c0 1724
f2a6fb8a
EL
1725 if (afpconfig->bpf_filter) {
1726 ptv->bpf_filter = afpconfig->bpf_filter;
1727 }
1728
6efd37a3 1729#ifdef PACKET_STATISTICS
1ef786e7
VJ
1730 ptv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets",
1731 ptv->tv);
1732 ptv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops",
1733 ptv->tv);
6efd37a3
EL
1734#endif
1735
662dccd8
EL
1736 ptv->copy_mode = afpconfig->copy_mode;
1737 if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
1738 strlcpy(ptv->out_iface, afpconfig->out_iface, AFP_IFACE_NAME_LENGTH);
1739 ptv->out_iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
b7e78d33
EL
1740 /* Warn about BPF filter consequence */
1741 if (ptv->bpf_filter) {
1742 SCLogWarning(SC_WARN_UNCOMMON, "Enabling a BPF filter in IPS mode result"
1743 " in dropping all non matching packets.");
1744 }
662dccd8 1745 }
c85ee1e3 1746
b7e78d33 1747
0581a23f
EL
1748 if (AFPPeersListAdd(ptv) == TM_ECODE_FAILED) {
1749 SCFree(ptv);
1750 afpconfig->DerefFunc(afpconfig);
1751 SCReturnInt(TM_ECODE_FAILED);
1752 }
1753
e80b30c0
EL
1754#define T_DATA_SIZE 70000
1755 ptv->data = SCMalloc(T_DATA_SIZE);
1756 if (ptv->data == NULL) {
45d5c3ca 1757 afpconfig->DerefFunc(afpconfig);
6019ae3d 1758 SCFree(ptv);
e80b30c0 1759 SCReturnInt(TM_ECODE_FAILED);
c45d8985 1760 }
e80b30c0
EL
1761 ptv->datalen = T_DATA_SIZE;
1762#undef T_DATA_SIZE
1763
c45d8985 1764 *data = (void *)ptv;
fbca1a4e 1765
45d5c3ca 1766 afpconfig->DerefFunc(afpconfig);
71e47868
EL
1767
1768 /* A bit strange to have this here but we only have vlan information
1769 * during reading so we need to know if we want to keep vlan during
1770 * the capture phase */
1771 int vlanbool = 0;
1772 if ((ConfGetBool("vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
1773 ptv->vlan_disabled = 1;
1774 }
1775
2cd6e128
EL
1776 /* If kernel is older than 3.0, VLAN is not stripped so we don't
1777 * get the info from packet extended header but we will use a standard
1778 * parsing of packet data (See Linux commit bcc6d47903612c3861201cc3a866fb604f26b8b2) */
1779 if (! SCKernelVersionIsAtLeast(3, 0)) {
1780 ptv->vlan_disabled = 1;
1781 }
1782
c45d8985
EL
1783 SCReturnInt(TM_ECODE_OK);
1784}
1785
1786/**
1787 * \brief This function prints stats to the screen at exit.
1788 * \param tv pointer to ThreadVars
1789 * \param data pointer that gets cast into AFPThreadVars for ptv
1790 */
8f1d7503
KS
1791void ReceiveAFPThreadExitStats(ThreadVars *tv, void *data)
1792{
c45d8985
EL
1793 SCEnter();
1794 AFPThreadVars *ptv = (AFPThreadVars *)data;
9549faae
EL
1795
1796#ifdef PACKET_STATISTICS
e8a4a4c4 1797 AFPDumpCounters(ptv);
6efd37a3
EL
1798 SCLogInfo("(%s) Kernel: Packets %" PRIu64 ", dropped %" PRIu64 "",
1799 tv->name,
752f03e7
VJ
1800 StatsGetLocalCounterValue(tv, ptv->capture_kernel_packets),
1801 StatsGetLocalCounterValue(tv, ptv->capture_kernel_drops));
9549faae 1802#endif
e80b30c0 1803
3ce39433 1804 SCLogInfo("(%s) Packets %" PRIu64 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes);
c45d8985
EL
1805}
1806
1807/**
1808 * \brief DeInit function closes af packet socket at exit.
1809 * \param tv pointer to ThreadVars
1810 * \param data pointer that gets cast into AFPThreadVars for ptv
1811 */
8f1d7503
KS
1812TmEcode ReceiveAFPThreadDeinit(ThreadVars *tv, void *data)
1813{
c45d8985
EL
1814 AFPThreadVars *ptv = (AFPThreadVars *)data;
1815
13f13b6d
EL
1816 AFPSwitchState(ptv, AFP_STATE_DOWN);
1817
e80b30c0
EL
1818 if (ptv->data != NULL) {
1819 SCFree(ptv->data);
1820 ptv->data = NULL;
1821 }
1822 ptv->datalen = 0;
1823
f2a6fb8a
EL
1824 ptv->bpf_filter = NULL;
1825
c45d8985
EL
1826 SCReturnInt(TM_ECODE_OK);
1827}
1828
1829/**
1830 * \brief This function passes off to link type decoders.
1831 *
1832 * DecodeAFP reads packets from the PacketQueue and passes
1833 * them off to the proper link type decoder.
1834 *
1835 * \param t pointer to ThreadVars
1836 * \param p pointer to the current packet
1837 * \param data pointer that gets cast into AFPThreadVars for ptv
1838 * \param pq pointer to the current PacketQueue
1839 */
1840TmEcode DecodeAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
1841{
1842 SCEnter();
1843 DecodeThreadVars *dtv = (DecodeThreadVars *)data;
1844
f7b1aefa
VJ
1845 /* XXX HACK: flow timeout can call us for injected pseudo packets
1846 * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */
1847 if (p->flags & PKT_PSEUDO_STREAM_END)
1848 return TM_ECODE_OK;
1849
c45d8985 1850 /* update counters */
14466a80 1851 DecodeUpdatePacketCounters(tv, dtv, p);
c45d8985 1852
1fb7c0dd
EL
1853 /* If suri has set vlan during reading, we increase vlan counter */
1854 if (p->vlan_idx) {
1c0b4ee0 1855 StatsIncr(tv, dtv->counter_vlan);
1fb7c0dd
EL
1856 }
1857
c45d8985 1858 /* call the decoder */
49dbb455 1859 switch (p->datalink) {
c45d8985
EL
1860 case LINKTYPE_ETHERNET:
1861 DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1862 break;
49dbb455
VJ
1863 case LINKTYPE_LINUX_SLL:
1864 DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1865 break;
c45d8985
EL
1866 case LINKTYPE_PPP:
1867 DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1868 break;
1869 case LINKTYPE_RAW:
1870 DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1871 break;
49dbb455
VJ
1872 case LINKTYPE_NULL:
1873 DecodeNull(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1874 break;
c45d8985
EL
1875 default:
1876 SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeAFP", p->datalink);
1877 break;
1878 }
1879
3088b6ac 1880 PacketDecodeFinalize(tv, dtv, p);
e7f09f24 1881
c45d8985
EL
1882 SCReturnInt(TM_ECODE_OK);
1883}
1884
1885TmEcode DecodeAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
1886{
1887 SCEnter();
1888 DecodeThreadVars *dtv = NULL;
1889
5f307aca 1890 dtv = DecodeThreadVarsAlloc(tv);
c45d8985
EL
1891
1892 if (dtv == NULL)
1893 SCReturnInt(TM_ECODE_FAILED);
1894
1895 DecodeRegisterPerfCounters(dtv, tv);
1896
1897 *data = (void *)dtv;
1898
e7f09f24
AS
1899#ifdef __SC_CUDA_SUPPORT__
1900 if (CudaThreadVarsInit(&dtv->cuda_vars) < 0)
1901 SCReturnInt(TM_ECODE_FAILED);
1902#endif
1903
c45d8985
EL
1904 SCReturnInt(TM_ECODE_OK);
1905}
1906
2864f9ee
VJ
1907TmEcode DecodeAFPThreadDeinit(ThreadVars *tv, void *data)
1908{
1909 if (data != NULL)
98c88d51 1910 DecodeThreadVarsFree(tv, data);
2864f9ee
VJ
1911 SCReturnInt(TM_ECODE_OK);
1912}
1913
e80b30c0 1914#endif /* HAVE_AF_PACKET */
c45d8985 1915/* eof */
a6457262
EL
1916/**
1917 * @}
1918 */