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