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; }
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},