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