windows-nt/Source/XPSP1/NT/net/rras/cm/customactions/cmroute/cmroute.cpp
2020-09-26 16:20:57 +08:00

1992 lines
53 KiB
C++

//+----------------------------------------------------------------------------
//
// File: cmroute.cpp
//
// Module: CMROUTE.DLL
//
// Synopsis: Route Plumbing implementation for CM, as a post-connect action
//
// Copyright (c) 1998-2000 Microsoft Corporation
//
// Author: 12-Mar-2000 SumitC Created
//
// Note:
//
//-----------------------------------------------------------------------------
#include "pch.h"
#include "iphlpapi.h"
#include "cmdebug.h"
//
// Function declarations
//
HRESULT ParseArgs(LPSTR pszArgList,
BOOL * pfUseFile,
LPSTR pszRoutesFile,
BOOL * pfUseURL,
LPSTR pszRoutesURL,
BOOL * pfProfile,
LPSTR pszProfile,
BOOL * pfURLNotFoundIgnorable,
BOOL * pfKeepTempFiles);
#if 0
// see note below
HRESULT CheckIPForwarding();
#endif
HRESULT Initialize(PMIB_IPFORWARDTABLE * pRouteTable, PMIB_IPFORWARDROW * pGateway);
HRESULT GetRoutesFromFile(LPSTR pszFileName,
LPSTR pszProfile,
LPSTR * ppszRouteInfo,
DWORD * pcbRouteInfo);
HRESULT GetRoutesFromURL(LPSTR pszURL,
BOOL fKeepTempFiles,
LPSTR * ppszRouteInfo,
DWORD * pcbRouteInfo);
HRESULT ProcessRouteInfo(const LPSTR pszNewRouteInfo,
DWORD cbNewRouteInfo,
PMIB_IPFORWARDTABLE pmibRouteTable,
PMIB_IPFORWARDROW pGateway,
BOOL * pfDeleteDefaultGateway);
HRESULT DeleteDefaultGateway(PMIB_IPFORWARDROW pGateway);
//
// Route Table functions
//
HRESULT GetRouteTable(PMIB_IPFORWARDTABLE * pTable);
DWORD GetIf(const MIB_IPFORWARDROW& route, const MIB_IPFORWARDTABLE& RouteTable);
PMIB_IPFORWARDROW GetDefaultGateway(PMIB_IPFORWARDTABLE pRouteTable);
//
// Helper functions
//
BOOL ConvertSzToIP(LPSTR sz, DWORD& dwIP);
LPTSTR IPtoTsz(DWORD dw);
LPSTR IPtosz(DWORD dwIP, char *psz);
LPSTR StrCpyWithoutQuotes(LPSTR pszDest, LPCSTR pszSrc);
BOOL VerifyProfileAndGetServiceDir(LPSTR pszProfile);
//
// IP Helper function prototypes
//
typedef DWORD (WINAPI *pfnCreateIpForwardEntrySpec)(PMIB_IPFORWARDROW);
typedef DWORD (WINAPI *pfnDeleteIpForwardEntrySpec)(PMIB_IPFORWARDROW);
typedef DWORD (WINAPI *pfnGetIpForwardTableSpec)(PMIB_IPFORWARDTABLE, PULONG, BOOL);
pfnCreateIpForwardEntrySpec g_pfnCreateIpForwardEntry = NULL;
pfnDeleteIpForwardEntrySpec g_pfnDeleteIpForwardEntry = NULL;
pfnGetIpForwardTableSpec g_pfnGetIpForwardTable = NULL;
HMODULE g_hIpHlpApi = NULL;
#if DBG
void PrintRouteTable();
#endif
//+----------------------------------------------------------------------------
//
// Func: FreeIpHlpApis
//
// Desc: This function frees the instance of iphlpapi.dll loaded through
// LoadIpHelpApis. Note that it also sets the module handle and all
// of the function pointers loaded from this module to NULL.
//
// Args: None
//
// Return: Nothing
//
// Notes:
//
// History: 14-Dec-2000 quintinb Created
//
//-----------------------------------------------------------------------------
void FreeIpHlpApis(void)
{
if (g_hIpHlpApi)
{
FreeLibrary(g_hIpHlpApi);
g_hIpHlpApi = NULL;
g_pfnCreateIpForwardEntry = NULL;
g_pfnDeleteIpForwardEntry = NULL;
g_pfnGetIpForwardTable = NULL;
}
}
//+----------------------------------------------------------------------------
//
// Func: LoadIpHelpApis
//
// Desc: This functions loads a copy of the iphlpapi.dll and then retrieves
// function pointers for CreateIpForwardEntry, DeleteIpForwardEntry,
// and GetIpForwardTable. The module handle and the function pointers
// are stored in globals vars.
//
// Args: None
//
// Return: HRESULT - S_OK on success, S_FALSE on failure. This prevents cmroute
// from returning an error value (which would stop the connection)
// but allows cmroute to exit cleanly.
//
// Notes:
//
// History: 14-Dec-2000 quintinb Created
//
//-----------------------------------------------------------------------------
HRESULT LoadIpHelpApis(void)
{
HRESULT hr = S_FALSE; // we want the connection to continue but cmroute to not do anything...
g_hIpHlpApi = LoadLibrary(TEXT("IPHLPAPI.DLL"));
if (g_hIpHlpApi)
{
g_pfnCreateIpForwardEntry = (pfnCreateIpForwardEntrySpec)GetProcAddress(g_hIpHlpApi, "CreateIpForwardEntry");
g_pfnDeleteIpForwardEntry = (pfnDeleteIpForwardEntrySpec)GetProcAddress(g_hIpHlpApi, "DeleteIpForwardEntry");
g_pfnGetIpForwardTable = (pfnGetIpForwardTableSpec)GetProcAddress(g_hIpHlpApi, "GetIpForwardTable");
if (g_pfnCreateIpForwardEntry && g_pfnDeleteIpForwardEntry && g_pfnGetIpForwardTable)
{
hr = S_OK;
}
else
{
FreeIpHlpApis();
}
}
CMTRACEHR("LoadIpHelpApis", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: SetRoutes
//
// Desc: The entry point for handling route munging for VPN connections.
// This is a Connection Manager connect action and uses the CM connect
// action format (see CMAK docs for more info). Thus the parameters
// to the dll are passed via a string which contains parameters (see the
// cmproxy spec for a list of the parameter values).
//
// Args: [hWnd] - window handle of caller
// [hInst] - instance handle of caller
// [pszArgs] - argument string for connect action
// [nShow] - unused
//
// Return: HRESULT
//
// Notes:
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT WINAPI SetRoutes(HWND hWnd, HINSTANCE hInst, LPSTR pszArgs, int nShow)
{
HRESULT hr = S_OK;
PMIB_IPFORWARDTABLE pRouteTable = NULL;
PMIB_IPFORWARDROW pGateway = NULL;
LPSTR pszRoutesFromFile = NULL;
DWORD cbRoutesFromFile = 0;
LPSTR pszRoutesFromURL = NULL;
DWORD cbRoutesFromURL = 0;
// results of parsing the commandline
BOOL fUseFile = FALSE;
BOOL fUseURL = FALSE;
BOOL fProfile = FALSE;
BOOL fURLNotFoundIsNotFatal = FALSE;
BOOL fDeleteDefaultGatewayViaFile = FALSE;
BOOL fDeleteDefaultGatewayViaURL = FALSE;
BOOL fKeepTempFiles = FALSE;
char szRoutesFile[MAX_PATH + 1];
char szRoutesURL[MAX_PATH + 1];
char szProfile[MAX_PATH + 1];
#if 0
/*
// start security check to block unauthorized users
// REVIEW: remove before shipping!
//
// Quick and dirty security test. See if we can open hard-coded file first.
// If file is not available, then bail out completely.
//
lstrcpy(szRoutesFile, "\\\\sherpa\\route-plumb\\msroutes.txt");
HANDLE hFile = CreateFile(szRoutesFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
CMTRACE1("Unable to access file %s\n", szRoutesFile);
MessageBox(NULL, "You are not authorized to use this tool.",
"CMROUTE.DLL Custom Action", MB_OK);
CloseHandle(hFile);
return E_ACCESSDENIED;
}
CloseHandle(hFile);
// end security check
*/
#endif
//
// See if we can get the function pointers we need in IP helper?
//
hr = LoadIpHelpApis();
if (S_OK != hr)
{
goto Cleanup;
}
//
// parse args
//
hr = ParseArgs(pszArgs,
&fUseFile,
szRoutesFile,
&fUseURL,
szRoutesURL,
&fProfile,
szProfile,
&fURLNotFoundIsNotFatal,
&fKeepTempFiles);
if (S_OK != hr)
{
goto Cleanup;
}
#if 0
// see note below
hr = CheckIPForwarding();
if (S_FALSE == hr)
{
CMTRACE("SetRoutes: IP forwarding is enabled - cmroute won't do anything");
hr = S_OK;
goto Cleanup;
}
if (S_OK != hr)
{
goto Cleanup;
}
#endif
#if DBG
PrintRouteTable();
#endif
//
// Get the routetable and default gateway
//
hr = Initialize(&pRouteTable, &pGateway);
if (S_OK != hr)
{
goto Cleanup;
}
//
// Get the routes out of the file if asked
//
if (fUseFile)
{
hr = GetRoutesFromFile(szRoutesFile,
(fProfile ? szProfile : NULL),
&pszRoutesFromFile,
&cbRoutesFromFile);
if (S_OK != hr)
{
goto Cleanup;
}
#if DBG
OutputDebugString(pszRoutesFromFile);
#endif
}
//
// Get the routes out of the URL if asked
//
if (fUseURL)
{
hr = GetRoutesFromURL(szRoutesURL,
fKeepTempFiles,
&pszRoutesFromURL,
&cbRoutesFromURL);
if (S_OK != hr)
{
//
// It might have been worth adding a clause below to restrict this
// to "failures to access the URL", but this list of errorcodes is
// likely to be large (and if the system is really hosed, we'll find
// out soon enough). So, bypass *all* errors if /DONT_REQUIRE_URL
// is set.
//
if (fURLNotFoundIsNotFatal)
{
//
// If URL_Access_Failure_Not_Fatal is set, don't return an error.
// However, we unset the flag so that we stop processing the URL.
//
CMTRACE("SetRoutes: dont_require_url is set, bypassing error");
fUseURL = FALSE;
hr = S_OK;
}
else
{
goto Cleanup;
}
}
#if DBG
OutputDebugString(pszRoutesFromURL);
#endif
}
//
// Now set the routes
//
MYDBGASSERT(S_OK == hr);
if (fUseFile)
{
hr = ProcessRouteInfo(pszRoutesFromFile, cbRoutesFromFile, pRouteTable, pGateway, &fDeleteDefaultGatewayViaFile);
if (S_OK != hr)
{
CMTRACE1("SetRoutes: adding routes from FILE failed with %x", hr);
goto Cleanup;
}
}
MYDBGASSERT(S_OK == hr);
if (fUseURL)
{
hr = ProcessRouteInfo(pszRoutesFromURL, cbRoutesFromURL, pRouteTable, pGateway, &fDeleteDefaultGatewayViaURL);
if (S_OK != hr)
{
if ((E_UNEXPECTED == hr) && fURLNotFoundIsNotFatal)
{
// we use E_UNEXPECTED to indicate that the URL points to a .htm file
// instead of the file containing just routes which is what we're
// expecting. In this case, we ignore this error.
//
CMTRACE("html string found error ignored because Dont_Require_URL is set");
hr = S_OK;
}
else
{
CMTRACE1("SetRoutes: adding routes from URL failed with %x", hr);
goto Cleanup;
}
}
}
//
// Delete default gateway
//
MYDBGASSERT(S_OK == hr);
if (fDeleteDefaultGatewayViaFile || fDeleteDefaultGatewayViaURL)
{
hr = DeleteDefaultGateway(pGateway);
}
Cleanup:
//
// cleanup and leave
//
if (pRouteTable)
{
VirtualFree(pRouteTable, 0, MEM_RELEASE);
}
FreeIpHlpApis();
CMTRACEHR("SetRoutes", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: GetNextToken
//
// Desc: utility function for parsing the argument string. Goes past leading
// whitespace and extracts a string
//
// Args: [pszStart] - IN the argument string
// [ppszEnd] - OUT where parsing for this arg ended
// [pszOut] - INOUT array of size MAX_PATH to hold arg if found
//
// Return: BOOL, TRUE if another arg found, FALSE if not
//
// Notes:
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
BOOL
GetNextToken(LPSTR pszStart, LPSTR * ppszEnd, LPSTR pszOut)
{
MYDBGASSERT(pszStart);
MYDBGASSERT(ppszEnd);
LPSTR pszEnd = NULL;
// clear leading white space
while (isspace(*pszStart))
{
pszStart++;
}
if (NULL == *pszStart)
{
// just white space, no arg
return FALSE;
}
//
// If this character is ", this is probably a quoted string, containing spaces.
// In this case, the termination character is another ". Otherwise, assume
// it is a regular string terminated by a space.
//
if ('"' == *pszStart)
{
// may be a string containing spaces.
pszEnd = strchr(pszStart + 1, '"');
}
if (NULL == pszEnd)
{
//
// Either it's a regular string, or we couldn't find a terminating " char
// so we fall back on space-delimited handling.
//
pszEnd = pszStart + 1;
while (*pszEnd && !isspace(*pszEnd))
{
pszEnd++;
}
pszEnd--;
}
UINT cLen = (UINT)(pszEnd - pszStart + 1);
if (cLen + 1 > MAX_PATH)
{
return FALSE;
}
else
{
lstrcpyn(pszOut, pszStart, cLen + 1);
*ppszEnd = ++pszEnd;
return TRUE;
}
}
//+----------------------------------------------------------------------------
//
// Func: Initialize
//
// Desc: Initialization function, gets the route table and default gateway
//
// Args: [ppmibRouteTable] - return location for route table
// [ppGateway] - return location for default gateway
//
// Return: HRESULT
//
// Notes:
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT
Initialize(
OUT PMIB_IPFORWARDTABLE * ppmibRouteTable,
OUT PMIB_IPFORWARDROW * ppGateway)
{
HRESULT hr = S_OK;
MYDBGASSERT(ppmibRouteTable);
MYDBGASSERT(ppGateway);
if (NULL == ppmibRouteTable || NULL == ppGateway)
{
return E_INVALIDARG;
}
hr = GetRouteTable(ppmibRouteTable);
if (S_OK == hr)
{
MYDBGASSERT(*ppmibRouteTable);
*ppGateway = GetDefaultGateway(*ppmibRouteTable);
}
CMTRACEHR("Initialize", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: ParseArgs
//
// Desc: convert the argument list into flags for our use.
//
// Args: [pszArgList] - IN, the argument list
// [the rest] - OUT, all the arg values returned
//
// Return: HRESULT
//
// Notes:
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT
ParseArgs(
LPSTR pszArgList,
BOOL * pfUseFile,
LPSTR pszRoutesFile,
BOOL * pfUseURL,
LPSTR pszRoutesURL,
BOOL * pfProfile,
LPSTR pszProfile,
BOOL * pfURLNotFoundIgnorable,
BOOL * pfKeepTempFiles)
{
HRESULT hr = S_OK;
char szArg[MAX_PATH];
//
// verify arguments
//
if (NULL == pszArgList || 0 == lstrlen(pszArgList) ||
!pfUseFile || !pszRoutesFile || !pfUseURL || !pszRoutesURL ||
!pfProfile || !pszProfile ||
!pfURLNotFoundIgnorable ||
!pfKeepTempFiles)
{
return E_INVALIDARG;
}
CMTRACE1("ParseArgs: arg list is %s", pszArgList);
//
// set the defaults
//
*pfUseFile = *pfUseURL = *pfProfile = *pfURLNotFoundIgnorable = FALSE;
//
// process the Arglist
//
while (GetNextToken(pszArgList, &pszArgList, szArg))
{
if (0 == lstrcmpi("/Static_File_Name", szArg))
{
*pfUseFile = TRUE;
if (!GetNextToken(pszArgList, &pszArgList, szArg))
{
return E_INVALIDARG;
}
if (lstrlen(szArg) > MAX_PATH)
{
CMTRACE("ParseArgs: file name is bigger than MAX_PATH!!");
return E_INVALIDARG;
}
StrCpyWithoutQuotes(pszRoutesFile, szArg);
}
else if (0 == lstrcmpi("/Dont_Require_URL", szArg))
{
*pfURLNotFoundIgnorable = TRUE;
}
else if (0 == lstrcmpi("/URL_Update_Path", szArg))
{
*pfUseURL = TRUE;
if (!GetNextToken(pszArgList, &pszArgList, szArg))
{
return E_INVALIDARG;
}
if (lstrlen(szArg) > MAX_PATH)
{
CMTRACE("ParseArgs: URL name is bigger than MAX_PATH!!");
return E_INVALIDARG;
}
lstrcpy(pszRoutesURL, szArg);
}
else if (0 == lstrcmpi("/Profile", szArg))
{
*pfProfile = TRUE;
if (!GetNextToken(pszArgList, &pszArgList, szArg))
{
return E_INVALIDARG;
}
if (lstrlen(szArg) > MAX_PATH)
{
CMTRACE("ParseArgs: Profile filename is bigger than MAX_PATH!!");
return E_INVALIDARG;
}
StrCpyWithoutQuotes(pszProfile, szArg);
}
else if (0 == lstrcmpi("/No_Delete", szArg))
{
*pfKeepTempFiles = TRUE;
}
else
{
CMTRACE1("Cmroute: unrecognized parameter - %s", szArg);
MYDBGASSERT("Cmroute - unrecognized parameter!!");
}
}
CMTRACEHR("ParseArgs", hr);
return hr;
}
#if 0
// 2000/11/28 SumitC
// It wasn't clear what the required action should be when IP forwarding was
// detected (should the connection be dropped or not) and it is a little late
// to add UI to Whistler. The 'Check IP forwarding' feature is thus removed.
//
// see Windows Db bug # 216558 for more details.
//+----------------------------------------------------------------------------
//
// Func: CheckIPForwarding
//
// Desc: checks to see if anything is enabled on the client machine that would
// make us want to have cmroute not do anything
//
// Args: none
//
// Return: HRESULT
//
// Notes:
//
// History: 01-Nov-2000 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT
CheckIPForwarding()
{
HRESULT hr = S_OK;
MIB_IPSTATS stats;
if (NO_ERROR != GetIpStatistics(&stats))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
if (stats.dwForwarding)
{
hr = S_FALSE;
}
}
CMTRACEHR("CheckIPForwarding", hr);
return hr;
}
#endif
//+----------------------------------------------------------------------------
//
// Func: GetRoutesFromFile
//
// Desc: extracts the contents of the given file
//
// Args: [pszFileName] - IN, filename
// [pszProfile] - IN, profile if available
// [ppszRouteInfo] - OUT, the route table bytes
// [pcbRouteInfo] - OUT, the route table size
//
// Return: HRESULT
//
// Notes:
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT
GetRoutesFromFile(
LPSTR pszFileName,
LPSTR pszProfile,
LPSTR * ppszRouteInfo,
DWORD * pcbRouteInfo)
{
HRESULT hr = S_OK;
HANDLE hFile = NULL;
LPSTR psz = NULL;
DWORD cb = 0;
BOOL fRet;
BY_HANDLE_FILE_INFORMATION info;
MYDBGASSERT(pszFileName);
MYDBGASSERT(ppszRouteInfo);
MYDBGASSERT(pcbRouteInfo);
if (NULL == pszFileName || NULL == ppszRouteInfo || NULL == pcbRouteInfo)
{
hr = E_INVALIDARG;
goto Cleanup;
}
CMTRACE1("GetRoutesFromFile: filename is %s", pszFileName);
//
// open the file, and read its contents into a buffer
//
hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
//
// perhaps the full pathname for the routes file wasn't specified. If
// a Profile was passed in, we extract the ServiceDir and try again,
// using the ServiceDir as the path.
//
if (VerifyProfileAndGetServiceDir(pszProfile))
{
char sz[2 * MAX_PATH + 1];
lstrcpy(sz, pszProfile);
lstrcat(sz, pszFileName);
CMTRACE1("GetRoutesFromFile: retrying with %s", sz);
hFile = CreateFile(sz, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
if (INVALID_HANDLE_VALUE == hFile)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}
}
if (FALSE == GetFileInformationByHandle(hFile, &info))
{
hr = E_FAIL;
goto Cleanup;
}
if (0 == info.nFileSizeLow)
{
CMTRACE("Routes file is EMPTY!!");
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
goto Cleanup;
}
psz = (LPSTR) VirtualAlloc(NULL, info.nFileSizeLow, MEM_COMMIT, PAGE_READWRITE);
if (NULL == psz)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
fRet = ReadFile(hFile, psz, info.nFileSizeLow, &cb, NULL);
if (FALSE == fRet)
{
hr = E_FAIL;
goto Cleanup;
}
// success
*ppszRouteInfo = psz;
*pcbRouteInfo = cb;
Cleanup:
if (hFile)
{
CloseHandle(hFile);
}
if (S_OK != hr)
{
VirtualFree(psz, 0, MEM_RELEASE);
}
CMTRACEHR("GetRoutesFromFile", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: GetRoutesFromURL
//
// Desc: extracts the contents of the given URL
//
// Args: [pszURL] - IN, the URL
// [fKeepTempFiles] - IN, do not delete temp buffer file(s)
// [ppszRouteInfo] - OUT, the route table bytes
// [pcbRouteInfo] - OUT, the route table size
//
// Return: HRESULT
//
// Notes:
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT
GetRoutesFromURL(
LPSTR pszURL,
BOOL fKeepTempFiles,
LPSTR * ppszRouteInfo,
DWORD * pcbRouteInfo)
{
HRESULT hr = S_OK;
HINTERNET hInternet = NULL;
HINTERNET hPage = NULL;
LPBYTE pb = NULL;
DWORD cb = 0;
TCHAR szLocalBufferFile[MAX_PATH + 1];
DWORD cchLocalBuffer = 0;
LPTSTR pszLocalBuffer = NULL;
FILE * fp = NULL;
BYTE Buffer[1024];
DWORD dwRead;
MYDBGASSERT(pszURL);
MYDBGASSERT(ppszRouteInfo);
MYDBGASSERT(pcbRouteInfo);
if (NULL == pszURL || NULL == ppszRouteInfo || NULL == pcbRouteInfo)
{
hr = E_INVALIDARG;
goto Cleanup;
}
CMTRACE1("GetRoutesFromURL: URL is %s", pszURL);
//
// Get the path to the temp dir, if there is one.
//
cchLocalBuffer = GetTempPath(0, NULL);
if (0 == cchLocalBuffer)
{
DWORD dwErr = GetLastError();
CMTRACE1(TEXT("GetTempPath failed, using current dir, GLE=%d"), dwErr);
}
else
{
cchLocalBuffer += (lstrlen(TEXT("\\")) + lstrlen(szLocalBufferFile) + 1);
pszLocalBuffer = (LPTSTR) VirtualAlloc(NULL,
cchLocalBuffer * sizeof(TCHAR),
MEM_COMMIT,
PAGE_READWRITE);
if (NULL == pszLocalBuffer)
{
hr = E_OUTOFMEMORY;
CMTRACE(TEXT("GetRoutesFromURL - VirtualAlloc failed"));
goto Cleanup;
}
if (0 == GetTempPath(cchLocalBuffer, pszLocalBuffer))
{
DWORD dwErr = GetLastError();
CMTRACE1(TEXT("GetTempPath 2nd call failed, GLE=%d"), GetLastError());
hr = HRESULT_FROM_WIN32(dwErr);
goto Cleanup;
}
}
//
// Get a name for the temp file (using the temp path if there is one)
//
if (0 == GetTempFileName(pszLocalBuffer ? pszLocalBuffer : TEXT("."),
TEXT("CMR"),
0,
szLocalBufferFile))
{
DWORD dwErr = GetLastError();
CMTRACE1(TEXT("GetTempFileName failed, GLE=%d"), dwErr);
hr = HRESULT_FROM_WIN32(dwErr);
goto Cleanup;
}
//
// Open the temp file, and proceed.
//
fp = fopen(szLocalBufferFile, "w+b");
if (NULL == fp)
{
CMTRACE1(TEXT("fopen failed(%s)"), szLocalBufferFile);
hr = E_FAIL;
goto Cleanup;
}
//
// Initialize WININET
//
hInternet = InternetOpen(TEXT("RouteMan"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (NULL == hInternet)
{
hr = HRESULT_FROM_WIN32(GetLastError());
CMTRACE1(TEXT("InternetOpen failed with 0x%x"), hr);
goto Cleanup;
}
//
// Open the URL
//
hPage = InternetOpenUrl(hInternet, pszURL, NULL, 0, 0, 0);
if (NULL == hPage)
{
hr = HRESULT_FROM_WIN32(GetLastError());
CMTRACE1(TEXT("InternetOpenUrl failed with 0x%x"), hr);
goto Cleanup;
}
//
// Read the entire URL contents into the tempfile
//
do
{
if (!InternetReadFile(hPage, Buffer, sizeof(Buffer), &dwRead))
{
hr = HRESULT_FROM_WIN32(GetLastError());
CMTRACE1(TEXT("InternetReadFile failed with 0x%x"), hr);
goto Cleanup;
}
if (fwrite(Buffer, sizeof(BYTE), dwRead, fp) != dwRead)
{
CMTRACE1(TEXT("write failed to %s"), pszLocalBuffer);
hr = HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
goto Cleanup;
}
cb += dwRead;
#if 0
// ISSUE-2000/07/21-SumitC Code seems strange but might need it later
//
// Vijay/Andrew's original code has this, but is this correct?
// The doc for InternetReadFile says this is just an EOF, if we
// are to handle this case at all, we should just break;
if (!dwRead)
goto Cleanup;
#endif
}
while (dwRead == 1024);
hr = S_OK;
if (fseek(fp, SEEK_SET, 0) != 0)
{
hr = E_FAIL;
goto Cleanup;
}
pb = (LPBYTE) VirtualAlloc(NULL, cb, MEM_COMMIT, PAGE_READWRITE);
if (NULL == pb)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
if (fread(pb, sizeof(BYTE), cb, fp) != cb)
{
hr = E_FAIL;
goto Cleanup;
}
// success
*ppszRouteInfo = (LPSTR) pb;
*pcbRouteInfo = cb;
Cleanup:
if (fp)
{
fclose(fp);
}
if (FALSE == fKeepTempFiles)
{
remove(szLocalBufferFile);
}
if (pszLocalBuffer && cchLocalBuffer)
{
VirtualFree(pszLocalBuffer, 0, MEM_RELEASE);
}
if (hPage)
{
InternetCloseHandle(hPage);
}
if (hInternet)
{
InternetCloseHandle(hInternet);
}
if (S_OK != hr)
{
VirtualFree(pb, 0, MEM_RELEASE);
}
CMTRACEHR("GetRoutesFromURL", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: ProcessRouteInfo
//
// Desc: Parses the given route table and modifies the real routetable accordingly
//
// Args: [pszNewRouteInfo] - IN, bytes of route table to parse and add to the real one
// [cbNewRouteInfo] - IN, size of routetable
// [pmibRouteTable] - IN, real route table
// [pGateway] - IN, default gateway
// [pfDeleteGateway] - OUT, does the route file say to delete default gateway?
//
// Return: HRESULT (E_INVALIDARG, E_UNEXPECTED - for html file, etc)
//
// Notes:
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT
ProcessRouteInfo(
const LPSTR pszNewRouteInfo,
DWORD cbNewRouteInfo,
PMIB_IPFORWARDTABLE pmibRouteTable,
PMIB_IPFORWARDROW pGateway,
BOOL * pfDeleteDefaultGateway)
{
HRESULT hr = S_OK;
DWORD cLines = 0;
char szBuf[MAX_PATH];
LPSTR pszNextLineToProcess;
MYDBGASSERT(pszNewRouteInfo);
MYDBGASSERT(cbNewRouteInfo);
MYDBGASSERT(pmibRouteTable);
MYDBGASSERT(pGateway);
MYDBGASSERT(pfDeleteDefaultGateway);
if (!pszNewRouteInfo || !cbNewRouteInfo || !pmibRouteTable || !pGateway || !pfDeleteDefaultGateway)
{
return E_INVALIDARG;
}
if ((NULL == g_pfnCreateIpForwardEntry) || (NULL == g_pfnDeleteIpForwardEntry))
{
return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
}
*pfDeleteDefaultGateway = FALSE;
// Make sure WININET zero terminates this....
pszNewRouteInfo[cbNewRouteInfo] = '\0';
//
// Convert string to lower
//
CharLowerA(pszNewRouteInfo);
//
// sanity checks (in the URL case, if the route file isn't found the server
// is likely to return an HTML file to indicate 404 - file not found.)
//
if (strstr(pszNewRouteInfo, "<html"))
{
CMTRACE("html string found - invalid route file\n");
hr = E_UNEXPECTED;
goto Cleanup;
}
//
// for each line
//
for (;;)
{
DWORD ipDest, ipMask, ipGateway, ipMetric;
DWORD dwIf = -1;
DWORD dwParam;
LPSTR psz; // temp var to hold each line as we process it
MIB_IPFORWARDROW route;
enum { VERB_ADD, VERB_DELETE } eVerb;
//
// Per strtok syntax, use pszNewRouteInfo the first time, and NULL thereafter
//
psz = strtok(((0 == cLines) ? pszNewRouteInfo : NULL), "\n\0");
if (NULL == psz)
break;
++cLines;
//
// All errors within the for statement are due to bad data within the file
//
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
//
// PART 1 : add/delete, followed by the IP address, or remove_gateway
//
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] didn't find add/delete which is required", cLines);
goto Cleanup;
}
if (0 == lstrcmpi(szBuf, "add"))
{
eVerb = VERB_ADD;
}
else if (0 == lstrcmpi(szBuf, "delete"))
{
eVerb = VERB_DELETE;
}
else if (0 == lstrcmpi(szBuf, "remove_gateway"))
{
*pfDeleteDefaultGateway = TRUE;
hr = S_OK;
// ignore the rest of the line
continue;
}
else
{
CMTRACE2("ProcessRouteInfo [%d] found unexpected string %s instead of add/delete/remove_gateway", cLines, szBuf);
goto Cleanup;
}
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] dest ip required for add/delete, and is missing", cLines);
goto Cleanup;
}
if (FALSE == ConvertSzToIP(szBuf, ipDest))
{
CMTRACE2("ProcessRouteInfo [%d] required ip address/mask %s has bad format", cLines, szBuf);
goto Cleanup;
}
//
// PART 2 : mask, followed by the IP address (NOT REQUIRED)
//
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] ends too early after add/delete", cLines);
goto Cleanup;
}
if (0 == lstrcmpi(szBuf, "mask"))
{
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] ip required for mask, and is missing", cLines);
goto Cleanup;
}
if (FALSE == ConvertSzToIP(szBuf, ipMask))
{
CMTRACE2("ProcessRouteInfo [%d] required ip address/mask %s has bad format", cLines, szBuf);
goto Cleanup;
}
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] ends too early after mask", cLines);
goto Cleanup;
}
}
else
{
CMTRACE1("ProcessRouteInfo [%d] didn't find \"mask\", that's ok, continuing", cLines);
ipMask = (DWORD)-1;
}
//
// PART 3 : gateway (or "default")
//
if (0 == lstrcmpi(szBuf, "default"))
{
ipGateway = pGateway->dwForwardNextHop;
}
else
{
if (FALSE == ConvertSzToIP(szBuf, ipGateway))
{
CMTRACE2("ProcessRouteInfo [%d] bad format for gateway %s", cLines, szBuf);
goto Cleanup;
}
}
//
// PART 4 : metric, followed by a number (REQUIRED)
//
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] didn't find \"metric\" which is required", cLines);
goto Cleanup;
}
if (0 == lstrcmpi(szBuf, "metric"))
{
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] number value after \"metric\" missing", cLines);
goto Cleanup;
}
if (0 == lstrcmpi(szBuf, "default"))
{
ipMetric = pGateway->dwForwardMetric1;
}
else
{
if (FALSE == ConvertSzToIP(szBuf, ipMetric))
{
CMTRACE2("ProcessRouteInfo [%d] required ip metric %s has bad format", cLines, szBuf);
goto Cleanup;
}
/*
#if 0
dwParam = sscanf(szBuf, "%d", &ipMetric);
if (0 == dwParam)
{
CMTRACE2("ProcessRouteInfo [%d] bad format for metric value - %s", cLines, szBuf);
goto Cleanup;
}
#endif
*/
}
}
else
{
CMTRACE2("ProcessRouteInfo [%d] found unexpected string %s instead of \"metric\"", cLines, szBuf);
goto Cleanup;
}
//
// PART 5 : if (the interface), followed by a number (REQUIRED)
//
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] didn't find \"if\" which is required", cLines);
goto Cleanup;
}
if (0 == lstrcmpi(szBuf, "if"))
{
if (FALSE == GetNextToken(psz, &psz, szBuf))
{
CMTRACE1("ProcessRouteInfo [%d] number value after \"if\" missing", cLines);
goto Cleanup;
}
if (0 == lstrcmpi(szBuf, "default"))
{
dwIf = pGateway->dwForwardIfIndex;
}
else
{
dwParam = sscanf(szBuf, "%d", &dwIf);
if (0 == dwParam)
{
CMTRACE2("ProcessRouteInfo [%d] bad format for if value - %s", cLines, szBuf);
goto Cleanup;
}
}
}
else
{
CMTRACE2("ProcessRouteInfo [%d] found unexpected string %s instead of \"if\"", cLines, szBuf);
goto Cleanup;
}
//
// Run the verb (add or delete)
//
ZeroMemory(&route, sizeof(route));
route.dwForwardDest = ipDest;
route.dwForwardIfIndex = dwIf;
route.dwForwardMask = ipMask;
route.dwForwardMetric1 = ipMetric;
route.dwForwardNextHop = ipGateway;
route.dwForwardPolicy = 0;
route.dwForwardNextHopAS = 0;
route.dwForwardType = 3;
route.dwForwardProto = 3;
route.dwForwardAge = INFINITE;
route.dwForwardMetric2 = 0xFFFFFFFF;
route.dwForwardMetric3 = 0xFFFFFFFF;
route.dwForwardMetric4 = 0xFFFFFFFF;
route.dwForwardMetric5 = 0xFFFFFFFF;
// ISSUE-2000/07/21-SumitC Can we ever really get here in the code with dwIf == -1 ?
//
// Check that the interface was specified
if (-1 == dwIf)
{
// Nope, lets go pick one
dwIf = GetIf(route, *pmibRouteTable);
}
DWORD dwRet = 0;
switch (eVerb)
{
case VERB_ADD:
dwRet = g_pfnCreateIpForwardEntry(&route);
if (ERROR_SUCCESS != dwRet)
{
CMTRACE2("ProcessRouteInfo [%d] CreateIpForwardEntry failed with %d", cLines, dwRet);
hr = HRESULT_FROM_WIN32(dwRet);
goto Cleanup;
}
hr = S_OK;
break;
case VERB_DELETE:
dwRet = g_pfnDeleteIpForwardEntry(&route);
if (ERROR_SUCCESS != dwRet)
{
CMTRACE2("ProcessRouteInfo [%d] DeleteIpForwardEntry failed with %d", cLines, dwRet);
hr = HRESULT_FROM_WIN32(dwRet);
goto Cleanup;
}
hr = S_OK;
break;
default:
CMTRACE("ProcessRouteInfo [%d] Unsupported route command, add or delete only");
MYDBGASSERT(0);
hr = E_FAIL;
break;
}
}
Cleanup:
CMTRACEHR("ProcessRouteInfo", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: DeleteDefaultGateway
//
// Desc: Deletes the default routing gateway for this system
//
// Args: [pGateway] - the gateway
//
// Return: HRESULT
//
// Notes: This should be the last function called within CMroute, and is called
// only if all other processing succeeded.
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
HRESULT
DeleteDefaultGateway(PMIB_IPFORWARDROW pGateway)
{
CMTRACE("DeleteDefaultGateway: entering");
HRESULT hr = S_OK;
DWORD dwErr = 0;
if (NULL == g_pfnDeleteIpForwardEntry)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
goto Cleanup;
}
dwErr = g_pfnDeleteIpForwardEntry(pGateway);
if (NO_ERROR != dwErr)
{
hr = HRESULT_FROM_WIN32(dwErr);
CMTRACE1("DeleteDefaultGateway failed with error %x", dwErr);
}
Cleanup:
CMTRACEHR("DeleteDefaultGateway", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: IsValidIPAddress
//
// Desc: Checks to see if given string can be a valid IP address
//
// Args: [sz] - IN, the string
//
// Return: BOOL, FALSE means invalid chars were found
//
// History: 20-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
BOOL
IsValidIPAddress(LPSTR sz)
{
MYDBGASSERT(sz);
while ((*sz) && (!isspace(*sz)))
{
if ((*sz >= '0') && (*sz <= '9'))
;
else if ((*sz == '.') || (*sz == '*') || (*sz == '?'))
;
else
{
CMTRACE1(TEXT("IsValidIPAddress failed on %s\n"), sz);
MYDBGASSERT("IsValidIPAddress");
return FALSE;
}
++sz;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Func: ConvertSzToIP
//
// Desc: Converts the given string into a DWORD representing an IP address
//
// Args: [sz] - IN, string to convert
// [dwIP] - OUT BYREF, dword for IP address
//
// Return: BOOL, FALSE if conversion failed (usually means bad format)
//
// History: 12-Mar-2000 SumitC Created
//
//-----------------------------------------------------------------------------
BOOL
ConvertSzToIP(LPSTR sz, DWORD& dwIP)
{
DWORD dwParams, d1, d2, d3, d4;
if (FALSE == IsValidIPAddress(sz))
{
return FALSE;
}
dwParams = sscanf(sz, "%d.%d.%d.%d", &d1, &d2, &d3, &d4);
if (0 == dwParams)
{
MYDBGASSERT("ConvertSzToIP - bad format for IP address");
return FALSE;
}
else if (1 == dwParams)
{
dwIP = d1 | 0xffffff00;
}
else if (2 == dwParams)
{
dwIP = d1 | (d2 << 8) | 0xffff0000;
}
else if (3 == dwParams)
{
dwIP = d1 | (d2 << 8) | (d3 << 16) | 0xff000000;
}
else
{
dwIP = d1 | (d2 << 8) | (d3 << 16) | (d4 << 24);
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Func: GetRouteTable
//
// Desc: Same as GetIpForwardTable but alloc's the table for you.
// VirtualFree() the buffer returned.
//
// Args: [ppTable] - OUT, returned route table
//
// Return: HRESULT
//
// Notes: ppTable should be VirtualFree'd by caller.
//
// History: 24-Feb-1999 AnBrad Created
// 22-Mar-2000 SumitC Rewrote
//
//-----------------------------------------------------------------------------
HRESULT
GetRouteTable(PMIB_IPFORWARDTABLE * ppTable)
{
DWORD dwErr = NO_ERROR;
DWORD cbbuf = 0;
PMIB_IPFORWARDTABLE p = NULL;
HRESULT hr = S_OK;
MYDBGASSERT(ppTable);
//
// Make sure we have a function pointer for GetIpForwardTable
//
if (NULL == g_pfnGetIpForwardTable)
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
goto Cleanup;
}
//
// Get the route table
//
dwErr = g_pfnGetIpForwardTable(NULL, &cbbuf, FALSE);
if (ERROR_INSUFFICIENT_BUFFER != dwErr)
{
// hmm, a real error
hr = HRESULT_FROM_WIN32(ERROR_UNEXP_NET_ERR);
goto Cleanup;
}
else
{
p = (PMIB_IPFORWARDTABLE) VirtualAlloc(NULL, cbbuf, MEM_COMMIT, PAGE_READWRITE);
if (!p)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
if (g_pfnGetIpForwardTable(p, &cbbuf, TRUE))
{
hr = E_FAIL;
goto Cleanup;
}
*ppTable = p;
}
Cleanup:
if (S_OK != hr)
{
if (p)
{
VirtualFree(p, 0, MEM_RELEASE);
}
}
CMTRACEHR("GetRouteTable", hr);
return hr;
}
//+----------------------------------------------------------------------------
//
// Func: GetIf
//
// Desc: Find the interface for a route
//
// Args: [route] - IN, route for which we need the Interface
// [RouteTable] - IN, route table
//
// Return: DWORD which is the IF
//
// Notes: Logic stolen from \nt\private\net\sockets\strmtcp\route
//
// History: 24-Feb-1999 AnBrad Created
// 22-Mar-2000 SumitC Cleaned up
//
//-----------------------------------------------------------------------------
DWORD
GetIf(const MIB_IPFORWARDROW& route, const MIB_IPFORWARDTABLE& RouteTable)
{
for(DWORD dwIndex = 0; dwIndex < RouteTable.dwNumEntries; dwIndex++)
{
const MIB_IPFORWARDROW& Row = RouteTable.table[dwIndex];
if (Row.dwForwardMask &&
(Row.dwForwardDest & Row.dwForwardMask) ==
(route.dwForwardNextHop & Row.dwForwardMask))
{
return Row.dwForwardIfIndex;
}
}
return 0;
}
//+----------------------------------------------------------------------------
//
// Func: GetDefaultGateway
//
// Desc: Find the default gateway
//
// Args: [pRouteTable] - IN, the route table (IP forward table)
//
// Return: PMIB_IPFORWARDROW the row of the gateway (a ptr within pRouteTable)
//
// Notes: Do not free returned value
//
// History: 24-Feb-1999 AnBrad Created
// 22-Mar-2000 SumitC Cleaned up
//
//-----------------------------------------------------------------------------
PMIB_IPFORWARDROW
GetDefaultGateway(PMIB_IPFORWARDTABLE pRouteTable)
{
PMIB_IPFORWARDROW pRow, pDefGateway;
// Cycle thru the entire table & find the gateway with the least metric
pDefGateway = NULL;
for(pRow = pRouteTable->table; pRow != pRouteTable->table + pRouteTable->dwNumEntries; ++pRow)
{
if (pRow->dwForwardDest == 0)
{
if (pDefGateway == NULL)
{
pDefGateway = pRow;
}
else
{
if (pRow->dwForwardMetric1 == pDefGateway->dwForwardMetric1 &&
pRow->dwForwardAge >= pDefGateway->dwForwardAge)
{
pDefGateway = pRow;
}
if (pRow->dwForwardMetric1 < pDefGateway->dwForwardMetric1)
{
pDefGateway = pRow;
}
}
}
}
return pDefGateway;
}
//+----------------------------------------------------------------------------
//
// Func: StrCpyWithoutQuotes
//
// Desc: Wrapper for lstrcpy, which removes surrounding double quotes if necessary
//
// Args: [pszDest] - OUT, destination for the copy
// [pszSrc] - OUT, source for the copy
//
// Return: a ptr to pszDest, or NULL if failure.
//
// Notes:
//
// History: 12-Apr-1999 SumitC Created
//
//-----------------------------------------------------------------------------
LPSTR
StrCpyWithoutQuotes(LPSTR pszDest, LPCSTR pszSrc)
{
MYDBGASSERT(pszDest);
MYDBGASSERT(pszSrc);
int len = lstrlen(pszSrc);
if ((len > 2) && ('"' == pszSrc[0]) && ('"' == pszSrc[len - 1]))
{
return lstrcpyn(pszDest, &pszSrc[1], len - 1);
}
else
{
return lstrcpy(pszDest, pszSrc);
}
}
//+----------------------------------------------------------------------------
//
// Func: VerifyProfileAndGetServiceDir
//
// Desc: Checks the given profile, and modifies it to produce the ServiceDir
//
// Args: [pszProfile] - IN OUT, profile name, modified IN PLACE
//
// Return: TRUE if modified pszProfile is now the ServiceDir, or FALSE if failure.
//
// Notes: pszProfile is MODIFIED IN PLACE.
//
// History: 12-Apr-1999 SumitC Created
//
//-----------------------------------------------------------------------------
BOOL
VerifyProfileAndGetServiceDir(IN OUT LPSTR pszProfile)
{
HANDLE hFile = NULL;
MYDBGASSERT(pszProfile);
MYDBGASSERT(lstrlen(pszProfile));
if ((NULL == pszProfile) || (lstrlen(pszProfile) < 4))
{
return FALSE;
}
//
// The profile string may be surrounded by double-quotes, if so remove them.
//
//
// First check to see if the profile really exists. This also serves as
// verification for the existence of the directory.
//
hFile = CreateFile(pszProfile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
return FALSE;
}
else
{
CloseHandle(hFile);
}
//
// Now check to see that the file does indeed end in .CMP
//
LPSTR psz = pszProfile + lstrlen(pszProfile) - lstrlen(".CMP");
if (0 != lstrcmpi(psz, ".CMP"))
{
return FALSE;
}
//
// The profile name is the same as the ServiceDir name, so we just terminate
// the string at the '.' and append a '\'
//
*psz = '\\';
psz++;
*psz = '\0';
return TRUE;
}
#if DBG
LPWSTR wszType[] = {L"Other",
L"Invalid",
L"Direct",
L"Indirect"};
LPWSTR wszProto[] ={L"Other", // MIB_IPPROTO_OTHER 1
L"Local", // MIB_IPPROTO_LOCAL 2
L"SNMP", // MIB_IPPROTO_NETMGMT 3
L"ICMP", // MIB_IPPROTO_ICMP 4
L"Exterior Gateway Protocol", // MIB_IPPROTO_EGP 5
L"GGP", // MIB_IPPROTO_GGP 6
L"Hello", // MIB_IPPROTO_HELLO 7
L"Routing Information Protocol", // MIB_IPPROTO_RIP 8
L"IS IS", // MIB_IPPROTO_IS_IS 9
L"ES IS", // MIB_IPPROTO_ES_IS 10
L"Cicso", // MIB_IPPROTO_CISCO 11
L"BBN", // MIB_IPPROTO_BBN 12
L"Open Shortest Path First", // MIB_IPPROTO_OSPF 13
L"Border Gateway Protocol"}; // MIB_IPPROTO_BGP 14
//+----------------------------------------------------------------------
//
// Function: PrintRoute
//
// Purpose: Prints out a route from the IP forward table
//
// Arguments:
// pRow [in] the route
//
// Returns: zip
//
// Author: anbrad 24 Feb 1999
//
// Notes:
//
//-----------------------------------------------------------------------
void PrintRoute(PMIB_IPFORWARDROW pRow)
{
TCHAR sz[MAX_PATH];
wsprintf(sz, "dwDest = %s\n", IPtoTsz(pRow->dwForwardDest)); // IP addr of destination
OutputDebugString(sz);
wsprintf(sz, "dwMask = %s\n", IPtoTsz(pRow->dwForwardMask)); // subnetwork mask of destination
OutputDebugString(sz);
wsprintf(sz, "dwPolicy = %d\n"
"dwNextHop = %s\n"
"dwIfIndex = %d\n"
"dwType = %s\n"
"dwProto = %s\n"
"dwAge = %d\n"
"dwNextHopAS = %d\n",
pRow->dwForwardPolicy, // conditions for multi-path route
IPtoTsz(pRow->dwForwardNextHop), // IP address of next hop
pRow->dwForwardIfIndex, // index of interface
wszType[pRow->dwForwardType-1], // route type
wszProto[pRow->dwForwardProto-1], // protocol that generated route
pRow->dwForwardAge, // age of route
pRow->dwForwardNextHopAS); // autonomous system number
// of next hop
OutputDebugString(sz);
if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric1)
{
wsprintf(sz, "dwMetric1 = %d\n", pRow->dwForwardMetric1);
OutputDebugString(sz);
}
if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric2)
{
wsprintf(sz, "dwMetric2 = %d\n", pRow->dwForwardMetric2);
OutputDebugString(sz);
}
if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric3)
{
wsprintf(sz, "dwMetric3 = %d\n", pRow->dwForwardMetric3);
OutputDebugString(sz);
}
if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric4)
{
wsprintf(sz, "dwMetric4 = %d\n", pRow->dwForwardMetric4);
OutputDebugString(sz);
}
if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric5)
{
wsprintf(sz, "dwMetric5 = %d\n", pRow->dwForwardMetric5);
OutputDebugString(sz);
}
wsprintf(sz, "\n");
OutputDebugString(sz);
}
#if DBG
//+----------------------------------------------------------------------
//
// Function: PrintRouteTable
//
// Purpose: Does a "ROUTE PRINT" using the iphlpapi's
//
// Arguments: none
//
// Returns: zip
//
// Author: anbrad 24 Feb 1999
//
// Notes:
//
//-----------------------------------------------------------------------
void PrintRouteTable()
{
#define PAGE 4096
BYTE buf[PAGE];
DWORD cbbuf = sizeof(buf);
TCHAR sz[MAX_PATH];
if (g_pfnGetIpForwardTable)
{
PMIB_IPFORWARDTABLE table = (PMIB_IPFORWARDTABLE)&buf;
if (g_pfnGetIpForwardTable(table, &cbbuf, TRUE))
return;
wsprintf(sz, "\n\nFound %d routes\n", table->dwNumEntries);
OutputDebugString(sz);
for (DWORD d=0; d < table->dwNumEntries; ++d)
{
PrintRoute(table->table+d);
}
}
}
#endif
//+----------------------------------------------------------------------
//
// Function: IPtoTsz
//
// Purpose: Changes a dword to a "dotted string" notation
//
// Arguments:
// dw [in] IP address
//
// Returns: LPTSTR which is a static string
//
// Author: anbrad 24 Feb 1999
//
// Notes: Global makes this NOT thread safe, and it is not needed
// for cmroute.exe
//
//-----------------------------------------------------------------------
TCHAR tsz[20];
LPTSTR IPtoTsz(DWORD dw)
{
wsprintf(tsz, TEXT("%03d.%03d.%03d.%03d"),
(DWORD)LOBYTE(LOWORD(dw)),
(DWORD)HIBYTE(LOWORD(dw)),
(DWORD)LOBYTE(HIWORD(dw)),
(DWORD)HIBYTE(HIWORD(dw)));
return tsz;
}
LPSTR IPtosz(DWORD dwIP, char *psz)
{
wsprintfA(psz, ("%d.%d.%d.%d"),
(DWORD)LOBYTE(LOWORD(dwIP)),
(DWORD)HIBYTE(LOWORD(dwIP)),
(DWORD)LOBYTE(HIWORD(dwIP)),
(DWORD)HIBYTE(HIWORD(dwIP)));
return psz;
}
#endif // DBG