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