Signed-off-by: Vitezslav Samel vitezslav@samel.cz --- Makefile | 2 + src/capt-mmap-v2.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ src/capt-mmap-v2.h | 6 ++ src/capt.c | 5 ++ src/iptraf-ng-compat.h | 1 + 5 files changed, 161 insertions(+) create mode 100644 src/capt-mmap-v2.c create mode 100644 src/capt-mmap-v2.h
diff --git a/Makefile b/Makefile index 71439a7..7326c3b 100644 --- a/Makefile +++ b/Makefile @@ -120,6 +120,7 @@ iptraf-h += src/built-in.h iptraf-h += src/sockaddr.h iptraf-h += src/capt.h iptraf-h += src/capt-recvmsg.h +iptraf-h += src/capt-mmap-v2.h
iptraf-o += src/tui/input.o iptraf-o += src/tui/labels.o @@ -164,6 +165,7 @@ iptraf-o += src/capture-pkt.o iptraf-o += src/sockaddr.o iptraf-o += src/capt.o iptraf-o += src/capt-recvmsg.o +iptraf-o += src/capt-mmap-v2.o
rvnamed-o += src/rvnamed.o rvnamed-o += src/getpath.o diff --git a/src/capt-mmap-v2.c b/src/capt-mmap-v2.c new file mode 100644 index 0000000..ebbc125 --- /dev/null +++ b/src/capt-mmap-v2.c @@ -0,0 +1,147 @@ +/* For terms of usage/redistribution/modification see the LICENSE file */ +/* For authors and contributors see the AUTHORS file */ + +#include "iptraf-ng-compat.h" + +#include "packet.h" +#include "capt.h" + +struct capt_data_mmap_v2 { + void *mmap; + size_t mmap_size; + struct tpacket2_hdr **hdr; + struct sockaddr_ll **sll; + unsigned int lastslot; + unsigned int slot; +}; + +#define FRAMES 512 + +static unsigned int capt_mmap_find_filled_slot(struct capt_data_mmap_v2 *data) +{ + for (unsigned int i = data->lastslot; i < data->lastslot + FRAMES; i++) { + unsigned int slot = i >= FRAMES ? i - FRAMES : i; + + if (data->hdr[slot]->tp_status & TP_STATUS_USER) + return slot; + } + return FRAMES; +} + +static unsigned int capt_have_packet_mmap_v2(struct capt *capt) +{ + struct capt_data_mmap_v2 *data = capt->priv; + + return capt_mmap_find_filled_slot(data) != FRAMES; +} + +static int capt_get_packet_mmap_v2(struct capt *capt, struct pkt_hdr *pkt) +{ + struct capt_data_mmap_v2 *data = capt->priv; + int ss = 0; + + unsigned int slot = capt_mmap_find_filled_slot(data); + if (slot < FRAMES) { + struct tpacket2_hdr *hdr = data->hdr[slot]; + struct sockaddr_ll *sll = data->sll[slot]; + + pkt->pkt_buf = (char *)hdr + hdr->tp_mac; + pkt->pkt_payload = NULL; + pkt->pkt_caplen = hdr->tp_snaplen; + pkt->pkt_len = hdr->tp_len; + pkt->from = sll; + pkt->pkt_protocol = ntohs(sll->sll_protocol); + + data->slot = slot; + ss = hdr->tp_len; + } + return ss; +} + +static int capt_put_packet_mmap_v2(struct capt *capt, struct pkt_hdr *pkt __unused) +{ + struct capt_data_mmap_v2 *data = capt->priv; + + /* hand out processed slot to kernel */ + if (data->slot < FRAMES) { + data->hdr[data->slot]->tp_status = TP_STATUS_KERNEL; + data->lastslot = data->slot; + } else + data->slot = FRAMES; + + return 0; +} + +static void capt_cleanup_mmap_v2(struct capt *capt) +{ + struct capt_data_mmap_v2 *data = capt->priv; + + free(data->sll); + data->sll = NULL; + + free(data->hdr); + data->hdr = NULL; + + munmap(data->mmap, data->mmap_size); + data->mmap = NULL; + data->mmap_size = 0; + + free(capt->priv); + capt->priv = NULL; +} + +int capt_setup_mmap_v2(struct capt *capt) +{ + int version = TPACKET_V2; + if (setsockopt(capt->fd, SOL_PACKET, PACKET_VERSION, &version, sizeof(version)) != 0) + return -1; + + int hdrlen = version; + socklen_t socklen = sizeof(hdrlen); + if (getsockopt(capt->fd, SOL_PACKET, PACKET_HDRLEN, &hdrlen, &socklen) != 0) + return -1; + + /* computed not exactly, but almost there */ + size_t frame_size = TPACKET_ALIGN(hdrlen) + + TPACKET_ALIGN(sizeof(struct sockaddr_ll)) + + TPACKET_ALIGN(MAX_PACKET_SIZE); + + struct tpacket_req req; + + req.tp_block_nr = 1; + req.tp_frame_nr = FRAMES; + /* frame_size must be a multiple of TPACKET_ALIGNMENT */ + req.tp_frame_size = frame_size; + /* block_size must be a multiple of PAGE_SIZE */ + /* TODO: check for this condition (incidently we are OK now) */ + req.tp_block_size = req.tp_frame_nr * req.tp_frame_size; + + if(setsockopt(capt->fd, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)) != 0) + return -1; + + size_t size = req.tp_block_size * req.tp_block_nr; + void *map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, capt->fd, 0); + if (map == MAP_FAILED) + return -1; + + struct capt_data_mmap_v2 *data = xmallocz(sizeof(struct capt_data_mmap_v2)); + + data->mmap = map; + data->mmap_size = size; + data->hdr = xmallocz(FRAMES * sizeof(*data->hdr)); + data->sll = xmallocz(FRAMES * sizeof(*data->sll)); + for (int i = 0; i < FRAMES; i++) { + data->hdr[i] = (struct tpacket2_hdr *)((char *)map + i * frame_size); + data->sll[i] = (struct sockaddr_ll *)((char *)data->hdr[i] + TPACKET_ALIGN(hdrlen)); + } + data->lastslot = 0; + data->slot = FRAMES; + + capt->priv = data; + capt->have_packet = capt_have_packet_mmap_v2; + capt->get_packet = capt_get_packet_mmap_v2; + capt->put_packet = capt_put_packet_mmap_v2; + capt->cleanup = capt_cleanup_mmap_v2; + + return 0; /* All O.K. */ +} diff --git a/src/capt-mmap-v2.h b/src/capt-mmap-v2.h new file mode 100644 index 0000000..daa92e7 --- /dev/null +++ b/src/capt-mmap-v2.h @@ -0,0 +1,6 @@ +#ifndef IPTRAF_NG_CAPT_MMAP_V2_H +#define IPTRAF_NG_CAPT_MMAP_V2_H + +int capt_setup_mmap_v2(struct capt *capt); + +#endif /* IPTRAF_NG_CAPT_MMAP_V2_H */ diff --git a/src/capt.c b/src/capt.c index b7a75ec..f704e13 100644 --- a/src/capt.c +++ b/src/capt.c @@ -11,6 +11,7 @@ #ifdef USE_RECVMMSG #include "capt-recvmmsg.h" #endif +#include "capt-mmap-v2.h"
static int capt_set_recv_timeout(int fd, unsigned int msec) { @@ -48,6 +49,10 @@ int capt_init(struct capt *capt, char *ifname) if (capt_set_recv_timeout(capt->fd, 250) == -1) goto out;
+ /* try packet mmap() TPACKET_V2 */ + if (capt_setup_mmap_v2(capt) == 0) + return 0; + #ifdef USE_RECVMMSG /* try packet recvmmsg() */ if (capt_setup_recvmmsg(capt) == 0) diff --git a/src/iptraf-ng-compat.h b/src/iptraf-ng-compat.h index aaa2807..8fe5154 100644 --- a/src/iptraf-ng-compat.h +++ b/src/iptraf-ng-compat.h @@ -26,6 +26,7 @@ #include <sys/ioctl.h> #include <sys/wait.h> #include <sys/un.h> +#include <sys/mman.h>
#include <netinet/in.h> #include <netinet/udp.h>