diff --git a/route_linux.go b/route_linux.go index d989bd7..0b00ddd 100644 --- a/route_linux.go +++ b/route_linux.go @@ -1539,6 +1539,7 @@ type RouteGetOptions struct { Iif string IifIndex int Oif string + OifIndex int VrfName string SrcAddr net.IP UID *uint32 @@ -1618,14 +1619,20 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption req.AddData(nl.NewRtAttr(unix.RTA_IIF, b)) } + oifIndex := uint32(0) if len(options.Oif) > 0 { link, err := h.LinkByName(options.Oif) if err != nil { return nil, err } + oifIndex = uint32(link.Attrs().Index) + } else if options.OifIndex > 0 { + oifIndex = uint32(options.OifIndex) + } + if oifIndex > 0 { b := make([]byte, 4) - native.PutUint32(b, uint32(link.Attrs().Index)) + native.PutUint32(b, oifIndex) req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) } diff --git a/route_test.go b/route_test.go index 0326be4..0a2745e 100644 --- a/route_test.go +++ b/route_test.go @@ -1436,6 +1436,16 @@ func TestRouteOifOption(t *testing.T) { t.Fatal("Get route from unmatched interface") } + // check getting route from specified Oifindex + routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{OifIndex: link1.Attrs().Index}) + if err != nil { + t.Fatal(err) + } + if len(routes) != 1 || routes[0].LinkIndex != link1.Attrs().Index || + !routes[0].Gw.Equal(gw1) { + t.Fatal("Get route from unmatched interface") + } + routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth1"}) if err != nil { t.Fatal(err) @@ -1446,6 +1456,14 @@ func TestRouteOifOption(t *testing.T) { t.Fatal("Get route from unmatched interface") } + routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{OifIndex: link2.Attrs().Index}) + if err != nil { + t.Fatal(err) + } + if len(routes) != 1 || routes[0].LinkIndex != link2.Attrs().Index || + !routes[0].Gw.Equal(gw2) { + t.Fatal("Get route from unmatched interface") + } } func TestFilterDefaultRoute(t *testing.T) {