2024-05-07 18:50:34 +02:00
|
|
|
package networkmonitor
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2024-06-25 10:35:51 +02:00
|
|
|
"strings"
|
2024-05-07 18:50:34 +02:00
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
|
2024-06-13 13:24:24 +02:00
|
|
|
"github.com/netbirdio/netbird/client/internal/routemanager/systemops"
|
2024-05-07 18:50:34 +02:00
|
|
|
)
|
|
|
|
|
2024-06-13 13:24:24 +02:00
|
|
|
func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop, callback func()) error {
|
2024-08-20 19:13:16 +02:00
|
|
|
routeMonitor, err := systemops.NewRouteMonitor(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to create route monitor: %w", err)
|
2024-05-07 18:50:34 +02:00
|
|
|
}
|
2024-08-20 19:13:16 +02:00
|
|
|
defer func() {
|
|
|
|
if err := routeMonitor.Stop(); err != nil {
|
|
|
|
log.Errorf("Network monitor: failed to stop route monitor: %v", err)
|
|
|
|
}
|
|
|
|
}()
|
2024-05-07 18:50:34 +02:00
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
2024-05-17 09:43:18 +02:00
|
|
|
return ErrStopped
|
2024-08-20 19:13:16 +02:00
|
|
|
case route := <-routeMonitor.RouteUpdates():
|
|
|
|
if route.Destination.Bits() != 0 {
|
|
|
|
continue
|
2024-05-07 18:50:34 +02:00
|
|
|
}
|
|
|
|
|
2024-08-20 19:13:16 +02:00
|
|
|
if routeChanged(route, nexthopv4, nexthopv6, callback) {
|
|
|
|
break
|
2024-05-07 18:50:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-06-25 10:35:51 +02:00
|
|
|
}
|
2024-05-07 18:50:34 +02:00
|
|
|
|
2024-08-20 19:13:16 +02:00
|
|
|
func routeChanged(route systemops.RouteUpdate, nexthopv4, nexthopv6 systemops.Nexthop, callback func()) bool {
|
|
|
|
intf := "<nil>"
|
|
|
|
if route.Interface != nil {
|
|
|
|
intf = route.Interface.Name
|
|
|
|
if isSoftInterface(intf) {
|
|
|
|
log.Debugf("Network monitor: ignoring default route change for soft interface %s", intf)
|
|
|
|
return false
|
|
|
|
}
|
2024-05-07 18:50:34 +02:00
|
|
|
}
|
|
|
|
|
2024-08-20 19:13:16 +02:00
|
|
|
switch route.Type {
|
|
|
|
case systemops.RouteModified:
|
|
|
|
// TODO: get routing table to figure out if our route is affected for modified routes
|
|
|
|
log.Infof("Network monitor: default route changed: via %s, interface %s", route.NextHop, intf)
|
|
|
|
go callback()
|
|
|
|
return true
|
|
|
|
case systemops.RouteAdded:
|
|
|
|
if route.NextHop.Is4() && route.NextHop != nexthopv4.IP || route.NextHop.Is6() && route.NextHop != nexthopv6.IP {
|
|
|
|
log.Infof("Network monitor: default route added: via %s, interface %s", route.NextHop, intf)
|
|
|
|
go callback()
|
2024-05-07 18:50:34 +02:00
|
|
|
return true
|
2024-08-20 19:13:16 +02:00
|
|
|
}
|
|
|
|
case systemops.RouteDeleted:
|
|
|
|
if nexthopv4.Intf != nil && route.NextHop == nexthopv4.IP || nexthopv6.Intf != nil && route.NextHop == nexthopv6.IP {
|
|
|
|
log.Infof("Network monitor: default route removed: via %s, interface %s", route.NextHop, intf)
|
|
|
|
go callback()
|
2024-05-07 18:50:34 +02:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2024-07-22 19:44:15 +02:00
|
|
|
func isSoftInterface(name string) bool {
|
|
|
|
return strings.Contains(strings.ToLower(name), "isatap") || strings.Contains(strings.ToLower(name), "teredo")
|
2024-05-07 18:50:34 +02:00
|
|
|
}
|