From ce0591d924f4bab5ef6f822d4dcfb9d8d0613f8c Mon Sep 17 00:00:00 2001 From: domosekai <54519668+domosekai@users.noreply.github.com> Date: Wed, 28 Jul 2021 15:50:23 +0800 Subject: [PATCH 1/4] Add IPv6 route management for Windows client --- src/Cedar/VLanWin32.c | 61 +++---- src/Mayaqua/Network.c | 400 +++++++++++++++++++++++++++++++++++++++--- src/Mayaqua/Network.h | 9 + 3 files changed, 411 insertions(+), 59 deletions(-) diff --git a/src/Cedar/VLanWin32.c b/src/Cedar/VLanWin32.c index b90ac2d2..8b2b55ad 100644 --- a/src/Cedar/VLanWin32.c +++ b/src/Cedar/VLanWin32.c @@ -224,8 +224,7 @@ void RouteTrackingMain(SESSION *s) } // Search for the default gateway - if (IPToUINT(&e->DestIP) == 0 && - IPToUINT(&e->DestMask) == 0) + if (IsZeroIP(&e->DestIP) && IsZeroIP(&e->DestMask)) { Debug("e->InterfaceID = %u, t->VLanInterfaceId = %u\n", e->InterfaceID, t->VLanInterfaceId); @@ -236,30 +235,34 @@ void RouteTrackingMain(SESSION *s) is_vlan_want_to_be_default_gateway = true; vlan_default_gateway_metric = e->Metric; - if (vlan_default_gateway_metric >= 2 && + // PPP route fix (IPv4 only) + if (IsIP4(&e->DestIP)) + { + if (vlan_default_gateway_metric >= 2 && t->OldDefaultGatewayMetric == (vlan_default_gateway_metric - 1)) - { - // Restore because the PPP server rewrites - // the routing table selfishly - DeleteRouteEntry(e); - e->Metric--; - AddRouteEntry(e); - Debug("** Restore metric destroyed by PPP.\n"); + { + // Restore because the PPP server rewrites + // the routing table selfishly + DeleteRouteEntry(e); + e->Metric--; + AddRouteEntry(e); + Debug("** Restore metric destroyed by PPP.\n"); - any_modified = true; + any_modified = true; + } + + // Keep this entry + if (t->DefaultGatewayByVLan != NULL) + { + // Delete if there is one added last time + FreeRouteEntry(t->DefaultGatewayByVLan); + } + + t->DefaultGatewayByVLan = ZeroMalloc(sizeof(ROUTE_ENTRY)); + Copy(t->DefaultGatewayByVLan, e, sizeof(ROUTE_ENTRY)); + + t->OldDefaultGatewayMetric = vlan_default_gateway_metric; } - - // Keep this entry - if (t->DefaultGatewayByVLan != NULL) - { - // Delete if there is one added last time - FreeRouteEntry(t->DefaultGatewayByVLan); - } - - t->DefaultGatewayByVLan = ZeroMalloc(sizeof(ROUTE_ENTRY)); - Copy(t->DefaultGatewayByVLan, e, sizeof(ROUTE_ENTRY)); - - t->OldDefaultGatewayMetric = vlan_default_gateway_metric; } else { @@ -372,8 +375,7 @@ void RouteTrackingMain(SESSION *s) if (e->InterfaceID != t->VLanInterfaceId) { - if (IPToUINT(&e->DestIP) == 0 && - IPToUINT(&e->DestMask) == 0) + if (IsZeroIP(&e->DestIP) && IsZeroIP(&e->DestMask)) { char str[64]; // Default gateway is found @@ -633,11 +635,6 @@ void RouteTrackingStart(SESSION *s) MsFreeAdapter(a); } } - else - { - // For Win9x - Win32RenewDhcp9x(if_id); - } // Clear the DNS cache Win32FlushDnsCache(); @@ -782,12 +779,12 @@ void RouteTrackingStop(SESSION *s, ROUTE_TRACKING *t) // If the restoring routing entry is a default gateway and // the existing routing table contains another default gateway // on the interface, give up restoring the entry - if (IPToUINT(&e->DestIP) == 0 && IPToUINT(&e->DestMask) == 0) + if (IsZeroIP(&e->DestIP) && IsZeroIP(&e->DestMask)) { for (i = 0;i < table->NumEntry;i++) { ROUTE_ENTRY *r = table->Entry[i]; - if (IPToUINT(&r->DestIP) == 0 && IPToUINT(&r->DestMask) == 0) + if (IsZeroIP(&r->DestIP) && IsZeroIP(&r->DestMask)) { if (r->InterfaceID == e->InterfaceID) { diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 9ee9a10e..3d9c453d 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -62,6 +62,7 @@ struct ROUTE_CHANGE_DATA OVERLAPPED Overlapped; HANDLE Handle; UINT NumCalled; + bool Changed; }; #endif @@ -6124,7 +6125,7 @@ ICMP_RESULT *IcmpApiEchoSend(IP *dest_ip, UCHAR ttl, UCHAR *data, UINT size, UIN ROUTE_CHANGE *NewRouteChange() { #ifdef OS_WIN32 - return Win32NewRouteChange(); + return Win32NewRouteChange2(true, true, NULL); #else // OS_WIN32 return NULL; #endif // OS_WIN32 @@ -6134,7 +6135,7 @@ ROUTE_CHANGE *NewRouteChange() void FreeRouteChange(ROUTE_CHANGE *r) { #ifdef OS_WIN32 - Win32FreeRouteChange(r); + Win32FreeRouteChange2(r); #endif // OS_WIN32 } @@ -6142,7 +6143,7 @@ void FreeRouteChange(ROUTE_CHANGE *r) bool IsRouteChanged(ROUTE_CHANGE *r) { #ifdef OS_WIN32 - return Win32IsRouteChanged(r); + return Win32IsRouteChanged2(r); #else // OS_WIN32 return false; #endif // OS_WIN32 @@ -6173,6 +6174,57 @@ ROUTE_CHANGE *Win32NewRouteChange() return r; } +void Win32RouteChangeCallback(void *context, MIB_IPFORWARD_ROW2 *row, MIB_NOTIFICATION_TYPE nt) +{ + ROUTE_CHANGE_DATA *data = context; + data->Changed = true; +} + +// Routing table change detector function (For Vista and later) +ROUTE_CHANGE *Win32NewRouteChange2(bool ipv4, bool ipv6, void *callback) +{ + ROUTE_CHANGE *r; + BOOL ret; + ADDRESS_FAMILY family; + + r = ZeroMalloc(sizeof(ROUTE_CHANGE)); + + r->Data = ZeroMalloc(sizeof(ROUTE_CHANGE_DATA)); + + if (ipv4 && ipv6) + { + family = AF_UNSPEC; + } + else if (ipv6) + { + family = AF_INET6; + } + else + { + family = AF_INET; + } + + if (callback != NULL) + { + ret = NotifyRouteChange2(family, (PIPFORWARD_CHANGE_CALLBACK)callback, r->Data, false, &r->Data->Handle); + } + else + { + // Use default callback if not provided + ret = NotifyRouteChange2(family, (PIPFORWARD_CHANGE_CALLBACK)Win32RouteChangeCallback, r->Data, false, &r->Data->Handle); + } + + if (ret != NO_ERROR) + { + Free(r->Data); + Free(r); + + return NULL; + } + + return r; +} + void Win32FreeRouteChange(ROUTE_CHANGE *r) { // Validate arguments @@ -6188,6 +6240,20 @@ void Win32FreeRouteChange(ROUTE_CHANGE *r) Free(r); } +void Win32FreeRouteChange2(ROUTE_CHANGE *r) +{ + // Validate arguments + if (r == NULL) + { + return; + } + + CancelMibChangeNotify2(r->Data->Handle); + + Free(r->Data); + Free(r); +} + bool Win32IsRouteChanged(ROUTE_CHANGE *r) { // Validate arguments @@ -6210,6 +6276,28 @@ bool Win32IsRouteChanged(ROUTE_CHANGE *r) return false; } +bool Win32IsRouteChanged2(ROUTE_CHANGE *r) +{ + // Validate arguments + if (r == NULL) + { + return false; + } + + if ((r->Data->NumCalled++) == 0) + { + return true; + } + + if (r->Data->Changed) + { + r->Data->Changed = false; + return true; + } + + return false; +} + typedef struct WIN32_ACCEPT_CHECK_DATA { bool IsIPv6; @@ -6481,6 +6569,17 @@ void GenerateEui64Address6(UCHAR *dst, UCHAR *mac) } // Examine whether two IP addresses are in the same network +bool IsInSameNetwork(IP *a1, IP *a2, IP *subnet) +{ + if (IsIP4(a1)) + { + return IsInSameNetwork4(a1, a2, subnet); + } + else + { + return IsInSameNetwork6(a1, a2, subnet); + } +} bool IsInSameNetwork6ByStr(char *ip1, char *ip2, char *subnet) { IP p1, p2, s; @@ -9371,6 +9470,23 @@ void Win32DeleteRouteEntry(ROUTE_ENTRY *e) Free(p); } +// Remove a routing entry from the routing table (For Vista and later) +void Win32DeleteRouteEntry2(ROUTE_ENTRY *e) +{ + MIB_IPFORWARD_ROW2 *p; + // Validate arguments + if (e == NULL) + { + return; + } + + p = ZeroMallocFast(sizeof(MIB_IPFORWARD_ROW2)); + Win32RouteEntryToIpForwardRow2(p, e); + + DeleteIpForwardEntry2(p); + Free(p); +} + // Add a routing entry to the routing table bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists) { @@ -9418,6 +9534,53 @@ bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists) return ret; } +// Add a routing entry to the routing table (For Vista and later) +bool Win32AddRouteEntry2(ROUTE_ENTRY *e, bool *already_exists) +{ + bool ret = false; + bool dummy = false; + MIB_IPFORWARD_ROW2 *p; + UINT err = 0; + // Validate arguments + if (e == NULL) + { + return false; + } + if (already_exists == NULL) + { + already_exists = &dummy; + } + + *already_exists = false; + + p = ZeroMallocFast(sizeof(MIB_IPFORWARD_ROW2)); + Win32RouteEntryToIpForwardRow2(p, e); + + err = CreateIpForwardEntry2(p); + if (err != 0) + { + if (err == ERROR_OBJECT_ALREADY_EXISTS) + { + Debug("CreateIpForwardEntry2: Already Exists\n"); + *already_exists = true; + ret = true; + } + else + { + Debug("CreateIpForwardEntry2 Error: %u\n", err); + ret = false; + } + } + else + { + ret = true; + } + + Free(p); + + return ret; +} + // Get the routing table ROUTE_TABLE *Win32GetRouteTable() { @@ -9485,6 +9648,68 @@ FAILED: return t; } +// Get the routing table (For Vista and later) +ROUTE_TABLE *Win32GetRouteTable2(bool ipv4, bool ipv6) +{ + ROUTE_TABLE *t = ZeroMallocFast(sizeof(ROUTE_TABLE)); + MIB_IPFORWARD_TABLE2 *p = NULL; + UINT ret; + UINT num_retry = 0; + LIST *o; + UINT i; + ROUTE_ENTRY *e; + ADDRESS_FAMILY family; + + if (ipv4 && ipv6) + { + family = AF_UNSPEC; + } + else if (ipv6) + { + family = AF_INET6; + } + else + { + family = AF_INET; + } + +RETRY: + // Actually get + ret = GetIpForwardTable2(family, &p); + if (ret != NO_ERROR) + { + // Acquisition failure + if ((++num_retry) >= 5) + { + FreeMibTable(p); + t->Entry = MallocFast(0); + return t; + } + FreeMibTable(p); + goto RETRY; + } + + // Add to the list along + o = NewListFast(Win32CompareRouteEntryByMetric); + for (i = 0; i < p->NumEntries; i++) + { + e = ZeroMallocFast(sizeof(ROUTE_ENTRY)); + Win32IpForwardRow2ToRouteEntry(e, &p->Table[i]); + Add(o, e); + } + FreeMibTable(p); + + // Sort by metric + Sort(o); + + // Combine the results + t->NumEntry = LIST_NUM(o); + t->Entry = ToArrayEx(o, true); + ReleaseList(o); + + return t; +} + // Sort the routing entries by metric int Win32CompareRouteEntryByMetric(void *p1, void *p2) { @@ -9572,6 +9797,67 @@ void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry) Debug(" r->dwForwardIfIndex=%u\n", r->dwForwardIfIndex); } +// Convert the ROUTE_ENTRY to a MIB_IPFORWARD_ROW2 (For Vista and later) +void Win32RouteEntryToIpForwardRow2(void *ip_forward_row, ROUTE_ENTRY *entry) +{ + MIB_IPFORWARD_ROW2 *r; + // Validate arguments + if (entry == NULL || ip_forward_row == NULL) + { + return; + } + + r = (MIB_IPFORWARD_ROW2 *)ip_forward_row; + InitializeIpForwardEntry(r); + + MIB_IPINTERFACE_ROW *p; + p = ZeroMallocFast(sizeof(MIB_IPINTERFACE_ROW)); + + if (IsIP4(&entry->DestIP)) + { + // IP address + r->DestinationPrefix.Prefix.Ipv4.sin_family = AF_INET; + IPToInAddr(&r->DestinationPrefix.Prefix.Ipv4.sin_addr, &entry->DestIP); + // Subnet mask + r->DestinationPrefix.PrefixLength = SubnetMaskToInt4(&entry->DestMask); + // Gateway IP address + r->NextHop.Ipv4.sin_family = AF_INET; + IPToInAddr(&r->NextHop.Ipv4.sin_addr, &entry->GatewayIP); + // Interface + p->Family = AF_INET; + } + else + { + // IP address + r->DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6; + IPToInAddr6(&r->DestinationPrefix.Prefix.Ipv6.sin6_addr, &entry->DestIP); + // Subnet mask + r->DestinationPrefix.PrefixLength = SubnetMaskToInt6(&entry->DestMask); + // Gateway IP address + r->NextHop.Ipv6.sin6_family = AF_INET6; + IPToInAddr6(&r->NextHop.Ipv6.sin6_addr, &entry->GatewayIP); + // Interface + p->Family = AF_INET6; + } + + // Metric + p->InterfaceIndex = entry->InterfaceID; + if (GetIpInterfaceEntry(p) == NO_ERROR && entry->Metric >= p->Metric) + { + r->Metric = entry->Metric - p->Metric; + } + else + { + r->Metric = entry->Metric; + } + Free(p); + + // Interface ID + r->InterfaceIndex = entry->InterfaceID; + + Debug("Win32RouteEntryToIpForwardRow2()\n"); +} + // Convert the MIB_IPFORWARDROW to a ROUTE_ENTRY void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row) { @@ -9611,6 +9897,77 @@ void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row) entry->InterfaceID = r->dwForwardIfIndex; } +// Convert the MIB_IPFORWARD_ROW2 to a ROUTE_ENTRY (For Vista and later) +void Win32IpForwardRow2ToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row) +{ + MIB_IPFORWARD_ROW2 *r; + // Validate arguments + if (entry == NULL || ip_forward_row == NULL) + { + return; + } + + r = (MIB_IPFORWARD_ROW2 *)ip_forward_row; + + Zero(entry, sizeof(ROUTE_ENTRY)); + + MIB_IPINTERFACE_ROW *p; + p = ZeroMallocFast(sizeof(MIB_IPINTERFACE_ROW)); + + if (((struct sockaddr *)&r->DestinationPrefix.Prefix)->sa_family != AF_INET6) + { + // IP address + InAddrToIP(&entry->DestIP, &r->DestinationPrefix.Prefix.Ipv4.sin_addr); + // Subnet mask + IntToSubnetMask4(&entry->DestMask, r->DestinationPrefix.PrefixLength); + // Gateway IP address + InAddrToIP(&entry->GatewayIP, &r->NextHop.Ipv4.sin_addr); + // Interface + p->Family = AF_INET; + } + else + { + // IP address + InAddrToIP6(&entry->DestIP, &r->DestinationPrefix.Prefix.Ipv6.sin6_addr); + // Subnet mask + IntToSubnetMask6(&entry->DestMask, r->DestinationPrefix.PrefixLength); + // Gateway IP address + InAddrToIP6(&entry->GatewayIP, &r->NextHop.Ipv6.sin6_addr); + // Interface + p->Family = AF_INET6; + } + + // Local routing flag + if (IsZeroIP(&entry->GatewayIP)) + { + entry->LocalRouting = true; + } + else + { + entry->LocalRouting = false; + } + if (entry->LocalRouting && r->Protocol == 3) + { + // PPP. Danger! + entry->PPPConnection = true; + } + + // Metric + p->InterfaceIndex = r->InterfaceIndex; + if (GetIpInterfaceEntry(p) == NO_ERROR) + { + entry->Metric = r->Metric + p->Metric; + } + else + { + entry->Metric = r->Metric; + } + Free(p); + + // Interface ID + entry->InterfaceID = r->InterfaceIndex; +} + // Initializing the socket library void Win32InitSocketLibrary() { @@ -10233,23 +10590,12 @@ ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT return NULL; } - if (IsIP6(ip)) - { - // IPv6 is not supported - return NULL; - } - // Select routing table entry by following rule // 1. Largest subnet mask // 2. Smallest metric value for (i = 0; i < table->NumEntry; i++) { ROUTE_ENTRY *e = table->Entry[i]; - UINT dest, net, mask; - - dest = IPToUINT(ip); - net = IPToUINT(&e->DestIP); - mask = IPToUINT(&e->DestMask); if (exclude_if_id != 0) { @@ -10260,10 +10606,10 @@ ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT } // Mask test - if ((dest & mask) == (net & mask)) + if (IsInSameNetwork(ip, &e->DestIP, &e->DestMask)) { // Calculate the score - UINT score_high32 = mask; + UINT score_high32 = SubnetMaskToInt(&e->DestMask); UINT score_low32 = 0xFFFFFFFF - e->Metric; UINT64 score64 = (UINT64)score_high32 * (UINT64)0x80000000 * (UINT64)2 + (UINT64)score_low32; if (score64 == 0) @@ -10294,24 +10640,24 @@ ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT if (tmp != NULL) { - UINT dest, gateway, mask; - // Generate an entry ret = ZeroMallocFast(sizeof(ROUTE_ENTRY)); Copy(&ret->DestIP, ip, sizeof(IP)); - SetIP(&ret->DestMask, 255, 255, 255, 255); + if (IsIP4(ip)) + { + IntToSubnetMask4(&ret->DestMask, 32); + } + else + { + IntToSubnetMask6(&ret->DestMask, 128); + } Copy(&ret->GatewayIP, &tmp->GatewayIP, sizeof(IP)); ret->InterfaceID = tmp->InterfaceID; ret->LocalRouting = tmp->LocalRouting; ret->OldIfMetric = tmp->Metric; ret->Metric = 1; ret->PPPConnection = tmp->PPPConnection; - - // Calculation related to routing control - dest = IPToUINT(&tmp->DestIP); - gateway = IPToUINT(&tmp->GatewayIP); - mask = IPToUINT(&tmp->DestMask); } return ret; @@ -10479,7 +10825,7 @@ void DeleteRouteEntry(ROUTE_ENTRY *e) { Debug("DeleteRouteEntry();\n"); #ifdef OS_WIN32 - Win32DeleteRouteEntry(e); + Win32DeleteRouteEntry2(e); #else // OS_WIN32 UnixDeleteRouteEntry(e); #endif @@ -10496,7 +10842,7 @@ bool AddRouteEntryEx(ROUTE_ENTRY *e, bool *already_exists) bool ret = false; Debug("AddRouteEntryEx();\n"); #ifdef OS_WIN32 - ret = Win32AddRouteEntry(e, already_exists); + ret = Win32AddRouteEntry2(e, already_exists); #else // OS_WIN32 ret = UnixAddRouteEntry(e, already_exists); #endif @@ -10512,7 +10858,7 @@ ROUTE_TABLE *GetRouteTable() UCHAR hash[MD5_SIZE]; #ifdef OS_WIN32 - t = Win32GetRouteTable(); + t = Win32GetRouteTable2(true, true); #else //OS_WIN32 t = UnixGetRouteTable(); #endif // OS_WIN32 diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index 74c53554..d94de6c9 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -959,11 +959,16 @@ void Win32InitAsyncSocket(SOCK *sock); void Win32JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event); void Win32FreeAsyncSocket(SOCK *sock); void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row); +void Win32IpForwardRow2ToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row); void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry); +void Win32RouteEntryToIpForwardRow2(void *ip_forward_row, ROUTE_ENTRY *entry); int Win32CompareRouteEntryByMetric(void *p1, void *p2); ROUTE_TABLE *Win32GetRouteTable(); +ROUTE_TABLE *Win32GetRouteTable2(bool ipv4, bool ipv6); bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists); +bool Win32AddRouteEntry2(ROUTE_ENTRY *e, bool *already_exists); void Win32DeleteRouteEntry(ROUTE_ENTRY *e); +void Win32DeleteRouteEntry2(ROUTE_ENTRY *e); void Win32UINTToIP(IP *ip, UINT i); UINT Win32IPToUINT(IP *ip); UINT Win32GetVLanInterfaceID(char *instance_name); @@ -981,8 +986,11 @@ void Win32ReleaseDhcp9x(UINT if_id, bool wait); void Win32FlushDnsCache(); int CompareIpAdapterIndexMap(void *p1, void *p2); ROUTE_CHANGE *Win32NewRouteChange(); +ROUTE_CHANGE *Win32NewRouteChange2(bool ipv4, bool ipv6, void *callback); void Win32FreeRouteChange(ROUTE_CHANGE *r); +void Win32FreeRouteChange2(ROUTE_CHANGE *r); bool Win32IsRouteChanged(ROUTE_CHANGE *r); +bool Win32IsRouteChanged2(ROUTE_CHANGE *r); bool Win32GetAdapterFromGuid(void *a, char *guid); SOCKET Win32Accept(SOCK *sock, SOCKET s, struct sockaddr *addr, int *addrlen, bool ipv6); @@ -1225,6 +1233,7 @@ void GetLoopbackAddress6(IP *ip); UINT GetIPAddrType6(IP *ip); UINT GetIPv6AddrType(IPV6_ADDR *addr); void GetPrefixAddress6(IP *dst, IP *ip, IP *subnet); +bool IsInSameNetwork(IP *a1, IP *a2, IP *subnet); bool IsInSameNetwork6(IP *a1, IP *a2, IP *subnet); bool IsInSameNetwork6ByStr(char *ip1, char *ip2, char *subnet); void GenerateEui64Address6(UCHAR *dst, UCHAR *mac); From 4ddf39e7600c98199e3224e0a3c62c9b7c7f12b0 Mon Sep 17 00:00:00 2001 From: domosekai <54519668+domosekai@users.noreply.github.com> Date: Wed, 28 Jul 2021 16:30:06 +0800 Subject: [PATCH 2/4] Remove obsolete Win32 functions --- src/Mayaqua/Network.c | 412 ------------------------------------------ src/Mayaqua/Network.h | 11 -- 2 files changed, 423 deletions(-) diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index 3d9c453d..d75ca04b 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -59,7 +59,6 @@ struct ROUTE_CHANGE_DATA { - OVERLAPPED Overlapped; HANDLE Handle; UINT NumCalled; bool Changed; @@ -6149,31 +6148,7 @@ bool IsRouteChanged(ROUTE_CHANGE *r) #endif // OS_WIN32 } -// Routing table change detector function (Win32) #ifdef OS_WIN32 -ROUTE_CHANGE *Win32NewRouteChange() -{ - ROUTE_CHANGE *r; - BOOL ret; - - r = ZeroMalloc(sizeof(ROUTE_CHANGE)); - - r->Data = ZeroMalloc(sizeof(ROUTE_CHANGE_DATA)); - - r->Data->Overlapped.hEvent = CreateEventA(NULL, false, true, NULL); - - ret = NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped); - if (!(ret == NO_ERROR || ret == WSA_IO_PENDING || WSAGetLastError() == WSA_IO_PENDING)) - { - Free(r->Data); - Free(r); - - return NULL; - } - - return r; -} - void Win32RouteChangeCallback(void *context, MIB_IPFORWARD_ROW2 *row, MIB_NOTIFICATION_TYPE nt) { ROUTE_CHANGE_DATA *data = context; @@ -6225,21 +6200,6 @@ ROUTE_CHANGE *Win32NewRouteChange2(bool ipv4, bool ipv6, void *callback) return r; } -void Win32FreeRouteChange(ROUTE_CHANGE *r) -{ - // Validate arguments - if (r == NULL) - { - return; - } - - CancelIPChangeNotify(&r->Data->Overlapped); - CloseHandle(r->Data->Overlapped.hEvent); - - Free(r->Data); - Free(r); -} - void Win32FreeRouteChange2(ROUTE_CHANGE *r) { // Validate arguments @@ -6254,28 +6214,6 @@ void Win32FreeRouteChange2(ROUTE_CHANGE *r) Free(r); } -bool Win32IsRouteChanged(ROUTE_CHANGE *r) -{ - // Validate arguments - if (r == NULL) - { - return false; - } - - if ((r->Data->NumCalled++) == 0) - { - return true; - } - - if (WaitForSingleObject(r->Data->Overlapped.hEvent, 0) == WAIT_OBJECT_0) - { - NotifyRouteChange(&r->Data->Handle, &r->Data->Overlapped); - return true; - } - - return false; -} - bool Win32IsRouteChanged2(ROUTE_CHANGE *r) { // Validate arguments @@ -9071,118 +9009,6 @@ void Win32FlushDnsCache() Run("ipconfig.exe", "/flushdns", true, false); } -// Update the DHCP address of the specified LAN card -void Win32RenewDhcp9x(UINT if_id) -{ - IP_INTERFACE_INFO *info; - ULONG size; - int i; - LIST *o; - // Validate arguments - if (if_id == 0) - { - return; - } - - size = sizeof(IP_INTERFACE_INFO); - info = ZeroMallocFast(size); - - if (GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER) - { - Free(info); - info = ZeroMallocFast(size); - } - - if (GetInterfaceInfo(info, &size) != NO_ERROR) - { - Free(info); - return; - } - - o = NewListFast(CompareIpAdapterIndexMap); - - for (i = 0; i < info->NumAdapters; i++) - { - IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i]; - - Add(o, a); - } - - Sort(o); - - for (i = 0; i < (int)(LIST_NUM(o)); i++) - { - IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i); - - if (a->Index == if_id) - { - char arg[MAX_PATH]; - Format(arg, sizeof(arg), "/renew %u", i); - Run("ipconfig.exe", arg, true, false); - } - } - - ReleaseList(o); - - Free(info); -} - -// Release the DHCP address of the specified LAN card -void Win32ReleaseDhcp9x(UINT if_id, bool wait) -{ - IP_INTERFACE_INFO *info; - ULONG size; - int i; - LIST *o; - // Validate arguments - if (if_id == 0) - { - return; - } - - size = sizeof(IP_INTERFACE_INFO); - info = ZeroMallocFast(size); - - if (GetInterfaceInfo(info, &size) == ERROR_INSUFFICIENT_BUFFER) - { - Free(info); - info = ZeroMallocFast(size); - } - - if (GetInterfaceInfo(info, &size) != NO_ERROR) - { - Free(info); - return; - } - - o = NewListFast(CompareIpAdapterIndexMap); - - for (i = 0; i < info->NumAdapters; i++) - { - IP_ADAPTER_INDEX_MAP *a = &info->Adapter[i]; - - Add(o, a); - } - - Sort(o); - - for (i = 0; i < (int)(LIST_NUM(o)); i++) - { - IP_ADAPTER_INDEX_MAP *a = LIST_DATA(o, i); - - if (a->Index == if_id) - { - char arg[MAX_PATH]; - Format(arg, sizeof(arg), "/release %u", i); - Run("ipconfig.exe", arg, true, wait); - } - } - - ReleaseList(o); - - Free(info); -} - // Enumerate a list of virtual LAN cards that contains the specified string char **Win32EnumVLan(char *tag_name) { @@ -9441,35 +9267,6 @@ bool Win32GetDefaultDns(IP *ip, char *domain, UINT size) return true; } -// IP conversion function for Win32 -void Win32UINTToIP(IP *ip, UINT i) -{ - UINTToIP(ip, i); -} - -// IP conversion function for Win32 -UINT Win32IPToUINT(IP *ip) -{ - return IPToUINT(ip); -} - -// Remove a routing entry from the routing table -void Win32DeleteRouteEntry(ROUTE_ENTRY *e) -{ - MIB_IPFORWARDROW *p; - // Validate arguments - if (e == NULL) - { - return; - } - - p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW)); - Win32RouteEntryToIpForwardRow(p, e); - - DeleteIpForwardEntry(p); - Free(p); -} - // Remove a routing entry from the routing table (For Vista and later) void Win32DeleteRouteEntry2(ROUTE_ENTRY *e) { @@ -9487,53 +9284,6 @@ void Win32DeleteRouteEntry2(ROUTE_ENTRY *e) Free(p); } -// Add a routing entry to the routing table -bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists) -{ - bool ret = false; - bool dummy = false; - MIB_IPFORWARDROW *p; - UINT err = 0; - // Validate arguments - if (e == NULL) - { - return false; - } - if (already_exists == NULL) - { - already_exists = &dummy; - } - - *already_exists = false; - - p = ZeroMallocFast(sizeof(MIB_IPFORWARDROW)); - Win32RouteEntryToIpForwardRow(p, e); - - err = CreateIpForwardEntry(p); - if (err != 0) - { - if (err == ERROR_OBJECT_ALREADY_EXISTS) - { - Debug("CreateIpForwardEntry: Already Exists\n"); - *already_exists = true; - ret = true; - } - else - { - Debug("CreateIpForwardEntry Error: %u\n", err); - ret = false; - } - } - else - { - ret = true; - } - - Free(p); - - return ret; -} - // Add a routing entry to the routing table (For Vista and later) bool Win32AddRouteEntry2(ROUTE_ENTRY *e, bool *already_exists) { @@ -9581,73 +9331,6 @@ bool Win32AddRouteEntry2(ROUTE_ENTRY *e, bool *already_exists) return ret; } -// Get the routing table -ROUTE_TABLE *Win32GetRouteTable() -{ - ROUTE_TABLE *t = ZeroMallocFast(sizeof(ROUTE_TABLE)); - MIB_IPFORWARDTABLE *p; - UINT ret; - ULONG size_needed; - UINT num_retry = 0; - LIST *o; - UINT i; - ROUTE_ENTRY *e; - -RETRY: - p = ZeroMallocFast(sizeof(MIB_IFTABLE)); - size_needed = 0; - - // Examine the needed size - ret = GetIpForwardTable(p, &size_needed, 0); - if (ret == ERROR_INSUFFICIENT_BUFFER) - { - // Re-allocate the memory block of the needed size - Free(p); - p = ZeroMallocFast(size_needed); - } - else if (ret != NO_ERROR) - { - // Acquisition failure -FAILED: - Free(p); - t->Entry = MallocFast(0); - return t; - } - - // Actually get - ret = GetIpForwardTable(p, &size_needed, FALSE); - if (ret != NO_ERROR) - { - // Acquisition failure - if ((++num_retry) >= 5) - { - goto FAILED; - } - Free(p); - goto RETRY; - } - - // Add to the list along - o = NewListFast(Win32CompareRouteEntryByMetric); - for (i = 0; i < p->dwNumEntries; i++) - { - e = ZeroMallocFast(sizeof(ROUTE_ENTRY)); - Win32IpForwardRowToRouteEntry(e, &p->table[i]); - Add(o, e); - } - Free(p); - - // Sort by metric - Sort(o); - - // Combine the results - t->NumEntry = LIST_NUM(o); - t->Entry = ToArrayEx(o, true); - ReleaseList(o); - - return t; -} - // Get the routing table (For Vista and later) ROUTE_TABLE *Win32GetRouteTable2(bool ipv4, bool ipv6) { @@ -9741,62 +9424,6 @@ int Win32CompareRouteEntryByMetric(void *p1, void *p2) } } -// Convert the ROUTE_ENTRY to a MIB_IPFORWARDROW -void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry) -{ - MIB_IPFORWARDROW *r; - // Validate arguments - if (entry == NULL || ip_forward_row == NULL) - { - return; - } - - r = (MIB_IPFORWARDROW *)ip_forward_row; - Zero(r, sizeof(MIB_IPFORWARDROW)); - - // IP address - r->dwForwardDest = Win32IPToUINT(&entry->DestIP); - // Subnet mask - r->dwForwardMask = Win32IPToUINT(&entry->DestMask); - // Gateway IP address - r->dwForwardNextHop = Win32IPToUINT(&entry->GatewayIP); - // Local routing flag - if (entry->LocalRouting) - { - // Local - r->dwForwardType = 3; - } - else - { - // Remote router - r->dwForwardType = 4; - } - // Protocol - r->dwForwardProto = r->dwForwardType - 1; // Subtract by 1 in most cases - if (entry->PPPConnection) - { - // Isn't this a PPP? Danger! - r->dwForwardProto++; - } - // Metric - r->dwForwardMetric1 = entry->Metric; - r->dwForwardMetric2 = r->dwForwardMetric3 = r->dwForwardMetric4 = r->dwForwardMetric5 = 0; - r->dwForwardAge = 163240; - - // Interface ID - r->dwForwardIfIndex = entry->InterfaceID; - - Debug("Win32RouteEntryToIpForwardRow()\n"); - Debug(" r->dwForwardDest=%X\n", r->dwForwardDest); - Debug(" r->dwForwardMask=%X\n", r->dwForwardMask); - Debug(" r->dwForwardNextHop=%X\n", r->dwForwardNextHop); - Debug(" r->dwForwardType=%u\n", r->dwForwardType); - Debug(" r->dwForwardProto=%u\n", r->dwForwardProto); - Debug(" r->dwForwardMetric1=%u\n", r->dwForwardMetric1); - Debug(" r->dwForwardMetric2=%u\n", r->dwForwardMetric2); - Debug(" r->dwForwardIfIndex=%u\n", r->dwForwardIfIndex); -} - // Convert the ROUTE_ENTRY to a MIB_IPFORWARD_ROW2 (For Vista and later) void Win32RouteEntryToIpForwardRow2(void *ip_forward_row, ROUTE_ENTRY *entry) { @@ -9858,45 +9485,6 @@ void Win32RouteEntryToIpForwardRow2(void *ip_forward_row, ROUTE_ENTRY *entry) Debug("Win32RouteEntryToIpForwardRow2()\n"); } -// Convert the MIB_IPFORWARDROW to a ROUTE_ENTRY -void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row) -{ - MIB_IPFORWARDROW *r; - // Validate arguments - if (entry == NULL || ip_forward_row == NULL) - { - return; - } - - r = (MIB_IPFORWARDROW *)ip_forward_row; - - Zero(entry, sizeof(ROUTE_ENTRY)); - // IP address - Win32UINTToIP(&entry->DestIP, r->dwForwardDest); - // Subnet mask - Win32UINTToIP(&entry->DestMask, r->dwForwardMask); - // Gateway IP address - Win32UINTToIP(&entry->GatewayIP, r->dwForwardNextHop); - // Local routing flag - if (r->dwForwardType == 3) - { - entry->LocalRouting = true; - } - else - { - entry->LocalRouting = false; - } - if (entry->LocalRouting && r->dwForwardProto == 3) - { - // PPP. Danger! - entry->PPPConnection = true; - } - // Metric - entry->Metric = r->dwForwardMetric1; - // Interface ID - entry->InterfaceID = r->dwForwardIfIndex; -} - // Convert the MIB_IPFORWARD_ROW2 to a ROUTE_ENTRY (For Vista and later) void Win32IpForwardRow2ToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row) { diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index d94de6c9..f227cadd 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -958,19 +958,12 @@ void Win32Select(SOCKSET *set, UINT timeout, CANCEL *c1, CANCEL *c2); void Win32InitAsyncSocket(SOCK *sock); void Win32JoinSockToSockEvent(SOCK *sock, SOCK_EVENT *event); void Win32FreeAsyncSocket(SOCK *sock); -void Win32IpForwardRowToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row); void Win32IpForwardRow2ToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row); -void Win32RouteEntryToIpForwardRow(void *ip_forward_row, ROUTE_ENTRY *entry); void Win32RouteEntryToIpForwardRow2(void *ip_forward_row, ROUTE_ENTRY *entry); int Win32CompareRouteEntryByMetric(void *p1, void *p2); -ROUTE_TABLE *Win32GetRouteTable(); ROUTE_TABLE *Win32GetRouteTable2(bool ipv4, bool ipv6); -bool Win32AddRouteEntry(ROUTE_ENTRY *e, bool *already_exists); bool Win32AddRouteEntry2(ROUTE_ENTRY *e, bool *already_exists); -void Win32DeleteRouteEntry(ROUTE_ENTRY *e); void Win32DeleteRouteEntry2(ROUTE_ENTRY *e); -void Win32UINTToIP(IP *ip, UINT i); -UINT Win32IPToUINT(IP *ip); UINT Win32GetVLanInterfaceID(char *instance_name); char **Win32EnumVLan(char *tag_name); void Win32Cancel(CANCEL *c); @@ -982,14 +975,10 @@ void Win32CleanupSockEvent(SOCK_EVENT *event); bool Win32WaitSockEvent(SOCK_EVENT *event, UINT timeout); bool Win32GetDefaultDns(IP *ip, char *domain, UINT size); bool Win32GetDnsSuffix(char *domain, UINT size); -void Win32ReleaseDhcp9x(UINT if_id, bool wait); void Win32FlushDnsCache(); int CompareIpAdapterIndexMap(void *p1, void *p2); -ROUTE_CHANGE *Win32NewRouteChange(); ROUTE_CHANGE *Win32NewRouteChange2(bool ipv4, bool ipv6, void *callback); -void Win32FreeRouteChange(ROUTE_CHANGE *r); void Win32FreeRouteChange2(ROUTE_CHANGE *r); -bool Win32IsRouteChanged(ROUTE_CHANGE *r); bool Win32IsRouteChanged2(ROUTE_CHANGE *r); bool Win32GetAdapterFromGuid(void *a, char *guid); SOCKET Win32Accept(SOCK *sock, SOCKET s, struct sockaddr *addr, int *addrlen, bool ipv6); From dd9c3546f773291f0420d26109ae8b6e39c0782a Mon Sep 17 00:00:00 2001 From: domosekai <54519668+domosekai@users.noreply.github.com> Date: Thu, 29 Jul 2021 00:38:53 +0800 Subject: [PATCH 3/4] Prevent IPv6 leak if only IPv4 default route is added --- src/Cedar/VLanWin32.c | 67 +++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/src/Cedar/VLanWin32.c b/src/Cedar/VLanWin32.c index 8b2b55ad..03b80e61 100644 --- a/src/Cedar/VLanWin32.c +++ b/src/Cedar/VLanWin32.c @@ -190,9 +190,12 @@ void RouteTrackingMain(SESSION *s) { UINT i; bool route_to_server_erased = true; - bool is_vlan_want_to_be_default_gateway = false; - UINT vlan_default_gateway_metric = 0; - UINT other_if_default_gateway_metric_min = INFINITE; + bool is_vlan_want_to_be_default_gateway_v4 = false; + bool is_vlan_want_to_be_default_gateway_v6 = false; + UINT vlan_default_gateway_metric_v4 = 0; + UINT vlan_default_gateway_metric_v6 = 0; + UINT other_if_default_gateway_metric_min_v4 = INFINITE; + UINT other_if_default_gateway_metric_min_v6 = INFINITE; // Get whether the routing table have been changed if (t->LastRoutingTableHash != table->HashedValue) @@ -231,15 +234,15 @@ void RouteTrackingMain(SESSION *s) if (e->InterfaceID == t->VLanInterfaceId) { - // The virtual LAN card think that he want to be a default gateway - is_vlan_want_to_be_default_gateway = true; - vlan_default_gateway_metric = e->Metric; - - // PPP route fix (IPv4 only) if (IsIP4(&e->DestIP)) { - if (vlan_default_gateway_metric >= 2 && - t->OldDefaultGatewayMetric == (vlan_default_gateway_metric - 1)) + // The virtual LAN card think that he want to be a default gateway + is_vlan_want_to_be_default_gateway_v4 = true; + vlan_default_gateway_metric_v4 = e->Metric; + + // PPP route fix + if (vlan_default_gateway_metric_v4 >= 2 && + t->OldDefaultGatewayMetric == (vlan_default_gateway_metric_v4 - 1)) { // Restore because the PPP server rewrites // the routing table selfishly @@ -261,25 +264,40 @@ void RouteTrackingMain(SESSION *s) t->DefaultGatewayByVLan = ZeroMalloc(sizeof(ROUTE_ENTRY)); Copy(t->DefaultGatewayByVLan, e, sizeof(ROUTE_ENTRY)); - t->OldDefaultGatewayMetric = vlan_default_gateway_metric; + t->OldDefaultGatewayMetric = vlan_default_gateway_metric_v4; + } + else + { + is_vlan_want_to_be_default_gateway_v6 = true; + vlan_default_gateway_metric_v6 = e->Metric; } } else { - // There are default gateway other than the virtual LAN card - // Save the metric value of the default gateway - if (other_if_default_gateway_metric_min > e->Metric) + if (IsIP4(&e->DestIP)) { - // Ignore the metric value of all PPP connection in the case of Windows Vista - if (e->PPPConnection == false) + // There are default gateway other than the virtual LAN card + // Save the metric value of the default gateway + if (other_if_default_gateway_metric_min_v4 > e->Metric) { - other_if_default_gateway_metric_min = e->Metric; + // Ignore the metric value of all PPP connection in the case of Windows Vista + if (e->PPPConnection == false) + { + other_if_default_gateway_metric_min_v4 = e->Metric; + } + else + { + // a PPP is used to Connect to the network + // in using Windows Vista + t->VistaAndUsingPPP = true; + } } - else + } + else + { + if (other_if_default_gateway_metric_min_v6 > e->Metric) { - // a PPP is used to Connect to the network - // in using Windows Vista - t->VistaAndUsingPPP = true; + other_if_default_gateway_metric_min_v6 = e->Metric; } } } @@ -290,7 +308,7 @@ void RouteTrackingMain(SESSION *s) { if (t->DefaultGatewayByVLan != NULL) { - if (is_vlan_want_to_be_default_gateway) + if (is_vlan_want_to_be_default_gateway_v4) { if (t->VistaOldDefaultGatewayByVLan == NULL || Cmp(t->VistaOldDefaultGatewayByVLan, t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY)) != 0) { @@ -365,8 +383,9 @@ void RouteTrackingMain(SESSION *s) // to elect the virtual LAN card as the default gateway // Debug("is_vlan_want_to_be_default_gateway = %u, rs = %u, route_to_server_erased = %u, other_if_default_gateway_metric_min = %u, vlan_default_gateway_metric = %u\n", // is_vlan_want_to_be_default_gateway, rs, route_to_server_erased, other_if_default_gateway_metric_min, vlan_default_gateway_metric); - if (is_vlan_want_to_be_default_gateway && (rs != NULL && route_to_server_erased == false) && - other_if_default_gateway_metric_min >= vlan_default_gateway_metric) + if ((is_vlan_want_to_be_default_gateway_v4 && other_if_default_gateway_metric_min_v4 >= vlan_default_gateway_metric_v4 || + is_vlan_want_to_be_default_gateway_v6 && other_if_default_gateway_metric_min_v6 >= vlan_default_gateway_metric_v6) + && rs != NULL && route_to_server_erased == false) { // Scan the routing table again for (i = 0;i < table->NumEntry;i++) From 9b3077d955a735da7bf7501010a30067fd2d9904 Mon Sep 17 00:00:00 2001 From: domosekai <54519668+domosekai@users.noreply.github.com> Date: Thu, 29 Jul 2021 22:24:26 +0800 Subject: [PATCH 4/4] Store interface metric separately as it mau change --- src/Cedar/VLanWin32.c | 7 ------- src/Mayaqua/Network.c | 26 +++++++++----------------- src/Mayaqua/Network.h | 2 +- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/Cedar/VLanWin32.c b/src/Cedar/VLanWin32.c index 03b80e61..592fd595 100644 --- a/src/Cedar/VLanWin32.c +++ b/src/Cedar/VLanWin32.c @@ -162,7 +162,6 @@ void RouteTrackingMain(SESSION *s) char ip_str2[64]; Copy(&e->DestIP, &nat_t_ip, sizeof(IP)); - e->Metric = e->OldIfMetric; IPToStr(ip_str, sizeof(ip_str), &e->DestIP); IPToStr(ip_str2, sizeof(ip_str2), &e->GatewayIP); @@ -507,8 +506,6 @@ void RouteTrackingStart(SESSION *s) Debug("GetBestRouteEntry() Succeed. [Gateway: %s]\n", tmp); // Add a route - e->Metric = e->OldIfMetric; - if (AddRouteEntryEx(e, &already_exists) == false) { FreeRouteEntry(e); @@ -570,8 +567,6 @@ void RouteTrackingStart(SESSION *s) else { // Add a route - dns->Metric = dns->OldIfMetric; - if (AddRouteEntry(dns) == false) { FreeRouteEntry(dns); @@ -590,8 +585,6 @@ void RouteTrackingStart(SESSION *s) if (route_to_real_server_global != NULL) { - route_to_real_server_global->Metric = route_to_real_server_global->OldIfMetric; - if (AddRouteEntry(route_to_real_server_global) == false) { FreeRouteEntry(route_to_real_server_global); diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index d75ca04b..772c5a18 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -9437,9 +9437,6 @@ void Win32RouteEntryToIpForwardRow2(void *ip_forward_row, ROUTE_ENTRY *entry) r = (MIB_IPFORWARD_ROW2 *)ip_forward_row; InitializeIpForwardEntry(r); - MIB_IPINTERFACE_ROW *p; - p = ZeroMallocFast(sizeof(MIB_IPINTERFACE_ROW)); - if (IsIP4(&entry->DestIP)) { // IP address @@ -9450,8 +9447,6 @@ void Win32RouteEntryToIpForwardRow2(void *ip_forward_row, ROUTE_ENTRY *entry) // Gateway IP address r->NextHop.Ipv4.sin_family = AF_INET; IPToInAddr(&r->NextHop.Ipv4.sin_addr, &entry->GatewayIP); - // Interface - p->Family = AF_INET; } else { @@ -9463,21 +9458,17 @@ void Win32RouteEntryToIpForwardRow2(void *ip_forward_row, ROUTE_ENTRY *entry) // Gateway IP address r->NextHop.Ipv6.sin6_family = AF_INET6; IPToInAddr6(&r->NextHop.Ipv6.sin6_addr, &entry->GatewayIP); - // Interface - p->Family = AF_INET6; } - // Metric - p->InterfaceIndex = entry->InterfaceID; - if (GetIpInterfaceEntry(p) == NO_ERROR && entry->Metric >= p->Metric) + // Metric offset + if (entry->Metric >= entry->IfMetric) { - r->Metric = entry->Metric - p->Metric; + r->Metric = entry->Metric - entry->IfMetric; } else { - r->Metric = entry->Metric; + r->Metric = 0; } - Free(p); // Interface ID r->InterfaceIndex = entry->InterfaceID; @@ -9544,6 +9535,7 @@ void Win32IpForwardRow2ToRouteEntry(ROUTE_ENTRY *entry, void *ip_forward_row) p->InterfaceIndex = r->InterfaceIndex; if (GetIpInterfaceEntry(p) == NO_ERROR) { + entry->IfMetric = p->Metric; entry->Metric = r->Metric + p->Metric; } else @@ -10243,8 +10235,8 @@ ROUTE_ENTRY *GetBestRouteEntryFromRouteTableEx(ROUTE_TABLE *table, IP *ip, UINT Copy(&ret->GatewayIP, &tmp->GatewayIP, sizeof(IP)); ret->InterfaceID = tmp->InterfaceID; ret->LocalRouting = tmp->LocalRouting; - ret->OldIfMetric = tmp->Metric; - ret->Metric = 1; + ret->Metric = tmp->Metric; + ret->IfMetric = tmp->IfMetric; ret->PPPConnection = tmp->PPPConnection; } @@ -10402,9 +10394,9 @@ void RouteToStr(char *str, UINT str_size, ROUTE_ENTRY *e) IPToStr(dest_mask, sizeof(dest_mask), &e->DestMask); IPToStr(gateway_ip, sizeof(gateway_ip), &e->GatewayIP); - Format(str, str_size, "%s/%s %s m=%u oif=%u if=%u lo=%u p=%u", + Format(str, str_size, "%s/%s %s m=%u ifm=%u if=%u lo=%u p=%u", dest_ip, dest_mask, gateway_ip, - e->Metric, e->OldIfMetric, e->InterfaceID, + e->Metric, e->IfMetric, e->InterfaceID, e->LocalRouting, e->PPPConnection); } diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index f227cadd..bf58dceb 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -285,7 +285,7 @@ struct ROUTE_ENTRY bool LocalRouting; bool PPPConnection; UINT Metric; - UINT OldIfMetric; + UINT IfMetric; UINT InterfaceID; UINT64 InnerScore; };