Package: libpcap0.8
Version: 1.8.1-6
Severity: important
Tags: patch
Dear maintainer,
since Linux kernel 3.4, the outer vlan tag is no longer transparently
passed to userspace. Instead, libpcap and others needs to access ancillary
data in BPF [1], [2]. libpcap does this starting with 1.8, although
incorrectly.
The kernel returns the full TCI (16-bit), which includes the IEEE 802.1p
"COS" value. However libcap expects the 12-bit VLANID verbatim, meaning
that when the incoming frame has a non-null priority field, vlan matching
fails.
This has finally been fixed upstream in libpcap-1.9 branch (after the 1.9.0
release) and master, see [3] and [4].
This can be reproduced by generating such a frame via scapy on loopback:
$ sudo scapy
>>> sendp(Ether(src="00:11:22:33:44:55",dst="00:00:aa:bb:cc:dd")/\
Dot1Q(vlan=100,prio=2)/IP(src="1.2.3.4",dst="2.1.3.4")/\
UDP(sport=9999,dport=9999),iface="lo",count=1)
and tcpdumping it with a filter for vlan 100:
$ sudo tcpdump -nxxevi lo vlan 100
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel
$
Filter fails because of the nun-null dot1P field.
In fact the generated BPF code doesn't mask the 16-bit TCI with 0xfff:
$ sudo tcpdump -nxxevi lo vlan 100 -d
(000) ldb [-4048]
(001) jeq #0x1 jt 2 jf 5
(002) ldb [-4052]
(003) jeq #0x64 jt 4 jf 5
(004) ret #262144
(005) ret #0
$
As we apply the patch for this issue - which diverges from upstream fixes
because the 1.8 tree is different - a 0xfff mask is applied to the TCI field:
$ sudo tcpdump -nxxevi lo vlan 100 -d
(000) ldb [-4048]
(001) jeq #0x1 jt 2 jf 6
(002) ldb [-4052]
(003) and #0xfff
(004) jeq #0x64 jt 5 jf 6
(005) ret #262144
(006) ret #0
$
and the capture works flawlessly:
$ sudo tcpdump -nxxevi lo vlan 100
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
19:16:12.020500 00:11:22:33:44:55 > 00:00:aa:bb:cc:dd, ethertype 802.1Q
(0x8100), length 46: vlan 100, p 2, ethertype IPv4, (tos 0x0, ttl 64, id 1,
offset 0, flags [none], proto UDP (17), length 28)
1.2.3.4.9999 > 2.1.3.4.9999: UDP, length 0
0x0000: 0000 aabb ccdd 0011 2233 4455 8100 4064
0x0010: 0800 4500 001c 0001 0000 4011 71c6 0102
0x0020: 0304 0201 0304 270f 270f 0008 a8b5
^C
1 packet captured
1 packet received by filter
0 packets dropped by kernel
$
Please consider applying this patch to the libpcap0.8 package in Debian Stretch.
Thanks,
-lukas
[1] https://www.spinics.net/lists/netdev/msg244673.html
[2]
https://github.com/torvalds/linux/blob/6f0d349d922ba44e4348a17a78ea51b7135965b1/include/uapi/linux/filter.h#L60
[3] https://github.com/the-tcpdump-group/libpcap/issues/461
[4]
https://github.com/the-tcpdump-group/libpcap/commit/b525a0863466ba863630c0450926044230b447e8
-- System Information:
Debian Release: 9.5
APT prefers unstable
APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)
Kernel: Linux 4.9.0-7-amd64 (SMP w/1 CPU core)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8),
LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
Versions of packages libpcap0.8 depends on:
ii libc6 2.24-11+deb9u3
libpcap0.8 recommends no packages.
libpcap0.8 suggests no packages.
-- no debconf information
diff --git a/gencode.c b/gencode.c
index a887f27..ba095a5 100644
--- a/gencode.c
+++ b/gencode.c
@@ -7952,7 +7952,7 @@ static struct block *
gen_vlan_bpf_extensions(compiler_state_t *cstate, int vlan_num)
{
struct block *b0, *b1;
- struct slist *s;
+ struct slist *s, *s2;
/* generate new filter code based on extracting packet
* metadata */
@@ -7967,6 +7967,11 @@ gen_vlan_bpf_extensions(compiler_state_t *cstate, int
vlan_num)
s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
+ /* mask TCI field with 0xfff to extract VLANID */
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+ s2->s.k = 0xfff;
+ sappend(s, s2);
+
b1 = new_block(cstate, JMP(BPF_JEQ));
b1->stmts = s;
b1->s.k = (bpf_int32) vlan_num;