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 TmEcode ReceiveNFQLoop(ThreadVars *tv, void *data, void *slot);
136 TmEcode ReceiveNFQThreadInit(ThreadVars *, const void *, void **);
138 void ReceiveNFQThreadExitStats(ThreadVars *, void *);
139 
141 TmEcode VerdictNFQThreadInit(ThreadVars *, const void *, void **);
143 
145 TmEcode DecodeNFQThreadInit(ThreadVars *, const void *, void **);
147 
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";
184 }
185 
187 {
188  tmm_modules[TMM_VERDICTNFQ].name = "VerdictNFQ";
193 }
194 
196 {
197  tmm_modules[TMM_DECODENFQ].name = "DecodeNFQ";
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) {
220  nfq_config.mode = NFQ_ACCEPT_MODE;
221  } else {
222  if (!strcmp("accept", nfq_mode)) {
223  nfq_config.mode = NFQ_ACCEPT_MODE;
224  } else if (!strcmp("repeat", nfq_mode)) {
225  nfq_config.mode = NFQ_REPEAT_MODE;
226  } else if (!strcmp("route", nfq_mode)) {
227  nfq_config.mode = NFQ_ROUTE_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");
238  nfq_config.flags |= NFQ_FLAG_FAIL_OPEN;
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,
286  nfq_config.mark, nfq_config.mask);
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);
423  if (nfq_config.mode == NFQ_REPEAT_MODE) {
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;
504  tp->nfq_v.mark = (nfq_config.bypass_mark & nfq_config.bypass_mask)
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] */
513  p->nfq_v.mark = (nfq_config.bypass_mark & nfq_config.bypass_mask)
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 */
552  TmqhOutputPacketpool(tv, p);
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 (ntv->slot) {
566  if (TmThreadsSlotProcessPkt(tv, ntv->slot, p) != TM_ECODE_OK) {
567  TmqhOutputPacketpool(ntv->tv, p);
568  return -1;
569  }
570  } else {
571  /* pass on... */
572  tv->tmqh_out(tv, p);
573  }
574 
575  return 0;
576 }
577 
578 static TmEcode NFQInitThread(NFQThreadVars *t, uint32_t queue_maxlen)
579 {
580  struct timeval tv;
581  int opt;
583  if (q == NULL) {
584  SCLogError(SC_ERR_NFQ_OPEN, "no queue for given index");
585  return TM_ECODE_FAILED;
586  }
587  SCLogDebug("opening library handle");
588  q->h = nfq_open();
589  if (q->h == NULL) {
590  SCLogError(SC_ERR_NFQ_OPEN, "nfq_open() failed");
591  return TM_ECODE_FAILED;
592  }
593 
594  if (nfq_g.unbind == 0)
595  {
596  /* VJ: on my Ubuntu Hardy system this fails the first time it's
597  * run. Ignoring the error seems to have no bad effects. */
598  SCLogDebug("unbinding existing nf_queue handler for AF_INET (if any)");
599  if (nfq_unbind_pf(q->h, AF_INET) < 0) {
600  SCLogError(SC_ERR_NFQ_UNBIND, "nfq_unbind_pf() for AF_INET failed");
601  exit(EXIT_FAILURE);
602  }
603  if (nfq_unbind_pf(q->h, AF_INET6) < 0) {
604  SCLogError(SC_ERR_NFQ_UNBIND, "nfq_unbind_pf() for AF_INET6 failed");
605  exit(EXIT_FAILURE);
606  }
607  nfq_g.unbind = 1;
608 
609  SCLogDebug("binding nfnetlink_queue as nf_queue handler for AF_INET and AF_INET6");
610 
611  if (nfq_bind_pf(q->h, AF_INET) < 0) {
612  SCLogError(SC_ERR_NFQ_BIND, "nfq_bind_pf() for AF_INET failed");
613  exit(EXIT_FAILURE);
614  }
615  if (nfq_bind_pf(q->h, AF_INET6) < 0) {
616  SCLogError(SC_ERR_NFQ_BIND, "nfq_bind_pf() for AF_INET6 failed");
617  exit(EXIT_FAILURE);
618  }
619  }
620 
621  SCLogInfo("binding this thread %d to queue '%" PRIu32 "'", t->nfq_index, q->queue_num);
622 
623  /* pass the thread memory as a void ptr so the
624  * callback function has access to it. */
625  q->qh = nfq_create_queue(q->h, q->queue_num, &NFQCallBack, (void *)t);
626  if (q->qh == NULL) {
627  SCLogError(SC_ERR_NFQ_CREATE_QUEUE, "nfq_create_queue failed");
628  return TM_ECODE_FAILED;
629  }
630 
631  SCLogDebug("setting copy_packet mode");
632 
633  /* 05DC = 1500 */
634  //if (nfq_set_mode(nfq_t->qh, NFQNL_COPY_PACKET, 0x05DC) < 0) {
635  if (nfq_set_mode(q->qh, NFQNL_COPY_PACKET, 0xFFFF) < 0) {
636  SCLogError(SC_ERR_NFQ_SET_MODE, "can't set packet_copy mode");
637  return TM_ECODE_FAILED;
638  }
639 
640 #ifdef HAVE_NFQ_MAXLEN
641  if (queue_maxlen > 0) {
642  SCLogInfo("setting queue length to %" PRId32 "", queue_maxlen);
643 
644  /* non-fatal if it fails */
645  if (nfq_set_queue_maxlen(q->qh, queue_maxlen) < 0) {
646  SCLogWarning(SC_ERR_NFQ_MAXLEN, "can't set queue maxlen: your kernel probably "
647  "doesn't support setting the queue length");
648  }
649  }
650 #endif /* HAVE_NFQ_MAXLEN */
651 
652  /* set netlink buffer size to a decent value */
653  nfnl_rcvbufsiz(nfq_nfnlh(q->h), queue_maxlen * 1500);
654  SCLogInfo("setting nfnl bufsize to %" PRId32 "", queue_maxlen * 1500);
655 
656  q->nh = nfq_nfnlh(q->h);
657  q->fd = nfnl_fd(q->nh);
658  NFQMutexInit(q);
659 
660  /* Set some netlink specific option on the socket to increase
661  performance */
662  opt = 1;
663 #ifdef NETLINK_BROADCAST_SEND_ERROR
664  if (setsockopt(q->fd, SOL_NETLINK,
665  NETLINK_BROADCAST_SEND_ERROR, &opt, sizeof(int)) == -1) {
667  "can't set netlink broadcast error: %s",
668  strerror(errno));
669  }
670 #endif
671  /* Don't send error about no buffer space available but drop the
672  packets instead */
673 #ifdef NETLINK_NO_ENOBUFS
674  if (setsockopt(q->fd, SOL_NETLINK,
675  NETLINK_NO_ENOBUFS, &opt, sizeof(int)) == -1) {
677  "can't set netlink enobufs: %s",
678  strerror(errno));
679  }
680 #endif
681 
682 #ifdef HAVE_NFQ_SET_QUEUE_FLAGS
683  if (nfq_config.flags & NFQ_FLAG_FAIL_OPEN) {
684  uint32_t flags = NFQA_CFG_F_FAIL_OPEN;
685  uint32_t mask = NFQA_CFG_F_FAIL_OPEN;
686  int r = nfq_set_queue_flags(q->qh, mask, flags);
687 
688  if (r == -1) {
689  SCLogWarning(SC_ERR_NFQ_SET_MODE, "can't set fail-open mode: %s",
690  strerror(errno));
691  } else {
692  SCLogInfo("fail-open mode should be set on queue");
693  }
694  }
695 #endif
696 
697 #ifdef HAVE_NFQ_SET_VERDICT_BATCH
698  if (runmode_workers) {
699  q->verdict_cache.maxlen = nfq_config.batchcount;
700  } else if (nfq_config.batchcount) {
701  SCLogError(SC_ERR_INVALID_ARGUMENT, "nfq.batchcount is only valid in workers runmode.");
702  }
703 #endif
704 
705  /* set a timeout to the socket so we can check for a signal
706  * in case we don't get packets for a longer period. */
707  tv.tv_sec = 1;
708  tv.tv_usec = 0;
709 
710  if(setsockopt(q->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
711  SCLogWarning(SC_ERR_NFQ_SETSOCKOPT, "can't set socket timeout: %s", strerror(errno));
712  }
713 
714  SCLogDebug("nfq_q->h %p, nfq_q->nh %p, nfq_q->qh %p, nfq_q->fd %" PRId32 "",
715  q->h, q->nh, q->qh, q->fd);
716 
717  return TM_ECODE_OK;
718 }
719 
720 TmEcode ReceiveNFQThreadInit(ThreadVars *tv, const void *initdata, void **data)
721 {
722  SCMutexLock(&nfq_init_lock);
723 
724  sigset_t sigs;
725  sigfillset(&sigs);
726  pthread_sigmask(SIG_BLOCK, &sigs, NULL);
727 
728  NFQThreadVars *ntv = (NFQThreadVars *) initdata;
729  /* store the ThreadVars pointer in our NFQ thread context
730  * as we will need it in our callback function */
731  ntv->tv = tv;
732 
733  int r = NFQInitThread(ntv, (max_pending_packets * NFQ_BURST_FACTOR));
734  if (r != TM_ECODE_OK) {
735  SCLogError(SC_ERR_NFQ_THREAD_INIT, "nfq thread failed to initialize");
736 
737  SCMutexUnlock(&nfq_init_lock);
738  exit(EXIT_FAILURE);
739  }
740 
741 #define T_DATA_SIZE 70000
742  ntv->data = SCMalloc(T_DATA_SIZE);
743  if (ntv->data == NULL) {
744  SCMutexUnlock(&nfq_init_lock);
745  return TM_ECODE_FAILED;
746  }
747  ntv->datalen = T_DATA_SIZE;
748 #undef T_DATA_SIZE
749 
750  *data = (void *)ntv;
751 
752  SCMutexUnlock(&nfq_init_lock);
753  return TM_ECODE_OK;
754 }
755 
756 static void NFQDestroyQueue(NFQQueueVars *nq)
757 {
758  if (unlikely(nq == NULL)) {
759  return;
760  }
761 
762  SCLogDebug("starting... will close queuenum %" PRIu32 "", nq->queue_num);
763  NFQMutexLock(nq);
764  if (nq->qh != NULL) {
765  nfq_destroy_queue(nq->qh);
766  nq->qh = NULL;
767  nfq_close(nq->h);
768  nq->h = NULL;
769  }
770  NFQMutexUnlock(nq);
771 }
772 
774 {
775  NFQThreadVars *ntv = (NFQThreadVars *)data;
776  NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index);
777 
778  if (ntv->data != NULL) {
779  SCFree(ntv->data);
780  ntv->data = NULL;
781  }
782  ntv->datalen = 0;
783 
784  NFQDestroyQueue(nq);
785 
786  return TM_ECODE_OK;
787 }
788 
789 TmEcode VerdictNFQThreadInit(ThreadVars *tv, const void *initdata, void **data)
790 {
791  NFQThreadVars *ntv = (NFQThreadVars *) initdata;
792 
793  CaptureStatsSetup(tv, &ntv->stats);
794 
795  *data = (void *)ntv;
796  return TM_ECODE_OK;
797 }
798 
800 {
801  NFQThreadVars *ntv = (NFQThreadVars *)data;
802  NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index);
803 
804  NFQDestroyQueue(nq);
805 
806  return TM_ECODE_OK;
807 }
808 
809 /**
810  * \brief Add a single Netfilter queue
811  *
812  * \param string with the queue number
813  *
814  * \retval 0 on success.
815  * \retval -1 on failure.
816  */
817 int NFQRegisterQueue(const uint16_t number)
818 {
819  NFQThreadVars *ntv = NULL;
820  NFQQueueVars *nq = NULL;
821  char queue[10] = { 0 };
822  static bool many_queues_warned = false;
823  uint16_t num_cpus = UtilCpuGetNumProcessorsOnline();
824 
825  if (g_nfq_t == NULL || g_nfq_q == NULL) {
826  SCLogError(SC_ERR_INVALID_ARGUMENT, "NFQ context is not initialized");
827  return -1;
828  }
829 
830  SCMutexLock(&nfq_init_lock);
831  if (!many_queues_warned && (receive_queue_num >= num_cpus)) {
833  "using more Netfilter queues than %hu available CPU core(s) "
834  "may degrade performance",
835  num_cpus);
836  many_queues_warned = true;
837  }
838  if (receive_queue_num >= NFQ_MAX_QUEUE) {
840  "can not register more than %d Netfilter queues",
841  NFQ_MAX_QUEUE);
842  SCMutexUnlock(&nfq_init_lock);
843  return -1;
844  }
845 
846  ntv = &g_nfq_t[receive_queue_num];
847  ntv->nfq_index = receive_queue_num;
848 
849  nq = &g_nfq_q[receive_queue_num];
850  memset(nq, 0, sizeof(*nq));
851  nq->queue_num = number;
852  receive_queue_num++;
853  SCMutexUnlock(&nfq_init_lock);
854  snprintf(queue, sizeof(queue) - 1, "NFQ#%hu", number);
855  LiveRegisterDevice(queue);
856 
857  ntv->livedev = LiveGetDevice(queue);
858 
859  if (ntv->livedev == NULL) {
860  SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device");
861  return -1;
862  }
863 
864  SCLogDebug("Queue %d registered.", number);
865  return 0;
866 }
867 
868 /**
869  * \brief Parses and adds Netfilter queue(s).
870  *
871  * \param string with the queue number or range
872  *
873  * \retval 0 on success.
874  * \retval -1 on failure.
875  */
876 int NFQParseAndRegisterQueues(const char *queues)
877 {
878  uint16_t queue_start = 0;
879  uint16_t queue_end = 0;
880  uint16_t num_queues = 1; // if argument is correct, at least one queue will be created
881 
882  // Either "id" or "start:end" format (e.g., "12" or "0:5")
883  int count = sscanf(queues, "%hu:%hu", &queue_start, &queue_end);
884 
885  if (count < 1) {
886  SCLogError(SC_ERR_INVALID_ARGUMENT, "specified queue(s) argument '%s' is not "
887  "valid (allowed queue numbers are 0-65535)", queues);
888  return -1;
889  }
890 
891  // Do we have a range?
892  if (count == 2) {
893  // Sanity check
894  if (queue_start > queue_end) {
895  SCLogError(SC_ERR_INVALID_ARGUMENT, "start queue's number %d is greater than "
896  "ending number %d", queue_start, queue_end);
897  return -1;
898  }
899 
900  num_queues = queue_end - queue_start + 1; // +1 due to inclusive range
901  }
902 
903  // We do realloc() to preserve previously registered queues
904  void *ptmp = SCRealloc(g_nfq_t, (receive_queue_num + num_queues) * sizeof(NFQThreadVars));
905  if (ptmp == NULL) {
906  SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate NFQThreadVars");
908  exit(EXIT_FAILURE);
909  }
910 
911  g_nfq_t = (NFQThreadVars *)ptmp;
912 
913  ptmp = SCRealloc(g_nfq_q, (receive_queue_num + num_queues) * sizeof(NFQQueueVars));
914  if (ptmp == NULL) {
915  SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate NFQQueueVars");
917  exit(EXIT_FAILURE);
918  }
919 
920  g_nfq_q = (NFQQueueVars *)ptmp;
921 
922  do {
923  if (NFQRegisterQueue(queue_start) != 0) {
924  return -1;
925  }
926  } while (++queue_start <= queue_end);
927 
928  return 0;
929 }
930 
931 /**
932  * \brief Get a pointer to the NFQ queue at index
933  *
934  * \param number idx of the queue in our array
935  *
936  * \retval ptr pointer to the NFQThreadVars at index
937  * \retval NULL on error
938  */
939 void *NFQGetQueue(int number)
940 {
941  if (unlikely(number < 0 || number >= receive_queue_num || g_nfq_q == NULL))
942  return NULL;
943 
944  return (void *)&g_nfq_q[number];
945 }
946 
947 /**
948  * \brief Get a pointer to the NFQ thread at index
949  *
950  * This function is temporary used as configuration parser.
951  *
952  * \param number idx of the queue in our array
953  *
954  * \retval ptr pointer to the NFQThreadVars at index
955  * \retval NULL on error
956  */
957 void *NFQGetThread(int number)
958 {
959  if (unlikely(number < 0 || number >= receive_queue_num || g_nfq_t == NULL))
960  return NULL;
961 
962  return (void *)&g_nfq_t[number];
963 }
964 
965 /**
966  * \brief NFQ function to get a packet from the kernel
967  *
968  * \note separate functions for Linux and Win32 for readability.
969  */
970 static void NFQRecvPkt(NFQQueueVars *t, NFQThreadVars *tv)
971 {
972  int ret;
973  int flag = NFQVerdictCacheLen(t) ? MSG_DONTWAIT : 0;
974 
975  int rv = recv(t->fd, tv->data, tv->datalen, flag);
976  if (rv < 0) {
977  if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
978  /* no error on timeout */
979  if (flag)
980  NFQVerdictCacheFlush(t);
981 
982  /* handle timeout */
983  TmThreadsCaptureHandleTimeout(tv->tv, tv->slot, NULL);
984  } else {
985 #ifdef COUNTERS
986  NFQMutexLock(t);
987  t->errs++;
988  NFQMutexUnlock(t);
989 #endif /* COUNTERS */
990  }
991  } else if(rv == 0) {
992  SCLogWarning(SC_ERR_NFQ_RECV, "recv got returncode 0");
993  } else {
994 #ifdef DBG_PERF
995  if (rv > t->dbg_maxreadsize)
996  t->dbg_maxreadsize = rv;
997 #endif /* DBG_PERF */
998 
999  NFQMutexLock(t);
1000  if (t->qh != NULL) {
1001  ret = nfq_handle_packet(t->h, tv->data, rv);
1002  } else {
1003  SCLogWarning(SC_ERR_NFQ_HANDLE_PKT, "NFQ handle has been destroyed");
1004  ret = -1;
1005  }
1006  NFQMutexUnlock(t);
1007  if (ret != 0) {
1008  SCLogDebug("nfq_handle_packet error %"PRId32, ret);
1009  }
1010  }
1011 }
1012 
1013 /**
1014  * \brief Main NFQ reading Loop function
1015  */
1017 {
1018  SCEnter();
1019  NFQThreadVars *ntv = (NFQThreadVars *)data;
1020  NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index);
1021 
1022  ntv->slot = ((TmSlot *) slot)->slot_next;
1023 
1024  while(1) {
1025  if (unlikely(suricata_ctl_flags != 0)) {
1026  NFQDestroyQueue(nq);
1027  break;
1028  }
1029  NFQRecvPkt(nq, ntv);
1030 
1032  }
1034 }
1035 
1036 /**
1037  * \brief NFQ receive module stats printing function
1038  */
1040 {
1041  NFQThreadVars *ntv = (NFQThreadVars *)data;
1042  NFQQueueVars *nq = NFQGetQueue(ntv->nfq_index);
1043 #ifdef COUNTERS
1044  SCLogNotice("(%s) Treated: Pkts %" PRIu32 ", Bytes %" PRIu64 ", Errors %" PRIu32 "",
1045  tv->name, nq->pkts, nq->bytes, nq->errs);
1046  SCLogNotice("(%s) Verdict: Accepted %"PRIu32", Dropped %"PRIu32", Replaced %"PRIu32,
1047  tv->name, nq->accepted, nq->dropped, nq->replaced);
1048 #endif
1049 }
1050 
1051 static inline uint32_t GetVerdict(const Packet *p)
1052 {
1053  uint32_t verdict = NF_ACCEPT;
1054 
1055  if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
1056  verdict = NF_DROP;
1057  } else {
1058  switch (nfq_config.mode) {
1059  default:
1060  case NFQ_ACCEPT_MODE:
1061  verdict = NF_ACCEPT;
1062  break;
1063  case NFQ_REPEAT_MODE:
1064  verdict = NF_REPEAT;
1065  break;
1066  case NFQ_ROUTE_MODE:
1067  verdict = ((uint32_t) NF_QUEUE) | nfq_config.next_queue;
1068  break;
1069  }
1070  }
1071  return verdict;
1072 }
1073 
1074 #ifdef COUNTERS
1075 static inline void UpdateCounters(NFQQueueVars *t, const Packet *p)
1076 {
1077  if (PACKET_TEST_ACTION(p, ACTION_DROP)) {
1078  t->dropped++;
1079  } else {
1080  if (p->flags & PKT_STREAM_MODIFIED) {
1081  t->replaced++;
1082  }
1083 
1084  t->accepted++;
1085  }
1086 }
1087 #endif /* COUNTERS */
1088 
1089 /**
1090  * \brief NFQ verdict function
1091  */
1093 {
1094  int iter = 0;
1095  /* we could also have a direct pointer but we need to have a ref counf in this case */
1096  NFQQueueVars *t = g_nfq_q + p->nfq_v.nfq_index;
1097 
1098  p->nfq_v.verdicted = 1;
1099 
1100  /* can't verdict a "fake" packet */
1101  if (PKT_IS_PSEUDOPKT(p)) {
1102  return TM_ECODE_OK;
1103  }
1104 
1105  //printf("%p verdicting on queue %" PRIu32 "\n", t, t->queue_num);
1106  NFQMutexLock(t);
1107 
1108  if (t->qh == NULL) {
1109  /* Somebody has started a clean-up, we leave */
1110  NFQMutexUnlock(t);
1111  return TM_ECODE_OK;
1112  }
1113 
1114  uint32_t verdict = GetVerdict(p);
1115 #ifdef COUNTERS
1116  UpdateCounters(t, p);
1117 #endif /* COUNTERS */
1118 
1119  int ret = NFQVerdictCacheAdd(t, p, verdict);
1120  if (ret == 0) {
1121  NFQMutexUnlock(t);
1122  return TM_ECODE_OK;
1123  }
1124 
1125  do {
1126  switch (nfq_config.mode) {
1127  default:
1128  case NFQ_ACCEPT_MODE:
1129  case NFQ_ROUTE_MODE:
1130  if (p->flags & PKT_MARK_MODIFIED) {
1131 #ifdef HAVE_NFQ_SET_VERDICT2
1132  if (p->flags & PKT_STREAM_MODIFIED) {
1133  ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
1134  p->nfq_v.mark,
1135  GET_PKT_LEN(p), GET_PKT_DATA(p));
1136  } else {
1137  ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
1138  p->nfq_v.mark,
1139  0, NULL);
1140  }
1141 #else /* fall back to old function */
1142  if (p->flags & PKT_STREAM_MODIFIED) {
1143  ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
1144  htonl(p->nfq_v.mark),
1145  GET_PKT_LEN(p), GET_PKT_DATA(p));
1146  } else {
1147  ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
1148  htonl(p->nfq_v.mark),
1149  0, NULL);
1150  }
1151 #endif /* HAVE_NFQ_SET_VERDICT2 */
1152  } else {
1153  if (p->flags & PKT_STREAM_MODIFIED) {
1154  ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict,
1155  GET_PKT_LEN(p), GET_PKT_DATA(p));
1156  } else {
1157  ret = nfq_set_verdict(t->qh, p->nfq_v.id, verdict, 0, NULL);
1158  }
1159 
1160  }
1161  break;
1162  case NFQ_REPEAT_MODE:
1163 #ifdef HAVE_NFQ_SET_VERDICT2
1164  if (p->flags & PKT_STREAM_MODIFIED) {
1165  ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
1166  (nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask),
1167  GET_PKT_LEN(p), GET_PKT_DATA(p));
1168  } else {
1169  ret = nfq_set_verdict2(t->qh, p->nfq_v.id, verdict,
1170  (nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask),
1171  0, NULL);
1172  }
1173 #else /* fall back to old function */
1174  if (p->flags & PKT_STREAM_MODIFIED) {
1175  ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
1176  htonl((nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask)),
1177  GET_PKT_LEN(p), GET_PKT_DATA(p));
1178  } else {
1179  ret = nfq_set_verdict_mark(t->qh, p->nfq_v.id, verdict,
1180  htonl((nfq_config.mark & nfq_config.mask) | (p->nfq_v.mark & ~nfq_config.mask)),
1181  0, NULL);
1182  }
1183 #endif /* HAVE_NFQ_SET_VERDICT2 */
1184  break;
1185  }
1186  } while ((ret < 0) && (iter++ < NFQ_VERDICT_RETRY_TIME));
1187 
1188  NFQMutexUnlock(t);
1189 
1190  if (ret < 0) {
1192  "nfq_set_verdict of %p failed %" PRId32 ": %s",
1193  p, ret, strerror(errno));
1194  return TM_ECODE_FAILED;
1195  }
1196  return TM_ECODE_OK;
1197 }
1198 
1199 /**
1200  * \brief NFQ verdict module packet entry function
1201  */
1203 {
1204  NFQThreadVars *ntv = (NFQThreadVars *)data;
1205  /* update counters */
1206  CaptureStatsUpdate(tv, &ntv->stats, p);
1207 
1208  /* if this is a tunnel packet we check if we are ready to verdict
1209  * already. */
1210  if (IS_TUNNEL_PKT(p)) {
1211  SCLogDebug("tunnel pkt: %p/%p %s", p, p->root, p->root ? "upper layer" : "root");
1212  bool verdict = VerdictTunnelPacket(p);
1213  /* don't verdict if we are not ready */
1214  if (verdict == true) {
1215  int ret = NFQSetVerdict(p->root ? p->root : p);
1216  if (ret != TM_ECODE_OK) {
1217  return ret;
1218  }
1219  }
1220  } else {
1221  /* no tunnel, verdict normally */
1222  int ret = NFQSetVerdict(p);
1223  if (ret != TM_ECODE_OK) {
1224  return ret;
1225  }
1226  }
1227  return TM_ECODE_OK;
1228 }
1229 
1230 /**
1231  * \brief Decode a packet coming from NFQ
1232  */
1234 {
1235 
1236  IPV4Hdr *ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
1237  IPV6Hdr *ip6h = (IPV6Hdr *)GET_PKT_DATA(p);
1238  DecodeThreadVars *dtv = (DecodeThreadVars *)data;
1239 
1240  /* XXX HACK: flow timeout can call us for injected pseudo packets
1241  * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */
1242  if (PKT_IS_PSEUDOPKT(p))
1243  return TM_ECODE_OK;
1244 
1245  DecodeUpdatePacketCounters(tv, dtv, p);
1246 
1247  if (IPV4_GET_RAW_VER(ip4h) == 4) {
1248  if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) {
1249  return TM_ECODE_FAILED;
1250  }
1251  SCLogDebug("IPv4 packet");
1252  DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1253  } else if (IPV6_GET_RAW_VER(ip6h) == 6) {
1254  if (unlikely(GET_PKT_LEN(p) > USHRT_MAX)) {
1255  return TM_ECODE_FAILED;
1256  }
1257  SCLogDebug("IPv6 packet");
1258  DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1259  } else {
1260  SCLogDebug("packet unsupported by NFQ, first byte: %02x", *GET_PKT_DATA(p));
1261  }
1262 
1263  PacketDecodeFinalize(tv, dtv, p);
1264 
1265  return TM_ECODE_OK;
1266 }
1267 
1268 /**
1269  * \brief Initialize the NFQ Decode threadvars
1270  */
1271 TmEcode DecodeNFQThreadInit(ThreadVars *tv, const void *initdata, void **data)
1272 {
1274  if (dtv == NULL)
1276 
1277  DecodeRegisterPerfCounters(dtv, tv);
1278 
1279  *data = (void *)dtv;
1280  return TM_ECODE_OK;
1281 }
1282 
1284 {
1285  if (data != NULL)
1286  DecodeThreadVarsFree(tv, data);
1288 }
1289 
1290 /**
1291  * \brief Clean global contexts. Must be called on exit.
1292  */
1294 {
1295  if (g_nfq_q != NULL) {
1296  SCFree(g_nfq_q);
1297  g_nfq_q = NULL;
1298  }
1299 
1300  if (g_nfq_t != NULL) {
1301  SCFree(g_nfq_t);
1302  g_nfq_t = NULL;
1303  }
1304 }
1305 #endif /* NFQ */
#define MAX_ALREADY_TREATED
Definition: source-nfq.c:103
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:1039
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
Definition: decode.c:614
#define SCLogDebug(...)
Definition: util-debug.h:335
void CaptureStatsUpdate(ThreadVars *tv, CaptureStats *s, const Packet *p)
Definition: decode.c:703
#define NFQ_VERDICT_RETRY_TIME
Definition: source-nfq.c:104
uint32_t verdict
Definition: source-nfq.h:78
int(* BypassPacketsFlow)(struct Packet_ *)
Definition: decode.h:487
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:124
TmEcode ReceiveNFQLoop(ThreadVars *tv, void *data, void *slot)
Main NFQ reading Loop function.
Definition: source-nfq.c:1016
uint32_t packet_id
Definition: source-nfq.h:77
void NFQContextsClean()
Clean global contexts. Must be called on exit.
Definition: source-nfq.c:1293
uint8_t flags
Definition: tm-modules.h:70
#define PACKET_TEST_ACTION(p, a)
Definition: decode.h:857
TmEcode DecodeNFQ(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
Decode a packet coming from NFQ.
Definition: source-nfq.c:1233
#define SET_PKT_LEN(p, len)
Definition: decode.h:229
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
Definition: decode.c:115
TmEcode DecodeNFQThreadInit(ThreadVars *, const void *, void **)
Initialize the NFQ Decode threadvars.
Definition: source-nfq.c:1271
#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:111
uint8_t batchcount
Definition: source-nfq.c:166
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
Definition: decode.c:474
TmSlot * slot
Definition: source-nfq.c:118
#define NFQMutexUnlock(nq)
Definition: source-nfq.c:397
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:881
uint32_t next_queue
Definition: source-nfq.c:164
TmEcode DecodeNFQThreadDeinit(ThreadVars *tv, void *data)
Definition: source-nfq.c:1283
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:799
uint32_t bypass_mark
Definition: source-nfq.c:162
#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:209
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:177
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:484
#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:162
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:876
char * RunmodeGetActive(void)
Definition: runmodes.c:187
uint32_t mark
Definition: source-nfq.c:160
uint64_t bytes
Definition: source-nfq.h:71
TmEcode NFQSetVerdict(Packet *p)
NFQ verdict function.
Definition: source-nfq.c:1092
uint32_t dropped
Definition: source-nfq.h:74
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1135
#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:957
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:57
TmEcode ReceiveNFQThreadInit(ThreadVars *, const void *, void **)
Definition: source-nfq.c:720
uint32_t replaced
Definition: source-nfq.h:75
NFQMode_
Definition: source-nfq.c:150
#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:817
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:1095
void(* tmqh_out)(struct ThreadVars_ *, struct Packet_ *)
Definition: threadvars.h:80
void TmModuleVerdictNFQRegister(void)
Definition: source-nfq.c:186
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:1120
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:1202
uint32_t ifi
Definition: source-nfq.h:46
#define SCMutexInit(mut, mutattrs)
NFQMode mode
Definition: source-nfq.c:159
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:236
#define SCNtohl(x)
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:48
#define PACKET_UPDATE_ACTION(p, a)
Definition: decode.h:862
TmEcode VerdictNFQThreadInit(ThreadVars *, const void *, void **)
Definition: source-nfq.c:789
#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:238
int PacketSetData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Set data for Packet and set length when zeo copy is used.
Definition: decode.c:653
const char * name
Definition: tm-modules.h:44
#define NFQ_BURST_FACTOR
Definition: source-nfq.c:108
#define SCMalloc(a)
Definition: util-mem.h:222
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len, PacketQueue *pq)
Definition: decode-ipv6.c:585
SCMutex tunnel_mutex
Definition: decode.h:587
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
struct NFQThreadVars_ NFQThreadVars
uint32_t flags
Definition: source-nfq.c:165
#define SCFree(a)
Definition: util-mem.h:322
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len, PacketQueue *pq)
Definition: decode-ipv4.c:532
#define NFQMutexLock(nq)
Definition: source-nfq.c:392
#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:120
TmEcode ReceiveNFQThreadDeinit(ThreadVars *, void *)
Definition: source-nfq.c:773
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 FatalError(x,...)
Definition: util-debug.h:539
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:137
uint16_t nfq_index
Definition: source-nfq.c:116
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:163
#define NFQ_FLAG_FAIL_OPEN
Definition: source-nfq.c:156
uint32_t mask
Definition: source-nfq.c:161
void TmModuleReceiveNFQRegister(void)
Definition: source-nfq.c:171
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:225
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
Definition: decode.c:580
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:1132
struct NFQCnf_ NFQCnf
void * NFQGetQueue(int number)
Get a pointer to the NFQ queue at index.
Definition: source-nfq.c:939
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:259
void CaptureStatsSetup(ThreadVars *tv, CaptureStats *s)
Definition: decode.c:716
NFQPacketVars nfq_v
Definition: decode.h:459
NFQCnf nfq_config
Definition: source-nfq.c:169
Per thread variable structure.
Definition: threadvars.h:57
struct timeval ts
Definition: decode.h:451
#define GET_PKT_LEN(p)
Definition: decode.h:224
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:1096
#define ACTION_DROP
uint32_t flags
Definition: decode.h:443
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
Definition: decode.c:633
uint32_t pkts
Definition: source-nfq.h:70
struct NFQQueueVars_::@135 verdict_cache
void TmModuleDecodeNFQRegister(void)
Definition: source-nfq.c:195
ThreadVars * tv
Definition: source-nfq.c:117
CaptureStats stats
Definition: source-nfq.c:125
struct Packet_ * root
Definition: decode.h:577