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