offline pcap reading working
[netsniff-ng.git] / src / rx_ring.c
blobf99b7776f865b79f90efb5831f4ecb9b73d50d81
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Subject to the GPL.
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <sys/mman.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <arpa/inet.h>
16 #include <linux/if_ether.h>
18 #include "xmalloc.h"
19 #include "die.h"
20 #include "rx_ring.h"
22 void destroy_rx_ring(int sock, struct ring *ring)
24 memset(&ring->layout, 0, sizeof(ring->layout));
25 setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->layout,
26 sizeof(ring->layout));
28 munmap(ring->mm_space, ring->mm_len);
29 ring->mm_len = 0;
31 xfree(ring->frames);
34 void setup_rx_ring_layout(int sock, struct ring *ring, unsigned int size)
37 * FIXME: We currently have 2048 Byte per frame. Frames need to
38 * fit exactly into blocks. Blocks can only be a multiple of the
39 * systems page size. What do we do with jumbo frames?
41 memset(&ring->layout, 0, sizeof(ring->layout));
42 ring->layout.tp_block_size = getpagesize() << 2;
43 ring->layout.tp_frame_size = TPACKET_ALIGNMENT << 7;
44 ring->layout.tp_block_nr = size / ring->layout.tp_block_size;
45 ring->layout.tp_frame_nr = ring->layout.tp_block_size /
46 ring->layout.tp_frame_size *
47 ring->layout.tp_block_nr;
50 void create_rx_ring(int sock, struct ring *ring)
52 int ret;
53 retry:
54 ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->layout,
55 sizeof(ring->layout));
56 if (errno == ENOMEM && ring->layout.tp_block_nr > 1) {
57 ring->layout.tp_block_nr >>= 1;
58 ring->layout.tp_frame_nr = ring->layout.tp_block_size /
59 ring->layout.tp_frame_size *
60 ring->layout.tp_block_nr;
61 goto retry;
64 if (ret < 0)
65 error_and_die(EXIT_FAILURE, "Cannot allocate RX_RING!\n");
67 ring->mm_len = ring->layout.tp_block_size * ring->layout.tp_block_nr;
69 printf("RX: %.2f MB, %u Frames each %u Byte allocated\n",
70 1.f * ring->mm_len / (1 << 20),
71 ring->layout.tp_frame_nr, ring->layout.tp_frame_size);
74 void mmap_rx_ring(int sock, struct ring *ring)
76 ring->mm_space = mmap(0, ring->mm_len, PROT_READ | PROT_WRITE,
77 MAP_SHARED, sock, 0);
78 if (ring->mm_space == MAP_FAILED) {
79 destroy_rx_ring(sock, ring);
80 error_and_die(EXIT_FAILURE, "Cannot mmap RX_RING!\n");
84 void alloc_rx_ring_frames(struct ring *ring)
86 int i;
88 ring->frames = xzmalloc(ring->layout.tp_frame_nr *
89 sizeof(*ring->frames));
91 for (i = 0; i < ring->layout.tp_frame_nr; ++i) {
92 ring->frames[i].iov_len = ring->layout.tp_frame_size;
93 ring->frames[i].iov_base = ring->mm_space +
94 (i * ring->layout.tp_frame_size);
98 void bind_rx_ring(int sock, struct ring *ring, int ifindex)
101 * The RX_RING registers itself to the networking stack with
102 * dev_add_pack(), so we have one single RX_RING for all devs
103 * otherwise you'll get the packet twice.
105 memset(&ring->s_ll, 0, sizeof(ring->s_ll));
106 ring->s_ll.sll_family = AF_PACKET;
107 ring->s_ll.sll_protocol = htons(ETH_P_ALL);
108 ring->s_ll.sll_ifindex = ifindex; /* Take 0 for "any"-device */
109 ring->s_ll.sll_hatype = 0;
110 ring->s_ll.sll_halen = 0;
111 ring->s_ll.sll_pkttype = 0;
113 int ret = bind(sock, (struct sockaddr *) &ring->s_ll,
114 sizeof(ring->s_ll));
115 if (ret < 0) {
116 destroy_rx_ring(sock, ring);
117 error_and_die(EXIT_FAILURE, "Cannot bind RX_RING!\n");