RouteGetWithOptions: Add UID option

This commit is contained in:
Manjiri Gadagkar 2022-04-27 23:50:30 +00:00 committed by Alessandro Boch
parent 7e7feb220f
commit 6e2993d135
2 changed files with 104 additions and 0 deletions

View File

@ -1298,6 +1298,7 @@ type RouteGetOptions struct {
Oif string
VrfName string
SrcAddr net.IP
UID *uint32
}
// RouteGetWithOptions gets a route to a specific destination from the host system.
@ -1384,6 +1385,13 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr))
}
if options.UID != nil {
uid := *options.UID
b := make([]byte, 4)
native.PutUint32(b, uid)
req.AddData(nl.NewRtAttr(unix.RTA_UID, b))
}
}
msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE)

View File

@ -1644,3 +1644,99 @@ func TestRouteViaAddDel(t *testing.T) {
t.Fatal("Route not removed properly")
}
}
func TestRouteUIDOption(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
// setup eth0 so that network is reachable
err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
if err != nil {
t.Fatal(err)
}
link, err := LinkByName("eth0")
if err != nil {
t.Fatal(err)
}
if err = LinkSetUp(link); err != nil {
t.Fatal(err)
}
addr := &Addr{
IPNet: &net.IPNet{
IP: net.IPv4(192, 168, 1, 1),
Mask: net.CIDRMask(16, 32),
},
}
if err = AddrAdd(link, addr); err != nil {
t.Fatal(err)
}
// a table different than unix.RT_TABLE_MAIN
testtable := 1000
gw1 := net.IPv4(192, 168, 1, 254)
gw2 := net.IPv4(192, 168, 2, 254)
// add default route via gw1 (in main route table by default)
defaultRouteMain := Route{
Dst: nil,
Gw: gw1,
}
if err := RouteAdd(&defaultRouteMain); err != nil {
t.Fatal(err)
}
// add default route via gw2 in test route table
defaultRouteTest := Route{
Dst: nil,
Gw: gw2,
Table: testtable,
}
if err := RouteAdd(&defaultRouteTest); err != nil {
t.Fatal(err)
}
// check the routes are in different tables
routes, err := RouteListFiltered(FAMILY_V4, &Route{
Dst: nil,
Table: unix.RT_TABLE_UNSPEC,
}, RT_FILTER_DST|RT_FILTER_TABLE)
if err != nil {
t.Fatal(err)
}
if len(routes) != 2 || routes[0].Table == routes[1].Table {
t.Fatal("Routes not added properly")
}
// add a rule that uidrange match should result in route lookup of test table for uid other than current
// current uid is 0 due to skipUnlessRoot()
var uid uint32 = 1000
rule := NewRule()
rule.UIDRange = NewRuleUIDRange(uid, uid)
rule.Table = testtable
if err := RuleAdd(rule); err != nil {
t.Fatal(err)
}
dstIP := net.IPv4(10, 1, 1, 1)
// check getting route without UID option
routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{UID: nil})
if err != nil {
t.Fatal(err)
}
// current uid is outside uidrange; rule does not apply; lookup main table
if len(routes) != 1 || !routes[0].Gw.Equal(gw1) {
t.Fatal(routes)
}
// check getting route with UID option
routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{UID: &uid})
if err != nil {
t.Fatal(err)
}
// option uid is within uidrange; rule applies; lookup test table
if len(routes) != 1 || !routes[0].Gw.Equal(gw2) {
t.Fatal(routes)
}
}