diff options
Diffstat (limited to 'framework/src/suricata/src/source-pcap.c')
-rw-r--r-- | framework/src/suricata/src/source-pcap.c | 826 |
1 files changed, 0 insertions, 826 deletions
diff --git a/framework/src/suricata/src/source-pcap.c b/framework/src/suricata/src/source-pcap.c deleted file mode 100644 index 0656f958..00000000 --- a/framework/src/suricata/src/source-pcap.c +++ /dev/null @@ -1,826 +0,0 @@ -/* Copyright (C) 2007-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. - */ - -/** - * \file - * - * \author Victor Julien <victor@inliniac.net> - * - * Live pcap packet acquisition support - */ - -#include "suricata-common.h" -#include "suricata.h" -#include "decode.h" -#include "packet-queue.h" -#include "threads.h" -#include "threadvars.h" -#include "tm-queuehandlers.h" -#include "tm-threads.h" -#include "source-pcap.h" -#include "conf.h" -#include "util-debug.h" -#include "util-error.h" -#include "util-privs.h" -#include "util-device.h" -#include "util-optimize.h" -#include "util-checksum.h" -#include "util-ioctl.h" -#include "tmqh-packetpool.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__ */ - -#define PCAP_STATE_DOWN 0 -#define PCAP_STATE_UP 1 - -#define PCAP_RECONNECT_TIMEOUT 500000 - -/** - * \brief Structure to hold thread specific variables. - */ -typedef struct PcapThreadVars_ -{ - /* thread specific handle */ - pcap_t *pcap_handle; - /* handle state */ - unsigned char pcap_state; - /* thread specific bpf */ - struct bpf_program filter; - /* ptr to string from config */ - char *bpf_filter; - - time_t last_stats_dump; - - /* data link type for the thread */ - int datalink; - - /* counters */ - uint32_t pkts; - uint64_t bytes; - uint32_t errs; - - uint16_t capture_kernel_packets; - uint16_t capture_kernel_drops; - uint16_t capture_kernel_ifdrops; - - ThreadVars *tv; - TmSlot *slot; - - /** callback result -- set if one of the thread module failed. */ - int cb_result; - - /* pcap buffer size */ - int pcap_buffer_size; - int pcap_snaplen; - - ChecksumValidationMode checksum_mode; - -#if LIBPCAP_VERSION_MAJOR == 0 - char iface[PCAP_IFACE_NAME_LENGTH]; -#endif - LiveDevice *livedev; -} PcapThreadVars; - -TmEcode ReceivePcapThreadInit(ThreadVars *, void *, void **); -void ReceivePcapThreadExitStats(ThreadVars *, void *); -TmEcode ReceivePcapThreadDeinit(ThreadVars *, void *); -TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot); - -TmEcode DecodePcapThreadInit(ThreadVars *, void *, void **); -TmEcode DecodePcapThreadDeinit(ThreadVars *tv, void *data); -TmEcode DecodePcap(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *); - -/** protect pcap_compile and pcap_setfilter, as they are not thread safe: - * http://seclists.org/tcpdump/2009/q1/62 */ -static SCMutex pcap_bpf_compile_lock = SCMUTEX_INITIALIZER; - -/** - * \brief Registration Function for RecievePcap. - * \todo Unit tests are needed for this module. - */ -void TmModuleReceivePcapRegister (void) -{ - tmm_modules[TMM_RECEIVEPCAP].name = "ReceivePcap"; - tmm_modules[TMM_RECEIVEPCAP].ThreadInit = ReceivePcapThreadInit; - tmm_modules[TMM_RECEIVEPCAP].Func = NULL; - tmm_modules[TMM_RECEIVEPCAP].PktAcqLoop = ReceivePcapLoop; - tmm_modules[TMM_RECEIVEPCAP].ThreadExitPrintStats = ReceivePcapThreadExitStats; - tmm_modules[TMM_RECEIVEPCAP].ThreadDeinit = NULL; - tmm_modules[TMM_RECEIVEPCAP].RegisterTests = NULL; - tmm_modules[TMM_RECEIVEPCAP].cap_flags = SC_CAP_NET_RAW; - tmm_modules[TMM_RECEIVEPCAP].flags = TM_FLAG_RECEIVE_TM; -} - -/** - * \brief Registration Function for DecodePcap. - * \todo Unit tests are needed for this module. - */ -void TmModuleDecodePcapRegister (void) -{ - tmm_modules[TMM_DECODEPCAP].name = "DecodePcap"; - tmm_modules[TMM_DECODEPCAP].ThreadInit = DecodePcapThreadInit; - tmm_modules[TMM_DECODEPCAP].Func = DecodePcap; - tmm_modules[TMM_DECODEPCAP].ThreadExitPrintStats = NULL; - tmm_modules[TMM_DECODEPCAP].ThreadDeinit = DecodePcapThreadDeinit; - tmm_modules[TMM_DECODEPCAP].RegisterTests = NULL; - tmm_modules[TMM_DECODEPCAP].cap_flags = 0; - tmm_modules[TMM_DECODEPCAP].flags = TM_FLAG_DECODE_TM; -} - -static inline void PcapDumpCounters(PcapThreadVars *ptv) -{ - struct pcap_stat pcap_s; - if (likely((pcap_stats(ptv->pcap_handle, &pcap_s) >= 0))) { - StatsSetUI64(ptv->tv, ptv->capture_kernel_packets, pcap_s.ps_recv); - StatsSetUI64(ptv->tv, ptv->capture_kernel_drops, pcap_s.ps_drop); - (void) SC_ATOMIC_SET(ptv->livedev->drop, pcap_s.ps_drop); - StatsSetUI64(ptv->tv, ptv->capture_kernel_ifdrops, pcap_s.ps_ifdrop); - } -} - - -#if LIBPCAP_VERSION_MAJOR == 1 -static int PcapTryReopen(PcapThreadVars *ptv) -{ - int pcap_activate_r; - - ptv->pcap_state = PCAP_STATE_DOWN; - pcap_activate_r = pcap_activate(ptv->pcap_handle); - if (pcap_activate_r != 0) { - return pcap_activate_r; - } - /* set bpf filter if we have one */ - if (ptv->bpf_filter != NULL) { - if(pcap_compile(ptv->pcap_handle,&ptv->filter,ptv->bpf_filter,1,0) < 0) { - SCLogError(SC_ERR_BPF,"bpf compilation error %s",pcap_geterr(ptv->pcap_handle)); - return -1; - } - - if(pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) { - SCLogError(SC_ERR_BPF,"could not set bpf filter %s",pcap_geterr(ptv->pcap_handle)); - return -1; - } - } - - SCLogInfo("Recovering interface listening"); - ptv->pcap_state = PCAP_STATE_UP; - return 0; -} -#else /* implied LIBPCAP_VERSION_MAJOR == 0 */ -static int PcapTryReopen(PcapThreadVars *ptv) -{ - char errbuf[PCAP_ERRBUF_SIZE] = ""; - - ptv->pcap_state = PCAP_STATE_DOWN; - pcap_close(ptv->pcap_handle); - - ptv->pcap_handle = pcap_open_live((char *)ptv->iface, ptv->pcap_snaplen, - LIBPCAP_PROMISC, LIBPCAP_COPYWAIT, errbuf); - if (ptv->pcap_handle == NULL) { - SCLogError(SC_ERR_PCAP_OPEN_LIVE, "Problem creating pcap handler for live mode, error %s", errbuf); - return -1; - } - - /* set bpf filter if we have one */ - if (ptv->bpf_filter != NULL) { - SCLogInfo("using bpf-filter \"%s\"", ptv->bpf_filter); - - if(pcap_compile(ptv->pcap_handle,&ptv->filter,ptv->bpf_filter,1,0) < 0) { - SCLogError(SC_ERR_BPF,"bpf compilation error %s",pcap_geterr(ptv->pcap_handle)); - return -1; - } - - if(pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) { - SCLogError(SC_ERR_BPF,"could not set bpf filter %s",pcap_geterr(ptv->pcap_handle)); - return -1; - } - } - - SCLogInfo("Recovering interface listening"); - ptv->pcap_state = PCAP_STATE_UP; - return 0; -} - -#endif - -void PcapCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt) -{ - SCEnter(); - - PcapThreadVars *ptv = (PcapThreadVars *)user; - Packet *p = PacketGetFromQueueOrAlloc(); - struct timeval current_time; - - if (unlikely(p == NULL)) { - SCReturn; - } - - PKT_SET_SRC(p, PKT_SRC_WIRE); - p->ts.tv_sec = h->ts.tv_sec; - p->ts.tv_usec = h->ts.tv_usec; - SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec); - p->datalink = ptv->datalink; - - ptv->pkts++; - ptv->bytes += h->caplen; - (void) SC_ATOMIC_ADD(ptv->livedev->pkts, 1); - p->livedev = ptv->livedev; - - if (unlikely(PacketCopyData(p, pkt, h->caplen))) { - TmqhOutputPacketpool(ptv->tv, p); - SCReturn; - } - - switch (ptv->checksum_mode) { - case CHECKSUM_VALIDATION_AUTO: - if (ptv->livedev->ignore_checksum) { - p->flags |= PKT_IGNORE_CHECKSUM; - } else if (ChecksumAutoModeCheck(ptv->pkts, - SC_ATOMIC_GET(ptv->livedev->pkts), - SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) { - ptv->livedev->ignore_checksum = 1; - p->flags |= PKT_IGNORE_CHECKSUM; - } - break; - case CHECKSUM_VALIDATION_DISABLE: - p->flags |= PKT_IGNORE_CHECKSUM; - break; - default: - break; - } - - if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) { - pcap_breakloop(ptv->pcap_handle); - ptv->cb_result = TM_ECODE_FAILED; - } - - /* Trigger one dump of stats every second */ - TimeGet(¤t_time); - if (current_time.tv_sec != ptv->last_stats_dump) { - PcapDumpCounters(ptv); - ptv->last_stats_dump = current_time.tv_sec; - } - - SCReturn; -} - -/** - * \brief Main PCAP reading Loop function - */ -TmEcode ReceivePcapLoop(ThreadVars *tv, void *data, void *slot) -{ - SCEnter(); - - int packet_q_len = 64; - PcapThreadVars *ptv = (PcapThreadVars *)data; - int r; - TmSlot *s = (TmSlot *)slot; - - ptv->slot = s->slot_next; - ptv->cb_result = TM_ECODE_OK; - - while (1) { - if (suricata_ctl_flags & (SURICATA_STOP | SURICATA_KILL)) { - SCReturnInt(TM_ECODE_OK); - } - - /* make sure we have at least one packet in the packet pool, to prevent - * us from alloc'ing packets at line rate */ - PacketPoolWait(); - - /* Right now we just support reading packets one at a time. */ - r = pcap_dispatch(ptv->pcap_handle, packet_q_len, - (pcap_handler)PcapCallbackLoop, (u_char *)ptv); - if (unlikely(r < 0)) { - int dbreak = 0; - SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s", - r, pcap_geterr(ptv->pcap_handle)); -#ifdef PCAP_ERROR_BREAK - if (r == PCAP_ERROR_BREAK) { - SCReturnInt(ptv->cb_result); - } -#endif - do { - usleep(PCAP_RECONNECT_TIMEOUT); - if (suricata_ctl_flags != 0) { - dbreak = 1; - break; - } - r = PcapTryReopen(ptv); - } while (r < 0); - if (dbreak) { - break; - } - } else if (ptv->cb_result == TM_ECODE_FAILED) { - SCLogError(SC_ERR_PCAP_DISPATCH, "Pcap callback PcapCallbackLoop failed"); - SCReturnInt(TM_ECODE_FAILED); - } - - StatsSyncCountersIfSignalled(tv); - } - - PcapDumpCounters(ptv); - StatsSyncCountersIfSignalled(tv); - SCReturnInt(TM_ECODE_OK); -} - -/** - * \brief Init function for ReceivePcap. - * - * This is a setup function for recieving packets - * via libpcap. There are two versions of this function - * depending on the major version of libpcap used. - * For versions prior to 1.x we use open_pcap_live, - * for versions 1.x and greater we use pcap_create + pcap_activate. - * - * \param tv pointer to ThreadVars - * \param initdata pointer to the interface passed from the user - * \param data pointer gets populated with PcapThreadVars - * - * \todo Create a general pcap setup function. - */ -#if LIBPCAP_VERSION_MAJOR == 1 -TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) -{ - SCEnter(); - PcapIfaceConfig *pcapconfig = initdata; - - if (initdata == NULL) { - SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL"); - SCReturnInt(TM_ECODE_FAILED); - } - - PcapThreadVars *ptv = SCMalloc(sizeof(PcapThreadVars)); - if (unlikely(ptv == NULL)) { - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } - memset(ptv, 0, sizeof(PcapThreadVars)); - - ptv->tv = tv; - - ptv->livedev = LiveGetDevice(pcapconfig->iface); - if (ptv->livedev == NULL) { - SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); - SCFree(ptv); - SCReturnInt(TM_ECODE_FAILED); - } - - SCLogInfo("using interface %s", (char *)pcapconfig->iface); - - ptv->checksum_mode = pcapconfig->checksum_mode; - if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) { - SCLogInfo("Running in 'auto' checksum mode. Detection of interface state will require " - xstr(CHECKSUM_SAMPLE_COUNT) " packets."); - } - - /* XXX create a general pcap setup function */ - char errbuf[PCAP_ERRBUF_SIZE]; - ptv->pcap_handle = pcap_create((char *)pcapconfig->iface, errbuf); - if (ptv->pcap_handle == NULL) { - if (strlen(errbuf)) { - SCLogError(SC_ERR_PCAP_CREATE, "Couldn't create a new pcap handler for %s, error %s", - (char *)pcapconfig->iface, errbuf); - } else { - SCLogError(SC_ERR_PCAP_CREATE, "Couldn't create a new pcap handler for %s", - (char *)pcapconfig->iface); - } - SCFree(ptv); - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } - - if (pcapconfig->snaplen == 0) { - /* We set snaplen if we can get the MTU */ - ptv->pcap_snaplen = GetIfaceMaxPacketSize(pcapconfig->iface); - } else { - ptv->pcap_snaplen = pcapconfig->snaplen; - } - if (ptv->pcap_snaplen > 0) { - /* set Snaplen. Must be called before pcap_activate */ - int pcap_set_snaplen_r = pcap_set_snaplen(ptv->pcap_handle, ptv->pcap_snaplen); - if (pcap_set_snaplen_r != 0) { - SCLogError(SC_ERR_PCAP_SET_SNAPLEN, "Couldn't set snaplen, error: %s", pcap_geterr(ptv->pcap_handle)); - SCFree(ptv); - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } - SCLogInfo("Set snaplen to %d for '%s'", ptv->pcap_snaplen, - pcapconfig->iface); - } - - /* set Promisc, and Timeout. Must be called before pcap_activate */ - int pcap_set_promisc_r = pcap_set_promisc(ptv->pcap_handle, pcapconfig->promisc); - //printf("ReceivePcapThreadInit: pcap_set_promisc(%p) returned %" PRId32 "\n", ptv->pcap_handle, pcap_set_promisc_r); - if (pcap_set_promisc_r != 0) { - SCLogError(SC_ERR_PCAP_SET_PROMISC, "Couldn't set promisc mode, error %s", pcap_geterr(ptv->pcap_handle)); - SCFree(ptv); - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } - - int pcap_set_timeout_r = pcap_set_timeout(ptv->pcap_handle,LIBPCAP_COPYWAIT); - //printf("ReceivePcapThreadInit: pcap_set_timeout(%p) returned %" PRId32 "\n", ptv->pcap_handle, pcap_set_timeout_r); - if (pcap_set_timeout_r != 0) { - SCLogError(SC_ERR_PCAP_SET_TIMEOUT, "Problems setting timeout, error %s", pcap_geterr(ptv->pcap_handle)); - SCFree(ptv); - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } -#ifdef HAVE_PCAP_SET_BUFF - ptv->pcap_buffer_size = pcapconfig->buffer_size; - if (ptv->pcap_buffer_size >= 0 && ptv->pcap_buffer_size <= INT_MAX) { - if (ptv->pcap_buffer_size > 0) - SCLogInfo("Going to use pcap buffer size of %" PRId32 "", ptv->pcap_buffer_size); - - int pcap_set_buffer_size_r = pcap_set_buffer_size(ptv->pcap_handle,ptv->pcap_buffer_size); - //printf("ReceivePcapThreadInit: pcap_set_timeout(%p) returned %" PRId32 "\n", ptv->pcap_handle, pcap_set_buffer_size_r); - if (pcap_set_buffer_size_r != 0) { - SCLogError(SC_ERR_PCAP_SET_BUFF_SIZE, "Problems setting pcap buffer size, error %s", pcap_geterr(ptv->pcap_handle)); - SCFree(ptv); - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } - } -#endif /* HAVE_PCAP_SET_BUFF */ - - /* activate the handle */ - int pcap_activate_r = pcap_activate(ptv->pcap_handle); - //printf("ReceivePcapThreadInit: pcap_activate(%p) returned %" PRId32 "\n", ptv->pcap_handle, pcap_activate_r); - if (pcap_activate_r != 0) { - SCLogError(SC_ERR_PCAP_ACTIVATE_HANDLE, "Couldn't activate the pcap handler, error %s", pcap_geterr(ptv->pcap_handle)); - SCFree(ptv); - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } else { - ptv->pcap_state = PCAP_STATE_UP; - } - - /* set bpf filter if we have one */ - if (pcapconfig->bpf_filter) { - SCMutexLock(&pcap_bpf_compile_lock); - - ptv->bpf_filter = pcapconfig->bpf_filter; - - if (pcap_compile(ptv->pcap_handle,&ptv->filter,ptv->bpf_filter,1,0) < 0) { - SCLogError(SC_ERR_BPF, "bpf compilation error %s", pcap_geterr(ptv->pcap_handle)); - - SCMutexUnlock(&pcap_bpf_compile_lock); - SCFree(ptv); - pcapconfig->DerefFunc(pcapconfig); - return TM_ECODE_FAILED; - } - - if (pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) { - SCLogError(SC_ERR_BPF, "could not set bpf filter %s", pcap_geterr(ptv->pcap_handle)); - - SCMutexUnlock(&pcap_bpf_compile_lock); - SCFree(ptv); - pcapconfig->DerefFunc(pcapconfig); - return TM_ECODE_FAILED; - } - - SCMutexUnlock(&pcap_bpf_compile_lock); - } - - /* Making it conditional to Linux even if GetIfaceOffloading return 0 - * for non Linux. */ -#ifdef HAVE_LINUX_ETHTOOL_H - if (GetIfaceOffloading(pcapconfig->iface) == 1) { - SCLogWarning(SC_ERR_PCAP_CREATE, - "Using Pcap capture with GRO or LRO activated can lead to " - "capture problems."); - } -#endif /* HAVE_LINUX_ETHTOOL_H */ - - ptv->datalink = pcap_datalink(ptv->pcap_handle); - - pcapconfig->DerefFunc(pcapconfig); - - ptv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets", - ptv->tv); - ptv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops", - ptv->tv); - ptv->capture_kernel_ifdrops = StatsRegisterCounter("capture.kernel_ifdrops", - ptv->tv); - - *data = (void *)ptv; - SCReturnInt(TM_ECODE_OK); -} -#else /* implied LIBPCAP_VERSION_MAJOR == 0 */ -TmEcode ReceivePcapThreadInit(ThreadVars *tv, void *initdata, void **data) -{ - SCEnter(); - PcapIfaceConfig *pcapconfig = initdata; - - if (initdata == NULL) { - SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL"); - SCReturnInt(TM_ECODE_FAILED); - } - - PcapThreadVars *ptv = SCMalloc(sizeof(PcapThreadVars)); - if (unlikely(ptv == NULL)) { - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } - memset(ptv, 0, sizeof(PcapThreadVars)); - - ptv->tv = tv; - - ptv->livedev = LiveGetDevice(pcapconfig->iface); - if (ptv->livedev == NULL) { - SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); - SCReturnInt(TM_ECODE_FAILED); - } - - SCLogInfo("using interface %s", pcapconfig->iface); - if (strlen(pcapconfig->iface) > PCAP_IFACE_NAME_LENGTH) { - SCFree(ptv); - /* Dereference config */ - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } - strlcpy(ptv->iface, pcapconfig->iface, PCAP_IFACE_NAME_LENGTH); - - if (pcapconfig->snaplen == 0) { - /* We try to set snaplen from MTU value */ - ptv->pcap_snaplen = GetIfaceMaxPacketSize(pcapconfig->iface); - /* be conservative with old pcap lib to mimic old tcpdump behavior - when MTU was not available. */ - if (ptv->pcap_snaplen <= 0) - ptv->pcap_snaplen = LIBPCAP_SNAPLEN; - } else { - ptv->pcap_snaplen = pcapconfig->snaplen; - } - - char errbuf[PCAP_ERRBUF_SIZE] = ""; - ptv->pcap_handle = pcap_open_live(ptv->iface, ptv->pcap_snaplen, - LIBPCAP_PROMISC, LIBPCAP_COPYWAIT, errbuf); - if (ptv->pcap_handle == NULL) { - SCLogError(SC_ERR_PCAP_OPEN_LIVE, "Problem creating pcap handler for live mode, error %s", errbuf); - SCFree(ptv); - /* Dereference config */ - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_FAILED); - } - - /* set bpf filter if we have one */ - if (pcapconfig->bpf_filter) { - SCMutexLock(&pcap_bpf_compile_lock); - - ptv->bpf_filter = pcapconfig->bpf_filter; - SCLogInfo("using bpf-filter \"%s\"", ptv->bpf_filter); - - if(pcap_compile(ptv->pcap_handle,&ptv->filter, ptv->bpf_filter,1,0) < 0) { - SCLogError(SC_ERR_BPF,"bpf compilation error %s",pcap_geterr(ptv->pcap_handle)); - - SCMutexUnlock(&pcap_bpf_compile_lock); - SCFree(ptv); - /* Dereference config */ - pcapconfig->DerefFunc(pcapconfig); - return TM_ECODE_FAILED; - } - - if(pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) { - SCLogError(SC_ERR_BPF,"could not set bpf filter %s",pcap_geterr(ptv->pcap_handle)); - - SCMutexUnlock(&pcap_bpf_compile_lock); - SCFree(ptv); - /* Dereference config */ - pcapconfig->DerefFunc(pcapconfig); - return TM_ECODE_FAILED; - } - - SCMutexUnlock(&pcap_bpf_compile_lock); - } - - ptv->datalink = pcap_datalink(ptv->pcap_handle); - - ptv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets", - ptv->tv); - ptv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops", - ptv->tv); - ptv->capture_kernel_ifdrops = StatsRegisterCounter("capture.kernel_ifdrops", - ptv->tv); - - *data = (void *)ptv; - - /* Dereference config */ - pcapconfig->DerefFunc(pcapconfig); - SCReturnInt(TM_ECODE_OK); -} -#endif /* LIBPCAP_VERSION_MAJOR */ - -/** - * \brief This function prints stats to the screen at exit. - * \param tv pointer to ThreadVars - * \param data pointer that gets cast into PcapThreadVars for ptv - */ -void ReceivePcapThreadExitStats(ThreadVars *tv, void *data) -{ - SCEnter(); - PcapThreadVars *ptv = (PcapThreadVars *)data; - struct pcap_stat pcap_s; - - if (pcap_stats(ptv->pcap_handle, &pcap_s) < 0) { - SCLogError(SC_ERR_STAT,"(%s) Failed to get pcap_stats: %s", tv->name, pcap_geterr(ptv->pcap_handle)); - SCLogInfo("(%s) Packets %" PRIu32 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes); - - return; - } else { - SCLogInfo("(%s) Packets %" PRIu32 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes); - - /* these numbers are not entirely accurate as ps_recv contains packets that are still waiting to be processed at exit. - * ps_drop only contains packets dropped by the driver and not any packets dropped by the interface. - * Additionally see http://tracker.icir.org/bro/ticket/18 - * - * Note: ps_recv includes dropped packets and should be considered total. - * Unless we start to look at ps_ifdrop which isn't supported everywhere. - */ - SCLogInfo("(%s) Pcap Total:%" PRIu64 " Recv:%" PRIu64 " Drop:%" PRIu64 " (%02.1f%%).", tv->name, - (uint64_t)pcap_s.ps_recv, (uint64_t)pcap_s.ps_recv - (uint64_t)pcap_s.ps_drop, (uint64_t)pcap_s.ps_drop, - (((float)(uint64_t)pcap_s.ps_drop)/(float)(uint64_t)pcap_s.ps_recv)*100); - - return; - } -} - -/** - * \brief DeInit function closes pcap_handle at exit. - * \param tv pointer to ThreadVars - * \param data pointer that gets cast into PcapThreadVars for ptv - */ -TmEcode ReceivePcapThreadDeinit(ThreadVars *tv, void *data) -{ - PcapThreadVars *ptv = (PcapThreadVars *)data; - - pcap_close(ptv->pcap_handle); - SCReturnInt(TM_ECODE_OK); -} - -/** - * \brief This function passes off to link type decoders. - * - * DecodePcap 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 PcapThreadVars for ptv - * \param pq pointer to the current PacketQueue - */ -TmEcode DecodePcap(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) - return TM_ECODE_OK; - - /* update counters */ - DecodeUpdatePacketCounters(tv, dtv, p); - - /* call the decoder */ - switch(p->datalink) { - case LINKTYPE_LINUX_SLL: - DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); - break; - case LINKTYPE_ETHERNET: - DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq); - break; - case LINKTYPE_PPP: - DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); - break; - case LINKTYPE_RAW: - DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); - break; - case LINKTYPE_NULL: - DecodeNull(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); - break; - default: - SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodePcap", p->datalink); - break; - } - - PacketDecodeFinalize(tv, dtv, p); - - SCReturnInt(TM_ECODE_OK); -} - -TmEcode DecodePcapThreadInit(ThreadVars *tv, void *initdata, void **data) -{ - SCEnter(); - DecodeThreadVars *dtv = NULL; - - dtv = DecodeThreadVarsAlloc(tv); - - if (dtv == NULL) - SCReturnInt(TM_ECODE_FAILED); - - DecodeRegisterPerfCounters(dtv, tv); - -#ifdef __SC_CUDA_SUPPORT__ - if (CudaThreadVarsInit(&dtv->cuda_vars) < 0) - SCReturnInt(TM_ECODE_FAILED); -#endif - - *data = (void *)dtv; - - SCReturnInt(TM_ECODE_OK); -} - -TmEcode DecodePcapThreadDeinit(ThreadVars *tv, void *data) -{ - if (data != NULL) - DecodeThreadVarsFree(tv, data); - SCReturnInt(TM_ECODE_OK); -} - -void PcapTranslateIPToDevice(char *pcap_dev, size_t len) -{ - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_if_t *alldevsp = NULL; - pcap_if_t *devsp = NULL; - - struct addrinfo aiHints; - struct addrinfo *aiList = NULL; - int retVal = 0; - - memset(&aiHints, 0, sizeof(aiHints)); - aiHints.ai_family = AF_UNSPEC; - aiHints.ai_flags = AI_NUMERICHOST; - - /* try to translate IP */ - if ((retVal = getaddrinfo(pcap_dev, NULL, &aiHints, &aiList)) != 0) { - return; - } - - if (pcap_findalldevs(&alldevsp, errbuf)) { - freeaddrinfo(aiList); - return; - } - - for (devsp = alldevsp; devsp ; devsp = devsp->next) { - pcap_addr_t *ip = NULL; - - for (ip = devsp->addresses; ip ; ip = ip->next) { - - if (aiList->ai_family != ip->addr->sa_family) { - continue; - } - - if (ip->addr->sa_family == AF_INET) { - if (memcmp(&((struct sockaddr_in*)aiList->ai_addr)->sin_addr, &((struct sockaddr_in*)ip->addr)->sin_addr, sizeof(struct in_addr))) { - continue; - } - } else if (ip->addr->sa_family == AF_INET6) { - if (memcmp(&((struct sockaddr_in6*)aiList->ai_addr)->sin6_addr, &((struct sockaddr_in6*)ip->addr)->sin6_addr, sizeof(struct in6_addr))) { - continue; - } - } else { - continue; - } - - freeaddrinfo(aiList); - - memset(pcap_dev, 0, len); - strlcpy(pcap_dev, devsp->name, len); - - pcap_freealldevs(alldevsp); - return; - } - } - - freeaddrinfo(aiList); - - pcap_freealldevs(alldevsp); -} - -/* eof */ - |