diff options
author | Ashlee Young <ashlee@wildernessvoice.com> | 2016-01-20 01:10:01 +0000 |
---|---|---|
committer | Ashlee Young <ashlee@wildernessvoice.com> | 2016-01-20 01:10:11 +0000 |
commit | 19d701ddf07d855128ded0cf2b573ce468e3bdd6 (patch) | |
tree | 0edcd3461ca903c76e431bb7c6348c42a0f12488 /framework/src/suricata/src/source-netmap.c | |
parent | fac6fbefbfad1cf837ddd88bc0d330559c8eb6f9 (diff) |
Removing Suricata and Audit from source repo, and updated build.sh to avoid building suricata. Will re-address this in C release via tar balls.
Change-Id: I3710076f8b7f3313cb3cb5260c4eb0a6834d4f6e
Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/suricata/src/source-netmap.c')
-rw-r--r-- | framework/src/suricata/src/source-netmap.c | 1098 |
1 files changed, 0 insertions, 1098 deletions
diff --git a/framework/src/suricata/src/source-netmap.c b/framework/src/suricata/src/source-netmap.c deleted file mode 100644 index 73930118..00000000 --- a/framework/src/suricata/src/source-netmap.c +++ /dev/null @@ -1,1098 +0,0 @@ -/* Copyright (C) 2011-2014 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** -* \defgroup netmap Netmap running mode -* -* @{ -*/ - -/** -* \file -* -* \author Aleksey Katargin <gureedo@gmail.com> -* -* Netmap socket acquisition support -* -*/ - -#include "suricata-common.h" -#include "config.h" -#include "suricata.h" -#include "decode.h" -#include "packet-queue.h" -#include "threads.h" -#include "threadvars.h" -#include "tm-queuehandlers.h" -#include "tm-modules.h" -#include "tm-threads.h" -#include "tm-threads-common.h" -#include "conf.h" -#include "util-debug.h" -#include "util-device.h" -#include "util-error.h" -#include "util-privs.h" -#include "util-optimize.h" -#include "util-checksum.h" -#include "util-ioctl.h" -#include "util-host-info.h" -#include "tmqh-packetpool.h" -#include "source-netmap.h" -#include "runmodes.h" - -#ifdef __SC_CUDA_SUPPORT__ - -#include "util-cuda.h" -#include "util-cuda-buffer.h" -#include "util-mpm-ac.h" -#include "util-cuda-handlers.h" -#include "detect-engine.h" -#include "detect-engine-mpm.h" -#include "util-cuda-vars.h" - -#endif /* __SC_CUDA_SUPPORT__ */ - -#ifdef HAVE_NETMAP - -#if HAVE_SYS_IOCTL_H -#include <sys/ioctl.h> -#endif - -#if HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - -#include <net/netmap_user.h> - -#endif /* HAVE_NETMAP */ - -extern int max_pending_packets; - -#ifndef HAVE_NETMAP - -TmEcode NoNetmapSupportExit(ThreadVars *, void *, void **); - -void TmModuleReceiveNetmapRegister (void) -{ - tmm_modules[TMM_RECEIVENETMAP].name = "ReceiveNetmap"; - tmm_modules[TMM_RECEIVENETMAP].ThreadInit = NoNetmapSupportExit; - tmm_modules[TMM_RECEIVENETMAP].Func = NULL; - tmm_modules[TMM_RECEIVENETMAP].ThreadExitPrintStats = NULL; - tmm_modules[TMM_RECEIVENETMAP].ThreadDeinit = NULL; - tmm_modules[TMM_RECEIVENETMAP].RegisterTests = NULL; - tmm_modules[TMM_RECEIVENETMAP].cap_flags = 0; - tmm_modules[TMM_RECEIVENETMAP].flags = TM_FLAG_RECEIVE_TM; -} - -/** -* \brief Registration Function for DecodeNetmap. -* \todo Unit tests are needed for this module. -*/ -void TmModuleDecodeNetmapRegister (void) -{ - tmm_modules[TMM_DECODENETMAP].name = "DecodeNetmap"; - tmm_modules[TMM_DECODENETMAP].ThreadInit = NoNetmapSupportExit; - tmm_modules[TMM_DECODENETMAP].Func = NULL; - tmm_modules[TMM_DECODENETMAP].ThreadExitPrintStats = NULL; - tmm_modules[TMM_DECODENETMAP].ThreadDeinit = NULL; - tmm_modules[TMM_DECODENETMAP].RegisterTests = NULL; - tmm_modules[TMM_DECODENETMAP].cap_flags = 0; - tmm_modules[TMM_DECODENETMAP].flags = TM_FLAG_DECODE_TM; -} - -/** -* \brief this function prints an error message and exits. -*/ -TmEcode NoNetmapSupportExit(ThreadVars *tv, void *initdata, void **data) -{ - SCLogError(SC_ERR_NO_NETMAP,"Error creating thread %s: you do not have " - "support for netmap enabled, please recompile " - "with --enable-netmap", tv->name); - exit(EXIT_FAILURE); -} - -#else /* We have NETMAP support */ - -#define max(a, b) (((a) > (b)) ? (a) : (b)) - -#define POLL_TIMEOUT 100 - -#if defined(__linux__) -#define POLL_EVENTS (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL) -#else -#define POLL_EVENTS (POLLHUP|POLLERR|POLLNVAL) -#endif - -enum { - NETMAP_OK, - NETMAP_FAILURE, -}; - -enum { - NETMAP_FLAG_ZERO_COPY = 1, -}; - -/** - * \brief Netmap ring isntance. - */ -typedef struct NetmapRing -{ - int fd; - struct netmap_ring *rx; - struct netmap_ring *tx; - int dst_ring_from; - int dst_ring_to; - int dst_next_ring; - SCSpinlock tx_lock; -} NetmapRing; - -/** - * \brief Netmap device instance. - */ -typedef struct NetmapDevice_ -{ - char ifname[IFNAMSIZ]; - void *mem; - size_t memsize; - struct netmap_if *nif; - int rings_cnt; - int rx_rings_cnt; - int tx_rings_cnt; - /* hw rings + sw ring */ - NetmapRing *rings; - unsigned int ref; - SC_ATOMIC_DECLARE(unsigned int, threads_run); - TAILQ_ENTRY(NetmapDevice_) next; -} NetmapDevice; - -/** - * \brief Module thread local variables. - */ -typedef struct NetmapThreadVars_ -{ - /* receive inteface */ - NetmapDevice *ifsrc; - /* dst interface for IPS mode */ - NetmapDevice *ifdst; - - int src_ring_from; - int src_ring_to; - int thread_idx; - int flags; - struct bpf_program bpf_prog; - - /* internal shit */ - TmSlot *slot; - ThreadVars *tv; - LiveDevice *livedev; - - /* copy from config */ - int copy_mode; - ChecksumValidationMode checksum_mode; - - /* counters */ - uint64_t pkts; - uint64_t bytes; - uint64_t drops; - uint16_t capture_kernel_packets; - uint16_t capture_kernel_drops; - - -} NetmapThreadVars; - -typedef TAILQ_HEAD(NetmapDeviceList_, NetmapDevice_) NetmapDeviceList; - -static NetmapDeviceList netmap_devlist = TAILQ_HEAD_INITIALIZER(netmap_devlist); -static SCMutex netmap_devlist_lock = SCMUTEX_INITIALIZER; - -/** - * \brief Get interface flags. - * \param fd Network susbystem file descritor. - * \param ifname Inteface name. - * \return Interface flags or -1 on error - */ -static int NetmapGetIfaceFlags(int fd, const char *ifname) -{ - struct ifreq ifr; - - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - - if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Unable to get flags for iface \"%s\": %s", - ifname, strerror(errno)); - return -1; - } - -#ifdef OS_FREEBSD - int flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); - return flags; -#else - return ifr.ifr_flags; -#endif -} - -/** - * \brief Set interface flags. - * \param fd Network susbystem file descritor. - * \param ifname Inteface name. - * \param flags Flags to set. - * \return Zero on success. - */ -static int NetmapSetIfaceFlags(int fd, const char *ifname, int flags) -{ - struct ifreq ifr; - - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); -#ifdef OS_FREEBSD - ifr.ifr_flags = flags & 0xffff; - ifr.ifr_flagshigh = flags >> 16; -#else - ifr.ifr_flags = flags; -#endif - - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Unable to set flags for iface \"%s\": %s", - ifname, strerror(errno)); - return -1; - } - - return 0; -} - -/** - * \brief Open interface in netmap mode. - * \param ifname Interface name. - * \param promisc Enable promiscuous mode. - * \param dev Pointer to requested netmap device instance. - * \param verbose Verbose error logging. - * \return Zero on success. - */ -static int NetmapOpen(char *ifname, int promisc, NetmapDevice **pdevice, int verbose) -{ - NetmapDevice *pdev = NULL; - struct nmreq nm_req; - - *pdevice = NULL; - - SCMutexLock(&netmap_devlist_lock); - - /* search interface in our already opened list */ - TAILQ_FOREACH(pdev, &netmap_devlist, next) { - if (strcmp(ifname, pdev->ifname) == 0) { - *pdevice = pdev; - pdev->ref++; - SCMutexUnlock(&netmap_devlist_lock); - return 0; - } - } - - /* not found, create new record */ - pdev = SCMalloc(sizeof(*pdev)); - if (unlikely(pdev == NULL)) { - SCLogError(SC_ERR_MEM_ALLOC, "Memory allocation failed"); - goto error; - } - - memset(pdev, 0, sizeof(*pdev)); - SC_ATOMIC_INIT(pdev->threads_run); - strlcpy(pdev->ifname, ifname, sizeof(pdev->ifname)); - - /* open netmap */ - int fd = open("/dev/netmap", O_RDWR); - if (fd == -1) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Couldn't open netmap device, error %s", - strerror(errno)); - goto error_pdev; - } - - /* check interface is up */ - int if_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (if_fd < 0) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Couldn't create control socket for '%s' interface", - ifname); - goto error_fd; - } - int if_flags = NetmapGetIfaceFlags(if_fd, ifname); - if (if_flags == -1) { - if (verbose) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Can not access to interface '%s'", - ifname); - } - close(if_fd); - goto error_fd; - } - if ((if_flags & IFF_UP) == 0) { - if (verbose) { - SCLogError(SC_ERR_NETMAP_CREATE, "Interface '%s' is down", ifname); - } - close(if_fd); - goto error_fd; - } - if (promisc) { - if_flags |= IFF_PROMISC; - NetmapSetIfaceFlags(if_fd, ifname, if_flags); - } - close(if_fd); - - /* query netmap info */ - memset(&nm_req, 0, sizeof(nm_req)); - strlcpy(nm_req.nr_name, ifname, sizeof(nm_req.nr_name)); - nm_req.nr_version = NETMAP_API; - - if (ioctl(fd, NIOCGINFO, &nm_req) != 0) { - if (verbose) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Couldn't query netmap for %s, error %s", - ifname, strerror(errno)); - } - goto error_fd; - }; - - pdev->memsize = nm_req.nr_memsize; - pdev->rx_rings_cnt = nm_req.nr_rx_rings; - pdev->tx_rings_cnt = nm_req.nr_tx_rings; - pdev->rings_cnt = max(pdev->rx_rings_cnt, pdev->tx_rings_cnt); - - /* hw rings + sw ring */ - pdev->rings = SCMalloc(sizeof(*pdev->rings) * (pdev->rings_cnt + 1)); - if (unlikely(pdev->rings == NULL)) { - SCLogError(SC_ERR_MEM_ALLOC, "Memory allocation failed"); - goto error_fd; - } - memset(pdev->rings, 0, sizeof(*pdev->rings) * (pdev->rings_cnt + 1)); - - /* open individual instance for each ring */ - int success_cnt = 0; - for (int i = 0; i <= pdev->rings_cnt; i++) { - NetmapRing *pring = &pdev->rings[i]; - pring->fd = open("/dev/netmap", O_RDWR); - if (pring->fd == -1) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Couldn't open netmap device: %s", - strerror(errno)); - break; - } - - if (i < pdev->rings_cnt) { - nm_req.nr_flags = NR_REG_ONE_NIC; - nm_req.nr_ringid = i | NETMAP_NO_TX_POLL; - } else { - nm_req.nr_flags = NR_REG_SW; - nm_req.nr_ringid = NETMAP_NO_TX_POLL; - } - if (ioctl(pring->fd, NIOCREGIF, &nm_req) != 0) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Couldn't register %s with netmap: %s", - ifname, strerror(errno)); - break; - } - - if (pdev->mem == NULL) { - pdev->mem = mmap(0, pdev->memsize, PROT_WRITE | PROT_READ, - MAP_SHARED, pring->fd, 0); - if (pdev->mem == MAP_FAILED) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Couldn't mmap netmap device: %s", - strerror(errno)); - break; - } - pdev->nif = NETMAP_IF(pdev->mem, nm_req.nr_offset); - } - - if ((i < pdev->rx_rings_cnt) || (i == pdev->rings_cnt)) { - pring->rx = NETMAP_RXRING(pdev->nif, i); - } - if ((i < pdev->tx_rings_cnt) || (i == pdev->rings_cnt)) { - pring->tx = NETMAP_TXRING(pdev->nif, i); - } - SCSpinInit(&pring->tx_lock, 0); - success_cnt++; - } - - if (success_cnt != (pdev->rings_cnt + 1)) { - for(int i = 0; i < success_cnt; i++) { - close(pdev->rings[i].fd); - } - if (pdev->mem) { - munmap(pdev->mem, pdev->memsize); - } - SCFree(pdev->rings); - goto error_fd; - } - - close(fd); - *pdevice = pdev; - - TAILQ_INSERT_TAIL(&netmap_devlist, pdev, next); - SCMutexUnlock(&netmap_devlist_lock); - - return 0; - -error_fd: - close(fd); -error_pdev: - SCFree(pdev); -error: - SCMutexUnlock(&netmap_devlist_lock); - return -1; -} - -/** - * \brief Close or dereference netmap device instance. - * \param pdev Netmap device instance. - * \return Zero on success. - */ -static int NetmapClose(NetmapDevice *dev) -{ - NetmapDevice *pdev, *tmp; - - SCMutexLock(&netmap_devlist_lock); - - TAILQ_FOREACH_SAFE(pdev, &netmap_devlist, next, tmp) { - if (pdev == dev) { - pdev->ref--; - if (!pdev->ref) { - munmap(pdev->mem, pdev->memsize); - for (int i = 0; i <= pdev->rings_cnt; i++) { - NetmapRing *pring = &pdev->rings[i]; - close(pring->fd); - SCSpinDestroy(&pring->tx_lock); - } - SCFree(pdev->rings); - TAILQ_REMOVE(&netmap_devlist, pdev, next); - SCFree(pdev); - } - SCMutexUnlock(&netmap_devlist_lock); - return 0; - } - } - - SCMutexUnlock(&netmap_devlist_lock); - return -1; -} - -/** - * \brief PcapDumpCounters - * \param ntv - */ -static inline void NetmapDumpCounters(NetmapThreadVars *ntv) -{ - StatsAddUI64(ntv->tv, ntv->capture_kernel_packets, ntv->pkts); - StatsAddUI64(ntv->tv, ntv->capture_kernel_drops, ntv->drops); - (void) SC_ATOMIC_ADD(ntv->livedev->drop, ntv->drops); - (void) SC_ATOMIC_ADD(ntv->livedev->pkts, ntv->pkts); - ntv->drops = 0; - ntv->pkts = 0; -} - -/** - * \brief Init function for ReceiveNetmap. - * \param tv pointer to ThreadVars - * \param initdata pointer to the interface passed from the user - * \param data pointer gets populated with NetmapThreadVars - */ -static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, void *initdata, void **data) -{ - SCEnter(); - NetmapIfaceConfig *aconf = initdata; - - if (initdata == NULL) { - SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL"); - SCReturnInt(TM_ECODE_FAILED); - } - - NetmapThreadVars *ntv = SCMalloc(sizeof(*ntv)); - if (unlikely(ntv == NULL)) { - SCLogError(SC_ERR_MEM_ALLOC, "Memory allocation failed"); - goto error; - } - memset(ntv, 0, sizeof(*ntv)); - - ntv->tv = tv; - ntv->checksum_mode = aconf->checksum_mode; - ntv->copy_mode = aconf->copy_mode; - - ntv->livedev = LiveGetDevice(aconf->iface_name); - if (ntv->livedev == NULL) { - SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); - goto error_ntv; - } - - if (NetmapOpen(aconf->iface, aconf->promisc, &ntv->ifsrc, 1) != 0) { - goto error_ntv; - } - - if (unlikely(!aconf->iface_sw && !ntv->ifsrc->rx_rings_cnt)) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Input interface '%s' does not have Rx rings", - aconf->iface_name); - goto error_src; - } - - if (unlikely(aconf->iface_sw && aconf->threads > 1)) { - SCLogError(SC_ERR_INVALID_VALUE, - "Interface '%s+'. " - "Thread count can't be greater than 1 for SW ring.", - aconf->iface_name); - goto error_src; - } else if (unlikely(aconf->threads > ntv->ifsrc->rx_rings_cnt)) { - SCLogError(SC_ERR_INVALID_VALUE, - "Thread count can't be greater than Rx ring count. " - "Configured %d threads for interface '%s' with %d Rx rings.", - aconf->threads, aconf->iface_name, ntv->ifsrc->rx_rings_cnt); - goto error_src; - } - - if (aconf->iface_sw) { - ntv->thread_idx = 0; - } else { - do { - ntv->thread_idx = SC_ATOMIC_GET(ntv->ifsrc->threads_run); - } while (SC_ATOMIC_CAS(&ntv->ifsrc->threads_run, ntv->thread_idx, ntv->thread_idx + 1) == 0); - } - - /* calculate thread rings binding */ - if (aconf->iface_sw) { - ntv->src_ring_from = ntv->src_ring_to = ntv->ifsrc->rings_cnt; - } else { - int tmp = (ntv->ifsrc->rx_rings_cnt + 1) / aconf->threads; - ntv->src_ring_from = ntv->thread_idx * tmp; - ntv->src_ring_to = ntv->src_ring_from + tmp - 1; - if (ntv->thread_idx == (aconf->threads - 1)) { - ntv->src_ring_to = ntv->ifsrc->rx_rings_cnt - 1; - } - } - SCLogDebug("netmap: %s thread:%d rings:%d-%d", aconf->iface_name, - ntv->thread_idx, ntv->src_ring_from, ntv->src_ring_to); - - if (aconf->copy_mode != NETMAP_COPY_MODE_NONE) { - if (NetmapOpen(aconf->out_iface, 0, &ntv->ifdst, 1) != 0) { - goto error_src; - } - - if (unlikely(!aconf->out_iface_sw && !ntv->ifdst->tx_rings_cnt)) { - SCLogError(SC_ERR_NETMAP_CREATE, - "Output interface '%s' does not have Tx rings", - aconf->out_iface_name); - goto error_dst; - } - - /* calculate dst rings bindings */ - for (int i = ntv->src_ring_from; i <= ntv->src_ring_to; i++) { - NetmapRing *ring = &ntv->ifsrc->rings[i]; - if (aconf->out_iface_sw) { - ring->dst_ring_from = ring->dst_ring_to = ntv->ifdst->rings_cnt; - } else if (ntv->ifdst->tx_rings_cnt > ntv->ifsrc->rx_rings_cnt) { - int tmp = (ntv->ifdst->tx_rings_cnt + 1) / ntv->ifsrc->rx_rings_cnt; - ring->dst_ring_from = i * tmp; - ring->dst_ring_to = ring->dst_ring_from + tmp - 1; - if (i == (ntv->src_ring_to - 1)) { - ring->dst_ring_to = ntv->ifdst->tx_rings_cnt - 1; - } - } else { - ring->dst_ring_from = ring->dst_ring_to = - i % ntv->ifdst->tx_rings_cnt; - } - ring->dst_next_ring = ring->dst_ring_from; - - SCLogDebug("netmap: %s(%d)->%s(%d-%d)", - aconf->iface_name, i, aconf->out_iface_name, - ring->dst_ring_from, ring->dst_ring_to); - } - } - - /* basic counters */ - ntv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets", - ntv->tv); - ntv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops", - ntv->tv); - - /* enable zero-copy mode for workers runmode */ - char const *active_runmode = RunmodeGetActive(); - if ((aconf->copy_mode != NETMAP_COPY_MODE_NONE) && active_runmode - && !strcmp("workers", active_runmode)) { - if (likely(ntv->ifsrc->mem == ntv->ifdst->mem)) { - ntv->flags |= NETMAP_FLAG_ZERO_COPY; - SCLogInfo("Enabling zero copy mode for %s->%s", - aconf->iface_name, aconf->out_iface_name); - } else { - SCLogInfo("Unable to set zero copy mode for %s->%s", - aconf->iface_name, aconf->out_iface_name); - } - } - - if (aconf->bpf_filter) { - SCLogInfo("Using BPF '%s' on iface '%s'", - aconf->bpf_filter, ntv->ifsrc->ifname); - if (pcap_compile_nopcap(default_packet_size, /* snaplen_arg */ - LINKTYPE_ETHERNET, /* linktype_arg */ - &ntv->bpf_prog, /* program */ - aconf->bpf_filter, /* const char *buf */ - 1, /* optimize */ - PCAP_NETMASK_UNKNOWN /* mask */ - ) == -1) { - SCLogError(SC_ERR_NETMAP_CREATE, "Filter compilation failed."); - goto error_dst; - } - } - - if (GetIfaceOffloading(aconf->iface) == 1) { - SCLogWarning(SC_ERR_NETMAP_CREATE, - "Using mmap mode with GRO or LRO activated can lead to capture problems"); - } - - *data = (void *)ntv; - aconf->DerefFunc(aconf); - SCReturnInt(TM_ECODE_OK); - -error_dst: - if (aconf->copy_mode != NETMAP_COPY_MODE_NONE) { - NetmapClose(ntv->ifdst); - } -error_src: - NetmapClose(ntv->ifsrc); -error_ntv: - SCFree(ntv); -error: - aconf->DerefFunc(aconf); - SCReturnInt(TM_ECODE_FAILED); -} - -/** - * \brief Output packet to destination interface or drop. - * \param ntv Thread local variables. - * \param p Source packet. - */ -static TmEcode NetmapWritePacket(NetmapThreadVars *ntv, Packet *p) -{ - if (ntv->copy_mode == NETMAP_COPY_MODE_IPS) { - if (PACKET_TEST_ACTION(p, ACTION_DROP)) { - return TM_ECODE_OK; - } - } - - /* map src ring_id to dst ring_id */ - NetmapRing *rxring = &ntv->ifsrc->rings[p->netmap_v.ring_id]; - NetmapRing *txring = &ntv->ifdst->rings[p->netmap_v.dst_ring_id]; - - SCSpinLock(&txring->tx_lock); - - if (!nm_ring_space(txring->tx)) { - ntv->drops++; - SCSpinUnlock(&txring->tx_lock); - return TM_ECODE_FAILED; - } - - struct netmap_slot *ts = &txring->tx->slot[txring->tx->cur]; - - if (ntv->flags & NETMAP_FLAG_ZERO_COPY) { - struct netmap_slot *rs = &rxring->rx->slot[p->netmap_v.slot_id]; - - /* swap slot buffers */ - uint32_t tmp_idx; - tmp_idx = ts->buf_idx; - ts->buf_idx = rs->buf_idx; - rs->buf_idx = tmp_idx; - - ts->len = rs->len; - - ts->flags |= NS_BUF_CHANGED; - rs->flags |= NS_BUF_CHANGED; - } else { - unsigned char *slot_data = (unsigned char *)NETMAP_BUF(txring->tx, ts->buf_idx); - memcpy(slot_data, GET_PKT_DATA(p), GET_PKT_LEN(p)); - ts->len = GET_PKT_LEN(p); - ts->flags |= NS_BUF_CHANGED; - } - - txring->tx->head = txring->tx->cur = nm_ring_next(txring->tx, txring->tx->cur); - if ((ntv->flags & NETMAP_FLAG_ZERO_COPY) == 0) { - ioctl(txring->fd, NIOCTXSYNC, 0); - } - - SCSpinUnlock(&txring->tx_lock); - - return TM_ECODE_OK; -} - -/** - * \brief Packet release routine. - * \param p Packet. - */ -static void NetmapReleasePacket(Packet *p) -{ - NetmapThreadVars *ntv = (NetmapThreadVars *)p->netmap_v.ntv; - - /* Need to be in copy mode and need to detect early release - where Ethernet header could not be set (and pseudo packet) */ - if ((ntv->copy_mode != NETMAP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) { - NetmapWritePacket(ntv, p); - } - - PacketFreeOrRelease(p); -} - -/** - * \brief Read packets from ring and pass them further. - * \param ntv Thread local variables. - * \param ring_id Ring id to read. - */ -static int NetmapRingRead(NetmapThreadVars *ntv, int ring_id) -{ - SCEnter(); - - NetmapRing *ring = &ntv->ifsrc->rings[ring_id]; - struct netmap_ring *rx = ring->rx; - uint32_t avail = nm_ring_space(rx); - uint32_t cur = rx->cur; - - while (likely(avail-- > 0)) { - struct netmap_slot *slot = &rx->slot[cur]; - unsigned char *slot_data = (unsigned char *)NETMAP_BUF(rx, slot->buf_idx); - - if (ntv->bpf_prog.bf_len) { - struct pcap_pkthdr pkthdr = { {0, 0}, slot->len, slot->len }; - if (pcap_offline_filter(&ntv->bpf_prog, &pkthdr, slot_data) == 0) { - /* rejected by bpf */ - cur = nm_ring_next(rx, cur); - continue; - } - } - - Packet *p = PacketGetFromQueueOrAlloc(); - if (unlikely(p == NULL)) { - SCReturnInt(NETMAP_FAILURE); - } - - PKT_SET_SRC(p, PKT_SRC_WIRE); - p->livedev = ntv->livedev; - p->datalink = LINKTYPE_ETHERNET; - p->ts = rx->ts; - ntv->pkts++; - ntv->bytes += slot->len; - - /* checksum validation */ - if (ntv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) { - p->flags |= PKT_IGNORE_CHECKSUM; - } else if (ntv->checksum_mode == CHECKSUM_VALIDATION_AUTO) { - if (ntv->livedev->ignore_checksum) { - p->flags |= PKT_IGNORE_CHECKSUM; - } else if (ChecksumAutoModeCheck(ntv->pkts, - SC_ATOMIC_GET(ntv->livedev->pkts), - SC_ATOMIC_GET(ntv->livedev->invalid_checksums))) { - ntv->livedev->ignore_checksum = 1; - p->flags |= PKT_IGNORE_CHECKSUM; - } - } - - if (ntv->flags & NETMAP_FLAG_ZERO_COPY) { - if (PacketSetData(p, slot_data, slot->len) == -1) { - TmqhOutputPacketpool(ntv->tv, p); - SCReturnInt(NETMAP_FAILURE); - } - } else { - if (PacketCopyData(p, slot_data, slot->len) == -1) { - TmqhOutputPacketpool(ntv->tv, p); - SCReturnInt(NETMAP_FAILURE); - } - } - - p->ReleasePacket = NetmapReleasePacket; - p->netmap_v.ring_id = ring_id; - p->netmap_v.slot_id = cur; - p->netmap_v.dst_ring_id = ring->dst_next_ring; - p->netmap_v.ntv = ntv; - - if (ring->dst_ring_from != ring->dst_ring_to) { - ring->dst_next_ring++; - if (ring->dst_next_ring == ring->dst_ring_to) { - ring->dst_next_ring = ring->dst_ring_from; - } - } - - SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)", - GET_PKT_LEN(p), p, GET_PKT_DATA(p)); - - if (TmThreadsSlotProcessPkt(ntv->tv, ntv->slot, p) != TM_ECODE_OK) { - TmqhOutputPacketpool(ntv->tv, p); - SCReturnInt(NETMAP_FAILURE); - } - - cur = nm_ring_next(rx, cur); - } - rx->head = rx->cur = cur; - - SCReturnInt(NETMAP_OK); -} - -/** - * \brief Main netmap reading loop function - */ -static TmEcode ReceiveNetmapLoop(ThreadVars *tv, void *data, void *slot) -{ - SCEnter(); - - TmSlot *s = (TmSlot *)slot; - NetmapThreadVars *ntv = (NetmapThreadVars *)data; - struct pollfd *fds; - int rings_count = ntv->src_ring_to - ntv->src_ring_from + 1; - - ntv->slot = s->slot_next; - - fds = SCMalloc(sizeof(*fds) * rings_count); - if (unlikely(fds == NULL)) { - SCLogError(SC_ERR_MEM_ALLOC, "Memory allocation failed"); - SCReturnInt(TM_ECODE_FAILED); - } - - for (int i = 0; i < rings_count; i++) { - fds[i].fd = ntv->ifsrc->rings[ntv->src_ring_from + i].fd; - fds[i].events = POLLIN; - } - - for(;;) { - if (suricata_ctl_flags != 0) { - break; - } - - /* make sure we have at least one packet in the packet pool, - * to prevent us from alloc'ing packets at line rate */ - PacketPoolWait(); - - int r = poll(fds, rings_count, POLL_TIMEOUT); - - if (r < 0) { - /* error */ - if(errno != EINTR) - SCLogError(SC_ERR_NETMAP_READ, - "Error polling netmap from iface '%s': (%d" PRIu32 ") %s", - ntv->ifsrc->ifname, errno, strerror(errno)); - continue; - } else if (r == 0) { - /* no events, timeout */ - SCLogDebug("(%s:%d-%d) Poll timeout", ntv->ifsrc->ifname, - ntv->src_ring_from, ntv->src_ring_to); - continue; - } - - for (int i = 0; i < rings_count; i++) { - if (fds[i].revents & POLL_EVENTS) { - if (fds[i].revents & POLLERR) { - SCLogError(SC_ERR_NETMAP_READ, - "Error reading data from iface '%s': (%d" PRIu32 ") %s", - ntv->ifsrc->ifname, errno, strerror(errno)); - } else if (fds[i].revents & POLLNVAL) { - SCLogError(SC_ERR_NETMAP_READ, - "Invalid polling request"); - } - continue; - } - - if (likely(fds[i].revents & POLLIN)) { - int src_ring_id = ntv->src_ring_from + i; - NetmapRingRead(ntv, src_ring_id); - - if ((ntv->copy_mode != NETMAP_COPY_MODE_NONE) && - (ntv->flags & NETMAP_FLAG_ZERO_COPY)) { - - NetmapRing *src_ring = &ntv->ifsrc->rings[src_ring_id]; - - /* sync dst tx rings */ - for (int j = src_ring->dst_ring_from; j <= src_ring->dst_ring_to; j++) { - NetmapRing *dst_ring = &ntv->ifdst->rings[j]; - /* if locked, another loop already do sync */ - if (SCSpinTrylock(&dst_ring->tx_lock) == 0) { - ioctl(dst_ring->fd, NIOCTXSYNC, 0); - SCSpinUnlock(&dst_ring->tx_lock); - } - } - } - } - } - - NetmapDumpCounters(ntv); - StatsSyncCountersIfSignalled(tv); - } - - SCFree(fds); - StatsSyncCountersIfSignalled(tv); - SCReturnInt(TM_ECODE_OK); -} - -/** - * \brief This function prints stats to the screen at exit. - * \param tv pointer to ThreadVars - * \param data pointer that gets cast into NetmapThreadVars for ntv - */ -static void ReceiveNetmapThreadExitStats(ThreadVars *tv, void *data) -{ - SCEnter(); - NetmapThreadVars *ntv = (NetmapThreadVars *)data; - - NetmapDumpCounters(ntv); - SCLogInfo("(%s) Kernel: Packets %" PRIu64 ", dropped %" PRIu64 ", bytes %" PRIu64 "", - tv->name, - StatsGetLocalCounterValue(tv, ntv->capture_kernel_packets), - StatsGetLocalCounterValue(tv, ntv->capture_kernel_drops), - ntv->bytes); -} - -/** - * \brief - * \param tv - * \param data Pointer to NetmapThreadVars. - */ -static TmEcode ReceiveNetmapThreadDeinit(ThreadVars *tv, void *data) -{ - SCEnter(); - - NetmapThreadVars *ntv = (NetmapThreadVars *)data; - - if (ntv->ifsrc) { - NetmapClose(ntv->ifsrc); - ntv->ifsrc = NULL; - } - if (ntv->ifdst) { - NetmapClose(ntv->ifdst); - ntv->ifdst = NULL; - } - if (ntv->bpf_prog.bf_insns) { - pcap_freecode(&ntv->bpf_prog); - } - - SCReturnInt(TM_ECODE_OK); -} - -/** - * \brief Prepare netmap decode thread. - * \param tv Thread local avariables. - * \param initdata Thread config. - * \param data Pointer to DecodeThreadVars placed here. - */ -static TmEcode DecodeNetmapThreadInit(ThreadVars *tv, void *initdata, void **data) -{ - SCEnter(); - DecodeThreadVars *dtv = NULL; - - dtv = DecodeThreadVarsAlloc(tv); - - if (dtv == NULL) - SCReturnInt(TM_ECODE_FAILED); - - DecodeRegisterPerfCounters(dtv, tv); - - *data = (void *)dtv; - -#ifdef __SC_CUDA_SUPPORT__ - if (CudaThreadVarsInit(&dtv->cuda_vars) < 0) - SCReturnInt(TM_ECODE_FAILED); -#endif - - SCReturnInt(TM_ECODE_OK); -} - -/** - * \brief This function passes off to link type decoders. - * - * DecodeNetmap reads packets from the PacketQueue and passes - * them off to the proper link type decoder. - * - * \param t pointer to ThreadVars - * \param p pointer to the current packet - * \param data pointer that gets cast into NetmapThreadVars for ntv - * \param pq pointer to the current PacketQueue - * \param postpq - */ -static TmEcode DecodeNetmap(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) -{ - SCEnter(); - - DecodeThreadVars *dtv = (DecodeThreadVars *)data; - - /* XXX HACK: flow timeout can call us for injected pseudo packets - * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ - if (p->flags & PKT_PSEUDO_STREAM_END) - SCReturnInt(TM_ECODE_OK); - - /* update counters */ - DecodeUpdatePacketCounters(tv, dtv, p); - - DecodeEthernet(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); - - PacketDecodeFinalize(tv, dtv, p); - - SCReturnInt(TM_ECODE_OK); -} - -/** - * \brief - * \param tv - * \param data Pointer to DecodeThreadVars. - */ -static TmEcode DecodeNetmapThreadDeinit(ThreadVars *tv, void *data) -{ - SCEnter(); - - if (data != NULL) - DecodeThreadVarsFree(tv, data); - - SCReturnInt(TM_ECODE_OK); -} - -/** - * \brief Registration Function for RecieveNetmap. - */ -void TmModuleReceiveNetmapRegister(void) -{ - tmm_modules[TMM_RECEIVENETMAP].name = "ReceiveNetmap"; - tmm_modules[TMM_RECEIVENETMAP].ThreadInit = ReceiveNetmapThreadInit; - tmm_modules[TMM_RECEIVENETMAP].Func = NULL; - tmm_modules[TMM_RECEIVENETMAP].PktAcqLoop = ReceiveNetmapLoop; - tmm_modules[TMM_RECEIVENETMAP].ThreadExitPrintStats = ReceiveNetmapThreadExitStats; - tmm_modules[TMM_RECEIVENETMAP].ThreadDeinit = ReceiveNetmapThreadDeinit; - tmm_modules[TMM_RECEIVENETMAP].RegisterTests = NULL; - tmm_modules[TMM_RECEIVENETMAP].cap_flags = SC_CAP_NET_RAW; - tmm_modules[TMM_RECEIVENETMAP].flags = TM_FLAG_RECEIVE_TM; -} - -/** - * \brief Registration Function for DecodeNetmap. - */ -void TmModuleDecodeNetmapRegister(void) -{ - tmm_modules[TMM_DECODENETMAP].name = "DecodeNetmap"; - tmm_modules[TMM_DECODENETMAP].ThreadInit = DecodeNetmapThreadInit; - tmm_modules[TMM_DECODENETMAP].Func = DecodeNetmap; - tmm_modules[TMM_DECODENETMAP].ThreadExitPrintStats = NULL; - tmm_modules[TMM_DECODENETMAP].ThreadDeinit = DecodeNetmapThreadDeinit; - tmm_modules[TMM_DECODENETMAP].RegisterTests = NULL; - tmm_modules[TMM_DECODENETMAP].cap_flags = 0; - tmm_modules[TMM_DECODENETMAP].flags = TM_FLAG_DECODE_TM; -} - -#endif /* HAVE_NETMAP */ -/* eof */ -/** -* @} -*/ |