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.

823 lines
24 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Abstract:
  4. Routines implementing Dynamic DNS registration of IPv6 addresses.
  5. --*/
  6. #include "precomp.h"
  7. #pragma hdrstop
  8. #include <windns.h>
  9. #include <ntddip6.h>
  10. //
  11. // DHCP IPv4 addresses inside Microsoft have a default TTL of 20 minutes.
  12. //
  13. #define MAX_AAAA_TTL 1200 // Seconds.
  14. //
  15. // We must update the DNS records occasionally,
  16. // or the DNS server might garbage-collect them.
  17. // MSDN recommends a one-day interval.
  18. //
  19. #define MIN_UPDATE_INTERVAL (1*DAYS*1000) // Milliseconds.
  20. __inline ULONG
  21. MIN(ULONG a, ULONG b)
  22. {
  23. if (a < b)
  24. return a;
  25. else
  26. return b;
  27. }
  28. SOCKET g_hIpv6Socket = INVALID_SOCKET;
  29. WSAEVENT g_hIpv6AddressChangeEvent = NULL;
  30. HANDLE g_hIpv6AddressChangeWait = NULL;
  31. WSAOVERLAPPED g_hIpv6AddressChangeOverlapped;
  32. //
  33. // Stores the state from the last invocation of OnIpv6AddressChange. The only
  34. // two fields used from the previous state are the site id
  35. // (ZoneIndices[ScopeLevelSite]) and Mtu. The mtu field is overloaded to store
  36. // information if the site id was manually changed for the interface or not. If
  37. // the site id was manually change, Mtu is set to 1, otherwise 0. Once the site
  38. // id has been manually changed, we do not try to override it. Also, this
  39. // information is not persistent across reboots. If the site id is changed
  40. // manually, on the next reboot, this information is lost and the 6to4 service
  41. // might try to assign a new value. Secondly, there is no way to undo a manual
  42. // setting. If a user sets the site id once, there is no way to go back to
  43. // automatic configuration.
  44. //
  45. PIP_ADAPTER_ADDRESSES g_PreviousInterfaceState = NULL;
  46. #define SITEID_MANUALLY_CHANGED Mtu
  47. //
  48. // Our caller uses StopIpv6AddressChangeNotification
  49. // if we fail, so we don't need to cleanup.
  50. //
  51. DWORD
  52. StartIpv6AddressChangeNotification()
  53. {
  54. ASSERT(g_hIpv6Socket == INVALID_SOCKET);
  55. g_hIpv6Socket = WSASocket(AF_INET6, 0, 0,
  56. NULL, 0,
  57. WSA_FLAG_OVERLAPPED);
  58. if (g_hIpv6Socket == INVALID_SOCKET)
  59. return WSAGetLastError();
  60. //
  61. // We create an auto-reset event in the signalled state.
  62. // So OnIpv6AddressChange will be executed initially.
  63. //
  64. ASSERT(g_hIpv6AddressChangeEvent == NULL);
  65. g_hIpv6AddressChangeEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
  66. if (g_hIpv6AddressChangeEvent == NULL)
  67. return GetLastError();
  68. //
  69. // We specify a timeout, so that we update DNS
  70. // at least that often. Otherwise the DNS server might
  71. // garbage-collect our records.
  72. //
  73. IncEventCount("AC:StartIpv6AddressChangeNotification");
  74. if (! RegisterWaitForSingleObject(&g_hIpv6AddressChangeWait,
  75. g_hIpv6AddressChangeEvent,
  76. OnIpv6AddressChange,
  77. NULL,
  78. MIN_UPDATE_INTERVAL,
  79. WT_EXECUTELONGFUNCTION)) {
  80. DecEventCount("AC:StartIpv6AddressChangeNotification");
  81. return GetLastError();
  82. }
  83. return NO_ERROR;
  84. }
  85. //
  86. // Assume that if the primary DNS server is the same, then that's
  87. // good enough to combine the records.
  88. //
  89. BOOL
  90. IsSameDNSServer(
  91. PIP_ADAPTER_ADDRESSES pIf1,
  92. PIP_ADAPTER_ADDRESSES pIf2
  93. )
  94. {
  95. PIP_ADAPTER_DNS_SERVER_ADDRESS pDns1, pDns2;
  96. pDns1 = pIf1->FirstDnsServerAddress;
  97. while ((pDns1 != NULL) &&
  98. (pDns1->Address.lpSockaddr->sa_family != AF_INET)) {
  99. pDns1 = pDns1->Next;
  100. }
  101. pDns2 = pIf2->FirstDnsServerAddress;
  102. while ((pDns2 != NULL) &&
  103. (pDns2->Address.lpSockaddr->sa_family != AF_INET)) {
  104. pDns2 = pDns2->Next;
  105. }
  106. if ((pDns1 == NULL) || (pDns2 == NULL)) {
  107. return FALSE;
  108. }
  109. ASSERT(pDns1->Address.lpSockaddr->sa_family ==
  110. pDns2->Address.lpSockaddr->sa_family);
  111. return !memcmp(pDns1->Address.lpSockaddr,
  112. pDns2->Address.lpSockaddr,
  113. pDns1->Address.iSockaddrLength);
  114. }
  115. DNS_RECORD *
  116. BuildRecordSetW(
  117. WCHAR *hostname,
  118. PIP_ADAPTER_ADDRESSES pFirstIf,
  119. PIP4_ARRAY *ppServerList
  120. )
  121. {
  122. DNS_RECORD *RSet, *pNext;
  123. int i, iAddressCount = 0;
  124. PIP_ADAPTER_UNICAST_ADDRESS Address;
  125. PIP_ADAPTER_ADDRESSES pIf;
  126. int ServerCount = 0;
  127. PIP_ADAPTER_DNS_SERVER_ADDRESS DnsServer;
  128. LPSOCKADDR_IN sin;
  129. BOOL RegisterSiteLocals = ENABLED;
  130. //
  131. // Count DNS servers
  132. //
  133. for (DnsServer = pFirstIf->FirstDnsServerAddress;
  134. DnsServer;
  135. DnsServer = DnsServer->Next)
  136. {
  137. if (DnsServer->Address.lpSockaddr->sa_family != AF_INET) {
  138. //
  139. // DNS api currently only supports IPv4 addresses of servers
  140. //
  141. continue;
  142. }
  143. ServerCount++;
  144. }
  145. if (ServerCount == 0) {
  146. *ppServerList = NULL;
  147. return NULL;
  148. }
  149. //
  150. // Fill in DNS server array
  151. //
  152. *ppServerList = MALLOC(FIELD_OFFSET(IP4_ARRAY, AddrArray[ServerCount]));
  153. if (*ppServerList == NULL) {
  154. return NULL;
  155. }
  156. (*ppServerList)->AddrCount = ServerCount;
  157. for (i = 0, DnsServer = pFirstIf->FirstDnsServerAddress;
  158. DnsServer;
  159. DnsServer = DnsServer->Next)
  160. {
  161. sin = (LPSOCKADDR_IN)DnsServer->Address.lpSockaddr;
  162. if (sin->sin_family == AF_INET) {
  163. (*ppServerList)->AddrArray[i++] = sin->sin_addr.s_addr;
  164. }
  165. }
  166. ASSERT(i == ServerCount);
  167. //
  168. // Decide whether to register site locals in DNS.
  169. //
  170. {
  171. HKEY hKey;
  172. DWORD dwErr;
  173. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KEY_GLOBAL, 0,
  174. KEY_QUERY_VALUE, &hKey);
  175. if (dwErr == NO_ERROR) {
  176. RegisterSiteLocals = GetInteger(hKey, L"EnableSiteLocalDdns",
  177. ENABLED);
  178. RegCloseKey(hKey);
  179. }
  180. }
  181. //
  182. // Count eligible addresses
  183. //
  184. for (pIf=pFirstIf; pIf; pIf=pIf->Next) {
  185. if (!(pIf->Flags & IP_ADAPTER_DDNS_ENABLED))
  186. continue;
  187. //
  188. // Make sure interface has same DNS server
  189. //
  190. if ((pIf != pFirstIf) && !IsSameDNSServer(pFirstIf, pIf)) {
  191. continue;
  192. }
  193. for (Address=pIf->FirstUnicastAddress; Address; Address=Address->Next) {
  194. if ((Address->Address.lpSockaddr->sa_family == AF_INET6) &&
  195. (Address->Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE) &&
  196. ((RegisterSiteLocals == ENABLED) ||
  197. !IN6_IS_ADDR_SITELOCAL(&((LPSOCKADDR_IN6)
  198. Address->Address.lpSockaddr)->sin6_addr))) {
  199. iAddressCount++;
  200. }
  201. }
  202. }
  203. Trace1(FSM, _T("DDNS building record set of %u addresses"), iAddressCount);
  204. if (iAddressCount == 0) {
  205. //
  206. // Build a record set that specifies deletion.
  207. //
  208. RSet = MALLOC(sizeof *RSet);
  209. if (RSet == NULL) {
  210. return NULL;
  211. }
  212. memset(RSet, 0, sizeof *RSet);
  213. RSet->pName = (LPTSTR)hostname;
  214. RSet->wType = DNS_TYPE_AAAA;
  215. return RSet;
  216. }
  217. RSet = MALLOC(sizeof *RSet * iAddressCount);
  218. if (RSet == NULL) {
  219. return NULL;
  220. }
  221. memset(RSet, 0, sizeof *RSet * iAddressCount);
  222. pNext = NULL;
  223. i = iAddressCount;
  224. while (--i >= 0) {
  225. RSet[i].pNext = pNext;
  226. pNext = &RSet[i];
  227. }
  228. i=0;
  229. for (pIf=pFirstIf; pIf; pIf=pIf->Next) {
  230. if (!(pIf->Flags & IP_ADAPTER_DDNS_ENABLED))
  231. continue;
  232. if ((pIf != pFirstIf) && !IsSameDNSServer(pFirstIf, pIf)) {
  233. continue;
  234. }
  235. for (Address=pIf->FirstUnicastAddress;
  236. Address;
  237. Address=Address->Next) {
  238. if ((Address->Address.lpSockaddr->sa_family == AF_INET6) &&
  239. (Address->Flags & IP_ADAPTER_ADDRESS_DNS_ELIGIBLE) &&
  240. ((RegisterSiteLocals == ENABLED) ||
  241. !IN6_IS_ADDR_SITELOCAL(&((LPSOCKADDR_IN6)
  242. Address->Address.lpSockaddr)->sin6_addr))) {
  243. SOCKADDR_IN6 *sin6 = (SOCKADDR_IN6 *)
  244. Address->Address.lpSockaddr;
  245. RSet[i].pName = (LPTSTR)hostname;
  246. //
  247. // Using a large TTL is not good because it means
  248. // any changes (adding a new address, removing an address)
  249. // might not be visible for a long time.
  250. //
  251. RSet[i].dwTtl = MIN(MAX_AAAA_TTL,
  252. MIN(Address->PreferredLifetime,
  253. Address->LeaseLifetime));
  254. RSet[i].wType = DNS_TYPE_AAAA;
  255. RSet[i].wDataLength = sizeof RSet[i].Data.AAAA;
  256. RSet[i].Data.AAAA.Ip6Address =
  257. * (IP6_ADDRESS *) &sin6->sin6_addr;
  258. i++;
  259. }
  260. }
  261. }
  262. ASSERT(i == iAddressCount);
  263. return RSet;
  264. }
  265. VOID
  266. ReportDnsUpdateStatusW(
  267. IN DNS_STATUS Status,
  268. IN WCHAR *hostname,
  269. IN DNS_RECORD *RSet
  270. )
  271. {
  272. Trace3(ERR, _T("6to4svc: DnsReplaceRecordSet(%ls) %s: status %d"),
  273. hostname,
  274. RSet->wDataLength == 0 ? "delete" : "replace",
  275. Status);
  276. }
  277. //
  278. // This function adapted from net\tcpip\commands\ipconfig\info.c
  279. //
  280. VOID
  281. GetInterfaceDeviceName(
  282. IN ULONG Ipv4IfIndex,
  283. IN PIP_INTERFACE_INFO InterfaceInfo,
  284. OUT LPWSTR *IfDeviceName
  285. )
  286. {
  287. DWORD i;
  288. //
  289. // search the InterfaceInfo to get the devicename for this interface.
  290. //
  291. (*IfDeviceName) = NULL;
  292. for( i = 0; i < (DWORD)InterfaceInfo->NumAdapters; i ++ ) {
  293. if( InterfaceInfo->Adapter[i].Index != Ipv4IfIndex ) continue;
  294. (*IfDeviceName) = InterfaceInfo->Adapter[i].Name + strlen(
  295. "\\Device\\Tcpip_" );
  296. break;
  297. }
  298. }
  299. VOID
  300. RegisterNameOnInterface(
  301. PIP_ADAPTER_ADDRESSES pIf,
  302. PWCHAR hostname,
  303. DWORD namelen)
  304. {
  305. DNS_RECORD *RSet = NULL;
  306. PIP4_ARRAY pServerList = NULL;
  307. DWORD Status;
  308. //
  309. // Convert to a DNS record set.
  310. //
  311. RSet = BuildRecordSetW(hostname, pIf, &pServerList);
  312. if ((RSet == NULL) || (pServerList == NULL)) {
  313. goto Cleanup;
  314. }
  315. Trace2(ERR, _T("DDNS registering %ls to server %d.%d.%d.%d"),
  316. hostname, PRINT_IPADDR(pServerList->AddrArray[0]));
  317. //
  318. // REVIEW: We could (should?) compare the current record set
  319. // to the previous record set, and only update DNS
  320. // if there has been a change or if there was a timeout.
  321. //
  322. Status = DnsReplaceRecordSetW(
  323. RSet,
  324. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  325. NULL,
  326. pServerList,
  327. NULL);
  328. if (Status != NO_ERROR) {
  329. Trace1(ERR, _T("Error: DnsReplaceRecordSet returned %d"), Status);
  330. }
  331. ReportDnsUpdateStatusW(Status, hostname, RSet);
  332. Cleanup:
  333. if (pServerList) {
  334. FREE(pServerList);
  335. }
  336. if (RSet) {
  337. FREE(RSet);
  338. }
  339. }
  340. VOID
  341. DoDdnsOnInterface(
  342. PIP_ADAPTER_ADDRESSES pIf)
  343. {
  344. // Leave room to add a trailing "."
  345. WCHAR hostname[NI_MAXHOST+1];
  346. DWORD namelen;
  347. //
  348. // Get the fully-qualified DNS name for this machine
  349. // and append a trailing dot.
  350. //
  351. namelen = NI_MAXHOST;
  352. if (! GetComputerNameExW(ComputerNamePhysicalDnsFullyQualified,
  353. hostname, &namelen)) {
  354. return;
  355. }
  356. namelen = (DWORD)wcslen(hostname);
  357. hostname[namelen] = L'.';
  358. hostname[namelen+1] = L'\0';
  359. RegisterNameOnInterface(pIf, hostname, namelen);
  360. //
  361. // Also register the connection-specific name if configured to do so.
  362. //
  363. if (pIf->Flags & IP_ADAPTER_REGISTER_ADAPTER_SUFFIX) {
  364. namelen = NI_MAXHOST;
  365. if (! GetComputerNameExW(ComputerNamePhysicalDnsHostname,
  366. hostname, &namelen)) {
  367. return;
  368. }
  369. wcscat(hostname, L".");
  370. wcscat(hostname, pIf->DnsSuffix);
  371. namelen = (DWORD)wcslen(hostname);
  372. hostname[namelen] = L'.';
  373. hostname[namelen+1] = L'\0';
  374. RegisterNameOnInterface(pIf, hostname, namelen);
  375. }
  376. }
  377. //
  378. // Set the site id of a given interface.
  379. //
  380. VOID
  381. SetSiteId(
  382. IN PIP_ADAPTER_ADDRESSES pIf,
  383. IN ULONG SiteId)
  384. {
  385. PIP_ADAPTER_DNS_SERVER_ADDRESS pDNS;
  386. IPV6_INFO_INTERFACE Update;
  387. DWORD Result;
  388. PSOCKADDR_IN6 pAddr;
  389. IPV6_INIT_INFO_INTERFACE(&Update);
  390. Update.This.Index = pIf->Ipv6IfIndex;
  391. Update.ZoneIndices[ADE_SITE_LOCAL] = SiteId;
  392. Result = UpdateInterface(&Update);
  393. Trace3(ERR, _T("SetSiteId if=%d site=%d result=%d"),
  394. pIf->Ipv6IfIndex, SiteId, Result);
  395. pIf->ZoneIndices[ScopeLevelSite] = SiteId;
  396. //
  397. // Site-local addresses of DNS servers may now have the wrong scope id.
  398. // Fix them.
  399. //
  400. for (pDNS = pIf->FirstDnsServerAddress; pDNS != NULL; pDNS = pDNS->Next) {
  401. pAddr = (PSOCKADDR_IN6)pDNS->Address.lpSockaddr;
  402. if ((pAddr->sin6_family == AF_INET6) &&
  403. (IN6_IS_ADDR_SITELOCAL(&pAddr->sin6_addr))) {
  404. pAddr->sin6_scope_id = SiteId;
  405. }
  406. }
  407. }
  408. //
  409. // Set the site id of a given interface to an unused value.
  410. //
  411. VOID
  412. NewSiteId(
  413. IN PIP_ADAPTER_ADDRESSES pIf,
  414. IN PIP_ADAPTER_ADDRESSES pAdapterAddresses)
  415. {
  416. PIP_ADAPTER_ADDRESSES CompareWithIf;
  417. ULONG PotentialSiteId = 1;
  418. //
  419. // Find the lowest unused site id.
  420. //
  421. CompareWithIf = pAdapterAddresses;
  422. while (CompareWithIf != NULL) {
  423. if (CompareWithIf->ZoneIndices[ScopeLevelSite] == PotentialSiteId) {
  424. PotentialSiteId++;
  425. CompareWithIf = pAdapterAddresses;
  426. } else {
  427. CompareWithIf = CompareWithIf->Next;
  428. }
  429. }
  430. SetSiteId(pIf, PotentialSiteId);
  431. }
  432. BOOL
  433. SameSite(
  434. IN PIP_ADAPTER_ADDRESSES A,
  435. IN PIP_ADAPTER_ADDRESSES B)
  436. {
  437. IPV6_INFO_SITE_PREFIX PrefixA, PrefixB;
  438. //
  439. // If a connection-specific DNS suffix exists on either, then compare that.
  440. //
  441. // We do this first because it's more efficient than diving to the
  442. // kernel to get the site prefixes. In addition, it's immune to
  443. // whether the site prefix length is correct.
  444. //
  445. if (((A->DnsSuffix != NULL) && (A->DnsSuffix[0] != L'\0')) ||
  446. ((B->DnsSuffix != NULL) && (B->DnsSuffix[0] != L'\0'))) {
  447. if ((A->DnsSuffix == NULL) || (B->DnsSuffix == NULL)) {
  448. return FALSE;
  449. }
  450. return (wcscmp(A->DnsSuffix, B->DnsSuffix) == 0);
  451. }
  452. //
  453. // No connection-specific DNS suffix exists on either interface.
  454. // If an IPv6 site prefix exists on either, then compare that.
  455. //
  456. GetFirstSitePrefix(A->Ipv6IfIndex, &PrefixA);
  457. GetFirstSitePrefix(B->Ipv6IfIndex, &PrefixB);
  458. if ((PrefixA.Query.IF.Index != 0) || (PrefixB.Query.IF.Index != 0)) {
  459. if ((PrefixA.Query.IF.Index == 0) || (PrefixB.Query.IF.Index == 0)) {
  460. return FALSE;
  461. }
  462. if (PrefixA.Query.PrefixLength != PrefixB.Query.PrefixLength) {
  463. return FALSE;
  464. }
  465. return (RtlEqualMemory(PrefixA.Query.Prefix.s6_addr,
  466. PrefixB.Query.Prefix.s6_addr,
  467. sizeof(IPv6Addr)));
  468. }
  469. //
  470. // No site prefix exists on either interface.
  471. // Default to saying they're in different sites.
  472. //
  473. return FALSE;
  474. }
  475. VOID CALLBACK
  476. OnIpv6AddressChange(
  477. IN PVOID lpParameter,
  478. IN BOOLEAN TimerOrWaitFired)
  479. {
  480. PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL;
  481. PIP_ADAPTER_ADDRESSES pIf, pIf2, PreviousInterfaceState;
  482. BOOLEAN SetPreviousState = FALSE;
  483. ULONG BytesNeeded = 0;
  484. DWORD dwErr;
  485. DWORD BytesReturned;
  486. //
  487. // Sleep for one second.
  488. // Often there will be multiple address changes in a small time period,
  489. // and we prefer to update DNS once.
  490. //
  491. Sleep(1000);
  492. ENTER_API();
  493. TraceEnter("OnIpv6AddressChange");
  494. if (g_stService == DISABLED) {
  495. Trace0(FSM, L"Service disabled");
  496. goto Done;
  497. }
  498. //
  499. // First request another async notification.
  500. // We must do this *before* getting the address list,
  501. // to avoid missing an address change.
  502. //
  503. if (TimerOrWaitFired == FALSE) {
  504. for (;;) {
  505. ZeroMemory(&g_hIpv6AddressChangeOverlapped, sizeof(WSAOVERLAPPED));
  506. g_hIpv6AddressChangeOverlapped.hEvent = g_hIpv6AddressChangeEvent;
  507. dwErr = WSAIoctl(g_hIpv6Socket, SIO_ADDRESS_LIST_CHANGE,
  508. NULL, 0,
  509. NULL, 0, &BytesReturned,
  510. &g_hIpv6AddressChangeOverlapped,
  511. NULL);
  512. if (dwErr != 0) {
  513. dwErr = WSAGetLastError();
  514. if (dwErr != WSA_IO_PENDING) {
  515. goto Done;
  516. }
  517. //
  518. // The overlapped operation was initiated.
  519. //
  520. break;
  521. }
  522. //
  523. // The overlapped operation completed immediately.
  524. // Just try it again.
  525. //
  526. }
  527. }
  528. //
  529. // Get the address list.
  530. //
  531. for (;;) {
  532. //
  533. // GetAdaptersAddresses only returns addresses of the specified address
  534. // family. To obtain both IPv4 DNS server addresses and IPv6 unicast
  535. // addresses in the same call we need to pass AF_UNSPEC.
  536. //
  537. dwErr = GetAdaptersAddresses(
  538. AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
  539. GAA_FLAG_SKIP_FRIENDLY_NAME,
  540. NULL, pAdapterAddresses, &BytesNeeded);
  541. if (dwErr == NO_ERROR) {
  542. SetPreviousState = TRUE;
  543. break;
  544. }
  545. if (dwErr != ERROR_BUFFER_OVERFLOW) {
  546. Trace1(ERR, _T("Error: GetAdaptersAddresses returned %d"), dwErr);
  547. if (pAdapterAddresses != NULL) {
  548. FREE(pAdapterAddresses);
  549. pAdapterAddresses = NULL;
  550. }
  551. goto Cleanup;
  552. }
  553. if (pAdapterAddresses == NULL)
  554. pAdapterAddresses = MALLOC(BytesNeeded);
  555. else {
  556. PVOID Mem;
  557. Mem = REALLOC(pAdapterAddresses, BytesNeeded);
  558. if (Mem == NULL) {
  559. FREE(pAdapterAddresses);
  560. }
  561. pAdapterAddresses = Mem;
  562. }
  563. if (pAdapterAddresses == NULL) {
  564. Trace0(ERR, _T("Error: malloc failed"));
  565. goto Cleanup;
  566. }
  567. }
  568. //
  569. // Check for site id changes. At the start of each iteration, everything
  570. // before 'pIf' will be fine. Everything after it will be untouched.
  571. //
  572. for (pIf = pAdapterAddresses; pIf != NULL; pIf = pIf->Next) {
  573. //
  574. // Don't change values for the 6to4 or ISATAP interfaces,
  575. // since the site id is inherited off the underlying interface.
  576. // Also we can't change values for IPv4-only interfaces.
  577. //
  578. if ((pIf->Ipv6IfIndex == V4_COMPAT_IFINDEX) ||
  579. (pIf->Ipv6IfIndex == SIX_TO_FOUR_IFINDEX) ||
  580. (pIf->Ipv6IfIndex == 0)) {
  581. continue;
  582. }
  583. //
  584. // Try to find if we have state for this interface from a previous
  585. // invocation of OnIpv6AddressChange.
  586. //
  587. for (PreviousInterfaceState = g_PreviousInterfaceState;
  588. PreviousInterfaceState != NULL;
  589. PreviousInterfaceState = PreviousInterfaceState->Next) {
  590. if (PreviousInterfaceState->Ipv6IfIndex == pIf->Ipv6IfIndex) {
  591. break;
  592. }
  593. }
  594. if (PreviousInterfaceState != NULL) {
  595. //
  596. // There is already state present for this interface. If the site
  597. // id has changed from the previous state, this is a manual
  598. // configuration. Set the manually changed flag to 1 (note that the
  599. // Mtu is overloaded for this purpose).
  600. //
  601. if (PreviousInterfaceState->ZoneIndices[ScopeLevelSite] !=
  602. pIf->ZoneIndices[ScopeLevelSite]) {
  603. pIf->SITEID_MANUALLY_CHANGED = 1;
  604. } else {
  605. pIf->SITEID_MANUALLY_CHANGED =
  606. PreviousInterfaceState->SITEID_MANUALLY_CHANGED;
  607. }
  608. } else {
  609. pIf->SITEID_MANUALLY_CHANGED = 0;
  610. }
  611. if (pIf->SITEID_MANUALLY_CHANGED == 1) {
  612. continue;
  613. }
  614. for (pIf2 = pAdapterAddresses; pIf2 != pIf; pIf2 = pIf2->Next) {
  615. if ((pIf2->Ipv6IfIndex == V4_COMPAT_IFINDEX) ||
  616. (pIf2->Ipv6IfIndex == SIX_TO_FOUR_IFINDEX) ||
  617. (pIf2->Ipv6IfIndex == 0) ||
  618. (pIf2->SITEID_MANUALLY_CHANGED == 1)) {
  619. continue;
  620. }
  621. if (SameSite(pIf, pIf2)) {
  622. if (pIf->ZoneIndices[ScopeLevelSite] !=
  623. pIf2->ZoneIndices[ScopeLevelSite]) {
  624. //
  625. // pIf has just moved into the same site as an earlier
  626. // interface.
  627. //
  628. SetSiteId(pIf, pIf2->ZoneIndices[ScopeLevelSite]);
  629. }
  630. } else {
  631. if (pIf->ZoneIndices[ScopeLevelSite] ==
  632. pIf2->ZoneIndices[ScopeLevelSite]) {
  633. //
  634. // pIf has just moved out of its previous site.
  635. // Pick a new unused site id.
  636. //
  637. NewSiteId(pIf, pAdapterAddresses);
  638. }
  639. }
  640. }
  641. }
  642. for (pIf=pAdapterAddresses; pIf; pIf=pIf->Next) {
  643. if (pIf->Flags & IP_ADAPTER_DDNS_ENABLED) {
  644. //
  645. // See if we've already done this interface because it
  646. // had the same DNS server as a previous one.
  647. //
  648. for (pIf2=pAdapterAddresses; pIf2 != pIf; pIf2 = pIf2->Next) {
  649. if (!(pIf2->Flags & IP_ADAPTER_DDNS_ENABLED))
  650. continue;
  651. if (IsSameDNSServer(pIf2, pIf)) {
  652. break;
  653. }
  654. }
  655. //
  656. // If not, go ahead and do DDNS.
  657. //
  658. if (pIf2 == pIf) {
  659. DoDdnsOnInterface(pIf);
  660. }
  661. }
  662. }
  663. //
  664. // A change in the set of IPv6 addresses might update the need for the
  665. // different transition mechanisms.
  666. //
  667. UpdateServiceRequirements(pAdapterAddresses);
  668. Cleanup:
  669. //
  670. // At this point, pAdapterAddresses is NULL, otherwise points to valid
  671. // adapter data.
  672. //
  673. if (SetPreviousState) {
  674. if (g_PreviousInterfaceState) {
  675. FREE(g_PreviousInterfaceState);
  676. }
  677. g_PreviousInterfaceState = pAdapterAddresses;
  678. } else {
  679. ASSERT(pAdapterAddresses == NULL);
  680. }
  681. Done:
  682. TraceLeave("OnIpv6AddressChange");
  683. LEAVE_API();
  684. }
  685. VOID
  686. StopIpv6AddressChangeNotification()
  687. {
  688. if (g_hIpv6AddressChangeWait != NULL) {
  689. //
  690. // Block until we're sure that the address change callback isn't
  691. // still running.
  692. //
  693. LEAVE_API();
  694. UnregisterWaitEx(g_hIpv6AddressChangeWait, INVALID_HANDLE_VALUE);
  695. ENTER_API();
  696. //
  697. // Release the event we counted for RegisterWaitForSingleObject
  698. //
  699. DecEventCount("AC:StopIpv6AddressChangeNotification");
  700. g_hIpv6AddressChangeWait = NULL;
  701. }
  702. if (g_PreviousInterfaceState != NULL) {
  703. FREE(g_PreviousInterfaceState);
  704. g_PreviousInterfaceState = NULL;
  705. }
  706. if (g_hIpv6AddressChangeEvent != NULL) {
  707. CloseHandle(g_hIpv6AddressChangeEvent);
  708. g_hIpv6AddressChangeEvent = NULL;
  709. }
  710. if (g_hIpv6Socket != INVALID_SOCKET) {
  711. closesocket(g_hIpv6Socket);
  712. g_hIpv6Socket = INVALID_SOCKET;
  713. }
  714. }