the-tcpdump-group / libpcap

the LIBpcap interface to various kernel packet capture mechanism
https://www.tcpdump.org/
Other
2.6k stars 830 forks source link

Live filtering by VLAN fails in Linux 2.6 #390

Open adaviel opened 9 years ago

adaviel commented 9 years ago

We have a capture system running CentOS 6 connected to a mirror port on a Juniper router, capturing VLAN tagged packets with a Mellanox card.

If I use tcpdump or tethereal to view packets live, I cannot filter by VLAN, but I can by host, e.g. tethereal -i eth2 -n host www.example.com works, while tethereal -i eth2 -n vlan 123 and host www.example.com does not (it captures no data) If I record a pcap file, e.g. tethereal -i eth2 -w my.cap -c 400 then I can replay it with e.g. tcpdump -r my.cap -n vlan and host www.example.com or tcpdump -r my.cap -n vlan 123 host www.example.com but not tcpdump -r my.cap -n host www.example.com

It is particularly annoying that we cannot filter live by VLAN, e.g. tethereal -i eth2 -n vlan 123 On an older router (Nortel Passport), this worked.

We have libpcap-1.4.0 on CentOS 6 (Linux 2.6.32-431) with a Mellanox driver v2.0 and a MT26448 card, connected to a Juniper EX9008 router. I tried installing the latest libpcap 1.6.2 but that made no difference.

msekletar commented 9 years ago

Hi, I've just opened PR #391 which should address this issue. Also, I am RHEL maintainer for tcpdump and libpcap, thus if accepted I will backport to RHEL6/CentOS6 as well.

Anyway, testing of PR #391 would be much appreciated. Thanks.

adaviel commented 9 years ago

Yes, that seems to work, thanks. At least on my target machine with CentOS 6.5 and kernel 2.6.32-431.29.2.el6.x86_64. I tried to build it as an RPM on my desktop at home (also CentOS 6.5) which had rpmbuild and bison installed, and although it seemed virtually identical, did not work. I finally tracked that down to the fact that SKF_AD_VLAN_TAG is defined in /linux/filter.h in kernel-headers-2.6.32-431.29.2.el6.x86_64 but not in kernel-headers-2.6.32-431.23.3.el6.x86_64, in which case libpcap silently builds without the VLAN feature, but with identical config.h.

msekletar commented 9 years ago

inally tracked that down to the fact that SKF_AD_VLAN_TAG is defined in /linux/filter.h in kernel-headers-2.6.32-431.29.2.el6.x86_64 but not in kernel-headers-2.6.32-431.23.3.el6.x86_64, in which case libpcap silently builds without the VLAN feature, but with identical config.h.

Hmm this looks like a kernel bug to me. Kernel is removing vlan tag but doesn't provide userspace a way how to get the vlan tag information.

guyharris commented 6 years ago

Prior to 3.0, the VLAN auxiliary information for packets included a VLAN TCI field but did not include a flag to indicate whether the packet originally had a VLAN tag or not. If it didn't, the VLAN TCI field was set to 0, which meant that packets in VLAN 0 couldn't be distinguished from packets without a VLAN tag.

In this Linux kernel commit, the TP_STATUS_VLAN_VALID flag in tp_status was introduced, "to distinguish VID 0 from no-vlan". I think that commit was in 3.0; it's from 2011-06-01.

In this Linux kernel commit, the SKF_AD_VLAN_TAG special BPF load offset was added to "[allow] libpcap/tcpdump to use a kernel filter instead of having to fallback to accept all packets, then filter them in user space"; it's from 2012-10-31.

If a kernel-headers package for a 2.x kernel has SKF_AD_VLAN_TAG, that's probably a backport. If your kernel implements it and libpcap uses it, filtering should work, otherwise it may have issues.