the-tcpdump-group/libpcap — pull request #353 by chemag (2014-04-24 18:45:41+00:00)
Title: libpcap: added raw filters

The goal of supporting raw filters* is to provide libpcap/tcpdump support
for generic BPF insns, including those that are not-supported by libpcap
(e.g., the BPF_MOD/BPF_XOR ops in Linux, or any of the multiple ancillary
loads in linux). It also allows testing new kernel extensions to the
BPF ISA without having to modify libpcap/tcpdump.

We provide support by modifying pcap_compile() so that it first checks
for raw filters. This works for expressions appended in the command line,
and for expressions read from a file ("-F" option). Filters starting
with an integer and a valid separator (',' or '\n') are considered raw.
All other filters are considered (traditional) expressions.

We also make sure that filters compiled from raw filters are left for the
kernel to validate (added "skip_validate" to pcap_t).

*Raw filters are those generated by tcpdump -ddd. i.e.

$ ./tcpdump -ddd -i eth0 icmp
6
40 0 0 12
21 0 3 2048
48 0 0 23
21 0 1 1
6 0 0 65535
6 0 0 0

We also support replacing the new line characters with commas, as to
make possible to have inline filters.

$ ./tcpdump -ddd -i eth0 icmp |tr '\n' ','
6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 65535,6 0 0 0,

Tested:

$ cat icmp.bpf
ldh [12]
jne #0x800, drop
ldb [23]
jneq #1, drop
ret #-1
drop: ret #0
$ linux/net/tools/bpf_asm icmp.bpf > icmp.1.bpfraw
$ cat icmp.1.bpfraw
6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 4294967295,6 0 0 0,
$ linux/net/tools/bpf_asm icmp.bpf |tr ',' '\n' > icmp.2.bpfraw
$ cat icmp.2.bpfraw
6
40 0 0 12
21 0 3 2048
48 0 0 23
21 0 1 1
6 0 0 4294967295
6 0 0 0

-- start pinging at 8.8.8.8 from another xterm

$ echo 2 > /proc/sys/net/core/bpf_jit_enable

$ ./tcpdump -nn -i eth0 icmp
[000096.500054] device eth0 entered promiscuous mode
[000096.530154] flen=1 proglen=3 pass=3 image=ffffffffa000878c
[000096.531000] JIT code: 00000000: 31 c0 c3
[000096.531676] flen=6 proglen=70 pass=3 image=ffffffffa00049ad
[000096.532505] JIT code: 00000000: 55 48 89 e5 48 83 ec 60 48 89 5d f8 44 8b 4f 68
[000096.533567] JIT code: 00000010: 44 2b 4f 6c 4c 8b 87 d8 00 00 00 be 0c 00 00 00
[000096.534661] JIT code: 00000020: e8 cf 26 04 e1 3d 00 08 00 00 75 16 be 17 00 00
[000096.535707] JIT code: 00000030: 00 e8 da 26 04 e1 83 f8 01 75 07 b8 ff ff 00 00
[000096.536733] JIT code: 00000040: eb 02 31 c0 c9 c3
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
16:35:09.097308 IP 192.168.100.1 > 8.8.8.8: ICMP echo request, id 10357, seq 1, length 64
16:35:09.118301 IP 8.8.8.8 > 192.168.100.1: ICMP echo reply, id 10357, seq 1, length 64
16:35:10.098626 IP 192.168.100.1 > 8.8.8.8: ICMP echo request, id 10357, seq 2, length 64
16:35:10.119608 IP 8.8.8.8 > 192.168.100.1: ICMP echo reply, id 10357, seq 2, length 64

$ ./tcpdump -nn -i eth0 -F ~/bpf/icmp.1.bpfraw
[000166.010055] device eth0 entered promiscuous mode
[000166.040163] flen=1 proglen=3 pass=3 image=ffffffffa0008e83
[000166.040689] JIT code: 00000000: 31 c0 c3
[000166.041138] flen=6 proglen=70 pass=3 image=ffffffffa0004161
[000166.041884] JIT code: 00000000: 55 48 89 e5 48 83 ec 60 48 89 5d f8 44 8b 4f 68
[000166.042809] JIT code: 00000010: 44 2b 4f 6c 4c 8b 87 d8 00 00 00 be 0c 00 00 00
[000166.043744] JIT code: 00000020: e8 1b 2f 04 e1 3d 00 08 00 00 75 16 be 17 00 00
[000166.044725] JIT code: 00000030: 00 e8 26 2f 04 e1 83 f8 01 75 07 b8 ff ff ff ff
[000166.045644] JIT code: 00000040: eb 02 31 c0 c9 c3
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
16:36:00.089773 IP 192.168.100.1 > 8.8.8.8: ICMP echo request, id 10359, seq 1, length 64
16:36:00.110723 IP 8.8.8.8 > 192.168.100.1: ICMP echo reply, id 10359, seq 1, length 64
16:36:01.091191 IP 192.168.100.1 > 8.8.8.8: ICMP echo request, id 10359, seq 2, length 64
16:36:01.112169 IP 8.8.8.8 > 192.168.100.1: ICMP echo reply, id 10359, seq 2, length 64
16:36:02.092495 IP 192.168.100.1 > 8.8.8.8: ICMP echo request, id 10359, seq 3, length 64
16:36:02.113500 IP 8.8.8.8 > 192.168.100.1: ICMP echo reply, id 10359, seq 3, length 64

$ ./tcpdump -nn -i eth0 "6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 65535,6 0 0 0,"
[000100.590119] device eth0 entered promiscuous mode
[000100.620140] flen=1 proglen=3 pass=3 image=ffffffffa00040cc
...

$ ./tcpdump -nn -i eth0 -F ~/bpf/icmp.2.bpfraw
[000199.950055] device eth0 entered promiscuous mode
[000199.980521] flen=1 proglen=3 pass=3 image=ffffffffa0008d82
[000199.981505] JIT code: 00000000: 31 c0 c3
[000199.982220] flen=6 proglen=70 pass=3 image=ffffffffa0004655
[000199.983214] JIT code: 00000000: 55 48 89 e5 48 83 ec 60 48 89 5d f8 44 8b 4f 68
[000199.984375] JIT code: 00000010: 44 2b 4f 6c 4c 8b 87 d8 00 00 00 be 0c 00 00 00
[000199.985498] JIT code: 00000020: e8 27 2a 04 e1 3d 00 08 00 00 75 16 be 17 00 00
[000199.986579] JIT code: 00000030: 00 e8 32 2a 04 e1 83 f8 01 75 07 b8 ff ff ff ff
[000199.987664] JIT code: 00000040: eb 02 31 c0 c9 c3
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
16:36:33.402095 IP 192.168.100.1 > 8.8.8.8: ICMP echo request, id 10361, seq 1, length 64
16:36:33.423003 IP 8.8.8.8 > 192.168.100.1: ICMP echo reply, id 10361, seq 1, length 64
16:36:34.403321 IP 192.168.100.1 > 8.8.8.8: ICMP echo request, id 10361, seq 2, length 64
16:36:34.424359 IP 8.8.8.8 > 192.168.100.1: ICMP echo reply, id 10361, seq 2, length 64

And this uses an extended Linux feature (random numbers):

$ ./tcpdump -nn -i eth0 "9,40 0 0 12,21 0 6 2048,48 0 0 23,21 0 4 1,32 0 0 4294963256,148 0 0 4,21 0 1 1,6 0 0 4294967295,6 0 0 0,"
...