Go to the documentation of this file.
93 FatalError(
"Error creating thread %s: you do not "
94 "have support for nfqueue enabled please recompile with "
103 #define MAX_ALREADY_TREATED 5
104 #define NFQ_VERDICT_RETRY_COUNT 3
105 static int already_seen_warning;
106 static int runmode_workers;
108 #define NFQ_BURST_FACTOR 4
111 #define SOL_NETLINK 270
130 static uint16_t receive_queue_num = 0;
136 static void ReceiveNFQThreadExitStats(
ThreadVars *,
void *);
146 static TmEcode NFQSetVerdict(
Packet *p,
const uint32_t mark_value,
const bool mark_modified);
147 static void NFQReleasePacket(
Packet *p);
155 #define NFQ_FLAG_FAIL_OPEN (1 << 0)
173 memset(&nfq_g, 0,
sizeof(nfq_g));
211 const char *nfq_mode = NULL;
218 if ((
SCConfGet(
"nfq.mode", &nfq_mode)) == 0) {
221 if (!strcmp(
"accept", nfq_mode)) {
223 }
else if (!strcmp(
"repeat", nfq_mode)) {
225 }
else if (!strcmp(
"route", nfq_mode)) {
234 #ifdef HAVE_NFQ_SET_QUEUE_FLAGS
235 SCLogInfo(
"Enabling fail-open on queue");
238 SCLogError(
"nfq.%s set but NFQ library has no support for it.",
"fail-open");
263 #ifdef HAVE_NFQ_SET_VERDICT_BATCH
271 SCLogWarning(
"nfq.%s set but NFQ library has no support for it.",
"batchcount");
278 SCLogInfo(
"NFQ running in standard ACCEPT/DROP mode");
281 SCLogInfo(
"NFQ running in REPEAT mode with mark %"PRIu32
"/%"PRIu32,
285 SCLogInfo(
"NFQ running in route mode with next queue %"PRIu32,
295 #ifdef HAVE_NFQ_SET_VERDICT_BATCH
304 #ifdef HAVE_NFQ_SET_VERDICT_BATCH
310 ret = nfq_set_verdict_batch2(t->
qh,
315 ret = nfq_set_verdict_batch(t->
qh,
321 SCLogWarning(
"nfq_set_verdict_batch failed: %s", strerror(errno));
330 const uint32_t mark_value,
const bool mark_modified)
332 #ifdef HAVE_NFQ_SET_VERDICT_BATCH
361 NFQVerdictCacheFlush(t);
367 if (NFQVerdictCacheLen(t) > 0)
368 NFQVerdictCacheFlush(t);
377 if (active_runmode && !strcmp(
"workers", active_runmode)) {
380 SCLogDebug(
"NFQ running in 'workers' runmode, will not use mutex.");
388 #define NFQMutexLock(nq) do { \
389 if ((nq)->use_mutex) \
390 SCMutexLock(&(nq)->mutex_qh); \
393 #define NFQMutexUnlock(nq) do { \
394 if ((nq)->use_mutex) \
395 SCMutexUnlock(&(nq)->mutex_qh); \
405 static int NFQSetupPkt (
Packet *p,
struct nfq_q_handle *qh,
void *data)
407 struct nfq_data *tb = (
struct nfq_data *)data;
410 struct nfqnl_msg_packet_hdr *ph;
416 ph = nfq_get_msg_packet_hdr(tb);
428 SCLogInfo(
"Packet seems already treated by suricata");
429 already_seen_warning++;
431 ret = nfq_set_verdict(qh, p->
nfq_v.
id, NF_ACCEPT, 0, NULL);
435 "nfq_set_verdict of %p failed %" PRId32
": %s", p, ret, strerror(errno));
448 #ifdef NFQ_GET_PAYLOAD_SIGNED
449 ret = nfq_get_payload(tb, &pktdata);
451 ret = nfq_get_payload(tb, (
unsigned char **) &pktdata);
463 }
else if (runmode_workers) {
468 }
else if (ret == -1) {
475 ret = nfq_get_timestamp(tb, &
tv);
476 if (ret != 0 ||
tv.tv_sec == 0) {
477 memset(&
tv, 0,
sizeof(
tv));
478 gettimeofday(&
tv, NULL);
486 static void NFQReleasePacket(
Packet *p)
488 if (PacketIsNotTunnel(p)) {
503 const uint32_t mark_value = root_p->
nfq_v.
mark;
508 NFQSetVerdict(p, mark_value, mark_modified);
520 static int NFQBypassCallback(
Packet *p)
522 if (PacketIsTunnel(p)) {
546 static int NFQCallBack(
struct nfq_q_handle *qh,
struct nfgenmsg *nfmsg,
547 struct nfq_data *nfa,
void *data)
566 ret = NFQSetupPkt(p, qh, (
void *)nfa);
616 SCLogDebug(
"unbinding existing nf_queue handler for AF_INET (if any)");
617 if (nfq_unbind_pf(q->
h, AF_INET) < 0) {
618 FatalError(
"nfq_unbind_pf() for AF_INET failed: %s", strerror(errno));
620 if (nfq_unbind_pf(q->
h, AF_INET6) < 0) {
621 FatalError(
"nfq_unbind_pf() for AF_INET6 failed");
625 SCLogDebug(
"binding nfnetlink_queue as nf_queue handler for AF_INET and AF_INET6");
627 if (nfq_bind_pf(q->
h, AF_INET) < 0) {
628 FatalError(
"nfq_bind_pf() for AF_INET failed");
630 if (nfq_bind_pf(q->
h, AF_INET6) < 0) {
631 FatalError(
"nfq_bind_pf() for AF_INET6 failed");
639 q->
qh = nfq_create_queue(q->
h, q->
queue_num, &NFQCallBack, (
void *)t);
649 if (nfq_set_mode(q->
qh, NFQNL_COPY_PACKET, 0xFFFF) < 0) {
654 #ifdef HAVE_NFQ_MAXLEN
655 if (queue_maxlen > 0) {
656 SCLogInfo(
"setting queue length to %" PRId32
"", queue_maxlen);
659 if (nfq_set_queue_maxlen(q->
qh, queue_maxlen) < 0) {
660 SCLogWarning(
"can't set queue maxlen: your kernel probably "
661 "doesn't support setting the queue length");
667 nfnl_rcvbufsiz(nfq_nfnlh(q->
h), queue_maxlen * 1500);
668 SCLogInfo(
"setting nfnl bufsize to %" PRId32
"", queue_maxlen * 1500);
670 q->
nh = nfq_nfnlh(q->
h);
671 q->
fd = nfnl_fd(q->
nh);
677 #ifdef NETLINK_BROADCAST_SEND_ERROR
679 NETLINK_BROADCAST_SEND_ERROR, &opt,
sizeof(
int)) == -1) {
680 SCLogWarning(
"can't set netlink broadcast error: %s", strerror(errno));
685 #ifdef NETLINK_NO_ENOBUFS
687 NETLINK_NO_ENOBUFS, &opt,
sizeof(
int)) == -1) {
688 SCLogWarning(
"can't set netlink enobufs: %s", strerror(errno));
692 #ifdef HAVE_NFQ_SET_QUEUE_FLAGS
694 uint32_t
flags = NFQA_CFG_F_FAIL_OPEN;
695 uint32_t mask = NFQA_CFG_F_FAIL_OPEN;
696 int r = nfq_set_queue_flags(q->
qh, mask,
flags);
699 SCLogWarning(
"can't set fail-open mode: %s", strerror(errno));
701 SCLogInfo(
"fail-open mode should be set on queue");
706 #ifdef HAVE_NFQ_SET_VERDICT_BATCH
707 if (runmode_workers) {
710 SCLogError(
"nfq.batchcount is only valid in workers runmode.");
719 if(setsockopt(q->
fd, SOL_SOCKET, SO_RCVTIMEO, &
tv,
sizeof(
tv)) == -1) {
720 SCLogWarning(
"can't set socket timeout: %s", strerror(errno));
723 SCLogDebug(
"nfq_q->h %p, nfq_q->nh %p, nfq_q->qh %p, nfq_q->fd %" PRId32
"",
735 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
744 SCLogError(
"nfq thread failed to initialize");
750 #define T_DATA_SIZE 70000
752 if (ntv->
data == NULL) {
775 if (nq->
qh != NULL) {
776 nfq_destroy_queue(nq->
qh);
789 if (ntv->
data != NULL) {
829 char queue[10] = { 0 };
830 static bool many_queues_warned =
false;
833 if (g_nfq_t == NULL || g_nfq_q == NULL) {
839 if (!many_queues_warned && (receive_queue_num >= num_cpus)) {
840 SCLogWarning(
"using more Netfilter queues than %hu available CPU core(s) "
841 "may degrade performance",
843 many_queues_warned =
true;
851 ntv = &g_nfq_t[receive_queue_num];
854 nq = &g_nfq_q[receive_queue_num];
855 memset(nq, 0,
sizeof(*nq));
859 snprintf(queue,
sizeof(queue) - 1,
"NFQ#%hu", number);
883 uint16_t queue_start = 0;
884 uint16_t queue_end = 0;
885 uint16_t num_queues = 1;
888 int count = sscanf(queues,
"%hu:%hu", &queue_start, &queue_end);
891 SCLogError(
"specified queue(s) argument '%s' is not "
892 "valid (allowed queue numbers are 0-65535)",
900 if (queue_start > queue_end) {
901 SCLogError(
"start queue's number %d is greater than "
903 queue_start, queue_end);
907 num_queues = queue_end - queue_start + 1;
913 SCLogError(
"Unable to allocate NFQThreadVars");
922 SCLogError(
"Unable to allocate NFQQueueVars");
933 }
while (++queue_start <= queue_end);
948 if (
unlikely(number < 0 || number >= receive_queue_num || g_nfq_q == NULL))
951 return (
void *)&g_nfq_q[number];
966 if (
unlikely(number < 0 || number >= receive_queue_num || g_nfq_t == NULL))
969 return (
void *)&g_nfq_t[number];
978 int flag = NFQVerdictCacheLen(t) ? MSG_DONTWAIT : 0;
980 int rv = recv(t->
fd,
tv->data,
tv->datalen, flag);
982 if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
985 NFQVerdictCacheFlush(t);
988 TmThreadsCaptureHandleTimeout(
tv->tv, NULL);
1000 if (rv > t->dbg_maxreadsize)
1001 t->dbg_maxreadsize = rv;
1005 if (t->
qh != NULL) {
1006 ret = nfq_handle_packet(t->
h,
tv->data, rv);
1013 SCLogDebug(
"nfq_handle_packet error %"PRId32, ret);
1035 NFQDestroyQueue(nq);
1038 NFQRecvPkt(nq, ntv);
1048 void ReceiveNFQThreadExitStats(
ThreadVars *
tv,
void *data)
1053 SCLogNotice(
"(%s) Treated: Pkts %" PRIu32
", Bytes %" PRIu64
", Errors %" PRIu32
"",
1055 SCLogNotice(
"(%s) Verdict: Accepted %"PRIu32
", Dropped %"PRIu32
", Replaced %"PRIu32,
1060 static inline uint32_t GetVerdict(
const Packet *p)
1062 uint32_t verdict = NF_ACCEPT;
1070 verdict = NF_ACCEPT;
1073 verdict = NF_REPEAT;
1102 static TmEcode NFQSetVerdict(
Packet *p,
const uint32_t mark_value,
const bool mark_modified)
1116 if (t->
qh == NULL) {
1122 uint32_t verdict = GetVerdict(p);
1124 UpdateCounters(t, p);
1127 int ret = NFQVerdictCacheAdd(t, p, verdict, mark_value, mark_modified);
1138 if (mark_modified) {
1139 #ifdef HAVE_NFQ_SET_VERDICT2
1141 ret = nfq_set_verdict2(t->
qh, p->
nfq_v.
id, verdict, mark_value,
1144 ret = nfq_set_verdict2(t->
qh, p->
nfq_v.
id, verdict, mark_value, 0, NULL);
1148 ret = nfq_set_verdict_mark(t->
qh, p->
nfq_v.
id, verdict, htonl(mark_value),
1151 ret = nfq_set_verdict_mark(
1152 t->
qh, p->
nfq_v.
id, verdict, htonl(mark_value), 0, NULL);
1157 ret = nfq_set_verdict(t->
qh, p->
nfq_v.
id, verdict,
1160 ret = nfq_set_verdict(t->
qh, p->
nfq_v.
id, verdict, 0, NULL);
1165 #ifdef HAVE_NFQ_SET_VERDICT2
1167 ret = nfq_set_verdict2(t->
qh, p->
nfq_v.
id, verdict,
1171 ret = nfq_set_verdict2(t->
qh, p->
nfq_v.
id, verdict,
1177 ret = nfq_set_verdict_mark(t->
qh, p->
nfq_v.
id, verdict,
1182 ret = nfq_set_verdict_mark(t->
qh, p->
nfq_v.
id, verdict,
1195 SCLogWarning(
"nfq_set_verdict of %p failed %" PRId32
": %s", p, ret, strerror(errno));
1208 if (PacketIsTunnel(p)) {
1215 const bool do_verdict = VerdictTunnelPacketInternal(p);
1218 const uint32_t mark_value = root_p->
nfq_v.
mark;
1223 int ret = NFQSetVerdict(root_p, mark_value, mark_modified);
1288 *data = (
void *)
dtv;
1304 if (g_nfq_q != NULL) {
1309 if (g_nfq_t != NULL) {
bool PacketCheckAction(const Packet *p, const uint8_t a)
void * NFQGetThread(int number)
Get a pointer to the NFQ thread at index.
int LiveRegisterDevice(const char *dev)
Add a pcap device for monitoring and create structure.
#define IPV6_GET_RAW_VER(ip6h)
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
#define TM_FLAG_VERDICT_TM
struct NFQThreadVars_ NFQThreadVars
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
#define PKT_STREAM_MODIFIED
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
#define NFQ_FLAG_FAIL_OPEN
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
struct NFQQueueVars_::@148 verdict_cache
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
struct Packet_::@39 persistent
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
char * RunmodeGetActive(void)
void NFQInitConfig(bool quiet)
To initialize the NFQ global configuration data.
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
int(* BypassPacketsFlow)(struct Packet_ *)
#define NFQMutexUnlock(nq)
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
#define PKT_SET_SRC(p, src_val)
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
int NFQParseAndRegisterQueues(const char *queues)
Parses and adds Netfilter queue(s).
#define SET_PKT_LEN(p, len)
void TmModuleVerdictNFQRegister(void)
void * NFQGetQueue(int number)
Get a pointer to the NFQ queue at index.
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
#define SCMutexUnlock(mut)
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Per thread variable structure.
#define SCTIME_FROM_TIMEVAL(tv)
#define NFQ_VERDICT_RETRY_COUNT
TmEcode(* Func)(ThreadVars *, Packet *, void *)
#define SCLogWarning(...)
Macro used to log WARNING messages.
#define TM_FLAG_DECODE_TM
TmModule tmm_modules[TMM_SIZE]
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
#define IPV4_GET_RAW_VER(ip4h)
uint32_t max_pending_packets
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
#define SCMutexInit(mut, mutattrs)
#define TM_FLAG_RECEIVE_TM
#define SCRealloc(ptr, sz)
void(* ReleasePacket)(struct Packet_ *)
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
@ PKT_DROP_REASON_NFQ_ERROR
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
void TmModuleReceiveNFQRegister(void)
#define MAX_ALREADY_TREATED
void(* ThreadExitPrintStats)(ThreadVars *, void *)
#define PKT_REBUILT_FRAGMENT
#define SCLogError(...)
Macro used to log ERROR messages.
void DatalinkSetGlobalType(int datalink)
Structure to hold thread specific data for all decode modules.
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
int PacketSetData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Set data for Packet and set length when zero copy is used.
void PacketDrop(Packet *p, const uint8_t action, enum PacketDropReason r)
issue drop action
struct TmSlot_ * slot_next
void StatsSyncCountersIfSignalled(ThreadVars *tv)
uint16_t UtilCpuGetNumProcessorsOnline(void)
Get the number of cpus online in the system.
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
#define SCLogNotice(...)
Macro used to log NOTICE messages.
void NFQContextsClean(void)
Clean global contexts. Must be called on exit.
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...
void TmModuleDecodeNFQRegister(void)
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
volatile uint8_t suricata_ctl_flags
int NFQRegisterQueue(const uint16_t number)
Add a single Netfilter queue.