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.

609 lines
12 KiB

  1. /*++
  2. Copyright (c) 2001-2002 Microsoft Corporation
  3. Module Name:
  4. isatap.c
  5. Abstract:
  6. This module contains the ISATAP interface to the IPv6 Helper Service.
  7. Author:
  8. Mohit Talwar (mohitt) Tue May 07 10:16:49 2002
  9. Environment:
  10. User mode only.
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #define DEFAULT_ISATAP_STATE ENABLED
  15. #define DEFAULT_ISATAP_ROUTER_NAME L"isatap"
  16. #define DEFAULT_ISATAP_RESOLUTION_STATE ENABLED
  17. #define DEFAULT_ISATAP_RESOLUTION_INTERVAL (24 * HOURS)
  18. #define KEY_ISATAP_STATE L"IsatapState"
  19. #define KEY_ISATAP_ROUTER_NAME L"IsatapRouterName"
  20. #define KEY_ISATAP_RESOLUTION_STATE L"EnableIsatapResolution"
  21. #define KEY_ISATAP_RESOLUTION_INTERVAL L"IsatapResolutionInterval"
  22. STATE IsatapState;
  23. WCHAR IsatapRouterName[NI_MAXHOST];
  24. STATE IsatapResolutionState;
  25. ULONG IsatapResolutionInterval; // in minutes
  26. HANDLE IsatapTimer; // Periodic timer started for the service.
  27. HANDLE IsatapTimerEvent; // Event signalled upon Timer deletion.
  28. HANDLE IsatapTimerEventWait; // Wait registered for TimerEvent.
  29. IN_ADDR IsatapRouter;
  30. IN_ADDR IsatapToken;
  31. BOOL IsatapInitialized = FALSE;
  32. DWORD
  33. GetPreferredSource(
  34. IN IN_ADDR Destination,
  35. OUT PIN_ADDR Source
  36. )
  37. {
  38. SOCKADDR_IN DestinationAddress, SourceAddress;
  39. int BytesReturned;
  40. memset(&DestinationAddress, 0, sizeof(SOCKADDR_IN));
  41. DestinationAddress.sin_family = AF_INET;
  42. DestinationAddress.sin_addr = Destination;
  43. if (WSAIoctl(
  44. g_sIPv4Socket, SIO_ROUTING_INTERFACE_QUERY,
  45. &DestinationAddress, sizeof(SOCKADDR_IN),
  46. &SourceAddress, sizeof(SOCKADDR_IN),
  47. &BytesReturned, NULL, NULL) == SOCKET_ERROR) {
  48. return WSAGetLastError();
  49. }
  50. *Source = SourceAddress.sin_addr;
  51. return NO_ERROR;
  52. }
  53. VOID
  54. IsatapUpdateRouterAddress(
  55. VOID
  56. )
  57. {
  58. DWORD Error = NO_ERROR;
  59. ADDRINFOW Hints;
  60. PADDRINFOW Addresses;
  61. IN_ADDR NewRouter = { INADDR_ANY }, NewToken = { INADDR_ANY };
  62. //
  63. // Set the ISATAP router address if ISATAP resolution is enabled.
  64. //
  65. if (IsatapResolutionState == ENABLED) {
  66. //
  67. // Resolve IsatapRouterName to an IPv4 address.
  68. //
  69. ZeroMemory(&Hints, sizeof(Hints));
  70. Hints.ai_family = PF_INET;
  71. Error = GetAddrInfoW(IsatapRouterName, NULL, &Hints, &Addresses);
  72. if (Error == NO_ERROR) {
  73. NewRouter = ((LPSOCKADDR_IN) Addresses->ai_addr)->sin_addr;
  74. FreeAddrInfoW(Addresses);
  75. //
  76. // Determine the preferred source address.
  77. //
  78. if (GetPreferredSource(NewRouter, &NewToken) != NO_ERROR) {
  79. //
  80. // What use is the IsatapRouter that cannot be reached?
  81. //
  82. NewRouter.s_addr = INADDR_ANY;
  83. }
  84. } else {
  85. Trace2(ERR, _T("GetAddrInfoW(%s): %x"), IsatapRouterName, Error);
  86. }
  87. }
  88. //
  89. // Update the stack with the new addresses.
  90. //
  91. IsatapRouter = NewRouter;
  92. IsatapToken = NewToken;
  93. UpdateRouterLinkAddress(V4_COMPAT_IFINDEX, IsatapToken, IsatapRouter);
  94. }
  95. VOID
  96. IsatapConfigureAddress(
  97. IN BOOL Delete,
  98. IN IN_ADDR Ipv4
  99. )
  100. /*++
  101. Routine Description:
  102. Creates an ISATAP link-scoped address from an IPv4 address.
  103. --*/
  104. {
  105. SOCKADDR_IN6 IsatapAddress;
  106. memset(&IsatapAddress, 0, sizeof(SOCKADDR_IN6));
  107. IsatapAddress.sin6_family = AF_INET6;
  108. IsatapAddress.sin6_addr.s6_addr[0] = 0xfe;
  109. IsatapAddress.sin6_addr.s6_addr[1] = 0x80;
  110. IsatapAddress.sin6_addr.s6_addr[10] = 0x5e;
  111. IsatapAddress.sin6_addr.s6_addr[11] = 0xfe;
  112. memcpy(&IsatapAddress.sin6_addr.s6_addr[12], &Ipv4, sizeof(IN_ADDR));
  113. (VOID) ConfigureAddressUpdate(
  114. V4_COMPAT_IFINDEX,
  115. &IsatapAddress,
  116. Delete ? 0 : INFINITE_LIFETIME,
  117. ADE_UNICAST, PREFIX_CONF_WELLKNOWN, IID_CONF_LL_ADDRESS);
  118. }
  119. VOID
  120. IsatapConfigureAddressList(
  121. IN BOOL Delete
  122. )
  123. {
  124. int i;
  125. //
  126. // Configure the lifetime of link-local ISATAP addresses.
  127. // This will cause them to be either added or deleted.
  128. //
  129. for (i = 0; i < g_pIpv4AddressList->iAddressCount; i++) {
  130. IsatapConfigureAddress(
  131. Delete,
  132. ((PSOCKADDR_IN)
  133. g_pIpv4AddressList->Address[i].lpSockaddr)->sin_addr);
  134. }
  135. }
  136. __inline
  137. VOID
  138. IsatapRestartTimer(
  139. VOID
  140. )
  141. {
  142. ULONG ResolveInterval = (IsatapResolutionState == ENABLED)
  143. ? IsatapResolutionInterval * MINUTES * 1000 // minutes to milliseconds
  144. : INFINITE_INTERVAL;
  145. (VOID) ChangeTimerQueueTimer(NULL, IsatapTimer, 0, ResolveInterval);
  146. }
  147. __inline
  148. VOID
  149. IsatapStart(
  150. VOID
  151. )
  152. {
  153. ASSERT(IsatapState != ENABLED);
  154. IsatapState = ENABLED;
  155. IsatapConfigureAddressList(FALSE);
  156. IsatapRestartTimer();
  157. }
  158. __inline
  159. VOID
  160. IsatapStop(
  161. VOID
  162. )
  163. {
  164. ASSERT(IsatapState == ENABLED);
  165. IsatapState = DISABLED;
  166. IsatapConfigureAddressList(TRUE);
  167. IsatapRestartTimer();
  168. }
  169. __inline
  170. VOID
  171. IsatapRefresh(
  172. VOID
  173. )
  174. {
  175. ASSERT(IsatapState == ENABLED);
  176. IsatapRestartTimer();
  177. }
  178. VOID
  179. CALLBACK
  180. IsatapTimerCallback(
  181. IN PVOID Parameter,
  182. IN BOOLEAN TimerOrWaitFired
  183. )
  184. /*++
  185. Routine Description:
  186. Callback routine for IsatapTimer expiration.
  187. The timer is always active.
  188. Arguments:
  189. Parameter, TimerOrWaitFired - Ignored.
  190. Return Value:
  191. None.
  192. --*/
  193. {
  194. ENTER_API();
  195. TraceEnter("IsatapTimerCallback");
  196. IsatapUpdateRouterAddress();
  197. TraceLeave("IsatapTimerCallback");
  198. LEAVE_API();
  199. }
  200. VOID
  201. CALLBACK
  202. IsatapTimerCleanup(
  203. IN PVOID Parameter,
  204. IN BOOLEAN TimerOrWaitFired
  205. )
  206. /*++
  207. Routine Description:
  208. Callback routine for IsatapTimer deletion.
  209. Deletion is performed asynchronously since we acquire a lock in
  210. the callback function that we hold when deleting the timer.
  211. Arguments:
  212. Parameter, TimerOrWaitFired - Ignored.
  213. Return Value:
  214. None.
  215. --*/
  216. {
  217. UnregisterWait(IsatapTimerEventWait);
  218. IsatapTimerEventWait = NULL;
  219. CloseHandle(IsatapTimerEvent);
  220. IsatapTimerEvent = NULL;
  221. IsatapState = IsatapResolutionState = DISABLED;
  222. IsatapUpdateRouterAddress();
  223. DecEventCount("IsatapCleanupTimer");
  224. }
  225. DWORD
  226. IsatapInitializeTimer(
  227. VOID
  228. )
  229. /*++
  230. Routine Description:
  231. Initializes the timer.
  232. Arguments:
  233. None.
  234. Return Value:
  235. NO_ERROR or failure code.
  236. --*/
  237. {
  238. DWORD Error;
  239. ULONG ResolveInterval;
  240. IsatapTimerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  241. if (IsatapTimerEvent == NULL) {
  242. Error = GetLastError();
  243. return Error;
  244. }
  245. if (!RegisterWaitForSingleObject(
  246. &(IsatapTimerEventWait),
  247. IsatapTimerEvent,
  248. IsatapTimerCleanup,
  249. NULL,
  250. INFINITE,
  251. 0)) {
  252. Error = GetLastError();
  253. CloseHandle(IsatapTimerEvent);
  254. return Error;
  255. }
  256. ResolveInterval = (IsatapResolutionState == ENABLED)
  257. ? (IsatapResolutionInterval * MINUTES * 1000)
  258. : INFINITE_INTERVAL;
  259. if (!CreateTimerQueueTimer(
  260. &(IsatapTimer),
  261. NULL,
  262. IsatapTimerCallback,
  263. NULL,
  264. 0,
  265. ResolveInterval,
  266. 0)) {
  267. Error = GetLastError();
  268. UnregisterWait(IsatapTimerEventWait);
  269. CloseHandle(IsatapTimerEvent);
  270. return Error;
  271. }
  272. IncEventCount("IsatapInitializeTimer");
  273. return NO_ERROR;
  274. }
  275. VOID
  276. IsatapUninitializeTimer(
  277. VOID
  278. )
  279. /*++
  280. Routine Description:
  281. Uninitializes the timer. Typically invoked upon service stop.
  282. Arguments:
  283. None.
  284. Return Value:
  285. None.
  286. --*/
  287. {
  288. DeleteTimerQueueTimer(NULL, IsatapTimer, IsatapTimerEvent);
  289. IsatapTimer = NULL;
  290. }
  291. DWORD
  292. IsatapInitialize(
  293. VOID
  294. )
  295. /*++
  296. Routine Description:
  297. Initializes ISATAP and attempts to start it.
  298. Arguments:
  299. None.
  300. Return Value:
  301. NO_ERROR or failure code.
  302. --*/
  303. {
  304. DWORD Error;
  305. IsatapState = DEFAULT_ISATAP_STATE;
  306. wcscpy(IsatapRouterName, DEFAULT_ISATAP_ROUTER_NAME);
  307. IsatapResolutionState = DEFAULT_ISATAP_RESOLUTION_STATE;
  308. IsatapResolutionInterval = DEFAULT_ISATAP_RESOLUTION_INTERVAL;
  309. IsatapRouter.s_addr = INADDR_ANY;
  310. IsatapToken.s_addr = INADDR_ANY;
  311. IsatapUpdateRouterAddress();
  312. Error = IsatapInitializeTimer();
  313. if (Error != NO_ERROR) {
  314. return Error;
  315. }
  316. IsatapInitialized = TRUE;
  317. return NO_ERROR;
  318. }
  319. VOID
  320. IsatapUninitialize(
  321. VOID
  322. )
  323. /*++
  324. Routine Description:
  325. Uninitializes ISATAP.
  326. Arguments:
  327. None.
  328. Return Value:
  329. None.
  330. --*/
  331. {
  332. if (!IsatapInitialized) {
  333. return;
  334. }
  335. IsatapUninitializeTimer();
  336. IsatapInitialized = FALSE;
  337. }
  338. VOID
  339. IsatapAddressChangeNotification(
  340. IN BOOL Delete,
  341. IN IN_ADDR Address
  342. )
  343. /*++
  344. Routine Description:
  345. Process an address deletion or addition request.
  346. Arguments:
  347. Delete - Supplies a boolean. TRUE if the address was deleted, FALSE o/w.
  348. Address - Supplies the IPv4 address that was deleted or added.
  349. Return Value:
  350. None.
  351. Caller LOCK: API.
  352. --*/
  353. {
  354. IsatapConfigureAddress(Delete, Address);
  355. if (IsatapResolutionState == ENABLED) {
  356. //
  357. // Preferred source address deleted -or- Any address added.
  358. //
  359. if (Delete
  360. ? (IsatapToken.s_addr == Address.s_addr)
  361. : (IsatapToken.s_addr == INADDR_ANY)) {
  362. Sleep(1000); // Wait a second to ensure DNS is alerted.
  363. IsatapUpdateRouterAddress();
  364. }
  365. }
  366. }
  367. VOID
  368. IsatapRouteChangeNotification(
  369. VOID
  370. )
  371. /*++
  372. Routine Description:
  373. Process a route change notification.
  374. Arguments:
  375. None.
  376. Return Value:
  377. None.
  378. Caller LOCK: API.
  379. --*/
  380. {
  381. if (IsatapResolutionState == ENABLED) {
  382. IsatapRefresh();
  383. }
  384. }
  385. VOID
  386. IsatapConfigurationChangeNotification(
  387. VOID
  388. )
  389. /*++
  390. Routine Description:
  391. Process an configuration change request.
  392. Arguments:
  393. None.
  394. Return Value:
  395. None.
  396. Caller LOCK: API.
  397. --*/
  398. {
  399. HKEY Key = INVALID_HANDLE_VALUE;
  400. STATE State;
  401. (VOID) RegOpenKeyExW(
  402. HKEY_LOCAL_MACHINE, KEY_GLOBAL, 0, KEY_QUERY_VALUE, &Key);
  403. //
  404. // Continue despite errors, reverting to default values.
  405. //
  406. State = GetInteger(
  407. Key,
  408. KEY_ISATAP_STATE,
  409. DEFAULT_ISATAP_STATE);
  410. IsatapResolutionState = GetInteger(
  411. Key,
  412. KEY_ISATAP_RESOLUTION_STATE,
  413. DEFAULT_ISATAP_RESOLUTION_STATE);
  414. IsatapResolutionInterval= GetInteger(
  415. Key,
  416. KEY_ISATAP_RESOLUTION_INTERVAL,
  417. DEFAULT_ISATAP_RESOLUTION_INTERVAL);
  418. GetString(
  419. Key,
  420. KEY_ISATAP_ROUTER_NAME,
  421. IsatapRouterName,
  422. NI_MAXHOST,
  423. DEFAULT_ISATAP_ROUTER_NAME);
  424. if (Key != INVALID_HANDLE_VALUE) {
  425. RegCloseKey(Key);
  426. }
  427. if (State == DISABLED) {
  428. IsatapResolutionState = DISABLED;
  429. }
  430. //
  431. // Start / Reconfigure / Stop.
  432. //
  433. if (State == ENABLED) {
  434. if (IsatapState == ENABLED) {
  435. IsatapRefresh();
  436. } else {
  437. IsatapStart();
  438. }
  439. } else {
  440. if (IsatapState == ENABLED) {
  441. IsatapStop();
  442. }
  443. }
  444. }