static int file_read(FileImpl* impl) { int n = read(impl->fid, impl->buf, impl->snaplen); if ( !n ) { if ( !impl->eof ) { impl->eof = 1; return 1; // <= zero won't make it :( } return DAQ_READFILE_EOF; } if ( n < 0 ) { if (errno != EINTR) { char error_msg[1024] = {0}; if (strerror_r(errno, error_msg, sizeof(error_msg)) == 0) DPE(impl->error, "%s: can't read from file (%s)\n", DAQ_NAME, error_msg); else DPE(impl->error, "%s: can't read from file: %d\n", DAQ_NAME, errno); } return DAQ_ERROR; } return n; }
static int bind_interface(AFPacket_Context_t *afpc, AFPacketInstance *instance) { struct sockaddr_ll *sll; int err; socklen_t errlen = sizeof(err); /* Bind to the specified device so we only see packets from it. */ sll = &instance->sll; sll->sll_family = AF_PACKET; sll->sll_ifindex = instance->index; sll->sll_protocol = htons(ETH_P_ALL); if (bind(instance->fd, (struct sockaddr *) sll, sizeof(*sll)) == -1) { DPE(afpc->errbuf, "%s: bind(%s): %s\n", __FUNCTION__, instance->name, strerror(errno)); return DAQ_ERROR; } /* Any pending errors, e.g., network is down? */ if (getsockopt(instance->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) || err) { DPE(afpc->errbuf, "%s: getsockopt: %s", __FUNCTION__, strerror(errno)); return DAQ_ERROR; } return DAQ_SUCCESS; }
static int create_ring(AFPacket_Context_t *afpc, AFPacketInstance *instance, AFPacketRing *ring, int optname) { int rc, order; /* Starting with page allocations of order 3, try to allocate an RX ring in the kernel. */ for (order = DEFAULT_ORDER; order >= 0; order--) { if (calculate_layout(afpc, &ring->layout, instance->tp_hdrlen, order)) return DAQ_ERROR; /* Ask the kernel to create the ring. */ rc = setsockopt(instance->fd, SOL_PACKET, optname, (void*) &ring->layout, sizeof(struct tpacket_req)); if (rc) { if (errno == ENOMEM) { if (afpc->debug) printf("%s: Allocation of kernel packet ring failed with order %d, retrying...\n", instance->name, order); continue; } DPE(afpc->errbuf, "%s: Couldn't create kernel ring on packet socket: %s", __FUNCTION__, strerror(errno)); return DAQ_ERROR; } /* Store the total ring size for later. */ ring->size = ring->layout.tp_block_size * ring->layout.tp_block_nr; if (afpc->debug) printf("Created a ring of type %d with total size of %u\n", optname, ring->size); return DAQ_SUCCESS; } /* If we got here, it means we failed allocation on order 0. */ DPE(afpc->errbuf, "%s: Couldn't allocate enough memory for the kernel packet ring!", instance->name); return DAQ_ERROR; }
static int pfring_zc_daq_set_filter(void *handle, const char *filter) { Pfring_Context_t *context = (Pfring_Context_t *) handle; #ifdef ENABLE_BPF if (pcap_compile_nopcap(context->snaplen, /* snaplen_arg */ DLT_EN10MB, /* linktype_arg */ &context->filter, /* program */ filter, /* const char *buf */ 0, /* optimize */ 0 /* mask */ ) == -1) { goto bpf_error; } if (context->filter.bf_insns == NULL) goto bpf_error; context->bpf_filter = 1; return DAQ_SUCCESS; bpf_error: DPE(context->errbuf, "%s: BPF state machine compilation failed!", __FUNCTION__); #else DPE(context->errbuf, "%s: BPF filters not supported!", __FUNCTION__); #endif return DAQ_ERROR; }
static int afpacket_daq_set_filter(void *handle, const char *filter) { AFPacket_Context_t *afpc = (AFPacket_Context_t *) handle; struct sfbpf_program fcode; if (afpc->filter) free(afpc->filter); afpc->filter = strdup(filter); if (!afpc->filter) { DPE(afpc->errbuf, "%s: Couldn't allocate memory for the filter string!", __FUNCTION__); return DAQ_ERROR; } if (sfbpf_compile(afpc->snaplen, DLT_EN10MB, &fcode, afpc->filter, 1, 0) < 0) { DPE(afpc->errbuf, "%s: BPF state machine compilation failed!", __FUNCTION__); return DAQ_ERROR; } sfbpf_freecode(&afpc->fcode); afpc->fcode.bf_len = fcode.bf_len; afpc->fcode.bf_insns = fcode.bf_insns; return DAQ_SUCCESS; }
static int create_rx_ring(AFPacket_Context_t *afpc, AFPacketInstance *instance) { int rc, order; /* Starting with page allocations of order 3, try to allocate an RX ring in the kernel. */ for (order = DEFAULT_ORDER; order >= 0; order--) { if (calculate_layout(afpc, instance, order)) return DAQ_ERROR; /* Ask the kernel to create the ring. */ rc = setsockopt(instance->fd, SOL_PACKET, PACKET_RX_RING, (void*) &instance->layout, sizeof(struct tpacket_req)); if (rc) { if (errno == ENOMEM) { if (afpc->debug) printf("%s: Allocation of kernel packet RX ring failed with order %d, retrying...\n", instance->name, order); continue; } DPE(afpc->errbuf, "%s: Couldn't create kernel RX ring on packet socket: %s", __FUNCTION__, strerror(errno)); return DAQ_ERROR; } return DAQ_SUCCESS; } /* If we got here, it means we failed allocation on order 0. */ DPE(afpc->errbuf, "%s: Couldn't allocate enough memory for the kernel RX ring!", instance->name); return DAQ_ERROR; }
static int nfq_daq_acquire ( void* handle, int c, DAQ_Analysis_Func_t callback, void* user) { NfqImpl *impl = (NfqImpl*)handle; int n = 0; fd_set fdset; struct timeval tv; tv.tv_usec = 0; // If c is <= 0, don't limit the packets acquired. However, // impl->count = 0 has a special meaning, so interpret accordingly. impl->count = (c == 0) ? -1 : c; impl->user_data = user; impl->user_func = callback; while ( (impl->count < 0) || (n < impl->count) ) { FD_ZERO(&fdset); FD_SET(impl->sock, &fdset); // set this per call tv.tv_sec = impl->timeout; tv.tv_usec = 0; // at least ipq had a timeout! if ( select(impl->sock+1, &fdset, NULL, NULL, &tv) < 0 ) { if ( errno == EINTR ) break; DPE(impl->error, "%s: select = %s", __FUNCTION__, strerror(errno)); return DAQ_ERROR; } if (FD_ISSET(impl->sock, &fdset)) { int len = recv(impl->sock, impl->buf, MSG_BUF_SIZE, 0); if ( len > 0) { int stat = nfq_handle_packet( impl->nf_handle, (char*)impl->buf, len); impl->stats.hw_packets_received++; if ( stat < 0 ) { DPE(impl->error, "%s: nfq_handle_packet = %s", __FUNCTION__, strerror(errno)); return DAQ_ERROR; } n++; } } } return 0; }
static int start_instance(AFPacket_Context_t *afpc, AFPacketInstance *instance) { struct packet_mreq mr; int arptype; /* Bind the RX ring to this interface. */ if (bind_instance_interface(afpc, instance) != 0) return -1; /* Turn on promiscuous mode for the device. */ memset(&mr, 0, sizeof(mr)); mr.mr_ifindex = instance->index; mr.mr_type = PACKET_MR_PROMISC; if (setsockopt(instance->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) { DPE(afpc->errbuf, "%s: setsockopt: %s", __FUNCTION__, strerror(errno)); return -1; } /* Get the link-layer type. */ arptype = iface_get_arptype(instance); if (arptype < 0) { DPE(afpc->errbuf, "%s: failed to get interface type for device %s: (%d) %s", __FUNCTION__, instance->name, errno, strerror(errno)); return -1; } if (arptype != ARPHRD_ETHER) { DPE(afpc->errbuf, "%s: invalid interface type for device %s: %d != %d", __FUNCTION__, instance->name, arptype, ARPHRD_ETHER); return -1; } /* Determine which versions of TPACKET the socket supports. */ if (determine_version(afpc, instance) != DAQ_SUCCESS) return -1; /* Request the kernel RX ring from af_packet... */ if (create_ring(afpc, instance, &instance->rx_ring, PACKET_RX_RING) != DAQ_SUCCESS) return -1; /* ...request the kernel TX ring from af_packet if we're in inline mode... */ if (instance->peer && create_ring(afpc, instance, &instance->tx_ring, PACKET_TX_RING) != DAQ_SUCCESS) return -1; /* ...map the memory for the kernel ring(s) into userspace... */ if (mmap_rings(afpc, instance) != DAQ_SUCCESS) return -1; /* ...and, finally, set up a userspace ring buffer to represent the kernel RX ring... */ if (set_up_ring(afpc, instance, &instance->rx_ring) != DAQ_SUCCESS) return -1; /* ...as well as one for the TX ring if we're in inline mode. */ if (instance->peer && set_up_ring(afpc, instance, &instance->tx_ring) != DAQ_SUCCESS) return -1; return 0; }
static int pfring_zc_daq_open(Pfring_Context_t *context, int id) { uint32_t default_net = 0xFFFFFF00; char *device = context->devices[id], *tx_device = context->tx_devices[id]; pfring_zc_queue *q = NULL; if (device == NULL) { DPE(context->errbuf, "pfring_zc_open_device(): device #%d name not found", id); return -1; } if (context->mode == DAQ_MODE_INLINE || (context->mode == DAQ_MODE_PASSIVE && context->ids_bridge)) { q = pfring_zc_open_device(context->cluster, tx_device, tx_only, (context->promisc_flag ? PF_RING_PROMISC : 0)); if (q == NULL) { DPE(context->errbuf, "pfring_zc_open_device(): unable to open device '%s' (TX)", tx_device); return -1; } context->tx_queues[id] = q; #ifdef DAQ_PF_RING_BEST_EFFORT_BOOST context->mq_queues[id] = q; #endif } if (!context->ipc_attach) { q = pfring_zc_open_device(context->cluster, device, rx_only, (context->promisc_flag ? PF_RING_PROMISC : 0) | PF_RING_ZC_DEVICE_SW_TIMESTAMP); if (q == NULL) { DPE(context->errbuf, "pfring_zc_open_device(): unable to open device '%s' (RX)", device); return -1; } } else { q = pfring_zc_ipc_attach_queue(context->cluster_id, context->ipc_queues[id], rx_only); if (q == NULL) { DPE(context->errbuf, "pfring_zc_ipc_attach_queue(): unable to open queue %d from cluster %d (RX)", context->ipc_queues[id], context->cluster_id); return -1; } } context->rx_queues[id] = q; context->netmask = htonl(default_net); return 0; }
static int start_instance(AFPacket_Context_t *afpc, AFPacketInstance *instance) { struct packet_mreq mr; int arptype; /* Bind to the specified device so we only see packets from it. */ if (bind_interface(afpc, instance) != 0) return -1; /* Turn on promiscuous mode for the device. */ memset(&mr, 0, sizeof(mr)); mr.mr_ifindex = instance->index; mr.mr_type = PACKET_MR_PROMISC; if (setsockopt(instance->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) { DPE(afpc->errbuf, "%s: setsockopt: %s", __FUNCTION__, strerror(errno)); return -1; } /* Get the link-layer type. */ arptype = iface_get_arptype(instance); if (arptype < 0) { DPE(afpc->errbuf, "%s: failed to get interface type for device %s: (%d) %s", __FUNCTION__, instance->name, errno, strerror(errno)); return -1; } if (arptype != ARPHRD_ETHER) { DPE(afpc->errbuf, "%s: invalid interface type for device %s: %d != %d", __FUNCTION__, instance->name, arptype, ARPHRD_ETHER); return -1; } /* Determine which versions of TPACKET the socket supports. */ if (determine_version(afpc, instance) != DAQ_SUCCESS) return -1; if (afpc->debug) { printf("Version: %u\n", instance->tp_version); printf("Header Length: %u\n", instance->tp_hdrlen); } if (create_rx_ring(afpc, instance) != DAQ_SUCCESS) return -1; if (set_up_rx_ring(afpc, instance) != DAQ_SUCCESS) return -1; return 0; }
static AFPacketInstance *create_instance(AFPacket_Context_t *afpc, const char *device) { AFPacketInstance *instance = NULL; instance = calloc(1, sizeof(AFPacketInstance)); if (!instance) { DPE(afpc->errbuf, "%s: Could not allocate a new instance structure.", __FUNCTION__); goto err; } instance->buffer = MAP_FAILED; if ((instance->name = strdup(device)) == NULL) { DPE(afpc->errbuf, "%s: Could not allocate a copy of the device name.", __FUNCTION__); goto err;; } /* Open the PF_PACKET raw socket to receive all network traffic completely unmodified. */ instance->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (instance->fd == -1) { DPE(afpc->errbuf, "%s: Could not open the PF_PACKET socket: %s", __FUNCTION__, strerror(errno)); goto err; } /* #ifdef SO_BROADCAST tmp = 1; if (setsockopt(instance->fd, SOL_SOCKET, SO_BROADCAST, &tmp, sizeof(tmp)) < 0) { fprintf(stderr, "init_af_packet: failed to set broadcast for device %s", instance->name); rval = -8; goto bail; } #endif */ /* Find the device index of the specified interface. */ instance->index = find_device_index(instance, instance->name); if (instance->index == -1) { DPE(afpc->errbuf, "%s: Could not find index for device %s", __FUNCTION__, instance->name); goto err; } return instance; err: destroy_instance(instance); return NULL; }
static int set_up_ring(AFPacket_Context_t *afpc, AFPacketInstance *instance, AFPacketRing *ring) { unsigned int idx, block, block_offset, frame, frame_offset; /* Allocate a ring to hold packet pointers. */ ring->entries = calloc(ring->layout.tp_frame_nr, sizeof(AFPacketEntry)); if (!ring->entries) { DPE(afpc->errbuf, "%s: Could not allocate ring buffer entries for device %s!", __FUNCTION__, instance->name); return DAQ_ERROR_NOMEM; } /* Set up the buffer entry pointers in the ring. */ idx = 0; for (block = 0; block < ring->layout.tp_block_nr; block++) { block_offset = block * ring->layout.tp_block_size; for (frame = 0; frame < (ring->layout.tp_block_size / ring->layout.tp_frame_size) && idx < ring->layout.tp_frame_nr; frame++) { frame_offset = frame * ring->layout.tp_frame_size; ring->entries[idx].hdr.raw = (uint8_t *) ring->start + block_offset + frame_offset; ring->entries[idx].next = &ring->entries[idx + 1]; idx++; } } /* Make this a circular buffer ... a RING if you will! */ ring->entries[ring->layout.tp_frame_nr - 1].next = &ring->entries[0]; /* Initialize our entry point into the ring as the first buffer entry. */ ring->cursor = &ring->entries[0]; return DAQ_SUCCESS; }
static int file_read(FileImpl* impl) { int n = read(impl->fid, impl->buf, impl->snaplen); if ( !n ) { if ( !impl->eof ) { impl->eof = 1; return 1; // <= zero won't make it :( } return DAQ_READFILE_EOF; } if ( n < 0 ) { if (errno != EINTR) { DPE(impl->error, "%s: can't read from file (%s)\n", DAQ_NAME, strerror(errno)); } return DAQ_ERROR; } return n; }
static int calculate_layout(AFPacket_Context_t *afpc, AFPacketInstance *instance, int order) { /* Calculate the frame size and minimum block size required. */ instance->layout.tp_frame_size = TPACKET_ALIGN(afpc->snaplen + TPACKET_ALIGN(TPACKET_ALIGN(instance->tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN); instance->layout.tp_block_size = getpagesize() << order; while (instance->layout.tp_block_size < instance->layout.tp_frame_size) instance->layout.tp_block_size <<= 1; instance->frames_per_block = instance->layout.tp_block_size / instance->layout.tp_frame_size; if (instance->frames_per_block == 0) { DPE(afpc->errbuf, "%s: Invalid frames per block (%u/%u) for %s", __FUNCTION__, instance->layout.tp_block_size, instance->layout.tp_frame_size, afpc->device); return DAQ_ERROR; } /* Find the total number of frames required to amount to the requested per-interface memory. Then find the number of blocks required to hold those packet buffer frames. */ instance->layout.tp_frame_nr = afpc->size / instance->layout.tp_frame_size; instance->layout.tp_block_nr = instance->layout.tp_frame_nr / instance->frames_per_block; /* afpc->layout.tp_frame_nr is requested to match frames_per_block*n_blocks */ instance->layout.tp_frame_nr = instance->layout.tp_block_nr * instance->frames_per_block; if (afpc->debug) { printf("AFPacket Layout:\n"); printf(" Frame Size: %u\n", instance->layout.tp_frame_size); printf(" Frames: %u\n", instance->layout.tp_frame_nr); printf(" Block Size: %u (Order %d)\n", instance->layout.tp_block_size, order); printf(" Blocks: %u\n", instance->layout.tp_block_nr); } return DAQ_SUCCESS; }
static int update_hw_stats(Pfring_Context_t *context) { pfring_stat ps; int i; for (i = 0; i < context->num_devices; i++) if (context->ring_handles[i] == NULL) /* daq stopped - using last available stats */ return DAQ_SUCCESS; context->stats.hw_packets_received = 0; context->stats.hw_packets_dropped = 0; for (i = 0; i < context->num_devices; i++) { memset(&ps, 0, sizeof(pfring_stat)); if(pfring_stats(context->ring_handles[i], &ps) < 0) { DPE(context->errbuf, "%s: pfring_stats error [ring_idx = %d]", __FUNCTION__, i); return DAQ_ERROR; } context->stats.hw_packets_received += (ps.recv - context->base_recv[i]); context->stats.hw_packets_dropped += (ps.drop - context->base_drop[i]); } return DAQ_SUCCESS; }
static int hext_read(FileImpl* impl) { int n = 0; while ( impl->line[0] || fgets(impl->line, sizeof(impl->line), impl->fyle) ) { if ( (n = parse(impl)) ) break; } if ( !n ) n = flush(impl); if ( !n ) { if ( (impl->dlt == DLT_USER) && !impl->eof ) { impl->eof = 1; return 1; // <= zero won't make it :( } return DAQ_READFILE_EOF; } if ( n < 0 ) { if (errno != EINTR) { DPE(impl->error, "%s: can't read from file (%s)\n", DAQ_NAME, strerror(errno)); } return DAQ_ERROR; } return n; }
static int afpacket_daq_inject(void *handle, const DAQ_PktHdr_t *hdr, const uint8_t *packet_data, uint32_t len, int reverse) { AFPacket_Context_t *afpc = (AFPacket_Context_t *) handle; AFPacketInstance *instance; AFPacketEntry *entry; /* Find the instance that the packet was received on. */ for (instance = afpc->instances; instance; instance = instance->next) { if (instance->index == hdr->ingress_index) break; } if (!instance || (!reverse && !(instance = instance->peer))) return DAQ_ERROR; entry = instance->tx_ring.cursor; if (entry->hdr.h2->tp_status == TP_STATUS_AVAILABLE) { memcpy(entry->hdr.raw + TPACKET_ALIGN(instance->tp_hdrlen), packet_data, len); entry->hdr.h2->tp_len = len; entry->hdr.h2->tp_status = TP_STATUS_SEND_REQUEST; instance->tx_ring.cursor = entry->next; if (send(instance->fd, NULL, 0, 0) < 0) { DPE(afpc->errbuf, "%s: Error sending packet: %s (%d)", __FUNCTION__, strerror(errno), errno); return DAQ_ERROR; } afpc->stats.packets_injected++; } return DAQ_SUCCESS; }
static int pfring_daq_set_filter(void *handle, const char *filter) { Pfring_Context_t *context = (Pfring_Context_t *) handle; int ret, i; struct sfbpf_program fcode; if(context->ring_handles[DAQ_PF_RING_PASSIVE_DEV_IDX]) { if(sfbpf_compile(context->snaplen, DLT_EN10MB, &fcode, filter, 0 /* 1: optimize */, htonl(context->netmask)) < 0) { DPE(context->errbuf, "%s: BPF state machine compilation failed!", __FUNCTION__); return DAQ_ERROR; } ret = DAQ_SUCCESS; for (i = 0; i < context->num_devices; i++) { if(setsockopt(pfring_get_selectable_fd(context->ring_handles[i]), 0, SO_ATTACH_FILTER, &fcode, sizeof(fcode)) != 0) { ret = DAQ_ERROR; } } sfbpf_freecode(&fcode); } else { /* Just check if the filter is valid */ if(sfbpf_compile(context->snaplen, DLT_EN10MB, &fcode, filter, 0 /* 1: optimize */, 0 /* netmask */) < 0) { DPE(context->errbuf, "%s: BPF state machine compilation failed!", __FUNCTION__); return DAQ_ERROR; } ret = DAQ_SUCCESS; if(context->filter_string) free(context->filter_string); context->filter_string = strdup(filter); if(!context->filter_string) { DPE(context->errbuf, "%s: Couldn't allocate memory for the filter string!", __FUNCTION__); ret = DAQ_ERROR; } sfbpf_freecode(&fcode); } return ret; }
static void pfring_zc_daq_set_errbuf(void *handle, const char *string) { Pfring_Context_t *context =(Pfring_Context_t *) handle; if (!string) return; DPE(context->errbuf, "%s", string); }
static void afpacket_daq_set_errbuf(void *handle, const char *string) { AFPacket_Context_t *afpc = (AFPacket_Context_t *) handle; if (!string) return; DPE(afpc->errbuf, "%s", string); }
static int set_up_rx_ring(AFPacket_Context_t *afpc, AFPacketInstance *instance) { unsigned idx, block, frame, ringsize; /* Memory map the RX ring. */ ringsize = instance->layout.tp_block_nr * instance->layout.tp_block_size; instance->buffer = mmap(0, ringsize, PROT_READ | PROT_WRITE, MAP_SHARED, instance->fd, 0); if (instance->buffer == MAP_FAILED) { DPE(afpc->errbuf, "%s: Couldn't MMAP the RX ring: %s", __FUNCTION__, strerror(errno)); /* Destroy the kernel RX ring on error. */ destroy_rx_ring(instance); return DAQ_ERROR; } /* Allocate a ring to hold packet pointers. */ instance->ring = calloc(instance->layout.tp_frame_nr, sizeof(AFPacketEntry)); if (!instance->ring) { DPE(afpc->errbuf, "%s: Could not allocate entry ring for device %s", __FUNCTION__, instance->name); destroy_rx_ring(instance); return DAQ_ERROR_NOMEM; } /* Set up the buffer entry pointers in the ring. */ idx = 0; for (block = 0; block < instance->layout.tp_block_nr; block++) { for (frame = 0; frame < instance->frames_per_block; frame++) { instance->ring[idx].begin = (uint8_t *) instance->buffer + (block * instance->layout.tp_block_size) + (frame * instance->layout.tp_frame_size); instance->ring[idx].hdr.raw = instance->ring[idx].begin; instance->ring[idx].next = &instance->ring[idx + 1]; idx++; } } /* Make this a circular buffer ... a RING if you will! */ instance->ring[instance->layout.tp_frame_nr - 1].next = &instance->ring[0]; /* Initialize our entry point into the ring as the first buffer entry. */ instance->entry = &instance->ring[0]; return DAQ_SUCCESS; }
static int file_setup(FileImpl* impl) { if ( !strcmp(impl->name, "tty") ) { impl->fid = STDIN_FILENO; } else if ( (impl->fid = open(impl->name, O_RDONLY|O_NONBLOCK)) < 0 ) { char error_msg[1024] = {0}; if (strerror_r(errno, error_msg, sizeof(error_msg)) == 0) DPE(impl->error, "%s: can't open file (%s)\n", DAQ_NAME, error_msg); else DPE(impl->error, "%s: can't open file: %d\n", DAQ_NAME, errno); return -1; } impl->start = 1; return 0; }
/* The function below was heavily influenced by LibPCAP's pcap-linux.c. Thanks! */ static int determine_version(AFPacket_Context_t *afpc, AFPacketInstance *instance) { socklen_t len; int val; /* Probe whether kernel supports TPACKET_V2 */ val = TPACKET_V2; len = sizeof(val); if (getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) { DPE(afpc->errbuf, "Couldn't retrieve TPACKET_V2 header length: %s", strerror(errno)); return -1; } instance->tp_hdrlen = val; /* Tell the kernel to use TPACKET_V2 */ val = TPACKET_V2; if (setsockopt(instance->fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)) < 0) { DPE(afpc->errbuf, "Couldn't activate TPACKET_V2 on packet socket: %s", strerror(errno)); return -1; } instance->tp_version = TPACKET_V2; /* Reserve space for VLAN tag reconstruction */ val = VLAN_TAG_LEN; if (setsockopt(instance->fd, SOL_PACKET, PACKET_RESERVE, &val, sizeof(val)) < 0) { DPE(afpc->errbuf, "Couldn't set up a %d-byte reservation packet socket: %s", val, strerror(errno)); return -1; } if (afpc->debug) { printf("Version: %u\n", instance->tp_version); printf("Header Length: %u\n", instance->tp_hdrlen); } return DAQ_SUCCESS; }
static void endace_daq_set_errbuf(void *handle, const char *string) { EndaceDAGCtx_t *ctx = (EndaceDAGCtx_t *) handle; if (!ctx) { return; } if (!string) { return; } DPE(ctx->errbuf, "%s", string); }
static int daq_nfq_callback( struct nfq_q_handle* qh, struct nfgenmsg* nfmsg, struct nfq_data* nfad, void* data) { NfqImpl *impl = (NfqImpl*)data; struct nfqnl_msg_packet_hdr* ph = nfq_get_msg_packet_hdr(nfad); DAQ_Verdict verdict; DAQ_PktHdr_t hdr; uint8_t* pkt; int nf_verdict; uint32_t data_len; if ( impl->state != DAQ_STATE_STARTED ) return -1; if ( !ph || SetPktHdr(impl, nfad, &hdr, &pkt) ) { DPE(impl->error, "%s: can't setup packet header", __FUNCTION__); return -1; } if ( impl->fcode.bf_insns && sfbpf_filter(impl->fcode.bf_insns, pkt, hdr.caplen, hdr.caplen) == 0 ) { verdict = DAQ_VERDICT_PASS; impl->stats.packets_filtered++; } else { verdict = impl->user_func(impl->user_data, &hdr, pkt); if ( verdict >= MAX_DAQ_VERDICT ) verdict = DAQ_VERDICT_BLOCK; impl->stats.verdicts[verdict]++; impl->stats.packets_received++; } nf_verdict = ( impl->passive || s_fwd[verdict] ) ? NF_ACCEPT : NF_DROP; data_len = ( verdict == DAQ_VERDICT_REPLACE ) ? hdr.caplen : 0; nfq_set_verdict( impl->nf_queue, ntohl(ph->packet_id), nf_verdict, data_len, pkt); return 0; }
/* The function below was heavily influenced by LibPCAP's pcap-linux.c. Thanks! */ static int determine_version(AFPacket_Context_t *afpc, AFPacketInstance *instance) { #ifdef HAVE_TPACKET2 socklen_t len; int val; #endif instance->tp_version = TPACKET_V1; instance->tp_hdrlen = sizeof(struct tpacket_hdr); #ifdef HAVE_TPACKET2 /* Probe whether kernel supports TPACKET_V2 */ val = TPACKET_V2; len = sizeof(val); if (getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) { /* Version 2 is not supported, stick with V1. */ if (errno == ENOPROTOOPT) return DAQ_SUCCESS; DPE(afpc->errbuf, "Couldn't retrieve TPACKET_V2 header length: %s", strerror(errno)); return -1; } instance->tp_hdrlen = val; val = TPACKET_V2; if (setsockopt(instance->fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)) < 0) { DPE(afpc->errbuf, "Couldn't activate TPACKET_V2 on packet socket: %s", strerror(errno)); return -1; } instance->tp_version = TPACKET_V2; #endif /* HAVE_TPACKET2 */ return DAQ_SUCCESS; }
static int file_setup(FileImpl* impl) { if ( !strcmp(impl->name, "tty") ) { impl->fid = STDIN_FILENO; } else if ( (impl->fid = open(impl->name, O_RDONLY|O_NONBLOCK)) < 0 ) { DPE(impl->error, "%s: can't open file (%s)\n", DAQ_NAME, strerror(errno)); return -1; } impl->start = 1; return 0; }
static int pfring_zc_daq_send_packet(Pfring_Context_t *context, pfring_zc_queue *txq, u_int pkt_len) { int rc; if (txq == NULL) return DAQ_ERROR; rc = pfring_zc_send_pkt(txq, &context->buffer, 1 /* flush packet */); if (rc < 0) { DPE(context->errbuf, "%s", "pfring_zc_send_pkt() error"); return DAQ_ERROR; } context->stats.packets_injected++; return DAQ_SUCCESS; }
static int mmap_rings(AFPacket_Context_t *afpc, AFPacketInstance *instance) { unsigned int ringsize; /* Map the ring into userspace. */ ringsize = instance->rx_ring.size + instance->tx_ring.size; instance->buffer = mmap(0, ringsize, PROT_READ | PROT_WRITE, MAP_SHARED, instance->fd, 0); if (instance->buffer == MAP_FAILED) { DPE(afpc->errbuf, "%s: Could not MMAP the ring: %s", __FUNCTION__, strerror(errno)); return DAQ_ERROR; } instance->rx_ring.start = instance->buffer; instance->tx_ring.start = (uint8_t *) instance->buffer + instance->tx_ring.size; return DAQ_SUCCESS; }
static int pcaprr_daq_inject(void *handle, const DAQ_PktHdr_t *hdr, const uint8_t *packet_data, uint32_t len, int reverse) { Pcaprr_Context_t *context = (Pcaprr_Context_t *) handle; int i; pcap_t *thandle; for (i = 0 ; i < context->handle_count ; i++) { thandle = context->handle[i]; if (pcap_inject(thandle, packet_data, len) < 0) { DPE(context->errbuf, "%s", pcap_geterr(thandle)); return DAQ_ERROR; } } context->stats.packets_injected++; return DAQ_SUCCESS; }