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.

790 lines
17 KiB

  1. #include "inc.h"
  2. CMD_ENTRY g_rgRouteCmdTable[] = {
  3. {TOKEN_ADD, AddRoute},
  4. {TOKEN_DELETE, DeleteRoute},
  5. {TOKEN_PRINT, PrintRoute},
  6. {TOKEN_MATCH, MatchRoute},
  7. {TOKEN_ENABLE, EnableRoute},
  8. };
  9. VOID
  10. HandleRoute(
  11. LONG lNumArgs,
  12. PWCHAR rgpwszArgs[]
  13. )
  14. {
  15. LONG lIndex;
  16. if(lNumArgs < 2)
  17. {
  18. DisplayMessage(HMSG_ROUTE_USAGE);
  19. return;
  20. }
  21. lIndex = ParseCommand(g_rgRouteCmdTable,
  22. sizeof(g_rgRouteCmdTable)/sizeof(CMD_ENTRY),
  23. rgpwszArgs[1]);
  24. if(lIndex is -1)
  25. {
  26. DisplayMessage(HMSG_ROUTE_USAGE);
  27. return;
  28. }
  29. g_rgRouteCmdTable[lIndex].pfnHandler(lNumArgs - 1,
  30. &rgpwszArgs[1]);
  31. return;
  32. }
  33. VOID
  34. PrintRoute(
  35. LONG lNumArgs,
  36. PWCHAR rgpwszArgs[]
  37. )
  38. {
  39. DWORD dwResult;
  40. PMIB_IPFORWARDTABLE pTable;
  41. ULONG i;
  42. dwResult = AllocateAndGetIpForwardTableFromStack(&pTable,
  43. TRUE,
  44. GetProcessHeap(),
  45. HEAP_NO_SERIALIZE);
  46. if(dwResult isnot NO_ERROR)
  47. {
  48. PWCHAR pwszEntry;
  49. pwszEntry = MakeString(STR_RTTABLE);
  50. if(pwszEntry)
  51. {
  52. DisplayMessage(EMSG_RETRIEVAL_ERROR1,
  53. dwResult,
  54. pwszEntry);
  55. FreeString(pwszEntry);
  56. }
  57. else
  58. {
  59. DisplayMessage(EMSG_RETRIEVAL_ERROR2,
  60. dwResult);
  61. }
  62. return;
  63. }
  64. if(pTable->dwNumEntries is 0)
  65. {
  66. PWCHAR pwszEntryType;
  67. pwszEntryType = MakeString(TOKEN_ROUTE);
  68. if(pwszEntryType)
  69. {
  70. DisplayMessage(EMSG_NO_ENTRIES1,
  71. pwszEntryType);
  72. FreeString(pwszEntryType);
  73. }
  74. else
  75. {
  76. DisplayMessage(EMSG_NO_ENTRIES2);
  77. }
  78. HeapFree(GetProcessHeap(),
  79. HEAP_NO_SERIALIZE,
  80. pTable);
  81. return;
  82. }
  83. DisplayMessage(MSG_RTTABLE_HDR);
  84. for(i = 0; i < pTable->dwNumEntries; i++)
  85. {
  86. ADDR_STRING rgwcDest, rgwcMask, rgwcNHop;
  87. NetworkToUnicode(pTable->table[i].dwForwardDest,
  88. rgwcDest);
  89. NetworkToUnicode(pTable->table[i].dwForwardMask,
  90. rgwcMask);
  91. NetworkToUnicode(pTable->table[i].dwForwardNextHop,
  92. rgwcNHop);
  93. wprintf(L"%-15s\t%-15s\t%-15s\t%8d\t%4d\t%4d\n",
  94. rgwcDest,
  95. rgwcMask,
  96. rgwcNHop,
  97. pTable->table[i].dwForwardIfIndex,
  98. pTable->table[i].dwForwardMetric1,
  99. pTable->table[i].dwForwardProto);
  100. }
  101. HeapFree(GetProcessHeap(),
  102. HEAP_NO_SERIALIZE,
  103. pTable);
  104. }
  105. VOID
  106. AddRoute(
  107. LONG lNumArgs,
  108. PWCHAR rgpwszArgs[]
  109. )
  110. {
  111. DWORD dwResult, dwMask, dwDest, dwNHop, dwMetric, dwIfIndex;
  112. BOOL bValid;
  113. ULONG i;
  114. PMIB_IPADDRTABLE pTable;
  115. MIB_IPFORWARDROW Route;
  116. //
  117. // Parse the rest of the arguments
  118. // The command line at this point should read:
  119. // ADD <dest> MASK <mask> <nhop> [IF <ifIndex>] [METRIC <metric>]
  120. //
  121. if(lNumArgs < 5)
  122. {
  123. DisplayMessage(HMSG_ROUTE_ADD_USAGE);
  124. return;
  125. }
  126. if(!MatchToken(rgpwszArgs[2],
  127. TOKEN_MASK))
  128. {
  129. DisplayMessage(HMSG_ROUTE_ADD_USAGE);
  130. return;
  131. }
  132. dwDest = UnicodeToNetwork(rgpwszArgs[1]);
  133. dwMask = UnicodeToNetwork(rgpwszArgs[3]);
  134. dwNHop = UnicodeToNetwork(rgpwszArgs[4]);
  135. do
  136. {
  137. DWORD dwTestMask, i, dwNMask;
  138. dwTestMask = 0;
  139. if(dwMask is 0)
  140. {
  141. bValid = TRUE;
  142. break;
  143. }
  144. bValid = FALSE;
  145. for(i = 0; bValid or (i < 32); i++)
  146. {
  147. dwTestMask = 0x80000000 | (dwTestMask >> 1);
  148. dwNMask = RtlUlongByteSwap(dwTestMask);
  149. if(dwMask is dwNMask)
  150. {
  151. bValid = TRUE;
  152. break;
  153. }
  154. }
  155. }while(FALSE);
  156. if(dwDest is INADDR_NONE)
  157. {
  158. DisplayMessage(EMSG_RT_BAD_DEST);
  159. return;
  160. }
  161. if(dwNHop is INADDR_NONE)
  162. {
  163. DisplayMessage(EMSG_RT_BAD_NHOP);
  164. return;
  165. }
  166. if(bValid isnot TRUE)
  167. {
  168. DisplayMessage(EMSG_RT_BAD_MASK);
  169. return;
  170. }
  171. if((dwDest & dwMask) isnot dwDest)
  172. {
  173. DisplayMessage(EMSG_RT_BAD_DEST);
  174. return;
  175. }
  176. //
  177. // See if we have an index or metric
  178. //
  179. dwIfIndex = (DWORD)-1;
  180. dwMetric = 1;
  181. if(lNumArgs > 5)
  182. {
  183. if((lNumArgs isnot 7) and
  184. (lNumArgs isnot 9))
  185. {
  186. DisplayMessage(HMSG_ROUTE_ADD_USAGE);
  187. return;
  188. }
  189. if(!MatchToken(rgpwszArgs[5],
  190. TOKEN_INTERFACE))
  191. {
  192. DisplayMessage(HMSG_ROUTE_ADD_USAGE);
  193. return;
  194. }
  195. dwIfIndex = wcstoul(rgpwszArgs[6],
  196. NULL,
  197. 10);
  198. if(lNumArgs is 9)
  199. {
  200. if(!MatchToken(rgpwszArgs[7],
  201. TOKEN_METRIC))
  202. {
  203. DisplayMessage(HMSG_ROUTE_ADD_USAGE);
  204. return;
  205. }
  206. dwMetric = wcstoul(rgpwszArgs[8],
  207. NULL,
  208. 10);
  209. }
  210. if((dwIfIndex && dwMetric) is 0)
  211. {
  212. DisplayMessage(EMSG_RT_ZERO_IF_METRIC);
  213. return;
  214. }
  215. }
  216. //
  217. // Get the address table
  218. //
  219. dwResult = AllocateAndGetIpAddrTableFromStack(&pTable,
  220. FALSE,
  221. GetProcessHeap(),
  222. HEAP_NO_SERIALIZE);
  223. if(dwResult isnot NO_ERROR)
  224. {
  225. PWCHAR pwszEntry;
  226. pwszEntry = MakeString(STR_ADDRTABLE);
  227. if(pwszEntry)
  228. {
  229. DisplayMessage(EMSG_RETRIEVAL_ERROR1,
  230. dwResult,
  231. pwszEntry);
  232. FreeString(pwszEntry);
  233. }
  234. else
  235. {
  236. DisplayMessage(EMSG_RETRIEVAL_ERROR2,
  237. dwResult);
  238. }
  239. return;
  240. }
  241. bValid = FALSE;
  242. for(i = 0; i < pTable->dwNumEntries; i++)
  243. {
  244. DWORD dwNet;
  245. if((pTable->table[i].dwAddr is 0) or
  246. (pTable->table[i].dwMask is 0))
  247. {
  248. continue;
  249. }
  250. if(dwIfIndex isnot (DWORD)-1)
  251. {
  252. if(pTable->table[i].dwIndex is dwIfIndex)
  253. {
  254. if(pTable->table[i].dwMask is 0xFFFFFFFF)
  255. {
  256. //
  257. // cant do a next hop check
  258. //
  259. bValid = TRUE;
  260. break;
  261. }
  262. dwNet = pTable->table[i].dwAddr & pTable->table[i].dwMask;
  263. if((dwNHop & pTable->table[i].dwMask) is dwNet)
  264. {
  265. bValid = TRUE;
  266. break;
  267. }
  268. }
  269. }
  270. else
  271. {
  272. //
  273. // Dont have an interface index
  274. // See if we can find an network on which the next hop lies
  275. //
  276. dwNet = pTable->table[i].dwAddr & pTable->table[i].dwMask;
  277. if((dwNHop & pTable->table[i].dwMask) is dwNet)
  278. {
  279. bValid = TRUE;
  280. dwIfIndex = pTable->table[i].dwIndex;
  281. break;
  282. }
  283. }
  284. }
  285. if(!bValid)
  286. {
  287. DisplayMessage(EMSG_RT_BAD_IF_NHOP);
  288. return;
  289. }
  290. ZeroMemory(&Route,
  291. sizeof(MIB_IPFORWARDROW));
  292. Route.dwForwardDest = dwDest;
  293. Route.dwForwardMask = dwMask;
  294. Route.dwForwardNextHop = dwNHop;
  295. Route.dwForwardIfIndex = dwIfIndex;
  296. Route.dwForwardMetric1 = dwMetric;
  297. Route.dwForwardProto = MIB_IPPROTO_LOCAL;
  298. if((dwDest is pTable->table[i].dwAddr) or
  299. (dwDest is dwNHop))
  300. {
  301. Route.dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
  302. }
  303. else
  304. {
  305. Route.dwForwardType = MIB_IPROUTE_TYPE_INDIRECT;
  306. }
  307. dwResult = SetIpForwardEntryToStack(&Route);
  308. if(dwResult isnot NO_ERROR)
  309. {
  310. PWCHAR pwszEntry;
  311. pwszEntry = MakeString(STR_RTENTRY);
  312. if(pwszEntry)
  313. {
  314. DisplayMessage(EMSG_SET_ERROR1,
  315. dwResult,
  316. pwszEntry);
  317. FreeString(pwszEntry);
  318. }
  319. else
  320. {
  321. DisplayMessage(EMSG_SET_ERROR2,
  322. dwResult);
  323. }
  324. }
  325. HeapFree(GetProcessHeap(),
  326. HEAP_NO_SERIALIZE,
  327. pTable);
  328. }
  329. VOID
  330. DeleteRoute(
  331. LONG lNumArgs,
  332. PWCHAR rgpwszArgs[]
  333. )
  334. {
  335. DWORD dwResult, dwMask, dwDest, dwNHop, dwIfIndex;
  336. BOOL bAny;
  337. ULONG i;
  338. PMIB_IPFORWARDTABLE pTable;
  339. PMIB_IPFORWARDROW pRoute;
  340. //
  341. // Parse the rest of the arguments
  342. // The command line at this point should read:
  343. // DELETE <dest> [MASK <mask>] [<nhop>] [IF <ifIndex>]
  344. //
  345. if(lNumArgs < 2)
  346. {
  347. DisplayMessage(HMSG_ROUTE_DELETE_USAGE);
  348. return;
  349. }
  350. dwDest = UnicodeToNetwork(rgpwszArgs[1]);
  351. if((lNumArgs > 2) and
  352. (lNumArgs isnot 7))
  353. {
  354. DisplayMessage(HMSG_ROUTE_DELETE_USAGE);
  355. return;
  356. }
  357. bAny = TRUE;
  358. if(lNumArgs is 7)
  359. {
  360. if(!MatchToken(rgpwszArgs[2],
  361. TOKEN_MASK))
  362. {
  363. DisplayMessage(HMSG_ROUTE_DELETE_USAGE);
  364. return;
  365. }
  366. if(!MatchToken(rgpwszArgs[5],
  367. TOKEN_INTERFACE))
  368. {
  369. DisplayMessage(HMSG_ROUTE_DELETE_USAGE);
  370. return;
  371. }
  372. dwMask = UnicodeToNetwork(rgpwszArgs[3]);
  373. dwNHop = UnicodeToNetwork(rgpwszArgs[4]);
  374. dwIfIndex = wcstoul(rgpwszArgs[6],
  375. NULL,
  376. 10);
  377. if((dwNHop is INADDR_NONE) or
  378. (dwIfIndex is 0))
  379. {
  380. DisplayMessage(HMSG_ROUTE_DELETE_USAGE);
  381. return;
  382. }
  383. bAny = FALSE;
  384. }
  385. //
  386. // Get the route table and see if such a route exists
  387. //
  388. dwResult = AllocateAndGetIpForwardTableFromStack(&pTable,
  389. TRUE,
  390. GetProcessHeap(),
  391. HEAP_NO_SERIALIZE);
  392. if(dwResult isnot NO_ERROR)
  393. {
  394. PWCHAR pwszEntry;
  395. pwszEntry = MakeString(STR_RTTABLE);
  396. if(pwszEntry)
  397. {
  398. DisplayMessage(EMSG_RETRIEVAL_ERROR1,
  399. dwResult,
  400. pwszEntry);
  401. FreeString(pwszEntry);
  402. }
  403. else
  404. {
  405. DisplayMessage(EMSG_RETRIEVAL_ERROR2,
  406. dwResult);
  407. }
  408. return;
  409. }
  410. if(pTable->dwNumEntries is 0)
  411. {
  412. PWCHAR pwszEntryType;
  413. pwszEntryType = MakeString(TOKEN_ROUTE);
  414. if(pwszEntryType)
  415. {
  416. DisplayMessage(EMSG_NO_ENTRIES1,
  417. pwszEntryType);
  418. FreeString(pwszEntryType);
  419. }
  420. else
  421. {
  422. DisplayMessage(EMSG_NO_ENTRIES2);
  423. }
  424. HeapFree(GetProcessHeap(),
  425. HEAP_NO_SERIALIZE,
  426. pTable);
  427. return;
  428. }
  429. pRoute = NULL;
  430. for(i = 0; i < pTable->dwNumEntries; i++)
  431. {
  432. if(pTable->table[i].dwForwardDest is dwDest)
  433. {
  434. if(bAny)
  435. {
  436. if((i is (pTable->dwNumEntries - 1)) or
  437. (pTable->table[i + 1].dwForwardDest isnot dwDest))
  438. {
  439. //
  440. // Unique entry
  441. //
  442. pRoute = &(pTable->table[i]);
  443. }
  444. break;
  445. }
  446. else
  447. {
  448. //
  449. // Do an exact match
  450. //
  451. if((pTable->table[i].dwForwardMask is dwMask) and
  452. (pTable->table[i].dwForwardNextHop is dwNHop) and
  453. (pTable->table[i].dwForwardIfIndex is dwIfIndex))
  454. {
  455. pRoute = &(pTable->table[i]);
  456. break;
  457. }
  458. }
  459. }
  460. }
  461. if(pRoute is NULL)
  462. {
  463. DisplayMessage(EMSG_UNIQUE_ROUTE_ABSENT);
  464. HeapFree(GetProcessHeap(),
  465. HEAP_NO_SERIALIZE,
  466. pTable);
  467. return;
  468. }
  469. pRoute->dwForwardType = MIB_IPROUTE_TYPE_INVALID;
  470. dwResult = SetIpForwardEntryToStack(pRoute);
  471. if(dwResult isnot NO_ERROR)
  472. {
  473. PWCHAR pwszEntry;
  474. pwszEntry = MakeString(STR_RTENTRY);
  475. if(pwszEntry)
  476. {
  477. DisplayMessage(EMSG_SET_ERROR1,
  478. dwResult,
  479. pwszEntry);
  480. FreeString(pwszEntry);
  481. }
  482. else
  483. {
  484. DisplayMessage(EMSG_SET_ERROR2,
  485. dwResult);
  486. }
  487. }
  488. HeapFree(GetProcessHeap(),
  489. HEAP_NO_SERIALIZE,
  490. pTable);
  491. }
  492. VOID
  493. MatchRoute(
  494. LONG lNumArgs,
  495. PWCHAR rgpwszArgs[]
  496. )
  497. {
  498. DWORD dwResult, dwDest, dwSrc;
  499. ADDR_STRING rgwcDest, rgwcMask, rgwcNHop;
  500. MIB_IPFORWARDROW Route;
  501. //
  502. // Command line should be MATCH <dest> [SRC <srcAddr>]
  503. //
  504. if(lNumArgs < 2)
  505. {
  506. DisplayMessage(HMSG_ROUTE_MATCH_USAGE);
  507. return;
  508. }
  509. dwSrc = 0;
  510. if(lNumArgs > 2)
  511. {
  512. if(lNumArgs isnot 4)
  513. {
  514. DisplayMessage(HMSG_ROUTE_MATCH_USAGE);
  515. return;
  516. }
  517. if(!MatchToken(rgpwszArgs[2],
  518. TOKEN_SRC))
  519. {
  520. DisplayMessage(HMSG_ROUTE_MATCH_USAGE);
  521. return;
  522. }
  523. dwSrc = UnicodeToNetwork(rgpwszArgs[3]);
  524. }
  525. dwDest = UnicodeToNetwork(rgpwszArgs[1]);
  526. dwResult = GetBestRouteFromStack(dwDest,
  527. dwSrc,
  528. &Route);
  529. if(dwResult isnot NO_ERROR)
  530. {
  531. PWCHAR pwszEntry;
  532. pwszEntry = MakeString(STR_RTENTRY);
  533. if(pwszEntry)
  534. {
  535. DisplayMessage(EMSG_RETRIEVAL_ERROR1,
  536. dwResult,
  537. pwszEntry);
  538. FreeString(pwszEntry);
  539. }
  540. else
  541. {
  542. DisplayMessage(EMSG_RETRIEVAL_ERROR2,
  543. dwResult);
  544. }
  545. return;
  546. }
  547. NetworkToUnicode(Route.dwForwardDest,
  548. rgwcDest);
  549. NetworkToUnicode(Route.dwForwardMask,
  550. rgwcMask);
  551. NetworkToUnicode(Route.dwForwardNextHop,
  552. rgwcNHop);
  553. DisplayMessage(MSG_RTTABLE_HDR);
  554. wprintf(L"%-15s\t%-15s\t%-15s\t%-4d\t%d\t%4d\n",
  555. rgwcDest,
  556. rgwcMask,
  557. rgwcNHop,
  558. Route.dwForwardIfIndex,
  559. Route.dwForwardMetric1,
  560. Route.dwForwardProto);
  561. }
  562. VOID
  563. EnableRoute(
  564. LONG lNumArgs,
  565. PWCHAR rgpwszArgs[]
  566. )
  567. {
  568. const WCHAR Empty[] = L"";
  569. UNICODE_STRING BindList;
  570. HKEY Key;
  571. UNICODE_STRING LowerComponent;
  572. IP_PNP_RECONFIG_REQUEST Request;
  573. UINT status;
  574. const WCHAR Tcpip[] = L"Tcpip";
  575. const TCHAR TcpipParameters[] =
  576. TEXT("System\\CurrentControlSet\\Services\\Tcpip\\Parameters");
  577. UNICODE_STRING UpperComponent;
  578. RtlInitUnicodeString(&BindList, Empty);
  579. RtlInitUnicodeString(&LowerComponent, Empty);
  580. RtlInitUnicodeString(&UpperComponent, Tcpip);
  581. Request.version = IP_PNP_RECONFIG_VERSION;
  582. Request.NextEntryOffset = 0;
  583. Request.arpConfigOffset = 0;
  584. Request.IPEnableRouter = TRUE;
  585. Request.Flags = IP_PNP_FLAG_IP_ENABLE_ROUTER;
  586. status = NdisHandlePnPEvent(NDIS,
  587. RECONFIGURE,
  588. &LowerComponent,
  589. &UpperComponent,
  590. &BindList,
  591. &Request,
  592. sizeof(Request)
  593. );
  594. if (!status)
  595. {
  596. DisplayMessage(EMSG_ROUTE_ENABLE, GetLastError());
  597. }
  598. if (RegOpenKey(HKEY_LOCAL_MACHINE, TcpipParameters, &Key) == NO_ERROR)
  599. {
  600. status = TRUE;
  601. RegSetValueEx(Key,
  602. TEXT("IPEnableRouter"),
  603. 0,
  604. REG_DWORD,
  605. (PBYTE)&status,
  606. sizeof(status)
  607. );
  608. RegCloseKey(Key);
  609. }
  610. }