Closed Snshadow closed 6 months ago
The test cases are correct for what they do, they test that the instructions for a netmasked net are what are expected. The problem is expectation doesn't seem to work in eBPF, so obviously something subtle is missing.
For example, here are the eBPF instructions for ip net 127.0.0.0
[]golang.org/x/net/bpf.Instruction len: 8, cap: 12, [
golang.org/x/net/bpf.LoadAbsolute {Off: 12, Size: 2},
golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2048, SkipTrue: 0, SkipFalse: 5},
golang.org/x/net/bpf.LoadAbsolute {Off: 26, Size: 4},
golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2130706432, SkipTrue: 2, SkipFalse: 0},
golang.org/x/net/bpf.LoadAbsolute {Off: 30, Size: 4},
golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2130706432, SkipTrue: 0, SkipFalse: 1},
golang.org/x/net/bpf.RetConstant {Val: 262144},
golang.org/x/net/bpf.RetConstant {Val: 0},
]
And for ip net 127.0.0.0/24
:
[]golang.org/x/net/bpf.Instruction len: 10, cap: 16, [
golang.org/x/net/bpf.LoadAbsolute {Off: 12, Size: 2},
golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2048, SkipTrue: 0, SkipFalse: 7},
golang.org/x/net/bpf.LoadAbsolute {Off: 26, Size: 4},
golang.org/x/net/bpf.ALUOpConstant {Op: ALUOpAdd (0), Val: 4294967040},
golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2130706432, SkipTrue: 3, SkipFalse: 0},
golang.org/x/net/bpf.LoadAbsolute {Off: 30, Size: 4},
golang.org/x/net/bpf.ALUOpConstant {Op: ALUOpAdd (0), Val: 4294967040},
golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2130706432, SkipTrue: 0, SkipFalse: 1},
golang.org/x/net/bpf.RetConstant {Val: 262144},
golang.org/x/net/bpf.RetConstant {Val: 0},
]
First 3 steps are identical: load the protocol (at offset 12) and see that it matches "IP", then load src IP4 address (at offset 26).
After that it varies:
net 127.0.0.0
does a straight compare of the 4 bytes address to the expected 4 bytesALUOpConstant {Op: ALUOpAdd (0), Val: 0xffffff00}
, then tries to compare the address in the same way as the previous step.Both then move on to repeat the same thing with the destination address (offset 30).
I suspect something about the math with the CIDR compare process is off.
The hex of 127.0.0.0 is 0x7f000000
. So it should load that in. We then apply the netmask of 0xffffff00, so we should be left with 0x7f000000
. And then we compare it.
So it all looks like it should work.
@Snshadow check out the branch in #51, see if it fixes it. My tests show it does.
Working as intended for me as well.
Thank you for taking your time for fixing this.
Amazing what a one-letter typo can do. And because it is just one letter difference to another similarly-typed constant in the same package, linters didn't catch it either.
Using BPF filter with netmask does not capture any packets. In tcpdumps filter with netmask in handled correctly.
Looking into the test cases in https://github.com/packetcap/go-pcap/blob/master/filter/compile_cases_test.go#L1125, the test from https://github.com/packetcap/go-pcap/blob/master/filter/compile_test.go#L166-L178 passes with "net 192.168.0.0/24" without any issue, making it look like it should work.
Expected Behavior
Actual Behavior
Steps to Reproduce the Problem
Specifications