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.

334 lines
7.7 KiB

  1. //============================================================================
  2. // Copyright (c) 1995, Microsoft Corporation
  3. //
  4. // File: update.c
  5. //
  6. // History:
  7. // Abolade Gbadegesin July-24-1995 Created
  8. //
  9. // Routing table update thread
  10. //============================================================================
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <time.h>
  14. #include <ctype.h>
  15. #ifndef CHICAGO
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #endif
  20. #include <windows.h>
  21. #include <string.h>
  22. #include <malloc.h>
  23. #include <io.h>
  24. #include <winsvc.h>
  25. #include "ipinfo.h"
  26. #include "llinfo.h"
  27. #include "ntddtcp.h"
  28. #include "tdiinfo.h"
  29. #include "routetab.h"
  30. #include "rtdefs.h"
  31. #define POS_DHCP 0
  32. #define POS_EXIT 1
  33. #define POS_LAST 2
  34. //----------------------------------------------------------------------------
  35. // Function: RTUpdateThread
  36. //
  37. // This is the main function for the background thread which is responsible
  38. // for updating our tables of interfaces and addresses whenever DHCP
  39. // notifies us of an address change.
  40. //----------------------------------------------------------------------------
  41. DWORD
  42. RTUpdateThread(
  43. LPVOID lpvParam
  44. )
  45. {
  46. DWORD dwErr;
  47. HMODULE hmodule;
  48. HANDLE hEvents[POS_LAST];
  49. //
  50. // Save the module-handle, which is passed to us
  51. // as the thread-parameter
  52. //
  53. hmodule = (HMODULE)lpvParam;
  54. //
  55. // set up the event array for waiting
  56. //
  57. hEvents[POS_DHCP] = g_rtCfg.hDHCPEvent;
  58. hEvents[POS_EXIT] = g_rtCfg.hUpdateThreadExit;
  59. while(TRUE) {
  60. dwErr = WaitForMultipleObjects(POS_LAST, hEvents, FALSE, INFINITE);
  61. //
  62. // wait returned, find out why
  63. //
  64. if (dwErr == POS_EXIT) { break; }
  65. else
  66. if (dwErr == POS_DHCP) {
  67. //
  68. // an IP address changed.
  69. // we reload the interface table and IP address table
  70. // and signal the attached application
  71. //
  72. RT_LOCK();
  73. if (g_rtCfg.lpIfTable != NULL) {
  74. HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIfTable);
  75. g_rtCfg.lpIfTable = NULL;
  76. }
  77. if (g_rtCfg.lpIPAddressTable != NULL) {
  78. HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIPAddressTable);
  79. g_rtCfg.lpIPAddressTable = NULL;
  80. }
  81. //
  82. // reload the tables
  83. //
  84. dwErr = RTGetTables(
  85. &g_rtCfg.lpIfTable, &g_rtCfg.dwIfCount,
  86. &g_rtCfg.lpIPAddressTable, &g_rtCfg.dwIPAddressCount
  87. );
  88. if (dwErr != 0) { RT_UNLOCK(); break; }
  89. //
  90. // signal the application if it has requested notification
  91. //
  92. if (g_rtCfg.hUserNotifyEvent != NULL) {
  93. SetEvent(g_rtCfg.hUserNotifyEvent);
  94. }
  95. RT_UNLOCK();
  96. }
  97. }
  98. //
  99. // Clean up the resources we're using
  100. //
  101. RTCleanUp();
  102. //
  103. // Unload the library and exit; this call never returns
  104. //
  105. FreeLibraryAndExitThread(hmodule, 0);
  106. return 0;
  107. }
  108. DWORD
  109. RTGetTables(
  110. LPIF_ENTRY* lplpIfTable,
  111. LPDWORD lpdwIfCount,
  112. LPIPADDRESS_ENTRY* lplpAddrTable,
  113. LPDWORD lpdwAddrCount
  114. )
  115. {
  116. ULONG_PTR *lpContext;
  117. IPSNMPInfo ipsiInfo;
  118. TDIObjectID *lpObject;
  119. DWORD dwErr, dwInSize, dwOutSize;
  120. TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
  121. //
  122. // first get interface and address count
  123. //
  124. dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  125. dwOutSize = sizeof(IPSNMPInfo);
  126. lpContext = trqiBuffer.Context;
  127. ZeroMemory(lpContext, CONTEXT_SIZE);
  128. lpObject = &trqiBuffer.ID;
  129. lpObject->toi_id = IP_MIB_STATS_ID;
  130. lpObject->toi_type = INFO_TYPE_PROVIDER;
  131. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  132. lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
  133. lpObject->toi_entity.tei_instance = 0;
  134. dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize,
  135. &ipsiInfo, &dwOutSize);
  136. if (dwErr != NO_ERROR || ipsiInfo.ipsi_numaddr == 0) {
  137. return dwErr;
  138. }
  139. // save the interface and address counts
  140. //
  141. *lpdwIfCount = ipsiInfo.ipsi_numif;
  142. *lpdwAddrCount = ipsiInfo.ipsi_numaddr;
  143. // now get the interface table and address table
  144. //
  145. dwErr = RTGetIfTable(lplpIfTable, lpdwIfCount);
  146. if (dwErr == 0) {
  147. dwErr = RTGetAddrTable(lplpAddrTable, lpdwAddrCount);
  148. }
  149. return dwErr;
  150. }
  151. DWORD
  152. RTGetIfTable(
  153. LPIF_ENTRY* lplpIfTable,
  154. LPDWORD lpdwIfCount
  155. )
  156. {
  157. LPIF_ENTRY lpIfTable, lpif;
  158. ULONG_PTR *lpContext;
  159. TDIObjectID *lpObject;
  160. DWORD dwErr, dwi, dwInSize, dwOutSize;
  161. TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
  162. if (*lpdwIfCount == 0) {
  163. return ERROR_INVALID_PARAMETER;
  164. }
  165. dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  166. lpContext = trqiBuffer.Context;
  167. lpObject = &trqiBuffer.ID;
  168. lpObject->toi_id = IF_MIB_STATS_ID;
  169. lpObject->toi_type = INFO_TYPE_PROVIDER;
  170. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  171. lpObject->toi_entity.tei_entity = IF_ENTITY;
  172. lpIfTable = HeapAlloc(GetProcessHeap(), 0,
  173. *lpdwIfCount * sizeof(IF_ENTRY));
  174. if (lpIfTable == NULL) {
  175. *lpdwIfCount = 0;
  176. *lplpIfTable = NULL;
  177. return GetLastError();
  178. }
  179. lpif = lpIfTable;
  180. for (dwi = 0; dwi < *lpdwIfCount; dwi++) {
  181. dwOutSize = sizeof(IF_ENTRY);
  182. lpObject->toi_entity.tei_instance = dwi;
  183. ZeroMemory(lpContext, CONTEXT_SIZE);
  184. dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize,
  185. lpif, &dwOutSize);
  186. if (dwErr == NO_ERROR) {
  187. ++lpif;
  188. }
  189. }
  190. *lpdwIfCount = (DWORD)(lpif - lpIfTable);
  191. if (*lpdwIfCount == 0) {
  192. *lpdwIfCount = 0;
  193. *lplpIfTable = NULL;
  194. HeapFree(GetProcessHeap(), 0, lpIfTable);
  195. return ERROR_INVALID_PARAMETER;
  196. }
  197. *lplpIfTable = lpIfTable;
  198. return 0;
  199. }
  200. DWORD
  201. RTGetAddrTable(
  202. LPIPADDRESS_ENTRY* lplpAddrTable,
  203. LPDWORD lpdwAddrCount
  204. )
  205. {
  206. ULONG_PTR *lpContext;
  207. TDIObjectID *lpObject;
  208. LPIPADDRESS_ENTRY lpAddrTable;
  209. DWORD dwErr, dwInSize, dwOutSize;
  210. TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
  211. if (*lpdwAddrCount == 0) {
  212. return ERROR_INVALID_PARAMETER;
  213. }
  214. dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  215. dwOutSize = *lpdwAddrCount * sizeof(IPADDRESS_ENTRY);
  216. lpAddrTable = HeapAlloc(GetProcessHeap(), 0, dwOutSize);
  217. if (lpAddrTable == NULL) {
  218. *lpdwAddrCount = 0;
  219. *lplpAddrTable = NULL;
  220. return GetLastError();
  221. }
  222. lpContext = trqiBuffer.Context;
  223. ZeroMemory(lpContext, CONTEXT_SIZE);
  224. lpObject = &trqiBuffer.ID;
  225. lpObject->toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
  226. lpObject->toi_type = INFO_TYPE_PROVIDER;
  227. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  228. lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
  229. lpObject->toi_entity.tei_instance = 0;
  230. dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize,
  231. lpAddrTable, &dwOutSize);
  232. if (dwErr != NO_ERROR) {
  233. *lpdwAddrCount = 0;
  234. *lplpAddrTable = NULL;
  235. HeapFree(GetProcessHeap(), 0, lpAddrTable);
  236. return dwErr;
  237. }
  238. *lpdwAddrCount = dwOutSize / sizeof(IPADDRESS_ENTRY);
  239. *lplpAddrTable = lpAddrTable;
  240. return 0;
  241. }
  242.