Source code of Windows XP (NT5)
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.

1991 lines
53 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: cmroute.cpp
  4. //
  5. // Module: CMROUTE.DLL
  6. //
  7. // Synopsis: Route Plumbing implementation for CM, as a post-connect action
  8. //
  9. // Copyright (c) 1998-2000 Microsoft Corporation
  10. //
  11. // Author: 12-Mar-2000 SumitC Created
  12. //
  13. // Note:
  14. //
  15. //-----------------------------------------------------------------------------
  16. #include "pch.h"
  17. #include "iphlpapi.h"
  18. #include "cmdebug.h"
  19. //
  20. // Function declarations
  21. //
  22. HRESULT ParseArgs(LPSTR pszArgList,
  23. BOOL * pfUseFile,
  24. LPSTR pszRoutesFile,
  25. BOOL * pfUseURL,
  26. LPSTR pszRoutesURL,
  27. BOOL * pfProfile,
  28. LPSTR pszProfile,
  29. BOOL * pfURLNotFoundIgnorable,
  30. BOOL * pfKeepTempFiles);
  31. #if 0
  32. // see note below
  33. HRESULT CheckIPForwarding();
  34. #endif
  35. HRESULT Initialize(PMIB_IPFORWARDTABLE * pRouteTable, PMIB_IPFORWARDROW * pGateway);
  36. HRESULT GetRoutesFromFile(LPSTR pszFileName,
  37. LPSTR pszProfile,
  38. LPSTR * ppszRouteInfo,
  39. DWORD * pcbRouteInfo);
  40. HRESULT GetRoutesFromURL(LPSTR pszURL,
  41. BOOL fKeepTempFiles,
  42. LPSTR * ppszRouteInfo,
  43. DWORD * pcbRouteInfo);
  44. HRESULT ProcessRouteInfo(const LPSTR pszNewRouteInfo,
  45. DWORD cbNewRouteInfo,
  46. PMIB_IPFORWARDTABLE pmibRouteTable,
  47. PMIB_IPFORWARDROW pGateway,
  48. BOOL * pfDeleteDefaultGateway);
  49. HRESULT DeleteDefaultGateway(PMIB_IPFORWARDROW pGateway);
  50. //
  51. // Route Table functions
  52. //
  53. HRESULT GetRouteTable(PMIB_IPFORWARDTABLE * pTable);
  54. DWORD GetIf(const MIB_IPFORWARDROW& route, const MIB_IPFORWARDTABLE& RouteTable);
  55. PMIB_IPFORWARDROW GetDefaultGateway(PMIB_IPFORWARDTABLE pRouteTable);
  56. //
  57. // Helper functions
  58. //
  59. BOOL ConvertSzToIP(LPSTR sz, DWORD& dwIP);
  60. LPTSTR IPtoTsz(DWORD dw);
  61. LPSTR IPtosz(DWORD dwIP, char *psz);
  62. LPSTR StrCpyWithoutQuotes(LPSTR pszDest, LPCSTR pszSrc);
  63. BOOL VerifyProfileAndGetServiceDir(LPSTR pszProfile);
  64. //
  65. // IP Helper function prototypes
  66. //
  67. typedef DWORD (WINAPI *pfnCreateIpForwardEntrySpec)(PMIB_IPFORWARDROW);
  68. typedef DWORD (WINAPI *pfnDeleteIpForwardEntrySpec)(PMIB_IPFORWARDROW);
  69. typedef DWORD (WINAPI *pfnGetIpForwardTableSpec)(PMIB_IPFORWARDTABLE, PULONG, BOOL);
  70. pfnCreateIpForwardEntrySpec g_pfnCreateIpForwardEntry = NULL;
  71. pfnDeleteIpForwardEntrySpec g_pfnDeleteIpForwardEntry = NULL;
  72. pfnGetIpForwardTableSpec g_pfnGetIpForwardTable = NULL;
  73. HMODULE g_hIpHlpApi = NULL;
  74. #if DBG
  75. void PrintRouteTable();
  76. #endif
  77. //+----------------------------------------------------------------------------
  78. //
  79. // Func: FreeIpHlpApis
  80. //
  81. // Desc: This function frees the instance of iphlpapi.dll loaded through
  82. // LoadIpHelpApis. Note that it also sets the module handle and all
  83. // of the function pointers loaded from this module to NULL.
  84. //
  85. // Args: None
  86. //
  87. // Return: Nothing
  88. //
  89. // Notes:
  90. //
  91. // History: 14-Dec-2000 quintinb Created
  92. //
  93. //-----------------------------------------------------------------------------
  94. void FreeIpHlpApis(void)
  95. {
  96. if (g_hIpHlpApi)
  97. {
  98. FreeLibrary(g_hIpHlpApi);
  99. g_hIpHlpApi = NULL;
  100. g_pfnCreateIpForwardEntry = NULL;
  101. g_pfnDeleteIpForwardEntry = NULL;
  102. g_pfnGetIpForwardTable = NULL;
  103. }
  104. }
  105. //+----------------------------------------------------------------------------
  106. //
  107. // Func: LoadIpHelpApis
  108. //
  109. // Desc: This functions loads a copy of the iphlpapi.dll and then retrieves
  110. // function pointers for CreateIpForwardEntry, DeleteIpForwardEntry,
  111. // and GetIpForwardTable. The module handle and the function pointers
  112. // are stored in globals vars.
  113. //
  114. // Args: None
  115. //
  116. // Return: HRESULT - S_OK on success, S_FALSE on failure. This prevents cmroute
  117. // from returning an error value (which would stop the connection)
  118. // but allows cmroute to exit cleanly.
  119. //
  120. // Notes:
  121. //
  122. // History: 14-Dec-2000 quintinb Created
  123. //
  124. //-----------------------------------------------------------------------------
  125. HRESULT LoadIpHelpApis(void)
  126. {
  127. HRESULT hr = S_FALSE; // we want the connection to continue but cmroute to not do anything...
  128. g_hIpHlpApi = LoadLibrary(TEXT("IPHLPAPI.DLL"));
  129. if (g_hIpHlpApi)
  130. {
  131. g_pfnCreateIpForwardEntry = (pfnCreateIpForwardEntrySpec)GetProcAddress(g_hIpHlpApi, "CreateIpForwardEntry");
  132. g_pfnDeleteIpForwardEntry = (pfnDeleteIpForwardEntrySpec)GetProcAddress(g_hIpHlpApi, "DeleteIpForwardEntry");
  133. g_pfnGetIpForwardTable = (pfnGetIpForwardTableSpec)GetProcAddress(g_hIpHlpApi, "GetIpForwardTable");
  134. if (g_pfnCreateIpForwardEntry && g_pfnDeleteIpForwardEntry && g_pfnGetIpForwardTable)
  135. {
  136. hr = S_OK;
  137. }
  138. else
  139. {
  140. FreeIpHlpApis();
  141. }
  142. }
  143. CMTRACEHR("LoadIpHelpApis", hr);
  144. return hr;
  145. }
  146. //+----------------------------------------------------------------------------
  147. //
  148. // Func: SetRoutes
  149. //
  150. // Desc: The entry point for handling route munging for VPN connections.
  151. // This is a Connection Manager connect action and uses the CM connect
  152. // action format (see CMAK docs for more info). Thus the parameters
  153. // to the dll are passed via a string which contains parameters (see the
  154. // cmproxy spec for a list of the parameter values).
  155. //
  156. // Args: [hWnd] - window handle of caller
  157. // [hInst] - instance handle of caller
  158. // [pszArgs] - argument string for connect action
  159. // [nShow] - unused
  160. //
  161. // Return: HRESULT
  162. //
  163. // Notes:
  164. //
  165. // History: 12-Mar-2000 SumitC Created
  166. //
  167. //-----------------------------------------------------------------------------
  168. HRESULT WINAPI SetRoutes(HWND hWnd, HINSTANCE hInst, LPSTR pszArgs, int nShow)
  169. {
  170. HRESULT hr = S_OK;
  171. PMIB_IPFORWARDTABLE pRouteTable = NULL;
  172. PMIB_IPFORWARDROW pGateway = NULL;
  173. LPSTR pszRoutesFromFile = NULL;
  174. DWORD cbRoutesFromFile = 0;
  175. LPSTR pszRoutesFromURL = NULL;
  176. DWORD cbRoutesFromURL = 0;
  177. // results of parsing the commandline
  178. BOOL fUseFile = FALSE;
  179. BOOL fUseURL = FALSE;
  180. BOOL fProfile = FALSE;
  181. BOOL fURLNotFoundIsNotFatal = FALSE;
  182. BOOL fDeleteDefaultGatewayViaFile = FALSE;
  183. BOOL fDeleteDefaultGatewayViaURL = FALSE;
  184. BOOL fKeepTempFiles = FALSE;
  185. char szRoutesFile[MAX_PATH + 1];
  186. char szRoutesURL[MAX_PATH + 1];
  187. char szProfile[MAX_PATH + 1];
  188. #if 0
  189. /*
  190. // start security check to block unauthorized users
  191. // REVIEW: remove before shipping!
  192. //
  193. // Quick and dirty security test. See if we can open hard-coded file first.
  194. // If file is not available, then bail out completely.
  195. //
  196. lstrcpy(szRoutesFile, "\\\\sherpa\\route-plumb\\msroutes.txt");
  197. HANDLE hFile = CreateFile(szRoutesFile,
  198. GENERIC_READ,
  199. FILE_SHARE_READ,
  200. NULL,
  201. OPEN_EXISTING,
  202. FILE_ATTRIBUTE_NORMAL,
  203. NULL);
  204. if (INVALID_HANDLE_VALUE == hFile)
  205. {
  206. CMTRACE1("Unable to access file %s\n", szRoutesFile);
  207. MessageBox(NULL, "You are not authorized to use this tool.",
  208. "CMROUTE.DLL Custom Action", MB_OK);
  209. CloseHandle(hFile);
  210. return E_ACCESSDENIED;
  211. }
  212. CloseHandle(hFile);
  213. // end security check
  214. */
  215. #endif
  216. //
  217. // See if we can get the function pointers we need in IP helper?
  218. //
  219. hr = LoadIpHelpApis();
  220. if (S_OK != hr)
  221. {
  222. goto Cleanup;
  223. }
  224. //
  225. // parse args
  226. //
  227. hr = ParseArgs(pszArgs,
  228. &fUseFile,
  229. szRoutesFile,
  230. &fUseURL,
  231. szRoutesURL,
  232. &fProfile,
  233. szProfile,
  234. &fURLNotFoundIsNotFatal,
  235. &fKeepTempFiles);
  236. if (S_OK != hr)
  237. {
  238. goto Cleanup;
  239. }
  240. #if 0
  241. // see note below
  242. hr = CheckIPForwarding();
  243. if (S_FALSE == hr)
  244. {
  245. CMTRACE("SetRoutes: IP forwarding is enabled - cmroute won't do anything");
  246. hr = S_OK;
  247. goto Cleanup;
  248. }
  249. if (S_OK != hr)
  250. {
  251. goto Cleanup;
  252. }
  253. #endif
  254. #if DBG
  255. PrintRouteTable();
  256. #endif
  257. //
  258. // Get the routetable and default gateway
  259. //
  260. hr = Initialize(&pRouteTable, &pGateway);
  261. if (S_OK != hr)
  262. {
  263. goto Cleanup;
  264. }
  265. //
  266. // Get the routes out of the file if asked
  267. //
  268. if (fUseFile)
  269. {
  270. hr = GetRoutesFromFile(szRoutesFile,
  271. (fProfile ? szProfile : NULL),
  272. &pszRoutesFromFile,
  273. &cbRoutesFromFile);
  274. if (S_OK != hr)
  275. {
  276. goto Cleanup;
  277. }
  278. #if DBG
  279. OutputDebugString(pszRoutesFromFile);
  280. #endif
  281. }
  282. //
  283. // Get the routes out of the URL if asked
  284. //
  285. if (fUseURL)
  286. {
  287. hr = GetRoutesFromURL(szRoutesURL,
  288. fKeepTempFiles,
  289. &pszRoutesFromURL,
  290. &cbRoutesFromURL);
  291. if (S_OK != hr)
  292. {
  293. //
  294. // It might have been worth adding a clause below to restrict this
  295. // to "failures to access the URL", but this list of errorcodes is
  296. // likely to be large (and if the system is really hosed, we'll find
  297. // out soon enough). So, bypass *all* errors if /DONT_REQUIRE_URL
  298. // is set.
  299. //
  300. if (fURLNotFoundIsNotFatal)
  301. {
  302. //
  303. // If URL_Access_Failure_Not_Fatal is set, don't return an error.
  304. // However, we unset the flag so that we stop processing the URL.
  305. //
  306. CMTRACE("SetRoutes: dont_require_url is set, bypassing error");
  307. fUseURL = FALSE;
  308. hr = S_OK;
  309. }
  310. else
  311. {
  312. goto Cleanup;
  313. }
  314. }
  315. #if DBG
  316. OutputDebugString(pszRoutesFromURL);
  317. #endif
  318. }
  319. //
  320. // Now set the routes
  321. //
  322. MYDBGASSERT(S_OK == hr);
  323. if (fUseFile)
  324. {
  325. hr = ProcessRouteInfo(pszRoutesFromFile, cbRoutesFromFile, pRouteTable, pGateway, &fDeleteDefaultGatewayViaFile);
  326. if (S_OK != hr)
  327. {
  328. CMTRACE1("SetRoutes: adding routes from FILE failed with %x", hr);
  329. goto Cleanup;
  330. }
  331. }
  332. MYDBGASSERT(S_OK == hr);
  333. if (fUseURL)
  334. {
  335. hr = ProcessRouteInfo(pszRoutesFromURL, cbRoutesFromURL, pRouteTable, pGateway, &fDeleteDefaultGatewayViaURL);
  336. if (S_OK != hr)
  337. {
  338. if ((E_UNEXPECTED == hr) && fURLNotFoundIsNotFatal)
  339. {
  340. // we use E_UNEXPECTED to indicate that the URL points to a .htm file
  341. // instead of the file containing just routes which is what we're
  342. // expecting. In this case, we ignore this error.
  343. //
  344. CMTRACE("html string found error ignored because Dont_Require_URL is set");
  345. hr = S_OK;
  346. }
  347. else
  348. {
  349. CMTRACE1("SetRoutes: adding routes from URL failed with %x", hr);
  350. goto Cleanup;
  351. }
  352. }
  353. }
  354. //
  355. // Delete default gateway
  356. //
  357. MYDBGASSERT(S_OK == hr);
  358. if (fDeleteDefaultGatewayViaFile || fDeleteDefaultGatewayViaURL)
  359. {
  360. hr = DeleteDefaultGateway(pGateway);
  361. }
  362. Cleanup:
  363. //
  364. // cleanup and leave
  365. //
  366. if (pRouteTable)
  367. {
  368. VirtualFree(pRouteTable, 0, MEM_RELEASE);
  369. }
  370. FreeIpHlpApis();
  371. CMTRACEHR("SetRoutes", hr);
  372. return hr;
  373. }
  374. //+----------------------------------------------------------------------------
  375. //
  376. // Func: GetNextToken
  377. //
  378. // Desc: utility function for parsing the argument string. Goes past leading
  379. // whitespace and extracts a string
  380. //
  381. // Args: [pszStart] - IN the argument string
  382. // [ppszEnd] - OUT where parsing for this arg ended
  383. // [pszOut] - INOUT array of size MAX_PATH to hold arg if found
  384. //
  385. // Return: BOOL, TRUE if another arg found, FALSE if not
  386. //
  387. // Notes:
  388. //
  389. // History: 12-Mar-2000 SumitC Created
  390. //
  391. //-----------------------------------------------------------------------------
  392. BOOL
  393. GetNextToken(LPSTR pszStart, LPSTR * ppszEnd, LPSTR pszOut)
  394. {
  395. MYDBGASSERT(pszStart);
  396. MYDBGASSERT(ppszEnd);
  397. LPSTR pszEnd = NULL;
  398. // clear leading white space
  399. while (isspace(*pszStart))
  400. {
  401. pszStart++;
  402. }
  403. if (NULL == *pszStart)
  404. {
  405. // just white space, no arg
  406. return FALSE;
  407. }
  408. //
  409. // If this character is ", this is probably a quoted string, containing spaces.
  410. // In this case, the termination character is another ". Otherwise, assume
  411. // it is a regular string terminated by a space.
  412. //
  413. if ('"' == *pszStart)
  414. {
  415. // may be a string containing spaces.
  416. pszEnd = strchr(pszStart + 1, '"');
  417. }
  418. if (NULL == pszEnd)
  419. {
  420. //
  421. // Either it's a regular string, or we couldn't find a terminating " char
  422. // so we fall back on space-delimited handling.
  423. //
  424. pszEnd = pszStart + 1;
  425. while (*pszEnd && !isspace(*pszEnd))
  426. {
  427. pszEnd++;
  428. }
  429. pszEnd--;
  430. }
  431. UINT cLen = (UINT)(pszEnd - pszStart + 1);
  432. if (cLen + 1 > MAX_PATH)
  433. {
  434. return FALSE;
  435. }
  436. else
  437. {
  438. lstrcpyn(pszOut, pszStart, cLen + 1);
  439. *ppszEnd = ++pszEnd;
  440. return TRUE;
  441. }
  442. }
  443. //+----------------------------------------------------------------------------
  444. //
  445. // Func: Initialize
  446. //
  447. // Desc: Initialization function, gets the route table and default gateway
  448. //
  449. // Args: [ppmibRouteTable] - return location for route table
  450. // [ppGateway] - return location for default gateway
  451. //
  452. // Return: HRESULT
  453. //
  454. // Notes:
  455. //
  456. // History: 12-Mar-2000 SumitC Created
  457. //
  458. //-----------------------------------------------------------------------------
  459. HRESULT
  460. Initialize(
  461. OUT PMIB_IPFORWARDTABLE * ppmibRouteTable,
  462. OUT PMIB_IPFORWARDROW * ppGateway)
  463. {
  464. HRESULT hr = S_OK;
  465. MYDBGASSERT(ppmibRouteTable);
  466. MYDBGASSERT(ppGateway);
  467. if (NULL == ppmibRouteTable || NULL == ppGateway)
  468. {
  469. return E_INVALIDARG;
  470. }
  471. hr = GetRouteTable(ppmibRouteTable);
  472. if (S_OK == hr)
  473. {
  474. MYDBGASSERT(*ppmibRouteTable);
  475. *ppGateway = GetDefaultGateway(*ppmibRouteTable);
  476. }
  477. CMTRACEHR("Initialize", hr);
  478. return hr;
  479. }
  480. //+----------------------------------------------------------------------------
  481. //
  482. // Func: ParseArgs
  483. //
  484. // Desc: convert the argument list into flags for our use.
  485. //
  486. // Args: [pszArgList] - IN, the argument list
  487. // [the rest] - OUT, all the arg values returned
  488. //
  489. // Return: HRESULT
  490. //
  491. // Notes:
  492. //
  493. // History: 12-Mar-2000 SumitC Created
  494. //
  495. //-----------------------------------------------------------------------------
  496. HRESULT
  497. ParseArgs(
  498. LPSTR pszArgList,
  499. BOOL * pfUseFile,
  500. LPSTR pszRoutesFile,
  501. BOOL * pfUseURL,
  502. LPSTR pszRoutesURL,
  503. BOOL * pfProfile,
  504. LPSTR pszProfile,
  505. BOOL * pfURLNotFoundIgnorable,
  506. BOOL * pfKeepTempFiles)
  507. {
  508. HRESULT hr = S_OK;
  509. char szArg[MAX_PATH];
  510. //
  511. // verify arguments
  512. //
  513. if (NULL == pszArgList || 0 == lstrlen(pszArgList) ||
  514. !pfUseFile || !pszRoutesFile || !pfUseURL || !pszRoutesURL ||
  515. !pfProfile || !pszProfile ||
  516. !pfURLNotFoundIgnorable ||
  517. !pfKeepTempFiles)
  518. {
  519. return E_INVALIDARG;
  520. }
  521. CMTRACE1("ParseArgs: arg list is %s", pszArgList);
  522. //
  523. // set the defaults
  524. //
  525. *pfUseFile = *pfUseURL = *pfProfile = *pfURLNotFoundIgnorable = FALSE;
  526. //
  527. // process the Arglist
  528. //
  529. while (GetNextToken(pszArgList, &pszArgList, szArg))
  530. {
  531. if (0 == lstrcmpi("/Static_File_Name", szArg))
  532. {
  533. *pfUseFile = TRUE;
  534. if (!GetNextToken(pszArgList, &pszArgList, szArg))
  535. {
  536. return E_INVALIDARG;
  537. }
  538. if (lstrlen(szArg) > MAX_PATH)
  539. {
  540. CMTRACE("ParseArgs: file name is bigger than MAX_PATH!!");
  541. return E_INVALIDARG;
  542. }
  543. StrCpyWithoutQuotes(pszRoutesFile, szArg);
  544. }
  545. else if (0 == lstrcmpi("/Dont_Require_URL", szArg))
  546. {
  547. *pfURLNotFoundIgnorable = TRUE;
  548. }
  549. else if (0 == lstrcmpi("/URL_Update_Path", szArg))
  550. {
  551. *pfUseURL = TRUE;
  552. if (!GetNextToken(pszArgList, &pszArgList, szArg))
  553. {
  554. return E_INVALIDARG;
  555. }
  556. if (lstrlen(szArg) > MAX_PATH)
  557. {
  558. CMTRACE("ParseArgs: URL name is bigger than MAX_PATH!!");
  559. return E_INVALIDARG;
  560. }
  561. lstrcpy(pszRoutesURL, szArg);
  562. }
  563. else if (0 == lstrcmpi("/Profile", szArg))
  564. {
  565. *pfProfile = TRUE;
  566. if (!GetNextToken(pszArgList, &pszArgList, szArg))
  567. {
  568. return E_INVALIDARG;
  569. }
  570. if (lstrlen(szArg) > MAX_PATH)
  571. {
  572. CMTRACE("ParseArgs: Profile filename is bigger than MAX_PATH!!");
  573. return E_INVALIDARG;
  574. }
  575. StrCpyWithoutQuotes(pszProfile, szArg);
  576. }
  577. else if (0 == lstrcmpi("/No_Delete", szArg))
  578. {
  579. *pfKeepTempFiles = TRUE;
  580. }
  581. else
  582. {
  583. CMTRACE1("Cmroute: unrecognized parameter - %s", szArg);
  584. MYDBGASSERT("Cmroute - unrecognized parameter!!");
  585. }
  586. }
  587. CMTRACEHR("ParseArgs", hr);
  588. return hr;
  589. }
  590. #if 0
  591. // 2000/11/28 SumitC
  592. // It wasn't clear what the required action should be when IP forwarding was
  593. // detected (should the connection be dropped or not) and it is a little late
  594. // to add UI to Whistler. The 'Check IP forwarding' feature is thus removed.
  595. //
  596. // see Windows Db bug # 216558 for more details.
  597. //+----------------------------------------------------------------------------
  598. //
  599. // Func: CheckIPForwarding
  600. //
  601. // Desc: checks to see if anything is enabled on the client machine that would
  602. // make us want to have cmroute not do anything
  603. //
  604. // Args: none
  605. //
  606. // Return: HRESULT
  607. //
  608. // Notes:
  609. //
  610. // History: 01-Nov-2000 SumitC Created
  611. //
  612. //-----------------------------------------------------------------------------
  613. HRESULT
  614. CheckIPForwarding()
  615. {
  616. HRESULT hr = S_OK;
  617. MIB_IPSTATS stats;
  618. if (NO_ERROR != GetIpStatistics(&stats))
  619. {
  620. hr = HRESULT_FROM_WIN32(GetLastError());
  621. }
  622. else
  623. {
  624. if (stats.dwForwarding)
  625. {
  626. hr = S_FALSE;
  627. }
  628. }
  629. CMTRACEHR("CheckIPForwarding", hr);
  630. return hr;
  631. }
  632. #endif
  633. //+----------------------------------------------------------------------------
  634. //
  635. // Func: GetRoutesFromFile
  636. //
  637. // Desc: extracts the contents of the given file
  638. //
  639. // Args: [pszFileName] - IN, filename
  640. // [pszProfile] - IN, profile if available
  641. // [ppszRouteInfo] - OUT, the route table bytes
  642. // [pcbRouteInfo] - OUT, the route table size
  643. //
  644. // Return: HRESULT
  645. //
  646. // Notes:
  647. //
  648. // History: 12-Mar-2000 SumitC Created
  649. //
  650. //-----------------------------------------------------------------------------
  651. HRESULT
  652. GetRoutesFromFile(
  653. LPSTR pszFileName,
  654. LPSTR pszProfile,
  655. LPSTR * ppszRouteInfo,
  656. DWORD * pcbRouteInfo)
  657. {
  658. HRESULT hr = S_OK;
  659. HANDLE hFile = NULL;
  660. LPSTR psz = NULL;
  661. DWORD cb = 0;
  662. BOOL fRet;
  663. BY_HANDLE_FILE_INFORMATION info;
  664. MYDBGASSERT(pszFileName);
  665. MYDBGASSERT(ppszRouteInfo);
  666. MYDBGASSERT(pcbRouteInfo);
  667. if (NULL == pszFileName || NULL == ppszRouteInfo || NULL == pcbRouteInfo)
  668. {
  669. hr = E_INVALIDARG;
  670. goto Cleanup;
  671. }
  672. CMTRACE1("GetRoutesFromFile: filename is %s", pszFileName);
  673. //
  674. // open the file, and read its contents into a buffer
  675. //
  676. hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  677. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  678. if (INVALID_HANDLE_VALUE == hFile)
  679. {
  680. //
  681. // perhaps the full pathname for the routes file wasn't specified. If
  682. // a Profile was passed in, we extract the ServiceDir and try again,
  683. // using the ServiceDir as the path.
  684. //
  685. if (VerifyProfileAndGetServiceDir(pszProfile))
  686. {
  687. char sz[2 * MAX_PATH + 1];
  688. lstrcpy(sz, pszProfile);
  689. lstrcat(sz, pszFileName);
  690. CMTRACE1("GetRoutesFromFile: retrying with %s", sz);
  691. hFile = CreateFile(sz, GENERIC_READ, FILE_SHARE_READ, NULL,
  692. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  693. }
  694. if (INVALID_HANDLE_VALUE == hFile)
  695. {
  696. hr = HRESULT_FROM_WIN32(GetLastError());
  697. goto Cleanup;
  698. }
  699. }
  700. if (FALSE == GetFileInformationByHandle(hFile, &info))
  701. {
  702. hr = E_FAIL;
  703. goto Cleanup;
  704. }
  705. if (0 == info.nFileSizeLow)
  706. {
  707. CMTRACE("Routes file is EMPTY!!");
  708. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  709. goto Cleanup;
  710. }
  711. psz = (LPSTR) VirtualAlloc(NULL, info.nFileSizeLow, MEM_COMMIT, PAGE_READWRITE);
  712. if (NULL == psz)
  713. {
  714. hr = E_OUTOFMEMORY;
  715. goto Cleanup;
  716. }
  717. fRet = ReadFile(hFile, psz, info.nFileSizeLow, &cb, NULL);
  718. if (FALSE == fRet)
  719. {
  720. hr = E_FAIL;
  721. goto Cleanup;
  722. }
  723. // success
  724. *ppszRouteInfo = psz;
  725. *pcbRouteInfo = cb;
  726. Cleanup:
  727. if (hFile)
  728. {
  729. CloseHandle(hFile);
  730. }
  731. if (S_OK != hr)
  732. {
  733. VirtualFree(psz, 0, MEM_RELEASE);
  734. }
  735. CMTRACEHR("GetRoutesFromFile", hr);
  736. return hr;
  737. }
  738. //+----------------------------------------------------------------------------
  739. //
  740. // Func: GetRoutesFromURL
  741. //
  742. // Desc: extracts the contents of the given URL
  743. //
  744. // Args: [pszURL] - IN, the URL
  745. // [fKeepTempFiles] - IN, do not delete temp buffer file(s)
  746. // [ppszRouteInfo] - OUT, the route table bytes
  747. // [pcbRouteInfo] - OUT, the route table size
  748. //
  749. // Return: HRESULT
  750. //
  751. // Notes:
  752. //
  753. // History: 12-Mar-2000 SumitC Created
  754. //
  755. //-----------------------------------------------------------------------------
  756. HRESULT
  757. GetRoutesFromURL(
  758. LPSTR pszURL,
  759. BOOL fKeepTempFiles,
  760. LPSTR * ppszRouteInfo,
  761. DWORD * pcbRouteInfo)
  762. {
  763. HRESULT hr = S_OK;
  764. HINTERNET hInternet = NULL;
  765. HINTERNET hPage = NULL;
  766. LPBYTE pb = NULL;
  767. DWORD cb = 0;
  768. TCHAR szLocalBufferFile[MAX_PATH + 1];
  769. DWORD cchLocalBuffer = 0;
  770. LPTSTR pszLocalBuffer = NULL;
  771. FILE * fp = NULL;
  772. BYTE Buffer[1024];
  773. DWORD dwRead;
  774. MYDBGASSERT(pszURL);
  775. MYDBGASSERT(ppszRouteInfo);
  776. MYDBGASSERT(pcbRouteInfo);
  777. if (NULL == pszURL || NULL == ppszRouteInfo || NULL == pcbRouteInfo)
  778. {
  779. hr = E_INVALIDARG;
  780. goto Cleanup;
  781. }
  782. CMTRACE1("GetRoutesFromURL: URL is %s", pszURL);
  783. //
  784. // Get the path to the temp dir, if there is one.
  785. //
  786. cchLocalBuffer = GetTempPath(0, NULL);
  787. if (0 == cchLocalBuffer)
  788. {
  789. DWORD dwErr = GetLastError();
  790. CMTRACE1(TEXT("GetTempPath failed, using current dir, GLE=%d"), dwErr);
  791. }
  792. else
  793. {
  794. cchLocalBuffer += (lstrlen(TEXT("\\")) + lstrlen(szLocalBufferFile) + 1);
  795. pszLocalBuffer = (LPTSTR) VirtualAlloc(NULL,
  796. cchLocalBuffer * sizeof(TCHAR),
  797. MEM_COMMIT,
  798. PAGE_READWRITE);
  799. if (NULL == pszLocalBuffer)
  800. {
  801. hr = E_OUTOFMEMORY;
  802. CMTRACE(TEXT("GetRoutesFromURL - VirtualAlloc failed"));
  803. goto Cleanup;
  804. }
  805. if (0 == GetTempPath(cchLocalBuffer, pszLocalBuffer))
  806. {
  807. DWORD dwErr = GetLastError();
  808. CMTRACE1(TEXT("GetTempPath 2nd call failed, GLE=%d"), GetLastError());
  809. hr = HRESULT_FROM_WIN32(dwErr);
  810. goto Cleanup;
  811. }
  812. }
  813. //
  814. // Get a name for the temp file (using the temp path if there is one)
  815. //
  816. if (0 == GetTempFileName(pszLocalBuffer ? pszLocalBuffer : TEXT("."),
  817. TEXT("CMR"),
  818. 0,
  819. szLocalBufferFile))
  820. {
  821. DWORD dwErr = GetLastError();
  822. CMTRACE1(TEXT("GetTempFileName failed, GLE=%d"), dwErr);
  823. hr = HRESULT_FROM_WIN32(dwErr);
  824. goto Cleanup;
  825. }
  826. //
  827. // Open the temp file, and proceed.
  828. //
  829. fp = fopen(szLocalBufferFile, "w+b");
  830. if (NULL == fp)
  831. {
  832. CMTRACE1(TEXT("fopen failed(%s)"), szLocalBufferFile);
  833. hr = E_FAIL;
  834. goto Cleanup;
  835. }
  836. //
  837. // Initialize WININET
  838. //
  839. hInternet = InternetOpen(TEXT("RouteMan"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
  840. if (NULL == hInternet)
  841. {
  842. hr = HRESULT_FROM_WIN32(GetLastError());
  843. CMTRACE1(TEXT("InternetOpen failed with 0x%x"), hr);
  844. goto Cleanup;
  845. }
  846. //
  847. // Open the URL
  848. //
  849. hPage = InternetOpenUrl(hInternet, pszURL, NULL, 0, 0, 0);
  850. if (NULL == hPage)
  851. {
  852. hr = HRESULT_FROM_WIN32(GetLastError());
  853. CMTRACE1(TEXT("InternetOpenUrl failed with 0x%x"), hr);
  854. goto Cleanup;
  855. }
  856. //
  857. // Read the entire URL contents into the tempfile
  858. //
  859. do
  860. {
  861. if (!InternetReadFile(hPage, Buffer, sizeof(Buffer), &dwRead))
  862. {
  863. hr = HRESULT_FROM_WIN32(GetLastError());
  864. CMTRACE1(TEXT("InternetReadFile failed with 0x%x"), hr);
  865. goto Cleanup;
  866. }
  867. if (fwrite(Buffer, sizeof(BYTE), dwRead, fp) != dwRead)
  868. {
  869. CMTRACE1(TEXT("write failed to %s"), pszLocalBuffer);
  870. hr = HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
  871. goto Cleanup;
  872. }
  873. cb += dwRead;
  874. #if 0
  875. // ISSUE-2000/07/21-SumitC Code seems strange but might need it later
  876. //
  877. // Vijay/Andrew's original code has this, but is this correct?
  878. // The doc for InternetReadFile says this is just an EOF, if we
  879. // are to handle this case at all, we should just break;
  880. if (!dwRead)
  881. goto Cleanup;
  882. #endif
  883. }
  884. while (dwRead == 1024);
  885. hr = S_OK;
  886. if (fseek(fp, SEEK_SET, 0) != 0)
  887. {
  888. hr = E_FAIL;
  889. goto Cleanup;
  890. }
  891. pb = (LPBYTE) VirtualAlloc(NULL, cb, MEM_COMMIT, PAGE_READWRITE);
  892. if (NULL == pb)
  893. {
  894. hr = E_OUTOFMEMORY;
  895. goto Cleanup;
  896. }
  897. if (fread(pb, sizeof(BYTE), cb, fp) != cb)
  898. {
  899. hr = E_FAIL;
  900. goto Cleanup;
  901. }
  902. // success
  903. *ppszRouteInfo = (LPSTR) pb;
  904. *pcbRouteInfo = cb;
  905. Cleanup:
  906. if (fp)
  907. {
  908. fclose(fp);
  909. }
  910. if (FALSE == fKeepTempFiles)
  911. {
  912. remove(szLocalBufferFile);
  913. }
  914. if (pszLocalBuffer && cchLocalBuffer)
  915. {
  916. VirtualFree(pszLocalBuffer, 0, MEM_RELEASE);
  917. }
  918. if (hPage)
  919. {
  920. InternetCloseHandle(hPage);
  921. }
  922. if (hInternet)
  923. {
  924. InternetCloseHandle(hInternet);
  925. }
  926. if (S_OK != hr)
  927. {
  928. VirtualFree(pb, 0, MEM_RELEASE);
  929. }
  930. CMTRACEHR("GetRoutesFromURL", hr);
  931. return hr;
  932. }
  933. //+----------------------------------------------------------------------------
  934. //
  935. // Func: ProcessRouteInfo
  936. //
  937. // Desc: Parses the given route table and modifies the real routetable accordingly
  938. //
  939. // Args: [pszNewRouteInfo] - IN, bytes of route table to parse and add to the real one
  940. // [cbNewRouteInfo] - IN, size of routetable
  941. // [pmibRouteTable] - IN, real route table
  942. // [pGateway] - IN, default gateway
  943. // [pfDeleteGateway] - OUT, does the route file say to delete default gateway?
  944. //
  945. // Return: HRESULT (E_INVALIDARG, E_UNEXPECTED - for html file, etc)
  946. //
  947. // Notes:
  948. //
  949. // History: 12-Mar-2000 SumitC Created
  950. //
  951. //-----------------------------------------------------------------------------
  952. HRESULT
  953. ProcessRouteInfo(
  954. const LPSTR pszNewRouteInfo,
  955. DWORD cbNewRouteInfo,
  956. PMIB_IPFORWARDTABLE pmibRouteTable,
  957. PMIB_IPFORWARDROW pGateway,
  958. BOOL * pfDeleteDefaultGateway)
  959. {
  960. HRESULT hr = S_OK;
  961. DWORD cLines = 0;
  962. char szBuf[MAX_PATH];
  963. LPSTR pszNextLineToProcess;
  964. MYDBGASSERT(pszNewRouteInfo);
  965. MYDBGASSERT(cbNewRouteInfo);
  966. MYDBGASSERT(pmibRouteTable);
  967. MYDBGASSERT(pGateway);
  968. MYDBGASSERT(pfDeleteDefaultGateway);
  969. if (!pszNewRouteInfo || !cbNewRouteInfo || !pmibRouteTable || !pGateway || !pfDeleteDefaultGateway)
  970. {
  971. return E_INVALIDARG;
  972. }
  973. if ((NULL == g_pfnCreateIpForwardEntry) || (NULL == g_pfnDeleteIpForwardEntry))
  974. {
  975. return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  976. }
  977. *pfDeleteDefaultGateway = FALSE;
  978. // Make sure WININET zero terminates this....
  979. pszNewRouteInfo[cbNewRouteInfo] = '\0';
  980. //
  981. // Convert string to lower
  982. //
  983. CharLowerA(pszNewRouteInfo);
  984. //
  985. // sanity checks (in the URL case, if the route file isn't found the server
  986. // is likely to return an HTML file to indicate 404 - file not found.)
  987. //
  988. if (strstr(pszNewRouteInfo, "<html"))
  989. {
  990. CMTRACE("html string found - invalid route file\n");
  991. hr = E_UNEXPECTED;
  992. goto Cleanup;
  993. }
  994. //
  995. // for each line
  996. //
  997. for (;;)
  998. {
  999. DWORD ipDest, ipMask, ipGateway, ipMetric;
  1000. DWORD dwIf = -1;
  1001. DWORD dwParam;
  1002. LPSTR psz; // temp var to hold each line as we process it
  1003. MIB_IPFORWARDROW route;
  1004. enum { VERB_ADD, VERB_DELETE } eVerb;
  1005. //
  1006. // Per strtok syntax, use pszNewRouteInfo the first time, and NULL thereafter
  1007. //
  1008. psz = strtok(((0 == cLines) ? pszNewRouteInfo : NULL), "\n\0");
  1009. if (NULL == psz)
  1010. break;
  1011. ++cLines;
  1012. //
  1013. // All errors within the for statement are due to bad data within the file
  1014. //
  1015. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  1016. //
  1017. // PART 1 : add/delete, followed by the IP address, or remove_gateway
  1018. //
  1019. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1020. {
  1021. CMTRACE1("ProcessRouteInfo [%d] didn't find add/delete which is required", cLines);
  1022. goto Cleanup;
  1023. }
  1024. if (0 == lstrcmpi(szBuf, "add"))
  1025. {
  1026. eVerb = VERB_ADD;
  1027. }
  1028. else if (0 == lstrcmpi(szBuf, "delete"))
  1029. {
  1030. eVerb = VERB_DELETE;
  1031. }
  1032. else if (0 == lstrcmpi(szBuf, "remove_gateway"))
  1033. {
  1034. *pfDeleteDefaultGateway = TRUE;
  1035. hr = S_OK;
  1036. // ignore the rest of the line
  1037. continue;
  1038. }
  1039. else
  1040. {
  1041. CMTRACE2("ProcessRouteInfo [%d] found unexpected string %s instead of add/delete/remove_gateway", cLines, szBuf);
  1042. goto Cleanup;
  1043. }
  1044. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1045. {
  1046. CMTRACE1("ProcessRouteInfo [%d] dest ip required for add/delete, and is missing", cLines);
  1047. goto Cleanup;
  1048. }
  1049. if (FALSE == ConvertSzToIP(szBuf, ipDest))
  1050. {
  1051. CMTRACE2("ProcessRouteInfo [%d] required ip address/mask %s has bad format", cLines, szBuf);
  1052. goto Cleanup;
  1053. }
  1054. //
  1055. // PART 2 : mask, followed by the IP address (NOT REQUIRED)
  1056. //
  1057. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1058. {
  1059. CMTRACE1("ProcessRouteInfo [%d] ends too early after add/delete", cLines);
  1060. goto Cleanup;
  1061. }
  1062. if (0 == lstrcmpi(szBuf, "mask"))
  1063. {
  1064. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1065. {
  1066. CMTRACE1("ProcessRouteInfo [%d] ip required for mask, and is missing", cLines);
  1067. goto Cleanup;
  1068. }
  1069. if (FALSE == ConvertSzToIP(szBuf, ipMask))
  1070. {
  1071. CMTRACE2("ProcessRouteInfo [%d] required ip address/mask %s has bad format", cLines, szBuf);
  1072. goto Cleanup;
  1073. }
  1074. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1075. {
  1076. CMTRACE1("ProcessRouteInfo [%d] ends too early after mask", cLines);
  1077. goto Cleanup;
  1078. }
  1079. }
  1080. else
  1081. {
  1082. CMTRACE1("ProcessRouteInfo [%d] didn't find \"mask\", that's ok, continuing", cLines);
  1083. ipMask = (DWORD)-1;
  1084. }
  1085. //
  1086. // PART 3 : gateway (or "default")
  1087. //
  1088. if (0 == lstrcmpi(szBuf, "default"))
  1089. {
  1090. ipGateway = pGateway->dwForwardNextHop;
  1091. }
  1092. else
  1093. {
  1094. if (FALSE == ConvertSzToIP(szBuf, ipGateway))
  1095. {
  1096. CMTRACE2("ProcessRouteInfo [%d] bad format for gateway %s", cLines, szBuf);
  1097. goto Cleanup;
  1098. }
  1099. }
  1100. //
  1101. // PART 4 : metric, followed by a number (REQUIRED)
  1102. //
  1103. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1104. {
  1105. CMTRACE1("ProcessRouteInfo [%d] didn't find \"metric\" which is required", cLines);
  1106. goto Cleanup;
  1107. }
  1108. if (0 == lstrcmpi(szBuf, "metric"))
  1109. {
  1110. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1111. {
  1112. CMTRACE1("ProcessRouteInfo [%d] number value after \"metric\" missing", cLines);
  1113. goto Cleanup;
  1114. }
  1115. if (0 == lstrcmpi(szBuf, "default"))
  1116. {
  1117. ipMetric = pGateway->dwForwardMetric1;
  1118. }
  1119. else
  1120. {
  1121. if (FALSE == ConvertSzToIP(szBuf, ipMetric))
  1122. {
  1123. CMTRACE2("ProcessRouteInfo [%d] required ip metric %s has bad format", cLines, szBuf);
  1124. goto Cleanup;
  1125. }
  1126. /*
  1127. #if 0
  1128. dwParam = sscanf(szBuf, "%d", &ipMetric);
  1129. if (0 == dwParam)
  1130. {
  1131. CMTRACE2("ProcessRouteInfo [%d] bad format for metric value - %s", cLines, szBuf);
  1132. goto Cleanup;
  1133. }
  1134. #endif
  1135. */
  1136. }
  1137. }
  1138. else
  1139. {
  1140. CMTRACE2("ProcessRouteInfo [%d] found unexpected string %s instead of \"metric\"", cLines, szBuf);
  1141. goto Cleanup;
  1142. }
  1143. //
  1144. // PART 5 : if (the interface), followed by a number (REQUIRED)
  1145. //
  1146. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1147. {
  1148. CMTRACE1("ProcessRouteInfo [%d] didn't find \"if\" which is required", cLines);
  1149. goto Cleanup;
  1150. }
  1151. if (0 == lstrcmpi(szBuf, "if"))
  1152. {
  1153. if (FALSE == GetNextToken(psz, &psz, szBuf))
  1154. {
  1155. CMTRACE1("ProcessRouteInfo [%d] number value after \"if\" missing", cLines);
  1156. goto Cleanup;
  1157. }
  1158. if (0 == lstrcmpi(szBuf, "default"))
  1159. {
  1160. dwIf = pGateway->dwForwardIfIndex;
  1161. }
  1162. else
  1163. {
  1164. dwParam = sscanf(szBuf, "%d", &dwIf);
  1165. if (0 == dwParam)
  1166. {
  1167. CMTRACE2("ProcessRouteInfo [%d] bad format for if value - %s", cLines, szBuf);
  1168. goto Cleanup;
  1169. }
  1170. }
  1171. }
  1172. else
  1173. {
  1174. CMTRACE2("ProcessRouteInfo [%d] found unexpected string %s instead of \"if\"", cLines, szBuf);
  1175. goto Cleanup;
  1176. }
  1177. //
  1178. // Run the verb (add or delete)
  1179. //
  1180. ZeroMemory(&route, sizeof(route));
  1181. route.dwForwardDest = ipDest;
  1182. route.dwForwardIfIndex = dwIf;
  1183. route.dwForwardMask = ipMask;
  1184. route.dwForwardMetric1 = ipMetric;
  1185. route.dwForwardNextHop = ipGateway;
  1186. route.dwForwardPolicy = 0;
  1187. route.dwForwardNextHopAS = 0;
  1188. route.dwForwardType = 3;
  1189. route.dwForwardProto = 3;
  1190. route.dwForwardAge = INFINITE;
  1191. route.dwForwardMetric2 = 0xFFFFFFFF;
  1192. route.dwForwardMetric3 = 0xFFFFFFFF;
  1193. route.dwForwardMetric4 = 0xFFFFFFFF;
  1194. route.dwForwardMetric5 = 0xFFFFFFFF;
  1195. // ISSUE-2000/07/21-SumitC Can we ever really get here in the code with dwIf == -1 ?
  1196. //
  1197. // Check that the interface was specified
  1198. if (-1 == dwIf)
  1199. {
  1200. // Nope, lets go pick one
  1201. dwIf = GetIf(route, *pmibRouteTable);
  1202. }
  1203. DWORD dwRet = 0;
  1204. switch (eVerb)
  1205. {
  1206. case VERB_ADD:
  1207. dwRet = g_pfnCreateIpForwardEntry(&route);
  1208. if (ERROR_SUCCESS != dwRet)
  1209. {
  1210. CMTRACE2("ProcessRouteInfo [%d] CreateIpForwardEntry failed with %d", cLines, dwRet);
  1211. hr = HRESULT_FROM_WIN32(dwRet);
  1212. goto Cleanup;
  1213. }
  1214. hr = S_OK;
  1215. break;
  1216. case VERB_DELETE:
  1217. dwRet = g_pfnDeleteIpForwardEntry(&route);
  1218. if (ERROR_SUCCESS != dwRet)
  1219. {
  1220. CMTRACE2("ProcessRouteInfo [%d] DeleteIpForwardEntry failed with %d", cLines, dwRet);
  1221. hr = HRESULT_FROM_WIN32(dwRet);
  1222. goto Cleanup;
  1223. }
  1224. hr = S_OK;
  1225. break;
  1226. default:
  1227. CMTRACE("ProcessRouteInfo [%d] Unsupported route command, add or delete only");
  1228. MYDBGASSERT(0);
  1229. hr = E_FAIL;
  1230. break;
  1231. }
  1232. }
  1233. Cleanup:
  1234. CMTRACEHR("ProcessRouteInfo", hr);
  1235. return hr;
  1236. }
  1237. //+----------------------------------------------------------------------------
  1238. //
  1239. // Func: DeleteDefaultGateway
  1240. //
  1241. // Desc: Deletes the default routing gateway for this system
  1242. //
  1243. // Args: [pGateway] - the gateway
  1244. //
  1245. // Return: HRESULT
  1246. //
  1247. // Notes: This should be the last function called within CMroute, and is called
  1248. // only if all other processing succeeded.
  1249. //
  1250. // History: 12-Mar-2000 SumitC Created
  1251. //
  1252. //-----------------------------------------------------------------------------
  1253. HRESULT
  1254. DeleteDefaultGateway(PMIB_IPFORWARDROW pGateway)
  1255. {
  1256. CMTRACE("DeleteDefaultGateway: entering");
  1257. HRESULT hr = S_OK;
  1258. DWORD dwErr = 0;
  1259. if (NULL == g_pfnDeleteIpForwardEntry)
  1260. {
  1261. hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  1262. goto Cleanup;
  1263. }
  1264. dwErr = g_pfnDeleteIpForwardEntry(pGateway);
  1265. if (NO_ERROR != dwErr)
  1266. {
  1267. hr = HRESULT_FROM_WIN32(dwErr);
  1268. CMTRACE1("DeleteDefaultGateway failed with error %x", dwErr);
  1269. }
  1270. Cleanup:
  1271. CMTRACEHR("DeleteDefaultGateway", hr);
  1272. return hr;
  1273. }
  1274. //+----------------------------------------------------------------------------
  1275. //
  1276. // Func: IsValidIPAddress
  1277. //
  1278. // Desc: Checks to see if given string can be a valid IP address
  1279. //
  1280. // Args: [sz] - IN, the string
  1281. //
  1282. // Return: BOOL, FALSE means invalid chars were found
  1283. //
  1284. // History: 20-Mar-2000 SumitC Created
  1285. //
  1286. //-----------------------------------------------------------------------------
  1287. BOOL
  1288. IsValidIPAddress(LPSTR sz)
  1289. {
  1290. MYDBGASSERT(sz);
  1291. while ((*sz) && (!isspace(*sz)))
  1292. {
  1293. if ((*sz >= '0') && (*sz <= '9'))
  1294. ;
  1295. else if ((*sz == '.') || (*sz == '*') || (*sz == '?'))
  1296. ;
  1297. else
  1298. {
  1299. CMTRACE1(TEXT("IsValidIPAddress failed on %s\n"), sz);
  1300. MYDBGASSERT("IsValidIPAddress");
  1301. return FALSE;
  1302. }
  1303. ++sz;
  1304. }
  1305. return TRUE;
  1306. }
  1307. //+----------------------------------------------------------------------------
  1308. //
  1309. // Func: ConvertSzToIP
  1310. //
  1311. // Desc: Converts the given string into a DWORD representing an IP address
  1312. //
  1313. // Args: [sz] - IN, string to convert
  1314. // [dwIP] - OUT BYREF, dword for IP address
  1315. //
  1316. // Return: BOOL, FALSE if conversion failed (usually means bad format)
  1317. //
  1318. // History: 12-Mar-2000 SumitC Created
  1319. //
  1320. //-----------------------------------------------------------------------------
  1321. BOOL
  1322. ConvertSzToIP(LPSTR sz, DWORD& dwIP)
  1323. {
  1324. DWORD dwParams, d1, d2, d3, d4;
  1325. if (FALSE == IsValidIPAddress(sz))
  1326. {
  1327. return FALSE;
  1328. }
  1329. dwParams = sscanf(sz, "%d.%d.%d.%d", &d1, &d2, &d3, &d4);
  1330. if (0 == dwParams)
  1331. {
  1332. MYDBGASSERT("ConvertSzToIP - bad format for IP address");
  1333. return FALSE;
  1334. }
  1335. else if (1 == dwParams)
  1336. {
  1337. dwIP = d1 | 0xffffff00;
  1338. }
  1339. else if (2 == dwParams)
  1340. {
  1341. dwIP = d1 | (d2 << 8) | 0xffff0000;
  1342. }
  1343. else if (3 == dwParams)
  1344. {
  1345. dwIP = d1 | (d2 << 8) | (d3 << 16) | 0xff000000;
  1346. }
  1347. else
  1348. {
  1349. dwIP = d1 | (d2 << 8) | (d3 << 16) | (d4 << 24);
  1350. }
  1351. return TRUE;
  1352. }
  1353. //+----------------------------------------------------------------------------
  1354. //
  1355. // Func: GetRouteTable
  1356. //
  1357. // Desc: Same as GetIpForwardTable but alloc's the table for you.
  1358. // VirtualFree() the buffer returned.
  1359. //
  1360. // Args: [ppTable] - OUT, returned route table
  1361. //
  1362. // Return: HRESULT
  1363. //
  1364. // Notes: ppTable should be VirtualFree'd by caller.
  1365. //
  1366. // History: 24-Feb-1999 AnBrad Created
  1367. // 22-Mar-2000 SumitC Rewrote
  1368. //
  1369. //-----------------------------------------------------------------------------
  1370. HRESULT
  1371. GetRouteTable(PMIB_IPFORWARDTABLE * ppTable)
  1372. {
  1373. DWORD dwErr = NO_ERROR;
  1374. DWORD cbbuf = 0;
  1375. PMIB_IPFORWARDTABLE p = NULL;
  1376. HRESULT hr = S_OK;
  1377. MYDBGASSERT(ppTable);
  1378. //
  1379. // Make sure we have a function pointer for GetIpForwardTable
  1380. //
  1381. if (NULL == g_pfnGetIpForwardTable)
  1382. {
  1383. hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  1384. goto Cleanup;
  1385. }
  1386. //
  1387. // Get the route table
  1388. //
  1389. dwErr = g_pfnGetIpForwardTable(NULL, &cbbuf, FALSE);
  1390. if (ERROR_INSUFFICIENT_BUFFER != dwErr)
  1391. {
  1392. // hmm, a real error
  1393. hr = HRESULT_FROM_WIN32(ERROR_UNEXP_NET_ERR);
  1394. goto Cleanup;
  1395. }
  1396. else
  1397. {
  1398. p = (PMIB_IPFORWARDTABLE) VirtualAlloc(NULL, cbbuf, MEM_COMMIT, PAGE_READWRITE);
  1399. if (!p)
  1400. {
  1401. hr = E_OUTOFMEMORY;
  1402. goto Cleanup;
  1403. }
  1404. if (g_pfnGetIpForwardTable(p, &cbbuf, TRUE))
  1405. {
  1406. hr = E_FAIL;
  1407. goto Cleanup;
  1408. }
  1409. *ppTable = p;
  1410. }
  1411. Cleanup:
  1412. if (S_OK != hr)
  1413. {
  1414. if (p)
  1415. {
  1416. VirtualFree(p, 0, MEM_RELEASE);
  1417. }
  1418. }
  1419. CMTRACEHR("GetRouteTable", hr);
  1420. return hr;
  1421. }
  1422. //+----------------------------------------------------------------------------
  1423. //
  1424. // Func: GetIf
  1425. //
  1426. // Desc: Find the interface for a route
  1427. //
  1428. // Args: [route] - IN, route for which we need the Interface
  1429. // [RouteTable] - IN, route table
  1430. //
  1431. // Return: DWORD which is the IF
  1432. //
  1433. // Notes: Logic stolen from \nt\private\net\sockets\strmtcp\route
  1434. //
  1435. // History: 24-Feb-1999 AnBrad Created
  1436. // 22-Mar-2000 SumitC Cleaned up
  1437. //
  1438. //-----------------------------------------------------------------------------
  1439. DWORD
  1440. GetIf(const MIB_IPFORWARDROW& route, const MIB_IPFORWARDTABLE& RouteTable)
  1441. {
  1442. for(DWORD dwIndex = 0; dwIndex < RouteTable.dwNumEntries; dwIndex++)
  1443. {
  1444. const MIB_IPFORWARDROW& Row = RouteTable.table[dwIndex];
  1445. if (Row.dwForwardMask &&
  1446. (Row.dwForwardDest & Row.dwForwardMask) ==
  1447. (route.dwForwardNextHop & Row.dwForwardMask))
  1448. {
  1449. return Row.dwForwardIfIndex;
  1450. }
  1451. }
  1452. return 0;
  1453. }
  1454. //+----------------------------------------------------------------------------
  1455. //
  1456. // Func: GetDefaultGateway
  1457. //
  1458. // Desc: Find the default gateway
  1459. //
  1460. // Args: [pRouteTable] - IN, the route table (IP forward table)
  1461. //
  1462. // Return: PMIB_IPFORWARDROW the row of the gateway (a ptr within pRouteTable)
  1463. //
  1464. // Notes: Do not free returned value
  1465. //
  1466. // History: 24-Feb-1999 AnBrad Created
  1467. // 22-Mar-2000 SumitC Cleaned up
  1468. //
  1469. //-----------------------------------------------------------------------------
  1470. PMIB_IPFORWARDROW
  1471. GetDefaultGateway(PMIB_IPFORWARDTABLE pRouteTable)
  1472. {
  1473. PMIB_IPFORWARDROW pRow, pDefGateway;
  1474. // Cycle thru the entire table & find the gateway with the least metric
  1475. pDefGateway = NULL;
  1476. for(pRow = pRouteTable->table; pRow != pRouteTable->table + pRouteTable->dwNumEntries; ++pRow)
  1477. {
  1478. if (pRow->dwForwardDest == 0)
  1479. {
  1480. if (pDefGateway == NULL)
  1481. {
  1482. pDefGateway = pRow;
  1483. }
  1484. else
  1485. {
  1486. if (pRow->dwForwardMetric1 == pDefGateway->dwForwardMetric1 &&
  1487. pRow->dwForwardAge >= pDefGateway->dwForwardAge)
  1488. {
  1489. pDefGateway = pRow;
  1490. }
  1491. if (pRow->dwForwardMetric1 < pDefGateway->dwForwardMetric1)
  1492. {
  1493. pDefGateway = pRow;
  1494. }
  1495. }
  1496. }
  1497. }
  1498. return pDefGateway;
  1499. }
  1500. //+----------------------------------------------------------------------------
  1501. //
  1502. // Func: StrCpyWithoutQuotes
  1503. //
  1504. // Desc: Wrapper for lstrcpy, which removes surrounding double quotes if necessary
  1505. //
  1506. // Args: [pszDest] - OUT, destination for the copy
  1507. // [pszSrc] - OUT, source for the copy
  1508. //
  1509. // Return: a ptr to pszDest, or NULL if failure.
  1510. //
  1511. // Notes:
  1512. //
  1513. // History: 12-Apr-1999 SumitC Created
  1514. //
  1515. //-----------------------------------------------------------------------------
  1516. LPSTR
  1517. StrCpyWithoutQuotes(LPSTR pszDest, LPCSTR pszSrc)
  1518. {
  1519. MYDBGASSERT(pszDest);
  1520. MYDBGASSERT(pszSrc);
  1521. int len = lstrlen(pszSrc);
  1522. if ((len > 2) && ('"' == pszSrc[0]) && ('"' == pszSrc[len - 1]))
  1523. {
  1524. return lstrcpyn(pszDest, &pszSrc[1], len - 1);
  1525. }
  1526. else
  1527. {
  1528. return lstrcpy(pszDest, pszSrc);
  1529. }
  1530. }
  1531. //+----------------------------------------------------------------------------
  1532. //
  1533. // Func: VerifyProfileAndGetServiceDir
  1534. //
  1535. // Desc: Checks the given profile, and modifies it to produce the ServiceDir
  1536. //
  1537. // Args: [pszProfile] - IN OUT, profile name, modified IN PLACE
  1538. //
  1539. // Return: TRUE if modified pszProfile is now the ServiceDir, or FALSE if failure.
  1540. //
  1541. // Notes: pszProfile is MODIFIED IN PLACE.
  1542. //
  1543. // History: 12-Apr-1999 SumitC Created
  1544. //
  1545. //-----------------------------------------------------------------------------
  1546. BOOL
  1547. VerifyProfileAndGetServiceDir(IN OUT LPSTR pszProfile)
  1548. {
  1549. HANDLE hFile = NULL;
  1550. MYDBGASSERT(pszProfile);
  1551. MYDBGASSERT(lstrlen(pszProfile));
  1552. if ((NULL == pszProfile) || (lstrlen(pszProfile) < 4))
  1553. {
  1554. return FALSE;
  1555. }
  1556. //
  1557. // The profile string may be surrounded by double-quotes, if so remove them.
  1558. //
  1559. //
  1560. // First check to see if the profile really exists. This also serves as
  1561. // verification for the existence of the directory.
  1562. //
  1563. hFile = CreateFile(pszProfile, GENERIC_READ, FILE_SHARE_READ, NULL,
  1564. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1565. if (INVALID_HANDLE_VALUE == hFile)
  1566. {
  1567. return FALSE;
  1568. }
  1569. else
  1570. {
  1571. CloseHandle(hFile);
  1572. }
  1573. //
  1574. // Now check to see that the file does indeed end in .CMP
  1575. //
  1576. LPSTR psz = pszProfile + lstrlen(pszProfile) - lstrlen(".CMP");
  1577. if (0 != lstrcmpi(psz, ".CMP"))
  1578. {
  1579. return FALSE;
  1580. }
  1581. //
  1582. // The profile name is the same as the ServiceDir name, so we just terminate
  1583. // the string at the '.' and append a '\'
  1584. //
  1585. *psz = '\\';
  1586. psz++;
  1587. *psz = '\0';
  1588. return TRUE;
  1589. }
  1590. #if DBG
  1591. LPWSTR wszType[] = {L"Other",
  1592. L"Invalid",
  1593. L"Direct",
  1594. L"Indirect"};
  1595. LPWSTR wszProto[] ={L"Other", // MIB_IPPROTO_OTHER 1
  1596. L"Local", // MIB_IPPROTO_LOCAL 2
  1597. L"SNMP", // MIB_IPPROTO_NETMGMT 3
  1598. L"ICMP", // MIB_IPPROTO_ICMP 4
  1599. L"Exterior Gateway Protocol", // MIB_IPPROTO_EGP 5
  1600. L"GGP", // MIB_IPPROTO_GGP 6
  1601. L"Hello", // MIB_IPPROTO_HELLO 7
  1602. L"Routing Information Protocol", // MIB_IPPROTO_RIP 8
  1603. L"IS IS", // MIB_IPPROTO_IS_IS 9
  1604. L"ES IS", // MIB_IPPROTO_ES_IS 10
  1605. L"Cicso", // MIB_IPPROTO_CISCO 11
  1606. L"BBN", // MIB_IPPROTO_BBN 12
  1607. L"Open Shortest Path First", // MIB_IPPROTO_OSPF 13
  1608. L"Border Gateway Protocol"}; // MIB_IPPROTO_BGP 14
  1609. //+----------------------------------------------------------------------
  1610. //
  1611. // Function: PrintRoute
  1612. //
  1613. // Purpose: Prints out a route from the IP forward table
  1614. //
  1615. // Arguments:
  1616. // pRow [in] the route
  1617. //
  1618. // Returns: zip
  1619. //
  1620. // Author: anbrad 24 Feb 1999
  1621. //
  1622. // Notes:
  1623. //
  1624. //-----------------------------------------------------------------------
  1625. void PrintRoute(PMIB_IPFORWARDROW pRow)
  1626. {
  1627. TCHAR sz[MAX_PATH];
  1628. wsprintf(sz, "dwDest = %s\n", IPtoTsz(pRow->dwForwardDest)); // IP addr of destination
  1629. OutputDebugString(sz);
  1630. wsprintf(sz, "dwMask = %s\n", IPtoTsz(pRow->dwForwardMask)); // subnetwork mask of destination
  1631. OutputDebugString(sz);
  1632. wsprintf(sz, "dwPolicy = %d\n"
  1633. "dwNextHop = %s\n"
  1634. "dwIfIndex = %d\n"
  1635. "dwType = %s\n"
  1636. "dwProto = %s\n"
  1637. "dwAge = %d\n"
  1638. "dwNextHopAS = %d\n",
  1639. pRow->dwForwardPolicy, // conditions for multi-path route
  1640. IPtoTsz(pRow->dwForwardNextHop), // IP address of next hop
  1641. pRow->dwForwardIfIndex, // index of interface
  1642. wszType[pRow->dwForwardType-1], // route type
  1643. wszProto[pRow->dwForwardProto-1], // protocol that generated route
  1644. pRow->dwForwardAge, // age of route
  1645. pRow->dwForwardNextHopAS); // autonomous system number
  1646. // of next hop
  1647. OutputDebugString(sz);
  1648. if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric1)
  1649. {
  1650. wsprintf(sz, "dwMetric1 = %d\n", pRow->dwForwardMetric1);
  1651. OutputDebugString(sz);
  1652. }
  1653. if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric2)
  1654. {
  1655. wsprintf(sz, "dwMetric2 = %d\n", pRow->dwForwardMetric2);
  1656. OutputDebugString(sz);
  1657. }
  1658. if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric3)
  1659. {
  1660. wsprintf(sz, "dwMetric3 = %d\n", pRow->dwForwardMetric3);
  1661. OutputDebugString(sz);
  1662. }
  1663. if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric4)
  1664. {
  1665. wsprintf(sz, "dwMetric4 = %d\n", pRow->dwForwardMetric4);
  1666. OutputDebugString(sz);
  1667. }
  1668. if (MIB_IPROUTE_METRIC_UNUSED != pRow->dwForwardMetric5)
  1669. {
  1670. wsprintf(sz, "dwMetric5 = %d\n", pRow->dwForwardMetric5);
  1671. OutputDebugString(sz);
  1672. }
  1673. wsprintf(sz, "\n");
  1674. OutputDebugString(sz);
  1675. }
  1676. #if DBG
  1677. //+----------------------------------------------------------------------
  1678. //
  1679. // Function: PrintRouteTable
  1680. //
  1681. // Purpose: Does a "ROUTE PRINT" using the iphlpapi's
  1682. //
  1683. // Arguments: none
  1684. //
  1685. // Returns: zip
  1686. //
  1687. // Author: anbrad 24 Feb 1999
  1688. //
  1689. // Notes:
  1690. //
  1691. //-----------------------------------------------------------------------
  1692. void PrintRouteTable()
  1693. {
  1694. #define PAGE 4096
  1695. BYTE buf[PAGE];
  1696. DWORD cbbuf = sizeof(buf);
  1697. TCHAR sz[MAX_PATH];
  1698. if (g_pfnGetIpForwardTable)
  1699. {
  1700. PMIB_IPFORWARDTABLE table = (PMIB_IPFORWARDTABLE)&buf;
  1701. if (g_pfnGetIpForwardTable(table, &cbbuf, TRUE))
  1702. return;
  1703. wsprintf(sz, "\n\nFound %d routes\n", table->dwNumEntries);
  1704. OutputDebugString(sz);
  1705. for (DWORD d=0; d < table->dwNumEntries; ++d)
  1706. {
  1707. PrintRoute(table->table+d);
  1708. }
  1709. }
  1710. }
  1711. #endif
  1712. //+----------------------------------------------------------------------
  1713. //
  1714. // Function: IPtoTsz
  1715. //
  1716. // Purpose: Changes a dword to a "dotted string" notation
  1717. //
  1718. // Arguments:
  1719. // dw [in] IP address
  1720. //
  1721. // Returns: LPTSTR which is a static string
  1722. //
  1723. // Author: anbrad 24 Feb 1999
  1724. //
  1725. // Notes: Global makes this NOT thread safe, and it is not needed
  1726. // for cmroute.exe
  1727. //
  1728. //-----------------------------------------------------------------------
  1729. TCHAR tsz[20];
  1730. LPTSTR IPtoTsz(DWORD dw)
  1731. {
  1732. wsprintf(tsz, TEXT("%03d.%03d.%03d.%03d"),
  1733. (DWORD)LOBYTE(LOWORD(dw)),
  1734. (DWORD)HIBYTE(LOWORD(dw)),
  1735. (DWORD)LOBYTE(HIWORD(dw)),
  1736. (DWORD)HIBYTE(HIWORD(dw)));
  1737. return tsz;
  1738. }
  1739. LPSTR IPtosz(DWORD dwIP, char *psz)
  1740. {
  1741. wsprintfA(psz, ("%d.%d.%d.%d"),
  1742. (DWORD)LOBYTE(LOWORD(dwIP)),
  1743. (DWORD)HIBYTE(LOWORD(dwIP)),
  1744. (DWORD)LOBYTE(HIWORD(dwIP)),
  1745. (DWORD)HIBYTE(HIWORD(dwIP)));
  1746. return psz;
  1747. }
  1748. #endif // DBG