]> git.ipfire.org Git - people/ms/suricata.git/blame - src/source-af-packet.c
af-packet: get datalink for each socket creation.
[people/ms/suricata.git] / src / source-af-packet.c
CommitLineData
c45d8985
EL
1/* Copyright (C) 2011 Open Information Security Foundation
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
18/**
19 * \file
20 *
21 * \author Eric Leblond <eric@regit.org>
22 *
23 * AF_PACKET socket acquisition support
24 *
25 * Fanouts socket from David Miller:
26 * we need to support the split of flow in different socket
27 * option:
e80b30c0
EL
28 * - packet_fanout type
29 * - fanout ID ?? seems it could be useful
30 * - protocol is the IEEE 802.3 protocol number in network order (filtering
31 * is great)
32 * - runmode -> family of threads in parallel (acccount)
33 * - add a new ratio or threads number (overwritten by cpu_affinity)
34 * - add af_max_read_packets for batched reading
c45d8985
EL
35 *
36 * architecture
37 * loop with read
38 * code needed for iface name to int mapping
39 * socket opening
40 * socket call
41 * bind
42 * must switch to promiscous mode -> use PACKET_MR_PROMISC socket option
43 *
e80b30c0
EL
44 * \todo watch other interface event to detect suppression of the monitored
45 * interface
c45d8985
EL
46 */
47
48#include "suricata-common.h"
e80b30c0 49#include "config.h"
c45d8985
EL
50#include "suricata.h"
51#include "decode.h"
52#include "packet-queue.h"
53#include "threads.h"
54#include "threadvars.h"
55#include "tm-queuehandlers.h"
56#include "tm-modules.h"
57#include "tm-threads.h"
58#include "tm-threads-common.h"
59#include "conf.h"
60#include "util-debug.h"
51eb9605 61#include "util-device.h"
c45d8985
EL
62#include "util-error.h"
63#include "util-privs.h"
e80b30c0 64#include "util-optimize.h"
51eb9605 65#include "util-checksum.h"
c45d8985
EL
66#include "tmqh-packetpool.h"
67#include "source-af-packet.h"
34b3f194 68#include "runmodes.h"
c45d8985 69
e80b30c0 70#ifdef HAVE_AF_PACKET
2bc0be6e 71#include <sys/ioctl.h>
c45d8985
EL
72#include <linux/if_ether.h>
73#include <linux/if_packet.h>
74#include <linux/if_arp.h>
e80b30c0 75#endif
c45d8985 76
49b7b00f
EL
77#include <sys/mman.h>
78
c45d8985
EL
79extern uint8_t suricata_ctl_flags;
80extern int max_pending_packets;
81
e80b30c0
EL
82#ifndef HAVE_AF_PACKET
83
84TmEcode NoAFPSupportExit(ThreadVars *, void *, void **);
85
86void TmModuleReceiveAFPRegister (void) {
87 tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
88 tmm_modules[TMM_RECEIVEAFP].ThreadInit = NoAFPSupportExit;
89 tmm_modules[TMM_RECEIVEAFP].Func = NULL;
90 tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = NULL;
91 tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
92 tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
93 tmm_modules[TMM_RECEIVEAFP].cap_flags = 0;
3f1c4efc 94 tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
e80b30c0
EL
95}
96
97/**
98 * \brief Registration Function for DecodeAFP.
99 * \todo Unit tests are needed for this module.
100 */
101void TmModuleDecodeAFPRegister (void) {
102 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
103 tmm_modules[TMM_DECODEAFP].ThreadInit = NoAFPSupportExit;
104 tmm_modules[TMM_DECODEAFP].Func = NULL;
105 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
106 tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
107 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
108 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
bc6cf438 109 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
e80b30c0
EL
110}
111
112/**
113 * \brief this function prints an error message and exits.
114 */
115TmEcode NoAFPSupportExit(ThreadVars *tv, void *initdata, void **data)
116{
117 SCLogError(SC_ERR_NO_AF_PACKET,"Error creating thread %s: you do not have "
118 "support for AF_PACKET enabled, on Linux host please recompile "
119 "with --enable-af-packet", tv->name);
120 exit(EXIT_FAILURE);
121}
122
123#else /* We have AF_PACKET support */
124
c45d8985
EL
125#define AFP_IFACE_NAME_LENGTH 48
126
127#define AFP_STATE_DOWN 0
128#define AFP_STATE_UP 1
129
130#define AFP_RECONNECT_TIMEOUT 500000
131
132#define POLL_TIMEOUT 100
133
62e63e3f
EL
134enum {
135 AFP_READ_OK,
136 AFP_READ_FAILURE,
137 AFP_FAILURE,
138};
139
49b7b00f
EL
140union thdr {
141 struct tpacket2_hdr *h2;
142 void *raw;
143};
144
c45d8985
EL
145/**
146 * \brief Structure to hold thread specific variables.
147 */
148typedef struct AFPThreadVars_
149{
150 /* thread specific socket */
151 int socket;
152 /* handle state */
153 unsigned char afp_state;
c45d8985
EL
154
155 /* data link type for the thread */
156 int datalink;
157 int cooked;
158
159 /* counters */
160 uint32_t pkts;
161 uint64_t bytes;
162 uint32_t errs;
163
ff6365dd
EL
164 ThreadVars *tv;
165 TmSlot *slot;
166
167 uint8_t *data; /** Per function and thread data */
168 int datalen; /** Length of per function and thread data */
169
170 char iface[AFP_IFACE_NAME_LENGTH];
51eb9605
EL
171 LiveDevice *livedev;
172
e80b30c0
EL
173 /* socket buffer size */
174 int buffer_size;
df7dbe36 175 int promisc;
6062e00c 176 ChecksumValidationMode checksum_mode;
e80b30c0 177
49b7b00f
EL
178 int flags;
179
e80b30c0
EL
180 int cluster_id;
181 int cluster_type;
c45d8985 182
fbca1a4e
EL
183 int threads;
184
49b7b00f
EL
185 struct tpacket_req req;
186 unsigned int tp_hdrlen;
187 unsigned int ring_buflen;
188 char *ring_buf;
189 char *frame_buf;
190 unsigned int frame_offset;
c45d8985
EL
191} AFPThreadVars;
192
193TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
194TmEcode ReceiveAFPThreadInit(ThreadVars *, void *, void **);
195void ReceiveAFPThreadExitStats(ThreadVars *, void *);
196TmEcode ReceiveAFPThreadDeinit(ThreadVars *, void *);
e80b30c0 197TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot);
c45d8985
EL
198
199TmEcode DecodeAFPThreadInit(ThreadVars *, void *, void **);
200TmEcode DecodeAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
201
202/**
203 * \brief Registration Function for RecieveAFP.
204 * \todo Unit tests are needed for this module.
205 */
206void TmModuleReceiveAFPRegister (void) {
207 tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
208 tmm_modules[TMM_RECEIVEAFP].ThreadInit = ReceiveAFPThreadInit;
ff6365dd 209 tmm_modules[TMM_RECEIVEAFP].Func = NULL;
e80b30c0 210 tmm_modules[TMM_RECEIVEAFP].PktAcqLoop = ReceiveAFPLoop;
c45d8985
EL
211 tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = ReceiveAFPThreadExitStats;
212 tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
213 tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
214 tmm_modules[TMM_RECEIVEAFP].cap_flags = SC_CAP_NET_RAW;
cd4705e6 215 tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
c45d8985
EL
216}
217
218/**
219 * \brief Registration Function for DecodeAFP.
220 * \todo Unit tests are needed for this module.
221 */
222void TmModuleDecodeAFPRegister (void) {
223 tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
224 tmm_modules[TMM_DECODEAFP].ThreadInit = DecodeAFPThreadInit;
225 tmm_modules[TMM_DECODEAFP].Func = DecodeAFP;
226 tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
227 tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
228 tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
229 tmm_modules[TMM_DECODEAFP].cap_flags = 0;
bc6cf438 230 tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
c45d8985
EL
231}
232
e80b30c0
EL
233static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose);
234
c45d8985
EL
235
236/**
237 * \brief AF packet read function.
238 *
239 * This function fills
240 * From here the packets are picked up by the DecodeAFP thread.
241 *
242 * \param user pointer to AFPThreadVars
243 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
244 */
62e63e3f 245int AFPRead(AFPThreadVars *ptv)
c45d8985
EL
246{
247 Packet *p = NULL;
248 /* XXX should try to use read that get directly to packet */
c45d8985
EL
249 int offset = 0;
250 int caplen;
251 struct sockaddr_ll from;
252 struct iovec iov;
253 struct msghdr msg;
c45d8985
EL
254 struct cmsghdr *cmsg;
255 union {
256 struct cmsghdr cmsg;
257 char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
258 } cmsg_buf;
c45d8985
EL
259
260 msg.msg_name = &from;
261 msg.msg_namelen = sizeof(from);
262 msg.msg_iov = &iov;
263 msg.msg_iovlen = 1;
c45d8985
EL
264 msg.msg_control = &cmsg_buf;
265 msg.msg_controllen = sizeof(cmsg_buf);
c45d8985
EL
266 msg.msg_flags = 0;
267
268 if (ptv->cooked)
269 offset = SLL_HEADER_LEN;
270 else
271 offset = 0;
e80b30c0
EL
272 iov.iov_len = ptv->datalen - offset;
273 iov.iov_base = ptv->data + offset;
c45d8985
EL
274
275 caplen = recvmsg(ptv->socket, &msg, MSG_TRUNC);
276
277 if (caplen < 0) {
278 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
279 errno);
62e63e3f 280 SCReturnInt(AFP_READ_FAILURE);
c45d8985 281 }
ff6365dd
EL
282
283 p = PacketGetFromQueueOrAlloc();
c45d8985 284 if (p == NULL) {
62e63e3f 285 SCReturnInt(AFP_FAILURE);
c45d8985
EL
286 }
287
288 /* get timestamp of packet via ioctl */
289 if (ioctl(ptv->socket, SIOCGSTAMP, &p->ts) == -1) {
290 SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
291 errno);
292 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 293 SCReturnInt(AFP_READ_FAILURE);
c45d8985
EL
294 }
295
296 ptv->pkts++;
297 ptv->bytes += caplen + offset;
51eb9605
EL
298 SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
299 p->livedev = ptv->livedev;
c45d8985
EL
300
301 /* add forged header */
302 if (ptv->cooked) {
e80b30c0 303 SllHdr * hdrp = (SllHdr *)ptv->data;
c45d8985
EL
304 /* XXX this is minimalist, but this seems enough */
305 hdrp->sll_protocol = from.sll_protocol;
306 }
307
308 p->datalink = ptv->datalink;
309 SET_PKT_LEN(p, caplen + offset);
e80b30c0 310 if (PacketCopyData(p, ptv->data, GET_PKT_LEN(p)) == -1) {
c45d8985 311 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 312 SCReturnInt(AFP_FAILURE);
c45d8985 313 }
e80b30c0
EL
314 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
315 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
316
6062e00c
EL
317 /* We only check for checksum disable */
318 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
51eb9605
EL
319 p->flags |= PKT_IGNORE_CHECKSUM;
320 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
321 if (ptv->livedev->ignore_checksum) {
322 p->flags |= PKT_IGNORE_CHECKSUM;
a565148f 323 } else if (ChecksumAutoModeCheck(ptv->pkts,
51eb9605
EL
324 SC_ATOMIC_GET(ptv->livedev->pkts),
325 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
326 ptv->livedev->ignore_checksum = 1;
6062e00c 327 p->flags |= PKT_IGNORE_CHECKSUM;
51eb9605 328 }
6062e00c
EL
329 } else {
330 /* List is NULL if we don't have activated auxiliary data */
331 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
332 struct tpacket_auxdata *aux;
333
334 if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
335 cmsg->cmsg_level != SOL_PACKET ||
336 cmsg->cmsg_type != PACKET_AUXDATA)
337 continue;
f6ddaf33 338
6062e00c 339 aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
f6ddaf33 340
6062e00c
EL
341 if (aux->tp_status & TP_STATUS_CSUMNOTREADY) {
342 p->flags |= PKT_IGNORE_CHECKSUM;
343 }
344 break;
f6ddaf33
EL
345 }
346 }
347
c469824b
EL
348 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
349 TmqhOutputPacketpool(ptv->tv, p);
62e63e3f 350 SCReturnInt(AFP_FAILURE);
c469824b 351 }
62e63e3f 352 SCReturnInt(AFP_READ_OK);
c45d8985
EL
353}
354
49b7b00f
EL
355/**
356 * \brief AF packet read function for ring
357 *
358 * This function fills
359 * From here the packets are picked up by the DecodeAFP thread.
360 *
361 * \param user pointer to AFPThreadVars
362 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
363 */
364int AFPReadFromRing(AFPThreadVars *ptv)
365{
366 Packet *p = NULL;
367 union thdr h;
368
369 /* Read packet from ring */
370 h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
371 if (h.raw == NULL) {
372 SCReturnInt(AFP_FAILURE);
373 }
374 if (h.h2->tp_status == 0) {
375 SCReturnInt(AFP_READ_OK);
376 }
377
378 p = PacketGetFromQueueOrAlloc();
379 if (p == NULL) {
380 SCReturnInt(AFP_FAILURE);
381 }
382
383 ptv->pkts++;
384 ptv->bytes += h.h2->tp_len;
385 SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
386 p->livedev = ptv->livedev;
387
388 /* add forged header */
389 if (ptv->cooked) {
390 SllHdr * hdrp = (SllHdr *)ptv->data;
391 struct sockaddr_ll *from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
392 /* XXX this is minimalist, but this seems enough */
393 hdrp->sll_protocol = from->sll_protocol;
394 }
395
396 p->datalink = ptv->datalink;
d8d9b098
EL
397 if (h.h2->tp_len > h.h2->tp_snaplen) {
398 SCLogDebug("Packet length (%d) > snaplen (%d), truncating",
399 h.h2->tp_len, h.h2->tp_snaplen);
400 }
34b3f194 401 if (ptv->flags & AFP_ZERO_COPY) {
d8d9b098 402 if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
34b3f194
EL
403 TmqhOutputPacketpool(ptv->tv, p);
404 SCReturnInt(AFP_FAILURE);
405 }
406 } else {
d8d9b098 407 if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
34b3f194
EL
408 TmqhOutputPacketpool(ptv->tv, p);
409 SCReturnInt(AFP_FAILURE);
410 }
49b7b00f
EL
411 }
412 /* Timestamp */
413 p->ts.tv_sec = h.h2->tp_sec;
414 p->ts.tv_usec = h.h2->tp_nsec/1000;
415 SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
416 GET_PKT_LEN(p), p, GET_PKT_DATA(p));
417
418 /* We only check for checksum disable */
419 if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
420 p->flags |= PKT_IGNORE_CHECKSUM;
421 } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
422 if (ptv->livedev->ignore_checksum) {
423 p->flags |= PKT_IGNORE_CHECKSUM;
424 } else if (ChecksumAutoModeCheck(ptv->pkts,
425 SC_ATOMIC_GET(ptv->livedev->pkts),
426 SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
427 ptv->livedev->ignore_checksum = 1;
428 p->flags |= PKT_IGNORE_CHECKSUM;
429 }
430 } else {
431 if (h.h2->tp_status & TP_STATUS_CSUMNOTREADY) {
432 p->flags |= PKT_IGNORE_CHECKSUM;
433 }
434 }
49b7b00f
EL
435
436 if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
34b3f194
EL
437 h.h2->tp_status = TP_STATUS_KERNEL;
438 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
439 ptv->frame_offset = 0;
440 }
49b7b00f
EL
441 TmqhOutputPacketpool(ptv->tv, p);
442 SCReturnInt(AFP_FAILURE);
443 }
444
34b3f194
EL
445 h.h2->tp_status = TP_STATUS_KERNEL;
446 if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
447 ptv->frame_offset = 0;
448 }
449
49b7b00f
EL
450 SCReturnInt(AFP_READ_OK);
451}
452
453
454
c45d8985
EL
455static int AFPTryReopen(AFPThreadVars *ptv)
456{
457 int afp_activate_r;
458
459 ptv->afp_state = AFP_STATE_DOWN;
460
e80b30c0 461 afp_activate_r = AFPCreateSocket(ptv, ptv->iface, 0);
c45d8985
EL
462 if (afp_activate_r != 0) {
463 return afp_activate_r;
464 }
465
466 SCLogInfo("Recovering interface listening");
467 ptv->afp_state = AFP_STATE_UP;
468 return 0;
469}
470
e80b30c0
EL
471/**
472 * \brief Main AF_PACKET reading Loop function
473 */
474TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
475{
476 uint16_t packet_q_len = 0;
477 AFPThreadVars *ptv = (AFPThreadVars *)data;
478 TmSlot *s = (TmSlot *)slot;
479 ptv->slot = s->slot_next;
480 struct pollfd fds;
481 int r;
482
483 SCEnter();
484
485 fds.fd = ptv->socket;
486 fds.events = POLLIN;
487
488 while (1) {
489 /* Start by checking the state of our interface */
490 if (unlikely(ptv->afp_state == AFP_STATE_DOWN)) {
491 int dbreak = 0;
492 do {
493 usleep(AFP_RECONNECT_TIMEOUT);
494 if (suricata_ctl_flags != 0) {
495 dbreak = 1;
496 break;
497 }
498 r = AFPTryReopen(ptv);
499 } while (r < 0);
500 if (dbreak == 1)
501 break;
502 }
503
504 /* make sure we have at least one packet in the packet pool, to prevent
505 * us from alloc'ing packets at line rate */
506 do {
507 packet_q_len = PacketPoolSize();
508 if (unlikely(packet_q_len == 0)) {
509 PacketPoolWait();
510 }
511 } while (packet_q_len == 0);
512
513 r = poll(&fds, 1, POLL_TIMEOUT);
514
515 if (suricata_ctl_flags != 0) {
516 break;
517 }
518
519 if (r > 0 &&
520 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
521 if (fds.revents & (POLLHUP | POLLRDHUP)) {
522 close(ptv->socket);
523 ptv->afp_state = AFP_STATE_DOWN;
524 continue;
ff6365dd 525 } else if (fds.revents & POLLERR) {
e80b30c0
EL
526 char c;
527 /* Do a recv to get errno */
528 if (recv(ptv->socket, &c, sizeof c, MSG_PEEK) != -1)
529 continue; /* what, no error? */
530 SCLogError(SC_ERR_AFP_READ, "Error reading data from socket: (%d" PRIu32 ") %s",
531 errno, strerror(errno));
532 close(ptv->socket);
533 ptv->afp_state = AFP_STATE_DOWN;
534 continue;
ff6365dd 535 } else if (fds.revents & POLLNVAL) {
e80b30c0
EL
536 SCLogError(SC_ERR_AFP_READ, "Invalid polling request");
537 close(ptv->socket);
538 ptv->afp_state = AFP_STATE_DOWN;
539 continue;
540 }
541 } else if (r > 0) {
49b7b00f
EL
542 if (ptv->flags & AFP_RING_MODE) {
543 r = AFPReadFromRing(ptv);
544 } else {
545 /* AFPRead will call TmThreadsSlotProcessPkt on read packets */
546 r = AFPRead(ptv);
547 }
62e63e3f
EL
548 switch (r) {
549 case AFP_READ_FAILURE:
550 /* AFPRead in error: best to reset the socket */
551 SCLogError(SC_ERR_AFP_READ, "AFPRead error reading data from socket: (%d" PRIu32 ") %s",
552 errno, strerror(errno));
553 close(ptv->socket);
554 ptv->afp_state = AFP_STATE_DOWN;
555 continue;
556 case AFP_FAILURE:
557 SCReturnInt(TM_ECODE_FAILED);
558 break;
559 case AFP_READ_OK:
560 break;
e80b30c0
EL
561 }
562 } else if ((r < 0) && (errno != EINTR)) {
563 SCLogError(SC_ERR_AFP_READ, "Error reading data from socket: (%d" PRIu32 ") %s",
564 errno, strerror(errno));
565 close(ptv->socket);
566 ptv->afp_state = AFP_STATE_DOWN;
567 continue;
568 }
d68f182e 569 SCPerfSyncCountersIfSignalled(tv, 0);
e80b30c0
EL
570 }
571
e80b30c0
EL
572 SCReturnInt(TM_ECODE_OK);
573}
574
e80b30c0 575static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose)
c45d8985
EL
576{
577 struct ifreq ifr;
578
579 memset(&ifr, 0, sizeof(ifr));
e80b30c0 580 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
c45d8985
EL
581
582 if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
583 if (verbose)
584 SCLogError(SC_ERR_AFP_CREATE, "Unable to find iface %s: %s",
585 ifname, strerror(errno));
586 return -1;
587 }
588
589 return ifr.ifr_ifindex;
590}
591
e80b30c0 592static int AFPGetDevLinktype(int fd, const char *ifname)
c45d8985
EL
593{
594 struct ifreq ifr;
595
596 memset(&ifr, 0, sizeof(ifr));
e80b30c0 597 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
c45d8985
EL
598
599 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
600 SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
601 ifname, strerror(errno));
602 return -1;
603 }
604
e80b30c0
EL
605 switch (ifr.ifr_hwaddr.sa_family) {
606 case ARPHRD_LOOPBACK:
607 return LINKTYPE_ETHERNET;
608 case ARPHRD_PPP:
609 return LINKTYPE_RAW;
610 default:
611 return ifr.ifr_hwaddr.sa_family;
612 }
c45d8985
EL
613}
614
49b7b00f
EL
615static int AFPComputeRingParams(AFPThreadVars *ptv, int order)
616{
617 /* Compute structure:
618 Target is to store all pending packets
619 with a size equal to MTU + auxdata
620 And we keep a decent number of block
621
622 To do so:
623 Compute frame_size (aligned to be able to fit in block
624 Check which block size we need. Blocksize is a 2^n * pagesize
625 We then need to get order, big enough to have
626 frame_size < block size
627 Find number of frame per block (divide)
628 Fill in packet_req
629
630 Compute frame size:
631 described in packet_mmap.txt
632 dependant on snaplen (need to use a variable ?)
633snaplen: MTU ?
634tp_hdrlen determine_version in daq_afpacket
635in V1: sizeof(struct tpacket_hdr);
636in V2: val in getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len)
637frame size: TPACKET_ALIGN(snaplen + TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
638
639 */
640 int tp_hdrlen = sizeof(struct tpacket_hdr);
641 int snaplen = default_packet_size;
642
643 ptv->req.tp_frame_size = TPACKET_ALIGN(snaplen +TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
644 ptv->req.tp_block_size = getpagesize() << order;
645 int frames_per_block = ptv->req.tp_block_size / ptv->req.tp_frame_size;
646 if (frames_per_block == 0) {
647 SCLogInfo("frame size to big");
648 return -1;
649 }
650 ptv->req.tp_frame_nr = max_pending_packets; /* Warrior mode */
d8d9b098 651 ptv->req.tp_block_nr = ptv->req.tp_frame_nr / frames_per_block + 1;
49b7b00f
EL
652 /* exact division */
653 ptv->req.tp_frame_nr = ptv->req.tp_block_nr * frames_per_block;
654 SCLogInfo("AF_PACKET RX Ring params: block_size=%d block_nr=%d frame_size=%d frame_nr=%d",
655 ptv->req.tp_block_size, ptv->req.tp_block_nr,
656 ptv->req.tp_frame_size, ptv->req.tp_frame_nr);
657 return 1;
658}
659
e80b30c0 660static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
c45d8985
EL
661{
662 int r;
663 struct packet_mreq sock_params;
664 struct sockaddr_ll bind_address;
49b7b00f
EL
665 int order;
666 unsigned int i;
667
c45d8985
EL
668 /* open socket */
669 ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
670 if (ptv->socket == -1) {
e80b30c0 671 SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
c45d8985
EL
672 return -1;
673 }
361bf221 674 SCLogDebug("using interface %s", (char *)devname);
c45d8985
EL
675 /* bind socket */
676 memset(&bind_address, 0, sizeof(bind_address));
677 bind_address.sll_family = AF_PACKET;
678 bind_address.sll_protocol = htons(ETH_P_ALL);
e80b30c0 679 bind_address.sll_ifindex = AFPGetIfnumByDev(ptv->socket, devname, verbose);
c45d8985
EL
680 if (bind_address.sll_ifindex == -1) {
681 if (verbose)
e80b30c0 682 SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
c45d8985
EL
683 return -1;
684 }
49b7b00f
EL
685
686 if (ptv->flags & AFP_RING_MODE) {
687 int val = TPACKET_V2;
688 unsigned int len = sizeof(val);
689 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
690 if (errno == ENOPROTOOPT) {
691 SCLogError(SC_ERR_AFP_CREATE,
692 "Too old kernel giving up (need 2.6.27 at least)");
693 }
694 SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len");
695 return -1;
696 }
697 ptv->tp_hdrlen = val;
698
699 val = TPACKET_V2;
700 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val,
701 sizeof(val)) < 0) {
702 SCLogError(SC_ERR_AFP_CREATE,
703 "Can't activate TPACKET_V2 on packet socket: %s",
704 strerror(errno));
705 return -1;
706 }
707
708 /* Allocate RX ring */
709#define DEFAULT_ORDER 3
710 for (order = DEFAULT_ORDER; order >= 0; order--) {
711 if (AFPComputeRingParams(ptv, order) != 1) {
712 SCLogInfo("Ring parameter are incorrect. Please correct the devel");
713 }
714
715 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, (void *) &ptv->req, sizeof(ptv->req));
716 if (r < 0) {
717 if (errno == ENOMEM) {
718 SCLogInfo("Memory issue with ring parameters. Retrying.");
719 continue;
720 }
721 SCLogError(SC_ERR_MEM_ALLOC,
722 "Unable to allocate RX Ring for iface %s: (%d) %s",
723 devname,
724 errno,
725 strerror(errno));
726 return -1;
727 } else {
728 break;
729 }
730 }
731
732 if (order < 0) {
733 SCLogError(SC_ERR_MEM_ALLOC,
734 "Unable to allocate RX Ring for iface %s (order 0 failed)",
735 devname);
736 return -1;
737 }
738
739 /* Allocate the Ring */
740 ptv->ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
741 ptv->ring_buf = mmap(0, ptv->ring_buflen, PROT_READ|PROT_WRITE,
742 MAP_SHARED, ptv->socket, 0);
743 if (ptv->ring_buf == MAP_FAILED) {
744 SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap");
745 return -1;
746 }
747 /* allocate a ring for each frame header pointer*/
748 ptv->frame_buf = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *));
749 if (ptv->frame_buf == NULL) {
750 SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf");
751 return -1;
752 }
753 memset(ptv->frame_buf, 0, ptv->req.tp_frame_nr * sizeof (union thdr *));
754 /* fill the header ring with proper frame ptr*/
755 ptv->frame_offset = 0;
756 for (i = 0; i < ptv->req.tp_block_nr; ++i) {
757 void *base = &ptv->ring_buf[i * ptv->req.tp_block_size];
758 unsigned int j;
759 for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
760 (((union thdr **)ptv->frame_buf)[ptv->frame_offset]) = base;
761 base += ptv->req.tp_frame_size;
762 }
763 }
764 ptv->frame_offset = 0;
765 }
766
c45d8985
EL
767 r = bind(ptv->socket, (struct sockaddr *)&bind_address, sizeof(bind_address));
768 if (r < 0) {
769 if (verbose) {
770 if (errno == ENETDOWN) {
771 SCLogError(SC_ERR_AFP_CREATE,
772 "Couldn't bind AF_PACKET socket, iface %s is down",
773 devname);
774 } else {
775 SCLogError(SC_ERR_AFP_CREATE,
776 "Couldn't bind AF_PACKET socket to iface %s, error %s",
777 devname,
778 strerror(errno));
779 }
780 }
781 close(ptv->socket);
782 return -1;
783 }
df7dbe36
EL
784 if (ptv->promisc != 0) {
785 /* Force promiscuous mode */
786 memset(&sock_params, 0, sizeof(sock_params));
787 sock_params.mr_type = PACKET_MR_PROMISC;
788 sock_params.mr_ifindex = bind_address.sll_ifindex;
789 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(void *)&sock_params, sizeof(sock_params));
790 if (r < 0) {
791 SCLogError(SC_ERR_AFP_CREATE,
792 "Couldn't switch iface %s to promiscuous, error %s",
793 devname,
794 strerror(errno));
795 close(ptv->socket);
796 return -1;
797 }
c45d8985 798 }
f6ddaf33 799
6062e00c 800 if (ptv->checksum_mode == CHECKSUM_VALIDATION_KERNEL) {
51eb9605 801 int val = 1;
67f791e8
EL
802 if (setsockopt(ptv->socket, SOL_PACKET, PACKET_AUXDATA, &val,
803 sizeof(val)) == -1 && errno != ENOPROTOOPT) {
a565148f
EL
804 SCLogWarning(SC_ERR_NO_AF_PACKET,
805 "'kernel' checksum mode not supported, failling back to full mode.");
806 ptv->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
67f791e8 807 }
f6ddaf33 808 }
f6ddaf33 809
e80b30c0
EL
810 /* set socket recv buffer size */
811 if (ptv->buffer_size != 0) {
812 /*
813 * Set the socket buffer size to the specified value.
814 */
815 SCLogInfo("Setting AF_PACKET socket buffer to %d", ptv->buffer_size);
816 if (setsockopt(ptv->socket, SOL_SOCKET, SO_RCVBUF,
817 &ptv->buffer_size,
818 sizeof(ptv->buffer_size)) == -1) {
819 SCLogError(SC_ERR_AFP_CREATE,
820 "Couldn't set buffer size to %d on iface %s, error %s",
821 ptv->buffer_size,
822 devname,
823 strerror(errno));
824 close(ptv->socket);
825 return -1;
826 }
827 }
828
c45d8985
EL
829#ifdef HAVE_PACKET_FANOUT
830 /* add binded socket to fanout group */
fbca1a4e 831 if (ptv->threads > 1) {
c45d8985 832 uint32_t option = 0;
e80b30c0
EL
833 uint16_t mode = ptv->cluster_type;
834 uint16_t id = ptv->cluster_id;
c45d8985
EL
835 option = (mode << 16) | (id & 0xffff);
836 r = setsockopt(ptv->socket, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
837 if (r < 0) {
838 SCLogError(SC_ERR_AFP_CREATE,
839 "Coudn't set fanout mode, error %s",
840 strerror(errno));
e80b30c0 841 close(ptv->socket);
c45d8985
EL
842 return -1;
843 }
844 }
845#endif
846
c85ee1e3
EL
847 ptv->datalink = AFPGetDevLinktype(ptv->socket, ptv->iface);
848 switch (ptv->datalink) {
849 case ARPHRD_PPP:
850 case ARPHRD_ATM:
851 ptv->cooked = 1;
852 }
853
49b7b00f 854 /* Init is ok */
c45d8985
EL
855 ptv->afp_state = AFP_STATE_UP;
856 return 0;
857}
858
859
860/**
861 * \brief Init function for ReceiveAFP.
862 *
863 * \param tv pointer to ThreadVars
864 * \param initdata pointer to the interface passed from the user
865 * \param data pointer gets populated with AFPThreadVars
866 *
867 * \todo Create a general AFP setup function.
868 */
869TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
870 SCEnter();
871 int r;
fbca1a4e 872 AFPIfaceConfig *afpconfig = initdata;
c45d8985 873
c45d8985
EL
874 if (initdata == NULL) {
875 SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL");
876 SCReturnInt(TM_ECODE_FAILED);
877 }
878
879 AFPThreadVars *ptv = SCMalloc(sizeof(AFPThreadVars));
45d5c3ca
EL
880 if (ptv == NULL) {
881 afpconfig->DerefFunc(afpconfig);
c45d8985 882 SCReturnInt(TM_ECODE_FAILED);
45d5c3ca 883 }
c45d8985
EL
884 memset(ptv, 0, sizeof(AFPThreadVars));
885
886 ptv->tv = tv;
887 ptv->cooked = 0;
888
fbca1a4e 889 strlcpy(ptv->iface, afpconfig->iface, AFP_IFACE_NAME_LENGTH);
c45d8985
EL
890 ptv->iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
891
51eb9605
EL
892 ptv->livedev = LiveGetDevice(ptv->iface);
893 if (ptv->livedev == NULL) {
894 SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device");
11bdf483 895 SCFree(ptv);
51eb9605
EL
896 SCReturnInt(TM_ECODE_FAILED);
897 }
898
fbca1a4e 899 ptv->buffer_size = afpconfig->buffer_size;
e80b30c0 900
df7dbe36 901 ptv->promisc = afpconfig->promisc;
6062e00c 902 ptv->checksum_mode = afpconfig->checksum_mode;
df7dbe36 903
fbca1a4e 904 ptv->threads = 1;
e80b30c0
EL
905#ifdef HAVE_PACKET_FANOUT
906 ptv->cluster_type = PACKET_FANOUT_LB;
907 ptv->cluster_id = 1;
908 /* We only set cluster info if the number of reader threads is greater than 1 */
fbca1a4e
EL
909 if (afpconfig->threads > 1) {
910 ptv->cluster_id = afpconfig->cluster_id;
911 ptv->cluster_type = afpconfig->cluster_type;
912 ptv->threads = afpconfig->threads;
e80b30c0
EL
913 }
914#endif
49b7b00f 915 ptv->flags = afpconfig->flags;
e80b30c0 916
34b3f194
EL
917 char *active_runmode = RunmodeGetActive();
918
919 if (active_runmode && !strcmp("workers", active_runmode)) {
920 ptv->flags |= AFP_ZERO_COPY;
921 SCLogInfo("Enabling zero copy mode");
922 }
923
fbca1a4e 924 r = AFPCreateSocket(ptv, ptv->iface, 1);
c45d8985 925 if (r < 0) {
e80b30c0 926 SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket");
c45d8985 927 SCFree(ptv);
45d5c3ca 928 afpconfig->DerefFunc(afpconfig);
c45d8985
EL
929 SCReturnInt(TM_ECODE_FAILED);
930 }
931
c85ee1e3 932
c45d8985 933
e80b30c0
EL
934#define T_DATA_SIZE 70000
935 ptv->data = SCMalloc(T_DATA_SIZE);
936 if (ptv->data == NULL) {
45d5c3ca 937 afpconfig->DerefFunc(afpconfig);
6019ae3d 938 SCFree(ptv);
e80b30c0 939 SCReturnInt(TM_ECODE_FAILED);
c45d8985 940 }
e80b30c0
EL
941 ptv->datalen = T_DATA_SIZE;
942#undef T_DATA_SIZE
943
c45d8985
EL
944
945 *data = (void *)ptv;
fbca1a4e 946
45d5c3ca 947 afpconfig->DerefFunc(afpconfig);
c45d8985
EL
948 SCReturnInt(TM_ECODE_OK);
949}
950
951/**
952 * \brief This function prints stats to the screen at exit.
953 * \param tv pointer to ThreadVars
954 * \param data pointer that gets cast into AFPThreadVars for ptv
955 */
956void ReceiveAFPThreadExitStats(ThreadVars *tv, void *data) {
957 SCEnter();
958 AFPThreadVars *ptv = (AFPThreadVars *)data;
9549faae
EL
959#ifdef PACKET_STATISTICS
960 struct tpacket_stats kstats;
961 socklen_t len = sizeof (struct tpacket_stats);
962#endif
963
964#ifdef PACKET_STATISTICS
965 if (getsockopt(ptv->socket, SOL_PACKET, PACKET_STATISTICS,
966 &kstats, &len) > -1) {
967 SCLogInfo("(%s) Kernel: Packets %" PRIu32 ", dropped %" PRIu32 "",
968 tv->name,
969 kstats.tp_packets, kstats.tp_drops);
970 }
971#endif
e80b30c0
EL
972
973 SCLogInfo("(%s) Packets %" PRIu32 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes);
c45d8985
EL
974}
975
976/**
977 * \brief DeInit function closes af packet socket at exit.
978 * \param tv pointer to ThreadVars
979 * \param data pointer that gets cast into AFPThreadVars for ptv
980 */
981TmEcode ReceiveAFPThreadDeinit(ThreadVars *tv, void *data) {
982 AFPThreadVars *ptv = (AFPThreadVars *)data;
983
e80b30c0
EL
984 if (ptv->data != NULL) {
985 SCFree(ptv->data);
986 ptv->data = NULL;
987 }
988 ptv->datalen = 0;
989
c45d8985
EL
990 close(ptv->socket);
991 SCReturnInt(TM_ECODE_OK);
992}
993
994/**
995 * \brief This function passes off to link type decoders.
996 *
997 * DecodeAFP reads packets from the PacketQueue and passes
998 * them off to the proper link type decoder.
999 *
1000 * \param t pointer to ThreadVars
1001 * \param p pointer to the current packet
1002 * \param data pointer that gets cast into AFPThreadVars for ptv
1003 * \param pq pointer to the current PacketQueue
1004 */
1005TmEcode DecodeAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
1006{
1007 SCEnter();
1008 DecodeThreadVars *dtv = (DecodeThreadVars *)data;
1009
1010 /* update counters */
1011 SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca);
1012 SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca);
1013
1014 SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p));
1015#if 0
1016 SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p));
1017 SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca,
1018 (GET_PKT_LEN(p) * 8)/1000000.0);
1019#endif
1020
1021 SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
1022 SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
1023
1024 /* call the decoder */
1025 switch(p->datalink) {
1026 case LINKTYPE_LINUX_SLL:
1027 DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1028 break;
1029 case LINKTYPE_ETHERNET:
1030 DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1031 break;
1032 case LINKTYPE_PPP:
1033 DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1034 break;
1035 case LINKTYPE_RAW:
1036 DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1037 break;
1038 default:
1039 SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeAFP", p->datalink);
1040 break;
1041 }
1042
1043 SCReturnInt(TM_ECODE_OK);
1044}
1045
1046TmEcode DecodeAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
1047{
1048 SCEnter();
1049 DecodeThreadVars *dtv = NULL;
1050
1051 dtv = DecodeThreadVarsAlloc();
1052
1053 if (dtv == NULL)
1054 SCReturnInt(TM_ECODE_FAILED);
1055
1056 DecodeRegisterPerfCounters(dtv, tv);
1057
1058 *data = (void *)dtv;
1059
1060 SCReturnInt(TM_ECODE_OK);
1061}
1062
e80b30c0 1063#endif /* HAVE_AF_PACKET */
c45d8985 1064/* eof */