Exemple #1
0
int packet_new(struct packet_pool* pool, struct pcap_pkthdr* header, const unsigned char* data)
{
	struct packet* ret = NULL;
	pthread_mutex_lock(&pool->free_lock);
	struct list_element_t* e = list_pop_front(pool->free_list);
	pthread_mutex_unlock(&pool->free_lock);

	pool->packets_seen++;
	if (!(pool->packets_seen % 1000000)) {
		msg(MSG_STATS, "Seen: %llu, Used: %llu, Free: %llu", pool->packets_seen, pool->used_list->size, pool->free_list->size);
	}

	if (!e) {
		pool->packets_lost++;
		return -1;
	}
	ret = e->data;

	memcpy(&ret->header, header, sizeof(*header));
	memcpy(ret->data, data, header->caplen);
	uint16_t et = ntohs(ETHERNET(data)->ether_type);
	if (!(et == ETHERTYPE_IP || et == ETHERTYPE_IPV6 || et == ETHERTYPE_VLAN)) {
		ret->is_ip = ret->is_ip6 = 0;
		ret->ip =  NULL;
		ret->ip6 = NULL;
	}

	uint8_t  offset = et == ETHERTYPE_VLAN?4:0; // ethernetheader is shifted by four bytes if vlan is available
	// we don't know whether we received ip or ipv6. So lets try:
	if ((IP(data + offset))->ip_v == 4 || et == ETHERTYPE_IP) {
		ret->is_ip6 = 0;
		ret->is_ip  = 1;
		ret->ip =  IP(ret->data);
		ret->ip6 = NULL;
		//msg(MSG_ERROR, "Found IPv4 packet");
	} else if ((IP(data + offset))->ip_v == 6 || et == ETHERTYPE_IPV6) {
		ret->is_ip6 = 1;
		ret->is_ip  = 0;
		ret->ip = NULL;
		ret->ip6 = IP6(ret->data);
	} else {
		//msg(MSG_ERROR, "Well. Something is weird here!: Ethertype: %d, IP vesrsion: %d", et, (IP(data + offset))->ip_v);
	}
	
	// only handle packets if its connection is still active
	ret->connection = connection_get(ret);
	// TODO: we should discard the packet earlier, at best before copying the packet content
	if (ret->connection && ret->connection->active) {
		pthread_mutex_lock(&pool->used_lock);
		list_push_back(pool->used_list, e);
		pthread_mutex_unlock(&pool->used_lock);
	} else {
		packet_free(pool, ret);
	}

	return 0;
}
Exemple #2
0
static int nfq_daq_initialize (
    const DAQ_Config_t* cfg, void** handle, char* errBuf, size_t errMax)
{
    if(cfg->name && *(cfg->name))
    {
        snprintf(errBuf, errMax, "The nfq DAQ module does not support interface or readback mode!");
        return DAQ_ERROR_INVAL;
    }
    // setup internal stuff
    NfqImpl *impl = calloc(1, sizeof(*impl));

    if ( !impl )
    {
        snprintf(errBuf, errMax, "%s: failed to allocate nfq context\n",
            __FUNCTION__);
        return DAQ_ERROR_NOMEM;
    }

    if ( nfq_daq_get_setup(impl, cfg, errBuf, errMax) != DAQ_SUCCESS )
    {
        nfq_daq_shutdown(impl);
        return DAQ_ERROR;
    }

    if ( (impl->buf = malloc(MSG_BUF_SIZE)) == NULL )
    {
        snprintf(errBuf, errMax, "%s: failed to allocate nfq buffer\n",
            __FUNCTION__);
        nfq_daq_shutdown(impl);
        return DAQ_ERROR_NOMEM;
    }

    // setup input stuff
    // 1. get a new q handle
    if ( !(impl->nf_handle = nfq_open()) )
    {
        snprintf(errBuf, errMax, "%s: failed to get handle for nfq\n",
            __FUNCTION__);
        nfq_daq_shutdown(impl);
        return DAQ_ERROR;
    }

    // 2. now use the new q handle to rip the rug out from other
    //    nfq users / handles?  actually that doesn't seem to
    //    happen which is good, but then why is this *supposed*
    //    to be necessary?  especially since we haven't bound to
    //    a qid yet, and that is exclusive anyway.
    if (
        (IP4(impl) && nfq_unbind_pf(impl->nf_handle, PF_INET) < 0) ||
        (IP6(impl) && nfq_unbind_pf(impl->nf_handle, PF_INET6) < 0) )
    {
        snprintf(errBuf, errMax, "%s: failed to unbind protocols for nfq\n",
            __FUNCTION__);
        //nfq_daq_shutdown(impl);
        //return DAQ_ERROR;
    }

    // 3. select protocols for the q handle
    //    this is necessary but insufficient because we still
    //    must configure iptables externally, eg:
    //
    //    iptables -A OUTPUT -p icmp -j NFQUEUE [--queue-num <#>]
    //    (# defaults to 0).
    //
    // :( iptables rules should be managed automatically to avoid
    //    queueing packets to nowhere or waiting for packets that
    //    will never come.  (ie this bind should take the -p, -s,
    //    etc args you can pass to iptables and create the dang
    //    rule!)
    if (
        (IP4(impl) && nfq_bind_pf(impl->nf_handle, PF_INET) < 0) ||
        (IP6(impl) && nfq_bind_pf(impl->nf_handle, PF_INET6) < 0) )
    {
        snprintf(errBuf, errMax, "%s: failed to bind protocols for nfq\n",
            __FUNCTION__);
        nfq_daq_shutdown(impl);
        return DAQ_ERROR;
    }

    // 4. bind to/allocate the specified nfqueue instance
    //    (this is the puppy specified via iptables as in
    //    above example.)
    //
    // ** there can be at most 1 nf_queue per qid
    if ( !(impl->nf_queue = nfq_create_queue(
        impl->nf_handle, impl->qid, daq_nfq_callback, impl)) )
    {
        snprintf(errBuf, errMax, "%s: nf queue creation failed\n",
            __FUNCTION__);
        nfq_daq_shutdown(impl);
        return DAQ_ERROR;
    }

    // 5. configure copying for maximum overhead
    if ( nfq_set_mode(impl->nf_queue, NFQNL_COPY_PACKET, IP_MAXPACKET) < 0 )
    {
        snprintf(errBuf, errMax, "%s: unable to set packet copy mode\n",
            __FUNCTION__);
        nfq_daq_shutdown(impl);
        return DAQ_ERROR;
    }

    // 6. set queue length (optional)
    if ( impl->qlen > 0 &&
            nfq_set_queue_maxlen(impl->nf_queue, impl->qlen))
    {
        snprintf(errBuf, errMax, "%s: unable to set queue length\n",
                __FUNCTION__);
        nfq_daq_shutdown(impl);
        return DAQ_ERROR;
    }

    // 7. get the q socket descriptor
    //    (after getting not 1 but 2 handles!)
    impl->sock = nfq_fd(impl->nf_handle);

    // setup output stuff
    // we've got 2 handles and a socket descriptor but, incredibly,
    // no way to inject?
    if ( impl->device && strcasecmp(impl->device, "ip") )
    {
        impl->link = eth_open(impl->device);

        if ( !impl->link )
        {
            snprintf(errBuf, errMax, "%s: can't open %s!\n",
                __FUNCTION__, impl->device);
            nfq_daq_shutdown(impl);
            return DAQ_ERROR;
        }
    }
    else
    {
        impl->net = ip_open();

        if ( !impl->net )
        {
            snprintf(errBuf, errMax, "%s: can't open ip!\n", __FUNCTION__);
            nfq_daq_shutdown(impl);
            return DAQ_ERROR;
        }
    }

    impl->state = DAQ_STATE_INITIALIZED;

    *handle = impl;
    return DAQ_SUCCESS;
}
};

const struct ipaddr_str ipaddr_valid_strs[] = {
		{"0.0.0.0", {AF_INET, {IP4(0,0,0,0)}, 0},
				CMDLINE_IPADDR_V4},
		{"0.0.0.0/0", {AF_INET, {IP4(0,0,0,0)}, 0},
				CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
		{"0.0.0.0/24", {AF_INET, {IP4(0,0,0,0)}, 24},
				CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
		{"192.168.1.0/24", {AF_INET, {IP4(192,168,1,0)}, 24},
				CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
		{"012.34.56.78/24", {AF_INET, {IP4(12,34,56,78)}, 24},
				CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
		{"34.56.78.90/1", {AF_INET, {IP4(34,56,78,90)}, 1},
				CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
		{"::", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 0},
					CMDLINE_IPADDR_V6},
		{"::1", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 0},
				CMDLINE_IPADDR_V6},
		{"::1/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 32},
				CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
		{"::/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 32},
					CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
		/* RFC5952 requests that only lowercase should be used */
		{"1234:5678:90ab:cdef:4321:8765:BA09:FEDC", {AF_INET6,
				{IP6(0x1234,0x5678,0x90AB,0xCDEF,0x4321,0x8765,0xBA09,0xFEDC)},
				0},
				CMDLINE_IPADDR_V6},
		{"1234::1234/64", {AF_INET6,
				{IP6(0x1234,0,0,0,0,0,0,0x1234)},
				64},