You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
701 lines
17 KiB
701 lines
17 KiB
//++
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1987 - 1999
|
|
//
|
|
// Module Name:
|
|
//
|
|
// route.c
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Queries into network drivers
|
|
//
|
|
// Author:
|
|
//
|
|
// Anilth - 4-20-1998
|
|
//
|
|
// Environment:
|
|
//
|
|
// User mode only.
|
|
// Contains NT-specific code.
|
|
//
|
|
// Revision History:
|
|
//
|
|
//--
|
|
|
|
#include "precomp.h"
|
|
|
|
//
|
|
// Rajkumar - Two Functions from iphlpapi.dll
|
|
//
|
|
|
|
DWORD
|
|
WINAPI
|
|
GetIpAddrTable(
|
|
OUT PMIB_IPADDRTABLE pIpAddrTable,
|
|
IN OUT PULONG pdwSize,
|
|
IN BOOL bOrder
|
|
);
|
|
|
|
DWORD
|
|
InternalGetIpForwardTable(
|
|
OUT MIB_IPFORWARDTABLE **ppIpForwardTable,
|
|
IN HANDLE hHeap,
|
|
IN DWORD dwAllocFlags
|
|
);
|
|
//--------------------------------------------------------
|
|
|
|
|
|
//functions defined in this file
|
|
void MapInterface(char *IPAddr, ULONG IfIndex);
|
|
BOOLEAN ImprovedInetAddr(char *AddressString, ULONG *AddressValue);
|
|
|
|
HRESULT
|
|
PrintRoute(
|
|
NETDIAG_RESULT *pResults,
|
|
char *Dest,
|
|
ULONG DestVal,
|
|
char *Gate,
|
|
ULONG GateVal,
|
|
BOOLEAN Persistent,
|
|
const char * DestPat
|
|
);
|
|
|
|
LPCTSTR
|
|
PrintRouteEntry(
|
|
ULONG Dest,
|
|
ULONG Mask,
|
|
ULONG Gate,
|
|
ULONG Interface,
|
|
ULONG Metric1
|
|
);
|
|
|
|
HRESULT
|
|
PrintPersistentRoutes(
|
|
NETDIAG_RESULT *pResults,
|
|
char* Dest,
|
|
ULONG DestVal,
|
|
char* Gate,
|
|
ULONG GateVal
|
|
);
|
|
|
|
|
|
BOOL
|
|
RouteTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerate the static and persistent entries in the routing table
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
TRUE
|
|
|
|
Author:
|
|
Rajkumar 06/27/98
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
//$REVIEW only perform the test when is really verbose
|
|
if (!pParams->fReallyVerbose)
|
|
return hr;
|
|
|
|
PrintStatusMessage( pParams, 4, IDS_ROUTE_STATUS_MSG );
|
|
//
|
|
// Print all static entries in the ip forward table
|
|
//
|
|
|
|
|
|
|
|
hr = PrintRoute(pResults,
|
|
"*",
|
|
WILD_CARD,
|
|
"*",
|
|
WILD_CARD,
|
|
TRUE,
|
|
"*"
|
|
);
|
|
|
|
//
|
|
// Print all the persistent route entries
|
|
//
|
|
|
|
if( S_OK == hr )
|
|
hr = PrintPersistentRoutes(pResults,
|
|
"*",
|
|
WILD_CARD,
|
|
"*",
|
|
WILD_CARD
|
|
);
|
|
|
|
|
|
pResults->Route.hrTestResult = hr;
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
PrintRoute(
|
|
NETDIAG_RESULT *pResults,
|
|
char *Dest,
|
|
ULONG DestVal,
|
|
char *Gate,
|
|
ULONG GateVal,
|
|
BOOLEAN Persistent,
|
|
const char * DestPat
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine prints all the static entries in then IP forward table.
|
|
The entry in the routing table is declared static if the type of the
|
|
entry is MIB_IPPROTO_LOCAL.
|
|
|
|
Arguments:
|
|
|
|
char *Dest: pointer to destination IP address string. This
|
|
is NULL if no value was provided/no filtering desired.
|
|
ULONG DestVal: value of destination IP address to filter route
|
|
table with. If Dest is NULL, this is ignored.
|
|
char *Gate: pointer to gateway IP address string. This is NULL
|
|
if no value was provided/no filtering desired.
|
|
ULONG GateVal: value of gateway IP address to filter route
|
|
table with. If Gate is NULL, this is ignored.
|
|
BOOL Persistent: set if persistent routes are to be printed.
|
|
Returns: ULONG
|
|
|
|
Can also be found in nt\private\net\sockets\tcpcmd\route\route.c
|
|
--*/
|
|
{
|
|
int printcount = 0;
|
|
int dwResult, j, k, err, alen;
|
|
DWORD i;
|
|
PMIB_IPFORWARDTABLE prifRouteTable = NULL;
|
|
PMIB_IFTABLE pIfTable = NULL;
|
|
|
|
// ====================================================================
|
|
// Get Route Table.
|
|
|
|
pResults->Route.dwNumRoutes = 0;
|
|
InitializeListHead(&pResults->Route.lmsgRoute);
|
|
|
|
dwResult = InternalGetIpForwardTable(&prifRouteTable,
|
|
GetProcessHeap(), HEAP_NO_SERIALIZE );
|
|
|
|
if(dwResult || !prifRouteTable){
|
|
DEBUG_PRINT(("GetIpForwardTable/2: err=%d, dwResult=%d\n",
|
|
GetLastError(), dwResult ));
|
|
return S_FALSE;
|
|
}
|
|
|
|
if( ! prifRouteTable->dwNumEntries )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
for(i = 0; i < prifRouteTable->dwNumEntries; i++)
|
|
{
|
|
PMIB_IPFORWARDROW pfr = &prifRouteTable->table[i];
|
|
|
|
// Only print this entry if the destination matches the parameter
|
|
|
|
if( ( Dest != NULL )
|
|
&& ( DestVal != WILD_CARD )
|
|
&& ( pfr->dwForwardDest != DestVal )
|
|
&& ( DestPat == NULL )
|
|
)
|
|
continue;
|
|
|
|
// Only print this entry if the Gateway matches the parameter
|
|
|
|
if( ( Gate != NULL )
|
|
&& ( GateVal != WILD_CARD )
|
|
&& ( pfr->dwForwardNextHop != GateVal )
|
|
)
|
|
continue;
|
|
|
|
if( DestPat )
|
|
{
|
|
char DestStr[32];
|
|
NetpIpAddressToStr( pfr->dwForwardDest, DestStr );
|
|
if( ! match( DestPat, DestStr ) )
|
|
{
|
|
TRACE_PRINT(("PrintRoute: skipping %s !~ %s\n",
|
|
DestPat, DestStr ));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Either we have a match on Dest/Gateway or they are
|
|
// wildcard/don't care.
|
|
|
|
// Display the header first time.
|
|
|
|
// We are going to display only static routes
|
|
|
|
if ( printcount++ < 1 )
|
|
//IDS_ROUTE_14203 "Network Destination Netmask Gateway Interface Metric\n"
|
|
AddMessageToListId( &pResults->Route.lmsgRoute, Nd_ReallyVerbose, IDS_ROUTE_14203);
|
|
|
|
//IDS_ROUTE_14204 "%s\n"
|
|
AddMessageToList( &pResults->Route.lmsgRoute, Nd_ReallyVerbose,
|
|
IDS_ROUTE_14204,
|
|
PrintRouteEntry( pfr->dwForwardDest,
|
|
pfr->dwForwardMask,
|
|
pfr->dwForwardNextHop,
|
|
pfr->dwForwardIfIndex,
|
|
pfr->dwForwardMetric1)
|
|
);
|
|
}
|
|
|
|
pResults->Route.dwNumRoutes = printcount;
|
|
|
|
HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, pIfTable );
|
|
HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, prifRouteTable);
|
|
|
|
return ( NO_ERROR );
|
|
}
|
|
|
|
|
|
LPCTSTR
|
|
PrintRouteEntry(
|
|
ULONG Dest,
|
|
ULONG Mask,
|
|
ULONG Gate,
|
|
ULONG Interface,
|
|
ULONG Metric1
|
|
)
|
|
/*++
|
|
Description:
|
|
Formats and displays a single route entry.
|
|
|
|
Arguments:
|
|
Dest: The destination address.
|
|
Mask: The destination netmask.
|
|
Gate: The first hop gateway address.
|
|
Interface: The interface address for the gateway net.
|
|
Metric1: The primary route metric.
|
|
|
|
Author:
|
|
07/01/98 Rajkumar
|
|
|
|
--*/
|
|
{
|
|
static TCHAR s_szBuffer[512];
|
|
TCHAR szFormat[128];
|
|
char DestStr[32];
|
|
char GateStr[32];
|
|
char NetmaskStr[32];
|
|
char MetricStr[32];
|
|
char IfStr[32];
|
|
|
|
NetpIpAddressToStr( Dest, DestStr);
|
|
NetpIpAddressToStr( Gate, GateStr);
|
|
NetpIpAddressToStr( Mask, NetmaskStr);
|
|
|
|
|
|
MapInterface(IfStr,Interface);
|
|
|
|
if( Metric1 > MAX_METRIC ) Metric1 = MAX_METRIC;
|
|
|
|
sprintf( MetricStr, "%u", Metric1 );
|
|
|
|
//IDS_ROUTE_14205 "%16s %16s %16s %16s %6s"
|
|
LoadString(NULL, IDS_ROUTE_14205, szFormat, DimensionOf(szFormat));
|
|
assert(szFormat[0]);
|
|
_stprintf(s_szBuffer, szFormat, DestStr,
|
|
NetmaskStr, GateStr, IfStr, MetricStr);
|
|
return s_szBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
ExtractRoute(
|
|
char *RouteString,
|
|
ULONG *DestVal,
|
|
ULONG *MaskVal,
|
|
ULONG *GateVal,
|
|
ULONG *MetricVal
|
|
)
|
|
/*++
|
|
Description:
|
|
Extracts the dest, mask, and gateway from a persistent
|
|
route string, as stored in the registry.
|
|
|
|
Arguments:
|
|
RouteString : The string to parse.
|
|
DestVal : The place to put the extracted destination
|
|
MaskVal : The place to put the extracted mask
|
|
GateVal : The place to put the extracted gateway
|
|
MetricVal : The place to put the extracted metric
|
|
|
|
|
|
Author:
|
|
07/01/98 Rajkumar . Created.
|
|
|
|
--*/
|
|
{
|
|
char *addressPtr = RouteString;
|
|
char *indexPtr = RouteString;
|
|
ULONG address;
|
|
ULONG i;
|
|
char saveChar;
|
|
BOOLEAN EndOfString=FALSE;
|
|
|
|
//
|
|
// The route is laid out in the string as "Dest,Mask,Gateway,Mertic".
|
|
//
|
|
|
|
|
|
//
|
|
// set MetricVal to 1 to take care of persistent routes without the
|
|
// metric value
|
|
//
|
|
|
|
*MetricVal = 1;
|
|
|
|
for (i=0; i<4 && !EndOfString; i++) {
|
|
//
|
|
// Walk the string to the end of the current item.
|
|
//
|
|
|
|
while (1) {
|
|
|
|
if (*indexPtr == '\0') {
|
|
|
|
if ((i >= 2) && (indexPtr != addressPtr)) {
|
|
//
|
|
// End of string
|
|
//
|
|
EndOfString = TRUE;
|
|
break;
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
if (*indexPtr == ROUTE_SEPARATOR) {
|
|
break;
|
|
}
|
|
|
|
indexPtr++;
|
|
}
|
|
|
|
//
|
|
// NULL terminate the current substring and extract the address value.
|
|
//
|
|
saveChar = *indexPtr;
|
|
|
|
*indexPtr = '\0';
|
|
|
|
if (i==3) {
|
|
address = atoi (addressPtr);
|
|
} else if (!ImprovedInetAddr(addressPtr, &address)) {
|
|
*indexPtr = saveChar;
|
|
return(FALSE);
|
|
}
|
|
|
|
*indexPtr = saveChar;
|
|
|
|
switch(i) {
|
|
case 0: *DestVal = address; break;
|
|
case 1: *MaskVal = address; break;
|
|
case 2: *GateVal = address; break;
|
|
case 3: *MetricVal = address; break;
|
|
default: return FALSE;
|
|
}
|
|
addressPtr = ++indexPtr;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//
|
|
// Rajkumar - This function is based on route implementation
|
|
//
|
|
|
|
HRESULT
|
|
PrintPersistentRoutes(
|
|
NETDIAG_RESULT *pResults,
|
|
char* Dest,
|
|
ULONG DestVal,
|
|
char* Gate,
|
|
ULONG GateVal
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Displays the list of persistent routes
|
|
|
|
|
|
Arguments: Dest : The destination string. (display filter)
|
|
DestVal : The numeric destination value. (display filter)
|
|
Gate : The gateway string. (display filter)
|
|
GateVal : The numeric gateway value. (display filter)
|
|
|
|
Returns: None
|
|
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Delete this route from the PersistentRoutes list in the
|
|
// registry if it is there.
|
|
//
|
|
DWORD status;
|
|
HKEY key;
|
|
char valueString[ROUTE_DATA_STRING_SIZE];
|
|
DWORD valueStringSize;
|
|
DWORD valueType;
|
|
DWORD index = 0;
|
|
ULONG dest, mask, gate, metric;
|
|
BOOLEAN headerPrinted = FALSE;
|
|
BOOLEAN match;
|
|
|
|
pResults->Route.dwNumPersistentRoutes = 0;
|
|
InitializeListHead(&pResults->Route.lmsgPersistentRoute);
|
|
|
|
status = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\PersistentRoutes", &key);
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
|
|
while(1) {
|
|
|
|
|
|
valueStringSize = ROUTE_DATA_STRING_SIZE - 1;
|
|
|
|
status = RegEnumValueA(
|
|
key,
|
|
index++,
|
|
valueString,
|
|
&valueStringSize,
|
|
NULL,
|
|
&valueType,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
if ((status == ERROR_BUFFER_OVERFLOW) ||
|
|
(status == ERROR_MORE_DATA) )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (valueType != REG_SZ)
|
|
continue;
|
|
|
|
|
|
valueString[valueStringSize++] = '\0';
|
|
|
|
|
|
if ( !ExtractRoute(
|
|
valueString,
|
|
&dest,
|
|
&mask,
|
|
&gate,
|
|
&metric
|
|
)
|
|
)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
//IDS_ROUTE_14207 "%s\n"
|
|
AddMessageToList( &pResults->Route.lmsgPersistentRoute, Nd_ReallyVerbose,
|
|
IDS_ROUTE_14207,
|
|
PrintRouteEntry(dest, mask, gate, 0, metric));
|
|
|
|
pResults->Route.dwNumPersistentRoutes++;
|
|
|
|
} // end while
|
|
|
|
CloseHandle(key);
|
|
}
|
|
else
|
|
{
|
|
DebugMessage2("RegOpenKeyA %s failed\n","Tcpip\\Parameters\\Persistent");
|
|
return S_FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void MapInterface(char *IPAddr, ULONG IfIndex)
|
|
{
|
|
|
|
DWORD IpAddrTableSize=0;
|
|
PMIB_IPADDRTABLE pIpAddrTable=NULL;
|
|
char *TempBuf;
|
|
BOOL bOrder=TRUE;
|
|
HRESULT hr;
|
|
DWORD i;
|
|
|
|
|
|
sprintf(IPAddr,"%x",IfIndex);
|
|
|
|
hr=GetIpAddrTable(NULL,
|
|
&IpAddrTableSize,
|
|
bOrder);
|
|
|
|
if (hr != ERROR_SUCCESS && hr != ERROR_INSUFFICIENT_BUFFER) {
|
|
DebugMessage("GetIpAddrTable() failed.\n");
|
|
return;
|
|
}
|
|
|
|
pIpAddrTable=(PMIB_IPADDRTABLE) Malloc(IpAddrTableSize);
|
|
|
|
if (pIpAddrTable == NULL) {
|
|
DebugMessage("Out of Memory in RouteTest::MapInterface().\n");
|
|
return;
|
|
}
|
|
|
|
ZeroMemory( pIpAddrTable, IpAddrTableSize );
|
|
|
|
hr=GetIpAddrTable(pIpAddrTable,
|
|
&IpAddrTableSize,
|
|
bOrder);
|
|
|
|
|
|
if (hr != ERROR_SUCCESS)
|
|
{
|
|
DebugMessage("GetIpAddrTable() failed.\n");
|
|
Free(pIpAddrTable);
|
|
return;
|
|
}
|
|
|
|
|
|
for (i=0; i < pIpAddrTable->dwNumEntries; i++)
|
|
{
|
|
if ((pIpAddrTable->table[i].dwIndex == IfIndex) && (pIpAddrTable->table[i].dwAddr != 0) && (pIpAddrTable->table[i].wType & MIB_IPADDR_PRIMARY))
|
|
{
|
|
TempBuf=inet_ntoa(*(struct in_addr*)&pIpAddrTable->table[i].dwAddr);
|
|
if (!TempBuf) {
|
|
break;;
|
|
}
|
|
strcpy(IPAddr, TempBuf);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
Free(pIpAddrTable);
|
|
return;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
ImprovedInetAddr(
|
|
char *AddressString,
|
|
ULONG *AddressValue
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
Converts an IP address string to its numeric equivalent.
|
|
|
|
Arguments:
|
|
char *AddressString: The string to convert
|
|
ULONG AddressValue : The place to store the converted value.
|
|
|
|
Returns: TRUE
|
|
|
|
Author:
|
|
07/01/98 Rajkumar . Created.
|
|
--*/
|
|
{
|
|
ULONG address = inet_addr(AddressString);
|
|
|
|
if (address == 0xFFFFFFFF) {
|
|
if (strcmp(AddressString, "255.255.255.255") == 0) {
|
|
*AddressValue = address;
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
*AddressValue = address;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
void RouteGlobalPrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
|
|
{
|
|
if (!pParams->fReallyVerbose)
|
|
return;
|
|
|
|
if (pParams->fReallyVerbose || !FHrOK(pResults->Route.hrTestResult))
|
|
{
|
|
PrintNewLine(pParams, 2);
|
|
PrintTestTitleResult(pParams,
|
|
IDS_ROUTE_LONG,
|
|
IDS_ROUTE_SHORT,
|
|
TRUE,
|
|
pResults->Route.hrTestResult,
|
|
0);
|
|
}
|
|
|
|
if( pParams->fReallyVerbose)
|
|
{
|
|
if( 0 == pResults->Route.dwNumRoutes)
|
|
{
|
|
//IDS_ROUTE_14201 "No Entries in the IP Forward Table\n"
|
|
PrintMessage( pParams, IDS_ROUTE_14201);
|
|
}
|
|
else
|
|
{
|
|
//IDS_ROUTE_14202 "Active Routes :\n"
|
|
PrintMessage( pParams, IDS_ROUTE_14202);
|
|
PrintMessageList(pParams, &pResults->Route.lmsgRoute);
|
|
}
|
|
|
|
if( 0 == pResults->Route.dwNumPersistentRoutes)
|
|
{
|
|
//IDS_ROUTE_14208 "No persistent route entries.\n"
|
|
PrintMessage( pParams, IDS_ROUTE_14208);
|
|
|
|
}
|
|
else
|
|
{
|
|
//IDS_ROUTE_14206 "\nPersistent Route Entries: \n"
|
|
PrintMessage( pParams, IDS_ROUTE_14206);
|
|
PrintMessageList(pParams, &pResults->Route.lmsgPersistentRoute);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void RoutePerInterfacePrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults, INTERFACE_RESULT *pInterfaceResults)
|
|
{
|
|
if (!pParams->fReallyVerbose)
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
void RouteCleanup(IN NETDIAG_PARAMS *pParams,
|
|
IN OUT NETDIAG_RESULT *pResults)
|
|
{
|
|
MessageListCleanUp(&pResults->Route.lmsgRoute);
|
|
MessageListCleanUp(&pResults->Route.lmsgPersistentRoute);
|
|
}
|