Payload offset fix
[netsniff-ng.git] / src / rx_ring.c
blobc216a324ba418f85225c8cca2c9b37f5ce0926f5
1 /*
2 * Copyright (C) 2009, 2010 Daniel Borkmann <daniel@netsniff-ng.org> and
3 * Emmanuel Roullit <emmanuel@netsniff-ng.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
20 #define _GNU_SOURCE
22 #include <stdio.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <signal.h>
30 #include <unistd.h>
31 #include <pthread.h>
33 #include <net/if.h>
34 #include <arpa/inet.h>
36 #include <sys/ioctl.h>
37 #include <sys/mman.h>
38 #include <sys/poll.h>
39 #include <sys/types.h>
41 #include <linux/if_ether.h>
42 #include <linux/if_packet.h>
43 #include <linux/filter.h>
45 #include "pcap.h"
46 #include "cursor.h"
47 #include "dump.h"
48 #include "macros.h"
49 #include "types.h"
50 #include "rx_ring.h"
51 #include "netdev.h"
52 #include "config.h"
53 #include "nsignal.h"
54 #include "bpf.h"
55 #include "xmalloc.h"
56 #include "strlcpy.h"
58 /**
59 * destroy_virt_rx_ring - Destroys virtual RX_RING buffer
60 * @sock: socket
61 * @rb: ring buffer
63 void destroy_virt_rx_ring(int sock, struct ring_buff *rb)
65 assert(rb);
67 memset(&(rb->layout), 0, sizeof(rb->layout));
68 setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (void *)&(rb->layout),
69 sizeof(rb->layout));
71 if (rb->buffer) {
72 munmap(rb->buffer, rb->len);
73 rb->buffer = 0;
74 rb->len = 0;
77 xfree(rb->frames);
80 /**
81 * create_virt_rx_ring - Creates virtual RX_RING buffer
82 * @sock: socket
83 * @rb: ring buffer
85 void create_virt_rx_ring(int sock, struct ring_buff *rb, char *ifname,
86 unsigned int usize)
88 short nic_flags;
89 int ret, dev_speed;
91 assert(rb);
92 assert(ifname);
94 nic_flags = get_nic_flags(ifname);
96 if ((nic_flags & IFF_UP) != IFF_UP) {
97 warn("The interface %s is not up\n\n", ifname);
98 exit(EXIT_FAILURE);
101 if ((nic_flags & IFF_RUNNING) != IFF_RUNNING) {
102 warn("The interface %s is not running\n\n", ifname);
103 exit(EXIT_FAILURE);
106 dev_speed = get_device_bitrate_generic_fallback(ifname);
107 memset(&(rb->layout), 0, sizeof(rb->layout));
109 /* max: getpagesize() << 11 for i386 */
110 rb->layout.tp_block_size = getpagesize() << 2;
111 rb->layout.tp_frame_size = TPACKET_ALIGNMENT << 7;
113 /* max: 15 for i386, old default: 1 << 13, now: approximated bandwidth size */
114 if (usize == 0) {
115 rb->layout.tp_block_nr =
116 ((dev_speed * 1024 * 1024) / rb->layout.tp_block_size);
117 } else {
118 rb->layout.tp_block_nr =
119 usize / (rb->layout.tp_block_size / 1024);
122 rb->layout.tp_frame_nr =
123 rb->layout.tp_block_size / rb->layout.tp_frame_size *
124 rb->layout.tp_block_nr;
126 __retry_sso:
127 ret =
128 setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (void *)&(rb->layout),
129 sizeof(rb->layout));
131 if (errno == ENOMEM && rb->layout.tp_block_nr > 1) {
132 rb->layout.tp_block_nr >>= 1;
133 rb->layout.tp_frame_nr =
134 rb->layout.tp_block_size / rb->layout.tp_frame_size *
135 rb->layout.tp_block_nr;
137 goto __retry_sso;
140 if (ret < 0) {
141 err("setsockopt: creation of rx_ring failed");
142 close(sock);
143 exit(EXIT_FAILURE);
146 rb->len = rb->layout.tp_block_size * rb->layout.tp_block_nr;
148 info("%.2f MB allocated for receive ring \n",
149 1.f * rb->len / (1024 * 1024));
150 info(" [ %d blocks, %d frames ] \n", rb->layout.tp_block_nr,
151 rb->layout.tp_frame_nr);
152 info(" [ %d frames per block ]\n",
153 rb->layout.tp_block_size / rb->layout.tp_frame_size);
154 info(" [ framesize: %d bytes, blocksize: %d bytes ]\n\n",
155 rb->layout.tp_frame_size, rb->layout.tp_block_size);
159 * mmap_virt_rx_ring - Memory maps virtual RX_RING kernel buffer into userspace
160 * in order to avoid syscalls for fetching packet buffers
161 * @sock: socket
162 * @rb: ring buffer
164 void mmap_virt_rx_ring(int sock, struct ring_buff *rb)
166 assert(rb);
168 rb->buffer =
169 mmap(0, rb->len, PROT_READ | PROT_WRITE, MAP_SHARED, sock, 0);
170 if (rb->buffer == MAP_FAILED) {
171 err("mmap: cannot mmap the rx_ring");
173 destroy_virt_rx_ring(sock, rb);
174 close(sock);
175 exit(EXIT_FAILURE);
180 * bind_dev_to_rx_ring - Binds virtual RX_RING to network device
181 * @sock: socket
182 * @ifindex: device number
183 * @rb: ring buffer
185 void bind_dev_to_rx_ring(int sock, int ifindex, struct ring_buff *rb)
187 int ret;
189 assert(rb);
191 memset(&(rb->params), 0, sizeof(rb->params));
193 rb->params.sll_family = AF_PACKET;
194 rb->params.sll_protocol = htons(ETH_P_ALL);
195 rb->params.sll_ifindex = ifindex;
196 rb->params.sll_hatype = 0;
197 rb->params.sll_halen = 0;
198 rb->params.sll_pkttype = 0;
200 ret =
201 bind(sock, (struct sockaddr *)&(rb->params),
202 sizeof(struct sockaddr_ll));
203 if (ret < 0) {
204 err("bind: cannot bind device");
206 close(sock);
207 exit(EXIT_FAILURE);
211 int compat_bind_dev(int sock, const char *dev)
213 struct sockaddr saddr = { 0 };
214 int rc;
216 strlcpy(saddr.sa_data, dev, sizeof(saddr.sa_data) - 1);
218 rc = bind(sock, &saddr, sizeof(saddr));
220 if (rc == -1) {
221 err("bind() failed");
222 return (rc);
225 return (0);
229 * fetch_packets_and_print - Traverses RX_RING and prints content
230 * @rb: ring buffer
231 * @pfd: file descriptor for polling
233 void fetch_packets(struct system_data *sd, int sock, struct ring_buff *rb)
235 int ret, foo, i = 0;
236 struct pollfd pfd = { 0 };
238 struct spinner_thread_context spinner_ctx = { 0 };
240 spinner_set_msg(&spinner_ctx, DEFAULT_RX_RING_SILENT_MESSAGE);
242 assert(rb);
243 assert(sd);
245 pfd.fd = sock;
246 pfd.events = POLLIN | POLLRDNORM | POLLERR;
248 info("--- Listening ---\n\n");
249 if (!sd->print_pkt) {
250 ret = spinner_create(&spinner_ctx);
251 if (ret) {
252 err("Cannot create spinner thread");
253 exit(EXIT_FAILURE);
257 if (sd->pcap_fd != PCAP_NO_DUMP) {
258 pcap_write_header(sd->pcap_fd, LINKTYPE_EN10MB, 0,
259 PCAP_DEFAULT_SNAPSHOT_LEN);
262 /* This is our critical path ... */
263 while (likely(!sigint)) {
264 while (mem_notify_user_for_rx(rb->frames[i]) && likely(!sigint)) {
265 struct frame_map *fm = rb->frames[i].iov_base;
266 uint8_t *rbb =
267 ((uint8_t *) rb->frames[i].iov_base) + fm->tp_h.tp_mac;/*sizeof(*fm) +
268 sizeof(short));*/
270 /* Check if the user wants to have a specific
271 packet type */
272 if (sd->packet_type != PACKET_DONT_CARE) {
273 if (fm->s_ll.sll_pkttype != sd->packet_type) {
274 goto __out_notify_kernel;
278 if (sd->pcap_fd != PCAP_NO_DUMP) {
279 pcap_dump(sd->pcap_fd, &fm->tp_h,
280 (struct ethhdr *)rbb);
284 if (sd->print_pkt) {
285 /* This path here slows us down ... well, but
286 the user wants to see what's going on */
287 sd->print_pkt(rbb, &fm->tp_h,
288 fm->s_ll.sll_pkttype);
291 /* Next frame */
292 i = (i + 1) % rb->layout.tp_frame_nr;
294 __out_notify_kernel:
295 /* This is very important, otherwise kernel starts
296 to drop packages */
297 mem_notify_kernel_for_rx(&(fm->tp_h));
300 while ((ret = poll(&pfd, 1, sd->blocking_mode)) <= 0) {
301 if (sigint) {
302 printf("Got SIGINT here!\n");
303 goto out;
307 spinner_trigger_event(&spinner_ctx);
309 if (ret > 0
310 && (pfd.
311 revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL))) {
312 if (pfd.revents & (POLLHUP | POLLRDHUP)) {
313 err("Hangup on socket occured");
315 return;
316 } else if (pfd.revents & POLLERR) {
317 /* recv is more specififc on the error */
318 errno = 0;
319 if (recv(sock, &foo, sizeof(foo), MSG_PEEK) !=
321 goto __out_grab_frame; /* Hmm... no error */
322 if (errno == ENETDOWN) {
323 err("Interface went down");
324 } else {
325 err("Receive error");
328 goto out;
329 } else if (pfd.revents & POLLNVAL) {
330 err("Invalid polling request on socket");
332 goto out;
336 __out_grab_frame:
337 /* Look-ahead if current frame is status kernel, otherwise we have
338 have incoming frames and poll spins / hangs all the time :( */
339 for (; ((struct tpacket_hdr *)rb->frames[i].iov_base)->tp_status
340 != TP_STATUS_USER && likely(!sigint);
341 i = (i + 1) % rb->layout.tp_frame_nr)
342 /* NOP */ ;
343 /* Why this should be okay:
344 1) Current frame[i] is TP_STATUS_USER:
345 This is our original case that occurs without
346 the for loop.
347 2) Current frame[i] is not TP_STATUS_USER:
348 poll returns correctly with return value 1 (number of
349 file descriptors), so an event has occured which has
350 to be POLLIN since all error conditions have been
351 caught previously. Furthermore, during ring traversal
352 a frame that has been set to TP_STATUS_USER will be
353 given back to kernel on finish with TP_STATUS_KERNEL.
354 So, if we look ahead all skipped frames are not ready
355 for user access. Since the kernel decides to put
356 frames, which are 'behind' our pointer, into
357 TP_STATUS_USER we do one loop and return at the
358 correct position after passing the for loop again. If
359 we grab frame which are 'in front of' our pointer
360 we'll fetch them within the first for loop.
364 out:
365 spinner_cancel(&spinner_ctx);
368 void compat_fetch_packets(struct system_data *sd, int sock,
369 struct ring_buff *rb)
371 struct timeval now;
372 struct spinner_thread_context spinner_ctx = { 0 };
373 struct tpacket_hdr tp_h = { 0 };
374 uint8_t *pkt_buf = NULL;
375 struct sockaddr_ll from = { 0 };
376 socklen_t from_len = sizeof(from);
377 int pf_sock;
378 int ret;
379 int pkt_len;
380 uint16_t mtu = get_mtu(sd->dev);
382 pf_sock = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
384 if (compat_bind_dev(pf_sock, sd->dev) != 0) {
385 return;
388 inject_kernel_bpf(pf_sock, &sd->bpf);
390 pkt_buf = xzmalloc(mtu);
392 spinner_set_msg(&spinner_ctx, DEFAULT_RX_RING_SILENT_MESSAGE);
394 info("--- Listening in compatibility mode---\n\n");
396 if (!sd->print_pkt) {
397 ret = spinner_create(&spinner_ctx);
398 if (ret) {
399 err("Cannot create spinner thread");
400 exit(EXIT_FAILURE);
404 if (sd->pcap_fd != PCAP_NO_DUMP) {
405 pcap_write_header(sd->pcap_fd, LINKTYPE_EN10MB, 0,
406 PCAP_DEFAULT_SNAPSHOT_LEN);
409 while (likely(!sigint)) {
410 pkt_len =
411 recvfrom(pf_sock, pkt_buf, mtu, MSG_TRUNC,
412 (struct sockaddr *)&from, &from_len);
414 if (errno == EINTR)
415 break;
417 spinner_trigger_event(&spinner_ctx);
419 gettimeofday(&now, NULL);
421 tp_h.tp_sec = now.tv_sec;
422 tp_h.tp_usec = now.tv_usec;
423 tp_h.tp_len = tp_h.tp_snaplen = pkt_len;
425 if (sd->pcap_fd != PCAP_NO_DUMP) {
426 pcap_dump(sd->pcap_fd, &tp_h,
427 (struct ethhdr *)(pkt_buf));
430 if (sd->print_pkt) {
431 /* This path here slows us down ... well, but
432 the user wants to see what's going on */
433 sd->print_pkt(pkt_buf, &tp_h, 5);
437 spinner_cancel(&spinner_ctx);
438 close(pf_sock);
439 xfree(pkt_buf);
442 void start_fetching_packets(struct system_data *sd, int sock,
443 struct ring_buff *rb)
445 if (sd->compatibility_mode)
446 compat_fetch_packets(sd, sock, rb);
447 else
448 fetch_packets(sd, sock, rb);