libpcap
libpcap copied to clipboard
"(vlan, pppoe, mpls, etc.) or {other test}" filter applies offset change in the other test
We'd like to be able to filter packets on vlan 0xAAA coming from ip 127.127.127.127 as well as on vlan 0xBBB coming from 247.247.247.247.
We use the following filter expression: (vlan 0xAAA and ip src 127.127.127.127) or (vlan 0xBBB and ip src 247.247.247.247)
Unfortunately, the shifted offsets from the first vlan expression apply over parentheses, so that the resulting BPF looks as follows
┌ (fcn) fcn.00000000 224
│ fcn.00000000 ();
│ 0x00000000 280000000c00. ldh [12] ; 0xc
│ ┌─< 0x00000008 150004000081. jeq 0x8100, 0x00000030, 0x00000010
│ │ ; DATA XREFS from fcn.00000000 (0x48, 0x68, 0x78, 0x88)
│ │ 0x00000010 280000000c00. ldh [12] ; 0xc
│ ┌──< 0x00000018 15000200a888. jeq 0x88a8, 0x00000030, 0x00000020
│ ││ 0x00000020 280000000c00. ldh [12] ; 0xc
│ ┌───< 0x00000028 150000070091. jeq 0x9100, 0x00000030, 0x00000068
│ └└└─> 0x00000030 280000000e00. ldh [14] ; 0xe
│ 0x00000038 54000000ff0f. and 0xfff
│ ┌─< 0x00000040 15000004aa0a. jeq 0xaaa, 0x00000048, 0x00000068
│ └─> 0x00000048 280000001000. ldh [16] ; 0x10
│ ┌─< 0x00000050 150000020008. jeq 0x800, 0x00000058, 0x00000068
│ └─> 0x00000058 200000001e00. ld [30] ; 0x1e
│ ┌─< 0x00000060 15000d007f7f. jeq 0x7f7f7f7f, 0x000000d0, 0x00000068
│ │ 0x00000068 280000001000. ldh [16] ; 0x10
│ ┌──< 0x00000070 150004000081. jeq 0x8100, 0x00000098, 0x00000078
│ ││ 0x00000078 280000001000. ldh [16] ; 0x10
│ ┌───< 0x00000080 15000200a888. jeq 0x88a8, 0x00000098, 0x00000088
│ │││ 0x00000088 280000001000. ldh [16] ; 0x10
│ ┌────< 0x00000090 150000080091. jeq 0x9100, 0x00000098, 0x000000d8
│ └└└──> 0x00000098 280000001200. ldh [18] ; 0x12
│ │ 0x000000a0 54000000ff0f. and 0xfff
│ ┌──< 0x000000a8 15000005bb0b. jeq 0xbbb, 0x000000b0, 0x000000d8
│ └──> 0x000000b0 280000001400. ldh [20] ; 0x14
│ ┌──< 0x000000b8 150000030008. jeq 0x800, 0x000000c0, 0x000000d8
│ └──> 0x000000c0 200000002200. ld [34] ; 0x22 ; '"'
│ ┌──< 0x000000c8 15000001f7f7. jeq 0xf7f7f7f7, 0x000000d0, 0x000000d8
│ └└─> 0x000000d0 06000000ffff. ret 0xffff
└ 0x000000d8 060000000000. ret 0
Note the differing offsets at 0x58 (offset 30) and 0xc0 (offset 34).
Is there any way to approach this, other than replacing the second vlan expression with ether[12:4] == 0x91000bbb?
This is a known bug/limitation in the vlan generation code.
This all applies to other filter operations that adjust the payload offset, such as "pppoe" and "mpls". Fixing it would require some restructuring of the filter expression compiler, so that in "{offset-affecting predicate} or {other expression}" the offset would be the pre-modification value in {other expression} (and so that in "{offset-affecting predicate} and {other expression}" the offset would be the post-modification value in {other expression}).
(There may be some expressions people are using that depend on this behavior, so there is some risk in making that change, but that behavior is sufficiently contrary to naive expectations that I suspsect nobody depends it.)
We'd like to be able to filter packets on vlan 0xAAA coming from ip 127.127.127.127 as well as on vlan 0xBBB coming from 247.247.247.247.
We use the following filter expression:
(vlan 0xAAA and ip src 127.127.127.127) or (vlan 0xBBB and ip src 247.247.247.247)
As a work-around, you could try using this capture filter expression instead: (ether[12:2] = 0x8100 or ether[12:2] = 0x88a8 or ether[12:2] = 0x9100) and ether[16:2] = 0x0800 and ((ether[14:2] & 0xfff = 0xaaa and ether[30:4] = 0x7f7f7f7f) or (ether[14:2] & 0xfff = 0xbbb and ether[30:4] = 0xf7f7f7f7))
A question related to this problem was recently posted at https://ask.wireshark.org/question/24957/capture-filter-pppoes-does-not-work-as-expected/ where I elaborated more on the capture filter and broke it down. A similar analysis applies here. Basically, tcpdump -d is your friend.
For posterity, there is now a FAQ entry about this.