|
|
//+----------------------------------------------------------------------------
//
// 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"
//
// Include the shared source code for SuppressInetAutoDial and SetInetStateConnected
//
#include "inetopt.cpp"
//
// Include the locale-safe replacement for lstrcmpi
//
#include "CompareString.cpp"
//
// Function declarations
//
HRESULT ParseArgs(LPSTR pszArgList, BOOL * pfUseFile, LPSTR pszRoutesFile, BOOL * pfUseURL, LPSTR pszRoutesURL, BOOL * pfProfile, LPSTR pszProfile, BOOL * pfURLNotFoundIgnorable, BOOL * pfStayAliveOnAccessDenied, 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 fStayAliveOnAccessDenied = 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, &fStayAliveOnAccessDenied, &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();
//
// If we failed because of an access denied error from iphlpapi, but the admin
// has set the flag to keep the connection alive anyway, mask the error.
//
if ((HRESULT_FROM_WIN32(ERROR_NETWORK_ACCESS_DENIED) == hr) && fStayAliveOnAccessDenied) { CMTRACE("SetRoutes: masking ERROR_NETWORK_ACCESS_DENIED because of StayAlive flag"); hr = S_FALSE; }
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 * pfStayAliveOnAccessDenied, 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 == SafeCompareString("/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 == SafeCompareString("/Dont_Require_URL", szArg)) { *pfURLNotFoundIgnorable = TRUE; } else if (0 == SafeCompareString("/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 == SafeCompareString("/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 == SafeCompareString("/IPHlpApi_Access_Denied_OK", szArg)) { *pfStayAliveOnAccessDenied = TRUE; } else if (0 == SafeCompareString("/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; }
//
// Supress auto-dial calls to CM from WININET now that we have a handle
//
SuppressInetAutoDial(hInternet);
//
// Make sure that WinInet isn't in offline mode
//
(VOID)SetInetStateConnected(hInternet);
//
// 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 == SafeCompareString(szBuf, "add")) { eVerb = VERB_ADD; } else if (0 == SafeCompareString(szBuf, "delete")) { eVerb = VERB_DELETE; } else if (0 == SafeCompareString(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 == SafeCompareString(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 == SafeCompareString(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 == SafeCompareString(szBuf, "metric")) { if (FALSE == GetNextToken(psz, &psz, szBuf)) { CMTRACE1("ProcessRouteInfo [%d] number value after \"metric\" missing", cLines); goto Cleanup; }
if (0 == SafeCompareString(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 == SafeCompareString(szBuf, "if")) { if (FALSE == GetNextToken(psz, &psz, szBuf)) { CMTRACE1("ProcessRouteInfo [%d] number value after \"if\" missing", cLines); goto Cleanup; }
if (0 == SafeCompareString(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) { // NETWORK_ACCESS_DENIED (0x41=65) is special-cased at the end of SetRoutes
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) { // NETWORK_ACCESS_DENIED (0x41=65) is special-cased at the end of SetRoutes
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 != SafeCompareString(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
LPTSTR aszMapType[] = {TEXT("Other"), TEXT("Invalid"), TEXT("Direct"), TEXT("Indirect")};
LPTSTR aszMapProto[] = {TEXT("Other"), // MIB_IPPROTO_OTHER 1
TEXT("Local"), // MIB_IPPROTO_LOCAL 2
TEXT("SNMP"), // MIB_IPPROTO_NETMGMT 3
TEXT("ICMP"), // MIB_IPPROTO_ICMP 4
TEXT("Exterior Gateway Protocol"), // MIB_IPPROTO_EGP 5
TEXT("GGP"), // MIB_IPPROTO_GGP 6
TEXT("Hello"), // MIB_IPPROTO_HELLO 7
TEXT("Routing Information Protocol"), // MIB_IPPROTO_RIP 8
TEXT("IS IS"), // MIB_IPPROTO_IS_IS 9
TEXT("ES IS"), // MIB_IPPROTO_ES_IS 10
TEXT("Cicso"), // MIB_IPPROTO_CISCO 11
TEXT("BBN"), // MIB_IPPROTO_BBN 12
TEXT("Open Shortest Path First"), // MIB_IPPROTO_OSPF 13
TEXT("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
aszMapType[pRow->dwForwardType-1], // route type
aszMapProto[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
|