diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index f24b6b346..3a020d61c 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -346,6 +346,38 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX & } } +static bool _winHasRoute(const NET_LUID &interfaceLuid, const NET_IFINDEX &interfaceIndex, const InetAddress &target, const InetAddress &via) +{ + MIB_IPFORWARD_ROW2 rtrow; + InitializeIpForwardEntry(&rtrow); + rtrow.InterfaceLuid.Value = interfaceLuid.Value; + rtrow.InterfaceIndex = interfaceIndex; + if (target.ss_family == AF_INET) { + rtrow.DestinationPrefix.Prefix.si_family = AF_INET; + rtrow.DestinationPrefix.Prefix.Ipv4.sin_family = AF_INET; + rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast(&target)->sin_addr.S_un.S_addr; + if (via.ss_family == AF_INET) { + rtrow.NextHop.si_family = AF_INET; + rtrow.NextHop.Ipv4.sin_family = AF_INET; + rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast(&via)->sin_addr.S_un.S_addr; + } + } else if (target.ss_family == AF_INET6) { + rtrow.DestinationPrefix.Prefix.si_family = AF_INET6; + rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6; + memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte, reinterpret_cast(&target)->sin6_addr.u.Byte, 16); + if (via.ss_family == AF_INET6) { + rtrow.NextHop.si_family = AF_INET6; + rtrow.NextHop.Ipv6.sin6_family = AF_INET6; + memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte, reinterpret_cast(&via)->sin6_addr.u.Byte, 16); + } + } else { + return false; + } + rtrow.DestinationPrefix.PrefixLength = target.netmaskBits(); + rtrow.SitePrefixLength = rtrow.DestinationPrefix.PrefixLength; + return (GetIpForwardEntry2(&rtrow) == NO_ERROR); +} + #endif // __WINDOWS__ -------------------------------------------------------- #ifndef ZT_ROUTING_SUPPORT_FOUND @@ -463,11 +495,11 @@ bool ManagedRoute::sync() #ifdef __WINDOWS__ // -------------------------------------------------------- - if (!_applied.count(leftt)) { + if ( (!_applied.count(leftt)) || (!_winHasRoute(interfaceLuid,interfaceIndex,leftt,_via)) ) { _applied[leftt] = false; // boolean unused _winRoute(false,interfaceLuid,interfaceIndex,leftt,_via); } - if ((rightt)&&(!_applied.count(rightt))) { + if ( (rightt) && ( (!_applied.count(rightt)) || (!_winHasRoute(interfaceLuid,interfaceIndex,rightt,_via)) ) ) { _applied[rightt] = false; // boolean unused _winRoute(false,interfaceLuid,interfaceIndex,rightt,_via); }