Skip to content

Commit 4e35dc9

Browse files
barisaydogduaboch
authored andcommitted
fix: normalize IPv4 length and apply 4-byte alignment padding in Via struct
1 parent d9154c8 commit 4e35dc9

2 files changed

Lines changed: 105 additions & 1 deletion

File tree

route_linux.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,11 +780,20 @@ func (v *Via) Family() int {
780780

781781
func (v *Via) Encode() ([]byte, error) {
782782
buf := &bytes.Buffer{}
783+
783784
err := binary.Write(buf, native, uint16(v.AddrFamily))
784785
if err != nil {
785786
return nil, err
786787
}
787-
err = binary.Write(buf, native, v.Addr)
788+
addr := v.Addr
789+
if v.AddrFamily == nl.FAMILY_V4 {
790+
ipv4 := addr.To4()
791+
if ipv4 == nil {
792+
return nil, fmt.Errorf("invalid IPv4 address in Via struct")
793+
}
794+
addr = ipv4
795+
}
796+
err = binary.Write(buf, native, addr)
788797
if err != nil {
789798
return nil, err
790799
}

route_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,6 +2529,101 @@ func TestRouteViaAddDel(t *testing.T) {
25292529
}
25302530
}
25312531

2532+
// TestRouteMultiPathViaIPv4Mapped verifies that adding a Multipath route
2533+
// with a 16-byte IPv4-mapped address is correctly normalized to 4 bytes
2534+
// during encoding, preventing kernel invalid gateway rejections.
2535+
func TestRouteMultiPathViaIPv4Mapped(t *testing.T) {
2536+
minKernelRequired(t, 5, 4)
2537+
t.Cleanup(setUpNetlinkTest(t))
2538+
2539+
link, err := LinkByName("lo")
2540+
if err != nil {
2541+
t.Fatal(err)
2542+
}
2543+
if err := LinkSetUp(link); err != nil {
2544+
t.Fatal(err)
2545+
}
2546+
2547+
buggyViaIP := net.ParseIP("1.1.1.1")
2548+
if len(buggyViaIP) != 16 {
2549+
t.Fatalf("expected a 16-byte IP object for the test, but got %d bytes", len(buggyViaIP))
2550+
}
2551+
2552+
dst := &net.IPNet{
2553+
IP: net.IPv4(192, 168, 99, 0),
2554+
Mask: net.CIDRMask(24, 32),
2555+
}
2556+
2557+
route := &Route{
2558+
LinkIndex: link.Attrs().Index,
2559+
Dst: dst,
2560+
MultiPath: []*NexthopInfo{
2561+
{
2562+
LinkIndex: link.Attrs().Index,
2563+
Flags: int(FLAG_ONLINK),
2564+
Via: &Via{
2565+
AddrFamily: FAMILY_V4,
2566+
Addr: buggyViaIP, // intentionally trying to send the 16-byte IP to the Kernel
2567+
},
2568+
},
2569+
},
2570+
}
2571+
2572+
if err := RouteAdd(route); err != nil {
2573+
t.Fatalf("RouteAdd should handle 16-byte IPv4 Via addresses: %v", err)
2574+
}
2575+
2576+
routes, err := RouteListFiltered(FAMILY_V4, &Route{Dst: dst}, RT_FILTER_DST)
2577+
if err != nil {
2578+
t.Fatal(err)
2579+
}
2580+
if len(routes) != 1 {
2581+
t.Fatal("Route was not added to the kernel properly")
2582+
}
2583+
2584+
if err := RouteDel(route); err != nil {
2585+
t.Fatal(err)
2586+
}
2587+
2588+
routesAfterDel, err := RouteListFiltered(FAMILY_V4, &Route{Dst: dst}, RT_FILTER_DST)
2589+
if err != nil {
2590+
t.Fatal(err)
2591+
}
2592+
if len(routesAfterDel) != 0 {
2593+
t.Fatal("Route was not deleted from the kernel properly")
2594+
}
2595+
}
2596+
2597+
// TestViaEncodeIPv4Mapped verifies that a 16-byte IPv4-mapped address
2598+
// is correctly compressed and encoded into a strictly 6-byte slice
2599+
// (2 bytes for AddrFamily + 4 bytes for the IPv4 address).
2600+
func TestViaEncodeIPv4Mapped(t *testing.T) {
2601+
via := &Via{
2602+
AddrFamily: FAMILY_V4,
2603+
Addr: net.ParseIP("1.1.1.1"),
2604+
}
2605+
2606+
b, err := via.Encode()
2607+
if err != nil {
2608+
t.Fatal(err)
2609+
}
2610+
2611+
if len(b) != 6 {
2612+
t.Fatalf("expected encoded Via length to be 6 bytes, got %d", len(b))
2613+
}
2614+
2615+
gotFamily := int(native.Uint16(b[0:2]))
2616+
if gotFamily != FAMILY_V4 {
2617+
t.Fatalf("unexpected address family; got %d, want %d", gotFamily, FAMILY_V4)
2618+
}
2619+
2620+
gotAddr := net.IP(b[2:6])
2621+
wantAddr := net.IPv4(1, 1, 1, 1)
2622+
if !gotAddr.Equal(wantAddr) {
2623+
t.Fatalf("unexpected IPv4 address; got %s, want %s", gotAddr, wantAddr)
2624+
}
2625+
}
2626+
25322627
func TestRouteUIDOption(t *testing.T) {
25332628
t.Cleanup(setUpNetlinkTest(t))
25342629

0 commit comments

Comments
 (0)