# snoop.c -rw-r--r-- 2.8 KiB View raw
                                                                                
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
#include <arpa/inet.h>
#include <errno.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/filter.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/uio.h>

void die(char *errstr, ...) {
	va_list ap;
	va_start(ap, errstr);
	vdprintf(2, errstr, ap);
	va_end(ap);
	exit(1);
}

#define NELEMS(x) (sizeof x / sizeof *x)

/* tcpdump -dd udp portrange 67-68 or udp portrange 546-547 or icmp6 */
struct sock_filter filter[] = {
	{ 0x28, 0, 0, 0x0000000c },
	{ 0x15, 0, 17, 0x000086dd },
	{ 0x30, 0, 0, 0x00000014 },
	{ 0x15, 0, 11, 0x00000011 },
	{ 0x28, 0, 0, 0x00000036 },
	{ 0x35, 0, 1, 0x00000043 },
	{ 0x25, 0, 30, 0x00000044 },
	{ 0x28, 0, 0, 0x00000038 },
	{ 0x35, 0, 1, 0x00000043 },
	{ 0x25, 0, 27, 0x00000044 },
	{ 0x28, 0, 0, 0x00000036 },
	{ 0x35, 0, 1, 0x00000222 },
	{ 0x25, 0, 24, 0x00000223 },
	{ 0x28, 0, 0, 0x00000038 },
	{ 0x35, 21, 23, 0x00000222 },
	{ 0x15, 21, 0, 0x0000003a },
	{ 0x15, 0, 21, 0x0000002c },
	{ 0x30, 0, 0, 0x00000036 },
	{ 0x15, 18, 19, 0x0000003a },
	{ 0x15, 0, 18, 0x00000800 },
	{ 0x30, 0, 0, 0x00000017 },
	{ 0x15, 0, 16, 0x00000011 },
	{ 0x28, 0, 0, 0x00000014 },
	{ 0x45, 14, 0, 0x00001fff },
	{ 0xb1, 0, 0, 0x0000000e },
	{ 0x48, 0, 0, 0x0000000e },
	{ 0x35, 0, 1, 0x00000043 },
	{ 0x25, 0, 9, 0x00000044 },
	{ 0x48, 0, 0, 0x00000010 },
	{ 0x35, 0, 1, 0x00000043 },
	{ 0x25, 0, 6, 0x00000044 },
	{ 0x48, 0, 0, 0x0000000e },
	{ 0x35, 0, 1, 0x00000222 },
	{ 0x25, 0, 3, 0x00000223 },
	{ 0x48, 0, 0, 0x00000010 },
	{ 0x35, 0, 2, 0x00000222 },
	{ 0x25, 1, 0, 0x00000223 },
	{ 0x6, 0, 0, 0x00040000 },
	{ 0x6, 0, 0, 0x00000000 },
};

int main(int argc, char **argv) {
	int sock;
	int one = 1;
	struct msghdr msg;
	struct sockaddr_ll link;
	struct packet_mreq mr;
	struct iovec iov;
	struct sock_fprog bpf;

	sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (sock < 0) die("socket: %s\n", strerror(errno));

	bpf.len = NELEMS(filter);
	bpf.filter = filter;
	if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof bpf) < 0)
		die("SO_ATTACH_FILTER: %s\n", strerror(errno));
	if (setsockopt(sock, SOL_SOCKET, SO_LOCK_FILTER, &one, sizeof one) < 0)
		die("SO_LOCK_FILTER: %s\n", strerror(errno));

	memset(&msg, 0, sizeof msg);
	iov.iov_base = malloc(1500);
	iov.iov_len = 1500;

	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_name = calloc(1, sizeof (struct sockaddr_ll));
	msg.msg_namelen = sizeof (struct sockaddr_ll);
	while(1) {
		if (recvmsg(sock, &msg, 0) < 0) die("recvmsg: %s\n", strerror(errno));
		memmove(&link, msg.msg_name, sizeof link);
		fprintf(stderr, "link index %d pkttype %d\n", link.sll_ifindex, link.sll_pkttype);
		if (writev(1, msg.msg_iov, msg.msg_iovlen) < 0) die("writev: %s\n", strerror(errno));
		msg.msg_iov = &iov;
		msg.msg_iovlen = 1;
	}
	return 0;
}