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-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
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;
79 }
80 
81 void TmModuleDecodeNFQRegister (void)
82 {
83  tmm_modules[TMM_DECODENFQ].name = "DecodeNFQ";
84  tmm_modules[TMM_DECODENFQ].ThreadInit = NoNFQSupportExit;
89 }
90 
91 static 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 
101 extern uint32_t max_pending_packets;
102 
103 #define MAX_ALREADY_TREATED 5
104 #define NFQ_VERDICT_RETRY_COUNT 3
105 static int already_seen_warning;
106 static int runmode_workers;
107 
108 #define NFQ_BURST_FACTOR 4
109 
110 #ifndef SOL_NETLINK
111 #define SOL_NETLINK 270
112 #endif
113 
114 typedef 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 */
126 static NFQGlobalVars nfq_g;
127 
128 static NFQThreadVars *g_nfq_t;
129 static NFQQueueVars *g_nfq_q;
130 static uint16_t receive_queue_num = 0;
131 static SCMutex nfq_init_lock;
132 
133 static TmEcode ReceiveNFQLoop(ThreadVars *tv, void *data, void *slot);
134 static TmEcode ReceiveNFQThreadInit(ThreadVars *, const void *, void **);
135 static TmEcode ReceiveNFQThreadDeinit(ThreadVars *, void *);
136 static void ReceiveNFQThreadExitStats(ThreadVars *, void *);
137 
138 static TmEcode VerdictNFQ(ThreadVars *, Packet *, void *);
139 static TmEcode VerdictNFQThreadInit(ThreadVars *, const void *, void **);
140 static TmEcode VerdictNFQThreadDeinit(ThreadVars *, void *);
141 
142 static TmEcode DecodeNFQ(ThreadVars *, Packet *, void *);
143 static TmEcode DecodeNFQThreadInit(ThreadVars *, const void *, void **);
144 static TmEcode DecodeNFQThreadDeinit(ThreadVars *tv, void *data);
145 
146 static TmEcode NFQSetVerdict(Packet *p, const uint32_t mark_value, const bool mark_modified);
147 static void NFQReleasePacket(Packet *p);
148 
149 typedef enum NFQMode_ {
154 
155 #define NFQ_FLAG_FAIL_OPEN (1 << 0)
156 
157 typedef 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  */
208 void 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 
293 static 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 
302 static void NFQVerdictCacheFlush(NFQQueueVars *t)
303 {
304 #ifdef HAVE_NFQ_SET_VERDICT_BATCH
305  int ret;
306  int iter = 0;
307 
308  do {
309  if (t->verdict_cache.mark_valid)
310  ret = nfq_set_verdict_batch2(t->qh,
313  t->verdict_cache.mark);
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;
324  t->verdict_cache.mark_valid = 0;
325  }
326 #endif
327 }
328 
329 static 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;
343  t->verdict_cache.mark_valid = 1;
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 
360  if (t->verdict_cache.len >= t->verdict_cache.maxlen)
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 
373 static 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  */
405 static 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) {
434  SCLogWarning(
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  }
480  p->ts = SCTIME_FROM_TIMEVAL(&tv);
481 
482  p->datalink = DLT_RAW;
483  return 0;
484 }
485 
486 static 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;
499  SCSpinLock(lock);
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  */
520 static 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] */
538  | (p->nfq_v.mark & ~nfq_config.bypass_mask);
539  /* coverity[missing_lock] */
540  p->nfq_v.mark_modified = true;
541  }
542 
543  return 1;
544 }
545 
546 static 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 */
562  if (nfq_config.bypass_mask) {
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 
596 static 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 
729 TmEcode 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 
767 static 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 
784 TmEcode ReceiveNFQThreadDeinit(ThreadVars *t, void *data)
785 {
786  NFQThreadVars *ntv = (NFQThreadVars *)data;
787  NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index);
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 
800 TmEcode 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 
807 TmEcode VerdictNFQThreadDeinit(ThreadVars *tv, void *data)
808 {
809  NFQThreadVars *ntv = (NFQThreadVars *)data;
810  NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index);
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  */
825 int 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  */
881 int 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  */
946 void *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  */
964 void *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  */
975 static 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++;
993  NFQMutexUnlock(t);
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  */
1021 TmEcode ReceiveNFQLoop(ThreadVars *tv, void *data, void *slot)
1022 {
1023  SCEnter();
1024  NFQThreadVars *ntv = (NFQThreadVars *)data;
1025  NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index);
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  */
1048 void ReceiveNFQThreadExitStats(ThreadVars *tv, void *data)
1049 {
1050  NFQThreadVars *ntv = (NFQThreadVars *)data;
1051  NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index);
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 
1060 static inline uint32_t GetVerdict(const Packet *p)
1061 {
1062  uint32_t verdict = NF_ACCEPT;
1063 
1064  if (PacketCheckAction(p, ACTION_DROP)) {
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
1084 static inline void UpdateCounters(NFQQueueVars *t, const Packet *p)
1085 {
1086  if (PacketCheckAction(p, ACTION_DROP)) {
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  */
1102 static 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  */
1204 TmEcode 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 
1213  SCSpinlock *lock = &root_p->persistent.tunnel_lock;
1214  SCSpinLock(lock);
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;
1220  SCSpinUnlock(lock);
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  int ret = NFQSetVerdict(p, p->nfq_v.mark, p->nfq_v.mark_modified);
1235  if (ret != TM_ECODE_OK) {
1236  return ret;
1237  }
1238  }
1239  return TM_ECODE_OK;
1240 }
1241 
1242 /**
1243  * \brief Decode a packet coming from NFQ
1244  */
1245 TmEcode DecodeNFQ(ThreadVars *tv, Packet *p, void *data)
1246 {
1247 
1248  IPV4Hdr *ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
1249  IPV6Hdr *ip6h = (IPV6Hdr *)GET_PKT_DATA(p);
1251 
1253 
1255 
1256  if (IPV4_GET_RAW_VER(ip4h) == 4) {
1257  if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) {
1258  return TM_ECODE_FAILED;
1259  }
1260  SCLogDebug("IPv4 packet");
1261  DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p));
1262  } else if (IPV6_GET_RAW_VER(ip6h) == 6) {
1263  if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) {
1264  return TM_ECODE_FAILED;
1265  }
1266  SCLogDebug("IPv6 packet");
1267  DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p));
1268  } else {
1269  SCLogDebug("packet unsupported by NFQ, first byte: %02x", *GET_PKT_DATA(p));
1270  }
1271 
1273 
1274  return TM_ECODE_OK;
1275 }
1276 
1277 /**
1278  * \brief Initialize the NFQ Decode threadvars
1279  */
1280 TmEcode DecodeNFQThreadInit(ThreadVars *tv, const void *initdata, void **data)
1281 {
1283  if (dtv == NULL)
1285 
1287 
1288  *data = (void *)dtv;
1289  return TM_ECODE_OK;
1290 }
1291 
1292 TmEcode DecodeNFQThreadDeinit(ThreadVars *tv, void *data)
1293 {
1294  if (data != NULL)
1295  DecodeThreadVarsFree(tv, data);
1297 }
1298 
1299 /**
1300  * \brief Clean global contexts. Must be called on exit.
1301  */
1303 {
1304  if (g_nfq_q != NULL) {
1305  SCFree(g_nfq_q);
1306  g_nfq_q = NULL;
1307  }
1308 
1309  if (g_nfq_t != NULL) {
1310  SCFree(g_nfq_t);
1311  g_nfq_t = NULL;
1312  }
1313 }
1314 #endif /* NFQ */
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:77
PacketCheckAction
bool PacketCheckAction(const Packet *p, const uint8_t a)
Definition: packet.c:49
NFQCnf_::flags
uint32_t flags
Definition: source-nfq.c:164
util-device-private.h
util-byte.h
tm-threads.h
NFQGetThread
void * NFQGetThread(int number)
Get a pointer to the NFQ thread at index.
Definition: source-nfq.c:964
LiveRegisterDevice
int LiveRegisterDevice(const char *dev)
Add a pcap device for monitoring and create structure.
Definition: util-device.c:132
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:65
PacketFreeOrRelease
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
Definition: decode.c:276
NFQQueueVars_::bytes
uint64_t bytes
Definition: source-nfq.h:72
TM_FLAG_VERDICT_TM
#define TM_FLAG_VERDICT_TM
Definition: tm-modules.h:35
NFQMutexLock
#define NFQMutexLock(nq)
Definition: source-nfq.c:388
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:377
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1319
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:1269
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:275
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:101
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:120
action-globals.h
Packet_::flags
uint32_t flags
Definition: decode.h:544
threads.h
NFQ_FLAG_FAIL_OPEN
#define NFQ_FLAG_FAIL_OPEN
Definition: source-nfq.c:155
NFQCnf_::mark
uint32_t mark
Definition: source-nfq.c:159
LiveDevice_
Definition: util-device-private.h:32
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:332
SCConfGet
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:350
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:55
NFQQueueVars_::verdict_cache
struct NFQQueueVars_::@148 verdict_cache
packet-queue.h
NFQQueueVars_
Definition: source-nfq.h:53
NFQThreadVars_::nfq_index
uint16_t nfq_index
Definition: source-nfq.c:116
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
SCConfGetBool
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:497
SCSpinLock
#define SCSpinLock
Definition: threads-debug.h:235
Packet_::persistent
struct Packet_::@39 persistent
util-privs.h
NFQ_REPEAT_MODE
@ NFQ_REPEAT_MODE
Definition: source-nfq.c:151
PacketDecodeFinalize
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition: decode.c:232
RunmodeGetActive
char * RunmodeGetActive(void)
Definition: runmodes.c:199
NFQThreadVars_::data
char * data
Definition: source-nfq.c:122
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:208
NFQCnf
struct NFQCnf_ NFQCnf
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:314
Packet_::BypassPacketsFlow
int(* BypassPacketsFlow)(struct Packet_ *)
Definition: decode.h:594
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
tmqh-packetpool.h
NFQMutexUnlock
#define NFQMutexUnlock(nq)
Definition: source-nfq.c:393
TmModule_::PktAcqLoop
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:58
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
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:53
Packet_::datalink
int datalink
Definition: decode.h:639
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1323
lock
HRLOCK_TYPE lock
Definition: host.h:0
NFQPacketVars_::ifo
uint32_t ifo
Definition: source-nfq.h:48
DecodeRegisterPerfCounters
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:628
NFQParseAndRegisterQueues
int NFQParseAndRegisterQueues(const char *queues)
Parses and adds Netfilter queue(s).
Definition: source-nfq.c:881
SET_PKT_LEN
#define SET_PKT_LEN(p, len)
Definition: decode.h:213
decode.h
util-debug.h
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:52
NFQQueueVars_::maxlen
uint8_t maxlen
Definition: source-nfq.h:83
source-nfq.h
util-error.h
TmModuleVerdictNFQRegister
void TmModuleVerdictNFQRegister(void)
Definition: source-nfq.c:185
NFQGetQueue
void * NFQGetQueue(int number)
Get a pointer to the NFQ queue at index.
Definition: source-nfq.c:946
TmModule_::PktAcqBreakLoop
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:61
util-cpu.h
Packet_::tunnel_lock
SCSpinlock tunnel_lock
Definition: decode.h:683
Packet_::ts
SCTime_t ts
Definition: decode.h:555
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:158
LiveGetDevice
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
Definition: util-device.c:268
NFQPacketVars_::id
int id
Definition: source-nfq.h:41
SCConfGetInt
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:414
SCEnter
#define SCEnter(...)
Definition: util-debug.h:277
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:209
NFQ_ACCEPT_MODE
@ NFQ_ACCEPT_MODE
Definition: source-nfq.c:150
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
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:104
TmModule_::Func
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition: tm-modules.h:56
NFQCnf_::bypass_mask
uint32_t bypass_mask
Definition: source-nfq.c:162
SCSpinUnlock
#define SCSpinUnlock
Definition: threads-debug.h:237
NFQCnf_::mask
uint32_t mask
Definition: source-nfq.c:160
nfq_config
NFQCnf nfq_config
Definition: source-nfq.c:168
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:255
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:161
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
NFQThreadVars_::tv
ThreadVars * tv
Definition: source-nfq.c:117
IPV6Hdr_
Definition: decode-ipv6.h:32
Packet_
Definition: decode.h:501
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:29
conf-yaml-loader.h
DecodeIPV6
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv6.c:560
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:208
conf.h
NFQ_BURST_FACTOR
#define NFQ_BURST_FACTOR
Definition: source-nfq.c:108
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:80
max_pending_packets
uint32_t max_pending_packets
Definition: suricata.c:183
NFQ_MAX_QUEUE
#define NFQ_MAX_QUEUE
Definition: source-nfq.h:34
TmModule_::name
const char * name
Definition: tm-modules.h:48
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:225
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:563
NFQMode_
NFQMode_
Definition: source-nfq.c:149
Packet_::ReleasePacket
void(* ReleasePacket)(struct Packet_ *)
Definition: decode.h:591
flags
uint8_t flags
Definition: decode-gre.h:0
DecodeThreadVarsFree
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition: decode.c:820
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:396
NFQThreadVars_::slot
TmSlot * slot
Definition: source-nfq.c:118
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:51
NFQPacketVars_::nfq_index
uint16_t nfq_index
Definition: source-nfq.h:42
FatalError
#define FatalError(...)
Definition: util-debug.h:510
TMM_VERDICTNFQ
@ TMM_VERDICTNFQ
Definition: tm-threads-common.h:36
TmModuleReceiveNFQRegister
void TmModuleReceiveNFQRegister(void)
Definition: source-nfq.c:170
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
MAX_ALREADY_TREATED
#define MAX_ALREADY_TREATED
Definition: source-nfq.c:103
TMM_RECEIVENFQ
@ TMM_RECEIVENFQ
Definition: tm-threads-common.h:37
TmModule_::ThreadExitPrintStats
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:52
threadvars.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
Packet_::root
struct Packet_ * root
Definition: decode.h:653
NFQQueueVars_::len
uint8_t len
Definition: source-nfq.h:82
PKT_REBUILT_FRAGMENT
#define PKT_REBUILT_FRAGMENT
Definition: decode.h:1300
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:267
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:430
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:963
NFQQueueVars_::mark_valid
uint8_t mark_valid
Definition: source-nfq.h:81
DecodeThreadVarsAlloc
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:802
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:840
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:33
NFQPacketVars_::verdicted
bool verdicted
Definition: source-nfq.h:43
suricata.h
NFQThreadVars_::datalen
int datalen
Definition: source-nfq.c:123
NFQThreadVars_
Definition: source-nfq.c:115
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:450
NFQCnf_::next_queue
uint32_t next_queue
Definition: source-nfq.c:163
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:165
NFQ_ROUTE_MODE
@ NFQ_ROUTE_MODE
Definition: source-nfq.c:152
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:243
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:281
SCMutex
#define SCMutex
Definition: threads-debug.h:114
SOL_NETLINK
#define SOL_NETLINK
Definition: source-nfq.c:111
NFQContextsClean
void NFQContextsClean(void)
Clean global contexts. Must be called on exit.
Definition: source-nfq.c:1302
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:293
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:80
TmModuleDecodeNFQRegister
void TmModuleDecodeNFQRegister(void)
Definition: source-nfq.c:194
DecodeUpdatePacketCounters
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition: decode.c:768
NFQQueueVars_::use_mutex
uint8_t use_mutex
Definition: source-nfq.h:57
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:172
NFQCnf_
Definition: source-nfq.c:157
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:825
T_DATA_SIZE
#define T_DATA_SIZE