/** * \brief Add a single Netfilter queue * * \param string with the queue number * * \retval 0 on success. * \retval -1 on failure. */ int NFQRegisterQueue(const uint16_t number) { NFQThreadVars *ntv = NULL; NFQQueueVars *nq = NULL; char queue[10] = { 0 }; static bool many_queues_warned = false; uint16_t num_cpus = UtilCpuGetNumProcessorsOnline(); if (g_nfq_t == NULL || g_nfq_q == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "NFQ context is not initialized"); return -1; } SCMutexLock(&nfq_init_lock); if (!many_queues_warned && (receive_queue_num >= num_cpus)) { SCLogWarning(SC_WARN_UNCOMMON, "using more Netfilter queues than %hu available CPU core(s) " "may degrade performance", num_cpus); many_queues_warned = true; } if (receive_queue_num >= NFQ_MAX_QUEUE) { SCLogError(SC_ERR_INVALID_ARGUMENT, "can not register more than %d Netfilter queues", NFQ_MAX_QUEUE); SCMutexUnlock(&nfq_init_lock); return -1; } ntv = &g_nfq_t[receive_queue_num]; ntv->nfq_index = receive_queue_num; nq = &g_nfq_q[receive_queue_num]; nq->queue_num = number; receive_queue_num++; SCMutexUnlock(&nfq_init_lock); snprintf(queue, sizeof(queue) - 1, "NFQ#%hu", number); LiveRegisterDevice(queue); ntv->livedev = LiveGetDevice(queue); if (ntv->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); return -1; } SCLogDebug("Queue %d registered.", number); return 0; }
/** * \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. */ TmEcode ReceivePcapThreadInit(ThreadVars *tv, const void *initdata, void **data) { SCEnter(); PcapIfaceConfig *pcapconfig = (PcapIfaceConfig *)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); if (LiveGetOffload() == 0) { (void)GetIfaceOffloading((char *)pcapconfig->iface, 1, 1); } else { DisableIfaceOffloading(ptv->livedev, 1, 1); } 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,(char *)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); } /* no offloading supported at all */ (void)GetIfaceOffloading(pcapconfig->iface, 1, 1); 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); }
/** * \brief Initialize the ERF receiver thread, generate a single * ErfDagThreadVar structure for each thread, this will * contain a DAG file descriptor which is read when the * thread executes. * * \param tv Thread variable to ThreadVars * \param initdata Initial data to the interface passed from the user, * this is processed by the user. * * We assume that we have only a single name for the DAG * interface. * * \param data data pointer gets populated with * */ TmEcode ReceiveErfDagThreadInit(ThreadVars *tv, void *initdata, void **data) { SCEnter(); int stream_count = 0; if (initdata == NULL) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Error: No DAG interface provided."); SCReturnInt(TM_ECODE_FAILED); } ErfDagThreadVars *ewtn = SCMalloc(sizeof(ErfDagThreadVars)); if (unlikely(ewtn == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate memory for ERF DAG thread vars."); exit(EXIT_FAILURE); } memset(ewtn, 0, sizeof(*ewtn)); /* dag_parse_name will return a DAG device name and stream number * to open for this thread. */ if (dag_parse_name(initdata, ewtn->dagname, DAGNAME_BUFSIZE, &ewtn->dagstream) < 0) { SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to parse DAG interface: %s", (char*)initdata); SCFree(ewtn); exit(EXIT_FAILURE); } ewtn->livedev = LiveGetDevice(initdata); if (ewtn->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to get %s live device", (char *)initdata); SCFree(ewtn); SCReturnInt(TM_ECODE_FAILED); } SCLogInfo("Opening DAG: %s on stream: %d for processing", ewtn->dagname, ewtn->dagstream); if ((ewtn->dagfd = dag_open(ewtn->dagname)) < 0) { SCLogError(SC_ERR_ERF_DAG_OPEN_FAILED, "Failed to open DAG: %s", ewtn->dagname); SCFree(ewtn); SCReturnInt(TM_ECODE_FAILED); } /* Check to make sure the card has enough available streams to * support reading from the one specified. */ if ((stream_count = dag_rx_get_stream_count(ewtn->dagfd)) < 0) { SCLogError(SC_ERR_ERF_DAG_OPEN_FAILED, "Failed to open stream: %d, DAG: %s, could not query stream count", ewtn->dagstream, ewtn->dagname); SCFree(ewtn); SCReturnInt(TM_ECODE_FAILED); } /* Check to make sure we have enough rx streams to open the stream * the user is asking for. */ if (ewtn->dagstream > stream_count * 2) { SCLogError(SC_ERR_ERF_DAG_OPEN_FAILED, "Failed to open stream: %d, DAG: %s, insufficient streams: %d", ewtn->dagstream, ewtn->dagname, stream_count); SCFree(ewtn); SCReturnInt(TM_ECODE_FAILED); } /* If we are transmitting into a soft DAG card then set the stream * to act in reverse mode. */ if (0 != (ewtn->dagstream & 0x01)) { /* Setting reverse mode for using with soft dag from daemon side */ if (dag_set_mode(ewtn->dagfd, ewtn->dagstream, DAG_REVERSE_MODE)) { SCLogError(SC_ERR_ERF_DAG_STREAM_OPEN_FAILED, "Failed to set mode to DAG_REVERSE_MODE on stream: %d, DAG: %s", ewtn->dagstream, ewtn->dagname); SCFree(ewtn); SCReturnInt(TM_ECODE_FAILED); } } if (dag_attach_stream(ewtn->dagfd, ewtn->dagstream, 0, 0) < 0) { SCLogError(SC_ERR_ERF_DAG_STREAM_OPEN_FAILED, "Failed to open DAG stream: %d, DAG: %s", ewtn->dagstream, ewtn->dagname); SCFree(ewtn); SCReturnInt(TM_ECODE_FAILED); } if (dag_start_stream(ewtn->dagfd, ewtn->dagstream) < 0) { SCLogError(SC_ERR_ERF_DAG_STREAM_START_FAILED, "Failed to start DAG stream: %d, DAG: %s", ewtn->dagstream, ewtn->dagname); SCFree(ewtn); SCReturnInt(TM_ECODE_FAILED); } SCLogInfo("Attached and started stream: %d on DAG: %s", ewtn->dagstream, ewtn->dagname); /* * Initialise DAG Polling parameters. */ timerclear(&ewtn->maxwait); ewtn->maxwait.tv_usec = MAXWAIT; timerclear(&ewtn->poll); ewtn->poll.tv_usec = POLL_INTERVAL; /* 32kB minimum data to return -- we still restrict the number of * pkts that are processed to a maximum of dag_max_read_packets. */ if (dag_set_stream_poll(ewtn->dagfd, ewtn->dagstream, MINDATA, &(ewtn->maxwait), &(ewtn->poll)) < 0) { SCLogError(SC_ERR_ERF_DAG_STREAM_SET_FAILED, "Failed to set poll parameters for stream: %d, DAG: %s", ewtn->dagstream, ewtn->dagname); SCFree(ewtn); SCReturnInt(TM_ECODE_FAILED); } ewtn->packets = SCPerfTVRegisterCounter("capture.dag_packets", tv, SC_PERF_TYPE_UINT64, "NULL"); ewtn->drops = SCPerfTVRegisterCounter("capture.dag_drops", tv, SC_PERF_TYPE_UINT64, "NULL"); ewtn->tv = tv; *data = (void *)ewtn; SCLogInfo("Starting processing packets from stream: %d on DAG: %s", ewtn->dagstream, ewtn->dagname); SCReturnInt(TM_ECODE_OK); }
/** * \brief Init function for RecievePfring. * * This is a setup function for recieving packets * via libpfring. * * \param tv pointer to ThreadVars * \param initdata pointer to the interface passed from the user * \param data pointer gets populated with PfringThreadVars * \todo add a config option for setting cluster id * \todo Create a general pfring setup function. * \retval TM_ECODE_OK on success * \retval TM_ECODE_FAILED on error */ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { int rc; u_int32_t version = 0; PfringIfaceConfig *pfconf = (PfringIfaceConfig *) initdata; unsigned int opflag; if (pfconf == NULL) return TM_ECODE_FAILED; PfringThreadVars *ptv = SCMalloc(sizeof(PfringThreadVars)); if (unlikely(ptv == NULL)) { pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } memset(ptv, 0, sizeof(PfringThreadVars)); ptv->tv = tv; ptv->threads = 1; ptv->interface = SCStrdup(pfconf->iface); if (unlikely(ptv->interface == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate device string"); SCReturnInt(TM_ECODE_FAILED); } ptv->livedev = LiveGetDevice(pfconf->iface); if (ptv->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); SCReturnInt(TM_ECODE_FAILED); } ptv->checksum_mode = pfconf->checksum_mode; opflag = PF_RING_REENTRANT | PF_RING_PROMISC; if (ptv->checksum_mode == CHECKSUM_VALIDATION_RXONLY) { if (strncmp(ptv->interface, "dna", 3) == 0) { SCLogWarning(SC_ERR_INVALID_VALUE, "Can't use rxonly checksum-checks on DNA interface," " resetting to auto"); ptv->checksum_mode = CHECKSUM_VALIDATION_AUTO; } else { opflag |= PF_RING_LONG_HEADER; } } #ifdef HAVE_PFRING_OPEN_NEW ptv->pd = pfring_open(ptv->interface, (uint32_t)default_packet_size, opflag); #else ptv->pd = pfring_open(ptv->interface, LIBPFRING_PROMISC, (uint32_t)default_packet_size, LIBPFRING_REENTRANT); #endif if (ptv->pd == NULL) { SCLogError(SC_ERR_PF_RING_OPEN,"Failed to open %s: pfring_open error." " Check if %s exists and pf_ring module is loaded.", ptv->interface, ptv->interface); pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } else { pfring_set_application_name(ptv->pd, PROG_NAME); pfring_version(ptv->pd, &version); } /* We only set cluster info if the number of pfring threads is greater than 1 */ ptv->threads = pfconf->threads; ptv->cluster_id = pfconf->cluster_id; if ((ptv->threads == 1) && (strncmp(ptv->interface, "dna", 3) == 0)) { SCLogInfo("DNA interface detected, not adding thread to cluster"); } else { #ifdef HAVE_PFRING_CLUSTER_TYPE ptv->ctype = pfconf->ctype; rc = pfring_set_cluster(ptv->pd, ptv->cluster_id, ptv->ctype); #else rc = pfring_set_cluster(ptv->pd, ptv->cluster_id); #endif /* HAVE_PFRING_CLUSTER_TYPE */ if (rc != 0) { SCLogError(SC_ERR_PF_RING_SET_CLUSTER_FAILED, "pfring_set_cluster " "returned %d for cluster-id: %d", rc, ptv->cluster_id); pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } } if (ptv->threads > 1) { SCLogInfo("(%s) Using PF_RING v.%d.%d.%d, interface %s, cluster-id %d", tv->name, (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF, ptv->interface, ptv->cluster_id); } else {
/** * \brief Init function for RecievePfring. * * This is a setup function for recieving packets * via libpfring. * * \param tv pointer to ThreadVars * \param initdata pointer to the interface passed from the user * \param data pointer gets populated with PfringThreadVars * \todo add a config option for setting cluster id * \todo Create a general pfring setup function. * \retval TM_ECODE_OK on success * \retval TM_ECODE_FAILED on error */ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { int rc; u_int32_t version = 0; PfringIfaceConfig *pfconf = (PfringIfaceConfig *) initdata; unsigned int opflag; char const *active_runmode = RunmodeGetActive(); if (pfconf == NULL) return TM_ECODE_FAILED; PfringThreadVars *ptv = SCMalloc(sizeof(PfringThreadVars)); if (unlikely(ptv == NULL)) { pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } memset(ptv, 0, sizeof(PfringThreadVars)); ptv->tv = tv; ptv->threads = 1; ptv->interface = SCStrdup(pfconf->iface); if (unlikely(ptv->interface == NULL)) { SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate device string"); SCFree(ptv); SCReturnInt(TM_ECODE_FAILED); } ptv->livedev = LiveGetDevice(pfconf->iface); if (ptv->livedev == NULL) { SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device"); SCFree(ptv); SCReturnInt(TM_ECODE_FAILED); } /* enable zero-copy mode for workers runmode */ if (active_runmode && strcmp("workers", active_runmode) == 0) { ptv->flags |= PFRING_FLAGS_ZERO_COPY; SCLogPerf("Enabling zero-copy for %s", ptv->interface); } ptv->checksum_mode = pfconf->checksum_mode; opflag = PF_RING_PROMISC; /* if suri uses VLAN and if we have a recent kernel, we need * to use parsed_pkt to get VLAN info */ if ((! ptv->vlan_disabled) && SCKernelVersionIsAtLeast(3, 0)) { opflag |= PF_RING_LONG_HEADER; } if (ptv->checksum_mode == CHECKSUM_VALIDATION_RXONLY) { if (strncmp(ptv->interface, "dna", 3) == 0) { SCLogWarning(SC_ERR_INVALID_VALUE, "Can't use rxonly checksum-checks on DNA interface," " resetting to auto"); ptv->checksum_mode = CHECKSUM_VALIDATION_AUTO; } else { opflag |= PF_RING_LONG_HEADER; } } ptv->pd = pfring_open(ptv->interface, (uint32_t)default_packet_size, opflag); if (ptv->pd == NULL) { SCLogError(SC_ERR_PF_RING_OPEN,"Failed to open %s: pfring_open error." " Check if %s exists and pf_ring module is loaded.", ptv->interface, ptv->interface); pfconf->DerefFunc(pfconf); SCFree(ptv); return TM_ECODE_FAILED; } pfring_set_application_name(ptv->pd, PROG_NAME); pfring_version(ptv->pd, &version); /* We only set cluster info if the number of pfring threads is greater than 1 */ ptv->threads = pfconf->threads; ptv->cluster_id = pfconf->cluster_id; if ((ptv->threads == 1) && (strncmp(ptv->interface, "dna", 3) == 0)) { SCLogInfo("DNA interface detected, not adding thread to cluster"); } else if (strncmp(ptv->interface, "zc", 2) == 0) { SCLogInfo("ZC interface detected, not adding thread to cluster"); } else { ptv->ctype = pfconf->ctype; rc = pfring_set_cluster(ptv->pd, ptv->cluster_id, ptv->ctype); if (rc != 0) { SCLogError(SC_ERR_PF_RING_SET_CLUSTER_FAILED, "pfring_set_cluster " "returned %d for cluster-id: %d", rc, ptv->cluster_id); if (rc != PF_RING_ERROR_NOT_SUPPORTED || (pfconf->flags & PFRING_CONF_FLAGS_CLUSTER)) { /* cluster is mandatory as explicitly specified in the configuration */ pfconf->DerefFunc(pfconf); return TM_ECODE_FAILED; } } } if (ptv->threads > 1) { SCLogPerf("(%s) Using PF_RING v.%d.%d.%d, interface %s, cluster-id %d", tv->name, (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF, ptv->interface, ptv->cluster_id); } else {
/* no offloading supported at all */ (void)GetIfaceOffloading(pcapconfig->iface, 1, 1); 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"); SCFree(ptv); 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); }