๐Ÿ“ฆ cloudflare / cloudflare-blog

๐Ÿ“„ main.c ยท 113 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <time.h>
#include <arpa/inet.h>

#define NETMAP_WITH_LIBS
#include <net/netmap_user.h>

static int
filter_packet(char *buf, int len)
{
	// Allow ARP
	if (len >= 14 &&
	    *((uint16_t *) (buf + 12)) == 0x0608) {
		return 1;
	}

	// Allow ICMP
	if (len >= 34 &&
	    *((uint16_t *) (buf + 12)) == 0x0008 &&
	    *((uint8_t *)  (buf + 23)) == 0x1) {
		return 1;
	}

	// Drop anything else
	return 0;
}

static void
receiver(struct nm_desc *d, unsigned int ring_id)
{
	struct pollfd fds;
	struct netmap_ring *ring;
	unsigned int i, len;
	char *buf;
	time_t now;
	int pps;

	now = time(NULL);
	pps = 0;

	while (1) {
		fds.fd     = d->fd;
		fds.events = POLLIN;

		int r = poll(&fds, 1, 1000);
		if (r < 0) {
			perror("poll()");
			exit(3);
		}

		if (time(NULL) > now) {
			printf("[+] receiving %d pps\n", pps);
			pps = 0;
			now = time(NULL);
		}

		ring = NETMAP_RXRING(d->nifp, ring_id);

		while (!nm_ring_empty(ring)) {
			i   = ring->cur;
			buf = NETMAP_BUF(ring, ring->slot[i].buf_idx);
			len = ring->slot[i].len;

			pps++;

			if (filter_packet(buf, len)) {
				// forward
				ring->flags         |= NR_FORWARD;
				ring->slot[i].flags |= NS_FORWARD;
			} else {
				// drop
			}

			ring->head = ring->cur = nm_ring_next(ring, i);
		}
	}
}

int
main(int argc, char *argv[])
{
	char netmap_ifname[IFNAMSIZ + 21];
	const char *interface;
	unsigned int ring_id;
	struct nm_desc *d;

	if (argc < 3) {
		fprintf(stderr, "Usage: %s [interface] [RX ring number]\n", argv[0]);
		exit(1);
	}

	interface = argv[1];
	ring_id   = atoi(argv[2]);

	snprintf(netmap_ifname, sizeof(netmap_ifname), "netmap:%s-%d/R", interface, ring_id);
	d = nm_open(netmap_ifname, NULL, 0, 0);

	if (!d) {
		perror("nm_open()");
		exit(2);
	}

	printf("[+] Receiving packets on interface %s, RX ring %d\n", interface, ring_id);
	receiver(d, ring_id);

	return 0;
}