2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Subject to the GPL, version 2.
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <arpa/inet.h>
15 #include <linux/if_ether.h>
22 void destroy_rx_ring(int sock
, struct ring
*ring
)
24 fmemset(&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 fmemset(&ring
->layout
, 0, sizeof(ring
->layout
));
39 ring
->layout
.tp_block_size
= (jumbo_support
?
42 ring
->layout
.tp_frame_size
= (jumbo_support
?
43 TPACKET_ALIGNMENT
<< 12 :
44 TPACKET_ALIGNMENT
<< 7);
45 ring
->layout
.tp_block_nr
= size
/ ring
->layout
.tp_block_size
;
46 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
47 ring
->layout
.tp_frame_size
*
48 ring
->layout
.tp_block_nr
;
50 bug_on(ring
->layout
.tp_block_size
< ring
->layout
.tp_frame_size
);
51 bug_on((ring
->layout
.tp_block_size
% ring
->layout
.tp_frame_size
) != 0);
52 bug_on((ring
->layout
.tp_block_size
% getpagesize()) != 0);
55 void create_rx_ring(int sock
, struct ring
*ring
, int verbose
)
59 set_sockopt_tpacket(sock
);
61 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_RX_RING
, &ring
->layout
,
62 sizeof(ring
->layout
));
63 if (errno
== ENOMEM
&& ring
->layout
.tp_block_nr
> 1) {
64 ring
->layout
.tp_block_nr
>>= 1;
65 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
66 ring
->layout
.tp_frame_size
*
67 ring
->layout
.tp_block_nr
;
72 panic("Cannot allocate RX_RING!\n");
74 ring
->mm_len
= ring
->layout
.tp_block_size
* ring
->layout
.tp_block_nr
;
77 printf("RX: %.2Lf MiB, %u Frames, each %u Byte allocated\n",
78 (long double) ring
->mm_len
/ (1 << 20),
79 ring
->layout
.tp_frame_nr
, ring
->layout
.tp_frame_size
);
83 void mmap_rx_ring(int sock
, struct ring
*ring
)
85 ring
->mm_space
= mmap(0, ring
->mm_len
, PROT_READ
| PROT_WRITE
,
86 MAP_SHARED
| MAP_LOCKED
| MAP_POPULATE
, sock
, 0);
87 if (ring
->mm_space
== MAP_FAILED
) {
88 destroy_rx_ring(sock
, ring
);
89 panic("Cannot mmap RX_RING!\n");
93 void alloc_rx_ring_frames(struct ring
*ring
)
96 size_t len
= ring
->layout
.tp_frame_nr
* sizeof(*ring
->frames
);
98 ring
->frames
= xmalloc_aligned(len
, CO_CACHE_LINE_SIZE
);
99 fmemset(ring
->frames
, 0, len
);
101 for (i
= 0; i
< ring
->layout
.tp_frame_nr
; ++i
) {
102 ring
->frames
[i
].iov_len
= ring
->layout
.tp_frame_size
;
103 ring
->frames
[i
].iov_base
= ring
->mm_space
+
104 (i
* ring
->layout
.tp_frame_size
);
108 void bind_rx_ring(int sock
, struct ring
*ring
, int ifindex
)
112 * The RX_RING registers itself to the networking stack with
113 * dev_add_pack(), so we have one single RX_RING for all devs
114 * otherwise you'll get the packet twice.
116 fmemset(&ring
->s_ll
, 0, sizeof(ring
->s_ll
));
118 ring
->s_ll
.sll_family
= AF_PACKET
;
119 ring
->s_ll
.sll_protocol
= htons(ETH_P_ALL
);
120 ring
->s_ll
.sll_ifindex
= ifindex
;
121 ring
->s_ll
.sll_hatype
= 0;
122 ring
->s_ll
.sll_halen
= 0;
123 ring
->s_ll
.sll_pkttype
= 0;
125 ret
= bind(sock
, (struct sockaddr
*) &ring
->s_ll
, sizeof(ring
->s_ll
));
127 destroy_rx_ring(sock
, ring
);
128 panic("Cannot bind RX_RING!\n");