2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <arpa/inet.h>
16 #include <linux/if_ether.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
);
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
)
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
;
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
,
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
)
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
,
116 destroy_rx_ring(sock
, ring
);
117 error_and_die(EXIT_FAILURE
, "Cannot bind RX_RING!\n");