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.

5097 lines
149 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // General IPv6 initialization code lives here.
  14. // Actually, this file is mostly interface/address management code.
  15. //
  16. #include "oscfg.h"
  17. #include "ndis.h"
  18. #include "ip6imp.h"
  19. #include "ip6def.h"
  20. #include "llip6if.h"
  21. #include "route.h"
  22. #include "select.h"
  23. #include "icmp.h"
  24. #include "neighbor.h"
  25. #include <tdiinfo.h>
  26. #include <tdi.h>
  27. #include <tdikrnl.h>
  28. #include "alloca.h"
  29. #include "security.h"
  30. #include "mld.h"
  31. #include "md5.h"
  32. #include "info.h"
  33. #include <ntddip6.h>
  34. extern void TCPRemoveIF(Interface *IF);
  35. static void InterfaceStopForwarding(Interface *IF);
  36. //
  37. // Useful IPv6 Address Constants.
  38. //
  39. IPv6Addr UnspecifiedAddr = { 0 };
  40. IPv6Addr LoopbackAddr = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  41. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
  42. IPv6Addr AllNodesOnNodeAddr = {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
  44. IPv6Addr AllNodesOnLinkAddr = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  45. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
  46. IPv6Addr AllRoutersOnLinkAddr = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  47. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
  48. IPv6Addr LinkLocalPrefix = {0xfe, 0x80, };
  49. IPv6Addr SiteLocalPrefix = {0xfe, 0xc0, };
  50. IPv6Addr SixToFourPrefix = {0x20, 0x02, };
  51. IPv6Addr V4MappedPrefix = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  52. 0x00, 0x00, 0xff, 0xff, };
  53. IPv6Addr MulticastPrefix = {0xff, };
  54. static uint MulticastScopes[] = {
  55. ADE_INTERFACE_LOCAL,
  56. ADE_LINK_LOCAL,
  57. ADE_SITE_LOCAL,
  58. ADE_ORG_LOCAL,
  59. ADE_GLOBAL
  60. };
  61. //
  62. // These variables are initialized from the registry.
  63. // See ConfigureGlobalParameters.
  64. //
  65. uint DefaultCurHopLimit;
  66. uint MaxTempDADAttempts;
  67. uint MaxTempPreferredLifetime;
  68. uint MaxTempValidLifetime;
  69. uint TempRegenerateTime;
  70. uint UseTemporaryAddresses;
  71. uint MaxTempRandomTime;
  72. uint TempRandomTime;
  73. #define TempPreferredLifetime (MaxTempPreferredLifetime - TempRandomTime)
  74. //
  75. // Timer variables.
  76. //
  77. KTIMER IPv6Timer;
  78. KDPC IPv6TimeoutDpc;
  79. int IPv6TimerStarted = FALSE;
  80. uint PacketPoolSize;
  81. NDIS_HANDLE IPv6PacketPool, IPv6BufferPool;
  82. //
  83. // Statistics
  84. //
  85. IPInternalPerCpuStats IPPerCpuStats[IPS_MAX_PROCESSOR_BUCKETS];
  86. CACHE_ALIGN IPSNMPInfo IPSInfo;
  87. uint NumForwardingInterfaces;
  88. //
  89. // The NetTableListLock may be acquired while holding an interface lock.
  90. //
  91. NetTableEntry *NetTableList; // Global list of NTEs.
  92. KSPIN_LOCK NetTableListLock; // Lock protecting this list.
  93. //
  94. // The IFListLock may be acquired while holding an interface lock
  95. // or route lock.
  96. //
  97. KSPIN_LOCK IFListLock; // Lock protecting this list.
  98. Interface *IFList = NULL; // List of interfaces active.
  99. //
  100. // The ZoneUpdateLock prevents concurrent updates
  101. // of interface ZoneIndices.
  102. //
  103. KSPIN_LOCK ZoneUpdateLock;
  104. //
  105. // Used to assign indices to interfaces.
  106. // See InterfaceIndex.
  107. //
  108. uint NextIFIndex = 0;
  109. //* AddNTEToNetTableList
  110. //
  111. // Called with the list already locked.
  112. //
  113. void
  114. AddNTEToNetTableList(NetTableEntry *NTE)
  115. {
  116. if (NetTableList != NULL)
  117. NetTableList->PrevOnNTL = &NTE->NextOnNTL;
  118. NTE->PrevOnNTL = &NetTableList;
  119. NTE->NextOnNTL = NetTableList;
  120. NetTableList = NTE;
  121. IPSInfo.ipsi_numaddr++;
  122. }
  123. //* RemoveNTEFromNetTableList
  124. //
  125. // Called with the list already locked.
  126. //
  127. void
  128. RemoveNTEFromNetTableList(NetTableEntry *NTE)
  129. {
  130. NetTableEntry *NextNTE;
  131. NextNTE = NTE->NextOnNTL;
  132. *NTE->PrevOnNTL = NextNTE;
  133. if (NextNTE != NULL)
  134. NextNTE->PrevOnNTL = NTE->PrevOnNTL;
  135. IPSInfo.ipsi_numaddr--;
  136. }
  137. //* AddNTEToInterface
  138. //
  139. // Adds an NTE to an Interface's list of ADEs.
  140. //
  141. // Called with the interface already locked.
  142. //
  143. void
  144. AddNTEToInterface(Interface *IF, NetTableEntry *NTE)
  145. {
  146. //
  147. // The NTE holds a reference for the interface,
  148. // so anyone with a reference for the NTE
  149. // can safely dereference NTE->IF.
  150. //
  151. AddRefIF(IF);
  152. NTE->IF = IF;
  153. NTE->Next = IF->ADE;
  154. IF->ADE = (AddressEntry *)NTE;
  155. }
  156. //* RemoveNTEFromInterface
  157. //
  158. // Removes a new NTE from the Interface's list of ADEs.
  159. //
  160. // Called with the interface already locked.
  161. // The NTE must be first on the list.
  162. //
  163. void
  164. RemoveNTEFromInterface(Interface *IF, NetTableEntry *NTE)
  165. {
  166. ASSERT(IF->ADE == (AddressEntry *)NTE);
  167. IF->ADE = NTE->Next;
  168. ReleaseIF(IF);
  169. }
  170. typedef struct SynchronizeMulticastContext {
  171. WORK_QUEUE_ITEM WQItem;
  172. Interface *IF;
  173. } SynchronizeMulticastContext;
  174. //* SynchronizeMulticastAddresses
  175. //
  176. // Synchronize the interface's list of link-layer multicast addresses
  177. // with the link's knowledge of those addresses.
  178. //
  179. // Callable from thread context, not from DPC context.
  180. // Called with no locks held.
  181. //
  182. void
  183. SynchronizeMulticastAddresses(void *Context)
  184. {
  185. SynchronizeMulticastContext *smc = (SynchronizeMulticastContext *) Context;
  186. Interface *IF = smc->IF;
  187. void *LinkAddresses;
  188. LinkLayerMulticastAddress *MCastAddr;
  189. uint SizeofLLMA = SizeofLinkLayerMulticastAddress(IF);
  190. uint NumKeep, NumDeleted, NumAdded, Position;
  191. uint i;
  192. NDIS_STATUS Status;
  193. KIRQL OldIrql;
  194. ExFreePool(smc);
  195. //
  196. // First acquire the heavy-weight lock used to serialize
  197. // SetMCastAddrList operations.
  198. //
  199. KeWaitForSingleObject(&IF->WorkerLock, Executive, KernelMode,
  200. FALSE, NULL);
  201. //
  202. // Second acquire the lock that protects the interface,
  203. // so we can examine IF->MCastAddresses et al.
  204. //
  205. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  206. //
  207. // If this interface is going away, do nothing.
  208. //
  209. if (IsDisabledIF(IF)) {
  210. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  211. "SynchronizeMulticastContext(IF %p)"
  212. " - disabled (%u refs)\n", IF, IF->RefCnt));
  213. goto ErrorExit;
  214. }
  215. //
  216. // Allocate sufficient space for the link addresses
  217. // that we will pass to SetMCastAddrList.
  218. // This is actually an over-estimate.
  219. //
  220. LinkAddresses = ExAllocatePool(NonPagedPool,
  221. IF->MCastAddrNum * IF->LinkAddressLength);
  222. if (LinkAddresses == NULL) {
  223. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  224. "SynchronizeMulticastContext(IF %p) - no pool\n", IF));
  225. goto ErrorExit;
  226. }
  227. //
  228. // Make three passes through the address array,
  229. // constructing LinkAddresses.
  230. //
  231. NumKeep = 0;
  232. MCastAddr = IF->MCastAddresses;
  233. for (i = 0; i < IF->MCastAddrNum; i++) {
  234. if ((MCastAddr->RefCntAndFlags & LLMA_FLAG_REGISTERED) &&
  235. IsLLMAReferenced(MCastAddr)) {
  236. //
  237. // This address has already been registered,
  238. // and we are keeping it.
  239. //
  240. Position = NumKeep++;
  241. RtlCopyMemory(((uchar *)LinkAddresses +
  242. Position * IF->LinkAddressLength),
  243. MCastAddr->LinkAddress,
  244. IF->LinkAddressLength);
  245. }
  246. MCastAddr = (LinkLayerMulticastAddress *)
  247. ((uchar *)MCastAddr + SizeofLLMA);
  248. }
  249. if (NumKeep == IF->MCastAddrNum) {
  250. //
  251. // Can happen if there are races between worker threads,
  252. // but should be rare.
  253. //
  254. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  255. "SynchronizeMulticastAddresses - noop?\n"));
  256. ExFreePool(LinkAddresses);
  257. goto ErrorExit;
  258. }
  259. NumAdded = 0;
  260. MCastAddr = IF->MCastAddresses;
  261. for (i = 0; i < IF->MCastAddrNum; i++) {
  262. if (!(MCastAddr->RefCntAndFlags & LLMA_FLAG_REGISTERED) &&
  263. IsLLMAReferenced(MCastAddr)) {
  264. //
  265. // This address has not been registered,
  266. // and we are adding it.
  267. // We set LLMA_FLAG_REGISTERED below,
  268. // after we are past all error cases.
  269. //
  270. Position = NumKeep + NumAdded++;
  271. RtlCopyMemory(((uchar *)LinkAddresses +
  272. Position * IF->LinkAddressLength),
  273. MCastAddr->LinkAddress,
  274. IF->LinkAddressLength);
  275. }
  276. MCastAddr = (LinkLayerMulticastAddress *)
  277. ((uchar *)MCastAddr + SizeofLLMA);
  278. }
  279. NumDeleted = 0;
  280. MCastAddr = IF->MCastAddresses;
  281. for (i = 0; i < IF->MCastAddrNum; i++) {
  282. if ((MCastAddr->RefCntAndFlags & LLMA_FLAG_REGISTERED) &&
  283. !IsLLMAReferenced(MCastAddr)) {
  284. //
  285. // This address has already been registered,
  286. // and we are deleting it.
  287. //
  288. Position = NumKeep + NumAdded + NumDeleted++;
  289. RtlCopyMemory(((uchar *)LinkAddresses +
  290. Position * IF->LinkAddressLength),
  291. MCastAddr->LinkAddress,
  292. IF->LinkAddressLength);
  293. }
  294. MCastAddr = (LinkLayerMulticastAddress *)
  295. ((uchar *)MCastAddr + SizeofLLMA);
  296. }
  297. //
  298. // Some addresses might have been added & removed
  299. // before being registered, so they have a zero RefCnt.
  300. // We do not want to notify the link-layer about them.
  301. //
  302. ASSERT(NumKeep + NumAdded + NumDeleted <= IF->MCastAddrNum);
  303. //
  304. // Remove any unreferenced addresses.
  305. //
  306. if (NumKeep + NumAdded != IF->MCastAddrNum) {
  307. LinkLayerMulticastAddress *NewMCastAddresses;
  308. LinkLayerMulticastAddress *NewMCastAddr;
  309. LinkLayerMulticastAddress *MCastAddrMark;
  310. LinkLayerMulticastAddress *NextMCastAddr;
  311. UINT_PTR Length;
  312. if (NumKeep + NumAdded == 0) {
  313. //
  314. // None left.
  315. //
  316. NewMCastAddresses = NULL;
  317. }
  318. else {
  319. NewMCastAddresses = ExAllocatePool(NonPagedPool,
  320. ((NumKeep + NumAdded) * SizeofLLMA));
  321. if (NewMCastAddresses == NULL) {
  322. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  323. "SynchronizeMulticastContext(IF %p)"
  324. " - no pool\n", IF));
  325. ExFreePool(LinkAddresses);
  326. goto ErrorExit;
  327. }
  328. //
  329. // Copy the addresses that are still referenced
  330. // to the new array. Normally there will only be
  331. // one unreferenced address, so it's faster to search
  332. // for it and then copy the elements before and after.
  333. // Of course there might be multiple unreferenced addresses.
  334. //
  335. NewMCastAddr = NewMCastAddresses;
  336. MCastAddrMark = IF->MCastAddresses;
  337. for (i = 0, MCastAddr = IF->MCastAddresses;
  338. i < IF->MCastAddrNum;
  339. i++, MCastAddr = NextMCastAddr) {
  340. NextMCastAddr = (LinkLayerMulticastAddress *)
  341. ((uchar *)MCastAddr + SizeofLLMA);
  342. if (!IsLLMAReferenced(MCastAddr)) {
  343. //
  344. // Remove this address because it has no references.
  345. //
  346. if (MCastAddrMark < MCastAddr) {
  347. Length = (uchar *)MCastAddr - (uchar *)MCastAddrMark;
  348. RtlCopyMemory(NewMCastAddr, MCastAddrMark, Length);
  349. NewMCastAddr = (LinkLayerMulticastAddress *)
  350. ((uchar *)NewMCastAddr + Length);
  351. }
  352. MCastAddrMark = NextMCastAddr;
  353. }
  354. else {
  355. //
  356. // Remember that we are registering this address.
  357. //
  358. MCastAddr->RefCntAndFlags |= LLMA_FLAG_REGISTERED;
  359. }
  360. }
  361. if (MCastAddrMark < MCastAddr) {
  362. Length = (uchar *)MCastAddr - (uchar *)MCastAddrMark;
  363. RtlCopyMemory(NewMCastAddr, MCastAddrMark, Length);
  364. }
  365. }
  366. ExFreePool(IF->MCastAddresses);
  367. IF->MCastAddresses = NewMCastAddresses;
  368. IF->MCastAddrNum = NumKeep + NumAdded;
  369. }
  370. else {
  371. //
  372. // We need to set LLMA_FLAG_REGISTERED.
  373. //
  374. MCastAddr = IF->MCastAddresses;
  375. for (i = 0; i < IF->MCastAddrNum; i++) {
  376. MCastAddr->RefCntAndFlags |= LLMA_FLAG_REGISTERED;
  377. MCastAddr = (LinkLayerMulticastAddress *)
  378. ((uchar *)MCastAddr + SizeofLLMA);
  379. }
  380. }
  381. //
  382. // We have constructed the LinkAddresses array from the interface.
  383. // Before we can call SetMCastAddrList, we must drop the interface lock.
  384. // We still hold the heavy-weight WorkerLock, so multiple SetMCastAddrList
  385. // calls are properly serialized.
  386. //
  387. KeReleaseSpinLock(&IF->Lock, OldIrql);
  388. //
  389. // Pass the multicast link addresses down to the link layer,
  390. // if there's actually anything changed.
  391. //
  392. if (NumAdded + NumDeleted == 0) {
  393. //
  394. // Can happen if there are races between worker threads,
  395. // but should be very rare.
  396. //
  397. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  398. "SynchronizeMulticastAddresses - noop?\n"));
  399. }
  400. else {
  401. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  402. "SynchronizeMulticastAddresses(IF %p) %u + %u + %u\n",
  403. IF, NumKeep, NumAdded, NumDeleted));
  404. Status = (*IF->SetMCastAddrList)(IF->LinkContext, LinkAddresses,
  405. NumKeep, NumAdded, NumDeleted);
  406. if (Status != NDIS_STATUS_SUCCESS) {
  407. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  408. "SynchronizeMulticastAddresses(%p) -> %x\n", IF, Status));
  409. }
  410. }
  411. KeReleaseMutex(&IF->WorkerLock, FALSE);
  412. ExFreePool(LinkAddresses);
  413. ReleaseIF(IF);
  414. return;
  415. ErrorExit:
  416. KeReleaseSpinLock(&IF->Lock, OldIrql);
  417. KeReleaseMutex(&IF->WorkerLock, FALSE);
  418. ReleaseIF(IF);
  419. }
  420. //* DeferSynchronizeMulticastAddresses
  421. //
  422. // Because SynchronizeMulticastAddresses can only be called
  423. // from a thread context with no locks held, this function
  424. // provides a way to defer a call to SynchronizeMulticastAddresses
  425. // when running at DPC level.
  426. //
  427. // In error cases (memory allocation failure),
  428. // we return with IF_FLAG_MCAST_SYNC still set,
  429. // so we will be called again later.
  430. //
  431. // Called with the interface lock held.
  432. //
  433. void
  434. DeferSynchronizeMulticastAddresses(Interface *IF)
  435. {
  436. SynchronizeMulticastContext *smc;
  437. smc = ExAllocatePool(NonPagedPool, sizeof *smc);
  438. if (smc == NULL) {
  439. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  440. "DeferSynchronizeMulticastAddresses - no pool\n"));
  441. return;
  442. }
  443. ExInitializeWorkItem(&smc->WQItem, SynchronizeMulticastAddresses, smc);
  444. smc->IF = IF;
  445. AddRefIF(IF);
  446. IF->Flags &= ~IF_FLAG_MCAST_SYNC;
  447. ExQueueWorkItem(&smc->WQItem, CriticalWorkQueue);
  448. }
  449. //* CheckLinkLayerMulticastAddress
  450. //
  451. // Is the interface receiving this link-layer multicast address?
  452. //
  453. // Callable from thread or DPC context.
  454. // Called with no locks held.
  455. //
  456. int
  457. CheckLinkLayerMulticastAddress(Interface *IF, const void *LinkAddress)
  458. {
  459. if (IF->SetMCastAddrList == NULL) {
  460. //
  461. // The interface does not track multicast link-layer addresses.
  462. // For example, point-to-point or loopback interfaces.
  463. // We must assume that the interface wants to receive all
  464. // link-layer multicasts.
  465. //
  466. return TRUE;
  467. }
  468. else {
  469. KIRQL OldIrql;
  470. LinkLayerMulticastAddress *MCastAddr;
  471. uint SizeofLLMA = SizeofLinkLayerMulticastAddress(IF);
  472. uint i;
  473. int Found = FALSE;
  474. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  475. MCastAddr = IF->MCastAddresses;
  476. for (i = 0; i < IF->MCastAddrNum; i++) {
  477. //
  478. // Have we found the link-layer address?
  479. //
  480. if (RtlCompareMemory(MCastAddr->LinkAddress, LinkAddress,
  481. IF->LinkAddressLength) ==
  482. IF->LinkAddressLength) {
  483. if (IsLLMAReferenced(MCastAddr))
  484. Found = TRUE;
  485. break;
  486. }
  487. MCastAddr = (LinkLayerMulticastAddress *)
  488. ((uchar *)MCastAddr + SizeofLLMA);
  489. }
  490. KeReleaseSpinLock(&IF->Lock, OldIrql);
  491. return Found;
  492. }
  493. }
  494. //* AddLinkLayerMulticastAddress
  495. //
  496. // Called to indicate interest in the link-layer multicast address
  497. // corresponding to the supplied IPv6 multicast address.
  498. //
  499. // Called with the interface locked.
  500. //
  501. void
  502. AddLinkLayerMulticastAddress(Interface *IF, const IPv6Addr *Address)
  503. {
  504. //
  505. // If the interface doesn't keep track of link-layer multicast
  506. // addresses (e.g., if it's P2P), we don't need to do anything.
  507. //
  508. if (IF->SetMCastAddrList != NULL) {
  509. void *LinkAddress = alloca(IF->LinkAddressLength);
  510. LinkLayerMulticastAddress *MCastAddr;
  511. uint SizeofLLMA = SizeofLinkLayerMulticastAddress(IF);
  512. uint i;
  513. //
  514. // Create the link-layer multicast address
  515. // that corresponds to the IPv6 multicast address.
  516. //
  517. (*IF->ConvertAddr)(IF->LinkContext, Address, LinkAddress);
  518. //
  519. // Check if the link-layer multicast address is already present.
  520. //
  521. MCastAddr = IF->MCastAddresses;
  522. for (i = 0; i < IF->MCastAddrNum; i++) {
  523. //
  524. // Have we found the link-layer address?
  525. //
  526. if (RtlCompareMemory(MCastAddr->LinkAddress, LinkAddress,
  527. IF->LinkAddressLength) ==
  528. IF->LinkAddressLength)
  529. goto FoundMCastAddr;
  530. MCastAddr = (LinkLayerMulticastAddress *)
  531. ((uchar *)MCastAddr + SizeofLLMA);
  532. }
  533. //
  534. // We must add this link-layer multicast address.
  535. //
  536. MCastAddr = ExAllocatePool(NonPagedPool,
  537. (IF->MCastAddrNum + 1) * SizeofLLMA);
  538. if (MCastAddr == NULL) {
  539. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  540. "AddLinkLayerMulticastAddress - no pool\n"));
  541. return;
  542. }
  543. if (IF->MCastAddresses != NULL) {
  544. RtlCopyMemory(MCastAddr, IF->MCastAddresses,
  545. IF->MCastAddrNum * SizeofLLMA);
  546. ExFreePool(IF->MCastAddresses);
  547. }
  548. IF->MCastAddresses = MCastAddr;
  549. MCastAddr = (LinkLayerMulticastAddress *)
  550. ((uchar *)MCastAddr + IF->MCastAddrNum * SizeofLLMA);
  551. MCastAddr->RefCntAndFlags = 0;
  552. RtlCopyMemory(MCastAddr->LinkAddress, LinkAddress, IF->LinkAddressLength);
  553. IF->MCastAddrNum++;
  554. IF->Flags |= IF_FLAG_MCAST_SYNC;
  555. FoundMCastAddr:
  556. AddRefLLMA(MCastAddr);
  557. }
  558. }
  559. //* DelLinkLayerMulticastAddress
  560. //
  561. // Called to retract interest in the link-layer multicast address
  562. // corresponding to the supplied IPv6 multicast address.
  563. //
  564. // Called with the interface locked.
  565. //
  566. void
  567. DelLinkLayerMulticastAddress(Interface *IF, IPv6Addr *Address)
  568. {
  569. //
  570. // If the interface doesn't keep track of link-layer multicast
  571. // addresses (e.g., if it's P2P), we don't need to do anything.
  572. //
  573. if (IF->SetMCastAddrList != NULL) {
  574. void *LinkAddress = alloca(IF->LinkAddressLength);
  575. LinkLayerMulticastAddress *MCastAddr;
  576. uint SizeofLLMA = SizeofLinkLayerMulticastAddress(IF);
  577. uint i;
  578. //
  579. // Create the link-layer multicast address
  580. // that corresponds to the IPv6 multicast address.
  581. //
  582. (*IF->ConvertAddr)(IF->LinkContext, Address, LinkAddress);
  583. //
  584. // Find the link-layer multicast address.
  585. // It must be present, but if it isn't, we avoid crashing.
  586. //
  587. MCastAddr = IF->MCastAddresses;
  588. for (i = 0; i < IF->MCastAddrNum; i++) {
  589. //
  590. // Have we found the link-layer address?
  591. //
  592. if (RtlCompareMemory(MCastAddr->LinkAddress, LinkAddress,
  593. IF->LinkAddressLength) ==
  594. IF->LinkAddressLength) {
  595. //
  596. // Decrement the address's refcount.
  597. // If it hits zero, indicate a need to synchronize.
  598. //
  599. ASSERT(IsLLMAReferenced(MCastAddr));
  600. ReleaseLLMA(MCastAddr);
  601. if (!IsLLMAReferenced(MCastAddr))
  602. IF->Flags |= IF_FLAG_MCAST_SYNC;
  603. break;
  604. }
  605. MCastAddr = (LinkLayerMulticastAddress *)
  606. ((uchar *)MCastAddr + SizeofLLMA);
  607. }
  608. ASSERT(i != IF->MCastAddrNum);
  609. }
  610. }
  611. //* RestartLinkLayerMulticast
  612. //
  613. // Resets the status of link-layer multicast addresses,
  614. // so that they are registered again with the link layer.
  615. // The ResetDone function is called under a lock that serializes
  616. // it with SetMCastAddrList calls.
  617. //
  618. // Callable from thread context, not DPC context.
  619. //
  620. void
  621. RestartLinkLayerMulticast(
  622. void *Context,
  623. void (*ResetDone)(void *Context))
  624. {
  625. Interface *IF = (Interface *) Context;
  626. KIRQL OldIrql;
  627. ASSERT(IF->SetMCastAddrList != NULL);
  628. //
  629. // Serialize with SetMCastAddrList operations.
  630. //
  631. KeWaitForSingleObject(&IF->WorkerLock, Executive, KernelMode,
  632. FALSE, NULL);
  633. //
  634. // So we can play with IF->MCastAddresses et al.
  635. //
  636. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  637. //
  638. // If this interface is going away, do nothing.
  639. //
  640. if (IsDisabledIF(IF)) {
  641. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  642. "RestartLinkLayerMulticast(IF %p)"
  643. " - disabled (%u refs)\n", IF, IF->RefCnt));
  644. KeReleaseSpinLock(&IF->Lock, OldIrql);
  645. }
  646. else {
  647. LinkLayerMulticastAddress *MCastAddr;
  648. uint SizeofLLMA = SizeofLinkLayerMulticastAddress(IF);
  649. uint i;
  650. //
  651. // Reset the registered flag for all multicast addresses.
  652. //
  653. MCastAddr = IF->MCastAddresses;
  654. for (i = 0; i < IF->MCastAddrNum; i++) {
  655. if (IsLLMAReferenced(MCastAddr)) {
  656. MCastAddr->RefCntAndFlags &= ~LLMA_FLAG_REGISTERED;
  657. IF->Flags |= IF_FLAG_MCAST_SYNC;
  658. }
  659. MCastAddr = (LinkLayerMulticastAddress *)
  660. ((uchar *)MCastAddr + SizeofLLMA);
  661. }
  662. if (IsMCastSyncNeeded(IF))
  663. DeferSynchronizeMulticastAddresses(IF);
  664. KeReleaseSpinLock(&IF->Lock, OldIrql);
  665. //
  666. // Let the link-layer know that the reset is done.
  667. //
  668. (*ResetDone)(IF->LinkContext);
  669. }
  670. KeReleaseMutex(&IF->WorkerLock, FALSE);
  671. }
  672. typedef enum {
  673. CONTROL_LOOPBACK_DISABLED,
  674. CONTROL_LOOPBACK_ENABLED,
  675. CONTROL_LOOPBACK_DESTROY
  676. } ControlLoopbackOp;
  677. //* ControlLoopback
  678. //
  679. // Controls loopback functionality for a unicast or anycast address.
  680. //
  681. // This function is used in three ways, depending on Op:
  682. // create a disabled loopback route (or disable an existing route),
  683. // create an enabled loopback route (or enable an existing route),
  684. // destroy any existing loopback route.
  685. //
  686. // It returns FALSE if there is a resource shortage.
  687. // In actual usage, it will only fail when an NTE/AAE
  688. // is first created, because subsequently the RTE and NCE
  689. // will already exist.
  690. //
  691. // Called with the interface lock held.
  692. //
  693. int
  694. ControlLoopback(Interface *IF, const IPv6Addr *Address,
  695. ControlLoopbackOp Op)
  696. {
  697. NeighborCacheEntry *NCE;
  698. int Loopback;
  699. uint Lifetime;
  700. uint Type;
  701. int rc;
  702. NTSTATUS Status;
  703. switch (Op) {
  704. case CONTROL_LOOPBACK_DISABLED:
  705. Loopback = FALSE;
  706. Lifetime = 0;
  707. Type = RTE_TYPE_SYSTEM;
  708. break;
  709. case CONTROL_LOOPBACK_ENABLED:
  710. Loopback = TRUE;
  711. Lifetime = INFINITE_LIFETIME;
  712. Type = RTE_TYPE_SYSTEM;
  713. break;
  714. case CONTROL_LOOPBACK_DESTROY:
  715. Loopback = FALSE;
  716. Lifetime = 0;
  717. Type = 0; // Special value for destroying system routes.
  718. break;
  719. default:
  720. ABORTMSG("ControlLoopback bad op");
  721. return FALSE;
  722. }
  723. //
  724. // Get the NCE for this address.
  725. //
  726. NCE = FindOrCreateNeighbor(IF, Address);
  727. if (NCE == NULL)
  728. return FALSE;
  729. //
  730. // Update the loopback route for this address.
  731. //
  732. Status = RouteTableUpdate(NULL, // System update.
  733. IF, NCE, Address, IPV6_ADDRESS_LENGTH, 0,
  734. Lifetime, Lifetime,
  735. ROUTE_PREF_LOOPBACK,
  736. Type,
  737. FALSE, FALSE);
  738. if (NT_SUCCESS(Status)) {
  739. //
  740. // Update the address's loopback status in the neighbor cache.
  741. //
  742. ControlNeighborLoopback(NCE, Loopback);
  743. rc = TRUE;
  744. }
  745. else {
  746. //
  747. // If RouteTableUpdate failed because the interface is
  748. // being destroyed, then we succeed without doing anything.
  749. //
  750. rc = (Status == STATUS_INVALID_PARAMETER_1);
  751. }
  752. ReleaseNCE(NCE);
  753. return rc;
  754. }
  755. //* DeleteMAE
  756. //
  757. // Cleanup and delete an MAE because the multicast address
  758. // is no longer assigned to the interface.
  759. // It is already removed from the interface's list.
  760. //
  761. // Called with the interface already locked.
  762. //
  763. void
  764. DeleteMAE(Interface *IF, MulticastAddressEntry *MAE)
  765. {
  766. int SendDoneMsg;
  767. KeAcquireSpinLockAtDpcLevel(&QueryListLock);
  768. if (!IsDisabledIF(IF) && (MAE->MCastFlags & MAE_LAST_REPORTER)) {
  769. //
  770. // We need to send a Done message.
  771. // Put the MAE on the QueryList with a zero timer.
  772. //
  773. if (MAE->MCastTimer == 0)
  774. AddToQueryList(MAE);
  775. else
  776. MAE->MCastTimer = 0;
  777. AddRefIF(IF);
  778. MAE->IF = IF;
  779. SendDoneMsg = TRUE;
  780. }
  781. else {
  782. //
  783. // If the MLD timer is running, remove from the query list.
  784. //
  785. if (MAE->MCastTimer != 0)
  786. RemoveFromQueryList(MAE);
  787. SendDoneMsg = FALSE;
  788. }
  789. KeReleaseSpinLockFromDpcLevel(&QueryListLock);
  790. //
  791. // Retract our interest in the corresponding
  792. // link-layer multicast address.
  793. //
  794. DelLinkLayerMulticastAddress(IF, &MAE->Address);
  795. //
  796. // Delete the MAE, unless we left it on the QueryList
  797. // pending a Done message.
  798. //
  799. if (!SendDoneMsg)
  800. ExFreePool(MAE);
  801. }
  802. //* FindAndReleaseMAE
  803. //
  804. // Finds the MAE for a multicast address and releases one reference
  805. // for the MAE. May result in the MAE disappearing.
  806. //
  807. // If successful, returns the MAE.
  808. // Note that it may be an invalid pointer!
  809. // Returns NULL on failure.
  810. //
  811. // Called with the interface already locked.
  812. //
  813. MulticastAddressEntry *
  814. FindAndReleaseMAE(Interface *IF, const IPv6Addr *Addr)
  815. {
  816. AddressEntry **pADE;
  817. MulticastAddressEntry *MAE;
  818. pADE = FindADE(IF, Addr);
  819. MAE = (MulticastAddressEntry *) *pADE;
  820. if (MAE != NULL) {
  821. if (MAE->Type == ADE_MULTICAST) {
  822. ASSERT(MAE->MCastRefCount != 0);
  823. if (--MAE->MCastRefCount == 0) {
  824. //
  825. // The MAE has no more references.
  826. // Remove it from the Interface and delete it.
  827. //
  828. *pADE = MAE->Next;
  829. DeleteMAE(IF, MAE);
  830. }
  831. }
  832. else {
  833. //
  834. // Return NULL for error.
  835. //
  836. MAE = NULL;
  837. }
  838. }
  839. return MAE;
  840. }
  841. //* FindAndReleaseSolicitedNodeMAE
  842. //
  843. // Finds the MAE for the corresponding solicited-node multicast address
  844. // and releases one reference for the MAE.
  845. // May result in the MAE disappearing.
  846. //
  847. // Called with the interface already locked.
  848. //
  849. void
  850. FindAndReleaseSolicitedNodeMAE(Interface *IF, const IPv6Addr *Addr)
  851. {
  852. if (IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS) {
  853. IPv6Addr MCastAddr;
  854. MulticastAddressEntry *MAE;
  855. //
  856. // Create the corresponding solicited-node multicast address.
  857. //
  858. CreateSolicitedNodeMulticastAddress(Addr, &MCastAddr);
  859. //
  860. // Release the MAE for the solicited-node address.
  861. // NB: This may fail during interface shutdown
  862. // if we remove the solicited-node MAE before the NTE or AAE.
  863. //
  864. MAE = FindAndReleaseMAE(IF, &MCastAddr);
  865. ASSERT((MAE != NULL) || IsDisabledIF(IF));
  866. }
  867. }
  868. //* FindOrCreateMAE
  869. //
  870. // If an MAE for the multicast address already exists,
  871. // just bump the reference count. Otherwise create a new MAE.
  872. // Returns NULL for failure.
  873. //
  874. // If an NTE is supplied and an MAE is created,
  875. // then the MAE is associated with the NTE.
  876. //
  877. // Called with the interface already locked.
  878. //
  879. MulticastAddressEntry *
  880. FindOrCreateMAE(
  881. Interface *IF,
  882. const IPv6Addr *Addr,
  883. NetTableEntry *NTE)
  884. {
  885. AddressEntry **pADE;
  886. MulticastAddressEntry *MAE;
  887. //
  888. // Can not create a new MAE if the interface is shutting down.
  889. //
  890. if (IsDisabledIF(IF))
  891. return NULL;
  892. pADE = FindADE(IF, Addr);
  893. MAE = (MulticastAddressEntry *) *pADE;
  894. if (MAE == NULL) {
  895. //
  896. // Create a new MAE.
  897. //
  898. MAE = ExAllocatePool(NonPagedPool, sizeof(MulticastAddressEntry));
  899. if (MAE == NULL)
  900. return NULL;
  901. //
  902. // Initialize the new MAE.
  903. //
  904. if (NTE != NULL)
  905. MAE->NTE = NTE;
  906. else
  907. MAE->IF = IF;
  908. MAE->Address = *Addr;
  909. MAE->Type = ADE_MULTICAST;
  910. MAE->Scope = MulticastAddressScope(Addr);
  911. MAE->MCastRefCount = 0; // Incremented below.
  912. MAE->MCastTimer = 0;
  913. MAE->NextQL = NULL;
  914. //
  915. // With any luck the compiler will optimize these
  916. // field assignments...
  917. //
  918. if (IsMLDReportable(MAE)) {
  919. //
  920. // We should send MLD reports for this address.
  921. // Start by sending initial reports immediately.
  922. //
  923. MAE->MCastFlags = MAE_REPORTABLE;
  924. MAE->MCastCount = MLD_NUM_INITIAL_REPORTS;
  925. MAE->MCastTimer = 1; // Immediately.
  926. KeAcquireSpinLockAtDpcLevel(&QueryListLock);
  927. AddToQueryList(MAE);
  928. KeReleaseSpinLockFromDpcLevel(&QueryListLock);
  929. }
  930. else {
  931. MAE->MCastFlags = 0;
  932. MAE->MCastCount = 0;
  933. MAE->MCastTimer = 0;
  934. }
  935. //
  936. // Add the MAE to the interface's ADE list.
  937. //
  938. MAE->Next = NULL;
  939. *pADE = (AddressEntry *)MAE;
  940. //
  941. // Indicate our interest in the corresponding
  942. // link-layer multicast address.
  943. //
  944. AddLinkLayerMulticastAddress(IF, Addr);
  945. }
  946. else {
  947. ASSERT(MAE->Type == ADE_MULTICAST);
  948. }
  949. MAE->MCastRefCount++;
  950. return MAE;
  951. }
  952. //* FindOrCreateSolicitedNodeMAE
  953. //
  954. // Called with a unicast or anycast address.
  955. //
  956. // If an MAE for the solicited-node multicast address already exists,
  957. // just bump the reference count. Otherwise create a new MAE.
  958. // Returns TRUE for success.
  959. //
  960. // Called with the interface already locked.
  961. //
  962. int
  963. FindOrCreateSolicitedNodeMAE(Interface *IF, const IPv6Addr *Addr)
  964. {
  965. if (IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS) {
  966. IPv6Addr MCastAddr;
  967. //
  968. // Create the corresponding solicited-node multicast address.
  969. //
  970. CreateSolicitedNodeMulticastAddress(Addr, &MCastAddr);
  971. //
  972. // Find or create an MAE for the solicited-node multicast address.
  973. //
  974. return FindOrCreateMAE(IF, &MCastAddr, NULL) != NULL;
  975. }
  976. else {
  977. //
  978. // Only interfaces that support Neighbor Discovery
  979. // use solicited-node multicast addresses.
  980. //
  981. return TRUE;
  982. }
  983. }
  984. //* FindOrCreateAAE
  985. //
  986. // Adds an anycast address to the interface,
  987. // associated with the NTE.
  988. //
  989. // If the interface already has the anycast address assigned,
  990. // then this does nothing.
  991. //
  992. // Returns TRUE for success.
  993. //
  994. // Called with NO locks held.
  995. // Callable from thread or DPC context.
  996. //
  997. int
  998. FindOrCreateAAE(Interface *IF, const IPv6Addr *Addr,
  999. NetTableEntryOrInterface *NTEorIF)
  1000. {
  1001. AddressEntry **pADE;
  1002. AnycastAddressEntry *AAE;
  1003. KIRQL OldIrql;
  1004. int rc;
  1005. if (NTEorIF == NULL)
  1006. NTEorIF = CastFromIF(IF);
  1007. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  1008. if (IsDisabledIF(IF)) {
  1009. //
  1010. // Can't create a new AAE if the interface is shutting down.
  1011. //
  1012. rc = FALSE;
  1013. }
  1014. else {
  1015. pADE = FindADE(IF, Addr);
  1016. AAE = (AnycastAddressEntry *) *pADE;
  1017. if (AAE == NULL) {
  1018. //
  1019. // Create an AAE for the anycast address.
  1020. //
  1021. AAE = ExAllocatePool(NonPagedPool, sizeof(AnycastAddressEntry));
  1022. if (AAE == NULL) {
  1023. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1024. "FindOrCreateAAE: no pool\n"));
  1025. rc = FALSE;
  1026. goto ErrorReturn;
  1027. }
  1028. //
  1029. // Initialize the new AAE.
  1030. //
  1031. AAE->NTEorIF = NTEorIF;
  1032. AAE->Address = *Addr;
  1033. AAE->Type = ADE_ANYCAST;
  1034. AAE->Scope = UnicastAddressScope(Addr);
  1035. //
  1036. // Add the AAE to the interface's ADE list.
  1037. // NB: FindOrCreateSolicitedNodeMAE may add an MAE at the end,
  1038. // so we do this first.
  1039. //
  1040. AAE->Next = NULL;
  1041. *pADE = (AddressEntry *)AAE;
  1042. //
  1043. // Create the corresponding solicited-node
  1044. // multicast address MAE.
  1045. //
  1046. rc = FindOrCreateSolicitedNodeMAE(IF, Addr);
  1047. if (! rc) {
  1048. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1049. "FindOrCreateAAE: "
  1050. "FindOrCreateSolicitedNodeMAE failed\n"));
  1051. goto ErrorReturnFreeAAE;
  1052. }
  1053. //
  1054. // Create a loopback route for this address.
  1055. //
  1056. rc = ControlLoopback(IF, Addr, CONTROL_LOOPBACK_ENABLED);
  1057. if (! rc) {
  1058. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  1059. "FindOrCreateAAE: "
  1060. "ControlLoopback failed\n"));
  1061. FindAndReleaseSolicitedNodeMAE(IF, Addr);
  1062. ErrorReturnFreeAAE:
  1063. //
  1064. // An MAE may have been added & removed above,
  1065. // but at this point the AAE should be last.
  1066. //
  1067. ASSERT((*pADE == (AddressEntry *)AAE) && (AAE->Next == NULL));
  1068. *pADE = NULL;
  1069. ExFreePool(AAE);
  1070. ErrorReturn:
  1071. ;
  1072. }
  1073. }
  1074. else {
  1075. //
  1076. // The ADE already exists -
  1077. // just verify that it is anycast.
  1078. //
  1079. rc = (AAE->Type == ADE_ANYCAST);
  1080. }
  1081. if (IsMCastSyncNeeded(IF))
  1082. DeferSynchronizeMulticastAddresses(IF);
  1083. }
  1084. KeReleaseSpinLock(&IF->Lock, OldIrql);
  1085. return rc;
  1086. }
  1087. //* DeleteAAE
  1088. //
  1089. // Cleanup and delete an AAE.
  1090. // It is already removed from the interface's list.
  1091. //
  1092. // Called with the interface lock held.
  1093. //
  1094. void
  1095. DeleteAAE(Interface *IF, AnycastAddressEntry *AAE)
  1096. {
  1097. int rc;
  1098. //
  1099. // The corresponding solicited-node address is not needed.
  1100. //
  1101. FindAndReleaseSolicitedNodeMAE(IF, &AAE->Address);
  1102. //
  1103. // The loopback route is not needed.
  1104. //
  1105. rc = ControlLoopback(IF, &AAE->Address, CONTROL_LOOPBACK_DESTROY);
  1106. ASSERT(rc);
  1107. ExFreePool(AAE);
  1108. }
  1109. //* FindAndDeleteAAE
  1110. //
  1111. // Deletes an anycast address from the interface.
  1112. // Returns TRUE for success.
  1113. //
  1114. // Called with NO locks held.
  1115. // Callable from thread or DPC context.
  1116. //
  1117. int
  1118. FindAndDeleteAAE(Interface *IF, const IPv6Addr *Addr)
  1119. {
  1120. AddressEntry **pADE;
  1121. AnycastAddressEntry *AAE;
  1122. KIRQL OldIrql;
  1123. int rc;
  1124. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  1125. pADE = FindADE(IF, Addr);
  1126. AAE = (AnycastAddressEntry *) *pADE;
  1127. if (AAE != NULL) {
  1128. if (AAE->Type == ADE_ANYCAST) {
  1129. //
  1130. // Delete the AAE.
  1131. //
  1132. *pADE = AAE->Next;
  1133. DeleteAAE(IF, AAE);
  1134. rc = TRUE;
  1135. }
  1136. else {
  1137. //
  1138. // This is an error - it should be anycast.
  1139. //
  1140. rc = FALSE;
  1141. }
  1142. }
  1143. else {
  1144. //
  1145. // If the address already doesn't exist, then OK.
  1146. //
  1147. rc = TRUE;
  1148. }
  1149. if (IsMCastSyncNeeded(IF))
  1150. DeferSynchronizeMulticastAddresses(IF);
  1151. KeReleaseSpinLock(&IF->Lock, OldIrql);
  1152. return rc;
  1153. }
  1154. //* LeaveGroupAtAllScopes
  1155. //
  1156. // Leave a multicast group at all scopes.
  1157. // Called with the interface already locked.
  1158. //
  1159. void
  1160. LeaveGroupAtAllScopes(Interface *IF, IPv6Addr *GroupAddr, uint MaxScope)
  1161. {
  1162. IPv6Addr Address = *GroupAddr;
  1163. MulticastAddressEntry *MAE;
  1164. uint i;
  1165. for (i = 0;
  1166. ((i < sizeof MulticastScopes / sizeof MulticastScopes[0]) &&
  1167. (MulticastScopes[i] <= MaxScope));
  1168. i++) {
  1169. Address.s6_bytes[1] = (UCHAR)((Address.s6_bytes[1] & 0xf0) |
  1170. MulticastScopes[i]);
  1171. MAE = FindAndReleaseMAE(IF, &Address);
  1172. ASSERT(MAE != NULL);
  1173. }
  1174. }
  1175. //* JoinGroupAtAllScopes
  1176. //
  1177. // Join a multicast group at all scopes up to the specified scope.
  1178. // Returns TRUE for success.
  1179. // Called with the interface already locked.
  1180. //
  1181. int
  1182. JoinGroupAtAllScopes(Interface *IF, IPv6Addr *GroupAddr, uint MaxScope)
  1183. {
  1184. IPv6Addr Address = *GroupAddr;
  1185. MulticastAddressEntry *MAE;
  1186. uint i;
  1187. for (i = 0;
  1188. ((i < sizeof MulticastScopes / sizeof MulticastScopes[0]) &&
  1189. (MulticastScopes[i] <= MaxScope));
  1190. i++) {
  1191. Address.s6_bytes[1] = (UCHAR)((Address.s6_bytes[1] & 0xf0) |
  1192. MulticastScopes[i]);
  1193. MAE = FindOrCreateMAE(IF, &Address, NULL);
  1194. if (MAE == NULL) {
  1195. //
  1196. // Failure. Leave the groups that we did manage to join.
  1197. //
  1198. if (i != 0)
  1199. LeaveGroupAtAllScopes(IF, GroupAddr, MulticastScopes[i-1]);
  1200. return FALSE;
  1201. }
  1202. }
  1203. return TRUE;
  1204. }
  1205. //* DestroyADEs
  1206. //
  1207. // Destroy all AddressEntries that reference an NTE.
  1208. //
  1209. // Called with the interface already locked.
  1210. //
  1211. // (Actually, we are at DPC level because we hold the interface lock.)
  1212. //
  1213. void
  1214. DestroyADEs(Interface *IF, NetTableEntry *NTE)
  1215. {
  1216. AddressEntry *AnycastList = NULL;
  1217. AddressEntry *ADE, **PrevADE;
  1218. PrevADE = &IF->ADE;
  1219. while ((ADE = *PrevADE) != NULL) {
  1220. if (ADE == (AddressEntry *)NTE) {
  1221. //
  1222. // Remove the NTE from the list but do not
  1223. // free the memory - that happens later.
  1224. //
  1225. *PrevADE = ADE->Next;
  1226. }
  1227. else if (ADE->NTE == NTE) {
  1228. //
  1229. // Remove this ADE because it references the NTE.
  1230. //
  1231. *PrevADE = ADE->Next;
  1232. switch (ADE->Type) {
  1233. case ADE_UNICAST:
  1234. ABORTMSG("DestroyADEs: unicast ADE?\n");
  1235. break;
  1236. case ADE_ANYCAST: {
  1237. //
  1238. // We can't call FindAndReleaseSolicitedNodeMAE here
  1239. // because it could mess up our list traversal.
  1240. // So put the ADE on our temporary list and do it later.
  1241. //
  1242. ADE->Next = AnycastList;
  1243. AnycastList = ADE;
  1244. break;
  1245. }
  1246. case ADE_MULTICAST: {
  1247. MulticastAddressEntry *MAE = (MulticastAddressEntry *) ADE;
  1248. DeleteMAE(IF, MAE);
  1249. break;
  1250. }
  1251. }
  1252. }
  1253. else {
  1254. if (ADE->Type == ADE_UNICAST) {
  1255. TempNetTableEntry *TempNTE = (TempNetTableEntry *) ADE;
  1256. if ((TempNTE->AddrConf == ADDR_CONF_TEMPORARY) &&
  1257. (TempNTE->Public == NTE)) {
  1258. //
  1259. // Break the public/temporary association
  1260. // and invalidate the temporary address.
  1261. // We can't use DestroyNTE directly here
  1262. // because it would mess up our traversal.
  1263. //
  1264. TempNTE->Public = NULL;
  1265. TempNTE->ValidLifetime = 0;
  1266. TempNTE->PreferredLifetime = 0;
  1267. }
  1268. }
  1269. PrevADE = &ADE->Next;
  1270. }
  1271. }
  1272. //
  1273. // Now we can safely process the anycast ADEs.
  1274. //
  1275. while ((ADE = AnycastList) != NULL) {
  1276. AnycastList = ADE->Next;
  1277. DeleteAAE(IF, (AnycastAddressEntry *)ADE);
  1278. }
  1279. }
  1280. //* FindADE - find an ADE entry for the given interface.
  1281. //
  1282. // If the address is assigned to the interface,
  1283. // returns the address of the link pointing to the ADE.
  1284. // Otherwise returns a pointer to the link (currently NULL)
  1285. // where a new ADE should be added to extend the list.
  1286. //
  1287. // The caller must lock the IF before calling this function.
  1288. //
  1289. AddressEntry **
  1290. FindADE(
  1291. Interface *IF,
  1292. const IPv6Addr *Addr)
  1293. {
  1294. AddressEntry **pADE, *ADE;
  1295. //
  1296. // Check if address is assigned to the interface using the
  1297. // interface's ADE list.
  1298. //
  1299. // REVIEW: Change the ADE list to a more efficient data structure?
  1300. //
  1301. for (pADE = &IF->ADE; (ADE = *pADE) != NULL; pADE = &ADE->Next) {
  1302. if (IP6_ADDR_EQUAL(Addr, &ADE->Address))
  1303. break;
  1304. }
  1305. return pADE;
  1306. }
  1307. //* FindAddressOnInterface
  1308. //
  1309. // Looks for an ADE on the interface.
  1310. // If a unicast ADE is found, returns the ADE (an NTE) and ADE_UNICAST.
  1311. // If a multicast/anycast ADE is found, returns ADE->NTEorIF and ADE->Type.
  1312. // If an ADE is not found, returns the interface and ADE_NONE.
  1313. // Whether the interface or an NTE is returned,
  1314. // the return value (if non-NULL) holds a reference.
  1315. //
  1316. // Returns NULL only if the interface is disabled.
  1317. //
  1318. // In normal usage, callers should hold a reference
  1319. // for the interface. (So if the interface is returned,
  1320. // it is returned with a second reference.) But in some
  1321. // paths (for example IPv6Receive/IPv6HeaderReceive),
  1322. // the caller knows the interface exists but does not
  1323. // hold a reference for it.
  1324. //
  1325. // Callable from DPC context, not from thread context.
  1326. //
  1327. NetTableEntryOrInterface *
  1328. FindAddressOnInterface(
  1329. Interface *IF,
  1330. const IPv6Addr *Addr,
  1331. ushort *AddrType)
  1332. {
  1333. AddressEntry *ADE;
  1334. NetTableEntryOrInterface *NTEorIF;
  1335. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  1336. if (IsDisabledIF(IF)) {
  1337. NTEorIF = NULL;
  1338. }
  1339. else if ((ADE = *FindADE(IF, Addr)) != NULL) {
  1340. if ((*AddrType = ADE->Type) == ADE_UNICAST) {
  1341. NTEorIF = CastFromNTE((NetTableEntry *)ADE);
  1342. goto ReturnNTE;
  1343. }
  1344. else {
  1345. NTEorIF = ADE->NTEorIF;
  1346. if (IsNTE(NTEorIF))
  1347. ReturnNTE:
  1348. AddRefNTE(CastToNTE(NTEorIF));
  1349. else
  1350. goto ReturnIF;
  1351. }
  1352. }
  1353. else {
  1354. *AddrType = ADE_NONE;
  1355. NTEorIF = CastFromIF(IF);
  1356. ReturnIF:
  1357. AddRefIF(CastToIF(NTEorIF));
  1358. }
  1359. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  1360. return NTEorIF;
  1361. }
  1362. //
  1363. // We keep track of the number of outstanding
  1364. // register-net-address work items.
  1365. // (Using InterlockedIncrement/InterlockedDecrement.)
  1366. // This way we can wait in the IPUnload
  1367. // until they are all done.
  1368. //
  1369. ULONG OutstandingRegisterNetAddressCount = 0;
  1370. //
  1371. // Note that this structure wouldn't be needed if IoQueueWorkItem
  1372. // had been designed to call the user's routine with the WorkItem
  1373. // as an additional argument along with the DeviceObject and Context.
  1374. // Sigh.
  1375. //
  1376. typedef struct RegisterNetAddressContext {
  1377. PIO_WORKITEM WorkItem;
  1378. NetTableEntry *NTE;
  1379. } RegisterNetAddressContext;
  1380. //* RegisterNetAddressWorker - De/Registers an address with TDI.
  1381. //
  1382. // Worker function for calling TdiRegisterNetAddress.
  1383. //
  1384. // Called to register or deregister an address with TDI when any one of
  1385. // the following two events occur...
  1386. //
  1387. // 1. The corresponding NTE's DADState changes between valid/invalid
  1388. // states while its interface's media state is connected.
  1389. //
  1390. // 2. The corresponding NTE's interface media state changes between
  1391. // connected/disconnected while its DADState is DAD_STATE_PREFERRED.
  1392. // For this case, DisconnectADEs queues a worker on the connect to
  1393. // disconnect transition whereas on the reverse transition the worker
  1394. // is queued at the completion the duplicate address detection.
  1395. //
  1396. // Since TdiRegisterNetAddress must be called when running at
  1397. // IRQL < DISPATCH_LEVEL, we use this function via a worker thread.
  1398. //
  1399. // Called with a reference held on the NTE, which we release on exit.
  1400. //
  1401. void
  1402. RegisterNetAddressWorker(
  1403. PDEVICE_OBJECT DevObj, // Unused. Wish they passed the WorkItem instead.
  1404. PVOID Context) // A RegisterNetAddressContext struct.
  1405. {
  1406. RegisterNetAddressContext *MyContext = Context;
  1407. NetTableEntry *NTE = MyContext->NTE;
  1408. Interface *IF = NTE->IF;
  1409. int ShouldBeRegistered;
  1410. KIRQL OldIrql;
  1411. NTSTATUS Status;
  1412. uint ScopeId;
  1413. UNREFERENCED_PARAMETER(DevObj);
  1414. IoFreeWorkItem(MyContext->WorkItem);
  1415. ExFreePool(MyContext);
  1416. //
  1417. // The heavy-weight WorkerLock protects this code against
  1418. // multiple instantiations of itself without raising IRQL.
  1419. //
  1420. KeWaitForSingleObject(&IF->WorkerLock, Executive, KernelMode,
  1421. FALSE, NULL);
  1422. //
  1423. // Figure out what state we should be in.
  1424. // Note that IF->Lock protects DADState and IF->Flags,
  1425. // while IF->WorkerLock protects TdiRegistrationHandle.
  1426. //
  1427. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  1428. //
  1429. // An address should be registered with TDI iff it is in the
  1430. // preferred DAD state and its corresponding interface is
  1431. // connected.
  1432. //
  1433. ShouldBeRegistered = ((NTE->DADState == DAD_STATE_PREFERRED) &&
  1434. !(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED));
  1435. KeReleaseSpinLock(&IF->Lock, OldIrql);
  1436. //
  1437. // DetermineScopeId is correct, not IF->ZoneIndices[NTE->Scope]
  1438. // because we register "external" scopeids with TDI not internal
  1439. // scopeids.
  1440. //
  1441. ScopeId = DetermineScopeId(&NTE->Address, IF);
  1442. //
  1443. // We need to deregister the existing address if it shouldn't be
  1444. // registered any longer, or if we need to register a new address
  1445. // due to a scope id change.
  1446. //
  1447. if ((NTE->TdiRegistrationHandle != NULL) &&
  1448. (!ShouldBeRegistered ||
  1449. (NTE->TdiRegistrationScopeId != ScopeId))) {
  1450. Status = TdiDeregisterNetAddress(NTE->TdiRegistrationHandle);
  1451. if (Status == STATUS_SUCCESS) {
  1452. NTE->TdiRegistrationHandle = NULL;
  1453. }
  1454. else {
  1455. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1456. "RegisterNetAddressWorker: "
  1457. "TdiDeregisterNetAddress(%d/%s): %x\n",
  1458. IF->Index, FormatV6Address(&NTE->Address), Status));
  1459. //
  1460. // REVIEW: Should we requeue ourselves for another attempt?
  1461. //
  1462. }
  1463. }
  1464. if (ShouldBeRegistered) {
  1465. if (NTE->TdiRegistrationHandle == NULL) {
  1466. char Buffer[sizeof(TA_ADDRESS) + TDI_ADDRESS_LENGTH_IP6 - 1];
  1467. PTA_ADDRESS TAAddress = (PTA_ADDRESS) Buffer;
  1468. PTDI_ADDRESS_IP6 TDIAddress =
  1469. (PTDI_ADDRESS_IP6) &TAAddress->Address;
  1470. //
  1471. // Create TAAddress from NTE->Address.
  1472. //
  1473. TAAddress->AddressLength = TDI_ADDRESS_LENGTH_IP6;
  1474. TAAddress->AddressType = TDI_ADDRESS_TYPE_IP6;
  1475. TDIAddress->sin6_port = 0;
  1476. TDIAddress->sin6_flowinfo = 0;
  1477. *(IPv6Addr *)&TDIAddress->sin6_addr = NTE->Address;
  1478. TDIAddress->sin6_scope_id = ScopeId;
  1479. Status = TdiRegisterNetAddress(TAAddress, &IF->DeviceName, NULL,
  1480. &NTE->TdiRegistrationHandle);
  1481. if (Status == STATUS_SUCCESS) {
  1482. NTE->TdiRegistrationScopeId = ScopeId;
  1483. } else {
  1484. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1485. "RegisterNetAddressWorker: "
  1486. "TdiRegisterNetAddress(%d/%s): %x\n",
  1487. IF->Index, FormatV6Address(&NTE->Address), Status));
  1488. //
  1489. // Due to a bug in TdiRegisterNetAddress, we can't be
  1490. // guaranteed the handle will be NULL on error.
  1491. //
  1492. NTE->TdiRegistrationHandle = NULL;
  1493. //
  1494. // REVIEW: Should we requeue ourselves for another attempt?
  1495. //
  1496. }
  1497. }
  1498. }
  1499. KeReleaseMutex(&IF->WorkerLock, FALSE);
  1500. ReleaseNTE(NTE);
  1501. InterlockedDecrement((PLONG)&OutstandingRegisterNetAddressCount);
  1502. }
  1503. //* DeferRegisterNetAddress
  1504. //
  1505. // Queue a work item that will execute RegisterNetAddressWorker.
  1506. //
  1507. // Callable from thread or DPC context.
  1508. //
  1509. void
  1510. DeferRegisterNetAddress(
  1511. NetTableEntry *NTE) // NTE that needs work.
  1512. {
  1513. RegisterNetAddressContext *Context;
  1514. PIO_WORKITEM WorkItem;
  1515. Context = ExAllocatePool(NonPagedPool, sizeof *Context);
  1516. if (Context == NULL) {
  1517. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1518. "DeferRegisterNetAddress: ExAllocatePool failed\n"));
  1519. return;
  1520. }
  1521. WorkItem = IoAllocateWorkItem(IPDeviceObject);
  1522. if (WorkItem == NULL) {
  1523. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  1524. "DeferRegisterNetAddress: IoAllocateWorkItem failed\n"));
  1525. ExFreePool(Context);
  1526. return;
  1527. }
  1528. Context->WorkItem = WorkItem;
  1529. AddRefNTE(NTE);
  1530. Context->NTE = NTE;
  1531. InterlockedIncrement((PLONG)&OutstandingRegisterNetAddressCount);
  1532. IoQueueWorkItem(WorkItem, RegisterNetAddressWorker,
  1533. CriticalWorkQueue, Context);
  1534. }
  1535. //* AddrConfStartDAD
  1536. //
  1537. // Starts duplicate address detection for the address,
  1538. // unless DAD is disabled.
  1539. //
  1540. // Called with the interface locked.
  1541. //
  1542. void
  1543. AddrConfStartDAD(Interface *IF, NetTableEntry *NTE)
  1544. {
  1545. if ((IF->DupAddrDetectTransmits == 0) ||
  1546. !(IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS) ||
  1547. ((NTE->AddrConf == ADDR_CONF_TEMPORARY) &&
  1548. (MaxTempDADAttempts == 0))) {
  1549. //
  1550. // Duplicate Address Detection is disabled,
  1551. // so go straight to a valid state
  1552. // if we aren't already valid.
  1553. //
  1554. AddrConfNotDuplicate(IF, NTE);
  1555. }
  1556. else if (IF->Flags & IF_FLAG_MEDIA_DISCONNECTED) {
  1557. //
  1558. // The interface is not connected,
  1559. // so we can not perform DAD.
  1560. // When the interface is connected,
  1561. // ReconnectADEs will start DAD.
  1562. //
  1563. }
  1564. else {
  1565. //
  1566. // Initialize for DAD.
  1567. // Send first solicit at next IPv6Timeout.
  1568. //
  1569. NTE->DADCount = (ushort)IF->DupAddrDetectTransmits;
  1570. NTE->DADTimer = 1;
  1571. }
  1572. }
  1573. //* CreateNTE - Creates an NTE on an interface.
  1574. //
  1575. // Returns one reference for the caller.
  1576. //
  1577. // Callable from thread or DPC context.
  1578. // Called with the interface locked.
  1579. //
  1580. // (Actually, we are at DPC level because we hold the interface lock.)
  1581. //
  1582. NetTableEntry *
  1583. CreateNTE(Interface *IF, const IPv6Addr *Address, uint AddrConf,
  1584. uint ValidLifetime, uint PreferredLifetime)
  1585. {
  1586. uint Size;
  1587. NetTableEntry *NTE = NULL;
  1588. //
  1589. // The address must not already be assigned.
  1590. //
  1591. ASSERT(*FindADE(IF, Address) == NULL);
  1592. //
  1593. // Can't create a new NTE if the interface is shutting down.
  1594. //
  1595. if (IsDisabledIF(IF))
  1596. goto ErrorExit;
  1597. //
  1598. // Temporary addresses need extra fields,
  1599. // which are initialized by our caller.
  1600. //
  1601. if (AddrConf == ADDR_CONF_TEMPORARY)
  1602. Size = sizeof(TempNetTableEntry);
  1603. else
  1604. Size = sizeof(NetTableEntry);
  1605. NTE = ExAllocatePool(NonPagedPool, Size);
  1606. if (NTE == NULL)
  1607. goto ErrorExit;
  1608. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1609. "CreateNTE(IF %u/%p, Addr %s) -> NTE %p\n",
  1610. IF->Index, IF, FormatV6Address(Address), NTE));
  1611. //
  1612. // Initialize the NTE with one reference for our caller.
  1613. // (EnlivenNTE may add a second reference for the interface.)
  1614. //
  1615. RtlZeroMemory(NTE, Size);
  1616. NTE->Address = *Address;
  1617. NTE->Type = ADE_UNICAST;
  1618. NTE->Scope = UnicastAddressScope(Address);
  1619. AddNTEToInterface(IF, NTE);
  1620. NTE->RefCnt = 1;
  1621. NTE->AddrConf = (uchar)AddrConf;
  1622. NTE->ValidLifetime = ValidLifetime;
  1623. NTE->PreferredLifetime = PreferredLifetime;
  1624. NTE->DADState = DAD_STATE_INVALID;
  1625. //
  1626. // Create a disabled loopback route.
  1627. // We pre-allocate the loopback RTE and NCE now,
  1628. // and then enable them later when the address is valid.
  1629. //
  1630. if (!ControlLoopback(IF, Address, CONTROL_LOOPBACK_DISABLED))
  1631. goto ErrorExitCleanup;
  1632. //
  1633. // Add this NTE to the front of the NetTableList.
  1634. //
  1635. KeAcquireSpinLockAtDpcLevel(&NetTableListLock);
  1636. AddNTEToNetTableList(NTE);
  1637. KeReleaseSpinLockFromDpcLevel(&NetTableListLock);
  1638. //
  1639. // If the NTE should be alive, make it so.
  1640. //
  1641. if (NTE->ValidLifetime != 0)
  1642. EnlivenNTE(IF, NTE);
  1643. return NTE;
  1644. ErrorExitCleanup:
  1645. RemoveNTEFromInterface(IF, NTE);
  1646. ASSERT(NTE->RefCnt == 1);
  1647. ExFreePool(NTE);
  1648. ErrorExit:
  1649. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  1650. "CreateNTE(IF %u/%p, Addr %s) -> NTE %p failed\n",
  1651. IF->Index, IF, FormatV6Address(Address), NTE));
  1652. return NULL;
  1653. }
  1654. //* InterfaceIndex
  1655. //
  1656. // Allocates the next interface index.
  1657. //
  1658. uint
  1659. InterfaceIndex(void)
  1660. {
  1661. return (uint) InterlockedIncrement((PLONG) &NextIFIndex);
  1662. }
  1663. //* AddInterface
  1664. //
  1665. // Add a new interface to the global list.
  1666. //
  1667. void
  1668. AddInterface(Interface *IF)
  1669. {
  1670. KIRQL OldIrql;
  1671. KeAcquireSpinLock(&IFListLock, &OldIrql);
  1672. IF->Next = IFList;
  1673. IFList = IF;
  1674. IPSInfo.ipsi_numif++;
  1675. KeReleaseSpinLock(&IFListLock, OldIrql);
  1676. }
  1677. //* CreateGUIDFromName
  1678. //
  1679. // Given the string name of an interface, creates a corresponding guid.
  1680. // The guid is a hash of the string name.
  1681. //
  1682. void
  1683. CreateGUIDFromName(const char *Name, GUID *Guid)
  1684. {
  1685. MD5_CTX Context;
  1686. MD5Init(&Context);
  1687. MD5Update(&Context, (uchar *)Name, (uint)strlen(Name));
  1688. MD5Final(&Context);
  1689. memcpy(Guid, Context.digest, MD5DIGESTLEN);
  1690. }
  1691. //* CreateInterface
  1692. //
  1693. // Creates an IPv6 interface given some link-layer information.
  1694. // If successful, returns a reference for the interface.
  1695. //
  1696. // NB: With some NICs, NDIS will report that the adapter
  1697. // is disconnected after enabling the adapter. Then a second or two
  1698. // later, the adapter's status changes to connected.
  1699. // Presumably this has something to do with the miniport initialization,
  1700. // because the adapter is physically connected throughout.
  1701. // NDIS drops any packets that we send while the adapter is disconnected.
  1702. // So we must be careful that after the SetInterfaceLinkStatus, we (re)send
  1703. // the correct sequence of initialization packets (MLD, DAD, RA/RSs).
  1704. // To accomplish this, we postpone DAD while the interface is disconnected
  1705. // and we postpone sending RA/RSs. ReconnectADEs restarts MLD correctly
  1706. // for this situation so it does not need to be postponed.
  1707. //
  1708. // Callable from thread context, not DPC context.
  1709. //
  1710. // Return codes:
  1711. // STATUS_UNSUCCESSFUL
  1712. // STATUS_SUCCESS
  1713. //
  1714. NTSTATUS
  1715. CreateInterface(const GUID *Guid, const LLIPv6BindInfo *BindInfo,
  1716. void **Context)
  1717. {
  1718. UNICODE_STRING GuidName;
  1719. Interface *IF = NULL; // Interface being added.
  1720. KIRQL OldIrql;
  1721. uint IFSize;
  1722. uint IFExportNamePrefixLen;
  1723. NTSTATUS Status;
  1724. ASSERT(KeGetCurrentIrql() == 0);
  1725. ASSERT(BindInfo->lip_addrlen <= MAX_LINK_LAYER_ADDRESS_LENGTH);
  1726. //
  1727. // Prevent new interfaces from being created
  1728. // while the stack is unloading.
  1729. //
  1730. if (Unloading)
  1731. goto ErrorExit;
  1732. //
  1733. // Before doing the real work, take advantage of the link-layer
  1734. // address passed up here to re-seed our random number generator.
  1735. //
  1736. SeedRandom(BindInfo->lip_addr, BindInfo->lip_addrlen);
  1737. //
  1738. // Convert the guid to string form.
  1739. // It will be null-terminated.
  1740. //
  1741. Status = RtlStringFromGUID(Guid, &GuidName);
  1742. if (! NT_SUCCESS(Status))
  1743. goto ErrorExit;
  1744. ASSERT(GuidName.MaximumLength == GuidName.Length + sizeof(WCHAR));
  1745. ASSERT(((WCHAR *)GuidName.Buffer)[GuidName.Length/sizeof(WCHAR)] == UNICODE_NULL);
  1746. //
  1747. // Allocate memory to hold an interface.
  1748. // We also allocate extra space to hold the device name string.
  1749. //
  1750. IFExportNamePrefixLen = sizeof IPV6_EXPORT_STRING_PREFIX - sizeof(WCHAR);
  1751. IFSize = sizeof *IF + IFExportNamePrefixLen + GuidName.MaximumLength;
  1752. IF = ExAllocatePool(NonPagedPool, IFSize);
  1753. if (IF == NULL)
  1754. goto ErrorExitCleanupGuidName;
  1755. RtlZeroMemory(IF, sizeof *IF);
  1756. IF->IF = IF;
  1757. IF->Index = InterfaceIndex();
  1758. IF->Guid = *Guid;
  1759. //
  1760. // Start with one reference because this is an active interface.
  1761. // And one reference for our caller.
  1762. //
  1763. IF->RefCnt = 2;
  1764. //
  1765. // Create the null-terminated exported device name from the guid.
  1766. //
  1767. IF->DeviceName.Buffer = (PVOID) (IF + 1);
  1768. IF->DeviceName.MaximumLength = (USHORT) (IFSize - sizeof *IF);
  1769. IF->DeviceName.Length = IF->DeviceName.MaximumLength - sizeof(WCHAR);
  1770. RtlCopyMemory(IF->DeviceName.Buffer,
  1771. IPV6_EXPORT_STRING_PREFIX,
  1772. IFExportNamePrefixLen);
  1773. RtlCopyMemory((uchar *) IF->DeviceName.Buffer + IFExportNamePrefixLen,
  1774. GuidName.Buffer,
  1775. GuidName.MaximumLength);
  1776. KeInitializeSpinLock(&IF->Lock);
  1777. IF->Type = BindInfo->lip_type;
  1778. IF->Flags = (BindInfo->lip_flags & IF_FLAGS_BINDINFO);
  1779. if (BindInfo->lip_context == NULL)
  1780. IF->LinkContext = IF;
  1781. else
  1782. IF->LinkContext = BindInfo->lip_context;
  1783. IF->Transmit = BindInfo->lip_transmit;
  1784. IF->CreateToken = BindInfo->lip_token;
  1785. IF->ReadLLOpt = BindInfo->lip_rdllopt;
  1786. IF->WriteLLOpt = BindInfo->lip_wrllopt;
  1787. IF->ConvertAddr = BindInfo->lip_cvaddr;
  1788. IF->SetRouterLLAddress = BindInfo->lip_setrtrlladdr;
  1789. IF->SetMCastAddrList = BindInfo->lip_mclist;
  1790. IF->Close = BindInfo->lip_close;
  1791. IF->Cleanup = BindInfo->lip_cleanup;
  1792. IF->LinkAddressLength = BindInfo->lip_addrlen;
  1793. IF->LinkAddress = BindInfo->lip_addr;
  1794. //
  1795. // We round-up the link-layer header size to a multiple of 2.
  1796. // This aligns the IPv6 header appropriately for IPv6Addr.
  1797. // When NDIS is fixed so we don't need AdjustPacketBuffer,
  1798. // we should align the IPv6 header to a multiple of 8.
  1799. //
  1800. IF->LinkHeaderSize = ALIGN_UP(BindInfo->lip_hdrsize, ushort);
  1801. IF->TrueLinkMTU = BindInfo->lip_maxmtu;
  1802. IF->DefaultLinkMTU = BindInfo->lip_defmtu;
  1803. IF->LinkMTU = BindInfo->lip_defmtu;
  1804. IF->DefaultPreference = BindInfo->lip_pref;
  1805. IF->Preference = BindInfo->lip_pref;
  1806. IF->BaseReachableTime = REACHABLE_TIME;
  1807. IF->ReachableTime = CalcReachableTime(IF->BaseReachableTime);
  1808. IF->RetransTimer = RETRANS_TIMER;
  1809. IF->DefaultDupAddrDetectTransmits = BindInfo->lip_dadxmit;
  1810. IF->DupAddrDetectTransmits = BindInfo->lip_dadxmit;
  1811. IF->CurHopLimit = DefaultCurHopLimit;
  1812. IF->DefSitePrefixLength = DEFAULT_SITE_PREFIX_LENGTH;
  1813. //
  1814. // Neighbor discovery requires multicast capability
  1815. //
  1816. ASSERT((IF->Flags & IF_FLAG_MULTICAST) ||
  1817. !(IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS));
  1818. //
  1819. // Router discovery requires either multicast capability,
  1820. // or a SetRouterLLAddress handler, or a Teredo interface.
  1821. //
  1822. ASSERT((IF->Flags & IF_FLAG_MULTICAST) ||
  1823. (IF->SetRouterLLAddress != NULL) ||
  1824. (IF->Type == IF_TYPE_TUNNEL_TEREDO) ||
  1825. !(IF->Flags & IF_FLAG_ROUTER_DISCOVERS));
  1826. //
  1827. // All interfaces are considered to be on different links
  1828. // but in the same site, until configured otherwise.
  1829. //
  1830. InitZoneIndices(IF->ZoneIndices, IF->Index);
  1831. NeighborCacheInit(IF);
  1832. //
  1833. // The worker lock serializes some heavy-weight
  1834. // calls to upper & lower layers.
  1835. //
  1836. KeInitializeMutex(&IF->WorkerLock, 0);
  1837. //
  1838. // We need to get APCs while holding WorkerLock,
  1839. // so that we can get IO completions
  1840. // for our TDI calls on 6over4 interfaces.
  1841. // This is not a security problem because
  1842. // only kernel worker threads use WorkerLock
  1843. // so they can't be suspended by the user.
  1844. //
  1845. IF->WorkerLock.ApcDisable = 0;
  1846. //
  1847. // Initialize some random state for temporary addresses.
  1848. //
  1849. *(uint UNALIGNED *)&IF->TempState = Random();
  1850. //
  1851. // Register this interface's device name with TDI.
  1852. // We need to do this before assigning any unicast addresses to this IF,
  1853. // and also before grabbing the lock (thus setting IRQL to DISPATCH_LEVEL).
  1854. //
  1855. Status = TdiRegisterDeviceObject(&IF->DeviceName,
  1856. &IF->TdiRegistrationHandle);
  1857. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1858. "CreateInterface(IF %u/%p): %ls -> %x\n",
  1859. IF->Index, IF,
  1860. IF->DeviceName.Buffer,
  1861. Status));
  1862. if (Status != STATUS_SUCCESS)
  1863. goto ErrorExitCleanupIF;
  1864. //
  1865. // After this point, we either return successfully
  1866. // or cleanup via ErrorExitDestroyIF.
  1867. //
  1868. RtlFreeUnicodeString(&GuidName);
  1869. //
  1870. // Return the new Interface to our caller now.
  1871. // This makes it available to the link-layer when
  1872. // we call CreateToken etc, before CreateInterface returns.
  1873. //
  1874. *Context = IF;
  1875. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  1876. if (IF->Flags & IF_FLAG_ROUTER_DISCOVERS) {
  1877. //
  1878. // Join the all-nodes multicast groups.
  1879. //
  1880. if (! JoinGroupAtAllScopes(IF, &AllNodesOnLinkAddr,
  1881. ADE_LINK_LOCAL))
  1882. goto ErrorExitDestroyIF;
  1883. if (IF->Flags & IF_FLAG_ADVERTISES) {
  1884. //
  1885. // Join the all-routers multicast groups.
  1886. //
  1887. if (! JoinGroupAtAllScopes(IF, &AllRoutersOnLinkAddr,
  1888. ADE_SITE_LOCAL))
  1889. goto ErrorExitDestroyIF;
  1890. //
  1891. // Start sending Router Advertisements.
  1892. //
  1893. if (!(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED))
  1894. IF->RATimer = 1;
  1895. IF->RACount = MAX_INITIAL_RTR_ADVERTISEMENTS;
  1896. }
  1897. else {
  1898. //
  1899. // Start sending Router Solicitations.
  1900. // The first RS will have the required random delay,
  1901. // because we randomize when IPv6Timeout first fires.
  1902. //
  1903. if (!(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED))
  1904. IF->RSTimer = 1;
  1905. }
  1906. }
  1907. //
  1908. // Initialize RALast to a value safely in the past,
  1909. // so that when/if this interface first sends an RA
  1910. // it is not inhibited due to rate-limiting.
  1911. //
  1912. IF->RALast = IPv6TickCount - MIN_DELAY_BETWEEN_RAS;
  1913. if (IF->Flags & IF_FLAG_FORWARDS)
  1914. InterlockedIncrement((PLONG)&NumForwardingInterfaces);
  1915. if (IF->CreateToken != NULL) {
  1916. IPv6Addr Address;
  1917. NetTableEntry *NTE;
  1918. //
  1919. // Create a link-local address for this interface.
  1920. // Other addresses will be created later via stateless
  1921. // auto-configuration.
  1922. //
  1923. Address = LinkLocalPrefix;
  1924. (*IF->CreateToken)(IF->LinkContext, &Address);
  1925. NTE = CreateNTE(IF, &Address, ADDR_CONF_LINK,
  1926. INFINITE_LIFETIME, INFINITE_LIFETIME);
  1927. if (NTE == NULL)
  1928. goto ErrorExitDestroyIF;
  1929. //
  1930. // The LinkLocalNTE field does not hold a reference.
  1931. //
  1932. IF->LinkLocalNTE = NTE;
  1933. ReleaseNTE(NTE);
  1934. }
  1935. if (IsMCastSyncNeeded(IF))
  1936. DeferSynchronizeMulticastAddresses(IF);
  1937. KeReleaseSpinLock(&IF->Lock, OldIrql);
  1938. //
  1939. // Configure the interface from the registry.
  1940. //
  1941. ConfigureInterface(IF);
  1942. //
  1943. // Add ourselves to the front of the global interface list.
  1944. // This is done last so the interface is fully initialized
  1945. // when it shows up on the list.
  1946. //
  1947. AddInterface(IF);
  1948. //
  1949. // If the interface is multicast enabled, create a multicast route.
  1950. //
  1951. if (IF->Flags & IF_FLAG_MULTICAST) {
  1952. RouteTableUpdate(NULL, // System update.
  1953. IF, NULL,
  1954. &MulticastPrefix, 8, 0,
  1955. INFINITE_LIFETIME, INFINITE_LIFETIME,
  1956. ROUTE_PREF_ON_LINK,
  1957. RTE_TYPE_SYSTEM,
  1958. FALSE, FALSE);
  1959. }
  1960. return STATUS_SUCCESS;
  1961. ErrorExitDestroyIF:
  1962. //
  1963. // Prevent calls down to the link layer,
  1964. // since our return code notifies the link layer
  1965. // synchronously that it should clean up.
  1966. //
  1967. IF->Close = NULL;
  1968. IF->Cleanup = NULL;
  1969. IF->SetMCastAddrList = NULL;
  1970. KeReleaseSpinLock(&IF->Lock, OldIrql);
  1971. //
  1972. // Destroy the interface.
  1973. // This will cleanup addresses and routes.
  1974. // Then add the disabled interface to the list
  1975. // so InterfaceCleanup can find it after
  1976. // we release the last reference.
  1977. //
  1978. DestroyIF(IF);
  1979. AddInterface(IF);
  1980. ReleaseIF(IF);
  1981. goto ErrorExit;
  1982. ErrorExitCleanupIF:
  1983. //
  1984. // The interface has not been registered with TDI
  1985. // and there are no addresses, routes, etc.
  1986. // So we can just free it.
  1987. //
  1988. ASSERT(IF->RefCnt == 2);
  1989. ExFreePool(IF);
  1990. ErrorExitCleanupGuidName:
  1991. RtlFreeUnicodeString(&GuidName);
  1992. ErrorExit:
  1993. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  1994. "CreateInterface(IF %p) failed\n", IF));
  1995. return STATUS_UNSUCCESSFUL;
  1996. }
  1997. //
  1998. // We keep track of the number of outstanding
  1999. // deregister-interface work items.
  2000. // (Using InterlockedIncrement/InterlockedDecrement.)
  2001. // This way we can wait in the IPUnload
  2002. // until they are all done.
  2003. //
  2004. ULONG OutstandingDeregisterInterfaceCount = 0;
  2005. //
  2006. // Note that this structure wouldn't be needed if IoQueueWorkItem
  2007. // had been designed to call the user's routine with the WorkItem
  2008. // as an additional argument along with the DeviceObject and Context.
  2009. // Sigh.
  2010. //
  2011. typedef struct DeregisterInterfaceContext {
  2012. PIO_WORKITEM WorkItem;
  2013. Interface *IF;
  2014. } DeregisterInterfaceContext;
  2015. //* DeregisterInterfaceWorker - De/Registers an address with TDI.
  2016. //
  2017. // Worker function for calling TdiDeregisterDeviceObject.
  2018. // This is the last thing we do with the interface structure,
  2019. // so this routine also frees the interface.
  2020. // It has no references at this point.
  2021. //
  2022. void
  2023. DeregisterInterfaceWorker(
  2024. PDEVICE_OBJECT DevObj, // Unused. Wish they passed the WorkItem instead.
  2025. PVOID Context) // A DeregisterInterfaceContext struct.
  2026. {
  2027. DeregisterInterfaceContext *MyContext = Context;
  2028. Interface *IF = MyContext->IF;
  2029. NTSTATUS Status;
  2030. UNREFERENCED_PARAMETER(DevObj);
  2031. IoFreeWorkItem(MyContext->WorkItem);
  2032. ExFreePool(MyContext);
  2033. //
  2034. // Deregister the interface with TDI, if it was registered.
  2035. // The loopback interface is not registered.
  2036. //
  2037. if (IF->TdiRegistrationHandle != NULL) {
  2038. Status = TdiDeregisterDeviceObject(IF->TdiRegistrationHandle);
  2039. if (Status != STATUS_SUCCESS)
  2040. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  2041. "DeregisterInterfaceContext: "
  2042. "TdiDeregisterDeviceObject: %x\n", Status));
  2043. }
  2044. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  2045. "DeregisterInterfaceWorker(IF %u/%p) -> freed\n", IF->Index, IF));
  2046. //
  2047. // Perform final cleanup of the link-layer data structures.
  2048. //
  2049. if (IF->Cleanup != NULL)
  2050. (*IF->Cleanup)(IF->LinkContext);
  2051. ExFreePool(IF);
  2052. //
  2053. // Note that we've finished our cleanup.
  2054. //
  2055. InterlockedDecrement((PLONG)&OutstandingDeregisterInterfaceCount);
  2056. }
  2057. //* DeferDeregisterInterface
  2058. //
  2059. // Queue a work item that will execute DeregisterInterfaceWorker.
  2060. //
  2061. // Callable from thread or DPC context.
  2062. //
  2063. void
  2064. DeferDeregisterInterface(
  2065. Interface *IF)
  2066. {
  2067. DeregisterInterfaceContext *Context;
  2068. PIO_WORKITEM WorkItem;
  2069. Context = ExAllocatePool(NonPagedPool, sizeof *Context);
  2070. if (Context == NULL) {
  2071. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  2072. "DeferDeregisterInterface: ExAllocatePool failed\n"));
  2073. return;
  2074. }
  2075. WorkItem = IoAllocateWorkItem(IPDeviceObject);
  2076. if (WorkItem == NULL) {
  2077. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  2078. "DeferDeregisterInterface: IoAllocateWorkItem failed\n"));
  2079. ExFreePool(Context);
  2080. return;
  2081. }
  2082. Context->WorkItem = WorkItem;
  2083. Context->IF = IF;
  2084. InterlockedIncrement((PLONG)&OutstandingDeregisterInterfaceCount);
  2085. IoQueueWorkItem(WorkItem, DeregisterInterfaceWorker,
  2086. CriticalWorkQueue, Context);
  2087. }
  2088. //* DestroyIF
  2089. //
  2090. // Shuts down an interface, making the interface effectively disappear.
  2091. // The interface will actually be freed when its last ref is gone.
  2092. //
  2093. // Callable from thread context, not DPC context.
  2094. // Called with NO locks held.
  2095. //
  2096. void
  2097. DestroyIF(Interface *IF)
  2098. {
  2099. AddressEntry *ADE;
  2100. int WasDisabled;
  2101. KIRQL OldIrql;
  2102. //
  2103. // First things first: disable the interface.
  2104. // If it's already disabled, we're done.
  2105. //
  2106. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  2107. ASSERT(OldIrql == 0);
  2108. KeAcquireSpinLockAtDpcLevel(&IFListLock);
  2109. WasDisabled = IF->Flags & IF_FLAG_DISABLED;
  2110. IF->Flags |= IF_FLAG_DISABLED;
  2111. KeReleaseSpinLockFromDpcLevel(&IFListLock);
  2112. if (WasDisabled) {
  2113. KeReleaseSpinLock(&IF->Lock, OldIrql);
  2114. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  2115. "DestroyIF(IF %u/%p) - already disabled?\n",
  2116. IF->Index, IF));
  2117. return;
  2118. }
  2119. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  2120. "DestroyIF(IF %u/%p) -> disabled\n",
  2121. IF->Index, IF));
  2122. //
  2123. // Stop generating Router Solicitations and Advertisements.
  2124. //
  2125. IF->RSTimer = IF->RATimer = 0;
  2126. //
  2127. // If the interface is currently forwarding,
  2128. // disable forwarding.
  2129. //
  2130. InterfaceStopForwarding(IF);
  2131. //
  2132. // Destroy all the ADEs. Because the interface is disabled,
  2133. // new ADEs will not subsequently be created.
  2134. //
  2135. while ((ADE = IF->ADE) != NULL) {
  2136. //
  2137. // First, remove this ADE from the interface.
  2138. //
  2139. IF->ADE = ADE->Next;
  2140. switch (ADE->Type) {
  2141. case ADE_UNICAST: {
  2142. NetTableEntry *NTE = (NetTableEntry *) ADE;
  2143. DestroyNTE(IF, NTE);
  2144. break;
  2145. }
  2146. case ADE_ANYCAST: {
  2147. AnycastAddressEntry *AAE = (AnycastAddressEntry *) ADE;
  2148. DeleteAAE(IF, AAE);
  2149. break;
  2150. }
  2151. case ADE_MULTICAST: {
  2152. MulticastAddressEntry *MAE = (MulticastAddressEntry *) ADE;
  2153. DeleteMAE(IF, MAE);
  2154. break;
  2155. }
  2156. }
  2157. }
  2158. KeReleaseSpinLock(&IF->Lock, OldIrql);
  2159. //
  2160. // Shutdown the link-layer.
  2161. //
  2162. if (IF->Close != NULL)
  2163. (*IF->Close)(IF->LinkContext);
  2164. //
  2165. // Clean up routing associated with the interface.
  2166. //
  2167. RouteTableRemove(IF);
  2168. //
  2169. // Clean up reassembly buffers associated with the interface.
  2170. //
  2171. ReassemblyRemove(IF);
  2172. //
  2173. // Clean up upper-layer state associated with the interface.
  2174. //
  2175. TCPRemoveIF(IF);
  2176. //
  2177. // Release the reference that the interface
  2178. // held for itself by virtue of being active.
  2179. //
  2180. ReleaseIF(IF);
  2181. //
  2182. // At this point, any NTEs still exist
  2183. // and hold references for the interface.
  2184. // The next calls to NetTableCleanup
  2185. // and InterfaceCleanup will finish the cleanup.
  2186. //
  2187. }
  2188. //* DestroyInterface
  2189. //
  2190. // Called from a link layer to destroy an interface.
  2191. //
  2192. // May be called when the interface has zero references
  2193. // and is already being destroyed.
  2194. //
  2195. void
  2196. DestroyInterface(void *Context)
  2197. {
  2198. Interface *IF = (Interface *) Context;
  2199. DestroyIF(IF);
  2200. }
  2201. //* ReleaseInterface
  2202. //
  2203. // Called from the link-layer to release its reference
  2204. // for the interface.
  2205. //
  2206. void
  2207. ReleaseInterface(void *Context)
  2208. {
  2209. Interface *IF = (Interface *) Context;
  2210. ReleaseIF(IF);
  2211. }
  2212. //* UpdateLinkMTU
  2213. //
  2214. // Update the link's MTU, either because of administrative configuration
  2215. // or autoconfiguration from a Router Advertisement.
  2216. //
  2217. // Callable from thread or DPC context.
  2218. // Called with NO locks held.
  2219. //
  2220. void
  2221. UpdateLinkMTU(Interface *IF, uint MTU)
  2222. {
  2223. KIRQL OldIrql;
  2224. ASSERT((IPv6_MINIMUM_MTU <= MTU) && (MTU <= IF->TrueLinkMTU));
  2225. //
  2226. // If the interface is advertising, then it should
  2227. // send a new RA promptly because the RAs contain the MTU option.
  2228. // This is what really needs the lock and the IsDisabledIF check.
  2229. //
  2230. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  2231. if ((IF->LinkMTU != MTU) && !IsDisabledIF(IF)) {
  2232. IF->LinkMTU = MTU;
  2233. if (IF->Flags & IF_FLAG_ADVERTISES) {
  2234. //
  2235. // Send a Router Advertisement very soon.
  2236. //
  2237. IF->RATimer = 1;
  2238. }
  2239. }
  2240. KeReleaseSpinLock(&IF->Lock, OldIrql);
  2241. }
  2242. //* FindInterfaceFromIndex
  2243. //
  2244. // Given the index of an interface, finds the interface.
  2245. // Returns a reference for the interface, or
  2246. // returns NULL if no valid interface is found.
  2247. //
  2248. // Callable from thread or DPC context.
  2249. //
  2250. Interface *
  2251. FindInterfaceFromIndex(uint Index)
  2252. {
  2253. Interface *IF;
  2254. KIRQL OldIrql;
  2255. KeAcquireSpinLock(&IFListLock, &OldIrql);
  2256. for (IF = IFList; IF != NULL; IF = IF->Next) {
  2257. if (IF->Index == Index) {
  2258. //
  2259. // Fail to find disabled interfaces.
  2260. //
  2261. if (IsDisabledIF(IF))
  2262. IF = NULL;
  2263. else
  2264. AddRefIF(IF);
  2265. break;
  2266. }
  2267. }
  2268. KeReleaseSpinLock(&IFListLock, OldIrql);
  2269. return IF;
  2270. }
  2271. //* FindInterfaceFromGuid
  2272. //
  2273. // Given the guid of an interface, finds the interface.
  2274. // Returns a reference for the interface, or
  2275. // returns NULL if no valid interface is found.
  2276. //
  2277. // Callable from thread or DPC context.
  2278. //
  2279. Interface *
  2280. FindInterfaceFromGuid(const GUID *Guid)
  2281. {
  2282. Interface *IF;
  2283. KIRQL OldIrql;
  2284. KeAcquireSpinLock(&IFListLock, &OldIrql);
  2285. for (IF = IFList; IF != NULL; IF = IF->Next) {
  2286. if (RtlCompareMemory(&IF->Guid, Guid, sizeof(GUID)) == sizeof(GUID)) {
  2287. //
  2288. // Fail to find disabled interfaces.
  2289. //
  2290. if (IsDisabledIF(IF))
  2291. IF = NULL;
  2292. else
  2293. AddRefIF(IF);
  2294. break;
  2295. }
  2296. }
  2297. KeReleaseSpinLock(&IFListLock, OldIrql);
  2298. return IF;
  2299. }
  2300. //* FindNextInterface
  2301. //
  2302. // Returns the next valid (not disabled) interface.
  2303. // If the argument is NULL, returns the first valid interface.
  2304. // Returns NULL if there is no next valid interface.
  2305. //
  2306. // Callable from thread or DPC context.
  2307. //
  2308. Interface *
  2309. FindNextInterface(Interface *IF)
  2310. {
  2311. KIRQL OldIrql;
  2312. KeAcquireSpinLock(&IFListLock, &OldIrql);
  2313. if (IF == NULL)
  2314. IF = IFList;
  2315. else
  2316. IF = IF->Next;
  2317. for (; IF != NULL; IF = IF->Next) {
  2318. if (! IsDisabledIF(IF)) {
  2319. AddRefIF(IF);
  2320. break;
  2321. }
  2322. }
  2323. KeReleaseSpinLock(&IFListLock, OldIrql);
  2324. return IF;
  2325. }
  2326. //* FindInterfaceFromZone
  2327. //
  2328. // Given a scope level and a zone index, finds an interface
  2329. // belonging to the specified zone. The interface
  2330. // must be different than the specified OrigIf.
  2331. //
  2332. // Called with the global ZoneUpdateLock lock held.
  2333. // (So we are at DPC level.)
  2334. //
  2335. Interface *
  2336. FindInterfaceFromZone(Interface *OrigIF, uint Scope, uint Index)
  2337. {
  2338. Interface *IF;
  2339. KeAcquireSpinLockAtDpcLevel(&IFListLock);
  2340. for (IF = IFList; IF != NULL; IF = IF->Next) {
  2341. if ((IF != OrigIF) &&
  2342. !IsDisabledIF(IF) &&
  2343. (IF->ZoneIndices[Scope] == Index)) {
  2344. AddRefIF(IF);
  2345. break;
  2346. }
  2347. }
  2348. KeReleaseSpinLockFromDpcLevel(&IFListLock);
  2349. return IF;
  2350. }
  2351. //* FindNewZoneIndex
  2352. //
  2353. // This is a helper function for CheckZoneIndices.
  2354. //
  2355. // Given a scope level, finds an unused zone index
  2356. // for use at that scope level.
  2357. // We return the value one more than the largest
  2358. // value currently in use.
  2359. //
  2360. // Called with the global ZoneUpdateLock lock held.
  2361. // Called from DPC context.
  2362. //
  2363. uint
  2364. FindNewZoneIndex(uint Scope)
  2365. {
  2366. Interface *IF;
  2367. uint ZoneIndex = 1;
  2368. KeAcquireSpinLockAtDpcLevel(&IFListLock);
  2369. for (IF = IFList; IF != NULL; IF = IF->Next) {
  2370. if (!IsDisabledIF(IF)) {
  2371. if (ZoneIndex <= IF->ZoneIndices[Scope])
  2372. ZoneIndex = IF->ZoneIndices[Scope] + 1;
  2373. }
  2374. }
  2375. KeReleaseSpinLockFromDpcLevel(&IFListLock);
  2376. return ZoneIndex;
  2377. }
  2378. //* InitZoneIndices
  2379. //
  2380. // Initializes an array of zone indices to default values.
  2381. //
  2382. void
  2383. InitZoneIndices(
  2384. uint *ZoneIndices,
  2385. uint Index)
  2386. {
  2387. ushort Scope;
  2388. ZoneIndices[ADE_SMALLEST_SCOPE] = Index;
  2389. ZoneIndices[ADE_INTERFACE_LOCAL] = Index;
  2390. ZoneIndices[ADE_LINK_LOCAL] = Index;
  2391. for (Scope = ADE_LINK_LOCAL + 1; Scope <= ADE_LARGEST_SCOPE; Scope++)
  2392. ZoneIndices[Scope] = 1;
  2393. }
  2394. //* UpdateZoneIndices
  2395. //
  2396. // Helper function for updating zone indices on an interface.
  2397. //
  2398. // Called with the ZoneUpdateLock and the interface lock held.
  2399. //
  2400. void
  2401. UpdateZoneIndices(
  2402. Interface *IF,
  2403. uint *ZoneIndices)
  2404. {
  2405. int SiteIdChanged, LinkIdChanged;
  2406. AddressEntry *ADE;
  2407. NetTableEntry *NTE;
  2408. LinkIdChanged = (ZoneIndices[ADE_LINK_LOCAL] !=
  2409. IF->ZoneIndices[ADE_LINK_LOCAL]);
  2410. SiteIdChanged = (ZoneIndices[ADE_SITE_LOCAL] !=
  2411. IF->ZoneIndices[ADE_SITE_LOCAL]);
  2412. RtlCopyMemory(IF->ZoneIndices, ZoneIndices, sizeof IF->ZoneIndices);
  2413. //
  2414. // The following checks are just optimizations to avoid the for loop
  2415. // and to avoid unnecessarily calling RegisterNetAddressWorker.
  2416. //
  2417. if ((IF->Flags & IF_FLAG_MEDIA_DISCONNECTED) ||
  2418. (!LinkIdChanged && !SiteIdChanged))
  2419. return;
  2420. //
  2421. // Media is connected and the scope id has changed for unicast addresses.
  2422. // We need to inform TDI clients of the change in any relevant addresses.
  2423. //
  2424. for (ADE = IF->ADE; ADE != NULL; ADE = ADE->Next) {
  2425. //
  2426. // Nothing to do for anycast or multicast addresses.
  2427. //
  2428. if (ADE->Type != ADE_UNICAST)
  2429. continue;
  2430. if (((ADE->Scope == ADE_LINK_LOCAL) && LinkIdChanged) ||
  2431. ((ADE->Scope == ADE_SITE_LOCAL) && SiteIdChanged)) {
  2432. NTE = (NetTableEntry *) ADE;
  2433. if (NTE->DADState == DAD_STATE_PREFERRED) {
  2434. //
  2435. // Queue worker to tell TDI that this address has changed.
  2436. //
  2437. DeferRegisterNetAddress(NTE);
  2438. }
  2439. }
  2440. }
  2441. }
  2442. //* FindDefaultInterfaceForZone
  2443. //
  2444. // Given a scope level and a zone index, finds the default interface
  2445. // belonging to the specified zone. The default interface
  2446. // is the one that we assume destinations in the zone
  2447. // are on-link to, if there are no routes matching the destination.
  2448. //
  2449. // It is an error for the zone index to be zero, unless
  2450. // all our interfaces are in the same zone at that scope level.
  2451. // In which case zero (meaning unspecified) is actually not ambiguous.
  2452. //
  2453. // The default interface is returned as NULL upon failure,
  2454. // and with a reference upon success.
  2455. //
  2456. // Called with the route cache lock held.
  2457. // (So we are at DPC level.)
  2458. //
  2459. Interface *
  2460. FindDefaultInterfaceForZone(
  2461. uint Scope,
  2462. uint ScopeId)
  2463. {
  2464. Interface *FirstIF = NULL;
  2465. Interface *FoundIF = NULL;
  2466. Interface *IF;
  2467. KeAcquireSpinLockAtDpcLevel(&IFListLock);
  2468. for (IF = IFList; IF != NULL; IF = IF->Next) {
  2469. if (!IsDisabledIF(IF)) {
  2470. if (ScopeId == 0) {
  2471. //
  2472. // Do we have interfaces in two zones at this scope level?
  2473. //
  2474. if (FirstIF == NULL) {
  2475. FirstIF = IF;
  2476. }
  2477. else if (IF->ZoneIndices[Scope] !=
  2478. FirstIF->ZoneIndices[Scope]) {
  2479. //
  2480. // Stop now with an error.
  2481. //
  2482. ASSERT(FoundIF != NULL);
  2483. ReleaseIF(FoundIF);
  2484. FoundIF = NULL;
  2485. break;
  2486. }
  2487. }
  2488. //
  2489. // Can we potentially use this interface?
  2490. //
  2491. if ((ScopeId == 0) ||
  2492. (IF->ZoneIndices[Scope] == ScopeId)) {
  2493. if (FoundIF == NULL) {
  2494. FoundInterface:
  2495. AddRefIF(IF);
  2496. FoundIF = IF;
  2497. }
  2498. else {
  2499. //
  2500. // Is this new interface better than the previous one?
  2501. //
  2502. if (IF->Preference < FoundIF->Preference) {
  2503. ReleaseIF(FoundIF);
  2504. goto FoundInterface;
  2505. }
  2506. }
  2507. }
  2508. }
  2509. }
  2510. KeReleaseSpinLockFromDpcLevel(&IFListLock);
  2511. return FoundIF;
  2512. }
  2513. #pragma BEGIN_INIT
  2514. //* IPInit - Initialize ourselves.
  2515. //
  2516. // This routine is called during initialization from the OS-specific
  2517. // init code.
  2518. //
  2519. int // Returns: 0 if initialization failed, non-zero if it succeeds.
  2520. IPInit(void)
  2521. {
  2522. NDIS_STATUS Status;
  2523. LARGE_INTEGER Time;
  2524. uint InitialWakeUp;
  2525. uchar InitialRandomBits[16]; // This size was arbitrarily chosen.
  2526. ASSERT(ConvertSecondsToTicks(0) == 0);
  2527. ASSERT(ConvertSecondsToTicks(INFINITE_LIFETIME) == INFINITE_LIFETIME);
  2528. ASSERT(ConvertSecondsToTicks(1) == IPv6_TICKS_SECOND);
  2529. ASSERT(ConvertTicksToSeconds(0) == 0);
  2530. ASSERT(ConvertTicksToSeconds(IPv6_TICKS_SECOND) == 1);
  2531. ASSERT(ConvertTicksToSeconds(INFINITE_LIFETIME) == INFINITE_LIFETIME);
  2532. ASSERT(ConvertMillisToTicks(1000) == IPv6_TICKS_SECOND);
  2533. ASSERT(ConvertMillisToTicks(1) > 0);
  2534. KeInitializeSpinLock(&NetTableListLock);
  2535. KeInitializeSpinLock(&IFListLock);
  2536. KeInitializeSpinLock(&ZoneUpdateLock);
  2537. //
  2538. // Perform initial seed of our psuedo-random number generator using
  2539. // 'random' bits from the KSecDD driver. KSecDD reportedly seeds itself
  2540. // with various system-unique values, which is exactly what we want
  2541. // (in order to avoid synchronicity issues between machines).
  2542. //
  2543. if (!GetSystemRandomBits(InitialRandomBits, sizeof(InitialRandomBits))) {
  2544. return FALSE;
  2545. }
  2546. SeedRandom(InitialRandomBits, sizeof(InitialRandomBits));
  2547. //
  2548. // Prepare our periodic timer and its associated DPC object.
  2549. //
  2550. // When the timer expires, the IPv6Timeout deferred procedure
  2551. // call (DPC) is queued. Everything we need to do at some
  2552. // specific frequency is driven off of this routine.
  2553. //
  2554. // We wait to start the timer until all our datastructures have
  2555. // been initialized below.
  2556. //
  2557. KeInitializeDpc(&IPv6TimeoutDpc, IPv6Timeout, NULL); // No parameter.
  2558. KeInitializeTimer(&IPv6Timer);
  2559. // Initialize the ProtocolSwitchTable.
  2560. ProtoTabInit();
  2561. //
  2562. // Create Packet and Buffer pools for IPv6.
  2563. //
  2564. switch (MmQuerySystemSize()) {
  2565. case MmSmallSystem:
  2566. PacketPoolSize = SMALL_POOL;
  2567. break;
  2568. case MmMediumSystem:
  2569. PacketPoolSize = MEDIUM_POOL;
  2570. break;
  2571. case MmLargeSystem:
  2572. default:
  2573. PacketPoolSize = LARGE_POOL;
  2574. break;
  2575. }
  2576. NdisAllocatePacketPool(&Status, &IPv6PacketPool,
  2577. PacketPoolSize, sizeof(Packet6Context));
  2578. if (Status != NDIS_STATUS_SUCCESS)
  2579. return FALSE;
  2580. //
  2581. // Currently, the size we pass to NdisAllocateBufferPool is ignored.
  2582. //
  2583. NdisAllocateBufferPool(&Status, &IPv6BufferPool, PacketPoolSize);
  2584. if (Status != NDIS_STATUS_SUCCESS)
  2585. return FALSE;
  2586. ReassemblyInit();
  2587. ICMPv6Init();
  2588. if (!IPSecInit())
  2589. return FALSE;
  2590. //
  2591. // Start the routing module.
  2592. //
  2593. InitRouting();
  2594. InitSelect();
  2595. //
  2596. // Start the IPv6 timer.
  2597. // Our data structures should all be initialized now.
  2598. //
  2599. // Start the timer with an initial relative expiration time and
  2600. // also a recurring period. The initial expiration time is
  2601. // negative (to indicate a relative time), and in 100ns units, so
  2602. // we first have to do some conversions. The initial expiration
  2603. // time is randomized to help prevent synchronization between
  2604. // different machines.
  2605. //
  2606. InitialWakeUp = RandomNumber(0, IPv6_TIMEOUT * 10000);
  2607. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  2608. "IPv6: InitialWakeUp = %u\n", InitialWakeUp));
  2609. Time.QuadPart = - (LONGLONG) InitialWakeUp;
  2610. KeSetTimerEx(&IPv6Timer, Time, IPv6_TIMEOUT, &IPv6TimeoutDpc);
  2611. //
  2612. // First create the loopback interface,
  2613. // so it will be interface 1.
  2614. //
  2615. if (!LoopbackInit())
  2616. return FALSE; // Couldn't initialize loopback.
  2617. //
  2618. // Second create the tunnel interface,
  2619. // so it will be interface 2.
  2620. // This can also result in 6over4 interfaces.
  2621. //
  2622. if (!TunnelInit())
  2623. return FALSE; // Couldn't initialize tunneling.
  2624. //
  2625. // Finally initialize with ndis,
  2626. // so ethernet interfaces can be created.
  2627. //
  2628. if (!LanInit())
  2629. return FALSE; // Couldn't initialize with ndis.
  2630. return TRUE;
  2631. }
  2632. #pragma END_INIT
  2633. //* IPUnload
  2634. //
  2635. // Called to shutdown the IP module in preparation
  2636. // for unloading the protocol stack.
  2637. //
  2638. void
  2639. IPUnload(void)
  2640. {
  2641. Interface *IF;
  2642. KIRQL OldIrql;
  2643. TdiDeregisterProvider(IPv6ProviderHandle);
  2644. //
  2645. // Stop the periodic timer.
  2646. //
  2647. KeCancelTimer(&IPv6Timer);
  2648. //
  2649. // Call each interface's close function.
  2650. // Note that interfaces might disappear while
  2651. // the interface list is unlocked,
  2652. // but new interfaces will not be created
  2653. // and the list does not get reordered.
  2654. //
  2655. KeAcquireSpinLock(&IFListLock, &OldIrql);
  2656. for (IF = IFList; IF != NULL; IF = IF->Next) {
  2657. AddRefIF(IF);
  2658. KeReleaseSpinLock(&IFListLock, OldIrql);
  2659. DestroyIF(IF);
  2660. KeAcquireSpinLock(&IFListLock, &OldIrql);
  2661. ReleaseIF(IF);
  2662. }
  2663. KeReleaseSpinLock(&IFListLock, OldIrql);
  2664. //
  2665. // DestroyIF/DestroyNTE spawned RegisterNetAddressWorker threads.
  2666. // Wait for them all to finish executing.
  2667. // This needs to be done before NetTableCleanup.
  2668. //
  2669. while (OutstandingRegisterNetAddressCount != 0) {
  2670. LARGE_INTEGER Interval;
  2671. Interval.QuadPart = -1; // Shortest possible relative wait.
  2672. KeDelayExecutionThread(KernelMode, FALSE, &Interval);
  2673. }
  2674. //
  2675. // TunnelUnload needs to be after calling DestroyIF
  2676. // on all the interfaces and before InterfaceCleanup.
  2677. //
  2678. TunnelUnload();
  2679. NetTableCleanup();
  2680. InterfaceCleanup();
  2681. UnloadSelect();
  2682. UnloadRouting();
  2683. IPSecUnload();
  2684. ReassemblyUnload();
  2685. ASSERT(NumForwardingInterfaces == 0);
  2686. ASSERT(IPSInfo.ipsi_numif == 0);
  2687. //
  2688. // InterfaceCleanup spawned DeregisterInterfaceWorker threads.
  2689. // Wait for them all to finish executing.
  2690. // Unfortunately, there is no good builtin synchronization primitive
  2691. // for this task. However, in practice because of the relative
  2692. // priorities of the threads involved, we almost never actually
  2693. // wait here. So this solution is quite efficient.
  2694. //
  2695. while (OutstandingDeregisterInterfaceCount != 0) {
  2696. LARGE_INTEGER Interval;
  2697. Interval.QuadPart = -1; // Shortest possible relative wait.
  2698. KeDelayExecutionThread(KernelMode, FALSE, &Interval);
  2699. }
  2700. #if DBG
  2701. {
  2702. NetTableEntry *NTE;
  2703. for (NTE = NetTableList; NTE != NULL; NTE = NTE->NextOnNTL) {
  2704. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  2705. "Leaked NTE %p (IF %u/%p) Addr %s Refs %u\n",
  2706. NTE, NTE->IF->Index, NTE->IF,
  2707. FormatV6Address(&NTE->Address),
  2708. NTE->RefCnt));
  2709. }
  2710. for (IF = IFList; IF != NULL; IF = IF->Next) {
  2711. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  2712. "Leaked IF %u/%p Refs %u\n",
  2713. IF->Index, IF, IF->RefCnt));
  2714. }
  2715. }
  2716. #endif // DBG
  2717. //
  2718. // We must wait until all the interfaces are completely cleaned up
  2719. // by DeregisterInterfaceWorker before freeing the packet pools.
  2720. // This is because Lan interfaces hold onto a packet (ai_tdpacket)
  2721. // that is freed in LanCleanupAdapter. NdisFreePacketPool
  2722. // blows away any packets that are still allocated so we can't call
  2723. // IPv6FreePacket after NdisFreePacketPool/NdisFreeBufferPool.
  2724. //
  2725. NdisFreePacketPool(IPv6PacketPool);
  2726. NdisFreeBufferPool(IPv6BufferPool);
  2727. }
  2728. //* GetLinkLocalNTE
  2729. //
  2730. // Returns the interface's link-local NTE (without a reference), or
  2731. // returns NULL if the interface does not have a valid link-local address.
  2732. //
  2733. // Called with the interface locked.
  2734. //
  2735. NetTableEntry *
  2736. GetLinkLocalNTE(Interface *IF)
  2737. {
  2738. NetTableEntry *NTE;
  2739. NTE = IF->LinkLocalNTE;
  2740. if ((NTE == NULL) || !IsValidNTE(NTE)) {
  2741. //
  2742. // If we didn't find a valid NTE in the LinkLocalNTE field,
  2743. // search the ADE list and cache the first valid link-local NTE
  2744. // we find (if any).
  2745. //
  2746. for (NTE = (NetTableEntry *) IF->ADE;
  2747. NTE != NULL;
  2748. NTE = (NetTableEntry *) NTE->Next) {
  2749. if ((NTE->Type == ADE_UNICAST) &&
  2750. IsValidNTE(NTE) &&
  2751. IsLinkLocal(&NTE->Address)) {
  2752. //
  2753. // Cache this NTE for future reference.
  2754. //
  2755. IF->LinkLocalNTE = NTE;
  2756. break;
  2757. }
  2758. }
  2759. }
  2760. return NTE;
  2761. }
  2762. //* GetLinkLocalAddress
  2763. //
  2764. // Returns the interface's link-local address,
  2765. // if it is valid. Otherwise, returns
  2766. // the unspecified address.
  2767. //
  2768. // Callable from thread or DPC context.
  2769. //
  2770. // Returns FALSE if the link-local address is not valid.
  2771. //
  2772. int
  2773. GetLinkLocalAddress(
  2774. Interface *IF, // Interface for which to find an address.
  2775. IPv6Addr *Addr) // Where to return address found (or unspecified).
  2776. {
  2777. KIRQL OldIrql;
  2778. NetTableEntry *NTE;
  2779. int Status;
  2780. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  2781. NTE = GetLinkLocalNTE(IF);
  2782. Status = (NTE != NULL);
  2783. if (Status)
  2784. *Addr = NTE->Address;
  2785. else
  2786. *Addr = UnspecifiedAddr;
  2787. KeReleaseSpinLock(&IF->Lock, OldIrql);
  2788. return Status;
  2789. }
  2790. //* FindOrCreateNTE
  2791. //
  2792. // Find the specified unicast address.
  2793. // If it already exists, update it.
  2794. // If it doesn't exist, create it if the lifetime is non-zero.
  2795. //
  2796. // Returns TRUE for success.
  2797. //
  2798. // Called with NO locks held.
  2799. // Callable from thread or DPC context.
  2800. //
  2801. int
  2802. FindOrCreateNTE(
  2803. Interface *IF,
  2804. const IPv6Addr *Addr,
  2805. uint AddrConf,
  2806. uint ValidLifetime,
  2807. uint PreferredLifetime)
  2808. {
  2809. NetTableEntry *NTE;
  2810. KIRQL OldIrql;
  2811. int rc;
  2812. ASSERT(!IsMulticast(Addr) && !IsUnspecified(Addr) &&
  2813. (!IsLoopback(Addr) || (IF == LoopInterface)));
  2814. ASSERT(PreferredLifetime <= ValidLifetime);
  2815. ASSERT(AddrConf != ADDR_CONF_TEMPORARY);
  2816. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  2817. NTE = (NetTableEntry *) *FindADE(IF, Addr);
  2818. if (NTE == NULL) {
  2819. //
  2820. // There is no such address, so create it.
  2821. //
  2822. NTE = CreateNTE(IF, Addr, AddrConf, ValidLifetime, PreferredLifetime);
  2823. if (NTE == NULL) {
  2824. rc = FALSE;
  2825. }
  2826. else {
  2827. ReleaseNTE(NTE);
  2828. rc = TRUE;
  2829. }
  2830. }
  2831. else if ((NTE->Type == ADE_UNICAST) &&
  2832. (NTE->AddrConf == AddrConf)) {
  2833. //
  2834. // Update the address lifetimes.
  2835. // If we set the lifetime to zero, AddrConfTimeout will remove it.
  2836. // NB: We do not allow NTE->AddrConf to change.
  2837. //
  2838. NTE->ValidLifetime = ValidLifetime;
  2839. NTE->PreferredLifetime = PreferredLifetime;
  2840. rc = TRUE;
  2841. }
  2842. else {
  2843. //
  2844. // We found the address, but we can't update it.
  2845. //
  2846. rc = FALSE;
  2847. }
  2848. if (IsMCastSyncNeeded(IF))
  2849. DeferSynchronizeMulticastAddresses(IF);
  2850. KeReleaseSpinLock(&IF->Lock, OldIrql);
  2851. return rc;
  2852. }
  2853. //* CreateTemporaryAddress
  2854. //
  2855. // Creates an temporary address for the interface.
  2856. //
  2857. // Called with the interface locked.
  2858. //
  2859. void
  2860. CreateTemporaryAddress(Interface *IF, const IPv6Addr *Prefix, IPv6Addr *Addr)
  2861. {
  2862. uint Now = IPv6TickCount;
  2863. if (TempRandomTime == 0) {
  2864. //
  2865. // We delay initializing TempRandomTime until it is needed.
  2866. // This way the random number generator has been initialized.
  2867. //
  2868. TempRandomTime = RandomNumber(0, MaxTempRandomTime);
  2869. }
  2870. //
  2871. // First, update the state that we use if it is too old.
  2872. //
  2873. if ((IF->TempStateAge == 0) ||
  2874. (UseTemporaryAddresses == USE_TEMP_ALWAYS) ||
  2875. ((uint)(Now - IF->TempStateAge) >=
  2876. (TempPreferredLifetime - TempRegenerateTime))) {
  2877. TryAgain:
  2878. IF->TempStateAge = Now;
  2879. if (UseTemporaryAddresses == USE_TEMP_COUNTER) {
  2880. //
  2881. // When testing, it's convenient to use interface identifiers
  2882. // that aren't actually random.
  2883. //
  2884. *(UINT UNALIGNED *)&IF->TempState.s6_bytes[12] =
  2885. net_long(net_long(*(UINT UNALIGNED *)&IF->TempState.s6_bytes[12]) + 1);
  2886. }
  2887. else {
  2888. MD5_CTX Context;
  2889. //
  2890. // The high half of IF->TempState is our history value.
  2891. // The low half is the temporary interface identifier.
  2892. //
  2893. // Append the history value to the usual interface identifier,
  2894. // and calculate the MD5 digest of the resulting quantity.
  2895. // Note MD5 digests and IPv6 addresses are the both 16 bytes,
  2896. // while our history value and the interface identifer are 8 bytes.
  2897. //
  2898. (*IF->CreateToken)(IF->LinkContext, &IF->TempState);
  2899. MD5Init(&Context);
  2900. MD5Update(&Context, (uchar *)&IF->TempState, sizeof IF->TempState);
  2901. MD5Final(&Context);
  2902. memcpy((uchar *)&IF->TempState, Context.digest, MD5DIGESTLEN);
  2903. }
  2904. //
  2905. // Clear the universal/local bit to indicate local significance.
  2906. //
  2907. IF->TempState.s6_bytes[8] &= ~0x2;
  2908. }
  2909. RtlCopyMemory(&Addr->s6_bytes[0], Prefix, 8);
  2910. RtlCopyMemory(&Addr->s6_bytes[8], &IF->TempState.s6_bytes[8], 8);
  2911. //
  2912. // Check that we haven't accidently generated
  2913. // a known anycast address format,
  2914. // or an existing address on the interface.
  2915. //
  2916. if (IsKnownAnycast(Addr) ||
  2917. (*FindADE(IF, Addr) != NULL))
  2918. goto TryAgain;
  2919. }
  2920. //* AddrConfUpdate - Perform address auto-configuration.
  2921. //
  2922. // Called when we receive a valid Router Advertisement
  2923. // with a Prefix Information option that has the A (autonomous) bit set.
  2924. //
  2925. // Our caller is responsible for any sanity-checking of the prefix.
  2926. //
  2927. // Our caller is responsible for checking that the preferred lifetime
  2928. // is not greater than the valid lifetime.
  2929. //
  2930. // Will also optionally return an NTE, with a reference for the caller.
  2931. // This is done when a public address is created.
  2932. //
  2933. // Called with NO locks held.
  2934. // Callable from DPC context, not from thread context.
  2935. //
  2936. void
  2937. AddrConfUpdate(
  2938. Interface *IF,
  2939. const IPv6Addr *Prefix,
  2940. uint ValidLifetime,
  2941. uint PreferredLifetime,
  2942. int Authenticated,
  2943. NetTableEntry **pNTE)
  2944. {
  2945. NetTableEntry *NTE;
  2946. int Create = TRUE;
  2947. ASSERT(PreferredLifetime <= ValidLifetime);
  2948. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  2949. //
  2950. // Scan the existing Net Table Entries.
  2951. // Note that some of the list elements
  2952. // are actually ADEs of other flavors.
  2953. //
  2954. for (NTE = (NetTableEntry *)IF->ADE;
  2955. ;
  2956. NTE = (NetTableEntry *)NTE->Next) {
  2957. if (NTE == NULL) {
  2958. //
  2959. // No existing entry for this prefix.
  2960. // Create an entry if the lifetime is non-zero.
  2961. //
  2962. if (Create && (ValidLifetime != 0)) {
  2963. IPv6Addr Addr;
  2964. //
  2965. // Auto-configure a new public address.
  2966. //
  2967. Addr = *Prefix;
  2968. (*IF->CreateToken)(IF->LinkContext, &Addr);
  2969. NTE = (NetTableEntry *) *FindADE(IF, &Addr);
  2970. if (NTE != NULL) {
  2971. if (NTE->Type == ADE_UNICAST) {
  2972. //
  2973. // Resurrect the address for our use.
  2974. //
  2975. ASSERT(NTE->DADState == DAD_STATE_INVALID);
  2976. NTE->ValidLifetime = ValidLifetime;
  2977. NTE->PreferredLifetime = PreferredLifetime;
  2978. //
  2979. // And return this NTE.
  2980. //
  2981. AddRefNTE(NTE);
  2982. }
  2983. else {
  2984. //
  2985. // We can not create the public address.
  2986. //
  2987. NTE = NULL;
  2988. break;
  2989. }
  2990. }
  2991. else {
  2992. //
  2993. // Create the public address, returning the new NTE.
  2994. //
  2995. NTE = CreateNTE(IF, &Addr, ADDR_CONF_PUBLIC,
  2996. ValidLifetime, PreferredLifetime);
  2997. }
  2998. //
  2999. // Auto-configure a new temporary address,
  3000. // if appropriate. Note that temporary addresses cannot
  3001. // be used on interfaces that do not support ND, since
  3002. // we have no way to resolve them to link-layer addresses.
  3003. //
  3004. if ((UseTemporaryAddresses != USE_TEMP_NO) &&
  3005. !IsSiteLocal(Prefix) &&
  3006. (IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS) &&
  3007. (PreferredLifetime > TempRegenerateTime) &&
  3008. (NTE != NULL)) {
  3009. IPv6Addr TempAddr;
  3010. uint TempValidLife;
  3011. uint TempPreferredLife;
  3012. TempNetTableEntry *TempNTE;
  3013. CreateTemporaryAddress(IF, Prefix, &TempAddr);
  3014. TempValidLife = MIN(ValidLifetime,
  3015. MaxTempValidLifetime);
  3016. TempPreferredLife = MIN(PreferredLifetime,
  3017. TempPreferredLifetime);
  3018. TempNTE = (TempNetTableEntry *)
  3019. CreateNTE(IF, &TempAddr, ADDR_CONF_TEMPORARY,
  3020. TempValidLife, TempPreferredLife);
  3021. if (TempNTE != NULL) {
  3022. //
  3023. // Create the association between
  3024. // the temporary & public address.
  3025. //
  3026. TempNTE->Public = NTE;
  3027. //
  3028. // Initialize the special temporary creation time.
  3029. // This limits the temporary address's lifetimes.
  3030. //
  3031. TempNTE->CreationTime = IPv6TickCount;
  3032. ReleaseNTE((NetTableEntry *)TempNTE);
  3033. }
  3034. else {
  3035. //
  3036. // Failure - destroy the public address.
  3037. //
  3038. DestroyNTE(IF, NTE);
  3039. ReleaseNTE(NTE);
  3040. NTE = NULL;
  3041. }
  3042. }
  3043. }
  3044. break;
  3045. }
  3046. //
  3047. // Is this a unicast address matching the prefix?
  3048. //
  3049. if ((NTE->Type == ADE_UNICAST) &&
  3050. (NTE->DADState != DAD_STATE_INVALID) &&
  3051. HasPrefix(&NTE->Address, Prefix,
  3052. IPV6_ADDRESS_LENGTH - IPV6_ID_LENGTH)) {
  3053. //
  3054. // Reset the lifetimes of auto-configured addresses.
  3055. // NB: RFC 2462 says to reset DHCP addresses too,
  3056. // but I think that's wrong.
  3057. //
  3058. // Note that to prevent denial of service,
  3059. // we don't accept updates that lower the lifetime
  3060. // to small values.
  3061. //
  3062. // AddrConfTimeout (called from IPv6Timeout) handles
  3063. // the invalid & deprecated state transitions.
  3064. //
  3065. if (IsStatelessAutoConfNTE(NTE)) {
  3066. if ((ValidLifetime > PREFIX_LIFETIME_SAFETY) ||
  3067. (ValidLifetime > NTE->ValidLifetime) ||
  3068. Authenticated)
  3069. NTE->ValidLifetime = ValidLifetime;
  3070. else if (NTE->ValidLifetime <= PREFIX_LIFETIME_SAFETY)
  3071. ; // ignore
  3072. else
  3073. NTE->ValidLifetime = PREFIX_LIFETIME_SAFETY;
  3074. NTE->PreferredLifetime = PreferredLifetime;
  3075. //
  3076. // For temporary addresses, ensure that the lifetimes
  3077. // are not extended indefinitely.
  3078. //
  3079. if (NTE->AddrConf == ADDR_CONF_TEMPORARY) {
  3080. TempNetTableEntry *TempNTE = (TempNetTableEntry *)NTE;
  3081. uint Now = IPv6TickCount;
  3082. //
  3083. // Must be careful of overflows in these comparisons.
  3084. // (Eg, TempNTE->ValidLifetime might be INFINITE_LIFETIME.)
  3085. // N Now
  3086. // V TempNTE->ValidLifetime
  3087. // MV MaxTempValidLifetime
  3088. // C TempNTE->CreationTime
  3089. // We want to check
  3090. // N + V > C + MV
  3091. // Transform this to
  3092. // N - C > MV - V
  3093. // Then underflow of MV - V must be checked but
  3094. // N - C is not a problem because the tick count wraps.
  3095. //
  3096. if ((TempNTE->ValidLifetime > MaxTempValidLifetime) ||
  3097. (Now - TempNTE->CreationTime >
  3098. MaxTempValidLifetime - TempNTE->ValidLifetime)) {
  3099. //
  3100. // This temporary address is showing its age.
  3101. // Must curtail its valid lifetime.
  3102. //
  3103. if (MaxTempValidLifetime > Now - TempNTE->CreationTime)
  3104. TempNTE->ValidLifetime =
  3105. TempNTE->CreationTime +
  3106. MaxTempValidLifetime - Now;
  3107. else
  3108. TempNTE->ValidLifetime = 0;
  3109. }
  3110. if ((TempNTE->PreferredLifetime > TempPreferredLifetime) ||
  3111. (Now - TempNTE->CreationTime >
  3112. TempPreferredLifetime - TempNTE->PreferredLifetime)) {
  3113. //
  3114. // This temporary address is showing its age.
  3115. // Must curtail its preferred lifetime.
  3116. //
  3117. if (TempPreferredLifetime > Now - TempNTE->CreationTime)
  3118. TempNTE->PreferredLifetime =
  3119. TempNTE->CreationTime +
  3120. TempPreferredLifetime - Now;
  3121. else
  3122. TempNTE->PreferredLifetime = 0;
  3123. }
  3124. }
  3125. //
  3126. // Maintain our invariant that the preferred lifetime
  3127. // is not larger than the valid lifetime.
  3128. //
  3129. if (NTE->ValidLifetime < NTE->PreferredLifetime)
  3130. NTE->PreferredLifetime = NTE->ValidLifetime;
  3131. }
  3132. if (NTE->ValidLifetime != 0) {
  3133. //
  3134. // We found an existing address that matches the prefix,
  3135. // so inhibit auto-configuration of a new address.
  3136. //
  3137. Create = FALSE;
  3138. }
  3139. }
  3140. }
  3141. if (IsMCastSyncNeeded(IF))
  3142. DeferSynchronizeMulticastAddresses(IF);
  3143. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  3144. if (pNTE != NULL)
  3145. *pNTE = NTE;
  3146. else if (NTE != NULL)
  3147. ReleaseNTE(NTE);
  3148. }
  3149. //* AddrConfDuplicate
  3150. //
  3151. // Duplicate Address Detection has found
  3152. // that the NTE conflicts with some other node.
  3153. //
  3154. // Called with the interface locked.
  3155. // Callable from thread or DPC context.
  3156. //
  3157. void
  3158. AddrConfDuplicate(Interface *IF, NetTableEntry *NTE)
  3159. {
  3160. int rc;
  3161. ASSERT(NTE->IF == IF);
  3162. if ((NTE->DADState != DAD_STATE_INVALID) &&
  3163. (NTE->DADState != DAD_STATE_DUPLICATE)) {
  3164. IF->DupAddrDetects++;
  3165. if (IsValidNTE(NTE)) {
  3166. if (NTE->DADState == DAD_STATE_PREFERRED) {
  3167. //
  3168. // Queue worker to tell TDI that this address is going away.
  3169. //
  3170. if (!(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED)) {
  3171. DeferRegisterNetAddress(NTE);
  3172. }
  3173. }
  3174. //
  3175. // This NTE is no longer available as a source address.
  3176. //
  3177. InvalidateRouteCache();
  3178. //
  3179. // Disable the loopback route for this address.
  3180. //
  3181. rc = ControlLoopback(IF, &NTE->Address, CONTROL_LOOPBACK_DISABLED);
  3182. ASSERT(rc);
  3183. }
  3184. NTE->DADState = DAD_STATE_DUPLICATE;
  3185. NTE->DADTimer = 0;
  3186. if (NTE->AddrConf == ADDR_CONF_TEMPORARY) {
  3187. NetTableEntry *Public;
  3188. //
  3189. // Make this address invalid so it will go away.
  3190. // NB: We still have a ref for the NTE via our caller.
  3191. //
  3192. DestroyNTE(IF, NTE);
  3193. //
  3194. // Should we create a new temporary address?
  3195. //
  3196. if ((UseTemporaryAddresses != USE_TEMP_NO) &&
  3197. ((Public = ((TempNetTableEntry *)NTE)->Public) != NULL) &&
  3198. (Public->PreferredLifetime > TempRegenerateTime) &&
  3199. (IF->DupAddrDetects < MaxTempDADAttempts)) {
  3200. IPv6Addr TempAddr;
  3201. TempNetTableEntry *NewNTE;
  3202. uint TempValidLife;
  3203. uint TempPreferredLife;
  3204. //
  3205. // Generate a new temporary address,
  3206. // forcing the use of a new interface identifier.
  3207. //
  3208. IF->TempStateAge = 0;
  3209. CreateTemporaryAddress(IF, &NTE->Address, &TempAddr);
  3210. TempValidLife = MIN(Public->ValidLifetime,
  3211. MaxTempValidLifetime);
  3212. TempPreferredLife = MIN(Public->PreferredLifetime,
  3213. TempPreferredLifetime);
  3214. //
  3215. // Configure the new address.
  3216. //
  3217. NewNTE = (TempNetTableEntry *)
  3218. CreateNTE(IF, &TempAddr, ADDR_CONF_TEMPORARY,
  3219. TempValidLife, TempPreferredLife);
  3220. if (NewNTE == NULL) {
  3221. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  3222. "AddrConfDuplicate: CreateNTE failed\n"));
  3223. }
  3224. else {
  3225. NewNTE->Public = Public;
  3226. NewNTE->CreationTime = IPv6TickCount;
  3227. ReleaseNTE((NetTableEntry *)NewNTE);
  3228. }
  3229. }
  3230. }
  3231. }
  3232. }
  3233. //* AddrConfNotDuplicate
  3234. //
  3235. // Duplicate Address Detection has NOT found
  3236. // a conflict with another node.
  3237. //
  3238. // Called with the interface locked.
  3239. // Callable from thread or DPC context.
  3240. //
  3241. void
  3242. AddrConfNotDuplicate(Interface *IF, NetTableEntry *NTE)
  3243. {
  3244. int rc;
  3245. //
  3246. // The address has passed Duplicate Address Detection.
  3247. // Transition to a valid state.
  3248. //
  3249. if (! IsValidNTE(NTE)) {
  3250. if (NTE->PreferredLifetime == 0)
  3251. NTE->DADState = DAD_STATE_DEPRECATED;
  3252. else
  3253. NTE->DADState = DAD_STATE_PREFERRED;
  3254. //
  3255. // This NTE is now available as a source address.
  3256. //
  3257. InvalidateRouteCache();
  3258. //
  3259. // Enable the loopback route for this address.
  3260. //
  3261. rc = ControlLoopback(IF, &NTE->Address, CONTROL_LOOPBACK_ENABLED);
  3262. ASSERT(rc);
  3263. }
  3264. //
  3265. // DAD is also triggered through an interface disconnect to connect
  3266. // transition in which case the address is not registered with TDI
  3267. // even if it is in the preferred state. Hence we queue a worker to
  3268. // tell TDI about this address outside the "if (!IsValidNTE)" clause.
  3269. //
  3270. if ((NTE->DADState == DAD_STATE_PREFERRED) &&
  3271. !(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED)) {
  3272. DeferRegisterNetAddress(NTE);
  3273. }
  3274. }
  3275. //* AddrConfResetAutoConfig
  3276. //
  3277. // Resets the interface's auto-configured address lifetimes.
  3278. //
  3279. // Called with the interface locked.
  3280. // Callable from thread or DPC context.
  3281. //
  3282. void
  3283. AddrConfResetAutoConfig(Interface *IF, uint MaxLifetime)
  3284. {
  3285. NetTableEntry *NTE;
  3286. for (NTE = (NetTableEntry *) IF->ADE;
  3287. NTE != NULL;
  3288. NTE = (NetTableEntry *) NTE->Next) {
  3289. //
  3290. // Is this an auto-configured unicast address?
  3291. //
  3292. if ((NTE->Type == ADE_UNICAST) &&
  3293. IsStatelessAutoConfNTE(NTE)) {
  3294. //
  3295. // Set the valid lifetime to a small value.
  3296. // If we don't get an RA soon, the address will expire.
  3297. //
  3298. if (NTE->ValidLifetime > MaxLifetime)
  3299. NTE->ValidLifetime = MaxLifetime;
  3300. if (NTE->PreferredLifetime > NTE->ValidLifetime)
  3301. NTE->PreferredLifetime = NTE->ValidLifetime;
  3302. }
  3303. }
  3304. }
  3305. //* ReconnectADEs
  3306. //
  3307. // Callable from thread or DPC context.
  3308. // Called with the interface locked.
  3309. //
  3310. // (Actually, we are at DPC level because we hold the interface lock.)
  3311. //
  3312. void
  3313. ReconnectADEs(Interface *IF)
  3314. {
  3315. AddressEntry *ADE;
  3316. for (ADE = IF->ADE; ADE != NULL; ADE = ADE->Next) {
  3317. switch (ADE->Type) {
  3318. case ADE_UNICAST: {
  3319. NetTableEntry *NTE = (NetTableEntry *) ADE;
  3320. if (NTE->DADState != DAD_STATE_INVALID) {
  3321. //
  3322. // Restart Duplicate Address Detection,
  3323. // if it is enabled for this interface.
  3324. //
  3325. AddrConfStartDAD(IF, NTE);
  3326. }
  3327. break;
  3328. }
  3329. case ADE_ANYCAST:
  3330. //
  3331. // Nothing to do for anycast addresses.
  3332. //
  3333. break;
  3334. case ADE_MULTICAST: {
  3335. MulticastAddressEntry *MAE = (MulticastAddressEntry *) ADE;
  3336. //
  3337. // Rejoin this multicast group,
  3338. // if it is reportable.
  3339. //
  3340. KeAcquireSpinLockAtDpcLevel(&QueryListLock);
  3341. if (MAE->MCastFlags & MAE_REPORTABLE) {
  3342. MAE->MCastCount = MLD_NUM_INITIAL_REPORTS;
  3343. if (MAE->MCastTimer == 0)
  3344. AddToQueryList(MAE);
  3345. MAE->MCastTimer = 1;
  3346. }
  3347. KeReleaseSpinLockFromDpcLevel(&QueryListLock);
  3348. break;
  3349. }
  3350. }
  3351. }
  3352. }
  3353. //* DisconnectADEs
  3354. //
  3355. // Callable from thread or DPC context.
  3356. // Called with the interface locked.
  3357. //
  3358. // (Actually, we are at DPC level because we hold the interface lock.)
  3359. //
  3360. void
  3361. DisconnectADEs(Interface *IF)
  3362. {
  3363. AddressEntry *ADE;
  3364. ASSERT(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED);
  3365. for (ADE = IF->ADE; ADE != NULL; ADE = ADE->Next) {
  3366. if (ADE->Type == ADE_UNICAST) {
  3367. NetTableEntry *NTE = (NetTableEntry *) ADE;
  3368. if (NTE->DADState == DAD_STATE_PREFERRED) {
  3369. //
  3370. // Queue worker to tell TDI that this address is going away.
  3371. //
  3372. DeferRegisterNetAddress(NTE);
  3373. }
  3374. }
  3375. //
  3376. // Nothing to do for anycast or multicast addresses.
  3377. //
  3378. }
  3379. }
  3380. //* DestroyNTE
  3381. //
  3382. // Make an NTE be invalid, resulting in its eventual destruction.
  3383. //
  3384. // In the DestroyIF case, the NTE has already been removed
  3385. // from the interface. In other situations, that doesn't happen
  3386. // until later, when NetTableCleanup runs.
  3387. //
  3388. // Callable from thread or DPC context.
  3389. // Called with the interface locked.
  3390. //
  3391. // (Actually, we are at DPC level because we hold the interface lock.)
  3392. //
  3393. void
  3394. DestroyNTE(Interface *IF, NetTableEntry *NTE)
  3395. {
  3396. int rc;
  3397. ASSERT(NTE->IF == IF);
  3398. if (NTE->DADState != DAD_STATE_INVALID) {
  3399. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  3400. "DestroyNTE(NTE %p, Addr %s) -> invalid\n",
  3401. NTE, FormatV6Address(&NTE->Address)));
  3402. if (IsValidNTE(NTE)) {
  3403. if (NTE->DADState == DAD_STATE_PREFERRED) {
  3404. //
  3405. // Queue worker to tell TDI that this address is going away.
  3406. //
  3407. if (!(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED)) {
  3408. DeferRegisterNetAddress(NTE);
  3409. }
  3410. }
  3411. //
  3412. // This NTE is no longer available as a source address.
  3413. //
  3414. InvalidateRouteCache();
  3415. //
  3416. // Disable the loopback route for this address.
  3417. //
  3418. rc = ControlLoopback(IF, &NTE->Address, CONTROL_LOOPBACK_DISABLED);
  3419. ASSERT(rc);
  3420. }
  3421. //
  3422. // Invalidate this address.
  3423. //
  3424. NTE->DADState = DAD_STATE_INVALID;
  3425. NTE->DADTimer = 0;
  3426. //
  3427. // We have to set its lifetime to zero,
  3428. // or else AddrConfTimeout will attempt
  3429. // to resurrect this address.
  3430. //
  3431. NTE->ValidLifetime = 0;
  3432. NTE->PreferredLifetime = 0;
  3433. //
  3434. // The corresponding solicited-node address is not needed.
  3435. //
  3436. FindAndReleaseSolicitedNodeMAE(IF, &NTE->Address);
  3437. if (NTE == IF->LinkLocalNTE) {
  3438. //
  3439. // Unmark it as the primary link-local NTE.
  3440. // GetLinkLocalAddress will update LinkLocalNTE lazily.
  3441. //
  3442. IF->LinkLocalNTE = NULL;
  3443. }
  3444. //
  3445. // Release the interface's reference for the NTE.
  3446. //
  3447. ReleaseNTE(NTE);
  3448. }
  3449. }
  3450. //* EnlivenNTE
  3451. //
  3452. // Make an NTE come alive, transitioning out of DAD_STATE_INVALID.
  3453. //
  3454. // Callable from thread or DPC context.
  3455. // Called with the interface locked.
  3456. //
  3457. void
  3458. EnlivenNTE(Interface *IF, NetTableEntry *NTE)
  3459. {
  3460. ASSERT(NTE->DADState == DAD_STATE_INVALID);
  3461. ASSERT(NTE->ValidLifetime != 0);
  3462. //
  3463. // The NTE needs a corresponding solicited-node MAE.
  3464. // If this fails, leave the address invalid and
  3465. // try again later.
  3466. //
  3467. if (FindOrCreateSolicitedNodeMAE(IF, &NTE->Address)) {
  3468. //
  3469. // The interface needs a reference for the NTE,
  3470. // because we are enlivening it.
  3471. //
  3472. AddRefNTE(NTE);
  3473. //
  3474. // Start the address in the tentative state.
  3475. //
  3476. NTE->DADState = DAD_STATE_TENTATIVE;
  3477. //
  3478. // Start duplicate address detection.
  3479. //
  3480. AddrConfStartDAD(IF, NTE);
  3481. }
  3482. }
  3483. //* AddrConfTimeout - Perform valid/preferred lifetime expiration.
  3484. //
  3485. // Called periodically from NetTableTimeout on every NTE.
  3486. // As usual, caller must hold a reference for the NTE.
  3487. //
  3488. // Called with NO locks held.
  3489. // Callable from DPC context, not from thread context.
  3490. //
  3491. void
  3492. AddrConfTimeout(NetTableEntry *NTE)
  3493. {
  3494. Interface *IF = NTE->IF;
  3495. int QueueWorker = FALSE;
  3496. NetTableEntry *Public;
  3497. ASSERT(NTE->Type == ADE_UNICAST);
  3498. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  3499. if (NTE->ValidLifetime == 0) {
  3500. //
  3501. // If the valid lifetime is zero, then the NTE should be invalid.
  3502. //
  3503. DestroyNTE(IF, NTE);
  3504. }
  3505. else {
  3506. //
  3507. // If the valid lifetime is non-zero, then the NTE should be alive.
  3508. //
  3509. if (NTE->DADState == DAD_STATE_INVALID)
  3510. EnlivenNTE(IF, NTE);
  3511. if (NTE->ValidLifetime != INFINITE_LIFETIME)
  3512. NTE->ValidLifetime--;
  3513. }
  3514. //
  3515. // Note that TempRegenerateTime might be zero.
  3516. // In which case it's important to only do this
  3517. // when transitioning from preferred to deprecated,
  3518. // NOT every time the preferred lifetime is zero.
  3519. //
  3520. if ((NTE->AddrConf == ADDR_CONF_TEMPORARY) &&
  3521. (NTE->DADState == DAD_STATE_PREFERRED) &&
  3522. (NTE->PreferredLifetime == TempRegenerateTime) &&
  3523. (IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS) &&
  3524. (UseTemporaryAddresses != USE_TEMP_NO) &&
  3525. ((Public = ((TempNetTableEntry *)NTE)->Public) != NULL) &&
  3526. (Public->PreferredLifetime > TempRegenerateTime)) {
  3527. IPv6Addr TempAddr;
  3528. TempNetTableEntry *NewNTE;
  3529. uint TempValidLife;
  3530. uint TempPreferredLife;
  3531. //
  3532. // We will soon deprecate this temporary address,
  3533. // so create a new temporary address.
  3534. //
  3535. CreateTemporaryAddress(IF, &NTE->Address, &TempAddr);
  3536. TempValidLife = MIN(Public->ValidLifetime,
  3537. MaxTempValidLifetime);
  3538. TempPreferredLife = MIN(Public->PreferredLifetime,
  3539. TempPreferredLifetime);
  3540. //
  3541. // Configure the new address.
  3542. //
  3543. NewNTE = (TempNetTableEntry *)
  3544. CreateNTE(IF, &TempAddr, ADDR_CONF_TEMPORARY,
  3545. TempValidLife, TempPreferredLife);
  3546. if (NewNTE == NULL) {
  3547. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  3548. "AddrConfTimeout: CreateNTE failed\n"));
  3549. }
  3550. else {
  3551. NewNTE->Public = Public;
  3552. NewNTE->CreationTime = IPv6TickCount;
  3553. ReleaseNTE((NetTableEntry *)NewNTE);
  3554. }
  3555. }
  3556. //
  3557. // If the preferred lifetime is zero, then the NTE should be deprecated.
  3558. //
  3559. if (NTE->PreferredLifetime == 0) {
  3560. if (NTE->DADState == DAD_STATE_PREFERRED) {
  3561. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  3562. "AddrConfTimeout(NTE %p, Addr %s) -> deprecated\n",
  3563. NTE, FormatV6Address(&NTE->Address)));
  3564. //
  3565. // Make this address be deprecated.
  3566. //
  3567. NTE->DADState = DAD_STATE_DEPRECATED;
  3568. if (!(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED)) {
  3569. QueueWorker = TRUE;
  3570. }
  3571. InvalidateRouteCache();
  3572. }
  3573. } else {
  3574. //
  3575. // If the address was deprecated, then it should be preferred.
  3576. // (AddrConfUpdate must have just increased the preferred lifetime.)
  3577. //
  3578. if (NTE->DADState == DAD_STATE_DEPRECATED) {
  3579. NTE->DADState = DAD_STATE_PREFERRED;
  3580. if (!(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED)) {
  3581. QueueWorker = TRUE;
  3582. }
  3583. InvalidateRouteCache();
  3584. }
  3585. if (NTE->PreferredLifetime != INFINITE_LIFETIME)
  3586. NTE->PreferredLifetime--;
  3587. }
  3588. if (IsMCastSyncNeeded(IF))
  3589. DeferSynchronizeMulticastAddresses(IF);
  3590. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  3591. if (QueueWorker)
  3592. DeferRegisterNetAddress(NTE);
  3593. }
  3594. //* NetTableCleanup
  3595. //
  3596. // Cleans up any NetTableEntries with zero references.
  3597. //
  3598. // Called with NO locks held.
  3599. // Callable from thread or DPC context.
  3600. //
  3601. void
  3602. NetTableCleanup(void)
  3603. {
  3604. NetTableEntry *DestroyList = NULL;
  3605. NetTableEntry *NTE, *NextNTE;
  3606. Interface *IF;
  3607. KIRQL OldIrql;
  3608. int rc;
  3609. KeAcquireSpinLock(&NetTableListLock, &OldIrql);
  3610. for (NTE = NetTableList; NTE != NULL; NTE = NextNTE) {
  3611. NextNTE = NTE->NextOnNTL;
  3612. if (NTE->RefCnt == 0) {
  3613. ASSERT(NTE->DADState == DAD_STATE_INVALID);
  3614. //
  3615. // We want to destroy this NTE.
  3616. // We have to release the list lock
  3617. // before we can acquire the interface lock,
  3618. // but we need references to hold the NTEs.
  3619. //
  3620. AddRefNTE(NTE);
  3621. if (NextNTE != NULL)
  3622. AddRefNTE(NextNTE);
  3623. KeReleaseSpinLock(&NetTableListLock, OldIrql);
  3624. IF = NTE->IF;
  3625. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  3626. KeAcquireSpinLockAtDpcLevel(&NetTableListLock);
  3627. //
  3628. // Now that we have the appropriate locks.
  3629. // Is no one else using this NTE?
  3630. //
  3631. ReleaseNTE(NTE);
  3632. if (NTE->RefCnt == 0) {
  3633. //
  3634. // OK, we will destroy this NTE.
  3635. // First remove from the list.
  3636. //
  3637. RemoveNTEFromNetTableList(NTE);
  3638. //
  3639. // It is now safe to release the list lock,
  3640. // because the NTE is removed from the list.
  3641. // We continue to hold the interface lock,
  3642. // so nobody can find this NTE via the interface.
  3643. //
  3644. KeReleaseSpinLockFromDpcLevel(&NetTableListLock);
  3645. //
  3646. // Remove ADEs that reference this address.
  3647. // Note that this also removes from the interface's list,
  3648. // but does not free, the NTE itself.
  3649. // NB: In the case of DestroyIF, the ADEs are already
  3650. // removed from the interface and DestroyADEs does nothing.
  3651. //
  3652. DestroyADEs(IF, NTE);
  3653. //
  3654. // Release the loopback route.
  3655. //
  3656. rc = ControlLoopback(IF, &NTE->Address,
  3657. CONTROL_LOOPBACK_DESTROY);
  3658. ASSERT(rc);
  3659. KeReleaseSpinLock(&IF->Lock, OldIrql);
  3660. //
  3661. // Put this NTE on the destroy list.
  3662. //
  3663. NTE->NextOnNTL = DestroyList;
  3664. DestroyList = NTE;
  3665. KeAcquireSpinLock(&NetTableListLock, &OldIrql);
  3666. }
  3667. else { // if (NTE->RefCnt != 0)
  3668. //
  3669. // We will not be destroying this NTE after all.
  3670. // Release the interface lock but keep the list lock.
  3671. //
  3672. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  3673. }
  3674. //
  3675. // At this point, we have the list lock again
  3676. // so we can release our reference for NextNTE.
  3677. //
  3678. if (NextNTE != NULL)
  3679. ReleaseNTE(NextNTE);
  3680. }
  3681. }
  3682. KeReleaseSpinLock(&NetTableListLock, OldIrql);
  3683. while (DestroyList != NULL) {
  3684. NTE = DestroyList;
  3685. DestroyList = NTE->NextOnNTL;
  3686. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  3687. "NetTableCleanup(NTE %p, Addr %s) -> destroyed\n",
  3688. NTE, FormatV6Address(&NTE->Address)));
  3689. ReleaseIF(NTE->IF);
  3690. ExFreePool(NTE);
  3691. }
  3692. }
  3693. //* NetTableTimeout
  3694. //
  3695. // Called periodically from IPv6Timeout.
  3696. //
  3697. // Called with NO locks held.
  3698. // Callable from DPC context, not from thread context.
  3699. //
  3700. void
  3701. NetTableTimeout(void)
  3702. {
  3703. NetTableEntry *NTE;
  3704. int SawZeroReferences = FALSE;
  3705. //
  3706. // Because new NTEs are only added at the head of the list,
  3707. // we can unlock the list during our traversal
  3708. // and know that the traversal will terminate properly.
  3709. //
  3710. KeAcquireSpinLockAtDpcLevel(&NetTableListLock);
  3711. for (NTE = NetTableList; NTE != NULL; NTE = NTE->NextOnNTL) {
  3712. AddRefNTE(NTE);
  3713. KeReleaseSpinLockFromDpcLevel(&NetTableListLock);
  3714. //
  3715. // Check for Duplicate Address Detection timeout.
  3716. // The timer check here is only an optimization,
  3717. // because it is made without holding the appropriate lock.
  3718. //
  3719. if (NTE->DADTimer != 0)
  3720. DADTimeout(NTE);
  3721. //
  3722. // Perform lifetime expiration.
  3723. //
  3724. AddrConfTimeout(NTE);
  3725. KeAcquireSpinLockAtDpcLevel(&NetTableListLock);
  3726. ReleaseNTE(NTE);
  3727. //
  3728. // We assume that loads of RefCnt are atomic.
  3729. //
  3730. if (NTE->RefCnt == 0)
  3731. SawZeroReferences = TRUE;
  3732. }
  3733. KeReleaseSpinLockFromDpcLevel(&NetTableListLock);
  3734. if (SawZeroReferences)
  3735. NetTableCleanup();
  3736. }
  3737. //* InterfaceCleanup
  3738. //
  3739. // Cleans up any Interfaces with zero references.
  3740. //
  3741. // Called with NO locks held.
  3742. // Callable from thread or DPC context.
  3743. //
  3744. void
  3745. InterfaceCleanup(void)
  3746. {
  3747. Interface *DestroyList = NULL;
  3748. Interface *IF, **PrevIF;
  3749. KIRQL OldIrql;
  3750. KeAcquireSpinLock(&IFListLock, &OldIrql);
  3751. PrevIF = &IFList;
  3752. while ((IF = *PrevIF) != NULL) {
  3753. if (IF->RefCnt == 0) {
  3754. ASSERT(IsDisabledIF(IF));
  3755. *PrevIF = IF->Next;
  3756. IF->Next = DestroyList;
  3757. DestroyList = IF;
  3758. IPSInfo.ipsi_numif--;
  3759. } else {
  3760. PrevIF = &IF->Next;
  3761. }
  3762. }
  3763. KeReleaseSpinLock(&IFListLock, OldIrql);
  3764. while (DestroyList != NULL) {
  3765. IF = DestroyList;
  3766. DestroyList = IF->Next;
  3767. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  3768. "InterfaceCleanup(IF %u/%p) -> destroyed\n",
  3769. IF->Index, IF));
  3770. //
  3771. // ADEs should already be destroyed.
  3772. // We just need to cleanup NCEs and free the interface.
  3773. //
  3774. ASSERT(IF->ADE == NULL);
  3775. NeighborCacheDestroy(IF);
  3776. if (IF->MCastAddresses != NULL)
  3777. ExFreePool(IF->MCastAddresses);
  3778. DeferDeregisterInterface(IF);
  3779. }
  3780. }
  3781. //* InterfaceTimeout
  3782. //
  3783. // Called periodically from IPv6Timeout.
  3784. //
  3785. // Called with NO locks held.
  3786. // Callable from DPC context, not from thread context.
  3787. //
  3788. void
  3789. InterfaceTimeout(void)
  3790. {
  3791. static uint RecalcReachableTimer = 0;
  3792. int RecalcReachable;
  3793. int ForceRAs;
  3794. Interface *IF;
  3795. int SawZeroReferences = FALSE;
  3796. //
  3797. // Recalculate ReachableTime every few hours,
  3798. // even if no Router Advertisements are received.
  3799. //
  3800. if (RecalcReachableTimer == 0) {
  3801. RecalcReachable = TRUE;
  3802. RecalcReachableTimer = RECALC_REACHABLE_INTERVAL;
  3803. } else {
  3804. RecalcReachable = FALSE;
  3805. RecalcReachableTimer--;
  3806. }
  3807. //
  3808. // Grab the value of ForceRouterAdvertisements.
  3809. //
  3810. ForceRAs = InterlockedExchange((PLONG)&ForceRouterAdvertisements, FALSE);
  3811. //
  3812. // Because new interfaces are only added at the head of the list,
  3813. // we can unlock the list during our traversal
  3814. // and know that the traversal will terminate properly.
  3815. //
  3816. KeAcquireSpinLockAtDpcLevel(&IFListLock);
  3817. for (IF = IFList; IF != NULL; IF = IF->Next) {
  3818. //
  3819. // We should not do any processing on an interface
  3820. // that has zero references. As an even stronger condition,
  3821. // we avoid doing any timeout processing if the interface
  3822. // is being destroyed. Of course, the interface might be
  3823. // destroyed after we drop the interface list lock.
  3824. //
  3825. if (! IsDisabledIF(IF)) {
  3826. AddRefIF(IF);
  3827. KeReleaseSpinLockFromDpcLevel(&IFListLock);
  3828. //
  3829. // Handle per-neighbor timeouts.
  3830. //
  3831. NeighborCacheTimeout(IF);
  3832. //
  3833. // Handle router solicitations.
  3834. // The timer check here is only an optimization,
  3835. // because it is made without holding the appropriate lock.
  3836. //
  3837. if (IF->RSTimer != 0)
  3838. RouterSolicitTimeout(IF);
  3839. //
  3840. // Handle router advertisements.
  3841. // The timer check here is only an optimization,
  3842. // because it is made without holding the appropriate lock.
  3843. //
  3844. if (IF->RATimer != 0)
  3845. RouterAdvertTimeout(IF, ForceRAs);
  3846. //
  3847. // Recalculate the reachable time.
  3848. //
  3849. if (RecalcReachable) {
  3850. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  3851. IF->ReachableTime = CalcReachableTime(IF->BaseReachableTime);
  3852. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  3853. }
  3854. KeAcquireSpinLockAtDpcLevel(&IFListLock);
  3855. ReleaseIF(IF);
  3856. }
  3857. //
  3858. // We assume that loads of RefCnt are atomic.
  3859. //
  3860. if (IF->RefCnt == 0)
  3861. SawZeroReferences = TRUE;
  3862. }
  3863. KeReleaseSpinLockFromDpcLevel(&IFListLock);
  3864. if (SawZeroReferences)
  3865. InterfaceCleanup();
  3866. }
  3867. //* InterfaceStartAdvertising
  3868. //
  3869. // If the interface is not currently advertising,
  3870. // makes it start advertising.
  3871. //
  3872. // Called with the interface locked.
  3873. // Caller must check whether the interface is disabled.
  3874. //
  3875. NTSTATUS
  3876. InterfaceStartAdvertising(Interface *IF)
  3877. {
  3878. ASSERT(! IsDisabledIF(IF));
  3879. ASSERT(IF->Flags & IF_FLAG_ROUTER_DISCOVERS);
  3880. if (!(IF->Flags & IF_FLAG_ADVERTISES)) {
  3881. //
  3882. // Join the all-routers multicast groups.
  3883. //
  3884. if (! JoinGroupAtAllScopes(IF, &AllRoutersOnLinkAddr,
  3885. ADE_SITE_LOCAL))
  3886. return STATUS_INSUFFICIENT_RESOURCES;
  3887. //
  3888. // A non-advertising interface is now advertising.
  3889. //
  3890. IF->Flags |= IF_FLAG_ADVERTISES;
  3891. //
  3892. // The reconnecting state is not useful
  3893. // for advertising interfaces because
  3894. // the interface will not receive RAs.
  3895. //
  3896. IF->Flags &= ~IF_FLAG_MEDIA_RECONNECTED;
  3897. //
  3898. // Remove addresses & routes that were auto-configured
  3899. // from Router Advertisements. Advertising interfaces
  3900. // must be manually configured. Better to remove it
  3901. // now than let it time-out at some random time.
  3902. //
  3903. AddrConfResetAutoConfig(IF, 0);
  3904. RouteTableResetAutoConfig(IF, 0);
  3905. InterfaceResetAutoConfig(IF);
  3906. //
  3907. // Start sending Router Advertisements.
  3908. //
  3909. IF->RATimer = 1; // Send first RA very quickly.
  3910. IF->RACount = MAX_INITIAL_RTR_ADVERTISEMENTS;
  3911. //
  3912. // Stop sending Router Solicitations.
  3913. //
  3914. IF->RSTimer = 0;
  3915. }
  3916. return STATUS_SUCCESS;
  3917. }
  3918. //* InterfaceStopAdvertising
  3919. //
  3920. // If the interface is currently advertising,
  3921. // stops the advertising behavior.
  3922. //
  3923. // Called with the interface locked.
  3924. // Caller must check whether the interface is disabled.
  3925. //
  3926. void
  3927. InterfaceStopAdvertising(Interface *IF)
  3928. {
  3929. ASSERT(! IsDisabledIF(IF));
  3930. if (IF->Flags & IF_FLAG_ADVERTISES) {
  3931. //
  3932. // Leave the all-routers multicast group.
  3933. //
  3934. LeaveGroupAtAllScopes(IF, &AllRoutersOnLinkAddr,
  3935. ADE_SITE_LOCAL);
  3936. //
  3937. // Stop sending Router Advertisements.
  3938. //
  3939. IF->Flags &= ~IF_FLAG_ADVERTISES;
  3940. IF->RATimer = 0;
  3941. //
  3942. // Remove addresses that were auto-configured
  3943. // from our own Router Advertisements.
  3944. // We will pick up new address lifetimes
  3945. // from other router's Advertisements.
  3946. // If some other router is not advertising
  3947. // the prefixes that this router was advertising,
  3948. // better to remove the addresses now than
  3949. // let them time-out at some random time.
  3950. //
  3951. AddrConfResetAutoConfig(IF, 0);
  3952. //
  3953. // There shouldn't be any auto-configured routes,
  3954. // but RouteTableResetAutoConfig also handles site prefixes.
  3955. //
  3956. RouteTableResetAutoConfig(IF, 0);
  3957. //
  3958. // Restore interface parameters.
  3959. //
  3960. InterfaceResetAutoConfig(IF);
  3961. //
  3962. // Send Router Solicitations again.
  3963. //
  3964. IF->RSCount = 0;
  3965. IF->RSTimer = 1;
  3966. }
  3967. }
  3968. //* InterfaceStartForwarding
  3969. //
  3970. // If the interface is not currently forwarding,
  3971. // makes it start forwarding.
  3972. //
  3973. // Called with the interface locked.
  3974. //
  3975. void
  3976. InterfaceStartForwarding(Interface *IF)
  3977. {
  3978. if (!(IF->Flags & IF_FLAG_FORWARDS)) {
  3979. //
  3980. // Any change in forwarding behavior requires InvalidRouteCache
  3981. // because FindNextHop uses IF_FLAG_FORWARDS. Also force the next RA
  3982. // for all advertising interfaces to be sent quickly,
  3983. // because their content might depend on forwarding behavior.
  3984. //
  3985. IF->Flags |= IF_FLAG_FORWARDS;
  3986. InterlockedIncrement((PLONG)&NumForwardingInterfaces);
  3987. InvalidateRouteCache();
  3988. ForceRouterAdvertisements = TRUE;
  3989. }
  3990. }
  3991. //* InterfaceStopForwarding
  3992. //
  3993. // If the interface is currently forwarding,
  3994. // stops the forwarding behavior.
  3995. //
  3996. // Called with the interface locked.
  3997. //
  3998. void
  3999. InterfaceStopForwarding(Interface *IF)
  4000. {
  4001. if (IF->Flags & IF_FLAG_FORWARDS) {
  4002. //
  4003. // Any change in forwarding behavior requires InvalidRouteCache
  4004. // because FindNextHop uses IF_FLAG_FORWARDS. Also force the next RA
  4005. // for all advertising interfaces to be sent quickly,
  4006. // because their content might depend on forwarding behavior.
  4007. //
  4008. IF->Flags &= ~IF_FLAG_FORWARDS;
  4009. InterlockedDecrement((PLONG)&NumForwardingInterfaces);
  4010. InvalidateRouteCache();
  4011. ForceRouterAdvertisements = TRUE;
  4012. }
  4013. }
  4014. //* AddrConfResetManualConfig
  4015. //
  4016. // Removes manually-configured addresses from the interface.
  4017. //
  4018. // Called with the interface already locked.
  4019. //
  4020. void
  4021. AddrConfResetManualConfig(Interface *IF)
  4022. {
  4023. AddressEntry *AnycastList = NULL;
  4024. AddressEntry *ADE, **PrevADE;
  4025. //
  4026. // We have to be careful about how we destroy addresses,
  4027. // because FindAndReleaseSolicitedNodeMAE will mess up our traversal.
  4028. //
  4029. PrevADE = &IF->ADE;
  4030. while ((ADE = *PrevADE) != NULL) {
  4031. //
  4032. // Is this a manually configured address?
  4033. //
  4034. switch (ADE->Type) {
  4035. case ADE_UNICAST: {
  4036. NetTableEntry *NTE = (NetTableEntry *) ADE;
  4037. if (NTE->AddrConf == ADDR_CONF_MANUAL) {
  4038. //
  4039. // Let NetTableTimeout destroy the address.
  4040. //
  4041. NTE->ValidLifetime = 0;
  4042. NTE->PreferredLifetime = 0;
  4043. }
  4044. break;
  4045. }
  4046. case ADE_ANYCAST:
  4047. //
  4048. // Most anycast addresses are manually configured.
  4049. // Subnet anycast addresses are the only exception.
  4050. // They are also the only anycast addresses
  4051. // which point to an NTE instead of the interface.
  4052. //
  4053. if (ADE->IF == IF) {
  4054. //
  4055. // Remove the ADE from the interface list.
  4056. //
  4057. *PrevADE = ADE->Next;
  4058. //
  4059. // Put the ADE on our temporary list.
  4060. //
  4061. ADE->Next = AnycastList;
  4062. AnycastList = ADE;
  4063. continue;
  4064. }
  4065. break;
  4066. }
  4067. PrevADE = &ADE->Next;
  4068. }
  4069. //
  4070. // Now we can safely process the anycast ADEs.
  4071. //
  4072. while ((ADE = AnycastList) != NULL) {
  4073. AnycastList = ADE->Next;
  4074. DeleteAAE(IF, (AnycastAddressEntry *)ADE);
  4075. }
  4076. }
  4077. //* InterfaceResetAutoConfig
  4078. //
  4079. // Resets interface parameters that are auto-configured
  4080. // from Router Advertisements.
  4081. //
  4082. // Called with the interface already locked.
  4083. //
  4084. void
  4085. InterfaceResetAutoConfig(Interface *IF)
  4086. {
  4087. IF->LinkMTU = IF->DefaultLinkMTU;
  4088. if (IF->BaseReachableTime != REACHABLE_TIME) {
  4089. IF->BaseReachableTime = REACHABLE_TIME;
  4090. IF->ReachableTime = CalcReachableTime(IF->BaseReachableTime);
  4091. }
  4092. IF->RetransTimer = RETRANS_TIMER;
  4093. IF->CurHopLimit = DefaultCurHopLimit;
  4094. }
  4095. //* InterfaceResetManualConfig
  4096. //
  4097. // Resets the manual configuration of the interface.
  4098. // Does not remove manual routes on the interface.
  4099. //
  4100. // Called with ZoneUpdateLock held.
  4101. //
  4102. void
  4103. InterfaceResetManualConfig(Interface *IF)
  4104. {
  4105. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  4106. if (! IsDisabledIF(IF)) {
  4107. uint ZoneIndices[ADE_NUM_SCOPES];
  4108. //
  4109. // Reset manually-configured interface parameters.
  4110. //
  4111. IF->LinkMTU = IF->DefaultLinkMTU;
  4112. IF->Preference = IF->DefaultPreference;
  4113. if (IF->BaseReachableTime != REACHABLE_TIME) {
  4114. IF->BaseReachableTime = REACHABLE_TIME;
  4115. IF->ReachableTime = CalcReachableTime(IF->BaseReachableTime);
  4116. }
  4117. IF->RetransTimer = RETRANS_TIMER;
  4118. IF->DupAddrDetectTransmits = IF->DefaultDupAddrDetectTransmits;
  4119. IF->CurHopLimit = DefaultCurHopLimit;
  4120. IF->DefSitePrefixLength = DEFAULT_SITE_PREFIX_LENGTH;
  4121. //
  4122. // ZoneUpdateLock is held by our caller.
  4123. //
  4124. InitZoneIndices(ZoneIndices, IF->Index);
  4125. UpdateZoneIndices(IF, ZoneIndices);
  4126. //
  4127. // Remove manually-configured addresses.
  4128. //
  4129. AddrConfResetManualConfig(IF);
  4130. //
  4131. // Stop advertising and forwarding,
  4132. // if either of those behaviors are enabled.
  4133. //
  4134. InterfaceStopAdvertising(IF);
  4135. InterfaceStopForwarding(IF);
  4136. //
  4137. // Reset the firewall mode.
  4138. //
  4139. IF->Flags &= ~IF_FLAG_FIREWALL_ENABLED;
  4140. }
  4141. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  4142. }
  4143. //* InterfaceReset
  4144. //
  4145. // Resets manual configuration for all interfaces.
  4146. // Tunnel interfaces are destroyed.
  4147. // Other interfaces have their attributes reset to default values.
  4148. // Manually-configured addresses are removed.
  4149. //
  4150. // The end result should be the same as if the machine
  4151. // had just booted without any persistent configuration.
  4152. //
  4153. // Called with no locks held.
  4154. //
  4155. void
  4156. InterfaceReset(void)
  4157. {
  4158. Interface *IF;
  4159. KIRQL OldIrql;
  4160. //
  4161. // Because new interfaces are only added at the head of the list,
  4162. // we can unlock the list during our traversals
  4163. // and know that the traversal will terminate properly.
  4164. //
  4165. //
  4166. // First destroy any manually configured tunnel interfaces.
  4167. //
  4168. KeAcquireSpinLock(&IFListLock, &OldIrql);
  4169. for (IF = IFList; IF != NULL; IF = IF->Next) {
  4170. //
  4171. // We should not do any processing (even just AddRefIF) on an interface
  4172. // that has zero references. As an even stronger condition,
  4173. // we avoid doing any processing if the interface
  4174. // is being destroyed. Of course, the interface might be
  4175. // destroyed after we drop the interface list lock.
  4176. //
  4177. if (! IsDisabledIF(IF)) {
  4178. AddRefIF(IF);
  4179. KeReleaseSpinLock(&IFListLock, OldIrql);
  4180. if ((IF->Type == IF_TYPE_TUNNEL_6OVER4) ||
  4181. (IF->Type == IF_TYPE_TUNNEL_V6V4)) {
  4182. //
  4183. // Destroy the tunnel interface.
  4184. //
  4185. DestroyIF(IF);
  4186. }
  4187. KeAcquireSpinLock(&IFListLock, &OldIrql);
  4188. ReleaseIF(IF);
  4189. }
  4190. }
  4191. KeReleaseSpinLock(&IFListLock, OldIrql);
  4192. //
  4193. // Now reset the remaining interfaces,
  4194. // while holding ZoneUpdateLock so
  4195. // InterfaceResetManualConfig can reset
  4196. // the zone indices consistently across the interfaces.
  4197. //
  4198. KeAcquireSpinLock(&ZoneUpdateLock, &OldIrql);
  4199. KeAcquireSpinLockAtDpcLevel(&IFListLock);
  4200. for (IF = IFList; IF != NULL; IF = IF->Next) {
  4201. if (! IsDisabledIF(IF)) {
  4202. AddRefIF(IF);
  4203. KeReleaseSpinLockFromDpcLevel(&IFListLock);
  4204. //
  4205. // Reset the interface.
  4206. //
  4207. InterfaceResetManualConfig(IF);
  4208. KeAcquireSpinLockAtDpcLevel(&IFListLock);
  4209. ReleaseIF(IF);
  4210. }
  4211. }
  4212. KeReleaseSpinLockFromDpcLevel(&IFListLock);
  4213. KeReleaseSpinLock(&ZoneUpdateLock, OldIrql);
  4214. }
  4215. //* UpdateInterface
  4216. //
  4217. // Allows the forwarding & advertising attributes
  4218. // of an interface to be changed.
  4219. //
  4220. // Called with no locks held.
  4221. //
  4222. // Return codes:
  4223. // STATUS_INVALID_PARAMETER_1 Bad Interface.
  4224. // STATUS_INSUFFICIENT_RESOURCES
  4225. // STATUS_SUCCESS
  4226. //
  4227. NTSTATUS
  4228. UpdateInterface(
  4229. Interface *IF,
  4230. int Advertises,
  4231. int Forwards)
  4232. {
  4233. KIRQL OldIrql;
  4234. NTSTATUS Status = STATUS_SUCCESS;
  4235. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  4236. if (IsDisabledIF(IF)) {
  4237. //
  4238. // Do not update an interface that is being destroyed.
  4239. //
  4240. Status = STATUS_INVALID_PARAMETER_1;
  4241. }
  4242. else if (Advertises == -1) {
  4243. //
  4244. // Do not change the Advertises attribute.
  4245. //
  4246. }
  4247. else if (!(IF->Flags & IF_FLAG_ROUTER_DISCOVERS)) {
  4248. //
  4249. // The Advertises attribute can only be controlled
  4250. // on interfaces that support Neighbor Discovery.
  4251. //
  4252. Status = STATUS_INVALID_PARAMETER_1;
  4253. }
  4254. else {
  4255. //
  4256. // Control the advertising behavior of the interface.
  4257. //
  4258. if (Advertises) {
  4259. //
  4260. // Become an advertising interfacing,
  4261. // if it is not already.
  4262. //
  4263. Status = InterfaceStartAdvertising(IF);
  4264. }
  4265. else {
  4266. //
  4267. // Stop being an advertising interface,
  4268. // if it is currently advertising.
  4269. //
  4270. InterfaceStopAdvertising(IF);
  4271. }
  4272. }
  4273. //
  4274. // Control the forwarding behavior, if we haven't had an error.
  4275. //
  4276. if ((Status == STATUS_SUCCESS) && (Forwards != -1)) {
  4277. if (Forwards) {
  4278. //
  4279. // If the interface is not currently forwarding,
  4280. // enable forwarding.
  4281. //
  4282. InterfaceStartForwarding(IF);
  4283. }
  4284. else {
  4285. //
  4286. // If the interface is currently forwarding,
  4287. // disable forwarding.
  4288. //
  4289. InterfaceStopForwarding(IF);
  4290. }
  4291. }
  4292. if (IsMCastSyncNeeded(IF))
  4293. DeferSynchronizeMulticastAddresses(IF);
  4294. KeReleaseSpinLock(&IF->Lock, OldIrql);
  4295. return Status;
  4296. }
  4297. //* ReconnectInterface
  4298. //
  4299. // Reconnect the interface. Called when a media connect notification
  4300. // is received (SetInterfaceLinkStatus) or when processing a renew
  4301. // request by IOCTL_IPV6_UPDATE_INTERFACE (IoctlUpdateInterface).
  4302. //
  4303. // Called with the interface already locked.
  4304. //
  4305. void
  4306. ReconnectInterface(
  4307. Interface *IF)
  4308. {
  4309. ASSERT(!IsDisabledIF(IF) && !(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED));
  4310. //
  4311. // Purge potentially obsolete link-layer information.
  4312. // Things might have changed while we were unplugged.
  4313. //
  4314. NeighborCacheFlush(IF, NULL);
  4315. //
  4316. // Rejoin multicast groups and restart Duplicate Address Detection.
  4317. //
  4318. // Preferred unicast addresses are registered with TDI when
  4319. // duplicate address detection completes (or is disabled).
  4320. //
  4321. ReconnectADEs(IF);
  4322. if (IF->Flags & IF_FLAG_ROUTER_DISCOVERS) {
  4323. if (IF->Flags & IF_FLAG_ADVERTISES) {
  4324. //
  4325. // Send a Router Advertisement very soon.
  4326. //
  4327. IF->RATimer = 1;
  4328. }
  4329. else {
  4330. //
  4331. // Start sending Router Solicitations.
  4332. //
  4333. IF->RSCount = 0;
  4334. IF->RSTimer = 1;
  4335. //
  4336. // Remember that this interface was just reconnected,
  4337. // so when we receive a Router Advertisement
  4338. // we can take special action.
  4339. //
  4340. IF->Flags |= IF_FLAG_MEDIA_RECONNECTED;
  4341. }
  4342. }
  4343. //
  4344. // We might have moved to a new link.
  4345. // Force the generation of a new temporary interface identifier.
  4346. // This only really makes a difference if we generate
  4347. // new addresses on this link - if it's the same link then
  4348. // we continue to use our old addresses, both public & temporary.
  4349. //
  4350. IF->TempStateAge = 0;
  4351. }
  4352. //* DisconnectInterface
  4353. //
  4354. // Disconnect the interface. Called when a media disconnect
  4355. // notification is received (SetInterfaceLinkStatus) for a connected
  4356. // interface.
  4357. //
  4358. // Called with the interface already locked.
  4359. //
  4360. void
  4361. DisconnectInterface(
  4362. Interface *IF)
  4363. {
  4364. ASSERT(!IsDisabledIF(IF) && (IF->Flags & IF_FLAG_MEDIA_DISCONNECTED));
  4365. //
  4366. // Deregister any preferred unicast addresses from TDI.
  4367. //
  4368. DisconnectADEs(IF);
  4369. }
  4370. //* SetInterfaceLinkStatus
  4371. //
  4372. // Change the interface's link status. In particular,
  4373. // set whether the media is connected or disconnected.
  4374. //
  4375. // May be called when the interface has zero references
  4376. // and is already being destroyed.
  4377. //
  4378. void
  4379. SetInterfaceLinkStatus(
  4380. void *Context,
  4381. int MediaConnected) // TRUE or FALSE.
  4382. {
  4383. Interface *IF = (Interface *) Context;
  4384. KIRQL OldIrql;
  4385. //
  4386. // Note that media-connect/disconnect events
  4387. // can be "lost". We are not informed if the
  4388. // cable is unplugged/replugged while we are
  4389. // shutdown, hibernating, or on standby.
  4390. //
  4391. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  4392. "SetInterfaceLinkStatus(IF %p) -> %s\n",
  4393. IF, MediaConnected ? "connected" : "disconnected"));
  4394. KeAcquireSpinLock(&IF->Lock, &OldIrql);
  4395. if (! IsDisabledIF(IF)) {
  4396. if (MediaConnected) {
  4397. if (IF->Flags & IF_FLAG_MEDIA_DISCONNECTED) {
  4398. //
  4399. // The cable was plugged back in.
  4400. //
  4401. IF->Flags &= ~IF_FLAG_MEDIA_DISCONNECTED;
  4402. //
  4403. // Changes in IF_FLAG_MEDIA_DISCONNECTED must
  4404. // invalidate the route cache.
  4405. //
  4406. InvalidateRouteCache();
  4407. }
  4408. //
  4409. // A connect event implies a change in the interface state
  4410. // regardless of whether the interface is already connected.
  4411. // Hence we process it outside the 'if' clause.
  4412. //
  4413. ReconnectInterface(IF);
  4414. }
  4415. else {
  4416. if (!(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED)) {
  4417. //
  4418. // The cable was unplugged.
  4419. //
  4420. IF->Flags = (IF->Flags | IF_FLAG_MEDIA_DISCONNECTED) &~
  4421. IF_FLAG_MEDIA_RECONNECTED;
  4422. //
  4423. // Changes in IF_FLAG_MEDIA_DISCONNECTED must
  4424. // invalidate the route cache.
  4425. //
  4426. InvalidateRouteCache();
  4427. //
  4428. // A disconnect event implies a change in the interface
  4429. // state only if the interface is already connected.
  4430. // Hence we process it inside the 'if' clause.
  4431. //
  4432. DisconnectInterface(IF);
  4433. }
  4434. }
  4435. }
  4436. KeReleaseSpinLock(&IF->Lock, OldIrql);
  4437. }