Trying to test "sio", "dpc", "opc", "sls", "hsio", "hdpc", "hopc",
"hsls", "vpi" or "vci" for being not equal to an integer produces
bytecode that does exactly the opposite of what is required:
$ filtertest MTP2 'sls != 8'
(000) ldb [7]
(001) and #0xf0
(002) jeq #0x80 jt 3 jf 4
(003) ret #262144
(004) ret #0
$ filtertest SUNATM 'vci != 0x1234'
(000) ldh [2]
(001) jeq #0x1234 jt 2 jf 3
(002) ret #262144
(003) ret #0
All other comparisons for these fields work as expected. The problem
occurs when jtype == BPF_JEQ and reverse == 1 in gen_ncmp(), which
reverses the logical meaning only when jtype is one of {BPF_JGT,
BPF_JGE}. This bug has been in place since the initial
implementations in 2002 for ATM (commit
243b20e) and in 2005 for MTP
(commit
a0a4852).
Make the reversal in gen_ncmp() nonspecific to jtype, same as it is in
gen_relation_internal(). This should not cause undesired side effects
because in this context reverse == 1 only if the caller is:
* gen_cmp_lt(), in which case jtype == BPF_JGE; or
* gen_cmp_le(), in which case jtype == BPF_JGT; or
* gen_mtp2type_abbrev(), in which case jtype == BPF_JGT; or
* gen_atmfield_code_internal(), in which case jtype is one of {BPF_JGT,
BPF_JGE, BPF_JEQ} via "atmvalue: ... irelop NUM" in grammar.y.in; or
* gen_mtp3field_code_internal(), idem via "mtp3value:" ibid.
This way, without jtype the reversal does exactly what it needs to do,
and nothing else.
$ filtertest MTP2 'sls != 8'
(000) ldb [7]
(001) and #0xf0
(002) jeq #0x80 jt 3 jf 4
(003) ret #0
(004) ret #262144
$ filtertest SUNATM 'vci != 0x1234'
(000) ldh [2]
(001) jeq #0x1234 jt 2 jf 3
(002) ret #0
(003) ret #262144