Leaked source code of windows server 2003
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.

409 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. stackex.c
  5. Abstract:
  6. Ex versions of GetTcpTableFromStack and GetUdpTableFromStack.
  7. These are used to get the owning process id associated with connections
  8. from the stack.
  9. Author:
  10. Shaun Cox (shaunco) 19-Feb-2000
  11. Revision History:
  12. --*/
  13. #include "inc.h"
  14. #pragma hdrstop
  15. int
  16. TCPQueryInformationEx(
  17. DWORD Family,
  18. void *InBuf,
  19. ulong *InBufLen,
  20. void *OutBuf,
  21. ulong *OutBufLen
  22. );
  23. DWORD
  24. GetTcpExTableFromStack(
  25. OUT TCP_EX_TABLE *pTcpTable,
  26. IN DWORD dwSize,
  27. IN BOOL bOrder,
  28. IN DWORD dwFamily
  29. )
  30. {
  31. DWORD dwInBufLen, dwOutBufLen, dwResult, dwEntryLen;
  32. TDIObjectID *ID;
  33. BYTE *Context;
  34. int (_cdecl *pfnCompare)(CONST VOID *pvElem1, CONST VOID *pvElem2);
  35. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  36. CheckTcpipState();
  37. if (dwFamily == AF_INET)
  38. {
  39. if (!g_bIpConfigured)
  40. {
  41. return ERROR_NOT_SUPPORTED;
  42. }
  43. dwEntryLen = sizeof(TCPConnTableEntryEx);
  44. pfnCompare = CompareTcpRow;
  45. dwOutBufLen = dwSize - FIELD_OFFSET(TCP_EX_TABLE, table[0]);
  46. }
  47. else if (dwFamily == AF_INET6)
  48. {
  49. if (!g_bIp6Configured)
  50. {
  51. return ERROR_NOT_SUPPORTED;
  52. }
  53. dwEntryLen = sizeof(TCP6ConnTableEntry);
  54. pfnCompare = CompareTcp6Row;
  55. dwOutBufLen = dwSize - FIELD_OFFSET(TCP6_EX_TABLE, table[0]);
  56. }
  57. else
  58. {
  59. return ERROR_INVALID_PARAMETER;
  60. }
  61. ID = &(trqiInBuf.ID);
  62. ID->toi_entity.tei_entity = CO_TL_ENTITY;
  63. ID->toi_entity.tei_instance = 0;
  64. ID->toi_class = INFO_CLASS_PROTOCOL;
  65. ID->toi_type = INFO_TYPE_PROVIDER;
  66. ID->toi_id = TCP_EX_TABLE_ID;
  67. Context = (BYTE *) &(trqiInBuf.Context[0]);
  68. ZeroMemory( Context, CONTEXT_SIZE );
  69. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  70. dwResult = TCPQueryInformationEx(dwFamily,
  71. &trqiInBuf,
  72. &dwInBufLen,
  73. (PVOID)(pTcpTable->table),
  74. &dwOutBufLen);
  75. if(dwResult isnot NO_ERROR)
  76. {
  77. Trace1(ERR,
  78. "GetTcpExTableFromStack: Couldnt query stack. Error %x",
  79. dwResult);
  80. return dwResult;
  81. }
  82. pTcpTable->dwNumEntries = (dwOutBufLen / dwEntryLen);
  83. if((pTcpTable->dwNumEntries > 0) and bOrder)
  84. {
  85. qsort(pTcpTable->table,
  86. pTcpTable->dwNumEntries,
  87. dwEntryLen,
  88. pfnCompare);
  89. }
  90. return NO_ERROR;
  91. }
  92. DWORD
  93. AllocateAndGetTcpExTableFromStack(
  94. OUT TCP_EX_TABLE **ppTcpTable,
  95. IN BOOL bOrder,
  96. IN HANDLE hHeap,
  97. IN DWORD dwFlags,
  98. IN DWORD dwFamily
  99. )
  100. {
  101. DWORD dwResult, dwCount, dwOutBufLen;
  102. MIB_TCPSTATS TcpInfo;
  103. DWORD dwEntryLen;
  104. *ppTcpTable = NULL;
  105. //
  106. // Find out the number of entries the stack has. It returns this as part of
  107. // the Tcp Stats. Also validate the dwFamily parameter.
  108. //
  109. dwResult = GetTcpStatsFromStackEx(&TcpInfo, dwFamily);
  110. if(dwResult isnot NO_ERROR)
  111. {
  112. Trace1(ERR,
  113. "AllocateAndGetTcpExTableFromStack: Couldnt get Tcp Stats From stack. Error %d",
  114. dwResult);
  115. return dwResult;
  116. }
  117. dwCount = TcpInfo.dwNumConns + OVERFLOW_COUNT;
  118. if (dwFamily == AF_INET)
  119. {
  120. dwEntryLen = sizeof(TCPConnTableEntryEx);
  121. dwOutBufLen = FIELD_OFFSET(TCP_EX_TABLE, table[0])
  122. + (dwCount * dwEntryLen)
  123. + ALIGN_SIZE;
  124. }
  125. else
  126. {
  127. dwEntryLen = sizeof(TCP6ConnTableEntry);
  128. dwOutBufLen = FIELD_OFFSET(TCP6_EX_TABLE, table[0])
  129. + (dwCount * dwEntryLen)
  130. + ALIGN_SIZE;
  131. }
  132. *ppTcpTable = HeapAlloc(hHeap, dwFlags, dwOutBufLen);
  133. if(*ppTcpTable is NULL)
  134. {
  135. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  136. Trace1(ERR,
  137. "AllocateAndGetTcpExTableFromStack: Couldnt allocate memory. Error %d",
  138. dwResult);
  139. return dwResult;
  140. }
  141. if(TcpInfo.dwNumConns is 0)
  142. {
  143. (*ppTcpTable)->dwNumEntries = 0;
  144. return NO_ERROR;
  145. }
  146. dwResult = GetTcpExTableFromStack(*ppTcpTable, dwOutBufLen, bOrder,
  147. dwFamily);
  148. if(dwResult isnot NO_ERROR)
  149. {
  150. Trace1(ERR,
  151. "AllocateAndGetTcpExTableFromStack: Error %d GetTcpExTableFromStack",
  152. dwResult);
  153. }
  154. return dwResult;
  155. }
  156. DWORD
  157. GetUdpExTableFromStack(
  158. OUT UDP_EX_TABLE *pUdpTable,
  159. IN DWORD dwSize,
  160. IN BOOL bOrder,
  161. IN DWORD dwFamily
  162. )
  163. {
  164. DWORD dwInBufLen, dwOutBufLen, dwResult;
  165. BYTE *Context;
  166. DWORD dwEntryLen;
  167. int (__cdecl *pfnCompare)(CONST VOID *pvElem1, CONST VOID *pvElem2);
  168. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  169. TDIObjectID *ID;
  170. CheckTcpipState();
  171. if (dwFamily == AF_INET)
  172. {
  173. if (!g_bIpConfigured)
  174. {
  175. return ERROR_NOT_SUPPORTED;
  176. }
  177. dwEntryLen = sizeof(UDPEntryEx);
  178. pfnCompare = CompareUdpRow;
  179. }
  180. else if (dwFamily == AF_INET6)
  181. {
  182. if (!g_bIp6Configured)
  183. {
  184. return ERROR_NOT_SUPPORTED;
  185. }
  186. dwEntryLen = sizeof(UDP6ListenerEntry);
  187. pfnCompare = CompareUdp6Row;
  188. }
  189. else
  190. {
  191. return ERROR_INVALID_PARAMETER;
  192. }
  193. ID = &(trqiInBuf.ID);
  194. ID->toi_entity.tei_entity = CL_TL_ENTITY;
  195. ID->toi_entity.tei_instance = 0;
  196. ID->toi_class = INFO_CLASS_PROTOCOL;
  197. ID->toi_type = INFO_TYPE_PROVIDER;
  198. ID->toi_id = UDP_EX_TABLE_ID;
  199. Context = (BYTE *) &(trqiInBuf.Context[0]);
  200. ZeroMemory( Context, CONTEXT_SIZE );
  201. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  202. dwOutBufLen = dwSize - FIELD_OFFSET(UDP6_LISTENER_TABLE, table[0]);
  203. dwResult = TCPQueryInformationEx(dwFamily,
  204. &trqiInBuf,
  205. &dwInBufLen,
  206. (PVOID)(pUdpTable->table),
  207. &dwOutBufLen);
  208. if(dwResult isnot NO_ERROR)
  209. {
  210. Trace1(ERR,
  211. "GetUdpExTableFromStack: Couldnt query TCP information. Error %d",
  212. dwResult);
  213. return dwResult;
  214. }
  215. pUdpTable->dwNumEntries = (dwOutBufLen / dwEntryLen);
  216. //
  217. // Now sort the UDP connection table. Keys are: local address, and local
  218. // port.
  219. //
  220. if((pUdpTable->dwNumEntries > 0) and bOrder)
  221. {
  222. qsort(pUdpTable->table,
  223. pUdpTable->dwNumEntries,
  224. dwEntryLen,
  225. pfnCompare);
  226. }
  227. TraceLeave("GetUdpExTableFromStack");
  228. return NO_ERROR;
  229. }
  230. DWORD
  231. AllocateAndGetUdpExTableFromStack(
  232. OUT UDP_EX_TABLE **ppUdpTable,
  233. IN BOOL bOrder,
  234. IN HANDLE hHeap,
  235. IN DWORD dwFlags,
  236. IN DWORD dwFamily
  237. )
  238. {
  239. DWORD dwResult, dwCount, dwOutBufLen;
  240. MIB_UDPSTATS UdpInfo;
  241. *ppUdpTable = NULL;
  242. //
  243. // Find out the number of entries the stack has. It returns this as part of
  244. // the Tcp Stats. Also validate the dwFamily parameter.
  245. //
  246. dwResult = GetUdpStatsFromStackEx(&UdpInfo, dwFamily);
  247. if(dwResult isnot NO_ERROR)
  248. {
  249. Trace1(ERR,
  250. "AllocateAndGetUdpExTableFromStack: Couldnt get Udp Stats From stack. Error %d",
  251. dwResult);
  252. return dwResult;
  253. }
  254. dwCount = UdpInfo.dwNumAddrs + OVERFLOW_COUNT;
  255. if (dwFamily == AF_INET)
  256. {
  257. dwOutBufLen = FIELD_OFFSET(UDP_EX_TABLE, table[0])
  258. + (dwCount * sizeof(UDPEntryEx))
  259. + ALIGN_SIZE;
  260. }
  261. else
  262. {
  263. dwOutBufLen = FIELD_OFFSET(UDP6_LISTENER_TABLE, table[0])
  264. + (dwCount * sizeof(UDP6ListenerEntry))
  265. + ALIGN_SIZE;
  266. }
  267. *ppUdpTable = HeapAlloc(hHeap, dwFlags, dwOutBufLen);
  268. if(*ppUdpTable is NULL)
  269. {
  270. dwResult = ERROR_NOT_ENOUGH_MEMORY;
  271. Trace1(ERR,
  272. "AllocateAndGetUdpExTableFromStack: Couldnt allocate memory. Error %d",
  273. dwResult);
  274. return dwResult;
  275. }
  276. if(UdpInfo.dwNumAddrs is 0)
  277. {
  278. (*ppUdpTable)->dwNumEntries = 0;
  279. return NO_ERROR;
  280. }
  281. dwResult = GetUdpExTableFromStack(*ppUdpTable, dwOutBufLen, bOrder,
  282. dwFamily);
  283. if(dwResult isnot NO_ERROR)
  284. {
  285. Trace1(ERR,
  286. "AllocateAndGetUdpExTableFromStack: Error %d GetUdpExTableFromStack",
  287. dwResult);
  288. }
  289. return dwResult;
  290. }
  291. DWORD
  292. GetBestInterfaceFromIpv6Stack(
  293. IN LPSOCKADDR_IN6 pSockAddr,
  294. OUT PDWORD pdwBestIfIndex
  295. )
  296. {
  297. DWORD dwOutBufLen, dwInBufLen, dwResult;
  298. CHAR byBuffer[FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context) +
  299. sizeof(TDI_ADDRESS_IP6)];
  300. TCP_REQUEST_QUERY_INFORMATION_EX *ptrqiInBuf = (TCP_REQUEST_QUERY_INFORMATION_EX *)byBuffer;
  301. IP6RouteEntry Ire;
  302. TDIObjectID *ID;
  303. ID = &(ptrqiInBuf->ID);
  304. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  305. ID->toi_entity.tei_instance = 0;
  306. ID->toi_class = INFO_CLASS_PROTOCOL;
  307. ID->toi_type = INFO_TYPE_PROVIDER;
  308. ID->toi_id = IP6_GET_BEST_ROUTE_ID;
  309. RtlCopyMemory((PVOID)ptrqiInBuf->Context, &pSockAddr->sin6_port,
  310. TDI_ADDRESS_LENGTH_IP6);
  311. dwInBufLen = sizeof(byBuffer);
  312. dwOutBufLen = sizeof(Ire);
  313. dwResult = TCPQueryInformationEx(AF_INET6,
  314. ptrqiInBuf,
  315. &dwInBufLen,
  316. (PVOID)&Ire,
  317. &dwOutBufLen);
  318. if (dwResult isnot NO_ERROR)
  319. {
  320. Trace1(ERR,"Couldn't query IPv6 stack. Error %d", dwResult);
  321. TraceLeave("GetBestInterfaceEx");
  322. return dwResult;
  323. }
  324. *pdwBestIfIndex = Ire.ire_IfIndex;
  325. return dwResult;
  326. }