Skip to content

Commit 3cddaf8

Browse files
committed
fix: normalize IPv4 length and apply 4-byte alignment padding in Via struct
1 parent c05a276 commit 3cddaf8

2 files changed

Lines changed: 99 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: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,6 +2472,95 @@ func TestRouteViaAddDel(t *testing.T) {
24722472
}
24732473
}
24742474

2475+
func TestRouteMultiPathViaIPv4Mapped(t *testing.T) {
2476+
minKernelRequired(t, 5, 4)
2477+
t.Cleanup(setUpNetlinkTest(t))
2478+
2479+
link, err := LinkByName("lo")
2480+
if err != nil {
2481+
t.Fatal(err)
2482+
}
2483+
if err := LinkSetUp(link); err != nil {
2484+
t.Fatal(err)
2485+
}
2486+
2487+
buggyViaIP := net.ParseIP("1.1.1.1")
2488+
if len(buggyViaIP) != 16 {
2489+
t.Fatalf("expected a 16-byte IP object for the test, but got %d bytes", len(buggyViaIP))
2490+
}
2491+
2492+
dst := &net.IPNet{
2493+
IP: net.IPv4(192, 168, 99, 0),
2494+
Mask: net.CIDRMask(24, 32),
2495+
}
2496+
2497+
route := &Route{
2498+
LinkIndex: link.Attrs().Index,
2499+
Dst: dst,
2500+
MultiPath: []*NexthopInfo{
2501+
{
2502+
LinkIndex: link.Attrs().Index,
2503+
Flags: int(FLAG_ONLINK),
2504+
Via: &Via{
2505+
AddrFamily: FAMILY_V4,
2506+
Addr: buggyViaIP, // intentionally trying to send the 16-byte IP to the Kernel
2507+
},
2508+
},
2509+
},
2510+
}
2511+
2512+
if err := RouteAdd(route); err != nil {
2513+
t.Fatalf("RouteAdd should handle 16-byte IPv4 Via addresses: %v", err)
2514+
}
2515+
2516+
routes, err := RouteListFiltered(FAMILY_V4, &Route{Dst: dst}, RT_FILTER_DST)
2517+
if err != nil {
2518+
t.Fatal(err)
2519+
}
2520+
if len(routes) != 1 {
2521+
t.Fatal("Route was not added to the kernel properly")
2522+
}
2523+
2524+
if err := RouteDel(route); err != nil {
2525+
t.Fatal(err)
2526+
}
2527+
2528+
routesAfterDel, err := RouteListFiltered(FAMILY_V4, &Route{Dst: dst}, RT_FILTER_DST)
2529+
if err != nil {
2530+
t.Fatal(err)
2531+
}
2532+
if len(routesAfterDel) != 0 {
2533+
t.Fatal("Route was not deleted from the kernel properly")
2534+
}
2535+
}
2536+
2537+
func TestViaEncodeIPv4Mapped(t *testing.T) {
2538+
via := &Via{
2539+
AddrFamily: FAMILY_V4,
2540+
Addr: net.ParseIP("1.1.1.1"),
2541+
}
2542+
2543+
b, err := via.Encode()
2544+
if err != nil {
2545+
t.Fatal(err)
2546+
}
2547+
2548+
if len(b) != 6 {
2549+
t.Fatalf("expected encoded Via length to be 6 bytes, got %d", len(b))
2550+
}
2551+
2552+
gotFamily := int(native.Uint16(b[0:2]))
2553+
if gotFamily != FAMILY_V4 {
2554+
t.Fatalf("unexpected address family; got %d, want %d", gotFamily, FAMILY_V4)
2555+
}
2556+
2557+
gotAddr := net.IP(b[2:6])
2558+
wantAddr := net.IPv4(1, 1, 1, 1)
2559+
if !gotAddr.Equal(wantAddr) {
2560+
t.Fatalf("unexpected IPv4 address; got %s, want %s", gotAddr, wantAddr)
2561+
}
2562+
}
2563+
24752564
func TestRouteUIDOption(t *testing.T) {
24762565
t.Cleanup(setUpNetlinkTest(t))
24772566

0 commit comments

Comments
 (0)