Ejemplo n.º 1
0
/**
 *  \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;
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
/**
 * \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);
}
Ejemplo n.º 4
0
/**
 * \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 {
Ejemplo n.º 5
0
/**
 * \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 {
Ejemplo n.º 6
0
    /* 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);
}