suricata
source-nfq.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2023 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 Victor Julien <victor@inliniac.net>
22 * \author Eric Leblond <eric@regit.org>
23 *
24 * Netfilter's netfilter_queue support for reading packets from the
25 * kernel and setting verdicts back to it (inline mode).
26 */
27
28#include "suricata-common.h"
29#include "suricata.h"
30#include "packet.h"
31#include "decode.h"
32#include "packet-queue.h"
33
34#include "threads.h"
35#include "threadvars.h"
36#include "tm-threads.h"
37#include "tm-queuehandlers.h"
38#include "tmqh-packetpool.h"
39
40#include "conf.h"
41#include "conf-yaml-loader.h"
43#include "action-globals.h"
44
45#include "util-datalink.h"
46#include "util-debug.h"
47#include "util-error.h"
48#include "util-byte.h"
49#include "util-cpu.h"
50#include "util-privs.h"
51#include "util-device-private.h"
52
53#include "runmodes.h"
54
55#include "source-nfq.h"
56
57/* Handle the case where no NFQ support is compiled in. */
58#ifndef NFQ
59static TmEcode NoNFQSupportExit(ThreadVars *, const void *, void **);
60
62{
63 tmm_modules[TMM_RECEIVENFQ].name = "ReceiveNFQ";
64 tmm_modules[TMM_RECEIVENFQ].ThreadInit = NoNFQSupportExit;
69}
70
72{
73 tmm_modules[TMM_VERDICTNFQ].name = "VerdictNFQ";
74 tmm_modules[TMM_VERDICTNFQ].ThreadInit = NoNFQSupportExit;
79}
80
82{
83 tmm_modules[TMM_DECODENFQ].name = "DecodeNFQ";
84 tmm_modules[TMM_DECODENFQ].ThreadInit = NoNFQSupportExit;
89}
90
91static TmEcode NoNFQSupportExit(ThreadVars *tv, const void *initdata, void **data)
92{
93 FatalError("Error creating thread %s: you do not "
94 "have support for nfqueue enabled please recompile with "
95 "--enable-nfqueue",
96 tv->name);
97}
98
99#else /* we do have NFQ support */
100
101extern uint32_t max_pending_packets;
102
103#define MAX_ALREADY_TREATED 5
104#define NFQ_VERDICT_RETRY_COUNT 3
105static int already_seen_warning;
106static int runmode_workers;
107
108#define NFQ_BURST_FACTOR 4
109
110#ifndef SOL_NETLINK
111#define SOL_NETLINK 270
112#endif
113
114typedef struct NFQThreadVars_
115{
116 uint16_t nfq_index;
119
121
122 char *data; /** Per function and thread data */
123 int datalen; /** Length of per function and thread data */
125/* shared vars for all for nfq queues and threads */
126static NFQGlobalVars nfq_g;
127
128static NFQThreadVars *g_nfq_t;
129static NFQQueueVars *g_nfq_q;
130static uint16_t receive_queue_num = 0;
131static SCMutex nfq_init_lock;
132
133static TmEcode ReceiveNFQLoop(ThreadVars *tv, void *data, void *slot);
134static TmEcode ReceiveNFQThreadInit(ThreadVars *, const void *, void **);
135static TmEcode ReceiveNFQThreadDeinit(ThreadVars *, void *);
136static void ReceiveNFQThreadExitStats(ThreadVars *, void *);
137
138static TmEcode VerdictNFQ(ThreadVars *, Packet *, void *);
139static TmEcode VerdictNFQThreadInit(ThreadVars *, const void *, void **);
140static TmEcode VerdictNFQThreadDeinit(ThreadVars *, void *);
141
142static TmEcode DecodeNFQ(ThreadVars *, Packet *, void *);
143static TmEcode DecodeNFQThreadInit(ThreadVars *, const void *, void **);
144static TmEcode DecodeNFQThreadDeinit(ThreadVars *tv, void *data);
145
146static TmEcode NFQSetVerdict(Packet *p, const uint32_t mark_value, const bool mark_modified);
147static void NFQReleasePacket(Packet *p);
148
154
155#define NFQ_FLAG_FAIL_OPEN (1 << 0)
156
157typedef struct NFQCnf_ {
159 uint32_t mark;
160 uint32_t mask;
161 uint32_t bypass_mark;
162 uint32_t bypass_mask;
163 uint32_t next_queue;
164 uint32_t flags;
165 uint8_t batchcount;
167
169
171{
172 /* XXX create a general NFQ setup function */
173 memset(&nfq_g, 0, sizeof(nfq_g));
174 SCMutexInit(&nfq_init_lock, NULL);
175
176 tmm_modules[TMM_RECEIVENFQ].name = "ReceiveNFQ";
177 tmm_modules[TMM_RECEIVENFQ].ThreadInit = ReceiveNFQThreadInit;
178 tmm_modules[TMM_RECEIVENFQ].PktAcqLoop = ReceiveNFQLoop;
180 tmm_modules[TMM_RECEIVENFQ].ThreadExitPrintStats = ReceiveNFQThreadExitStats;
181 tmm_modules[TMM_RECEIVENFQ].ThreadDeinit = ReceiveNFQThreadDeinit;
183}
184
186{
187 tmm_modules[TMM_VERDICTNFQ].name = "VerdictNFQ";
188 tmm_modules[TMM_VERDICTNFQ].ThreadInit = VerdictNFQThreadInit;
189 tmm_modules[TMM_VERDICTNFQ].Func = VerdictNFQ;
190 tmm_modules[TMM_VERDICTNFQ].ThreadDeinit = VerdictNFQThreadDeinit;
192}
193
195{
196 tmm_modules[TMM_DECODENFQ].name = "DecodeNFQ";
197 tmm_modules[TMM_DECODENFQ].ThreadInit = DecodeNFQThreadInit;
198 tmm_modules[TMM_DECODENFQ].Func = DecodeNFQ;
199 tmm_modules[TMM_DECODENFQ].ThreadDeinit = DecodeNFQThreadDeinit;
201}
202
203/** \brief To initialize the NFQ global configuration data
204 *
205 * \param quiet It tells the mode of operation, if it is TRUE nothing will
206 * be get printed.
207 */
208void NFQInitConfig(bool quiet)
209{
210 intmax_t value = 0;
211 const char *nfq_mode = NULL;
212 int boolval;
213
214 SCLogDebug("Initializing NFQ");
215
216 memset(&nfq_config, 0, sizeof(nfq_config));
217
218 if ((SCConfGet("nfq.mode", &nfq_mode)) == 0) {
220 } else {
221 if (!strcmp("accept", nfq_mode)) {
223 } else if (!strcmp("repeat", nfq_mode)) {
225 } else if (!strcmp("route", nfq_mode)) {
227 } else {
228 FatalError("Unknown nfq.mode");
229 }
230 }
231
232 (void)SCConfGetBool("nfq.fail-open", &boolval);
233 if (boolval) {
234#ifdef HAVE_NFQ_SET_QUEUE_FLAGS
235 SCLogInfo("Enabling fail-open on queue");
237#else
238 SCLogError("nfq.%s set but NFQ library has no support for it.", "fail-open");
239#endif
240 }
241
242 if ((SCConfGetInt("nfq.repeat-mark", &value)) == 1) {
243 nfq_config.mark = (uint32_t)value;
244 }
245
246 if ((SCConfGetInt("nfq.repeat-mask", &value)) == 1) {
247 nfq_config.mask = (uint32_t)value;
248 }
249
250 if ((SCConfGetInt("nfq.bypass-mark", &value)) == 1) {
251 nfq_config.bypass_mark = (uint32_t)value;
252 }
253
254 if ((SCConfGetInt("nfq.bypass-mask", &value)) == 1) {
255 nfq_config.bypass_mask = (uint32_t)value;
256 }
257
258 if ((SCConfGetInt("nfq.route-queue", &value)) == 1) {
259 nfq_config.next_queue = ((uint32_t)value) << 16;
260 }
261
262 if ((SCConfGetInt("nfq.batchcount", &value)) == 1) {
263#ifdef HAVE_NFQ_SET_VERDICT_BATCH
264 if (value > 255) {
265 SCLogWarning("nfq.batchcount cannot exceed 255.");
266 value = 255;
267 }
268 if (value > 1)
269 nfq_config.batchcount = (uint8_t) (value - 1);
270#else
271 SCLogWarning("nfq.%s set but NFQ library has no support for it.", "batchcount");
272#endif
273 }
274
275 if (!quiet) {
276 switch (nfq_config.mode) {
277 case NFQ_ACCEPT_MODE:
278 SCLogInfo("NFQ running in standard ACCEPT/DROP mode");
279 break;
280 case NFQ_REPEAT_MODE:
281 SCLogInfo("NFQ running in REPEAT mode with mark %"PRIu32"/%"PRIu32,
283 break;
284 case NFQ_ROUTE_MODE:
285 SCLogInfo("NFQ running in route mode with next queue %"PRIu32,
286 nfq_config.next_queue >> 16);
287 break;
288 }
289 }
290
291}
292
293static uint8_t NFQVerdictCacheLen(NFQQueueVars *t)
294{
295#ifdef HAVE_NFQ_SET_VERDICT_BATCH
296 return t->verdict_cache.len;
297#else
298 return 0;
299#endif
300}
301
302static void NFQVerdictCacheFlush(NFQQueueVars *t)
303{
304#ifdef HAVE_NFQ_SET_VERDICT_BATCH
305 int ret;
306 int iter = 0;
307
308 do {
310 ret = nfq_set_verdict_batch2(t->qh,
314 else
315 ret = nfq_set_verdict_batch(t->qh,
318 } while ((ret < 0) && (iter++ < NFQ_VERDICT_RETRY_COUNT));
319
320 if (ret < 0) {
321 SCLogWarning("nfq_set_verdict_batch failed: %s", strerror(errno));
322 } else {
323 t->verdict_cache.len = 0;
325 }
326#endif
327}
328
329static int NFQVerdictCacheAdd(NFQQueueVars *t, Packet *p, const uint32_t verdict,
330 const uint32_t mark_value, const bool mark_modified)
331{
332#ifdef HAVE_NFQ_SET_VERDICT_BATCH
333 if (t->verdict_cache.maxlen == 0)
334 return -1;
335
336 if (p->flags & PKT_STREAM_MODIFIED || verdict == NF_DROP)
337 goto flush;
338
339 if (mark_modified) {
340 if (!t->verdict_cache.mark_valid) {
341 if (t->verdict_cache.len)
342 goto flush;
344 t->verdict_cache.mark = mark_value;
345 } else if (t->verdict_cache.mark != mark_value) {
346 goto flush;
347 }
348 } else if (t->verdict_cache.mark_valid) {
349 goto flush;
350 }
351
352 if (t->verdict_cache.len == 0) {
353 t->verdict_cache.verdict = verdict;
354 } else if (t->verdict_cache.verdict != verdict)
355 goto flush;
356
357 /* same verdict, mark not set or identical -> can cache */
359
361 NFQVerdictCacheFlush(t);
362 else
363 t->verdict_cache.len++;
364 return 0;
365 flush:
366 /* can't cache. Flush current cache and signal caller it should send single verdict */
367 if (NFQVerdictCacheLen(t) > 0)
368 NFQVerdictCacheFlush(t);
369#endif
370 return -1;
371}
372
373static inline void NFQMutexInit(NFQQueueVars *nq)
374{
375 char *active_runmode = RunmodeGetActive();
376
377 if (active_runmode && !strcmp("workers", active_runmode)) {
378 nq->use_mutex = 0;
379 runmode_workers = 1;
380 SCLogDebug("NFQ running in 'workers' runmode, will not use mutex.");
381 } else {
382 nq->use_mutex = 1;
383 runmode_workers = 0;
384 SCMutexInit(&nq->mutex_qh, NULL);
385 }
386}
387
388#define NFQMutexLock(nq) do { \
389 if ((nq)->use_mutex) \
390 SCMutexLock(&(nq)->mutex_qh); \
391} while (0)
392
393#define NFQMutexUnlock(nq) do { \
394 if ((nq)->use_mutex) \
395 SCMutexUnlock(&(nq)->mutex_qh); \
396} while (0)
397
398/**
399 * \brief Read data from nfq message and setup Packet
400 *
401 * \note
402 * In case of error, this function verdict the packet
403 * to avoid skb to get stuck in kernel.
404 */
405static int NFQSetupPkt (Packet *p, struct nfq_q_handle *qh, void *data)
406{
407 struct nfq_data *tb = (struct nfq_data *)data;
408 int ret;
409 char *pktdata;
410 struct nfqnl_msg_packet_hdr *ph;
411
412 // Early release function -- will be updated once repeat
413 // mode handling has been done
415
416 ph = nfq_get_msg_packet_hdr(tb);
417 if (ph != NULL) {
418 p->nfq_v.id = SCNtohl(ph->packet_id);
419 p->nfq_v.hw_protocol = ph->hw_protocol;
420 }
421 /* coverity[missing_lock] */
422 p->nfq_v.mark = nfq_get_nfmark(tb);
424 if ((nfq_config.mark & nfq_config.mask) ==
425 (p->nfq_v.mark & nfq_config.mask)) {
426 int iter = 0;
427 if (already_seen_warning < MAX_ALREADY_TREATED)
428 SCLogInfo("Packet seems already treated by suricata");
429 already_seen_warning++;
430 do {
431 ret = nfq_set_verdict(qh, p->nfq_v.id, NF_ACCEPT, 0, NULL);
432 } while ((ret < 0) && (iter++ < NFQ_VERDICT_RETRY_COUNT));
433 if (ret < 0) {
435 "nfq_set_verdict of %p failed %" PRId32 ": %s", p, ret, strerror(errno));
436 }
437 return -1 ;
438 }
439 }
440
441 // Switch to full featured release function
442 p->ReleasePacket = NFQReleasePacket;
443 p->nfq_v.ifi = nfq_get_indev(tb);
444 p->nfq_v.ifo = nfq_get_outdev(tb);
445 /* coverity[missing_lock] */
446 p->nfq_v.verdicted = false;
447
448#ifdef NFQ_GET_PAYLOAD_SIGNED
449 ret = nfq_get_payload(tb, &pktdata);
450#else
451 ret = nfq_get_payload(tb, (unsigned char **) &pktdata);
452#endif /* NFQ_GET_PAYLOAD_SIGNED */
453 if (ret > 0) {
454 /* nfq_get_payload returns a pointer to a part of memory
455 * that is not preserved over the lifetime of our packet.
456 * So we need to copy it. */
457 if (ret > 65536) {
458 /* Will not be able to copy data ! Set length to 0
459 * to trigger an error in packet decoding.
460 * This is unlikely to happen */
461 SCLogWarning("NFQ sent too big packet");
462 SET_PKT_LEN(p, 0);
463 } else if (runmode_workers) {
464 PacketSetData(p, (uint8_t *)pktdata, ret);
465 } else {
466 PacketCopyData(p, (uint8_t *)pktdata, ret);
467 }
468 } else if (ret == -1) {
469 /* unable to get pointer to data, ensure packet length is zero.
470 * This will trigger an error in packet decoding */
471 SET_PKT_LEN(p, 0);
472 }
473
474 struct timeval tv;
475 ret = nfq_get_timestamp(tb, &tv);
476 if (ret != 0 || tv.tv_sec == 0) {
477 memset(&tv, 0, sizeof(tv));
478 gettimeofday(&tv, NULL);
479 }
481
482 p->datalink = DLT_RAW;
483 return 0;
484}
485
486static void NFQReleasePacket(Packet *p)
487{
488 if (PacketIsNotTunnel(p)) {
489 if (unlikely(!p->nfq_v.verdicted)) {
491 /* coverity[missing_lock] */
492 NFQSetVerdict(p, p->nfq_v.mark, p->nfq_v.mark_modified);
493 /* coverity[missing_lock] */
494 p->nfq_v.verdicted = true;
495 }
496 } else {
497 Packet *root_p = p->root ? p->root : p;
500 const bool verdicted = p->nfq_v.verdicted;
501 // taken from root packet
502 const bool mark_modified = root_p->nfq_v.mark_modified;
503 const uint32_t mark_value = root_p->nfq_v.mark;
504 root_p->nfq_v.verdicted = true;
506 if (!verdicted) {
508 NFQSetVerdict(p, mark_value, mark_modified);
509 }
510 }
512}
513
514/**
515 * \brief bypass callback function for NFQ
516 *
517 * \param p a Packet to use information from to trigger bypass
518 * \return 1 if bypass is successful, 0 if not
519 */
520static int NFQBypassCallback(Packet *p)
521{
522 if (PacketIsTunnel(p)) {
523 /* real tunnels may have multiple flows inside them, so bypass can't
524 * work for those. Rebuilt packets from IP fragments are fine. */
525 if (p->flags & PKT_REBUILT_FRAGMENT) {
526 Packet *tp = p->root ? p->root : p;
529 | (tp->nfq_v.mark & ~nfq_config.bypass_mask);
530 tp->nfq_v.mark_modified = true;
532 return 1;
533 }
534 return 0;
535 } else {
536 /* coverity[missing_lock] */
539 /* coverity[missing_lock] */
540 p->nfq_v.mark_modified = true;
541 }
542
543 return 1;
544}
545
546static int NFQCallBack(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
547 struct nfq_data *nfa, void *data)
548{
549 NFQThreadVars *ntv = (NFQThreadVars *)data;
550 ThreadVars *tv = ntv->tv;
551 int ret;
552
553 /* grab a packet */
555 if (p == NULL) {
556 return -1;
557 }
559
560 p->nfq_v.nfq_index = ntv->nfq_index;
561 /* if bypass mask is set then we may want to bypass so set pointer */
563 p->BypassPacketsFlow = NFQBypassCallback;
564 }
565
566 ret = NFQSetupPkt(p, qh, (void *)nfa);
567 if (ret == -1) {
568#ifdef COUNTERS
570 q->errs++;
571 q->pkts++;
572 q->bytes += GET_PKT_LEN(p);
573#endif /* COUNTERS */
574 (void) SC_ATOMIC_ADD(ntv->livedev->pkts, 1);
575
576 /* NFQSetupPkt is issuing a verdict
577 so we only recycle Packet and leave */
579 return 0;
580 }
581
582#ifdef COUNTERS
584 q->pkts++;
585 q->bytes += GET_PKT_LEN(p);
586#endif /* COUNTERS */
587 (void) SC_ATOMIC_ADD(ntv->livedev->pkts, 1);
588
589 if (TmThreadsSlotProcessPkt(tv, ntv->slot, p) != TM_ECODE_OK) {
590 return -1;
591 }
592
593 return 0;
594}
595
596static TmEcode NFQInitThread(NFQThreadVars *t, uint32_t queue_maxlen)
597{
598 struct timeval tv;
599 int opt;
601 if (q == NULL) {
602 SCLogError("no queue for given index");
603 return TM_ECODE_FAILED;
604 }
605 SCLogDebug("opening library handle");
606 q->h = nfq_open();
607 if (q->h == NULL) {
608 SCLogError("nfq_open() failed");
609 return TM_ECODE_FAILED;
610 }
611
612 if (nfq_g.unbind == 0)
613 {
614 /* VJ: on my Ubuntu Hardy system this fails the first time it's
615 * run. Ignoring the error seems to have no bad effects. */
616 SCLogDebug("unbinding existing nf_queue handler for AF_INET (if any)");
617 if (nfq_unbind_pf(q->h, AF_INET) < 0) {
618 FatalError("nfq_unbind_pf() for AF_INET failed: %s", strerror(errno));
619 }
620 if (nfq_unbind_pf(q->h, AF_INET6) < 0) {
621 FatalError("nfq_unbind_pf() for AF_INET6 failed");
622 }
623 nfq_g.unbind = 1;
624
625 SCLogDebug("binding nfnetlink_queue as nf_queue handler for AF_INET and AF_INET6");
626
627 if (nfq_bind_pf(q->h, AF_INET) < 0) {
628 FatalError("nfq_bind_pf() for AF_INET failed");
629 }
630 if (nfq_bind_pf(q->h, AF_INET6) < 0) {
631 FatalError("nfq_bind_pf() for AF_INET6 failed");
632 }
633 }
634
635 SCLogInfo("binding this thread %d to queue '%" PRIu32 "'", t->nfq_index, q->queue_num);
636
637 /* pass the thread memory as a void ptr so the
638 * callback function has access to it. */
639 q->qh = nfq_create_queue(q->h, q->queue_num, &NFQCallBack, (void *)t);
640 if (q->qh == NULL) {
641 SCLogError("nfq_create_queue failed");
642 return TM_ECODE_FAILED;
643 }
644
645 SCLogDebug("setting copy_packet mode");
646
647 /* 05DC = 1500 */
648 //if (nfq_set_mode(nfq_t->qh, NFQNL_COPY_PACKET, 0x05DC) < 0) {
649 if (nfq_set_mode(q->qh, NFQNL_COPY_PACKET, 0xFFFF) < 0) {
650 SCLogError("can't set packet_copy mode");
651 return TM_ECODE_FAILED;
652 }
653
654#ifdef HAVE_NFQ_MAXLEN
655 if (queue_maxlen > 0) {
656 SCLogInfo("setting queue length to %" PRId32 "", queue_maxlen);
657
658 /* non-fatal if it fails */
659 if (nfq_set_queue_maxlen(q->qh, queue_maxlen) < 0) {
660 SCLogWarning("can't set queue maxlen: your kernel probably "
661 "doesn't support setting the queue length");
662 }
663 }
664#endif /* HAVE_NFQ_MAXLEN */
665
666 /* set netlink buffer size to a decent value */
667 nfnl_rcvbufsiz(nfq_nfnlh(q->h), queue_maxlen * 1500);
668 SCLogInfo("setting nfnl bufsize to %" PRId32 "", queue_maxlen * 1500);
669
670 q->nh = nfq_nfnlh(q->h);
671 q->fd = nfnl_fd(q->nh);
672 NFQMutexInit(q);
673
674 /* Set some netlink specific option on the socket to increase
675 performance */
676 opt = 1;
677#ifdef NETLINK_BROADCAST_SEND_ERROR
678 if (setsockopt(q->fd, SOL_NETLINK,
679 NETLINK_BROADCAST_SEND_ERROR, &opt, sizeof(int)) == -1) {
680 SCLogWarning("can't set netlink broadcast error: %s", strerror(errno));
681 }
682#endif
683 /* Don't send error about no buffer space available but drop the
684 packets instead */
685#ifdef NETLINK_NO_ENOBUFS
686 if (setsockopt(q->fd, SOL_NETLINK,
687 NETLINK_NO_ENOBUFS, &opt, sizeof(int)) == -1) {
688 SCLogWarning("can't set netlink enobufs: %s", strerror(errno));
689 }
690#endif
691
692#ifdef HAVE_NFQ_SET_QUEUE_FLAGS
694 uint32_t flags = NFQA_CFG_F_FAIL_OPEN;
695 uint32_t mask = NFQA_CFG_F_FAIL_OPEN;
696 int r = nfq_set_queue_flags(q->qh, mask, flags);
697
698 if (r == -1) {
699 SCLogWarning("can't set fail-open mode: %s", strerror(errno));
700 } else {
701 SCLogInfo("fail-open mode should be set on queue");
702 }
703 }
704#endif
705
706#ifdef HAVE_NFQ_SET_VERDICT_BATCH
707 if (runmode_workers) {
709 } else if (nfq_config.batchcount) {
710 SCLogError("nfq.batchcount is only valid in workers runmode.");
711 }
712#endif
713
714 /* set a timeout to the socket so we can check for a signal
715 * in case we don't get packets for a longer period. */
716 tv.tv_sec = 1;
717 tv.tv_usec = 0;
718
719 if(setsockopt(q->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
720 SCLogWarning("can't set socket timeout: %s", strerror(errno));
721 }
722
723 SCLogDebug("nfq_q->h %p, nfq_q->nh %p, nfq_q->qh %p, nfq_q->fd %" PRId32 "",
724 q->h, q->nh, q->qh, q->fd);
725
726 return TM_ECODE_OK;
727}
728
729TmEcode ReceiveNFQThreadInit(ThreadVars *tv, const void *initdata, void **data)
730{
731 SCMutexLock(&nfq_init_lock);
732
733 sigset_t sigs;
734 sigfillset(&sigs);
735 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
736
737 NFQThreadVars *ntv = (NFQThreadVars *) initdata;
738 /* store the ThreadVars pointer in our NFQ thread context
739 * as we will need it in our callback function */
740 ntv->tv = tv;
741
742 int r = NFQInitThread(ntv, (max_pending_packets * NFQ_BURST_FACTOR));
743 if (r != TM_ECODE_OK) {
744 SCLogError("nfq thread failed to initialize");
745
746 SCMutexUnlock(&nfq_init_lock);
747 exit(EXIT_FAILURE);
748 }
749
750#define T_DATA_SIZE 70000
751 ntv->data = SCMalloc(T_DATA_SIZE);
752 if (ntv->data == NULL) {
753 SCMutexUnlock(&nfq_init_lock);
754 return TM_ECODE_FAILED;
755 }
756 ntv->datalen = T_DATA_SIZE;
757#undef T_DATA_SIZE
758
760
761 *data = (void *)ntv;
762
763 SCMutexUnlock(&nfq_init_lock);
764 return TM_ECODE_OK;
765}
766
767static void NFQDestroyQueue(NFQQueueVars *nq)
768{
769 if (unlikely(nq == NULL)) {
770 return;
771 }
772
773 SCLogDebug("starting... will close queuenum %" PRIu32 "", nq->queue_num);
774 NFQMutexLock(nq);
775 if (nq->qh != NULL) {
776 nfq_destroy_queue(nq->qh);
777 nq->qh = NULL;
778 nfq_close(nq->h);
779 nq->h = NULL;
780 }
781 NFQMutexUnlock(nq);
782}
783
784TmEcode ReceiveNFQThreadDeinit(ThreadVars *t, void *data)
785{
786 NFQThreadVars *ntv = (NFQThreadVars *)data;
788
789 if (ntv->data != NULL) {
790 SCFree(ntv->data);
791 ntv->data = NULL;
792 }
793 ntv->datalen = 0;
794
795 NFQDestroyQueue(nq);
796
797 return TM_ECODE_OK;
798}
799
800TmEcode VerdictNFQThreadInit(ThreadVars *tv, const void *initdata, void **data)
801{
802 NFQThreadVars *ntv = (NFQThreadVars *)initdata;
803 *data = (void *)ntv;
804 return TM_ECODE_OK;
805}
806
807TmEcode VerdictNFQThreadDeinit(ThreadVars *tv, void *data)
808{
809 NFQThreadVars *ntv = (NFQThreadVars *)data;
811
812 NFQDestroyQueue(nq);
813
814 return TM_ECODE_OK;
815}
816
817/**
818 * \brief Add a single Netfilter queue
819 *
820 * \param string with the queue number
821 *
822 * \retval 0 on success.
823 * \retval -1 on failure.
824 */
825int NFQRegisterQueue(const uint16_t number)
826{
827 NFQThreadVars *ntv = NULL;
828 NFQQueueVars *nq = NULL;
829 char queue[10] = { 0 };
830 static bool many_queues_warned = false;
831 uint16_t num_cpus = UtilCpuGetNumProcessorsOnline();
832
833 if (g_nfq_t == NULL || g_nfq_q == NULL) {
834 SCLogError("NFQ context is not initialized");
835 return -1;
836 }
837
838 SCMutexLock(&nfq_init_lock);
839 if (!many_queues_warned && (receive_queue_num >= num_cpus)) {
840 SCLogWarning("using more Netfilter queues than %hu available CPU core(s) "
841 "may degrade performance",
842 num_cpus);
843 many_queues_warned = true;
844 }
845 if (receive_queue_num >= NFQ_MAX_QUEUE) {
846 SCLogError("can not register more than %d Netfilter queues", NFQ_MAX_QUEUE);
847 SCMutexUnlock(&nfq_init_lock);
848 return -1;
849 }
850
851 ntv = &g_nfq_t[receive_queue_num];
852 ntv->nfq_index = receive_queue_num;
853
854 nq = &g_nfq_q[receive_queue_num];
855 memset(nq, 0, sizeof(*nq));
856 nq->queue_num = number;
857 receive_queue_num++;
858 SCMutexUnlock(&nfq_init_lock);
859 snprintf(queue, sizeof(queue) - 1, "NFQ#%hu", number);
860 LiveRegisterDevice(queue);
861
862 ntv->livedev = LiveGetDevice(queue);
863
864 if (ntv->livedev == NULL) {
865 SCLogError("Unable to find Live device");
866 return -1;
867 }
868
869 SCLogDebug("Queue %d registered.", number);
870 return 0;
871}
872
873/**
874 * \brief Parses and adds Netfilter queue(s).
875 *
876 * \param string with the queue number or range
877 *
878 * \retval 0 on success.
879 * \retval -1 on failure.
880 */
881int NFQParseAndRegisterQueues(const char *queues)
882{
883 uint16_t queue_start = 0;
884 uint16_t queue_end = 0;
885 uint16_t num_queues = 1; // if argument is correct, at least one queue will be created
886
887 // Either "id" or "start:end" format (e.g., "12" or "0:5")
888 int count = sscanf(queues, "%hu:%hu", &queue_start, &queue_end);
889
890 if (count < 1) {
891 SCLogError("specified queue(s) argument '%s' is not "
892 "valid (allowed queue numbers are 0-65535)",
893 queues);
894 return -1;
895 }
896
897 // Do we have a range?
898 if (count == 2) {
899 // Sanity check
900 if (queue_start > queue_end) {
901 SCLogError("start queue's number %d is greater than "
902 "ending number %d",
903 queue_start, queue_end);
904 return -1;
905 }
906
907 num_queues = queue_end - queue_start + 1; // +1 due to inclusive range
908 }
909
910 // We do realloc() to preserve previously registered queues
911 void *ptmp = SCRealloc(g_nfq_t, (receive_queue_num + num_queues) * sizeof(NFQThreadVars));
912 if (ptmp == NULL) {
913 SCLogError("Unable to allocate NFQThreadVars");
915 exit(EXIT_FAILURE);
916 }
917
918 g_nfq_t = (NFQThreadVars *)ptmp;
919
920 ptmp = SCRealloc(g_nfq_q, (receive_queue_num + num_queues) * sizeof(NFQQueueVars));
921 if (ptmp == NULL) {
922 SCLogError("Unable to allocate NFQQueueVars");
924 exit(EXIT_FAILURE);
925 }
926
927 g_nfq_q = (NFQQueueVars *)ptmp;
928
929 do {
930 if (NFQRegisterQueue(queue_start) != 0) {
931 return -1;
932 }
933 } while (++queue_start <= queue_end);
934
935 return 0;
936}
937
938/**
939 * \brief Get a pointer to the NFQ queue at index
940 *
941 * \param number idx of the queue in our array
942 *
943 * \retval ptr pointer to the NFQThreadVars at index
944 * \retval NULL on error
945 */
946void *NFQGetQueue(int number)
947{
948 if (unlikely(number < 0 || number >= receive_queue_num || g_nfq_q == NULL))
949 return NULL;
950
951 return (void *)&g_nfq_q[number];
952}
953
954/**
955 * \brief Get a pointer to the NFQ thread at index
956 *
957 * This function is temporary used as configuration parser.
958 *
959 * \param number idx of the queue in our array
960 *
961 * \retval ptr pointer to the NFQThreadVars at index
962 * \retval NULL on error
963 */
964void *NFQGetThread(int number)
965{
966 if (unlikely(number < 0 || number >= receive_queue_num || g_nfq_t == NULL))
967 return NULL;
968
969 return (void *)&g_nfq_t[number];
970}
971
972/**
973 * \brief NFQ function to get a packet from the kernel
974 */
975static void NFQRecvPkt(NFQQueueVars *t, NFQThreadVars *tv)
976{
977 int ret;
978 int flag = NFQVerdictCacheLen(t) ? MSG_DONTWAIT : 0;
979
980 int rv = recv(t->fd, tv->data, tv->datalen, flag);
981 if (rv < 0) {
982 if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
983 /* no error on timeout */
984 if (flag)
985 NFQVerdictCacheFlush(t);
986
987 /* handle timeout */
988 TmThreadsCaptureHandleTimeout(tv->tv, NULL);
989 } else {
990#ifdef COUNTERS
991 NFQMutexLock(t);
992 t->errs++;
994#endif /* COUNTERS */
995 }
996 } else if(rv == 0) {
997 SCLogWarning("recv got returncode 0");
998 } else {
999#ifdef DBG_PERF
1000 if (rv > t->dbg_maxreadsize)
1001 t->dbg_maxreadsize = rv;
1002#endif /* DBG_PERF */
1003
1004 NFQMutexLock(t);
1005 if (t->qh != NULL) {
1006 ret = nfq_handle_packet(t->h, tv->data, rv);
1007 } else {
1008 SCLogWarning("NFQ handle has been destroyed");
1009 ret = -1;
1010 }
1011 NFQMutexUnlock(t);
1012 if (ret != 0) {
1013 SCLogDebug("nfq_handle_packet error %"PRId32, ret);
1014 }
1015 }
1016}
1017
1018/**
1019 * \brief Main NFQ reading Loop function
1020 */
1021TmEcode ReceiveNFQLoop(ThreadVars *tv, void *data, void *slot)
1022{
1023 SCEnter();
1024 NFQThreadVars *ntv = (NFQThreadVars *)data;
1026
1027 ntv->slot = ((TmSlot *) slot)->slot_next;
1028
1029 // Indicate that the thread is actually running its application level code (i.e., it can poll
1030 // packets)
1032
1033 while(1) {
1034 if (unlikely(suricata_ctl_flags != 0)) {
1035 NFQDestroyQueue(nq);
1036 break;
1037 }
1038 NFQRecvPkt(nq, ntv);
1039
1041 }
1043}
1044
1045/**
1046 * \brief NFQ receive module stats printing function
1047 */
1048void ReceiveNFQThreadExitStats(ThreadVars *tv, void *data)
1049{
1050 NFQThreadVars *ntv = (NFQThreadVars *)data;
1052#ifdef COUNTERS
1053 SCLogNotice("(%s) Treated: Pkts %" PRIu32 ", Bytes %" PRIu64 ", Errors %" PRIu32 "",
1054 tv->name, nq->pkts, nq->bytes, nq->errs);
1055 SCLogNotice("(%s) Verdict: Accepted %"PRIu32", Dropped %"PRIu32", Replaced %"PRIu32,
1056 tv->name, nq->accepted, nq->dropped, nq->replaced);
1057#endif
1058}
1059
1060static inline uint32_t GetVerdict(const Packet *p)
1061{
1062 uint32_t verdict = NF_ACCEPT;
1063
1065 verdict = NF_DROP;
1066 } else {
1067 switch (nfq_config.mode) {
1068 default:
1069 case NFQ_ACCEPT_MODE:
1070 verdict = NF_ACCEPT;
1071 break;
1072 case NFQ_REPEAT_MODE:
1073 verdict = NF_REPEAT;
1074 break;
1075 case NFQ_ROUTE_MODE:
1076 verdict = ((uint32_t) NF_QUEUE) | nfq_config.next_queue;
1077 break;
1078 }
1079 }
1080 return verdict;
1081}
1082
1083#ifdef COUNTERS
1084static inline void UpdateCounters(NFQQueueVars *t, const Packet *p)
1085{
1087 t->dropped++;
1088 } else {
1089 if (p->flags & PKT_STREAM_MODIFIED) {
1090 t->replaced++;
1091 }
1092
1093 t->accepted++;
1094 }
1095}
1096#endif /* COUNTERS */
1097
1098/** \internal
1099 * \brief NFQ verdict function
1100 * \param p Packet to work with. Will be the tunnel root packet in case of tunnel.
1101 */
1102static TmEcode NFQSetVerdict(Packet *p, const uint32_t mark_value, const bool mark_modified)
1103{
1104 int iter = 0;
1105 /* we could also have a direct pointer but we need to have a ref count in this case */
1106 NFQQueueVars *t = g_nfq_q + p->nfq_v.nfq_index;
1107
1108 /* can't verdict a "fake" packet */
1109 if (PKT_IS_PSEUDOPKT(p)) {
1110 return TM_ECODE_OK;
1111 }
1112
1113 //printf("%p verdicting on queue %" PRIu32 "\n", t, t->queue_num);
1114 NFQMutexLock(t);
1115
1116 if (t->qh == NULL) {
1117 /* Somebody has started a clean-up, we leave */
1118 NFQMutexUnlock(t);
1119 return TM_ECODE_OK;
1120 }
1121
1122 uint32_t verdict = GetVerdict(p);
1123#ifdef COUNTERS
1124 UpdateCounters(t, p);
1125#endif /* COUNTERS */
1126
1127 int ret = NFQVerdictCacheAdd(t, p, verdict, mark_value, mark_modified);
1128 if (ret == 0) {
1129 NFQMutexUnlock(t);
1130 return TM_ECODE_OK;
1131 }
1132
1133 do {
1134 switch (nfq_config.mode) {
1135 default:
1136 case NFQ_ACCEPT_MODE:
1137 case NFQ_ROUTE_MODE:
1138 if (mark_modified) {
1139#ifdef HAVE_NFQ_SET_VERDICT2
1140 if (p->flags & PKT_STREAM_MODIFIED) {
1141 ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict, mark_value,
1142 GET_PKT_LEN(p), GET_PKT_DATA(p));
1143 } else {
1144 ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict, mark_value, 0, NULL);
1145 }
1146#else /* fall back to old function */
1147 if (p->flags & PKT_STREAM_MODIFIED) {
1148 ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict, htonl(mark_value),
1149 GET_PKT_LEN(p), GET_PKT_DATA(p));
1150 } else {
1151 ret = nfq_set_verdict_mark(
1152 t->qh, p->nfq_v.id, verdict, htonl(mark_value), 0, NULL);
1153 }
1154#endif /* HAVE_NFQ_SET_VERDICT2 */
1155 } else {
1156 if (p->flags & PKT_STREAM_MODIFIED) {
1157 ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict,
1158 GET_PKT_LEN(p), GET_PKT_DATA(p));
1159 } else {
1160 ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict, 0, NULL);
1161 }
1162 }
1163 break;
1164 case NFQ_REPEAT_MODE:
1165#ifdef HAVE_NFQ_SET_VERDICT2
1166 if (p->flags & PKT_STREAM_MODIFIED) {
1167 ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
1168 (nfq_config.mark & nfq_config.mask) | (mark_value & ~nfq_config.mask),
1169 GET_PKT_LEN(p), GET_PKT_DATA(p));
1170 } else {
1171 ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
1172 (nfq_config.mark & nfq_config.mask) | (mark_value & ~nfq_config.mask),
1173 0, NULL);
1174 }
1175#else /* fall back to old function */
1176 if (p->flags & PKT_STREAM_MODIFIED) {
1177 ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
1178 htonl((nfq_config.mark & nfq_config.mask) |
1179 (mark_value & ~nfq_config.mask)),
1180 GET_PKT_LEN(p), GET_PKT_DATA(p));
1181 } else {
1182 ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
1183 htonl((nfq_config.mark & nfq_config.mask) |
1184 (mark_value & ~nfq_config.mask)),
1185 0, NULL);
1186 }
1187#endif /* HAVE_NFQ_SET_VERDICT2 */
1188 break;
1189 }
1190 } while ((ret < 0) && (iter++ < NFQ_VERDICT_RETRY_COUNT));
1191
1192 NFQMutexUnlock(t);
1193
1194 if (ret < 0) {
1195 SCLogWarning("nfq_set_verdict of %p failed %" PRId32 ": %s", p, ret, strerror(errno));
1196 return TM_ECODE_FAILED;
1197 }
1198 return TM_ECODE_OK;
1199}
1200
1201/**
1202 * \brief NFQ verdict module packet entry function
1203 */
1204TmEcode VerdictNFQ(ThreadVars *tv, Packet *p, void *data)
1205{
1206 /* if this is a tunnel packet we check if we are ready to verdict
1207 * already. */
1208 if (PacketIsTunnel(p)) {
1209 Packet *root_p = p->root ? p->root : p;
1210
1211 SCLogDebug("tunnel pkt: %p/%p %s", p, p->root, p->root ? "upper layer" : "root");
1212
1215 const bool do_verdict = VerdictTunnelPacketInternal(p);
1216 // taken from root packet
1217 const bool mark_modified = root_p->nfq_v.mark_modified;
1218 const uint32_t mark_value = root_p->nfq_v.mark;
1219 root_p->nfq_v.verdicted = do_verdict;
1221 /* don't verdict if we are not ready */
1222 if (do_verdict) {
1223 int ret = NFQSetVerdict(root_p, mark_value, mark_modified);
1224 if (ret != TM_ECODE_OK) {
1225 return ret;
1226 }
1227 }
1228 } else {
1229 /* no tunnel, verdict normally */
1230
1231 /* coverity[missing_lock] */
1232 p->nfq_v.verdicted = true;
1233
1234 /* coverity[missing_lock] */
1235 int ret = NFQSetVerdict(p, p->nfq_v.mark, p->nfq_v.mark_modified);
1236 if (ret != TM_ECODE_OK) {
1237 return ret;
1238 }
1239 }
1240 return TM_ECODE_OK;
1241}
1242
1243/**
1244 * \brief Decode a packet coming from NFQ
1245 */
1246TmEcode DecodeNFQ(ThreadVars *tv, Packet *p, void *data)
1247{
1248
1249 IPV4Hdr *ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
1250 IPV6Hdr *ip6h = (IPV6Hdr *)GET_PKT_DATA(p);
1252
1254
1256
1257 if (IPV4_GET_RAW_VER(ip4h) == 4) {
1258 if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) {
1259 return TM_ECODE_FAILED;
1260 }
1261 SCLogDebug("IPv4 packet");
1263 } else if (IPV6_GET_RAW_VER(ip6h) == 6) {
1264 if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) {
1265 return TM_ECODE_FAILED;
1266 }
1267 SCLogDebug("IPv6 packet");
1269 } else {
1270 SCLogDebug("packet unsupported by NFQ, first byte: %02x", *GET_PKT_DATA(p));
1271 }
1272
1274
1275 return TM_ECODE_OK;
1276}
1277
1278/**
1279 * \brief Initialize the NFQ Decode threadvars
1280 */
1281TmEcode DecodeNFQThreadInit(ThreadVars *tv, const void *initdata, void **data)
1282{
1284 if (dtv == NULL)
1286
1288
1289 *data = (void *)dtv;
1290 return TM_ECODE_OK;
1291}
1292
1293TmEcode DecodeNFQThreadDeinit(ThreadVars *tv, void *data)
1294{
1295 if (data != NULL)
1296 DecodeThreadVarsFree(tv, data);
1298}
1299
1300/**
1301 * \brief Clean global contexts. Must be called on exit.
1302 */
1304{
1305 if (g_nfq_q != NULL) {
1306 SCFree(g_nfq_q);
1307 g_nfq_q = NULL;
1308 }
1309
1310 if (g_nfq_t != NULL) {
1311 SCFree(g_nfq_t);
1312 g_nfq_t = NULL;
1313 }
1314}
1315#endif /* NFQ */
#define ACTION_DROP
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition conf.c:414
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition conf.c:497
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition conf.c:350
void StatsSyncCountersIfSignalled(ThreadVars *tv)
Definition counters.c:450
uint8_t flags
Definition decode-gre.h:0
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
#define IPV4_GET_RAW_VER(ip4h)
Definition decode-ipv4.h:95
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
#define IPV6_GET_RAW_VER(ip6h)
Definition decode-ipv6.h:62
@ PKT_DROP_REASON_NFQ_ERROR
Definition decode.h:396
#define SET_PKT_LEN(p, len)
Definition decode.h:213
#define PKT_REBUILT_FRAGMENT
Definition decode.h:1302
#define PKT_SET_SRC(p, src_val)
Definition decode.h:1325
#define GET_PKT_DATA(p)
Definition decode.h:209
#define PKT_STREAM_MODIFIED
Definition decode.h:1271
#define GET_PKT_LEN(p)
Definition decode.h:208
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition decode.h:1321
@ PKT_SRC_WIRE
Definition decode.h:52
DecodeThreadVars * dtv
ThreadVars * tv
uint32_t max_pending_packets
Definition suricata.c:183
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
Definition decode.c:293
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition decode.c:628
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition decode.c:232
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition decode.c:804
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition decode.c:822
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition decode.c:377
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition decode.c:770
int PacketSetData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Set data for Packet and set length when zero copy is used.
Definition decode.c:842
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
Definition decode.c:276
HRLOCK_TYPE lock
Definition host.h:0
void PacketDrop(Packet *p, const uint8_t action, enum PacketDropReason r)
issue drop action
Definition packet.c:33
bool PacketCheckAction(const Packet *p, const uint8_t a)
Definition packet.c:49
char * RunmodeGetActive(void)
Definition runmodes.c:199
void NFQContextsClean(void)
Clean global contexts. Must be called on exit.
#define MAX_ALREADY_TREATED
Definition source-nfq.c:103
#define NFQ_FLAG_FAIL_OPEN
Definition source-nfq.c:155
enum NFQMode_ NFQMode
void TmModuleReceiveNFQRegister(void)
Definition source-nfq.c:170
NFQCnf nfq_config
Definition source-nfq.c:168
struct NFQThreadVars_ NFQThreadVars
#define SOL_NETLINK
Definition source-nfq.c:111
void NFQInitConfig(bool quiet)
To initialize the NFQ global configuration data.
Definition source-nfq.c:208
void * NFQGetQueue(int number)
Get a pointer to the NFQ queue at index.
Definition source-nfq.c:946
void TmModuleVerdictNFQRegister(void)
Definition source-nfq.c:185
#define NFQMutexUnlock(nq)
Definition source-nfq.c:393
int NFQParseAndRegisterQueues(const char *queues)
Parses and adds Netfilter queue(s).
Definition source-nfq.c:881
#define NFQMutexLock(nq)
Definition source-nfq.c:388
NFQMode_
Definition source-nfq.c:149
@ NFQ_ACCEPT_MODE
Definition source-nfq.c:150
@ NFQ_REPEAT_MODE
Definition source-nfq.c:151
@ NFQ_ROUTE_MODE
Definition source-nfq.c:152
int NFQRegisterQueue(const uint16_t number)
Add a single Netfilter queue.
Definition source-nfq.c:825
#define NFQ_BURST_FACTOR
Definition source-nfq.c:108
struct NFQCnf_ NFQCnf
void TmModuleDecodeNFQRegister(void)
Definition source-nfq.c:194
#define NFQ_VERDICT_RETRY_COUNT
Definition source-nfq.c:104
#define T_DATA_SIZE
void * NFQGetThread(int number)
Get a pointer to the NFQ thread at index.
Definition source-nfq.c:964
#define NFQ_MAX_QUEUE
Definition source-nfq.h:34
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
uint8_t batchcount
Definition source-nfq.c:165
uint32_t flags
Definition source-nfq.c:164
uint32_t mask
Definition source-nfq.c:160
uint32_t bypass_mark
Definition source-nfq.c:161
uint32_t next_queue
Definition source-nfq.c:163
NFQMode mode
Definition source-nfq.c:158
uint32_t bypass_mask
Definition source-nfq.c:162
uint32_t mark
Definition source-nfq.c:159
uint32_t ifi
Definition source-nfq.h:47
uint16_t hw_protocol
Definition source-nfq.h:49
uint32_t mark
Definition source-nfq.h:46
uint32_t ifo
Definition source-nfq.h:48
uint16_t nfq_index
Definition source-nfq.h:42
uint8_t len
Definition source-nfq.h:82
struct nfq_handle * h
Definition source-nfq.h:54
uint32_t verdict
Definition source-nfq.h:79
uint64_t bytes
Definition source-nfq.h:72
uint16_t queue_num
Definition source-nfq.h:62
uint32_t packet_id
Definition source-nfq.h:78
uint32_t mark
Definition source-nfq.h:80
struct nfq_q_handle * qh
Definition source-nfq.h:59
uint32_t dropped
Definition source-nfq.h:75
SCMutex mutex_qh
Definition source-nfq.h:60
uint32_t replaced
Definition source-nfq.h:76
uint8_t maxlen
Definition source-nfq.h:83
uint32_t errs
Definition source-nfq.h:73
uint32_t pkts
Definition source-nfq.h:71
uint8_t use_mutex
Definition source-nfq.h:57
struct NFQQueueVars_::@148 verdict_cache
uint32_t accepted
Definition source-nfq.h:74
struct nfnl_handle * nh
Definition source-nfq.h:55
uint8_t mark_valid
Definition source-nfq.h:81
uint16_t nfq_index
Definition source-nfq.c:116
ThreadVars * tv
Definition source-nfq.c:117
LiveDevice * livedev
Definition source-nfq.c:120
TmSlot * slot
Definition source-nfq.c:118
SCTime_t ts
Definition decode.h:555
SCSpinlock tunnel_lock
Definition decode.h:683
struct Packet_::@39 persistent
int datalink
Definition decode.h:639
struct Packet_ * root
Definition decode.h:653
void(* ReleasePacket)(struct Packet_ *)
Definition decode.h:591
uint32_t flags
Definition decode.h:544
NFQPacketVars nfq_v
Definition decode.h:563
int(* BypassPacketsFlow)(struct Packet_ *)
Definition decode.h:594
Per thread variable structure.
Definition threadvars.h:58
char name[16]
Definition threadvars.h:65
const char * name
Definition tm-modules.h:48
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition tm-modules.h:53
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition tm-modules.h:52
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition tm-modules.h:61
uint8_t cap_flags
Definition tm-modules.h:77
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition tm-modules.h:56
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition tm-modules.h:58
uint8_t flags
Definition tm-modules.h:80
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition tm-modules.h:51
struct TmSlot_ * slot_next
Definition tm-threads.h:62
#define BUG_ON(x)
#define SCNtohl(x)
volatile uint8_t suricata_ctl_flags
Definition suricata.c:172
#define SCSpinlock
#define SCSpinUnlock
#define SCMutex
#define SCMutexUnlock(mut)
#define SCSpinLock
#define SCMutexInit(mut, mutattrs)
#define SCMutexLock(mut)
#define THV_RUNNING
Definition threadvars.h:55
TmModule tmm_modules[TMM_SIZE]
Definition tm-modules.c:29
#define TM_FLAG_RECEIVE_TM
Definition tm-modules.h:32
#define TM_FLAG_DECODE_TM
Definition tm-modules.h:33
#define TM_FLAG_VERDICT_TM
Definition tm-modules.h:35
@ TMM_VERDICTNFQ
@ TMM_DECODENFQ
@ TMM_RECEIVENFQ
@ TM_ECODE_FAILED
@ TM_ECODE_OK
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition tm-threads.c:101
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
uint16_t UtilCpuGetNumProcessorsOnline(void)
Get the number of cpus online in the system.
Definition util-cpu.c:108
#define SCEnter(...)
Definition util-debug.h:277
#define FatalError(...)
Definition util-debug.h:510
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition util-debug.h:243
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
int LiveRegisterDevice(const char *dev)
Add a pcap device for monitoring and create structure.
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
#define SCRealloc(ptr, sz)
Definition util-mem.h:50
#define unlikely(expr)
#define SC_CAP_NET_ADMIN
Definition util-privs.h:31
#define SCTIME_FROM_TIMEVAL(tv)
Definition util-time.h:79