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.
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <arpa/inet.h>
18 #include <linux/if_ether.h>
25 void set_packet_loss_discard(int sock
)
29 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_LOSS
, (void *) &discard
,
32 error_and_die(EXIT_FAILURE
, "setsockopt: cannot set packet "
36 void destroy_tx_ring(int sock
, struct ring
*ring
)
38 memset(&ring
->layout
, 0, sizeof(ring
->layout
));
39 setsockopt(sock
, SOL_PACKET
, PACKET_TX_RING
, &ring
->layout
,
40 sizeof(ring
->layout
));
42 munmap(ring
->mm_space
, ring
->mm_len
);
48 void setup_tx_ring_layout(int sock
, struct ring
*ring
, unsigned int size
)
50 memset(&ring
->layout
, 0, sizeof(ring
->layout
));
51 ring
->layout
.tp_block_size
= getpagesize() << 2;
52 ring
->layout
.tp_frame_size
= TPACKET_ALIGNMENT
<< 10;
53 ring
->layout
.tp_block_nr
= size
/ ring
->layout
.tp_block_size
;
54 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
55 ring
->layout
.tp_frame_size
*
56 ring
->layout
.tp_block_nr
;
58 assert(ring
->layout
.tp_block_size
>= ring
->layout
.tp_frame_size
);
59 assert((ring
->layout
.tp_block_size
% ring
->layout
.tp_frame_size
) == 0);
62 void create_tx_ring(int sock
, struct ring
*ring
)
66 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_TX_RING
, &ring
->layout
,
67 sizeof(ring
->layout
));
68 if (errno
== ENOMEM
&& ring
->layout
.tp_block_nr
> 1) {
69 ring
->layout
.tp_block_nr
>>= 1;
70 ring
->layout
.tp_frame_nr
= ring
->layout
.tp_block_size
/
71 ring
->layout
.tp_frame_size
*
72 ring
->layout
.tp_block_nr
;
77 error_and_die(EXIT_FAILURE
, "Cannot allocate TX_RING!\n");
79 ring
->mm_len
= ring
->layout
.tp_block_size
* ring
->layout
.tp_block_nr
;
81 printf("TX: %.2f MB, %u Frames each %u Byte allocated\n",
82 1.f
* ring
->mm_len
/ (1 << 20),
83 ring
->layout
.tp_frame_nr
, ring
->layout
.tp_frame_size
);
86 void mmap_tx_ring(int sock
, struct ring
*ring
)
88 ring
->mm_space
= mmap(0, ring
->mm_len
, PROT_READ
| PROT_WRITE
,
90 if (ring
->mm_space
== MAP_FAILED
) {
91 destroy_tx_ring(sock
, ring
);
92 error_and_die(EXIT_FAILURE
, "Cannot mmap TX_RING!\n");
96 void alloc_tx_ring_frames(struct ring
*ring
)
100 ring
->frames
= xzmalloc(ring
->layout
.tp_frame_nr
*
101 sizeof(*ring
->frames
));
103 for (i
= 0; i
< ring
->layout
.tp_frame_nr
; ++i
) {
104 ring
->frames
[i
].iov_len
= ring
->layout
.tp_frame_size
;
105 ring
->frames
[i
].iov_base
= ring
->mm_space
+
106 (i
* ring
->layout
.tp_frame_size
);
110 void bind_tx_ring(int sock
, struct ring
*ring
, int ifindex
)
112 memset(&ring
->s_ll
, 0, sizeof(ring
->s_ll
));
113 ring
->s_ll
.sll_family
= AF_PACKET
;
114 ring
->s_ll
.sll_protocol
= htons(ETH_P_ALL
);
115 ring
->s_ll
.sll_ifindex
= ifindex
;
116 ring
->s_ll
.sll_hatype
= 0;
117 ring
->s_ll
.sll_halen
= 0;
118 ring
->s_ll
.sll_pkttype
= 0;
120 int ret
= bind(sock
, (struct sockaddr
*) &ring
->s_ll
,
123 destroy_tx_ring(sock
, ring
);
124 error_and_die(EXIT_FAILURE
, "Cannot bind TX_RING!\n");
128 int pull_and_flush_tx_ring(int sock
)
130 /* Flush buffers with TP_STATUS_SEND_REQUEST */
131 return sendto(sock
, NULL
, 0, MSG_DONTWAIT
, NULL
, 0);
134 #endif /* HAVE_TX_RING */