libpcap icon indicating copy to clipboard operation
libpcap copied to clipboard

Add support for the BPF "coprocessor" (BPF_COP and BPF_COPX instructions)

Open rmind opened this issue 10 years ago • 8 comments

Add support for the BPF "coprocessor": a raw primitive ("cop" keyword) to invoke a function provided by a coprocessor. References:

  • http://lists.sandelman.ca/pipermail/tcpdump-workers/2015-May/000256.html
  • http://mail-index.netbsd.org/tech-net/2013/08/22/msg004197.html

rmind avatar May 26 '15 00:05 rmind

@mcr: Any estimate on when this might get merged?

rmind avatar Jun 15 '19 16:06 rmind

This won't get merged until after 4.9.3 and 5.0 are out. Let's say, September.

mcr avatar Jun 15 '19 17:06 mcr

@mcr: Any progress here?

rmind avatar Nov 16 '19 22:11 rmind

I have tried the proposed changes, let me provide some feedback.

Regarding BPF_COPX, the change extends bpf_image() to recognize the instruction, but that code looks dead because the change does not add any code to generate the instruction. The only practical effect seems to be the allocation of a constant. This would need to be made consistent (or left out) before merging.

Regarding BPF_COP, the change seems to cover most of the other associated aspects:

$ ./tcpdump -d 'cop 1 2 3'
Warning: assuming Ethernet
(000) ld       #0x1
(001) cop      #2
(002) jeq      #0x3             jt 3	jf 4
(003) ret      #262144
(004) ret      #0

However, in my test on Linux an attempt to use cop on a live network interface seemed to work until the userspace BPF interpreter actually has to execute BPF_COP on an incoming packet, at which point the default case in pcap_filter_with_aux_data() raised SIGABRT and terminated tcpdump:

# idle loopback interface
tcpdump -i lo 'cop 1 2 3'
Warning: Kernel filter failed: Invalid argument
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel

# ping -n -4 localhost in the background
tcpdump -i lo -n 'tcp and cop 1 2 3'
Warning: Kernel filter failed: Invalid argument
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C
0 packets captured
12 packets received by filter
0 packets dropped by kernel

# ping -n -4 localhost in the background
tcpdump -i lo -n 'icmp and cop 1 2 3'
Warning: Kernel filter failed: Invalid argument
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
Aborted

This is a wrong way to indicate an error in user input, it would need to be made good before merging. It seems to me, pcap_compile() may emit BPF_COP when requested, but pcap_setfilter() ought to reject BPF_COP outright if the OS kernel does not support it. Other opinions are welcome.

Smaller issues include the use of pcap_snprintf() (which no longer exists) and the need to use "that" in "...the custom BPF interpreters which have the coprocessor support."

infrastation avatar Jun 30 '22 16:06 infrastation

Also grammar.y is a generated file, so the changes should modify grammar.y.in instead.

infrastation avatar Jun 30 '22 16:06 infrastation

I could perhaps look into this, but given that it took more than 7 years to get a feedback.. how long it will actually take to merge it?

rmind avatar Jun 30 '22 16:06 rmind

Hopefully sooner than that. If you want to progress this matter now, I have a bit of time to help now. If you prefer to do it later or not at all, that would be acceptable as well. In any case, the code should look and work well enough before merging.

As far as I managed to figure, BPF_COPX is a more meaningful aspect of this feature: the only inputs to a C function invoked via BPF_COP would be a hard-coded constant in the accumulator register and a pointer to the packet data, so the function needs to parse the packet using its own instrumentation instead of using what is already available in BPF (such as tcp[tcpflags]).

When using BPF_COPX, it should be possible to pick the item of interest from the packet and to pass it to the function via the X register. However, it is not clear how this is supposed to work at the filter expression level ("It is difficult to make complex things easy" comes to mind). Did you have something like copx ip[2:2] 1 1 in mind?

infrastation avatar Jun 30 '22 17:06 infrastation

Alright, for immediate practical purposes cbpf-savefile(5) includes provisions for BPF_COP and BPF_COPX, and the rest can be figured out later.

infrastation avatar Jul 04 '22 20:07 infrastation