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