Skip to content

Commit af2a3ea

Browse files
chent1996aboch
authored andcommitted
rule: fix RuleListFiltered not matching default route Src/Dst
When a rule has Src or Dst set to 0.0.0.0/0 (or ::/0), the kernel omits the FRA_SRC/FRA_DST attribute since the prefix length is 0, leaving rule.Src/rule.Dst as nil. The filter logic treated nil as "not matching", so these rules were always incorrectly filtered out. Fixes #1080
1 parent 72a8cd7 commit af2a3ea

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

rule_linux.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
297297
if filter != nil {
298298
switch {
299299
case filterMask&RT_FILTER_SRC != 0 &&
300-
(rule.Src == nil || rule.Src.String() != filter.Src.String()):
300+
!ruleIPNetEqual(rule.Src, filter.Src):
301301
continue
302302
case filterMask&RT_FILTER_DST != 0 &&
303-
(rule.Dst == nil || rule.Dst.String() != filter.Dst.String()):
303+
!ruleIPNetEqual(rule.Dst, filter.Dst):
304304
continue
305305
case filterMask&RT_FILTER_TABLE != 0 &&
306306
filter.Table != unix.RT_TABLE_UNSPEC && rule.Table != filter.Table:
@@ -376,3 +376,25 @@ func (r Rule) typeString() string {
376376
return fmt.Sprintf("type(0x%x)", r.Type)
377377
}
378378
}
379+
380+
// ruleIPNetEqual compares two *net.IPNet for rule filtering purposes.
381+
// Unlike ipNetEqual in route.go, this treats a nil IPNet as equivalent
382+
// to 0.0.0.0/0 or ::/0, which is how the kernel represents "from all" /
383+
// "to all" rules (it omits FRA_SRC/FRA_DST when prefix length is 0).
384+
// Two /0 prefixes are always equal regardless of IP (e.g. 0.0.0.0/0 == 1.2.3.4/0).
385+
func ruleIPNetEqual(a, b *net.IPNet) bool {
386+
aIsDefault := a == nil || prefixLen(a) == 0
387+
bIsDefault := b == nil || prefixLen(b) == 0
388+
if aIsDefault && bIsDefault {
389+
return true
390+
}
391+
if aIsDefault != bIsDefault {
392+
return false
393+
}
394+
return ipNetEqual(a, b)
395+
}
396+
397+
func prefixLen(ipNet *net.IPNet) int {
398+
ones, _ := ipNet.Mask.Size()
399+
return ones
400+
}

0 commit comments

Comments
 (0)