@@ -70,11 +70,13 @@ WindowsRouteMonitor::~WindowsRouteMonitor() {
70
70
71
71
void WindowsRouteMonitor::updateExclusionRoute (MIB_IPFORWARD_ROW2* data,
72
72
void * ptable) {
73
- PMIB_IPFORWARD_TABLE2 table = ( PMIB_IPFORWARD_TABLE2) ptable;
74
- SOCKADDR_INET nexthop;
73
+ PMIB_IPFORWARD_TABLE2 table = reinterpret_cast < PMIB_IPFORWARD_TABLE2>( ptable) ;
74
+ SOCKADDR_INET nexthop = { 0 } ;
75
75
quint64 bestLuid = 0 ;
76
76
int bestMatch = -1 ;
77
+ ULONG bestMetric = ULONG_MAX;
77
78
79
+ nexthop.si_family = data->DestinationPrefix .Prefix .si_family ;
78
80
for (ULONG i = 0 ; i < table->NumEntries ; i++) {
79
81
MIB_IPFORWARD_ROW2* row = &table->Table [i];
80
82
// Ignore routes into the VPN interface.
@@ -114,10 +116,28 @@ void WindowsRouteMonitor::updateExclusionRoute(MIB_IPFORWARD_ROW2* data,
114
116
continue ;
115
117
}
116
118
119
+ // Ensure that the outgoing network interface is actually online and usable.
120
+ DWORD result;
121
+ NL_NETWORK_CONNECTIVITY_HINT hint;
122
+ result = GetNetworkConnectivityHintForInterface (row->InterfaceIndex , &hint);
123
+ if ((result != NO_ERROR) ||
124
+ (hint.ConnectivityLevel == NetworkConnectivityLevelHintHidden)) {
125
+ logger.debug () << " Ignoring hidden ifindex:" << row->InterfaceIndex ;
126
+ continue ;
127
+ }
128
+
129
+ // Prefer routes with lower metric if we find multiple matches
130
+ // with the same prefix length.
131
+ if ((row->DestinationPrefix .PrefixLength == bestMatch) &&
132
+ (row->Metric >= bestMetric)) {
133
+ continue ;
134
+ }
135
+
117
136
// If we got here, then this is the longest prefix match so far.
118
137
memcpy (&nexthop, &row->NextHop , sizeof (SOCKADDR_INET));
119
138
bestLuid = row->InterfaceLuid .Value ;
120
139
bestMatch = row->DestinationPrefix .PrefixLength ;
140
+ bestMetric = row->Metric ;
121
141
}
122
142
123
143
// If neither the interface nor next-hop have changed, then do nothing.
@@ -135,7 +155,12 @@ void WindowsRouteMonitor::updateExclusionRoute(MIB_IPFORWARD_ROW2* data,
135
155
}
136
156
data->InterfaceLuid .Value = bestLuid;
137
157
memcpy (&data->NextHop , &nexthop, sizeof (SOCKADDR_INET));
138
- CreateIpForwardEntry2 (data);
158
+ if (data->InterfaceLuid .Value != 0 ) {
159
+ DWORD result = CreateIpForwardEntry2 (data);
160
+ if (result != NO_ERROR) {
161
+ logger.error () << " Failed to update route:" << result;
162
+ }
163
+ }
139
164
}
140
165
141
166
bool WindowsRouteMonitor::addExclusionRoute (const QHostAddress& address) {
0 commit comments