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.

701 lines
16 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // route.c
  8. //
  9. // Abstract:
  10. //
  11. // Queries into network drivers
  12. //
  13. // Author:
  14. //
  15. // Anilth - 4-20-1998
  16. //
  17. // Environment:
  18. //
  19. // User mode only.
  20. // Contains NT-specific code.
  21. //
  22. // Revision History:
  23. //
  24. //--
  25. #include "precomp.h"
  26. //
  27. // Rajkumar - Two Functions from iphlpapi.dll
  28. //
  29. DWORD
  30. WINAPI
  31. GetIpAddrTable(
  32. OUT PMIB_IPADDRTABLE pIpAddrTable,
  33. IN OUT PULONG pdwSize,
  34. IN BOOL bOrder
  35. );
  36. DWORD
  37. InternalGetIpForwardTable(
  38. OUT MIB_IPFORWARDTABLE **ppIpForwardTable,
  39. IN HANDLE hHeap,
  40. IN DWORD dwAllocFlags
  41. );
  42. //--------------------------------------------------------
  43. //functions defined in this file
  44. void MapInterface(char *IPAddr, ULONG IfIndex);
  45. BOOLEAN ImprovedInetAddr(char *AddressString, ULONG *AddressValue);
  46. HRESULT
  47. PrintRoute(
  48. NETDIAG_RESULT *pResults,
  49. char *Dest,
  50. ULONG DestVal,
  51. char *Gate,
  52. ULONG GateVal,
  53. BOOLEAN Persistent,
  54. const char * DestPat
  55. );
  56. LPCTSTR
  57. PrintRouteEntry(
  58. ULONG Dest,
  59. ULONG Mask,
  60. ULONG Gate,
  61. ULONG Interface,
  62. ULONG Metric1
  63. );
  64. HRESULT
  65. PrintPersistentRoutes(
  66. NETDIAG_RESULT *pResults,
  67. char* Dest,
  68. ULONG DestVal,
  69. char* Gate,
  70. ULONG GateVal
  71. );
  72. BOOL
  73. RouteTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
  74. /*++
  75. Routine Description:
  76. Enumerate the static and persistent entries in the routing table
  77. Arguments:
  78. None.
  79. Return Value:
  80. TRUE
  81. Author:
  82. Rajkumar 06/27/98
  83. --*/
  84. {
  85. HRESULT hr = S_OK;
  86. //$REVIEW only perform the test when is really verbose
  87. if (!pParams->fReallyVerbose)
  88. return hr;
  89. PrintStatusMessage( pParams, 4, IDS_ROUTE_STATUS_MSG );
  90. //
  91. // Print all static entries in the ip forward table
  92. //
  93. hr = PrintRoute(pResults,
  94. "*",
  95. WILD_CARD,
  96. "*",
  97. WILD_CARD,
  98. TRUE,
  99. "*"
  100. );
  101. //
  102. // Print all the persistent route entries
  103. //
  104. if( S_OK == hr )
  105. hr = PrintPersistentRoutes(pResults,
  106. "*",
  107. WILD_CARD,
  108. "*",
  109. WILD_CARD
  110. );
  111. pResults->Route.hrTestResult = hr;
  112. return hr;
  113. }
  114. HRESULT
  115. PrintRoute(
  116. NETDIAG_RESULT *pResults,
  117. char *Dest,
  118. ULONG DestVal,
  119. char *Gate,
  120. ULONG GateVal,
  121. BOOLEAN Persistent,
  122. const char * DestPat
  123. )
  124. /*++
  125. Routine Description:
  126. This routine prints all the static entries in then IP forward table.
  127. The entry in the routing table is declared static if the type of the
  128. entry is MIB_IPPROTO_LOCAL.
  129. Arguments:
  130. char *Dest: pointer to destination IP address string. This
  131. is NULL if no value was provided/no filtering desired.
  132. ULONG DestVal: value of destination IP address to filter route
  133. table with. If Dest is NULL, this is ignored.
  134. char *Gate: pointer to gateway IP address string. This is NULL
  135. if no value was provided/no filtering desired.
  136. ULONG GateVal: value of gateway IP address to filter route
  137. table with. If Gate is NULL, this is ignored.
  138. BOOL Persistent: set if persistent routes are to be printed.
  139. Returns: ULONG
  140. Can also be found in nt\private\net\sockets\tcpcmd\route\route.c
  141. --*/
  142. {
  143. int printcount = 0;
  144. int dwResult, j, k, err, alen;
  145. DWORD i;
  146. PMIB_IPFORWARDTABLE prifRouteTable = NULL;
  147. PMIB_IFTABLE pIfTable = NULL;
  148. // ====================================================================
  149. // Get Route Table.
  150. pResults->Route.dwNumRoutes = 0;
  151. InitializeListHead(&pResults->Route.lmsgRoute);
  152. dwResult = InternalGetIpForwardTable(&prifRouteTable,
  153. GetProcessHeap(), HEAP_NO_SERIALIZE );
  154. if(dwResult || !prifRouteTable){
  155. DEBUG_PRINT(("GetIpForwardTable/2: err=%d, dwResult=%d\n",
  156. GetLastError(), dwResult ));
  157. return S_FALSE;
  158. }
  159. if( ! prifRouteTable->dwNumEntries )
  160. {
  161. return S_OK;
  162. }
  163. for(i = 0; i < prifRouteTable->dwNumEntries; i++)
  164. {
  165. PMIB_IPFORWARDROW pfr = &prifRouteTable->table[i];
  166. // Only print this entry if the destination matches the parameter
  167. if( ( Dest != NULL )
  168. && ( DestVal != WILD_CARD )
  169. && ( pfr->dwForwardDest != DestVal )
  170. && ( DestPat == NULL )
  171. )
  172. continue;
  173. // Only print this entry if the Gateway matches the parameter
  174. if( ( Gate != NULL )
  175. && ( GateVal != WILD_CARD )
  176. && ( pfr->dwForwardNextHop != GateVal )
  177. )
  178. continue;
  179. if( DestPat )
  180. {
  181. char DestStr[32];
  182. NetpIpAddressToStr( pfr->dwForwardDest, DestStr );
  183. if( ! match( DestPat, DestStr ) )
  184. {
  185. TRACE_PRINT(("PrintRoute: skipping %s !~ %s\n",
  186. DestPat, DestStr ));
  187. continue;
  188. }
  189. }
  190. // Either we have a match on Dest/Gateway or they are
  191. // wildcard/don't care.
  192. // Display the header first time.
  193. // We are going to display only static routes
  194. if ( printcount++ < 1 )
  195. //IDS_ROUTE_14203 "Network Destination Netmask Gateway Interface Metric\n"
  196. AddMessageToListId( &pResults->Route.lmsgRoute, Nd_ReallyVerbose, IDS_ROUTE_14203);
  197. //IDS_ROUTE_14204 "%s\n"
  198. AddMessageToList( &pResults->Route.lmsgRoute, Nd_ReallyVerbose,
  199. IDS_ROUTE_14204,
  200. PrintRouteEntry( pfr->dwForwardDest,
  201. pfr->dwForwardMask,
  202. pfr->dwForwardNextHop,
  203. pfr->dwForwardIfIndex,
  204. pfr->dwForwardMetric1)
  205. );
  206. }
  207. pResults->Route.dwNumRoutes = printcount;
  208. HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, pIfTable );
  209. HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, prifRouteTable);
  210. return ( NO_ERROR );
  211. }
  212. LPCTSTR
  213. PrintRouteEntry(
  214. ULONG Dest,
  215. ULONG Mask,
  216. ULONG Gate,
  217. ULONG Interface,
  218. ULONG Metric1
  219. )
  220. /*++
  221. Description:
  222. Formats and displays a single route entry.
  223. Arguments:
  224. Dest: The destination address.
  225. Mask: The destination netmask.
  226. Gate: The first hop gateway address.
  227. Interface: The interface address for the gateway net.
  228. Metric1: The primary route metric.
  229. Author:
  230. 07/01/98 Rajkumar
  231. --*/
  232. {
  233. static TCHAR s_szBuffer[512];
  234. TCHAR szFormat[128];
  235. char DestStr[32];
  236. char GateStr[32];
  237. char NetmaskStr[32];
  238. char MetricStr[32];
  239. char IfStr[32];
  240. NetpIpAddressToStr( Dest, DestStr);
  241. NetpIpAddressToStr( Gate, GateStr);
  242. NetpIpAddressToStr( Mask, NetmaskStr);
  243. MapInterface(IfStr,Interface);
  244. if( Metric1 > MAX_METRIC ) Metric1 = MAX_METRIC;
  245. sprintf( MetricStr, "%u", Metric1 );
  246. //IDS_ROUTE_14205 "%16s %16s %16s %16s %6s"
  247. LoadString(NULL, IDS_ROUTE_14205, szFormat, DimensionOf(szFormat));
  248. assert(szFormat[0]);
  249. _stprintf(s_szBuffer, szFormat, DestStr,
  250. NetmaskStr, GateStr, IfStr, MetricStr);
  251. return s_szBuffer;
  252. }
  253. BOOLEAN
  254. ExtractRoute(
  255. char *RouteString,
  256. ULONG *DestVal,
  257. ULONG *MaskVal,
  258. ULONG *GateVal,
  259. ULONG *MetricVal
  260. )
  261. /*++
  262. Description:
  263. Extracts the dest, mask, and gateway from a persistent
  264. route string, as stored in the registry.
  265. Arguments:
  266. RouteString : The string to parse.
  267. DestVal : The place to put the extracted destination
  268. MaskVal : The place to put the extracted mask
  269. GateVal : The place to put the extracted gateway
  270. MetricVal : The place to put the extracted metric
  271. Author:
  272. 07/01/98 Rajkumar . Created.
  273. --*/
  274. {
  275. char *addressPtr = RouteString;
  276. char *indexPtr = RouteString;
  277. ULONG address;
  278. ULONG i;
  279. char saveChar;
  280. BOOLEAN EndOfString=FALSE;
  281. //
  282. // The route is laid out in the string as "Dest,Mask,Gateway,Mertic".
  283. //
  284. //
  285. // set MetricVal to 1 to take care of persistent routes without the
  286. // metric value
  287. //
  288. *MetricVal = 1;
  289. for (i=0; i<4 && !EndOfString; i++) {
  290. //
  291. // Walk the string to the end of the current item.
  292. //
  293. while (1) {
  294. if (*indexPtr == '\0') {
  295. if ((i >= 2) && (indexPtr != addressPtr)) {
  296. //
  297. // End of string
  298. //
  299. EndOfString = TRUE;
  300. break;
  301. }
  302. return(FALSE);
  303. }
  304. if (*indexPtr == ROUTE_SEPARATOR) {
  305. break;
  306. }
  307. indexPtr++;
  308. }
  309. //
  310. // NULL terminate the current substring and extract the address value.
  311. //
  312. saveChar = *indexPtr;
  313. *indexPtr = '\0';
  314. if (i==3) {
  315. address = atoi (addressPtr);
  316. } else if (!ImprovedInetAddr(addressPtr, &address)) {
  317. *indexPtr = saveChar;
  318. return(FALSE);
  319. }
  320. *indexPtr = saveChar;
  321. switch(i) {
  322. case 0: *DestVal = address; break;
  323. case 1: *MaskVal = address; break;
  324. case 2: *GateVal = address; break;
  325. case 3: *MetricVal = address; break;
  326. default: return FALSE;
  327. }
  328. addressPtr = ++indexPtr;
  329. }
  330. return(TRUE);
  331. }
  332. //
  333. // Rajkumar - This function is based on route implementation
  334. //
  335. HRESULT
  336. PrintPersistentRoutes(
  337. NETDIAG_RESULT *pResults,
  338. char* Dest,
  339. ULONG DestVal,
  340. char* Gate,
  341. ULONG GateVal
  342. )
  343. /*++
  344. Routine Description:
  345. Displays the list of persistent routes
  346. Arguments: Dest : The destination string. (display filter)
  347. DestVal : The numeric destination value. (display filter)
  348. Gate : The gateway string. (display filter)
  349. GateVal : The numeric gateway value. (display filter)
  350. Returns: None
  351. --*/
  352. {
  353. //
  354. // Delete this route from the PersistentRoutes list in the
  355. // registry if it is there.
  356. //
  357. DWORD status;
  358. HKEY key;
  359. char valueString[ROUTE_DATA_STRING_SIZE];
  360. DWORD valueStringSize;
  361. DWORD valueType;
  362. DWORD index = 0;
  363. ULONG dest, mask, gate, metric;
  364. BOOLEAN headerPrinted = FALSE;
  365. BOOLEAN match;
  366. pResults->Route.dwNumPersistentRoutes = 0;
  367. InitializeListHead(&pResults->Route.lmsgPersistentRoute);
  368. status = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\PersistentRoutes", &key);
  369. if (status == ERROR_SUCCESS)
  370. {
  371. while(1) {
  372. valueStringSize = ROUTE_DATA_STRING_SIZE - 1;
  373. status = RegEnumValueA(
  374. key,
  375. index++,
  376. valueString,
  377. &valueStringSize,
  378. NULL,
  379. &valueType,
  380. NULL,
  381. 0
  382. );
  383. if (status != ERROR_SUCCESS)
  384. {
  385. if ((status == ERROR_BUFFER_OVERFLOW) ||
  386. (status == ERROR_MORE_DATA) )
  387. {
  388. continue;
  389. }
  390. else
  391. break;
  392. }
  393. if (valueType != REG_SZ)
  394. continue;
  395. valueString[valueStringSize++] = '\0';
  396. if ( !ExtractRoute(
  397. valueString,
  398. &dest,
  399. &mask,
  400. &gate,
  401. &metric
  402. )
  403. )
  404. {
  405. continue;
  406. }
  407. //IDS_ROUTE_14207 "%s\n"
  408. AddMessageToList( &pResults->Route.lmsgPersistentRoute, Nd_ReallyVerbose,
  409. IDS_ROUTE_14207,
  410. PrintRouteEntry(dest, mask, gate, 0, metric));
  411. pResults->Route.dwNumPersistentRoutes++;
  412. } // end while
  413. CloseHandle(key);
  414. }
  415. else
  416. {
  417. DebugMessage2("RegOpenKeyA %s failed\n","Tcpip\\Parameters\\Persistent");
  418. return S_FALSE;
  419. }
  420. return S_OK;
  421. }
  422. void MapInterface(char *IPAddr, ULONG IfIndex)
  423. {
  424. DWORD IpAddrTableSize=0;
  425. PMIB_IPADDRTABLE pIpAddrTable=NULL;
  426. char *TempBuf;
  427. BOOL bOrder=TRUE;
  428. HRESULT hr;
  429. DWORD i;
  430. sprintf(IPAddr,"%x",IfIndex);
  431. hr=GetIpAddrTable(NULL,
  432. &IpAddrTableSize,
  433. bOrder);
  434. if (hr != ERROR_SUCCESS && hr != ERROR_INSUFFICIENT_BUFFER) {
  435. DebugMessage("GetIpAddrTable() failed.\n");
  436. return;
  437. }
  438. pIpAddrTable=(PMIB_IPADDRTABLE) Malloc(IpAddrTableSize);
  439. if (pIpAddrTable == NULL) {
  440. DebugMessage("Out of Memory in RouteTest::MapInterface().\n");
  441. return;
  442. }
  443. ZeroMemory( pIpAddrTable, IpAddrTableSize );
  444. hr=GetIpAddrTable(pIpAddrTable,
  445. &IpAddrTableSize,
  446. bOrder);
  447. if (hr != ERROR_SUCCESS)
  448. {
  449. DebugMessage("GetIpAddrTable() failed.\n");
  450. Free(pIpAddrTable);
  451. return;
  452. }
  453. for (i=0; i < pIpAddrTable->dwNumEntries; i++)
  454. {
  455. if ((pIpAddrTable->table[i].dwIndex == IfIndex) && (pIpAddrTable->table[i].dwAddr != 0) && (pIpAddrTable->table[i].wType & MIB_IPADDR_PRIMARY))
  456. {
  457. TempBuf=inet_ntoa(*(struct in_addr*)&pIpAddrTable->table[i].dwAddr);
  458. if (!TempBuf) {
  459. break;;
  460. }
  461. strcpy(IPAddr, TempBuf);
  462. break;
  463. }
  464. }
  465. Free(pIpAddrTable);
  466. return;
  467. }
  468. BOOLEAN
  469. ImprovedInetAddr(
  470. char *AddressString,
  471. ULONG *AddressValue
  472. )
  473. /*++
  474. Description:
  475. Converts an IP address string to its numeric equivalent.
  476. Arguments:
  477. char *AddressString: The string to convert
  478. ULONG AddressValue : The place to store the converted value.
  479. Returns: TRUE
  480. Author:
  481. 07/01/98 Rajkumar . Created.
  482. --*/
  483. {
  484. ULONG address = inet_addr(AddressString);
  485. if (address == 0xFFFFFFFF) {
  486. if (strcmp(AddressString, "255.255.255.255") == 0) {
  487. *AddressValue = address;
  488. return(TRUE);
  489. }
  490. return(FALSE);
  491. }
  492. *AddressValue = address;
  493. return TRUE;
  494. }
  495. void RouteGlobalPrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
  496. {
  497. if (!pParams->fReallyVerbose)
  498. return;
  499. if (pParams->fReallyVerbose || !FHrOK(pResults->Route.hrTestResult))
  500. {
  501. PrintNewLine(pParams, 2);
  502. PrintTestTitleResult(pParams,
  503. IDS_ROUTE_LONG,
  504. IDS_ROUTE_SHORT,
  505. TRUE,
  506. pResults->Route.hrTestResult,
  507. 0);
  508. }
  509. if( pParams->fReallyVerbose)
  510. {
  511. if( 0 == pResults->Route.dwNumRoutes)
  512. {
  513. //IDS_ROUTE_14201 "No Entries in the IP Forward Table\n"
  514. PrintMessage( pParams, IDS_ROUTE_14201);
  515. }
  516. else
  517. {
  518. //IDS_ROUTE_14202 "Active Routes :\n"
  519. PrintMessage( pParams, IDS_ROUTE_14202);
  520. PrintMessageList(pParams, &pResults->Route.lmsgRoute);
  521. }
  522. if( 0 == pResults->Route.dwNumPersistentRoutes)
  523. {
  524. //IDS_ROUTE_14208 "No persistent route entries.\n"
  525. PrintMessage( pParams, IDS_ROUTE_14208);
  526. }
  527. else
  528. {
  529. //IDS_ROUTE_14206 "\nPersistent Route Entries: \n"
  530. PrintMessage( pParams, IDS_ROUTE_14206);
  531. PrintMessageList(pParams, &pResults->Route.lmsgPersistentRoute);
  532. }
  533. }
  534. }
  535. void RoutePerInterfacePrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults, INTERFACE_RESULT *pInterfaceResults)
  536. {
  537. if (!pParams->fReallyVerbose)
  538. return;
  539. }
  540. void RouteCleanup(IN NETDIAG_PARAMS *pParams,
  541. IN OUT NETDIAG_RESULT *pResults)
  542. {
  543. MessageListCleanUp(&pResults->Route.lmsgRoute);
  544. MessageListCleanUp(&pResults->Route.lmsgPersistentRoute);
  545. }