the-tcpdump-group / libpcap

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

Support for eBPF filters ? #1379

Closed ferrieux closed 4 weeks ago

ferrieux commented 1 month ago

Hi,

While libpcap has been the motherland of cBPF for decades, it looks like there's no obvious transition from cBPF to eBPF in the context of packet filters.

Indeed, SO_ATTACH_BPF is already a socket option, and many sample programs do use it on a raw socket to do exactly that. The elephant sitting in the front row, is that libpcap doesn't offer a way of using SO_ATTACH_BPF. Which, in turn, quite naturally prevents tcpdump from exposing an option to load some (externally compiled) myprog.o similarly to what we do in XDP with ip link set dev $DEV xdp obj myprog.o.

Is there a hidden technical difficulty preventing this ?

guyharris commented 1 month ago

it looks like there's no obvious transition from cBPF to eBPF in the context of packet filters.

What do you mean by "transition"?

A Linux-only API, similar to pcap_setfilter(), that takes a pointer to a structure containing an eBPF program, and sets that as the filter? That's not a transition, it's added support, on one of libpcap's platforms, for eBPF filter programs when capturing; it doesn't mean that tcpdump/Wireshark/etc. filters would use eBPF.

That, plus a BSD-licensed eBPF interpreter (possibly plus a BSD-licensed JIT compiler for one or more platforms), thus allowing pcap_setfilter() to be used when reading capture files? That's still not a transition, just as the previous change isn't a transition.

An extension to the filter compiler that allows it to generate either cBPF or eBPF, done in a fashion so that a filter that could be compiled and set without the program using libpcap having to specify the target language, i.e. so that the target machine language is chosen by libpcap based on what's available? That would allow the Linux platform to transition to using eBPF. It wouldn't, of course, be a universal transition, it would just hide the details of the machine language, so that eBPF could be used if available and cBPF would be used otherwise.

The elephant sitting in the front row, is that libpcap doesn't offer a way of using SO_ATTACH_BPF.

It doesn't offer a way of doing that using only libpcap APIs; it does offer the ability to get the socket FD for a live capture, using pcap_fileno(), and directly doing a setsockopt() on that if it's a PF_PACKET socket.

Which, in turn, quite naturally prevents tcpdump from exposing an option to load some (externally compiled) myprog.o

Or, rather, it prevents it from doing so except by doing the above.

Is there a hidden technical difficulty preventing this ?

The only part that's technically difficult (not impossible, just requiring significant effort) is the filter compiler extension; that's not necessary for the "allow tcpdump to add an externally-compiled eBPF filter" part.

ferrieux commented 1 month ago

Hmm. From the tone of your reply I realize I must have touched on several taboos all at once. Apologies for that:

Now, to be honest, I don't care whether the feature comes through libpcap or tcpdump. And yes, I can do it alone with a personal patch on tcpdump, if you deem the idea too stupid for publication. If not, I can repost a similar issue on the tcpdump side.

Please tell me.

guyharris commented 4 weeks ago

I was under the impression that #ifdeffing a platform-specific feature was okay. If everything must be doable on all platforms

It's a "should have", not an absolute "must have" - there are platform-specific Windows APIs and one Linux-specific API.

I am completely ignorant about the licensing issues that you seem to be hinting at. If eBPF (or its toolchain) brings stuff that is incompatible with libpcap's license

As far as I know, there is nothing about the eBPF machine language that renders it incompatible with libpcap's license; an implementation of it, whether interpretive or "translate to machine code", can be written under any license.

The Linux kernel implementation is GPL2. That implementation can't be used as the basis of an implementation in libpcap, for use when reading a capture file or when the kernel rejects a filter handed to it. However a BSD-licensed eBPF interpreter or translator to machine code culd be used, as could an interpreter under another non-GPL (so that libpcap could be adopted by OSes that try to avoid GPLed code) and non-patent-licensed (as I think some OSes would reject that) license.

If we don't bother to provide a way to use eBPF filters when reading a capture file, or capturing on anything other than a Linux networkk device, we don't need the in-libpcap filter implementation, simplifying

I don't care whether the feature comes through libpcap or tcpdump

The one reason to provide it as a specialized call in tcpdump would be that making sure we support it only on live Linux captures would be more straightforward if we do it in libpcap.

ferrieux commented 4 weeks ago

Ok, reworded and posted to tcdump as Issue #1234