Skip to content

Commit 8f96fd8

Browse files
qxoqxaboch
authored andcommitted
# rule: fix 32-bit platforms don't support adding rules with a mark value of 0x80000000/0xF0000000 ~ 0xF0000000/0xF0000000
The maximum value for an `int` type on a 32-bit platform is 0x7FFFFFFF. Since 0xF0000000 exceeds this limit, we need to use `uint` instead of `int` to handle these values.
1 parent d13535d commit 8f96fd8

File tree

5 files changed

+295
-33
lines changed

5 files changed

+295
-33
lines changed

route_linux.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,7 +1521,7 @@ type RouteGetOptions struct {
15211521
VrfName string
15221522
SrcAddr net.IP
15231523
UID *uint32
1524-
Mark int
1524+
Mark uint32
15251525
FIBMatch bool
15261526
}
15271527

@@ -1630,7 +1630,7 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
16301630

16311631
if options.Mark > 0 {
16321632
b := make([]byte, 4)
1633-
native.PutUint32(b, uint32(options.Mark))
1633+
native.PutUint32(b, options.Mark)
16341634

16351635
req.AddData(nl.NewRtAttr(unix.RTA_MARK, b))
16361636
}

route_test.go

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,27 +2449,41 @@ func TestRouteFWMarkOption(t *testing.T) {
24492449
}
24502450

24512451
// a table different than unix.RT_TABLE_MAIN
2452-
testtable := 1000
2452+
testTable0 := 254
2453+
testTable1 := 1000
2454+
testTable2 := 1001
24532455

2454-
gw1 := net.IPv4(192, 168, 1, 254)
2455-
gw2 := net.IPv4(192, 168, 2, 254)
2456+
gw0 := net.IPv4(192, 168, 1, 254)
2457+
gw1 := net.IPv4(192, 168, 2, 254)
2458+
gw2 := net.IPv4(192, 168, 3, 254)
24562459

2457-
// add default route via gw1 (in main route table by default)
2460+
// add default route via gw0 (in main route table by default)
24582461
defaultRouteMain := Route{
2459-
Dst: nil,
2460-
Gw: gw1,
2462+
Dst: nil,
2463+
Gw: gw0,
2464+
Table: testTable0,
24612465
}
24622466
if err := RouteAdd(&defaultRouteMain); err != nil {
24632467
t.Fatal(err)
24642468
}
24652469

2470+
// add default route via gw1 in test route table
2471+
defaultRouteTest1 := Route{
2472+
Dst: nil,
2473+
Gw: gw1,
2474+
Table: testTable1,
2475+
}
2476+
if err := RouteAdd(&defaultRouteTest1); err != nil {
2477+
t.Fatal(err)
2478+
}
2479+
24662480
// add default route via gw2 in test route table
2467-
defaultRouteTest := Route{
2481+
defaultRouteTest2 := Route{
24682482
Dst: nil,
24692483
Gw: gw2,
2470-
Table: testtable,
2484+
Table: testTable2,
24712485
}
2472-
if err := RouteAdd(&defaultRouteTest); err != nil {
2486+
if err := RouteAdd(&defaultRouteTest2); err != nil {
24732487
t.Fatal(err)
24742488
}
24752489

@@ -2481,34 +2495,70 @@ func TestRouteFWMarkOption(t *testing.T) {
24812495
if err != nil {
24822496
t.Fatal(err)
24832497
}
2484-
if len(routes) != 2 || routes[0].Table == routes[1].Table {
2498+
if len(routes) != 3 || routes[0].Table == routes[1].Table || routes[1].Table == routes[2].Table ||
2499+
routes[0].Table == routes[2].Table {
24852500
t.Fatal("Routes not added properly")
24862501
}
24872502

24882503
// add a rule that fwmark match should result in route lookup of test table
2489-
fwmark := 1000
2504+
fwmark1 := uint32(0xAFFFFFFF)
2505+
fwmark2 := uint32(0xBFFFFFFF)
24902506

24912507
rule := NewRule()
2492-
rule.Mark = fwmark
2493-
rule.Mask = 0xFFFFFFFF
2494-
rule.Table = testtable
2508+
rule.Mark = fwmark1
2509+
rule.Mask = &[]uint32{0xFFFFFFFF}[0]
2510+
2511+
rule.Table = testTable1
24952512
if err := RuleAdd(rule); err != nil {
24962513
t.Fatal(err)
24972514
}
24982515

2516+
rule = NewRule()
2517+
rule.Mark = fwmark2
2518+
rule.Mask = &[]uint32{0xFFFFFFFF}[0]
2519+
rule.Table = testTable2
2520+
if err := RuleAdd(rule); err != nil {
2521+
t.Fatal(err)
2522+
}
2523+
2524+
rules, err := RuleListFiltered(FAMILY_V4, &Rule{Mark: fwmark1}, RT_FILTER_MARK)
2525+
if err != nil {
2526+
t.Fatal(err)
2527+
}
2528+
if len(rules) != 1 || rules[0].Table != testTable1 || rules[0].Mark != fwmark1 {
2529+
t.Fatal("Rules not added properly")
2530+
}
2531+
2532+
rules, err = RuleListFiltered(FAMILY_V4, &Rule{Mark: fwmark2}, RT_FILTER_MARK)
2533+
if err != nil {
2534+
t.Fatal(err)
2535+
}
2536+
if len(rules) != 1 || rules[0].Table != testTable2 || rules[0].Mark != fwmark2 {
2537+
t.Fatal("Rules not added properly")
2538+
}
2539+
24992540
dstIP := net.IPv4(10, 1, 1, 1)
25002541

25012542
// check getting route without FWMark option
25022543
routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{})
25032544
if err != nil {
25042545
t.Fatal(err)
25052546
}
2547+
if len(routes) != 1 || !routes[0].Gw.Equal(gw0) {
2548+
t.Fatal(routes)
2549+
}
2550+
2551+
// check getting route with FWMark option
2552+
routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Mark: fwmark1})
2553+
if err != nil {
2554+
t.Fatal(err)
2555+
}
25062556
if len(routes) != 1 || !routes[0].Gw.Equal(gw1) {
25072557
t.Fatal(routes)
25082558
}
25092559

25102560
// check getting route with FWMark option
2511-
routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Mark: fwmark})
2561+
routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Mark: fwmark2})
25122562
if err != nil {
25132563
t.Fatal(err)
25142564
}

rule.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ type Rule struct {
1010
Priority int
1111
Family int
1212
Table int
13-
Mark int
14-
Mask int
13+
Mark uint32
14+
Mask *uint32
1515
Tos uint
1616
TunID uint
1717
Goto int
@@ -51,8 +51,8 @@ func NewRule() *Rule {
5151
SuppressIfgroup: -1,
5252
SuppressPrefixlen: -1,
5353
Priority: -1,
54-
Mark: -1,
55-
Mask: -1,
54+
Mark: 0,
55+
Mask: nil,
5656
Goto: -1,
5757
Flow: -1,
5858
}

rule_linux.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
102102
native.PutUint32(b, uint32(rule.Priority))
103103
req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b))
104104
}
105-
if rule.Mark >= 0 {
105+
if rule.Mark != 0 || rule.Mask != nil {
106106
b := make([]byte, 4)
107-
native.PutUint32(b, uint32(rule.Mark))
107+
native.PutUint32(b, rule.Mark)
108108
req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b))
109109
}
110-
if rule.Mask >= 0 {
110+
if rule.Mask != nil {
111111
b := make([]byte, 4)
112-
native.PutUint32(b, uint32(rule.Mask))
112+
native.PutUint32(b, *rule.Mask)
113113
req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b))
114114
}
115115
if rule.Flow >= 0 {
@@ -242,9 +242,10 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
242242
Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)),
243243
}
244244
case nl.FRA_FWMARK:
245-
rule.Mark = int(native.Uint32(attrs[j].Value[0:4]))
245+
rule.Mark = native.Uint32(attrs[j].Value[0:4])
246246
case nl.FRA_FWMASK:
247-
rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
247+
mask := native.Uint32(attrs[j].Value[0:4])
248+
rule.Mask = &mask
248249
case nl.FRA_TUN_ID:
249250
rule.TunID = uint(native.Uint64(attrs[j].Value[0:8]))
250251
case nl.FRA_IIFNAME:
@@ -297,7 +298,7 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
297298
continue
298299
case filterMask&RT_FILTER_MARK != 0 && rule.Mark != filter.Mark:
299300
continue
300-
case filterMask&RT_FILTER_MASK != 0 && rule.Mask != filter.Mask:
301+
case filterMask&RT_FILTER_MASK != 0 && !ptrEqual(rule.Mask, filter.Mask):
301302
continue
302303
}
303304
}
@@ -321,3 +322,13 @@ func (pr *RuleUIDRange) toRtAttrData() []byte {
321322
native.PutUint32(b[1], pr.End)
322323
return bytes.Join(b, []byte{})
323324
}
325+
326+
func ptrEqual(a, b *uint32) bool {
327+
if a == b {
328+
return true
329+
}
330+
if (a == nil) || (b == nil) {
331+
return false
332+
}
333+
return *a == *b
334+
}

0 commit comments

Comments
 (0)