-
Notifications
You must be signed in to change notification settings - Fork 864
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Request filter for SocketCAN device #1247
Comments
|
I did originally try link[2:2] as well, but nothing got captured. |
Thank you, with the file post-capture filtering works as expected. I could get the USB dongle, would it need to be connected to something to capture any packets? The Wireshark decoder uses only the low 11 bits for the ID, so |
Okay, it seems the can ID must be a value that fits within 7 bits, so that explains the Wireshark information. To set this up, you don't need any other equipment, just the adapter. Bring it up with:
Send a message with: You can run the capture on a different CLI to test filtering. |
Thank you for the comments, I have ordered a very similar USB dongle and hopefully will be able to reproduce this problem soonish. Meanwhile other developers may want to make additional input. |
This is how my USB CAN device identifies itself:
On Debian 12/AMD64 the problem seems to reproduce as described, in that
Without the filter the capture has the packets of interest (which take 2-3 seconds to appear in the capture after the
This way, on the surface everything looks fine on the user-space side of the capture device, so maybe something could be wrong in the kernel. |
Using the previously discussed setup, I tried to debug this problem and started three processes:
As far as I understand this observed behaviour, |
Apparently, this bug does not even require a CAN hardware to reproduce, e.g. on Debian 12:
Then run the three programs as shown above using |
Thanks for confirming that and looking into it. |
The problem reproduces only for a live capture that uses kernel filtering. With the change below --- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -4598,7 +4598,7 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
/* Install kernel level filter if possible */
- if (handle->fcode.bf_len > USHRT_MAX) {
+ if (handle->fcode.bf_len > 0) {
/*
* fcode.len is an unsigned short for current kernel.
* I have yet to see BPF-Code with that much |
The problem reproduces exactly the same using two USB-CAN adapters plugged into two separate hosts and connected with wire, where on one host |
As it turns out, capturing on the "any" pseudo-interface in Linux captures CAN frames as well, but the encoding is different and the difference looks related to this problem. This is what the remote end sends:
This is what local end receives on the SocketCAN device:
The same frame looks different on the "any" pseudo-interface:
The first four bytes look endian-swapped, which looks consistent with the way Linux kernel source stores these bytes: typedef __u32 canid_t;
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ A test confirms that the encoding seen on the "any" pseudo-interface is the encoding the kernel mode filter gets on input when capturing on the "can0" interface: One other odd thing is that when a filter accesses the first four octets, the first CAN packet does not match the filter, but subsequent identical packets do:
It is not clear whether this effect is related. |
This seems most likely related to the byte order processing in One issue here is that this conversion does not occur consistently for both Another issue is that the kernel filter runs on the CAN message before the conversion, so as a long-term solution the filter bytecode would need to be rewritten to implement the reverse conversion on little-endian hosts. In particular, a new function similar to the existing @guyharris, does it make sense? Are there any other factors? |
I’d like to set capture filter for CAN ID.
Either specific CAN ID variable, or being able to specify which bytes of the payload to match.
Similar to this for selecting ID 5c2:
ether[2:2] == 0x05c2
That “ether” filter will not work, because the device type is SocketCAN.
However, that above filter does actually work if reading from a captured file.
I would like to be able to filter at the capture stage.
From current code:
case DLT_CAN_SOCKETCAN:
bpf_error(cstate, "CAN link-layer type filtering not implemented");
CAN only has an ID, length, and payload (of up to 8 bytes).
Even if we can only filter with specific bytes, that would be enough.
For instance, something like this maybe:
can[2:2] == 0x05c2
At least that way, we could define what bytes in the packet to filter for the CAN type.
Thanks
Paul.
The text was updated successfully, but these errors were encountered: