2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Copyright 2009, 2010 Emmanuel Roullit.
6 * Subject to the GPL, version 2.
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <arpa/inet.h>
18 #include <linux/if_ether.h>
24 void set_packet_loss_discard(int sock
)
27 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_LOSS
, (void *) &discard
,
30 panic("setsockopt: cannot set packet loss");
33 void destroy_tx_ring(int sock
, struct ring
*ring
)
35 memset(&ring
->layout
, 0, sizeof(ring
->layout
));
36 setsockopt(sock
, SOL_PACKET
, PACKET_TX_RING
, &ring
->layout
,
37 sizeof(ring
->layout
));
38 munmap(ring
->mm_space
, ring
->mm_len
);
43 void setup_tx_ring_layout(int sock
, struct ring
*ring
, unsigned int size
,
46 memset(&ring
->layout
, 0, sizeof(ring
->layout
));
47 ring
->layout
.tp_block_size
= (jumbo_support
?
48 getpagesize() << 4 : getpagesize() << 2);
49 ring
->layout
.tp_frame_size
= (jumbo_support
?
50 TPACKET_ALIGNMENT
<< 12 : TPACKET_ALIGNMENT
<< 7);
51 ring
->layout
.tp_block_nr
= size
/ ring
->layout
.tp_block_size
;
52 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
53 ring
->layout
.tp_frame_size
*
54 ring
->layout
.tp_block_nr
;
56 assert(ring
->layout
.tp_block_size
>= ring
->layout
.tp_frame_size
);
57 assert((ring
->layout
.tp_block_size
% ring
->layout
.tp_frame_size
) == 0);
58 assert((ring
->layout
.tp_block_size
% getpagesize()) == 0);
61 void create_tx_ring(int sock
, struct ring
*ring
)
65 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_TX_RING
, &ring
->layout
,
66 sizeof(ring
->layout
));
67 if (errno
== ENOMEM
&& ring
->layout
.tp_block_nr
> 1) {
68 ring
->layout
.tp_block_nr
>>= 1;
69 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
70 ring
->layout
.tp_frame_size
*
71 ring
->layout
.tp_block_nr
;
75 panic("Cannot allocate TX_RING!\n");
76 ring
->mm_len
= ring
->layout
.tp_block_size
* ring
->layout
.tp_block_nr
;
78 printf("TX: %.2f MB, %u Frames each %u Byte allocated\n",
79 1.f
* ring
->mm_len
/ (1 << 20),
80 ring
->layout
.tp_frame_nr
, ring
->layout
.tp_frame_size
);
83 void mmap_tx_ring(int sock
, struct ring
*ring
)
85 ring
->mm_space
= mmap(0, ring
->mm_len
, PROT_READ
| PROT_WRITE
,
86 MAP_SHARED
| MAP_LOCKED
, sock
, 0);
87 if (ring
->mm_space
== MAP_FAILED
) {
88 destroy_tx_ring(sock
, ring
);
89 panic("Cannot mmap TX_RING!\n");
93 void alloc_tx_ring_frames(struct ring
*ring
)
96 size_t len
= ring
->layout
.tp_frame_nr
* sizeof(*ring
->frames
);
97 ring
->frames
= xmalloc_aligned(len
, 64);
98 memset(ring
->frames
, 0, len
);
99 for (i
= 0; i
< ring
->layout
.tp_frame_nr
; ++i
) {
100 ring
->frames
[i
].iov_len
= ring
->layout
.tp_frame_size
;
101 ring
->frames
[i
].iov_base
= ring
->mm_space
+
102 (i
* ring
->layout
.tp_frame_size
);
106 void bind_tx_ring(int sock
, struct ring
*ring
, int ifindex
)
108 memset(&ring
->s_ll
, 0, sizeof(ring
->s_ll
));
109 ring
->s_ll
.sll_family
= AF_PACKET
;
110 ring
->s_ll
.sll_protocol
= htons(ETH_P_ALL
);
111 ring
->s_ll
.sll_ifindex
= ifindex
;
112 ring
->s_ll
.sll_hatype
= 0;
113 ring
->s_ll
.sll_halen
= 0;
114 ring
->s_ll
.sll_pkttype
= 0;
115 int ret
= bind(sock
, (struct sockaddr
*) &ring
->s_ll
,
118 destroy_tx_ring(sock
, ring
);
119 panic("Cannot bind TX_RING!\n");
123 int pull_and_flush_tx_ring(int sock
)
125 return sendto(sock
, NULL
, 0, MSG_DONTWAIT
, NULL
, 0);