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.

1458 lines
42 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. Revision History:
  6. Amritansh Raghav
  7. --*/
  8. #include "allinc.h"
  9. //
  10. // Definitions
  11. //
  12. //*****************************************************************************
  13. //
  14. // Name: GetIpAddrTableFromStack
  15. //
  16. // Description:
  17. //
  18. // Parameters: IPAddrEntry *lpipaeTable, LPDWORD lpdwNumEntries, BOOL bOrder
  19. //
  20. // Returns: DWORD: NO_ERROR or some error code.
  21. //
  22. // History:
  23. //
  24. //*****************************************************************************
  25. DWORD
  26. GetIpAddrTableFromStack(IPAddrEntry *lpipaeTable, LPDWORD lpdwNumEntries,
  27. BOOL bOrder, BOOL bMap)
  28. {
  29. DWORD dwResult;
  30. DWORD dwInBufLen;
  31. DWORD dwOutBufLen;
  32. DWORD i,j;
  33. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  34. TDIObjectID *ID;
  35. BYTE *Context;
  36. TraceEnter("GetIpAddrTableFromStack");
  37. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  38. dwOutBufLen = (*lpdwNumEntries) * sizeof( IPAddrEntry );
  39. ID = &(trqiInBuf.ID);
  40. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  41. ID->toi_entity.tei_instance = 0;
  42. ID->toi_class = INFO_CLASS_PROTOCOL;
  43. ID->toi_type = INFO_TYPE_PROVIDER;
  44. ID->toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
  45. Context = &(trqiInBuf.Context[0]);
  46. ZeroMemory( Context, CONTEXT_SIZE );
  47. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  48. &trqiInBuf,
  49. &dwInBufLen,
  50. (LPVOID)lpipaeTable,
  51. &dwOutBufLen );
  52. if (dwResult isnot NO_ERROR)
  53. {
  54. Trace1(ERR,
  55. "GetIpAddrTableFromStack: NtStatus %x querying IpAddrTable from stack",
  56. dwResult);
  57. TraceLeave("GetIpAddrTableFromStack");
  58. return dwResult;
  59. }
  60. *lpdwNumEntries =(dwOutBufLen / sizeof(IPAddrEntry));
  61. //
  62. // Now sort the address table. Key is IP address.
  63. //
  64. if(*lpdwNumEntries > 0)
  65. {
  66. if(bMap)
  67. {
  68. for (i = 0; i < (*lpdwNumEntries); i++ )
  69. {
  70. lpipaeTable[i].iae_index = GetInterfaceFromAdapter(lpipaeTable[i].iae_index);
  71. }
  72. }
  73. if(bOrder)
  74. {
  75. for (i = 0; i < (*lpdwNumEntries) - 1; i++ )
  76. {
  77. IPAddrEntry tempEntry;
  78. DWORD min;
  79. LONG lCompare;
  80. min = i;
  81. for (j = i + 1; j < *lpdwNumEntries; j++ )
  82. {
  83. if(InetCmp(lpipaeTable[min].iae_addr,lpipaeTable[j].iae_addr,lCompare) > 0)
  84. {
  85. min = j;
  86. }
  87. }
  88. if(min isnot i)
  89. {
  90. tempEntry = lpipaeTable[min];
  91. lpipaeTable[min] = lpipaeTable[i];
  92. lpipaeTable[i] = tempEntry;
  93. }
  94. }
  95. }
  96. }
  97. TraceLeave("GetIpAddrTableFromStack");
  98. return NO_ERROR;
  99. }
  100. //*****************************************************************************
  101. //
  102. // Name: GetTcpConnTableFromStack
  103. //
  104. // Description: Reads and sorts the route table from the stack.
  105. //
  106. // Parameters: TCPConnTableEntry *lptcteTable, LPDWORD lpdwNumEntries, BOOL bOrder
  107. //
  108. // Returns: DWORD: NO_ERROR or some error code.
  109. //
  110. // History:
  111. //
  112. //*****************************************************************************
  113. DWORD
  114. GetTcpTableFromStack(TCPConnTableEntry *lptcteTable, LPDWORD lpdwNumEntries, BOOL bOrder)
  115. {
  116. DWORD dwResult;
  117. DWORD dwInBufLen;
  118. DWORD dwOutBufLen;
  119. DWORD i,j;
  120. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  121. TDIObjectID *ID;
  122. BYTE *Context;
  123. TCPStats TcpInfo;
  124. DWORD NumConn;
  125. DWORD *IndTab;
  126. LONG CmpResult;
  127. TraceEnter("GetTcpTableFromStack");
  128. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  129. dwOutBufLen = (*lpdwNumEntries) * sizeof(TCPConnTableEntry);
  130. ID = &(trqiInBuf.ID);
  131. ID->toi_entity.tei_entity = CO_TL_ENTITY;
  132. ID->toi_entity.tei_instance = 0;
  133. ID->toi_class = INFO_CLASS_PROTOCOL;
  134. ID->toi_type = INFO_TYPE_PROVIDER;
  135. ID->toi_id = TCP_MIB_TABLE_ID;
  136. Context = &(trqiInBuf.Context[0]);
  137. ZeroMemory( Context, CONTEXT_SIZE );
  138. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  139. &trqiInBuf,
  140. &dwInBufLen,
  141. (LPVOID)lptcteTable,
  142. &dwOutBufLen);
  143. if (dwResult isnot NO_ERROR )
  144. {
  145. Trace1(ERR,
  146. "GetTcpTableFromStack: NtStatus %x querying TcpConnTable from stack",
  147. dwResult);
  148. TraceLeave("GetTcpTableFromStack");
  149. return dwResult;
  150. }
  151. *lpdwNumEntries = (dwOutBufLen/sizeof(TCPConnTableEntry));
  152. //
  153. // Now sort the TCP connection table. Keys are: local address, local
  154. // port, remote address, and remote port.
  155. //
  156. if((*lpdwNumEntries > 0) and bOrder)
  157. {
  158. for ( i = 0; i < (*lpdwNumEntries) - 1 ; i++ )
  159. {
  160. TCPConnTableEntry tempEntry;
  161. DWORD min;
  162. min = i;
  163. for ( j = i+1; j < *lpdwNumEntries ; j++ )
  164. {
  165. if(TcpCmp(lptcteTable[min].tct_localaddr,lptcteTable[min].tct_localport,
  166. lptcteTable[min].tct_remoteaddr,lptcteTable[min].tct_remoteport,
  167. lptcteTable[j].tct_localaddr,lptcteTable[j].tct_localport,
  168. lptcteTable[j].tct_remoteaddr,lptcteTable[j].tct_remoteport) > 0)
  169. {
  170. min = j;
  171. }
  172. }
  173. if(min isnot i)
  174. {
  175. tempEntry = lptcteTable[min];
  176. lptcteTable[min] = lptcteTable[i];
  177. lptcteTable[i] = tempEntry;
  178. }
  179. }
  180. }
  181. TraceLeave("GetTcpTableFromStack");
  182. return NO_ERROR;
  183. }
  184. DWORD
  185. SetTcpRowToStack(TCPConnTableEntry *tcpRow)
  186. {
  187. TCP_REQUEST_SET_INFORMATION_EX *lptrsiInBuf;
  188. TDIObjectID *ID;
  189. UCHAR *Context;
  190. TCPConnTableEntry *copyInfo;
  191. DWORD dwInBufLen,dwOutBufLen,dwResult;
  192. TraceEnter("SetTcpRowToStack");
  193. dwInBufLen = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(TCPConnTableEntry) - 1;
  194. lptrsiInBuf = HeapAlloc(GetProcessHeap(),0,dwInBufLen);
  195. if(lptrsiInBuf is NULL)
  196. {
  197. dwResult = GetLastError();
  198. Trace1(ERR,
  199. "SetTcpRowToStack: Error %d allocating memory",
  200. dwResult);
  201. TraceLeave("SetTcpRowToStack");
  202. return dwResult;
  203. }
  204. ID = &lptrsiInBuf->ID;
  205. ID->toi_class = INFO_CLASS_PROTOCOL;
  206. ID->toi_type = INFO_TYPE_PROVIDER;
  207. ID->toi_entity.tei_entity = CO_TL_ENTITY;
  208. ID->toi_id = TCP_MIB_TABLE_ID;
  209. ID->toi_entity.tei_instance = 0;
  210. lptrsiInBuf->BufferSize = sizeof(TCPConnTableEntry);
  211. copyInfo = (TCPConnTableEntry*)lptrsiInBuf->Buffer;
  212. *copyInfo = *tcpRow;
  213. dwResult = TCPSetInformationEx(g_hTcpDevice,
  214. (LPVOID)lptrsiInBuf,
  215. &dwInBufLen,
  216. NULL,
  217. &dwOutBufLen);
  218. HeapFree(GetProcessHeap(),0,lptrsiInBuf);
  219. TraceLeave("SetTcpRowToStack");
  220. return dwResult;
  221. }
  222. //*****************************************************************************
  223. //
  224. // Name: GetUdpConnTableFromStack
  225. //
  226. // Description: Reads and sorts the route table from the stack.
  227. //
  228. // Parameters: UDPEntry *lpueTable, LPDWORD lpdwNumEntries, BOOL bOrder
  229. //
  230. // Returns: DWORD: NO_ERROR or some error code.
  231. //
  232. // History:
  233. //
  234. //*****************************************************************************
  235. DWORD
  236. GetUdpTableFromStack(UDPEntry *lpueTable, LPDWORD lpdwNumEntries, BOOL bOrder)
  237. {
  238. DWORD dwResult;
  239. DWORD dwInBufLen;
  240. DWORD dwOutBufLen;
  241. DWORD i,j;
  242. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  243. TDIObjectID *ID;
  244. BYTE *Context;
  245. TraceEnter("GetUdpTableFromStack");
  246. //
  247. // Determine number of connections via the UDPStats structure
  248. //
  249. dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX );
  250. dwOutBufLen = (*lpdwNumEntries) * sizeof(UDPEntry);
  251. ID = &(trqiInBuf.ID);
  252. ID->toi_entity.tei_entity = CL_TL_ENTITY;
  253. ID->toi_entity.tei_instance = 0;
  254. ID->toi_class = INFO_CLASS_PROTOCOL;
  255. ID->toi_type = INFO_TYPE_PROVIDER;
  256. ID->toi_id = UDP_MIB_TABLE_ID;
  257. Context = &(trqiInBuf.Context[0]);
  258. ZeroMemory( Context, CONTEXT_SIZE );
  259. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  260. &trqiInBuf,
  261. &dwInBufLen,
  262. (LPVOID)lpueTable,
  263. &dwOutBufLen );
  264. if(dwResult isnot NO_ERROR)
  265. {
  266. Trace1(ERR,
  267. "GetUdpTableFromStack: NtStatus %x querying UdpTable from stack",
  268. dwResult);
  269. TraceLeave("GetUdpTableFromStack");
  270. return dwResult;
  271. }
  272. *lpdwNumEntries =(dwOutBufLen / sizeof(UDPEntry));
  273. //
  274. // Now sort the UDP connection table. Keys are: local address, and local
  275. // port.
  276. //
  277. if((*lpdwNumEntries > 0) and bOrder)
  278. {
  279. for ( i = 0; i < (*lpdwNumEntries) - 1; i++ )
  280. {
  281. UDPEntry tempEntry;
  282. DWORD min;
  283. min = i;
  284. for ( j = i + 1; j < (*lpdwNumEntries) ; j++ )
  285. {
  286. if(UdpCmp(lpueTable[min].ue_localaddr,
  287. lpueTable[min].ue_localport,
  288. lpueTable[j].ue_localaddr,
  289. lpueTable[j].ue_localport) > 0)
  290. {
  291. min = j;
  292. }
  293. }
  294. if(min isnot i)
  295. {
  296. tempEntry = lpueTable[min];
  297. lpueTable[min] = lpueTable[i];
  298. lpueTable[i] = tempEntry;
  299. }
  300. }
  301. }
  302. TraceLeave("GetUdpTableFromStack");
  303. return NO_ERROR;
  304. }
  305. //*****************************************************************************
  306. //
  307. // Name: GetIpStatsFromStack
  308. //
  309. // Description: Read the IPSNMPInfo structure from the stack.
  310. //
  311. // Parameters: IPSNMPInfo *IPSnmpInfo
  312. //
  313. // Returns: DWORD: NO_ERROR or some error code.
  314. //
  315. // History:
  316. //
  317. //*****************************************************************************
  318. DWORD
  319. GetIpStatsFromStack(IPSNMPInfo *IPSnmpInfo)
  320. {
  321. DWORD dwResult;
  322. DWORD dwInBufLen;
  323. DWORD dwOutBufLen;
  324. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  325. TDIObjectID *ID;
  326. BYTE *Context;
  327. TraceEnter("GetIpStatsFromStack");
  328. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  329. dwOutBufLen = sizeof(IPSNMPInfo);
  330. ID = &(trqiInBuf.ID);
  331. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  332. ID->toi_entity.tei_instance = 0;
  333. ID->toi_class = INFO_CLASS_PROTOCOL;
  334. ID->toi_type = INFO_TYPE_PROVIDER;
  335. ID->toi_id = IP_MIB_STATS_ID;
  336. Context = &(trqiInBuf.Context[0]);
  337. ZeroMemory(Context, CONTEXT_SIZE);
  338. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  339. &trqiInBuf,
  340. &dwInBufLen,
  341. IPSnmpInfo,
  342. &dwOutBufLen);
  343. if (dwResult isnot NO_ERROR)
  344. {
  345. Trace1(ERR,
  346. "GetIpStatsFromStack: NtStatus %x querying IpStats from stack",
  347. dwResult);
  348. TraceLeave("GetIpStatsFromStack");
  349. return dwResult;
  350. }
  351. TraceLeave("GetIpStatsFromStack");
  352. return NO_ERROR;
  353. }
  354. DWORD
  355. SetIpInfoToStack(IPSNMPInfo *ipsiInfo)
  356. {
  357. TCP_REQUEST_SET_INFORMATION_EX *lptrsiInBuf;
  358. TDIObjectID *ID;
  359. UCHAR *Context;
  360. IPSNMPInfo *copyInfo;
  361. DWORD dwInBufLen,dwOutBufLen,dwResult;
  362. TraceEnter("SetIpInfoToStack");
  363. dwInBufLen = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IPSNMPInfo) - 1;
  364. lptrsiInBuf = HeapAlloc(GetProcessHeap(),0,dwInBufLen);
  365. if(lptrsiInBuf is NULL)
  366. {
  367. dwResult = GetLastError();
  368. Trace1(ERR,
  369. "SetIpInfoToStack: Error %d allocating memory",
  370. dwResult);
  371. TraceLeave("SetIpInfoToStack");
  372. return dwResult;
  373. }
  374. ID = &lptrsiInBuf->ID;
  375. ID->toi_class = INFO_CLASS_PROTOCOL;
  376. ID->toi_type = INFO_TYPE_PROVIDER;
  377. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  378. ID->toi_id = IP_MIB_STATS_ID;
  379. ID->toi_entity.tei_instance = 0;
  380. copyInfo = (IPSNMPInfo*)lptrsiInBuf->Buffer;
  381. *copyInfo = *ipsiInfo;
  382. dwResult = TCPSetInformationEx(g_hTcpDevice,
  383. (LPVOID)lptrsiInBuf,
  384. &dwInBufLen,
  385. NULL,
  386. &dwOutBufLen);
  387. TraceLeave("SetIpInfoToStack");
  388. return dwResult;
  389. }
  390. //*****************************************************************************
  391. //
  392. // Name: GetIcmpStatsFromStack
  393. //
  394. // Description: Read the ICMPSNMPInfo structure from the stack.
  395. //
  396. // Parameters: ICMPSNMPInfo *ICMPSnmpInfo
  397. //
  398. // Returns: DWORD: NO_ERROR or some error code.
  399. //
  400. // History:
  401. //
  402. //*****************************************************************************
  403. DWORD
  404. GetIcmpStatsFromStack( ICMPSNMPInfo *ICMPSnmpInfo )
  405. {
  406. DWORD dwResult;
  407. DWORD dwInBufLen;
  408. DWORD dwOutBufLen;
  409. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  410. TDIObjectID *ID;
  411. BYTE *Context;
  412. TraceEnter("GetIcmpStatsFromStack");
  413. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  414. dwOutBufLen = sizeof(ICMPSNMPInfo);
  415. ID = &(trqiInBuf.ID);
  416. ID->toi_entity.tei_entity = ER_ENTITY;
  417. ID->toi_entity.tei_instance = 0;
  418. ID->toi_class = INFO_CLASS_PROTOCOL;
  419. ID->toi_type = INFO_TYPE_PROVIDER;
  420. ID->toi_id = ICMP_MIB_STATS_ID;
  421. Context = &(trqiInBuf.Context[0]);
  422. ZeroMemory(Context,CONTEXT_SIZE);
  423. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  424. &trqiInBuf,
  425. &dwInBufLen,
  426. ICMPSnmpInfo,
  427. &dwOutBufLen );
  428. if (dwResult isnot NO_ERROR)
  429. {
  430. Trace1(ERR,
  431. "GetIcmpStatsFromStack: NtStatus %x querying IcmpStats from stack",
  432. dwResult);
  433. TraceLeave("GetIcmpStatsFromStack");
  434. return dwResult;
  435. }
  436. TraceLeave("GetIcmpStatsFromStack");
  437. return NO_ERROR;
  438. }
  439. //*****************************************************************************
  440. //
  441. // Name: GetUdpStatsFromStack
  442. //
  443. // Description: Read the UDPStats structure from the stack.
  444. //
  445. // Parameters: UDPStats *UdpInfo
  446. //
  447. // Returns: DWORD: NO_ERROR or some error code.
  448. //
  449. // History:
  450. //
  451. //*****************************************************************************
  452. DWORD
  453. GetUdpStatsFromStack(UDPStats *UdpInfo)
  454. {
  455. DWORD dwResult;
  456. DWORD dwInBufLen;
  457. DWORD dwOutBufLen;
  458. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  459. TDIObjectID *ID;
  460. BYTE *Context;
  461. TraceEnter("GetUdpStatsFromStack");
  462. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  463. dwOutBufLen = sizeof(UDPStats);
  464. ID = &(trqiInBuf.ID);
  465. ID->toi_entity.tei_entity = CL_TL_ENTITY;
  466. ID->toi_entity.tei_instance = 0;
  467. ID->toi_class = INFO_CLASS_PROTOCOL;
  468. ID->toi_type = INFO_TYPE_PROVIDER;
  469. ID->toi_id = UDP_MIB_STAT_ID;
  470. Context = &(trqiInBuf.Context[0]);
  471. ZeroMemory( Context, CONTEXT_SIZE );
  472. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  473. &trqiInBuf,
  474. &dwInBufLen,
  475. UdpInfo,
  476. &dwOutBufLen );
  477. if(dwResult isnot NO_ERROR)
  478. {
  479. Trace1(ERR,
  480. "GetUdpStatsFromStack: NtStatus %x querying UdpStats from stack",
  481. dwResult);
  482. TraceLeave("GetUdpStatsFromStack");
  483. return dwResult;
  484. }
  485. TraceLeave("GetUdpStatsFromStack");
  486. return NO_ERROR;
  487. }
  488. //*****************************************************************************
  489. //
  490. // Name: GetTCPStats
  491. //
  492. // Description: Read the TCPStats structure from the stack.
  493. //
  494. // Parameters:
  495. //
  496. // Returns: DWORD: NO_ERROR or some error code.
  497. //
  498. // History:
  499. //
  500. //*****************************************************************************
  501. DWORD
  502. GetTcpStatsFromStack(TCPStats *TcpInfo)
  503. {
  504. DWORD dwResult;
  505. DWORD dwInBufLen;
  506. DWORD dwOutBufLen;
  507. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  508. TDIObjectID *ID;
  509. BYTE *Context;
  510. TraceEnter("GetTcpStatsFromStack");
  511. dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX );
  512. dwOutBufLen = sizeof( TCPStats );
  513. ID = &(trqiInBuf.ID);
  514. ID->toi_entity.tei_entity = CO_TL_ENTITY;
  515. ID->toi_entity.tei_instance = 0;
  516. ID->toi_class = INFO_CLASS_PROTOCOL;
  517. ID->toi_type = INFO_TYPE_PROVIDER;
  518. ID->toi_id = TCP_MIB_STAT_ID;
  519. Context = &(trqiInBuf.Context[0]);
  520. ZeroMemory(Context,CONTEXT_SIZE);
  521. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  522. &trqiInBuf,
  523. &dwInBufLen,
  524. TcpInfo,
  525. &dwOutBufLen );
  526. if(dwResult isnot NO_ERROR)
  527. {
  528. Trace1(ERR,
  529. "GetTcpStatsFromStack: NtStatus %x querying TcpStats from stack",
  530. dwResult);
  531. TraceLeave("GetTcpStatsFromStack");
  532. return dwResult;
  533. }
  534. TraceLeave("GetTcpStatsFromStack");
  535. return NO_ERROR;
  536. }
  537. //*****************************************************************************
  538. //
  539. // Name: GetRouteTableFromStack
  540. //
  541. // Description: Reads all the routes from the stack. This is needed because the ICMP redirect
  542. // routes are only kept in the stack and cant be queried from RTM
  543. //
  544. // Parameters:
  545. //
  546. // Returns: DWORD: NO_ERROR or some error code.
  547. //
  548. // History:
  549. //
  550. //*****************************************************************************
  551. DWORD
  552. GetIpRouteTableFromStack(IPRouteEntry *lpireTable,LPDWORD lpdwNumEntries, BOOL bOrder)
  553. {
  554. DWORD dwResult;
  555. DWORD dwInBufLen;
  556. DWORD dwOutBufLen;
  557. UCHAR *Context;
  558. TDIObjectID *ID;
  559. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  560. IPSNMPInfo ipsiInfo;
  561. TraceEnter("GetIpRouteTableFromStack");
  562. dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX );
  563. dwOutBufLen = *lpdwNumEntries * sizeof(IPRouteEntry);
  564. ID = &(trqiInBuf.ID);
  565. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  566. ID->toi_entity.tei_instance = 0;
  567. ID->toi_class = INFO_CLASS_PROTOCOL;
  568. ID->toi_type = INFO_TYPE_PROVIDER;
  569. ID->toi_id = IP_MIB_RTTABLE_ENTRY_ID;
  570. Context = &(trqiInBuf.Context[0]);
  571. ZeroMemory( Context, CONTEXT_SIZE );
  572. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  573. &trqiInBuf,
  574. &dwInBufLen,
  575. (LPVOID)lpireTable,
  576. &dwOutBufLen );
  577. if(dwResult isnot NO_ERROR)
  578. {
  579. Trace1(ERR,
  580. "GetIpRouteTableFromStack: NtStatus %x querying IpRouteTable from stack",
  581. dwResult);
  582. TraceLeave("GetIpRouteTableFromStack");
  583. return dwResult;
  584. }
  585. *lpdwNumEntries = (dwOutBufLen / sizeof( IPRouteEntry ));
  586. if((*lpdwNumEntries > 0) and bOrder)
  587. {
  588. DWORD i,j;
  589. for (i = 0; i < (*lpdwNumEntries) - 1; i++ )
  590. {
  591. IPRouteEntry tempEntry;
  592. DWORD min;
  593. LONG lCompare;
  594. min = i;
  595. for (j = i + 1; j < *lpdwNumEntries; j++ )
  596. {
  597. if(InetCmp(lpireTable[min].ire_dest,lpireTable[j].ire_dest,lCompare) > 0)
  598. {
  599. min = j;
  600. }
  601. }
  602. if(min isnot i)
  603. {
  604. tempEntry = lpireTable[min];
  605. lpireTable[min] = lpireTable[i];
  606. lpireTable[i] = tempEntry;
  607. }
  608. }
  609. }
  610. TraceLeave("GetIpRouteTableFromStack");
  611. return NO_ERROR;
  612. }
  613. //*****************************************************************************
  614. //
  615. // Name: GetARPEntityTable
  616. //
  617. // Description: Builds a list of AT entities. that support ARP. Keeps it in the global
  618. // entity table
  619. //
  620. // Parameters:
  621. //
  622. // Returns: DWORD: NO_ERROR or some error code.
  623. //
  624. // History:
  625. //
  626. //*****************************************************************************
  627. DWORD
  628. GetArpEntTableFromStack(DWORD **lpArpEntTable,
  629. LPDWORD lpdwSize,
  630. LPDWORD lpdwValid,
  631. HANDLE hHeap)
  632. {
  633. DWORD dwResult;
  634. DWORD dwInBufLen;
  635. DWORD dwOutBufLen;
  636. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  637. DWORD dwATType;
  638. UCHAR *Context;
  639. TDIObjectID *ID;
  640. LPVOID lpOutBuf;
  641. TDIEntityID *lpEntTable;
  642. DWORD dwNumEntities;
  643. DWORD i,dwCount ;
  644. TraceEnter("GetArpEntTableFromStack");
  645. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  646. dwOutBufLen = MAX_TDI_ENTITIES * sizeof(TDIEntityID);
  647. lpOutBuf = HeapAlloc(GetProcessHeap(),0,dwOutBufLen);
  648. ID = &(trqiInBuf.ID);
  649. ID->toi_entity.tei_entity = GENERIC_ENTITY;
  650. ID->toi_entity.tei_instance = 0;
  651. ID->toi_class = INFO_CLASS_GENERIC;
  652. ID->toi_type = INFO_TYPE_PROVIDER;
  653. ID->toi_id = ENTITY_LIST_ID;
  654. Context = &(trqiInBuf.Context[0]);
  655. ZeroMemory(Context, CONTEXT_SIZE);
  656. if(lpOutBuf is NULL)
  657. {
  658. dwResult = GetLastError();
  659. Trace1(ERR,"GetArpEntTableFromStack: Error %d allocating memory",
  660. dwResult);
  661. TraceLeave("GetArpEntTableFromStack");
  662. return dwResult;
  663. }
  664. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  665. &trqiInBuf,
  666. &dwInBufLen,
  667. lpOutBuf,
  668. &dwOutBufLen);
  669. if ( dwResult != NO_ERROR )
  670. {
  671. Trace1(ERR,
  672. "GetArpEntTableFromStack: NtStatus %x querying TDI Entities from stack",
  673. dwResult);
  674. HeapFree(GetProcessHeap(),0,lpOutBuf);
  675. TraceLeave("GetArpEntTableFromStack");
  676. return dwResult;
  677. }
  678. //
  679. // Now we have all the entities
  680. //
  681. dwNumEntities = dwOutBufLen / sizeof( TDIEntityID );
  682. dwCount = 0;
  683. lpEntTable = (TDIEntityID*)lpOutBuf;
  684. for(i = 0; i < dwNumEntities; i++)
  685. {
  686. //
  687. // See which ones are AT
  688. //
  689. if(lpEntTable[i].tei_entity is AT_ENTITY)
  690. {
  691. //
  692. // Query the entity to see if it supports ARP
  693. //
  694. ID->toi_entity.tei_entity = AT_ENTITY;
  695. ID->toi_class = INFO_CLASS_GENERIC;
  696. ID->toi_type = INFO_TYPE_PROVIDER;
  697. ID->toi_id = ENTITY_TYPE_ID;
  698. ID->toi_entity.tei_instance = lpEntTable[i].tei_instance;
  699. dwOutBufLen = sizeof(dwATType);
  700. ZeroMemory(Context,CONTEXT_SIZE);
  701. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  702. &trqiInBuf,
  703. &dwInBufLen,
  704. (LPVOID)&dwATType,
  705. &dwOutBufLen );
  706. if(dwResult is STATUS_INVALID_DEVICE_REQUEST)
  707. {
  708. continue;
  709. }
  710. if(dwResult isnot NO_ERROR)
  711. {
  712. HeapFree(GetProcessHeap(),0,lpOutBuf);
  713. return dwResult;
  714. }
  715. if(dwATType is AT_ARP)
  716. {
  717. if(dwCount is *lpdwSize)
  718. {
  719. //
  720. // Realloc more memory
  721. //
  722. *lpArpEntTable = (LPDWORD)HeapReAlloc(hHeap,
  723. 0,
  724. (LPVOID)*lpArpEntTable,
  725. ((*lpdwSize)<<1)*sizeof(DWORD));
  726. if(*lpArpEntTable is NULL)
  727. {
  728. dwResult = GetLastError();
  729. Trace1(ERR,
  730. "GetArpEntTableFromStack: Error %d reallocating memory",
  731. dwResult);
  732. TraceLeave("GetArpEntTableFromStack");
  733. return dwResult;
  734. }
  735. *lpdwSize = (*lpdwSize)<<1;
  736. }
  737. (*lpArpEntTable)[dwCount++] = lpEntTable[i].tei_instance;
  738. }
  739. }
  740. }
  741. *lpdwValid = dwCount;
  742. HeapFree(GetProcessHeap(),0,lpOutBuf);
  743. TraceLeave("GetArpEntTableFromStack");
  744. return NO_ERROR;
  745. }
  746. // Called only if you are a IPNET reader
  747. DWORD
  748. UpdateAdapterToATInstanceMap()
  749. {
  750. DWORD dwResult;
  751. DWORD dwInBufLen;
  752. DWORD i;
  753. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  754. TDIObjectID *ID;
  755. UCHAR *Context;
  756. DWORD dwSize;
  757. AddrXlatInfo AXI;
  758. TraceEnter("UpdateAdapterToATInstanceMap");
  759. dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX );
  760. Context = &(trqiInBuf.Context[0]);
  761. ID = &(trqiInBuf.ID);
  762. //
  763. // Maybe we should first clear out all the mappings
  764. //
  765. for (i = 0; i < g_IpInfo.dwValidArpEntEntries; i++ )
  766. {
  767. ID->toi_entity.tei_entity = AT_ENTITY;
  768. ID->toi_type = INFO_TYPE_PROVIDER;
  769. ID->toi_class = INFO_CLASS_PROTOCOL;
  770. ID->toi_id = AT_MIB_ADDRXLAT_INFO_ID;
  771. ID->toi_entity.tei_instance = g_IpInfo.arpEntTable[i];
  772. dwSize = sizeof(AXI);
  773. ZeroMemory(Context, CONTEXT_SIZE);
  774. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  775. &trqiInBuf,
  776. &dwInBufLen,
  777. &AXI,
  778. &dwSize );
  779. if(dwResult isnot NO_ERROR)
  780. {
  781. Trace1(ERR,
  782. "UpdateAdapterToATInstanceMap: NtStatus %x querying ArpInfo from stack",
  783. dwResult);
  784. TraceLeave("UpdateAdapterToATInstanceMap");
  785. return dwResult;
  786. }
  787. StoreAdapterToATInstanceMap(AXI.axi_index,g_IpInfo.arpEntTable[i]);
  788. }
  789. TraceLeave("UpdateAdapterToATInstanceMap");
  790. return NO_ERROR;
  791. }
  792. DWORD
  793. GetIpNetTableFromStackEx(LPDWORD arpEntTable,
  794. DWORD dwValidArpEntEntries,
  795. IPNetToMediaEntry **lpNetTable,
  796. LPDWORD lpdwTotalEntries,
  797. LPDWORD lpdwValidEntries,
  798. BOOL bOrder,
  799. HANDLE hHeap)
  800. {
  801. DWORD dwResult;
  802. DWORD dwInBufLen;
  803. DWORD dwOutBufLen;
  804. DWORD i,j;
  805. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  806. TDIObjectID *ID;
  807. UCHAR *Context;
  808. DWORD dwNetEntryCount,dwNumAdded,dwValidNetEntries;
  809. DWORD dwSize,dwNeed;
  810. AddrXlatInfo AXI;
  811. IPNetToMediaEntry *lpOutBuf,tempEntry;
  812. dwInBufLen = sizeof( TCP_REQUEST_QUERY_INFORMATION_EX );
  813. Context = &(trqiInBuf.Context[0]);
  814. ZeroMemory( Context, CONTEXT_SIZE );
  815. ID = &(trqiInBuf.ID);
  816. ID->toi_entity.tei_entity = AT_ENTITY;
  817. ID->toi_type = INFO_TYPE_PROVIDER;
  818. dwNetEntryCount = 0;
  819. for (i = 0; i < dwValidArpEntEntries; i++ )
  820. {
  821. // First add up the AXI counts
  822. ID->toi_class = INFO_CLASS_PROTOCOL;
  823. ID->toi_id = AT_MIB_ADDRXLAT_INFO_ID;
  824. ID->toi_entity.tei_instance = arpEntTable[i];
  825. dwSize = sizeof(AXI);
  826. ZeroMemory(Context, CONTEXT_SIZE);
  827. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  828. &trqiInBuf,
  829. &dwInBufLen,
  830. &AXI,
  831. &dwSize );
  832. if(dwResult isnot NO_ERROR)
  833. {
  834. Trace1(ERR,
  835. "GetIpNetTableFromStackEx: NtStatus %x querying information from stack",
  836. dwResult);
  837. TraceLeave("GetIpNetTableFromStackEx");
  838. return dwResult;
  839. }
  840. //
  841. // At this point map the index to the instance - the index is the adapter
  842. // index though the instance is not the same as IFInstance
  843. //
  844. StoreAdapterToATInstanceMap(AXI.axi_index,arpEntTable[i]);
  845. dwNetEntryCount += AXI.axi_count;
  846. }
  847. //
  848. // This is generally a memory hog
  849. //
  850. dwNeed = dwNetEntryCount + (dwValidArpEntEntries) * SPILLOVER;
  851. if(dwNeed > *lpdwTotalEntries)
  852. {
  853. if(*lpdwTotalEntries)
  854. {
  855. HeapFree(hHeap,0,*lpNetTable);
  856. }
  857. dwNeed += MAX_DIFF;
  858. //
  859. // Serialize the heap ???
  860. //
  861. *lpNetTable = (IPNetToMediaEntry*)HeapAlloc(hHeap,0,
  862. dwNeed*sizeof(IPNetToMediaEntry));
  863. if(*lpNetTable is NULL)
  864. {
  865. dwResult = GetLastError();
  866. Trace1(ERR,
  867. "GetIpNetTableFromStackEx: Error %d allocating memory for IpNetTable",
  868. dwResult);
  869. return ERROR_NOT_ENOUGH_MEMORY;
  870. }
  871. *lpdwTotalEntries = dwNeed;
  872. }
  873. else
  874. {
  875. dwNeed = *lpdwTotalEntries;
  876. }
  877. lpOutBuf = *lpNetTable;
  878. dwOutBufLen = dwNeed * sizeof(IPNetToMediaEntry);
  879. dwValidNetEntries = 0;
  880. for(i = 0; i < dwValidArpEntEntries; i++ )
  881. {
  882. ID->toi_class = INFO_CLASS_PROTOCOL;
  883. ID->toi_id = AT_MIB_ADDRXLAT_ENTRY_ID;
  884. ID->toi_entity.tei_instance = arpEntTable[i];
  885. ZeroMemory( Context, CONTEXT_SIZE );
  886. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  887. &trqiInBuf,
  888. &dwInBufLen,
  889. (LPVOID)lpOutBuf,
  890. &dwOutBufLen);
  891. if ( dwResult isnot NO_ERROR )
  892. {
  893. Trace1(ERR,
  894. "GetIpNetTableFromStackEx: Error %x getting AT Entry",
  895. dwResult);
  896. continue;
  897. }
  898. dwNumAdded = dwOutBufLen/(sizeof(IPNetToMediaEntry));
  899. lpOutBuf += dwNumAdded;
  900. dwValidNetEntries += dwNumAdded;
  901. dwOutBufLen = (dwNeed - dwValidNetEntries) * sizeof(IPNetToMediaEntry);
  902. }
  903. dwResult = NO_ERROR;
  904. *lpdwValidEntries = dwValidNetEntries;
  905. //
  906. // Now sort the net table
  907. //
  908. if(dwValidNetEntries > 0)
  909. {
  910. for(i = 0; i < dwValidNetEntries; i++)
  911. {
  912. (*lpNetTable)[i].inme_index = GetInterfaceFromAdapter((*lpNetTable)[i].inme_index);
  913. }
  914. if(bOrder)
  915. {
  916. for(i = 0; i < dwValidNetEntries - 1; i++)
  917. {
  918. DWORD min = i;
  919. for(j = i + 1; j < dwValidNetEntries; j++)
  920. {
  921. if(IpNetCmp((*lpNetTable)[min].inme_index,(*lpNetTable)[min].inme_addr,
  922. (*lpNetTable)[j].inme_index,(*lpNetTable)[j].inme_addr) > 0)
  923. {
  924. min = j;
  925. }
  926. }
  927. if(min isnot i)
  928. {
  929. tempEntry = (*lpNetTable)[min];
  930. (*lpNetTable)[min] = (*lpNetTable)[i];
  931. (*lpNetTable)[i] = tempEntry;
  932. }
  933. }
  934. }
  935. }
  936. TraceLeave("GetIpNetTableFromStackEx");
  937. return dwResult;
  938. }
  939. DWORD
  940. SetIpNetEntryToStack(IPNetToMediaEntry *inmeEntry, DWORD dwInstance)
  941. {
  942. TCP_REQUEST_SET_INFORMATION_EX *lptrsiInBuf;
  943. TDIObjectID *ID;
  944. UCHAR *Context;
  945. IPNetToMediaEntry *copyInfo;
  946. DWORD dwInBufLen,dwOutBufLen,dwResult;
  947. TraceEnter("SetIpNetEntryToStack");
  948. dwInBufLen = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IPNetToMediaEntry) - 1;
  949. lptrsiInBuf = HeapAlloc(GetProcessHeap(),0,dwInBufLen);
  950. if(lptrsiInBuf is NULL)
  951. {
  952. dwResult = GetLastError();
  953. Trace1(ERR,
  954. "SetIpNetEntryToStack: Error %d allocating memory",
  955. dwResult);
  956. return dwResult;
  957. }
  958. ID = &lptrsiInBuf->ID;
  959. ID->toi_class = INFO_CLASS_PROTOCOL;
  960. ID->toi_entity.tei_entity = AT_ENTITY;
  961. ID->toi_type = INFO_TYPE_PROVIDER;
  962. ID->toi_id = AT_MIB_ADDRXLAT_ENTRY_ID;
  963. ID->toi_entity.tei_instance = dwInstance;
  964. //
  965. // Since IPNetToMediaEntry is a fixed size structure
  966. //
  967. copyInfo = (IPNetToMediaEntry*)lptrsiInBuf->Buffer;
  968. *copyInfo = *inmeEntry;
  969. dwResult = TCPSetInformationEx(g_hTcpDevice,
  970. (LPVOID)lptrsiInBuf,
  971. &dwInBufLen,
  972. NULL,
  973. &dwOutBufLen);
  974. TraceLeave("SetIpNetEntryToStack");
  975. return dwResult;
  976. }
  977. DWORD
  978. UpdateAdapterToIFInstanceMap()
  979. {
  980. IPSNMPInfo ipsiInfo;
  981. DWORD dwResult;
  982. DWORD dwOutBufLen;
  983. DWORD dwInBufLen;
  984. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  985. TDIObjectID *ID;
  986. IFEntry *maxIfEntry;
  987. BYTE *Context;
  988. DWORD dwCount,i;
  989. TraceEnter("UpdateAdapterToIFInstanceMap");
  990. dwResult = GetIpStatsFromStack(&ipsiInfo);
  991. if(dwResult isnot NO_ERROR)
  992. {
  993. Trace1(ERR,
  994. "UpdateAdapterToIFInstanceMap: NtStatus %x querying IpSnmpInfo from stack to determine number if interface",
  995. dwResult);
  996. TraceLeave("UpdateAdapterToIFInstanceMap");
  997. return dwResult;
  998. }
  999. dwOutBufLen = sizeof(MIB_IFROW) - FIELD_OFFSET(MIB_IFROW, dwIndex);
  1000. if((maxIfEntry = (IFEntry*)HeapAlloc(GetProcessHeap(),
  1001. 0,
  1002. dwOutBufLen)) is NULL)
  1003. {
  1004. dwResult = GetLastError();
  1005. Trace1(ERR,
  1006. "UpdateAdapterToIFInstanceMap: Error %d allocating memory",
  1007. dwResult);
  1008. TraceLeave("UpdateAdapterToIFInstanceMap");
  1009. return ERROR_NOT_ENOUGH_MEMORY;
  1010. }
  1011. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  1012. ID = &(trqiInBuf.ID);
  1013. Context = &(trqiInBuf.Context[0]);
  1014. ID->toi_entity.tei_entity = IF_ENTITY;
  1015. ID->toi_class = INFO_CLASS_PROTOCOL;
  1016. ID->toi_type = INFO_TYPE_PROVIDER;
  1017. ID->toi_id = IF_MIB_STATS_ID;
  1018. //
  1019. // Read the interface entry items
  1020. //
  1021. for ( i = 0; i < ipsiInfo.ipsi_numif ; i++ )
  1022. {
  1023. dwOutBufLen = sizeof(MIB_IFROW) - FIELD_OFFSET(MIB_IFROW, dwIndex);
  1024. ID->toi_entity.tei_instance = i;
  1025. ZeroMemory(Context,CONTEXT_SIZE);
  1026. dwResult = TCPQueryInformationEx(g_hTcpDevice,
  1027. &trqiInBuf,
  1028. &dwInBufLen,
  1029. (LPVOID)maxIfEntry,
  1030. &dwOutBufLen);
  1031. if (dwResult isnot NO_ERROR)
  1032. {
  1033. Trace1(ERR,
  1034. "UpdateAdapterToIFInstanceMap: NtStatus %x getting IFRow from stack",
  1035. dwResult);
  1036. continue;
  1037. }
  1038. StoreAdapterToIFInstanceMap(maxIfEntry->if_index,i);
  1039. }
  1040. HeapFree(GetProcessHeap(),0,maxIfEntry);
  1041. TraceLeave("UpdateAdapterToIFInstanceMap");
  1042. return NO_ERROR;
  1043. }
  1044. //* TCPQueryInformationEx
  1045. //
  1046. // Description: Get information from the stack.
  1047. //
  1048. // Parameters: HANDLE hHandle: handle to the stack.
  1049. // TDIObjectID *ID: pointer to TDIObjectID info.
  1050. // void *Buffer: buffer to receive data from the stack.
  1051. // ulong *Bufferlen: IN: tells stack size of available buffer,
  1052. // OUT: tells us how much data is available.
  1053. // CONTEXT *Context: allows queries spanning more than one call.
  1054. //
  1055. // Returns: int:
  1056. //
  1057. //*
  1058. int
  1059. TCPQueryInformationEx( HANDLE hHandle,
  1060. void *InBuf,
  1061. ulong *InBufLen,
  1062. void *OutBuf,
  1063. ulong *OutBufLen )
  1064. {
  1065. NTSTATUS Status;
  1066. IO_STATUS_BLOCK IoStatusBlock;
  1067. TraceEnter("TCPQueryInformationEx");
  1068. Status = NtDeviceIoControlFile( hHandle,
  1069. NULL,
  1070. NULL,
  1071. NULL,
  1072. &IoStatusBlock,
  1073. IOCTL_TCP_QUERY_INFORMATION_EX,
  1074. InBuf,
  1075. *InBufLen,
  1076. OutBuf,
  1077. *OutBufLen );
  1078. if ( Status == STATUS_PENDING )
  1079. {
  1080. Status = NtWaitForSingleObject( hHandle, FALSE, NULL );
  1081. Status = IoStatusBlock.Status;
  1082. }
  1083. if ( !NT_SUCCESS( Status ) )
  1084. {
  1085. Trace1(ERR,
  1086. "TCPQueryInformationEx: NtStatus %x from NtDeviceIoControlFile",
  1087. Status);
  1088. *OutBufLen = 0;
  1089. TraceLeave("TCPQueryInformationEx");
  1090. return Status;
  1091. }
  1092. //
  1093. // Tell caller how much was written
  1094. //
  1095. *OutBufLen = IoStatusBlock.Information;
  1096. TraceLeave("TCPQueryInformationEx");
  1097. return NO_ERROR;
  1098. }
  1099. //* TCPSetInformationEx()
  1100. //
  1101. // Description: Send information to the stack
  1102. //
  1103. // Parameters: HANDLE hHandle: handle to the stack.
  1104. // TDIObjectID *ID: pointer to TDIObjectID info.
  1105. // void *Buffer: buffer to receive data from the stack.
  1106. // ulong Bufferlen: tells stack size of available buffer,
  1107. //
  1108. // Returns: int:
  1109. //
  1110. //*
  1111. int
  1112. TCPSetInformationEx(HANDLE hHandle,
  1113. void *InBuf,
  1114. ULONG *InBufLen,
  1115. void *OutBuf,
  1116. ULONG *OutBufLen )
  1117. {
  1118. NTSTATUS Status;
  1119. IO_STATUS_BLOCK IoStatusBlock;
  1120. TraceEnter("TCPSetInformationEx");
  1121. Status = NtDeviceIoControlFile(hHandle,
  1122. NULL,
  1123. NULL,
  1124. NULL,
  1125. &IoStatusBlock,
  1126. IOCTL_TCP_SET_INFORMATION_EX,
  1127. InBuf,
  1128. *InBufLen,
  1129. OutBuf,
  1130. *OutBufLen );
  1131. if ( Status == STATUS_PENDING )
  1132. {
  1133. Status = NtWaitForSingleObject(hHandle, FALSE, NULL );
  1134. Status = IoStatusBlock.Status;
  1135. }
  1136. if ( !NT_SUCCESS( Status ) )
  1137. {
  1138. Trace1(ERR,
  1139. "TCPSetInformationEx: NtStatus %x from NtDeviceIoControlFile",
  1140. Status);
  1141. TraceLeave("TCPSetInformationEx");
  1142. return Status;
  1143. }
  1144. TraceLeave("TCPSetInformationEx");
  1145. return NO_ERROR;
  1146. }