diff --git a/src/source-nfq.c b/src/source-nfq.c index 82cbf9ae58..33514efa35 100644 --- a/src/source-nfq.c +++ b/src/source-nfq.c @@ -1,10 +1,16 @@ /* Copyright (c) 2008 Victor Julien */ -/* TODO - * - test if Receive and Verdict if both are present +/** + * \file * + * \brief Netfilter's netfilter_queue support for reading packets from the + * kernel and setting verdicts back to it (inline mode). * + * Supported on Linux and Windows. * + * \todo test if Receive and Verdict if both are present + * + * \author Victor Julien */ #include "suricata-common.h" @@ -289,11 +295,12 @@ TmEcode NFQInitThread(NFQThreadVars *nfq_t, uint16_t queue_num, uint32_t queue_m SCLogDebug("nfq_t->h %p, nfq_t->nh %p, nfq_t->qh %p, nfq_t->fd %" PRId32 "", nfq_t->h, nfq_t->nh, nfq_t->qh, nfq_t->fd); #else /* OS_WIN32 */ - SCMutexInit(&nfq_t->mutex_qh, NULL); - nfq_t->ovr.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - nfq_t->fd = nfq_fd(nfq_t->h); + SCMutexInit(&nfq_t->mutex_qh, NULL); + nfq_t->ovr.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + nfq_t->fd = nfq_fd(nfq_t->h); SCLogDebug("nfq_t->h %p, nfq_t->qh %p, nfq_t->fd %p", nfq_t->h, nfq_t->qh, nfq_t->fd); #endif /* OS_WIN32 */ + return TM_ECODE_OK; } @@ -360,53 +367,85 @@ TmEcode VerdictNFQThreadDeinit(ThreadVars *tv, void *data) { return TM_ECODE_OK; } +/** + * \brief NFQ function to get a packet from the kernel + * + * \note separate functions for Linux and Win32 for readability. + */ +#ifndef OS_WIN32 void NFQRecvPkt(NFQThreadVars *t) { int rv, ret; char buf[70000]; -#ifdef OS_WIN32 - static int timeouted = 0; + /* XXX what happens on rv == 0? */ + rv = recv(t->fd, buf, sizeof(buf), 0); + + if (rv < 0) { + if (errno == EINTR || errno == EWOULDBLOCK + ) { + /* no error on timeout */ + } else { +#ifdef COUNTERS + t->errs++; +#endif /* COUNTERS */ + } + } else if(rv == 0) { + SCLogWarning(SC_ERR_NFQ_RECV, "recv got returncode 0"); + } else { +#ifdef DBG_PERF + if (rv > t->dbg_maxreadsize) + t->dbg_maxreadsize = rv; +#endif /* DBG_PERF */ + + //printf("NFQRecvPkt: t %p, rv = %" PRId32 "\n", t, rv); - if (timeouted) { - if (WaitForSingleObject(t->ovr.hEvent, 1000) == WAIT_TIMEOUT) { - rv = -1; - errno = EINTR; - goto process_rv; - } - timeouted = 0; - } + SCMutexLock(&t->mutex_qh); + ret = nfq_handle_packet(t->h, buf, rv); + SCMutexUnlock(&t->mutex_qh); + + if (ret != 0) { + SCLogWarning(SC_ERR_NFQ_HANDLE_PKT, "nfq_handle_packet error %" PRId32 "", ret); + } + } +} +#else /* WIN32 version of NFQRecvPkt */ +void NFQRecvPkt(NFQThreadVars *t) { + int rv, ret; + char buf[70000]; + static int timeouted = 0; + + if (timeouted) { + if (WaitForSingleObject(t->ovr.hEvent, 1000) == WAIT_TIMEOUT) { + rv = -1; + errno = EINTR; + goto process_rv; + } + timeouted = 0; + } read_packet_again: - if (!ReadFile(t->fd, buf, sizeof(buf), (DWORD*)&rv, &t->ovr)) { - if (GetLastError() != ERROR_IO_PENDING) { - rv = -1; - errno = EIO; - } else { - if (WaitForSingleObject(t->ovr.hEvent, 1000) == WAIT_TIMEOUT) { - rv = -1; - errno = EINTR; - timeouted = 1; - } else { - /* We needn't to call GetOverlappedResult() because it always fail with our error code ERROR_MORE_DATA. */ - goto read_packet_again; - } - } - } + if (!ReadFile(t->fd, buf, sizeof(buf), (DWORD*)&rv, &t->ovr)) { + if (GetLastError() != ERROR_IO_PENDING) { + rv = -1; + errno = EIO; + } else { + if (WaitForSingleObject(t->ovr.hEvent, 1000) == WAIT_TIMEOUT) { + rv = -1; + errno = EINTR; + timeouted = 1; + } else { + /* We needn't to call GetOverlappedResult() because it always + * fail with our error code ERROR_MORE_DATA. */ + goto read_packet_again; + } + } + } process_rv: -#else /* OS_WIN32 */ - /* XXX what happens on rv == 0? */ - rv = recv(t->fd, buf, sizeof(buf), 0); -#endif /* OS_WIN32 */ - if (rv < 0) { - if (errno == EINTR -#ifndef OS_WIN32 - || errno == EWOULDBLOCK -#endif - ) { + if (errno == EINTR) { /* no error on timeout */ } else { #ifdef COUNTERS @@ -432,7 +471,11 @@ process_rv: } } } +#endif /* OS_WIN32 */ +/** + * \brief NFQ receive module main entry function: receive a packet from NFQ + */ TmEcode ReceiveNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { NFQThreadVars *ntv = (NFQThreadVars *)data; @@ -451,6 +494,9 @@ TmEcode ReceiveNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { return TM_ECODE_OK; } +/** + * \brief NFQ receive module stats printing function + */ void ReceiveNFQThreadExitStats(ThreadVars *tv, void *data) { NFQThreadVars *ntv = (NFQThreadVars *)data; #ifdef COUNTERS @@ -459,6 +505,9 @@ void ReceiveNFQThreadExitStats(ThreadVars *tv, void *data) { #endif } +/** + * \brief NFQ verdict module stats printing function + */ void VerdictNFQThreadExitStats(ThreadVars *tv, void *data) { NFQThreadVars *ntv = (NFQThreadVars *)data; #ifdef COUNTERS @@ -467,6 +516,9 @@ void VerdictNFQThreadExitStats(ThreadVars *tv, void *data) { #endif } +/** + * \brief NFQ verdict function + */ void NFQSetVerdict(NFQThreadVars *t, Packet *p) { int ret; uint32_t verdict; @@ -495,6 +547,9 @@ void NFQSetVerdict(NFQThreadVars *t, Packet *p) { } } +/** + * \brief NFQ verdict module packet entry function + */ TmEcode VerdictNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { NFQThreadVars *ntv = (NFQThreadVars *)data; @@ -528,10 +583,8 @@ TmEcode VerdictNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { return TM_ECODE_OK; } -/* - * - * - * +/** + * \brief Decode a packet coming from NFQ */ TmEcode DecodeNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) { @@ -561,6 +614,9 @@ TmEcode DecodeNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) return TM_ECODE_OK; } +/** + * \brief Initialize the NFQ Decode threadvars + */ TmEcode DecodeNFQThreadInit(ThreadVars *tv, void *initdata, void **data) { DecodeThreadVars *dtv = NULL;