diff --git a/client/internal/routemanager/systemops.go b/client/internal/routemanager/systemops.go index 595425b94..9115763d8 100644 --- a/client/internal/routemanager/systemops.go +++ b/client/internal/routemanager/systemops.go @@ -21,7 +21,7 @@ func addToRouteTableIfNoExists(prefix netip.Prefix, addr string) error { } if prefixGateway != nil && !prefixGateway.Equal(gateway) { - log.Warnf("route for network %s already exist and is pointing to the gateway: %s, won't add another one", prefix, prefixGateway) + log.Warnf("skipping adding a new route for network %s because it already exists and is pointing to the non default gateway: %s", prefix, prefixGateway) return nil } return addToRouteTable(prefix, addr) @@ -45,11 +45,14 @@ func getExistingRIBRouteGateway(prefix netip.Prefix) (net.IP, error) { if err != nil { return nil, err } - _, _, localGatewayAddress, err := r.Route(prefix.Addr().AsSlice()) + _, gateway, preferredSrc, err := r.Route(prefix.Addr().AsSlice()) if err != nil { log.Errorf("getting routes returned an error: %v", err) return nil, errRouteNotFound } + if gateway == nil { + return preferredSrc, nil + } - return localGatewayAddress, nil + return gateway, nil } diff --git a/client/internal/routemanager/systemops_test.go b/client/internal/routemanager/systemops_test.go index 821e9a46e..8f6f4c6fe 100644 --- a/client/internal/routemanager/systemops_test.go +++ b/client/internal/routemanager/systemops_test.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/netbirdio/netbird/iface" "github.com/stretchr/testify/require" + "net" "net/netip" "testing" ) @@ -66,3 +67,45 @@ func TestAddRemoveRoutes(t *testing.T) { }) } } + +func TestGetExistingRIBRouteGateway(t *testing.T) { + gateway, err := getExistingRIBRouteGateway(netip.MustParsePrefix("0.0.0.0/0")) + if err != nil { + t.Fatal("shouldn't return error when fetching the gateway: ", err) + } + if gateway == nil { + t.Fatal("should return a gateway") + } + addresses, err := net.InterfaceAddrs() + if err != nil { + t.Fatal("shouldn't return error when fetching interface addresses: ", err) + } + + var testingIP string + var testingPrefix netip.Prefix + for _, address := range addresses { + if address.Network() != "ip+net" { + continue + } + prefix := netip.MustParsePrefix(address.String()) + if !prefix.Addr().IsLoopback() && prefix.Addr().Is4() { + testingIP = prefix.Addr().String() + testingPrefix = prefix.Masked() + break + } + } + + localIP, err := getExistingRIBRouteGateway(testingPrefix) + if err != nil { + t.Fatal("shouldn't return error: ", err) + } + if localIP == nil { + t.Fatal("should return a gateway for local network") + } + if localIP.String() == gateway.String() { + t.Fatal("local ip should not match with gateway IP") + } + if localIP.String() != testingIP { + t.Fatalf("local ip should match with testing IP: want %s got %s", testingIP, localIP.String()) + } +}