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.

3960 lines
130 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1998-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. // Neighbor Discovery (ND) Protocol for Internet Protocol Version 6.
  14. // Logically a part of ICMPv6, but put in a separate file for clarity.
  15. // See RFC 2461 for details.
  16. //
  17. #include "oscfg.h"
  18. #include "ndis.h"
  19. #include "ip6imp.h"
  20. #include "ip6def.h"
  21. #include "icmp.h"
  22. #include "neighbor.h"
  23. #include "route.h"
  24. #include "select.h"
  25. #include "alloca.h"
  26. #include "info.h"
  27. //
  28. //
  29. // NeighborCacheLimit is an upper-bound on IF->NCENumUnused.
  30. // NCENumUnused is the number of NCEs that have zero references.
  31. // We do not keep track of the total number of NCEs,
  32. // since NCEs with references are not available for reuse.
  33. //
  34. // REVIEW: What is a reasonable value for NeighborCacheLimit?
  35. // Should probably be sized relative to physical memory
  36. // and link characteristics.
  37. //
  38. // We cache & reclaim NCEs on a per-interface basis.
  39. // Theoretically it would be better to use a global LRU list.
  40. // However this would introduce added overhead (making NCEs bigger)
  41. // and locking. At this point I believe that it isn't worth it.
  42. //
  43. // Another thought - it's much more important to support many RCEs
  44. // than it is to support many NCEs.
  45. //
  46. uint NeighborCacheLimit; // Initialized in ConfigureGlobalParameters.
  47. //* NeighborCacheInit
  48. //
  49. // Initialize the neighbor cache for an interface.
  50. //
  51. void
  52. NeighborCacheInit(Interface *IF)
  53. {
  54. KeInitializeSpinLock(&IF->LockNC);
  55. IF->FirstNCE = IF->LastNCE = SentinelNCE(IF);
  56. ASSERT(IF->NCENumUnused == 0);
  57. ASSERT(IF->PacketList == NULL);
  58. }
  59. //* NeighborCacheDestroy
  60. //
  61. // Cleanup and deallocate the NCEs in the neighbor cache.
  62. //
  63. // This is done when the interface is being destroyed
  64. // and no one else has access to it, so it does not need to be locked.
  65. //
  66. void
  67. NeighborCacheDestroy(Interface *IF)
  68. {
  69. NeighborCacheEntry *NCE;
  70. PNDIS_PACKET Packet;
  71. ASSERT(IsDisabledIF(IF));
  72. ASSERT(IF->RefCnt == 0);
  73. while ((NCE = IF->FirstNCE) != SentinelNCE(IF)) {
  74. ASSERT(NCE->IF == IF);
  75. ASSERT(NCE->RefCnt == 0);
  76. //
  77. // Unlink the NCE.
  78. //
  79. NCE->Next->Prev = NCE->Prev;
  80. NCE->Prev->Next = NCE->Next;
  81. InterlockedDecrement((long *)&IF->NCENumUnused);
  82. //
  83. // If there's a packet waiting, destroy it too.
  84. //
  85. Packet = NCE->WaitQueue;
  86. if (Packet != NULL)
  87. IPv6SendComplete(NULL, Packet, IP_GENERAL_FAILURE);
  88. ExFreePool(NCE);
  89. }
  90. ASSERT(IF->NCENumUnused == 0);
  91. }
  92. //* NeighborCacheInitialize
  93. //
  94. // (Re)initialize a Neighbor Cache Entry.
  95. //
  96. // Our caller is responsible for using InvalidateRouteCache
  97. // when appropriate.
  98. //
  99. // Called with the neighbor cache lock held.
  100. // (So we are at DPC level.)
  101. //
  102. void
  103. NeighborCacheInitialize(
  104. Interface *IF,
  105. NeighborCacheEntry *NCE,
  106. ushort NDState,
  107. const void *LinkAddress)
  108. {
  109. //
  110. // Forget everything we know about this neighbor.
  111. //
  112. NCE->IsRouter = FALSE;
  113. NCE->IsUnreachable = FALSE;
  114. NCE->DoRoundRobin = FALSE;
  115. //
  116. // Initialize this timestamp to a value in the past,
  117. // so comparisons against it do not cause problems.
  118. //
  119. NCE->LastReachability = IPv6TickCount - IF->ReachableTime;
  120. if (NDState == ND_STATE_INCOMPLETE) {
  121. //
  122. // Let the link-layer create an initial link-layer address
  123. // and set the appropriate ND state.
  124. //
  125. NCE->NDState = (*IF->ConvertAddr)(IF->LinkContext,
  126. &NCE->NeighborAddress,
  127. NCE->LinkAddress);
  128. }
  129. else {
  130. //
  131. // Our caller supplied an ND state and a link-layer address.
  132. //
  133. NCE->NDState = NDState;
  134. RtlCopyMemory(NCE->LinkAddress, LinkAddress, IF->LinkAddressLength);
  135. }
  136. if (NCE->NDState == ND_STATE_DELAY) {
  137. //
  138. // Internally we use the PROBE state with zero NSCount instead.
  139. // If there is a packet waiting, we opt to send it immediately
  140. // instead of waiting the usual delay.
  141. //
  142. NCE->NDState = ND_STATE_PROBE;
  143. if (NCE->WaitQueue != NULL)
  144. NCE->NSTimer = 1;
  145. else
  146. NCE->NSTimer = DELAY_FIRST_PROBE_TIME;
  147. NCE->NSLimit = MAX_UNICAST_SOLICIT;
  148. }
  149. else if ((NCE->WaitQueue != NULL) ||
  150. (NCE->NDState == ND_STATE_PROBE)) {
  151. //
  152. // Get NeighborCacheTimeout to do our dirty work.
  153. // It will either send a solicitation (if the NCE is INCOMPLETE)
  154. // or send the waiting packet directly.
  155. // This is not a common case - not worth having code
  156. // here using IPv6SendLater etc.
  157. //
  158. NCE->NSTimer = 1;
  159. if (NCE->NDState == ND_STATE_INCOMPLETE)
  160. NCE->NSLimit = MAX_MULTICAST_SOLICIT;
  161. else if (NCE->NDState == ND_STATE_PROBE)
  162. NCE->NSLimit = MAX_UNICAST_SOLICIT;
  163. else
  164. NCE->NSLimit = 0;
  165. }
  166. else {
  167. //
  168. // Cancel any pending timeout.
  169. //
  170. NCE->NSTimer = 0;
  171. NCE->NSLimit = 0;
  172. }
  173. NCE->NSCount = 0;
  174. }
  175. //
  176. //* AddRefNCEInCache
  177. //
  178. // Increments the reference count on an NCE
  179. // in the interface's neighbor cache.
  180. // The NCE's current reference count may be zero.
  181. //
  182. // Called with the neighbor cache lock held.
  183. // (So we are at DPC level.)
  184. //
  185. void
  186. AddRefNCEInCache(NeighborCacheEntry *NCE)
  187. {
  188. //
  189. // If the NCE previously had no references,
  190. // increment the interface's reference count.
  191. //
  192. if (InterlockedIncrement(&NCE->RefCnt) == 1) {
  193. Interface *IF = NCE->IF;
  194. AddRefIF(IF);
  195. InterlockedDecrement((long *)&IF->NCENumUnused);
  196. }
  197. }
  198. //* ReleaseNCE
  199. //
  200. // Releases a reference for an NCE.
  201. // May result in deallocation of the NCE.
  202. //
  203. // Callable from thread or DPC context.
  204. //
  205. void
  206. ReleaseNCE(NeighborCacheEntry *NCE)
  207. {
  208. //
  209. // If the NCE has no more references,
  210. // release its reference for the interface.
  211. // This may cause the interface (and hence the NCE)
  212. // to be deallocated.
  213. //
  214. if (InterlockedDecrement(&NCE->RefCnt) == 0) {
  215. Interface *IF = NCE->IF;
  216. InterlockedIncrement((long *)&IF->NCENumUnused);
  217. ReleaseIF(IF);
  218. }
  219. }
  220. //* CreateOrReuseNeighbor
  221. //
  222. // Creates a new NCE for an interface.
  223. // Attempts to reuse an existing NCE if the interface
  224. // already has too many NCEs.
  225. //
  226. // Called with the neighbor cache lock held.
  227. // (So we are at DPC level.)
  228. //
  229. // Returns NULL if a new NCE could not be created.
  230. // Returns the NCE with RefCnt, IF, LinkAddress, WaitQueue
  231. // fields initialized. The NCE is last on the list
  232. // and IF->NCENumUnused is incremented.
  233. //
  234. NeighborCacheEntry *
  235. CreateOrReuseNeighbor(Interface *IF)
  236. {
  237. NeighborCacheEntry *NCE;
  238. //
  239. // If the cache is full, first try to free unused NCEs.
  240. //
  241. NeighborCacheCleanup(IF);
  242. //
  243. // FindNextHop tends to create NCEs that end up not getting used.
  244. // We reuse these unused NCEs even when the cache is not full.
  245. //
  246. if (((NCE = IF->LastNCE) != SentinelNCE(IF)) &&
  247. (NCE->RefCnt == 0) &&
  248. (NCE->WaitQueue == NULL) &&
  249. (((NCE->NDState == ND_STATE_INCOMPLETE) && !NCE->IsUnreachable) ||
  250. (NCE->NDState == ND_STATE_PERMANENT)))
  251. return NCE;
  252. //
  253. // Allocate a new NCE.
  254. //
  255. NCE = (NeighborCacheEntry *) ExAllocatePool(NonPagedPool, sizeof *NCE +
  256. IF->LinkAddressLength);
  257. if (NCE == NULL)
  258. return NULL;
  259. NCE->RefCnt = 0;
  260. NCE->LinkAddress = (void *)(NCE + 1);
  261. NCE->IF = IF;
  262. NCE->WaitQueue = NULL;
  263. //
  264. // Link new entry into chain of NCEs on this interface.
  265. // Put the new entry at the end, because until it is
  266. // used to send a packet it has not proven itself valuable.
  267. //
  268. NCE->Prev = IF->LastNCE;
  269. NCE->Prev->Next = NCE;
  270. NCE->Next = SentinelNCE(IF);
  271. NCE->Next->Prev = NCE;
  272. InterlockedIncrement((long *)&IF->NCENumUnused);
  273. return NCE;
  274. }
  275. //* NeighborCacheCleanup
  276. //
  277. // Removes unused NCEs if necessary to shrink the cache.
  278. // Pushes unsent packets (that were waiting for address resolution)
  279. // onto the interface's PacketList. Later NeighborCacheCompletePackets
  280. // will be called to complete the packets.
  281. //
  282. // Called with the neighbor cache lock held.
  283. //
  284. void
  285. NeighborCacheCleanup(Interface *IF)
  286. {
  287. NDIS_PACKET *Packet;
  288. NeighborCacheEntry *NCE;
  289. NeighborCacheEntry *PrevNCE;
  290. //
  291. // We traverse the cache from back to front so that
  292. // if we have to free unused NCEs, we free the LRU ones first.
  293. //
  294. for (NCE = IF->LastNCE;
  295. (NCE != SentinelNCE(IF)) && (IF->NCENumUnused > NeighborCacheLimit);
  296. NCE = PrevNCE) {
  297. PrevNCE = NCE->Prev;
  298. //
  299. // Free the NCE if it is not being used.
  300. //
  301. if (NCE->RefCnt == 0) {
  302. //
  303. // If this NCE has a waiting packet,
  304. // queue it for later completion.
  305. //
  306. Packet = NCE->WaitQueue;
  307. if (Packet != NULL) {
  308. PC(Packet)->pc_drop = TRUE;
  309. PC(Packet)->pc_link = IF->PacketList;
  310. IF->PacketList = Packet;
  311. }
  312. //
  313. // Remove and release the unused NCE.
  314. // It does not hold a reference for the interface.
  315. //
  316. NCE->Next->Prev = NCE->Prev;
  317. NCE->Prev->Next = NCE->Next;
  318. InterlockedDecrement((long *)&IF->NCENumUnused);
  319. ExFreePool(NCE);
  320. }
  321. }
  322. }
  323. //* NeighborCacheCompletePackets
  324. //
  325. // Completes a list of packets that had been waiting for address resolution.
  326. //
  327. // Called with no locks held.
  328. //
  329. void
  330. NeighborCacheCompletePackets(
  331. Interface *IF,
  332. NDIS_PACKET *PacketList)
  333. {
  334. NDIS_PACKET *Packet;
  335. while ((Packet = PacketList) != NULL) {
  336. PacketList = PC(Packet)->pc_link;
  337. if (PC(Packet)->pc_drop) {
  338. //
  339. // Drop the packet because of resource shortage.
  340. //
  341. IPv6SendComplete(NULL, Packet, IP_NO_RESOURCES);
  342. }
  343. else {
  344. //
  345. // Abort the packet because address resolution failed.
  346. //
  347. IPv6SendAbort(CastFromIF(IF),
  348. Packet, PC(Packet)->pc_offset,
  349. ICMPv6_DESTINATION_UNREACHABLE,
  350. ICMPv6_ADDRESS_UNREACHABLE,
  351. 0, FALSE);
  352. }
  353. }
  354. }
  355. //
  356. //* FindOrCreateNeighbor
  357. //
  358. // Searches an interface's neighbor cache for an entry.
  359. // Creates the entry (but does NOT send initial solicit)
  360. // if an existing entry is not found.
  361. //
  362. // May be called with route cache lock or interface lock held.
  363. // Callable from thread or DPC context.
  364. //
  365. // We avoid sending a solicit here, because this function
  366. // is called while holding locks that make that a bad idea.
  367. //
  368. // Returns NULL only if an NCE could not be created.
  369. //
  370. NeighborCacheEntry *
  371. FindOrCreateNeighbor(Interface *IF, const IPv6Addr *Addr)
  372. {
  373. KIRQL OldIrql;
  374. NeighborCacheEntry *NCE;
  375. KeAcquireSpinLock(&IF->LockNC, &OldIrql);
  376. for (NCE = IF->FirstNCE; NCE != SentinelNCE(IF); NCE = NCE->Next) {
  377. if (IP6_ADDR_EQUAL(Addr, &NCE->NeighborAddress)) {
  378. //
  379. // Found matching entry.
  380. //
  381. goto ReturnNCE;
  382. }
  383. }
  384. //
  385. // Get a new entry for this neighbor.
  386. //
  387. NCE = CreateOrReuseNeighbor(IF);
  388. if (NCE == NULL) {
  389. KeReleaseSpinLock(&IF->LockNC, OldIrql);
  390. return NULL;
  391. }
  392. ASSERT(IF->LastNCE == NCE);
  393. ASSERT(NCE->RefCnt == 0);
  394. //
  395. // Initialize the neighbor cache entry.
  396. // The RefCnt, IF, LinkAddress, WaitQueue fields are already initialized.
  397. //
  398. NCE->NeighborAddress = *Addr;
  399. #if DBG
  400. RtlZeroMemory(NCE->LinkAddress, IF->LinkAddressLength);
  401. #endif
  402. //
  403. // Initialize this NCE normally.
  404. // Loopback initialization happens in ControlNeighborLoopback.
  405. //
  406. NCE->IsLoopback = FALSE;
  407. NeighborCacheInitialize(IF, NCE, ND_STATE_INCOMPLETE, NULL);
  408. ReturnNCE:
  409. AddRefNCEInCache(NCE);
  410. KeReleaseSpinLock(&IF->LockNC, OldIrql);
  411. return NCE;
  412. }
  413. //* ControlNeighborLoopback
  414. //
  415. // Sets the Neighbor Discovery state of an NCE
  416. // to control loopback behavior.
  417. //
  418. // Called with the interface locked.
  419. // (So we are at DPC level.)
  420. //
  421. void
  422. ControlNeighborLoopback(
  423. NeighborCacheEntry *NCE,
  424. int Loopback)
  425. {
  426. Interface *IF = NCE->IF;
  427. KeAcquireSpinLockAtDpcLevel(&IF->LockNC);
  428. if (Loopback) {
  429. //
  430. // Initialize this NCE for loopback.
  431. //
  432. NCE->IsLoopback = TRUE;
  433. NeighborCacheInitialize(IF, NCE, ND_STATE_PERMANENT, IF->LinkAddress);
  434. }
  435. else {
  436. //
  437. // Initialize this NCE normally.
  438. //
  439. NCE->IsLoopback = FALSE;
  440. NeighborCacheInitialize(IF, NCE, ND_STATE_INCOMPLETE, NULL);
  441. }
  442. //
  443. // We changed state that affects routing.
  444. //
  445. InvalidateRouteCache();
  446. KeReleaseSpinLockFromDpcLevel(&IF->LockNC);
  447. }
  448. //* GetReachability
  449. //
  450. // Returns reachability information for a neighbor.
  451. //
  452. // Because FindNextHop uses GetReachability, any state change
  453. // that changes GetReachability's return value
  454. // must invalidate the route cache.
  455. //
  456. // The NeighborRoundRobin return value is special - it indicates
  457. // that FindNextHop should round-robin and use a different route.
  458. // It is not persistent - a subsequent call to GetReachability
  459. // will return NeighborUnreachable.
  460. //
  461. // Callable from DPC context (or with the route lock held),
  462. // not from thread context.
  463. //
  464. int
  465. GetReachability(NeighborCacheEntry *NCE)
  466. {
  467. Interface *IF = NCE->IF;
  468. NeighborReachability Reachable;
  469. KeAcquireSpinLockAtDpcLevel(&IF->LockNC);
  470. if (IF->Flags & IF_FLAG_MEDIA_DISCONNECTED)
  471. Reachable = NeighborInterfaceDisconnected;
  472. else if (NCE->IsUnreachable) {
  473. if (NCE->DoRoundRobin) {
  474. NCE->DoRoundRobin = FALSE;
  475. Reachable = NeighborRoundRobin;
  476. } else
  477. Reachable = NeighborUnreachable;
  478. } else
  479. Reachable = NeighborMayBeReachable;
  480. KeReleaseSpinLockFromDpcLevel(&IF->LockNC);
  481. return Reachable;
  482. }
  483. //* NeighborCacheUpdate - Update link address information about a neighbor.
  484. //
  485. // Called when we've received possibly new information about one of our
  486. // neighbors, the source of a Neighbor Solicitation, Router Advertisement,
  487. // or Router Solicitation.
  488. //
  489. // Note that our receipt of this packet DOES NOT imply forward reachability
  490. // to this neighbor, so we do not update our LastReachability timer.
  491. //
  492. // Callable from DPC context, not from thread context.
  493. //
  494. // The LinkAddress might be NULL, which means we can only process IsRouter.
  495. //
  496. // If IsRouter is FALSE, then we don't know whether the neighbor
  497. // is a router or not. If it's TRUE, then we know it is a router.
  498. //
  499. void
  500. NeighborCacheUpdate(NeighborCacheEntry *NCE, // The neighbor.
  501. const void *LinkAddress, // Corresponding media address.
  502. int IsRouter) // Do we know it's a router.
  503. {
  504. Interface *IF = NCE->IF;
  505. PNDIS_PACKET Packet = NULL;
  506. KeAcquireSpinLockAtDpcLevel(&IF->LockNC);
  507. if (NCE->NDState != ND_STATE_PERMANENT) {
  508. //
  509. // Check to see if the link address changed.
  510. //
  511. if ((LinkAddress != NULL) &&
  512. ((NCE->NDState == ND_STATE_INCOMPLETE) ||
  513. RtlCompareMemory(LinkAddress, NCE->LinkAddress,
  514. IF->LinkAddressLength) != IF->LinkAddressLength)) {
  515. //
  516. // Link-level address changed. Update cache entry with the
  517. // new one and change state to STALE as we haven't verified
  518. // forward reachability with the new address yet.
  519. //
  520. RtlCopyMemory(NCE->LinkAddress, LinkAddress,
  521. IF->LinkAddressLength);
  522. NCE->NSTimer = 0; // Cancel any outstanding timeout.
  523. NCE->NDState = ND_STATE_STALE;
  524. //
  525. // Flush the queue of waiting packets.
  526. // (Only relevant if we were in the INCOMPLETE state.)
  527. //
  528. if (NCE->WaitQueue != NULL) {
  529. Packet = NCE->WaitQueue;
  530. NCE->WaitQueue = NULL;
  531. }
  532. }
  533. //
  534. // If we know that the neighbor is a router,
  535. // remember that fact.
  536. //
  537. if (IsRouter)
  538. NCE->IsRouter = TRUE;
  539. } // end if (NCE->NDState != ND_STATE_PERMANENT)
  540. KeReleaseSpinLockFromDpcLevel(&IF->LockNC);
  541. //
  542. // If we can now send a packet, do so.
  543. // (Without holding a lock.)
  544. //
  545. if (Packet != NULL) {
  546. uint Offset;
  547. Offset = PC(Packet)->pc_offset;
  548. IPv6SendND(Packet, Offset, NCE, &(PC(Packet)->DiscoveryAddress));
  549. }
  550. }
  551. //* NeighborCacheSearch
  552. //
  553. // Searches the neighbor cache for an entry that matches
  554. // the neighbor IPv6 address. If found, returns the link-level address.
  555. // Returns FALSE to indicate failure.
  556. //
  557. // Callable from DPC context, not from thread context.
  558. //
  559. int
  560. NeighborCacheSearch(
  561. Interface *IF,
  562. const IPv6Addr *Neighbor,
  563. void *LinkAddress)
  564. {
  565. NeighborCacheEntry *NCE;
  566. KeAcquireSpinLockAtDpcLevel(&IF->LockNC);
  567. for (NCE = IF->FirstNCE; NCE != SentinelNCE(IF); NCE = NCE->Next) {
  568. if (IP6_ADDR_EQUAL(Neighbor, &NCE->NeighborAddress)) {
  569. //
  570. // Entry found. Return it's cached link-address,
  571. // if it's valid.
  572. //
  573. if (NCE->NDState == ND_STATE_INCOMPLETE) {
  574. //
  575. // No valid link address.
  576. //
  577. break;
  578. }
  579. //
  580. // The entry has a link-level address.
  581. // Must copy it with the lock held.
  582. //
  583. RtlCopyMemory(LinkAddress, NCE->LinkAddress,
  584. IF->LinkAddressLength);
  585. KeReleaseSpinLockFromDpcLevel(&IF->LockNC);
  586. return TRUE;
  587. }
  588. }
  589. KeReleaseSpinLockFromDpcLevel(&IF->LockNC);
  590. return FALSE;
  591. }
  592. //* NeighborCacheAdvert
  593. //
  594. // Updates the neighbor cache in response to an advertisement.
  595. // If no matching entry is found, ignores the advertisement.
  596. // (See RFC 1970 section 7.2.5.)
  597. //
  598. // Callable from DPC context, not from thread context.
  599. //
  600. void
  601. NeighborCacheAdvert(
  602. Interface *IF,
  603. const IPv6Addr *TargetAddress,
  604. const void *LinkAddress,
  605. ulong Flags)
  606. {
  607. NeighborCacheEntry *NCE;
  608. PNDIS_PACKET Packet = NULL;
  609. int PurgeRouting = FALSE;
  610. KeAcquireSpinLockAtDpcLevel(&IF->LockNC);
  611. for (NCE = IF->FirstNCE; NCE != SentinelNCE(IF); NCE = NCE->Next) {
  612. if (IP6_ADDR_EQUAL(TargetAddress, &NCE->NeighborAddress)) {
  613. if (NCE->NDState != ND_STATE_PERMANENT) {
  614. //
  615. // Pick up link-level address from the advertisement,
  616. // if we don't have one yet or if override is set.
  617. //
  618. if ((LinkAddress != NULL) &&
  619. ((NCE->NDState == ND_STATE_INCOMPLETE) ||
  620. ((Flags & ND_NA_FLAG_OVERRIDE) &&
  621. RtlCompareMemory(LinkAddress, NCE->LinkAddress,
  622. IF->LinkAddressLength) != IF->LinkAddressLength))) {
  623. RtlCopyMemory(NCE->LinkAddress, LinkAddress,
  624. IF->LinkAddressLength);
  625. NCE->NSTimer = 0; // Cancel any outstanding timeout.
  626. NCE->NDState = ND_STATE_STALE;
  627. //
  628. // Flush the queue of waiting packets.
  629. //
  630. if (NCE->WaitQueue != NULL) {
  631. Packet = NCE->WaitQueue;
  632. NCE->WaitQueue = NULL;
  633. //
  634. // Need to keep ref on NCE after we unlock.
  635. //
  636. AddRefNCEInCache(NCE);
  637. }
  638. goto AdvertisementMatchesCachedAddress;
  639. }
  640. if ((NCE->NDState != ND_STATE_INCOMPLETE) &&
  641. ((LinkAddress == NULL) ||
  642. RtlCompareMemory(LinkAddress, NCE->LinkAddress,
  643. IF->LinkAddressLength) == IF->LinkAddressLength)) {
  644. ushort WasRouter;
  645. AdvertisementMatchesCachedAddress:
  646. //
  647. // If this is a solicited advertisement
  648. // for our cached link-layer address,
  649. // then we have confirmed reachability.
  650. //
  651. if (Flags & ND_NA_FLAG_SOLICITED) {
  652. NCE->NSTimer = 0; // Cancel any outstanding timeout.
  653. NCE->NSCount = 0;
  654. NCE->LastReachability = IPv6TickCount; // Timestamp it.
  655. NCE->NDState = ND_STATE_REACHABLE;
  656. if (NCE->IsUnreachable) {
  657. //
  658. // We had previously concluded that this neighbor
  659. // is unreachable. Now we know otherwise.
  660. //
  661. NCE->IsUnreachable = FALSE;
  662. InvalidateRouteCache();
  663. }
  664. }
  665. //
  666. // If this is an advertisement
  667. // for our cached link-layer address,
  668. // then update IsRouter.
  669. //
  670. WasRouter = NCE->IsRouter;
  671. NCE->IsRouter = ((Flags & ND_NA_FLAG_ROUTER) != 0);
  672. if (WasRouter && !NCE->IsRouter) {
  673. //
  674. // This neighbor used to be a router, but is no longer.
  675. //
  676. PurgeRouting = TRUE;
  677. //
  678. // Need to keep ref on NCE after we unlock.
  679. //
  680. AddRefNCEInCache(NCE);
  681. }
  682. }
  683. else {
  684. //
  685. // This is not an advertisement
  686. // for our cached link-layer address.
  687. // If the advertisement was unsolicited,
  688. // give NUD a little nudge.
  689. //
  690. if (Flags & ND_NA_FLAG_SOLICITED) {
  691. //
  692. // This is probably a second NA in response
  693. // to our multicast NS for an anycast address.
  694. //
  695. }
  696. else {
  697. if (NCE->NDState == ND_STATE_REACHABLE)
  698. NCE->NDState = ND_STATE_STALE;
  699. }
  700. }
  701. } // end if (NCE->NDState != ND_STATE_PERMANENT)
  702. //
  703. // Only one NCE should match.
  704. //
  705. break;
  706. }
  707. }
  708. KeReleaseSpinLockFromDpcLevel(&IF->LockNC);
  709. //
  710. // If we can now send a packet, do so.
  711. // (Without holding a lock.)
  712. //
  713. // It is possible that this neighbor is no longer a router,
  714. // and the waiting packet wants to use the neighbor as a router.
  715. // In this situation the ND spec requires that we still send
  716. // the waiting packet to the neighbor. Narten/Nordmark confirmed
  717. // this interpretation in private email.
  718. //
  719. if (Packet != NULL) {
  720. uint Offset = PC(Packet)->pc_offset;
  721. IPv6SendND(Packet, Offset, NCE, &(PC(Packet)->DiscoveryAddress));
  722. ReleaseNCE(NCE);
  723. }
  724. //
  725. // If need be, purge the routing data structures.
  726. //
  727. if (PurgeRouting) {
  728. InvalidateRouter(NCE);
  729. ReleaseNCE(NCE);
  730. }
  731. }
  732. //* NeighborCacheProbeUnreachability
  733. //
  734. // Initiates an active probe of an unreachable neighbor,
  735. // to determine if the neighbor is still unreachable.
  736. //
  737. // To prevent ourselves from probing too frequently,
  738. // the first probe is scheduled after waiting at least
  739. // UNREACH_SOLICIT_INTERVAL from when we last determined
  740. // this neighbor to be unreachable. If called again in this
  741. // interval, we do nothing.
  742. //
  743. // Callable from DPC context (or with the route lock held),
  744. // not from thread context.
  745. //
  746. void
  747. NeighborCacheProbeUnreachability(NeighborCacheEntry *NCE)
  748. {
  749. Interface *IF = NCE->IF;
  750. uint Elapsed;
  751. ushort Delay;
  752. if (!(IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS)) {
  753. //
  754. // We cannot probe on interfaces that do not support ND.
  755. //
  756. return;
  757. }
  758. KeAcquireSpinLockAtDpcLevel(&IF->LockNC);
  759. if (!(IF->Flags & IF_FLAG_MEDIA_DISCONNECTED) && NCE->IsUnreachable) {
  760. //
  761. // Because the NCE is unreachable, we can not be in
  762. // the REACHABLE or PERMANENT states. The non-INCOMPLETE
  763. // states are possible if the NCE is unreachable/INCOMPLETE
  764. // and then we receive passive information in NeighborCacheUpdate.
  765. //
  766. ASSERT((NCE->NDState == ND_STATE_INCOMPLETE) ||
  767. (NCE->NDState == ND_STATE_PROBE) ||
  768. (NCE->NDState == ND_STATE_STALE));
  769. //
  770. // Calculate the appropriate delay until we can probe
  771. // unreachability. We do not want to determine unreachability
  772. // more frequently than UNREACH_SOLICIT_INTERVAL.
  773. //
  774. Elapsed = IPv6TickCount - NCE->LastReachability;
  775. if (Elapsed < UNREACH_SOLICIT_INTERVAL)
  776. Delay = (ushort) (UNREACH_SOLICIT_INTERVAL - Elapsed);
  777. else
  778. Delay = 1;
  779. //
  780. // If we are not already soliciting this neighbor,
  781. // probe the neighbor to check if it's still unreachable.
  782. //
  783. if (NCE->NDState == ND_STATE_STALE) {
  784. //
  785. // We need to be in the PROBE state to actively probe reachability.
  786. //
  787. NCE->NDState = ND_STATE_PROBE;
  788. ASSERT(NCE->NSTimer == 0);
  789. goto ProbeReachability;
  790. }
  791. else if ((NCE->NDState == ND_STATE_INCOMPLETE) &&
  792. (NCE->NSTimer == 0)) {
  793. ProbeReachability:
  794. //
  795. // NeighborCacheEntryTimeout will send the first probe.
  796. //
  797. NCE->NSLimit = MAX_UNREACH_SOLICIT;
  798. NCE->NSTimer = Delay;
  799. }
  800. else {
  801. //
  802. // We are already in the PROBE or active INCOMPLETE states.
  803. // First, check NSLimit. It might be MAX_UNICAST_SOLICIT or
  804. // MAX_MULTICAST_SOLICIT. Ensure it's at least MAX_UNICAST_SOLICIT.
  805. //
  806. if (NCE->NSLimit < MAX_UNREACH_SOLICIT)
  807. NCE->NSLimit = MAX_UNREACH_SOLICIT;
  808. //
  809. // Second, if we have not started actively probing yet, ensure
  810. // we do not wait longer than Delay to start.
  811. //
  812. if ((NCE->NSCount == 0) && (NCE->NSTimer > Delay))
  813. NCE->NSTimer = Delay;
  814. }
  815. }
  816. KeReleaseSpinLockFromDpcLevel(&IF->LockNC);
  817. }
  818. //* NeighborCacheReachabilityConfirmation
  819. //
  820. // Updates the neighbor cache entry in response to an indication
  821. // of forward reachability. This indication is from an upper layer
  822. // (for example, receipt of a reply to a request).
  823. //
  824. // Callable from thread or DPC context.
  825. //
  826. void
  827. NeighborCacheReachabilityConfirmation(NeighborCacheEntry *NCE)
  828. {
  829. Interface *IF = NCE->IF;
  830. KIRQL OldIrql;
  831. KeAcquireSpinLock(&IF->LockNC, &OldIrql);
  832. switch (NCE->NDState) {
  833. case ND_STATE_INCOMPLETE:
  834. //
  835. // This is strange. Perhaps the reachability confirmation is
  836. // arriving very late and ND has already decided the neighbor
  837. // is unreachable? Or perhaps the upper-layer protocol is just
  838. // mistaken? In any case ignore the confirmation.
  839. //
  840. break;
  841. case ND_STATE_PROBE:
  842. //
  843. // Stop sending solicitations.
  844. //
  845. NCE->NSCount = 0;
  846. NCE->NSTimer = 0;
  847. // fall-through
  848. case ND_STATE_STALE:
  849. //
  850. // We have forward reachability.
  851. //
  852. NCE->NDState = ND_STATE_REACHABLE;
  853. if (NCE->IsUnreachable) {
  854. //
  855. // We can get here if an NCE is reachable but goes INCOMPLETE.
  856. // Then we later receive passive information and the state
  857. // changes to STALE. Then we receive upper-layer confirmation
  858. // that the neighbor is reachable again.
  859. //
  860. // We had previously concluded that this neighbor
  861. // is unreachable. Now we know otherwise.
  862. //
  863. NCE->IsUnreachable = FALSE;
  864. InvalidateRouteCache();
  865. }
  866. // fall-through
  867. case ND_STATE_REACHABLE:
  868. //
  869. // Timestamp this reachability confirmation.
  870. //
  871. NCE->LastReachability = IPv6TickCount;
  872. // fall-through
  873. case ND_STATE_PERMANENT:
  874. //
  875. // Ignore the confirmation.
  876. //
  877. ASSERT(! NCE->IsUnreachable);
  878. break;
  879. default:
  880. ABORTMSG("Invalid ND state?");
  881. break;
  882. }
  883. KeReleaseSpinLock(&IF->LockNC, OldIrql);
  884. }
  885. //* NeighborCacheReachabilityInDoubt
  886. //
  887. // Updates the neighbor cache entry in response to an indication
  888. // from an upper-layer protocol that the neighbor may not be reachable.
  889. // (For example, a reply to a request was not received.)
  890. //
  891. // Callable from thread or DPC context.
  892. //
  893. void
  894. NeighborCacheReachabilityInDoubt(NeighborCacheEntry *NCE)
  895. {
  896. Interface *IF = NCE->IF;
  897. KIRQL OldIrql;
  898. KeAcquireSpinLock(&IF->LockNC, &OldIrql);
  899. if (NCE->NDState == ND_STATE_REACHABLE)
  900. NCE->NDState = ND_STATE_STALE;
  901. KeReleaseSpinLock(&IF->LockNC, OldIrql);
  902. }
  903. typedef struct NeighborCacheEntrySolicitInfo {
  904. struct NeighborCacheEntrySolicitInfo *Next;
  905. NeighborCacheEntry *NCE; // Holds a reference.
  906. const IPv6Addr *DiscoveryAddress; // NULL or points to AddrBuf.
  907. IPv6Addr AddrBuf;
  908. } NeighborCacheEntrySolicitInfo;
  909. //* NeighborCacheEntrySendSolicitHelper
  910. //
  911. // Helper function for sending a solicit for an NCE
  912. // when NeighborSolicitSend can not be used.
  913. // Allocates an info structure (which holds an NCE reference)
  914. // and pushes the structure on the list.
  915. // The list holds information about deferred solicits.
  916. // Later the list is processed and solicitations sent.
  917. //
  918. // Called with the neighbor cache lock held.
  919. // (So we are at DPC level.)
  920. //
  921. void
  922. NeighborCacheEntrySendSolicitHelper(
  923. NeighborCacheEntry *NCE,
  924. NeighborCacheEntrySolicitInfo **pInfoList)
  925. {
  926. NeighborCacheEntrySolicitInfo *Info;
  927. //
  928. // If this allocation fails we just skip this solicitation.
  929. //
  930. Info = ExAllocatePool(NonPagedPool, sizeof *Info);
  931. if (Info != NULL) {
  932. NDIS_PACKET *WaitPacket;
  933. AddRefNCEInCache(NCE);
  934. Info->NCE = NCE;
  935. //
  936. // If we have a packet waiting for address resolution,
  937. // then take the source address for the solicit
  938. // from the waiting packet.
  939. //
  940. WaitPacket = NCE->WaitQueue;
  941. if (WaitPacket != NULL) {
  942. Info->DiscoveryAddress = &Info->AddrBuf;
  943. Info->AddrBuf = PC(WaitPacket)->DiscoveryAddress;
  944. } else {
  945. Info->DiscoveryAddress = NULL;
  946. }
  947. Info->Next = *pInfoList;
  948. *pInfoList = Info;
  949. }
  950. }
  951. //* NeighborCacheEntryTimeout - handle an event timeout on an NCE.
  952. //
  953. // NeighborCacheTimeout calls this routine when
  954. // an NCE's NSTimer expires.
  955. //
  956. // Called with the neighbor cache lock held.
  957. // (So we are at DPC level.)
  958. //
  959. // We can not call NeighborSolicitSend or IPv6SendAbort
  960. // directly, because we hold the neighbor cache lock.
  961. // For NeighborSolicitSend we use NeighborCacheEntrySendSolicitHelper
  962. // to defer the solicit until later, and for IPv6SendAbort
  963. // we push the packet on the interface's PacketList and
  964. // NeighborCacheCompletePackets handles it later.
  965. // However we make all the NCE state transitions directly here,
  966. // so they will happen in a timely fashion.
  967. //
  968. // NB: We do not want to punt NeighborSolicitSend to a worker thread,
  969. // because DPC activity preempts worker threads. Prolonged activity
  970. // at DPC level (for example a DoS attack) would prevent solicits
  971. // from being sent, and more importantly, would prevent NCEs from
  972. // being recycled because the work items would hold NCE references.
  973. //
  974. void
  975. NeighborCacheEntryTimeout(
  976. NeighborCacheEntry *NCE,
  977. NeighborCacheEntrySolicitInfo **pInfoList)
  978. {
  979. Interface *IF = NCE->IF;
  980. NDIS_PACKET *Packet;
  981. NDIS_STATUS Status;
  982. //
  983. // Neighbor Discovery has timeouts for initial neighbor
  984. // solicitation retransmissions, the delay state, and probe
  985. // neighbor solicitation retransmissions. All of these share
  986. // the same NSTimer, and are distinguished from each other
  987. // by the NDState.
  988. //
  989. switch (NCE->NDState) {
  990. case ND_STATE_INCOMPLETE:
  991. //
  992. // Retransmission timer expired. Check to see if
  993. // sending another solicit would exceed the maximum.
  994. //
  995. if (NCE->NSCount >= NCE->NSLimit) {
  996. //
  997. // Failed to initiate connectivity to neighbor.
  998. // Reset to dormant INCOMPLETE state.
  999. //
  1000. NCE->NSCount = 0;
  1001. if (NCE->WaitQueue != NULL) {
  1002. //
  1003. // Remove the waiting packet from the NCE
  1004. // and let NeighborCacheTimeout handle it.
  1005. // We can't call IPv6SendAbort directly
  1006. // because we hold the neighbor cache lock.
  1007. //
  1008. Packet = NCE->WaitQueue;
  1009. NCE->WaitQueue = NULL;
  1010. PC(Packet)->pc_drop = FALSE;
  1011. PC(Packet)->pc_link = IF->PacketList;
  1012. IF->PacketList = Packet;
  1013. }
  1014. //
  1015. // This neighbor is not reachable.
  1016. // IsUnreachable may already be TRUE.
  1017. // But we need to give FindNextHop an opportunity to round-robin.
  1018. //
  1019. NCE->IsUnreachable = TRUE;
  1020. NCE->LastReachability = IPv6TickCount; // Timestamp it.
  1021. NCE->DoRoundRobin = TRUE;
  1022. InvalidateRouteCache();
  1023. }
  1024. else {
  1025. //
  1026. // Retransmit initial solicit, taking source address
  1027. // from the waiting packet.
  1028. //
  1029. NCE->NSCount++;
  1030. NeighborCacheEntrySendSolicitHelper(NCE, pInfoList);
  1031. //
  1032. // Re-arm timer for the next solicitation.
  1033. //
  1034. NCE->NSTimer = (ushort)IF->RetransTimer;
  1035. }
  1036. break;
  1037. case ND_STATE_PROBE:
  1038. //
  1039. // Retransmission timer expired. Check to see if
  1040. // sending another solicit would exceed the maximum.
  1041. //
  1042. if (NCE->NSCount >= NCE->NSLimit) {
  1043. //
  1044. // Failed to initiate connectivity to neighbor.
  1045. // Reset to dormant INCOMPLETE state.
  1046. //
  1047. NCE->NDState = ND_STATE_INCOMPLETE;
  1048. NCE->NSCount = 0;
  1049. //
  1050. // This neighbor is not reachable.
  1051. // IsUnreachable may already be TRUE.
  1052. // But we need to give FindNextHop an opportunity to round-robin.
  1053. //
  1054. NCE->IsUnreachable = TRUE;
  1055. NCE->LastReachability = IPv6TickCount; // Timestamp it.
  1056. NCE->DoRoundRobin = TRUE;
  1057. InvalidateRouteCache();
  1058. }
  1059. else {
  1060. //
  1061. // Retransmit probe solicitation. We can not call
  1062. // NeighborSolicitSend directly because we have
  1063. // the neighbor cache locked, so punt to a worker thread.
  1064. //
  1065. NCE->NSCount++;
  1066. NeighborCacheEntrySendSolicitHelper(NCE, pInfoList);
  1067. //
  1068. // Re-arm timer for the next solicitation.
  1069. //
  1070. NCE->NSTimer = (ushort)IF->RetransTimer;
  1071. }
  1072. // Fall-through to check for a waiting packet.
  1073. default:
  1074. //
  1075. // In rare cases (eg, see NeighborCacheInitialize)
  1076. // we can have a waiting packet when the state is not INCOMPLETE.
  1077. //
  1078. if (NCE->WaitQueue != NULL) {
  1079. LARGE_INTEGER Immediately;
  1080. Packet = NCE->WaitQueue;
  1081. NCE->WaitQueue = NULL;
  1082. //
  1083. // We use IPv6SendLater because we hold the neighbor cache lock.
  1084. //
  1085. Immediately.QuadPart = 0;
  1086. Status = IPv6SendLater(Immediately, // Send asap.
  1087. IF, Packet, PC(Packet)->pc_offset,
  1088. NCE->LinkAddress);
  1089. if (Status != NDIS_STATUS_SUCCESS) {
  1090. //
  1091. // We can't complete the packet here,
  1092. // because we hold the neighbor cache lock.
  1093. // So let NeighborCacheTimeout complete it.
  1094. //
  1095. PC(Packet)->pc_drop = TRUE;
  1096. PC(Packet)->pc_link = IF->PacketList;
  1097. IF->PacketList = Packet;
  1098. }
  1099. }
  1100. break;
  1101. }
  1102. }
  1103. //* NeighborCacheTimeout
  1104. //
  1105. // Called periodically from IPv6Timeout/InterfaceTimeout
  1106. // to handle timeouts in the interface's neighbor cache.
  1107. //
  1108. // Callable from DPC context, not from thread context.
  1109. //
  1110. // Note that NeighborCacheTimeout performs an unbounded
  1111. // (more precisely - bounded by the size of the cache)
  1112. // amount of work while holding the neighbor cache lock.
  1113. // (It does not however send packets.)
  1114. //
  1115. // One possible strategy that would help, if this is a problem,
  1116. // would be to have a second singly-linked list of NCEs
  1117. // that require action. With one traversal we reference NCEs
  1118. // and create the action list. Then we could traverse the action
  1119. // list at our leisure, taking/dropping the neighbor cache lock.
  1120. //
  1121. // On the other hand, this is all moot on a uniprocessor
  1122. // because our locks are spinlocks and we are already at DPC level.
  1123. // That is, on a uniprocessor KeAcquireSpinLockAtDpcLevel is a no-op.
  1124. //
  1125. void
  1126. NeighborCacheTimeout(Interface *IF)
  1127. {
  1128. NeighborCacheEntrySolicitInfo *InfoList = NULL;
  1129. NeighborCacheEntrySolicitInfo *Info;
  1130. NDIS_PACKET *PacketList;
  1131. NeighborCacheEntry *NCE;
  1132. KeAcquireSpinLockAtDpcLevel(&IF->LockNC);
  1133. for (NCE = IF->FirstNCE; NCE != SentinelNCE(IF); NCE = NCE->Next) {
  1134. #if DBG
  1135. //
  1136. // If there is packet waiting, we must be doing something.
  1137. //
  1138. ASSERT((NCE->WaitQueue == NULL) || (NCE->NSTimer != 0));
  1139. //
  1140. // If we are sending solicitations, we must have a timer running.
  1141. //
  1142. ASSERT((NCE->NSCount == 0) || (NCE->NSTimer != 0));
  1143. //
  1144. // If the neighbor is unreachable, the interface must support ND or
  1145. // the neighbor must be in the INCOMPLETE state.
  1146. //
  1147. ASSERT(! NCE->IsUnreachable ||
  1148. ((IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS) ||
  1149. (NCE->NDState == ND_STATE_INCOMPLETE)));
  1150. switch (NCE->NDState) {
  1151. case ND_STATE_INCOMPLETE:
  1152. //
  1153. // In the INCOMPLETE state, we can either be passive
  1154. // (no timer running, not sending solicitations)
  1155. // or active (timer running, sending solicitations).
  1156. //
  1157. ASSERT((NCE->NSTimer == 0) ||
  1158. ((NCE->NSLimit == MAX_MULTICAST_SOLICIT) ||
  1159. (NCE->NSLimit == MAX_UNREACH_SOLICIT)));
  1160. break;
  1161. case ND_STATE_PROBE:
  1162. //
  1163. // In the PROBE state, we are actively sending solicitations.
  1164. //
  1165. ASSERT((NCE->NSTimer != 0) &&
  1166. ((NCE->NSLimit == MAX_UNICAST_SOLICIT) ||
  1167. (NCE->NSLimit == MAX_UNREACH_SOLICIT)));
  1168. break;
  1169. case ND_STATE_REACHABLE:
  1170. case ND_STATE_PERMANENT:
  1171. //
  1172. // In the REACHABLE and PERMANENT states.
  1173. // the neighbor can not be considered unreachable.
  1174. //
  1175. ASSERT(! NCE->IsUnreachable);
  1176. // fall-through
  1177. case ND_STATE_STALE:
  1178. //
  1179. // In the STALE, REACHABLE, and PERMANENT states,
  1180. // we are not sending solicitations and there is no timer running,
  1181. // unless there is a packet waiting.
  1182. //
  1183. ASSERT((NCE->NSCount == 0) &&
  1184. ((NCE->NSTimer == 0) ||
  1185. ((NCE->WaitQueue != NULL) && (NCE->NSTimer == 1))));
  1186. break;
  1187. default:
  1188. ABORTMSG("bad ND state");
  1189. }
  1190. #endif // DBG
  1191. if (NCE->NSTimer != 0) {
  1192. //
  1193. // Timer is running. Decrement and check for expiration.
  1194. //
  1195. if (--NCE->NSTimer == 0) {
  1196. //
  1197. // Timer went off. NeighborCacheEntryTimeout may add
  1198. // items to our packet list and info list.
  1199. //
  1200. NeighborCacheEntryTimeout(NCE, &InfoList);
  1201. }
  1202. }
  1203. }
  1204. PacketList = IF->PacketList;
  1205. IF->PacketList = NULL;
  1206. KeReleaseSpinLockFromDpcLevel(&IF->LockNC);
  1207. //
  1208. // Now that we've unlocked, send neighbor solicitations.
  1209. //
  1210. while ((Info = InfoList) != NULL) {
  1211. InfoList = Info->Next;
  1212. NeighborSolicitSend(Info->NCE, Info->DiscoveryAddress);
  1213. ReleaseNCE(Info->NCE);
  1214. ExFreePool(Info);
  1215. }
  1216. //
  1217. // And complete the packets that we will not be sending.
  1218. //
  1219. NeighborCacheCompletePackets(IF, PacketList);
  1220. }
  1221. //* NeighborCacheFlush
  1222. //
  1223. // Flushes unused neighbor cache entries.
  1224. // If an address is supplied, flushes the NCE (at most one) for that address.
  1225. // Otherwise, flushes all unused NCEs on the interface.
  1226. //
  1227. // May be called with the interface lock held.
  1228. // Callable from thread or DPC context.
  1229. //
  1230. void
  1231. NeighborCacheFlush(Interface *IF, const IPv6Addr *Addr)
  1232. {
  1233. NeighborCacheEntry *Delete = NULL;
  1234. NeighborCacheEntry *NCE, *NextNCE;
  1235. KIRQL OldIrql;
  1236. KeAcquireSpinLock(&IF->LockNC, &OldIrql);
  1237. for (NCE = IF->FirstNCE; NCE != SentinelNCE(IF); NCE = NextNCE) {
  1238. NextNCE = NCE->Next;
  1239. if (Addr == NULL)
  1240. ; // Examine this NCE then keep looking.
  1241. else if (IP6_ADDR_EQUAL(Addr, &NCE->NeighborAddress))
  1242. NextNCE = SentinelNCE(IF); // Can terminate loop after this NCE.
  1243. else
  1244. continue; // Skip this NCE.
  1245. //
  1246. // Can we flush this NCE?
  1247. //
  1248. if ((NCE->RefCnt == 0) &&
  1249. (NCE->WaitQueue == NULL)) {
  1250. //
  1251. // Just need to unlink it.
  1252. //
  1253. NCE->Next->Prev = NCE->Prev;
  1254. NCE->Prev->Next = NCE->Next;
  1255. InterlockedDecrement((long *)&IF->NCENumUnused);
  1256. //
  1257. // And put it on our Delete list.
  1258. //
  1259. NCE->Next = Delete;
  1260. Delete = NCE;
  1261. }
  1262. else {
  1263. if (NCE->NDState != ND_STATE_PERMANENT) {
  1264. //
  1265. // Forget everything that we know about this NCE.
  1266. //
  1267. NeighborCacheInitialize(IF, NCE, ND_STATE_INCOMPLETE, NULL);
  1268. }
  1269. }
  1270. }
  1271. KeReleaseSpinLock(&IF->LockNC, OldIrql);
  1272. //
  1273. // We may have changed state that affects routing.
  1274. //
  1275. InvalidateRouteCache();
  1276. //
  1277. // Finish by actually deleting the flushed NCEs.
  1278. //
  1279. while (Delete != NULL) {
  1280. NCE = Delete;
  1281. Delete = NCE->Next;
  1282. ExFreePool(NCE);
  1283. }
  1284. }
  1285. //* RouterSolicitReceive - Handle Router Solicitation messages.
  1286. //
  1287. // See section 6.2.6 of the ND spec.
  1288. //
  1289. void
  1290. RouterSolicitReceive(
  1291. IPv6Packet *Packet, // Packet handed to us by ICMPv6Receive.
  1292. ICMPv6Header UNALIGNED *ICMP) // ICMP header.
  1293. {
  1294. Interface *IF = Packet->NTEorIF->IF;
  1295. const void *SourceLinkAddress;
  1296. //
  1297. // Ignore the solicitation unless this is an advertising interface.
  1298. //
  1299. if (!(IF->Flags & IF_FLAG_ADVERTISES))
  1300. return;
  1301. //
  1302. // Validate the solicitation.
  1303. // By the time we get here, any IPv6 Authentication Header will have
  1304. // already been checked, as will have the ICMPv6 checksum. Still need
  1305. // to check the length, source address, hop limit, and ICMP code.
  1306. //
  1307. if ((Packet->IP->HopLimit != 255) ||
  1308. (Packet->Flags & PACKET_TUNNELED)) {
  1309. //
  1310. // Packet was forwarded by a router, therefore it cannot be
  1311. // from a legitimate neighbor. Drop the packet.
  1312. //
  1313. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1314. "RouterSolicitReceive: "
  1315. "Received a routed router solicitation\n"));
  1316. return;
  1317. }
  1318. if (ICMP->Code != 0) {
  1319. //
  1320. // Bogus/corrupted router solicitation. Drop the packet.
  1321. //
  1322. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1323. "RouterSolicitReceive: "
  1324. "Received a corrupted router solicitation\n"));
  1325. return;
  1326. }
  1327. //
  1328. // We should have a 4-byte reserved field.
  1329. //
  1330. if (Packet->TotalSize < 4) {
  1331. //
  1332. // Packet too short to contain minimal solicitation.
  1333. //
  1334. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1335. "RouterSolicitReceive: "
  1336. "Received a too short solicitation\n"));
  1337. return;
  1338. }
  1339. //
  1340. // The code below assumes a contiguous buffer for all the options
  1341. // (the remainder of the packet). If that isn't currently the
  1342. // case, do a pullup for the whole thing.
  1343. //
  1344. if (! PacketPullup(Packet, Packet->TotalSize, 1, 0)) {
  1345. // Can only fail if we run out of memory.
  1346. return;
  1347. }
  1348. ASSERT(Packet->ContigSize == Packet->TotalSize);
  1349. //
  1350. // Skip over 4 byte "Reserved" field, ignoring whatever may be in it.
  1351. //
  1352. AdjustPacketParams(Packet, 4);
  1353. //
  1354. // We may have a source link-layer address option present.
  1355. // Check for it and silently ignore all others.
  1356. //
  1357. SourceLinkAddress = NULL;
  1358. while (Packet->ContigSize) {
  1359. uint OptionLength;
  1360. //
  1361. // Validate the option length.
  1362. //
  1363. if ((Packet->ContigSize < 8) ||
  1364. ((OptionLength = *((uchar *)Packet->Data + 1) << 3) == 0) ||
  1365. (OptionLength > Packet->ContigSize)) {
  1366. //
  1367. // Invalid option length. We MUST silently drop the packet.
  1368. //
  1369. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1370. "RouterSolicitReceive: "
  1371. "Received option with bogus length\n"));
  1372. return;
  1373. }
  1374. if (*((uchar *)Packet->Data) == ND_OPTION_SOURCE_LINK_LAYER_ADDRESS) {
  1375. //
  1376. // Some interfaces do not use SLLA and TLLA options.
  1377. // For example, see RFC 2893 section 3.8.
  1378. //
  1379. if (IF->ReadLLOpt != NULL) {
  1380. //
  1381. // Parse the link-layer address option.
  1382. //
  1383. SourceLinkAddress = (*IF->ReadLLOpt)(IF->LinkContext,
  1384. (uchar *)Packet->Data);
  1385. if (SourceLinkAddress == NULL) {
  1386. //
  1387. // Invalid option format. Drop the packet.
  1388. //
  1389. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1390. "RouterSolicitReceive: "
  1391. "Received bogus ll option\n"));
  1392. return;
  1393. }
  1394. }
  1395. //
  1396. // Note that if there are multiple options for some bogus reason,
  1397. // we use the last one. We must sanity-check all option lengths.
  1398. //
  1399. }
  1400. //
  1401. // Move forward to next option.
  1402. //
  1403. AdjustPacketParams(Packet, OptionLength);
  1404. }
  1405. //
  1406. // We've received and parsed a valid router solicitation.
  1407. //
  1408. if (IsUnspecified(AlignAddr(&Packet->IP->Source))) {
  1409. //
  1410. // This is a new check, introduced post-RFC 1970.
  1411. //
  1412. if (SourceLinkAddress != NULL) {
  1413. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1414. "RouterSolicitReceive: "
  1415. "Received SLA with unspecified Source?\n"));
  1416. return;
  1417. }
  1418. }
  1419. else {
  1420. //
  1421. // Only bother with this if SourceLinkAddress is present;
  1422. // if it's not, NeighborCacheUpdate won't do anything.
  1423. //
  1424. if (SourceLinkAddress != NULL) {
  1425. NeighborCacheEntry *NCE;
  1426. //
  1427. // Get the Neighbor Cache Entry for the source of this RS.
  1428. //
  1429. NCE = FindOrCreateNeighbor(IF, AlignAddr(&Packet->IP->Source));
  1430. if (NCE != NULL) {
  1431. //
  1432. // Update the Neighbor Cache Entry for the source of this RS.
  1433. //
  1434. // REVIEW: We deviate from the spec here. The spec says
  1435. // that if you receive an RS from a Source, then you MUST
  1436. // set the IsRouter flag for that Source to FALSE.
  1437. // However consider a node which is not advertising
  1438. // but it is forwarding. Such a node might send an RS
  1439. // but IsRouter should be TRUE for that node.
  1440. //
  1441. NeighborCacheUpdate(NCE, SourceLinkAddress, FALSE);
  1442. ReleaseNCE(NCE);
  1443. }
  1444. }
  1445. }
  1446. if (!(IF->Flags & IF_FLAG_MULTICAST)) {
  1447. NetTableEntry *NTE;
  1448. int GotSource;
  1449. IPv6Addr Source;
  1450. //
  1451. // What source address should we use for the RA?
  1452. //
  1453. if (IsNTE(Packet->NTEorIF) &&
  1454. ((NTE = CastToNTE(Packet->NTEorIF))->Scope == ADE_LINK_LOCAL)) {
  1455. //
  1456. // The RS was received on a link-local NTE, so use that address.
  1457. // IPv6HeaderReceive checks that the NTE is valid.
  1458. //
  1459. Source = NTE->Address;
  1460. GotSource = TRUE;
  1461. }
  1462. else {
  1463. //
  1464. // Try to get a valid link-local address.
  1465. //
  1466. GotSource = GetLinkLocalAddress(IF, &Source);
  1467. }
  1468. if (GotSource) {
  1469. //
  1470. // The interface doesn't support multicast, so instead,
  1471. // immediately send a unicast reply. This allows router
  1472. // discovery to work on NBMA interfaces such as for ISATAP.
  1473. //
  1474. RouterAdvertSend(IF, &Source, AlignAddr(&Packet->IP->Source));
  1475. }
  1476. }
  1477. else {
  1478. //
  1479. // Send a Router Advertisement very soon.
  1480. // The randomization in IPv6Timeout initialization
  1481. // provides the randomization required when sending
  1482. // a RA in response to an RS.
  1483. // NB: Although we checked IF_FLAG_ADVERTISES above,
  1484. // the situation could be different now.
  1485. //
  1486. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  1487. if (IF->RATimer != 0) {
  1488. //
  1489. // If MAX_RA_DELAY_TIME is not 1, then should use
  1490. // RandomNumber to generate the number of ticks.
  1491. //
  1492. C_ASSERT(MAX_RA_DELAY_TIME == 1);
  1493. IF->RATimer = 1;
  1494. }
  1495. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  1496. }
  1497. }
  1498. //* RouterAdvertReceive - Handle Router Advertisement messages.
  1499. //
  1500. // Validate message, update Default Router list, On-Link Prefix list,
  1501. // perform address auto-configuration.
  1502. // See sections 6.1.2, 6.3.4 of RFC 2461.
  1503. //
  1504. void
  1505. RouterAdvertReceive(
  1506. IPv6Packet *Packet, // Packet handed to us by ICMPv6Receive.
  1507. ICMPv6Header UNALIGNED *ICMP) // ICMP header.
  1508. {
  1509. Interface *IF = Packet->NTEorIF->IF;
  1510. uint CurHopLimit, RouterLifetime, MinLifetime;
  1511. uchar Flags;
  1512. uint AdvReachableTime, RetransTimer;
  1513. const void *SourceLinkAddress;
  1514. NeighborCacheEntry *NCE;
  1515. NDRouterAdvertisement UNALIGNED *RA;
  1516. //
  1517. // Ignore the advertisement if this is an advertising interface.
  1518. //
  1519. if (IF->Flags & IF_FLAG_ADVERTISES)
  1520. return;
  1521. //
  1522. // Validate the advertisement.
  1523. // By the time we get here, any IPv6 Authentication Header will have
  1524. // already been checked, as will have the ICMPv6 checksum. Still need
  1525. // to check the length, source address, hop limit, and ICMP code.
  1526. //
  1527. if ((Packet->IP->HopLimit != 255) ||
  1528. (Packet->Flags & PACKET_TUNNELED)) {
  1529. //
  1530. // Packet was forwarded by a router, therefore it cannot be
  1531. // from a legitimate neighbor. Drop the packet.
  1532. //
  1533. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1534. "RouterAdvertReceive: "
  1535. "Received a routed router advertisement\n"));
  1536. return;
  1537. }
  1538. if (ICMP->Code != 0) {
  1539. //
  1540. // Bogus/corrupted router advertisement. Drop the packet.
  1541. //
  1542. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1543. "RouterAdvertReceive: "
  1544. "Received a corrupted router advertisement\n"));
  1545. return;
  1546. }
  1547. if (!IsLinkLocal(AlignAddr(&Packet->IP->Source))) {
  1548. //
  1549. // Source address should always be link-local. Drop the packet.
  1550. //
  1551. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1552. "RouterAdvertReceive: "
  1553. "Non-link-local source in router advertisement\n"));
  1554. return;
  1555. }
  1556. //
  1557. // Pull CurHopLimit, Flags, RouterLifetime,
  1558. // AdvReachableTime, RetransTimer out of the packet.
  1559. //
  1560. if (! PacketPullup(Packet, sizeof *RA, 1, 0)) {
  1561. if (Packet->TotalSize < sizeof *RA) {
  1562. //
  1563. // Packet too short to contain minimal RA.
  1564. //
  1565. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1566. "RouterAdvertReceive: "
  1567. "Received a too short router advertisement\n"));
  1568. }
  1569. return;
  1570. }
  1571. RA = (NDRouterAdvertisement UNALIGNED *) Packet->Data;
  1572. CurHopLimit = RA->CurHopLimit;
  1573. Flags = RA->Flags;
  1574. RouterLifetime = net_short(RA->RouterLifetime);
  1575. AdvReachableTime = net_long(RA->ReachableTime);
  1576. RetransTimer = net_long(RA->RetransTimer);
  1577. AdjustPacketParams(Packet, sizeof *RA);
  1578. //
  1579. // The code below assumes a contiguous buffer for all the options
  1580. // (the remainder of the packet). If that isn't currently the
  1581. // case, do a pullup for the whole thing. We need alignment for
  1582. // IPv6Addr because of the options that we look at.
  1583. //
  1584. if (! PacketPullup(Packet, Packet->TotalSize,
  1585. __builtin_alignof(IPv6Addr), 0)) {
  1586. // Can only fail if we run out of memory.
  1587. return;
  1588. }
  1589. ASSERT(Packet->ContigSize == Packet->TotalSize);
  1590. //
  1591. // Look for a source link-layer address option.
  1592. // Also sanity-check the options before doing anything permanent.
  1593. //
  1594. SourceLinkAddress = NULL;
  1595. while (Packet->ContigSize) {
  1596. uint OptionLength;
  1597. //
  1598. // Validate the option length.
  1599. //
  1600. if ((Packet->ContigSize < 8) ||
  1601. ((OptionLength = *((uchar *)Packet->Data + 1) << 3) == 0) ||
  1602. (OptionLength > Packet->ContigSize)) {
  1603. //
  1604. // Invalid option length. We MUST silently drop the packet.
  1605. //
  1606. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1607. "RouterAdvertReceive: "
  1608. "Received RA option with with bogus length\n"));
  1609. return;
  1610. }
  1611. switch (*(uchar *)Packet->Data) {
  1612. case ND_OPTION_SOURCE_LINK_LAYER_ADDRESS:
  1613. //
  1614. // Some interfaces do not use SLLA and TLLA options.
  1615. // For example, see RFC 2893 section 3.8.
  1616. //
  1617. if (IF->ReadLLOpt != NULL) {
  1618. //
  1619. // Parse the link-layer address option.
  1620. //
  1621. SourceLinkAddress = (*IF->ReadLLOpt)(IF->LinkContext,
  1622. (uchar *)Packet->Data);
  1623. if (SourceLinkAddress == NULL) {
  1624. //
  1625. // Invalid option format. Drop the packet.
  1626. //
  1627. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1628. "RouterAdvertReceive: "
  1629. "Received RA with bogus ll option\n"));
  1630. return;
  1631. }
  1632. //
  1633. // Note that if there are multiple options for some bogus
  1634. // reason, we use the last one. We sanity-check all the
  1635. // options.
  1636. //
  1637. }
  1638. break;
  1639. case ND_OPTION_MTU:
  1640. //
  1641. // Sanity-check the option.
  1642. //
  1643. if (OptionLength != 8) {
  1644. //
  1645. // Invalid option format. Drop the packet.
  1646. //
  1647. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1648. "RouterAdvertReceive: "
  1649. "Received RA with bogus mtu option\n"));
  1650. return;
  1651. }
  1652. break;
  1653. case ND_OPTION_PREFIX_INFORMATION: {
  1654. NDOptionPrefixInformation UNALIGNED *option =
  1655. (NDOptionPrefixInformation *)Packet->Data;
  1656. //
  1657. // Sanity-check the option.
  1658. //
  1659. if ((OptionLength != 32) ||
  1660. (option->PrefixLength > IPV6_ADDRESS_LENGTH)) {
  1661. //
  1662. // Invalid option format. Drop the packet.
  1663. //
  1664. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1665. "RouterAdvertReceive: "
  1666. "Received RA with bogus prefix option\n"));
  1667. return;
  1668. }
  1669. break;
  1670. }
  1671. case ND_OPTION_ROUTE_INFORMATION: {
  1672. NDOptionRouteInformation UNALIGNED *option =
  1673. (NDOptionRouteInformation *)Packet->Data;
  1674. //
  1675. // Sanity-check the option.
  1676. // Depending on PrefixLength, the option may be 8, 16, 24 bytes.
  1677. // At this point, we know it is a multiple of 8 greater than zero.
  1678. //
  1679. if ((OptionLength > 24) ||
  1680. (option->PrefixLength > IPV6_ADDRESS_LENGTH) ||
  1681. ((option->PrefixLength > 64) && (OptionLength < 24)) ||
  1682. ((option->PrefixLength > 0) && (OptionLength < 16))) {
  1683. //
  1684. // Invalid option format. Drop the packet.
  1685. //
  1686. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1687. "RouterAdvertReceive: "
  1688. "Received RA with bogus route option\n"));
  1689. return;
  1690. }
  1691. break;
  1692. }
  1693. }
  1694. //
  1695. // Move forward to next option.
  1696. // Note that we are not updating TotalSize here,
  1697. // so we can use it below to back up.
  1698. //
  1699. (uchar *)Packet->Data += OptionLength;
  1700. Packet->ContigSize -= OptionLength;
  1701. }
  1702. //
  1703. // Reset Data pointer & ContigSize.
  1704. //
  1705. (uchar *)Packet->Data -= Packet->TotalSize;
  1706. Packet->ContigSize += Packet->TotalSize;
  1707. //
  1708. // Get the Neighbor Cache Entry for the source of this RA.
  1709. //
  1710. NCE = FindOrCreateNeighbor(IF, AlignAddr(&Packet->IP->Source));
  1711. if (NCE == NULL) {
  1712. //
  1713. // Couldn't find or create NCE. Drop the packet.
  1714. //
  1715. return;
  1716. }
  1717. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  1718. //
  1719. // Cache the parity of the "other stateful config" flag.
  1720. //
  1721. if (Flags & ND_RA_FLAG_OTHER) {
  1722. IF->Flags |= IF_FLAG_OTHER_STATEFUL_CONFIG;
  1723. } else {
  1724. IF->Flags &= ~IF_FLAG_OTHER_STATEFUL_CONFIG;
  1725. }
  1726. //
  1727. // If we just reconnected this interface,
  1728. // then give all state learned from auto-configuration
  1729. // a small "accelerated" lifetime.
  1730. // The processing below might extend accelerated lifetimes.
  1731. //
  1732. if (IF->Flags & IF_FLAG_MEDIA_RECONNECTED) {
  1733. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1734. "RouterAdvertReceive(IF %p) - reconnecting\n", IF));
  1735. IF->Flags &= ~IF_FLAG_MEDIA_RECONNECTED;
  1736. //
  1737. // Reset auto-configured address lifetimes.
  1738. //
  1739. AddrConfResetAutoConfig(IF,
  1740. 2 * MAX_RA_DELAY_TIME + MIN_DELAY_BETWEEN_RAS);
  1741. //
  1742. // Similarly, reset auto-configured routes.
  1743. //
  1744. RouteTableResetAutoConfig(IF,
  1745. 2 * MAX_RA_DELAY_TIME + MIN_DELAY_BETWEEN_RAS);
  1746. //
  1747. // Reset parameters that are learned from RAs.
  1748. //
  1749. InterfaceResetAutoConfig(IF);
  1750. }
  1751. //
  1752. // A host MUST stop sending router solicitations for an interface upon
  1753. // receiving a valid router advertisement with a non-zero router lifetime.
  1754. // We go a step further and, on a non-multicast interface, stop after the
  1755. // first valid response - presumably that's all we are going to receive.
  1756. // Note that we should always send at least one router solicitation,
  1757. // even if we receive an unsolicited router advertisement first.
  1758. //
  1759. if ((RouterLifetime != 0) || !(IF->Flags & IF_FLAG_MULTICAST)) {
  1760. if (IF->RSCount > 0)
  1761. IF->RSTimer = 0;
  1762. }
  1763. //
  1764. // Update the BaseReachableTime and ReachableTime.
  1765. // NB: We use a lock for coordinated updates, but other code
  1766. // reads the ReachableTime field without a lock.
  1767. //
  1768. if ((AdvReachableTime != 0) &&
  1769. (AdvReachableTime != IF->BaseReachableTime)) {
  1770. IF->BaseReachableTime = AdvReachableTime;
  1771. IF->ReachableTime = CalcReachableTime(AdvReachableTime);
  1772. }
  1773. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  1774. //
  1775. // Update the Neighbor Cache Entry for the source of this RA.
  1776. //
  1777. NeighborCacheUpdate(NCE, SourceLinkAddress, TRUE);
  1778. //
  1779. // Update the Default Router List.
  1780. // Note that router lifetimes on the wire,
  1781. // unlike prefix lifetimes, can not be infinite.
  1782. //
  1783. ASSERT(RouterLifetime != INFINITE_LIFETIME); // Because it's 16 bits.
  1784. MinLifetime = RouterLifetime = ConvertSecondsToTicks(RouterLifetime);
  1785. RouteTableUpdate(NULL, // System update.
  1786. IF, NCE,
  1787. &UnspecifiedAddr, 0, 0,
  1788. RouterLifetime, RouterLifetime,
  1789. ExtractRoutePreference(Flags),
  1790. RTE_TYPE_AUTOCONF,
  1791. FALSE, FALSE);
  1792. //
  1793. // Update the hop limit for the interface.
  1794. // NB: We rely on loads/stores of the CurHopLimit field being atomic.
  1795. //
  1796. if (CurHopLimit != 0) {
  1797. IF->CurHopLimit = CurHopLimit;
  1798. }
  1799. //
  1800. // Update the RetransTimer field.
  1801. // NB: We rely on loads/stores of this field being atomic.
  1802. //
  1803. if (RetransTimer != 0)
  1804. IF->RetransTimer = ConvertMillisToTicks(RetransTimer);
  1805. //
  1806. // Process any LinkMTU, PrefixInformation options.
  1807. //
  1808. while (Packet->ContigSize) {
  1809. uint OptionLength;
  1810. //
  1811. // The option length was validated in the first pass
  1812. // over the options, above.
  1813. //
  1814. OptionLength = *((uchar *)Packet->Data + 1) << 3;
  1815. switch (*(uchar *)Packet->Data) {
  1816. case ND_OPTION_MTU: {
  1817. NDOptionMTU UNALIGNED *option =
  1818. (NDOptionMTU UNALIGNED *)Packet->Data;
  1819. uint LinkMTU = net_long(option->MTU);
  1820. if ((IPv6_MINIMUM_MTU <= LinkMTU) &&
  1821. (LinkMTU <= IF->TrueLinkMTU))
  1822. UpdateLinkMTU(IF, LinkMTU);
  1823. break;
  1824. }
  1825. case ND_OPTION_PREFIX_INFORMATION: {
  1826. NDOptionPrefixInformation UNALIGNED *option =
  1827. (NDOptionPrefixInformation UNALIGNED *)Packet->Data;
  1828. uint PrefixLength, ValidLifetime, PreferredLifetime;
  1829. IPv6Addr Prefix;
  1830. //
  1831. // Extract the prefix length and prefix from option. We
  1832. // MUST ignore any bits in the prefix after the prefix length.
  1833. // RouteTableUpdate and SitePrefixUpdate do that also,
  1834. // but we look at the prefix directly here.
  1835. //
  1836. PrefixLength = option->PrefixLength; // In bits.
  1837. CopyPrefix(&Prefix, AlignAddr(&option->Prefix), PrefixLength);
  1838. ValidLifetime = net_long(option->ValidLifetime);
  1839. ValidLifetime = ConvertSecondsToTicks(ValidLifetime);
  1840. PreferredLifetime = net_long(option->PreferredLifetime);
  1841. PreferredLifetime = ConvertSecondsToTicks(PreferredLifetime);
  1842. if (MinLifetime > PreferredLifetime)
  1843. MinLifetime = PreferredLifetime;
  1844. //
  1845. // Silently ignore link-local and multicast prefixes.
  1846. // REVIEW - Is this actually the required check?
  1847. //
  1848. if (IsLinkLocal(&Prefix) || IsMulticast(&Prefix))
  1849. break;
  1850. //
  1851. // Generally at least one flag bit is set,
  1852. // but we must process them independently.
  1853. //
  1854. if (option->Flags & ND_PREFIX_FLAG_ON_LINK)
  1855. RouteTableUpdate(NULL, // System update.
  1856. IF, NULL,
  1857. &Prefix, PrefixLength, 0,
  1858. ValidLifetime, ValidLifetime,
  1859. ROUTE_PREF_ON_LINK,
  1860. RTE_TYPE_AUTOCONF,
  1861. FALSE, FALSE);
  1862. if (option->Flags & ND_PREFIX_FLAG_ROUTE)
  1863. RouteTableUpdate(NULL, // System update.
  1864. IF, NCE,
  1865. &Prefix, PrefixLength, 0,
  1866. ValidLifetime, ValidLifetime,
  1867. ROUTE_PREF_MEDIUM,
  1868. RTE_TYPE_AUTOCONF,
  1869. FALSE, FALSE);
  1870. //
  1871. // We ignore site-local prefixes here. Above check
  1872. // filters out link-local and multicast prefixes.
  1873. //
  1874. if (! IsSiteLocal(&Prefix)) {
  1875. uint SitePrefixLength;
  1876. //
  1877. // If the S bit is clear, then we check the A bit
  1878. // and use the interface's default site prefix length.
  1879. // This lets us infer site prefixes when routers
  1880. // do not support the S bit.
  1881. //
  1882. if (option->Flags & ND_PREFIX_FLAG_SITE_PREFIX)
  1883. SitePrefixLength = option->SitePrefixLength;
  1884. else if (option->Flags & ND_PREFIX_FLAG_AUTONOMOUS)
  1885. SitePrefixLength = IF->DefSitePrefixLength;
  1886. else
  1887. SitePrefixLength = 0;
  1888. //
  1889. // Ignore if the Site Prefix Length is zero.
  1890. //
  1891. if (SitePrefixLength != 0)
  1892. SitePrefixUpdate(IF,
  1893. &Prefix, SitePrefixLength,
  1894. ValidLifetime);
  1895. }
  1896. if (option->Flags & ND_PREFIX_FLAG_AUTONOMOUS) {
  1897. //
  1898. // Attempt autonomous address-configuration.
  1899. //
  1900. if (PreferredLifetime > ValidLifetime) {
  1901. //
  1902. // MAY log a system management error.
  1903. //
  1904. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1905. "RouterAdvertReceive: "
  1906. "Bogus valid/preferred lifetimes\n"));
  1907. }
  1908. else if ((PrefixLength + IPV6_ID_LENGTH) !=
  1909. IPV6_ADDRESS_LENGTH) {
  1910. //
  1911. // If the sum of the prefix length and the interface
  1912. // identifier (always 64 bits in our implementation)
  1913. // is not 128 bits, we MUST ignore the prefix option.
  1914. // MAY log a system management error.
  1915. //
  1916. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1917. "RouterAdvertReceive: Got prefix length of %u, "
  1918. "must be 64 for auto-config\n", PrefixLength));
  1919. }
  1920. else if (IF->CreateToken != NULL) {
  1921. AddrConfUpdate(IF, &Prefix,
  1922. ValidLifetime, PreferredLifetime,
  1923. FALSE, // Not authenticated.
  1924. NULL); // Do not return NTE.
  1925. }
  1926. }
  1927. break;
  1928. }
  1929. case ND_OPTION_ROUTE_INFORMATION: {
  1930. NDOptionRouteInformation UNALIGNED *option =
  1931. (NDOptionRouteInformation UNALIGNED *)Packet->Data;
  1932. uint PrefixLength, RouteLifetime;
  1933. IPv6Addr *Prefix;
  1934. //
  1935. // Extract the prefix length and prefix from option. We
  1936. // MUST ignore any bits in the prefix after the prefix length.
  1937. // RouteTableUpdate does that for us.
  1938. //
  1939. PrefixLength = option->PrefixLength; // In bits.
  1940. Prefix = AlignAddr(&option->Prefix);
  1941. RouteLifetime = net_long(option->RouteLifetime);
  1942. RouteLifetime = ConvertSecondsToTicks(RouteLifetime);
  1943. if (MinLifetime > RouteLifetime)
  1944. MinLifetime = RouteLifetime;
  1945. RouteTableUpdate(NULL, // System update.
  1946. IF, NCE,
  1947. Prefix, PrefixLength, 0,
  1948. RouteLifetime, RouteLifetime,
  1949. ExtractRoutePreference(option->Flags),
  1950. RTE_TYPE_AUTOCONF,
  1951. FALSE, FALSE);
  1952. break;
  1953. }
  1954. }
  1955. //
  1956. // Move forward to next option.
  1957. //
  1958. AdjustPacketParams(Packet, OptionLength);
  1959. }
  1960. if (!(IF->Flags & IF_FLAG_MULTICAST) && (IF->RSTimer == 0)) {
  1961. //
  1962. // On non-multicast interfaces such as the ISATAP interface,
  1963. // we need to send periodic Router Solicitations. We want
  1964. // to do so as infrequently as possible and still be reasonably
  1965. // robust. We'll try to refresh it halfway through the lowest
  1966. // lifetime in the RA we saw. However, if a renumbering event
  1967. // is going on, and a lifetime is low, we don't want to send
  1968. // too often, so we put on a minimum cap equal to what we'd
  1969. // use if we never got an RA.
  1970. //
  1971. if (MinLifetime < SLOW_RTR_SOLICITATION_INTERVAL * 2)
  1972. IF->RSTimer = SLOW_RTR_SOLICITATION_INTERVAL;
  1973. else
  1974. IF->RSTimer = MinLifetime / 2;
  1975. IF->RSCount = MAX_RTR_SOLICITATIONS;
  1976. }
  1977. //
  1978. // Done with packet.
  1979. //
  1980. ReleaseNCE(NCE);
  1981. }
  1982. //* NeighborSolicitReceive - Handle Neighbor Solicitation messages.
  1983. //
  1984. // Validate message, update ND cache, and reply with Neighbor Advertisement.
  1985. // See section 7.2.4 of RFC 1970.
  1986. //
  1987. void
  1988. NeighborSolicitReceive(
  1989. IPv6Packet *Packet, // Packet handed to us by ICMPv6Receive.
  1990. ICMPv6Header UNALIGNED *ICMP) // ICMP header.
  1991. {
  1992. Interface *IF = Packet->NTEorIF->IF;
  1993. const IPv6Addr *TargetAddress;
  1994. const void *SourceLinkAddress;
  1995. NDIS_STATUS Status;
  1996. NDIS_PACKET *AdvertPacket;
  1997. uint Offset;
  1998. uint PayloadLength;
  1999. void *Mem;
  2000. uint MemLen;
  2001. IPv6Header UNALIGNED *AdvertIP;
  2002. ICMPv6Header UNALIGNED *AdvertICMP;
  2003. ulong Flags;
  2004. void *AdvertTargetOption;
  2005. IPv6Addr *AdvertTargetAddress;
  2006. void *DestLinkAddress;
  2007. NetTableEntryOrInterface *TargetNTEorIF;
  2008. ushort TargetType;
  2009. //
  2010. // Validate the solicitation.
  2011. // By the time we get here, any IPv6 Authentication Header will have
  2012. // already been checked, as will have the ICMPv6 checksum. Still need
  2013. // to check the IP Hop Limit, and the ICMP code and length.
  2014. //
  2015. if ((Packet->IP->HopLimit != 255) ||
  2016. (Packet->Flags & PACKET_TUNNELED)) {
  2017. //
  2018. // Packet was forwarded by a router, therefore it cannot be
  2019. // from a legitimate neighbor. Drop the packet.
  2020. //
  2021. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2022. "NeighborSolicitReceive: "
  2023. "Received a routed neighbor solicitation\n"));
  2024. return;
  2025. }
  2026. if (ICMP->Code != 0) {
  2027. //
  2028. // Bogus/corrupted neighbor solicitation message. Drop the packet.
  2029. //
  2030. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2031. "NeighborSolicitReceive: "
  2032. "Received a corrupted neighbor solicitation\n"));
  2033. return;
  2034. }
  2035. //
  2036. // Next we have a 4 byte reserved field, then an IPv6 address.
  2037. //
  2038. if (! PacketPullup(Packet, 4 + sizeof(IPv6Addr),
  2039. __builtin_alignof(IPv6Addr), 0)) {
  2040. if (Packet->TotalSize < 4 + sizeof(IPv6Addr)) {
  2041. //
  2042. // Packet too short to contain minimal solicitation.
  2043. //
  2044. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2045. "NeighborSolicitReceive: "
  2046. "Received a too short solicitation\n"));
  2047. }
  2048. return;
  2049. }
  2050. //
  2051. // Skip over 4 byte "Reserved" field, ignoring whatever may be in it.
  2052. // Get a pointer to the target address which follows, then skip over that.
  2053. //
  2054. TargetAddress = AlignAddr((IPv6Addr UNALIGNED *)
  2055. ((uchar *)Packet->Data + 4));
  2056. AdjustPacketParams(Packet, 4 + sizeof(IPv6Addr));
  2057. //
  2058. // See if we're the target of the solicitation. If the target address is
  2059. // not a unicast or anycast address assigned to receiving interface,
  2060. // then we must silently drop the packet.
  2061. //
  2062. TargetNTEorIF = FindAddressOnInterface(IF, TargetAddress, &TargetType);
  2063. if (TargetNTEorIF == NULL) {
  2064. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  2065. "NeighborSolicitReceive: disabled IF\n"));
  2066. return;
  2067. }
  2068. else if (TargetType == ADE_NONE) {
  2069. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  2070. "NeighborSolicitReceive: Did not find target address\n"));
  2071. goto Return;
  2072. }
  2073. else if (TargetType == ADE_MULTICAST) {
  2074. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2075. "NeighborSolicitReceive: "
  2076. "Target address not uni/anycast\n"));
  2077. goto Return;
  2078. }
  2079. ASSERT(((TargetType == ADE_UNICAST) &&
  2080. IsNTE(TargetNTEorIF) &&
  2081. IP6_ADDR_EQUAL(&CastToNTE(TargetNTEorIF)->Address,
  2082. TargetAddress)) ||
  2083. (TargetType == ADE_ANYCAST));
  2084. //
  2085. // The code below assumes a contiguous buffer for all the options
  2086. // (the remainder of the packet). If that isn't currently the
  2087. // case, do a pullup for the whole thing.
  2088. //
  2089. if (! PacketPullup(Packet, Packet->TotalSize, 1, 0)) {
  2090. // Can only fail if we run out of memory.
  2091. goto Return;
  2092. }
  2093. ASSERT(Packet->ContigSize == Packet->TotalSize);
  2094. //
  2095. // We may have a source link-layer address option present.
  2096. // Check for it and silently ignore all others.
  2097. //
  2098. SourceLinkAddress = NULL;
  2099. while (Packet->ContigSize) {
  2100. uint OptionLength;
  2101. //
  2102. // Validate the option length.
  2103. //
  2104. if ((Packet->ContigSize < 8) ||
  2105. ((OptionLength = *((uchar *)Packet->Data + 1) << 3) == 0) ||
  2106. (OptionLength > Packet->ContigSize)) {
  2107. //
  2108. // Invalid option length. We MUST silently drop the packet.
  2109. //
  2110. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2111. "NeighborSolicitReceive: "
  2112. "Received option with bogus length\n"));
  2113. goto Return;
  2114. }
  2115. if (*((uchar *)Packet->Data) == ND_OPTION_SOURCE_LINK_LAYER_ADDRESS) {
  2116. //
  2117. // Some interfaces do not use SLLA and TLLA options.
  2118. // For example, see RFC 2893 section 3.8.
  2119. //
  2120. if (IF->ReadLLOpt != NULL) {
  2121. //
  2122. // Parse the link-layer address option.
  2123. //
  2124. SourceLinkAddress = (*IF->ReadLLOpt)(IF->LinkContext,
  2125. (uchar *)Packet->Data);
  2126. if (SourceLinkAddress == NULL) {
  2127. //
  2128. // Invalid option format. Drop the packet.
  2129. //
  2130. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2131. "NeighborSolicitReceive: "
  2132. "Received bogus ll option\n"));
  2133. goto Return;
  2134. }
  2135. //
  2136. // Note that if there are multiple options for some bogus
  2137. // reason, we use the last one. We sanity-check all the
  2138. // options.
  2139. //
  2140. }
  2141. }
  2142. //
  2143. // Move forward to next option.
  2144. //
  2145. AdjustPacketParams(Packet, OptionLength);
  2146. }
  2147. if (IsUnspecified(AlignAddr(&Packet->IP->Source))) {
  2148. //
  2149. // Checks that were added post-RFC 1970.
  2150. //
  2151. if (!IsSolicitedNodeMulticast(AlignAddr(&Packet->IP->Dest))) {
  2152. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2153. "NeighborSolicitReceive: NS with null src, bad dst\n"));
  2154. goto Return;
  2155. }
  2156. if (SourceLinkAddress != NULL) {
  2157. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2158. "NeighborSolicitReceive: NS with null src and SLA\n"));
  2159. goto Return;
  2160. }
  2161. }
  2162. //
  2163. // We've received and parsed a valid neighbor solicitation.
  2164. //
  2165. // First, we check our Duplicate Address Detection state.
  2166. // (See RFC 2461 section 5.4.3.)
  2167. //
  2168. if (TargetType == ADE_UNICAST) {
  2169. NetTableEntry *TargetNTE = CastToNTE(TargetNTEorIF);
  2170. int DefendAddress = TRUE;
  2171. //
  2172. // As an optimization, we perform this check without holding a lock.
  2173. // This results in one less lock acquire/release for the common case.
  2174. //
  2175. if (!IsValidNTE(TargetNTE)) {
  2176. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  2177. //
  2178. // If the source address of the solicitation is the unspecified
  2179. // address, it came from a node performing DAD on the address.
  2180. // If our address is tentative, then we make it duplicate.
  2181. //
  2182. if (IsUnspecified(AlignAddr(&Packet->IP->Source)) &&
  2183. IsTentativeNTE(TargetNTE)) {
  2184. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  2185. "NeighborSolicitReceive: DAD found duplicate\n"));
  2186. AddrConfDuplicate(IF, TargetNTE);
  2187. }
  2188. if (!IsValidNTE(TargetNTE)) {
  2189. //
  2190. // Do not advertise/defend our invalid address.
  2191. //
  2192. DefendAddress = FALSE;
  2193. }
  2194. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  2195. }
  2196. if (! DefendAddress) {
  2197. //
  2198. // We should not respond to the solicit.
  2199. //
  2200. goto Return;
  2201. }
  2202. }
  2203. //
  2204. // Update the Neighbor Cache Entry for the source of this solicit.
  2205. // In this case, only bother if the SourceLinkAddress is present;
  2206. // if it's not, NeighborCacheUpdate won't do anything.
  2207. //
  2208. if (!IsUnspecified(AlignAddr(&Packet->IP->Source)) &&
  2209. (SourceLinkAddress != NULL)) {
  2210. NeighborCacheEntry *NCE;
  2211. NCE = FindOrCreateNeighbor(IF, AlignAddr(&Packet->IP->Source));
  2212. if (NCE != NULL) {
  2213. NeighborCacheUpdate(NCE, SourceLinkAddress, FALSE);
  2214. ReleaseNCE(NCE);
  2215. }
  2216. }
  2217. //
  2218. // Send a solicited neighbor advertisement back to the source.
  2219. //
  2220. // Interface to send on is 'IF' (I/F solicitation received on).
  2221. //
  2222. ICMPv6OutStats.icmps_msgs++;
  2223. //
  2224. // Allocate a packet for advertisement.
  2225. // In addition to the 24 bytes for the solicit proper, leave space
  2226. // for target link-layer address option (round option length up to
  2227. // 8-byte multiple).
  2228. //
  2229. PayloadLength = 24;
  2230. if (IF->WriteLLOpt != NULL)
  2231. PayloadLength += (IF->LinkAddressLength + 2 + 7) & ~7;
  2232. Offset = IF->LinkHeaderSize;
  2233. MemLen = Offset + sizeof(IPv6Header) + PayloadLength;
  2234. Status = IPv6AllocatePacket(MemLen, &AdvertPacket, &Mem);
  2235. if (Status != NDIS_STATUS_SUCCESS) {
  2236. ICMPv6OutStats.icmps_errors++;
  2237. goto Return;
  2238. }
  2239. //
  2240. // Prepare IP header of advertisement.
  2241. //
  2242. AdvertIP = (IPv6Header UNALIGNED *)((uchar *)Mem + Offset);
  2243. AdvertIP->VersClassFlow = IP_VERSION;
  2244. AdvertIP->PayloadLength = net_short((ushort)PayloadLength);
  2245. AdvertIP->NextHeader = IP_PROTOCOL_ICMPv6;
  2246. AdvertIP->HopLimit = 255;
  2247. //
  2248. // Prepare ICMP header.
  2249. //
  2250. AdvertICMP = (ICMPv6Header UNALIGNED *)(AdvertIP + 1);
  2251. AdvertICMP->Type = ICMPv6_NEIGHBOR_ADVERT;
  2252. AdvertICMP->Code = 0;
  2253. AdvertICMP->Checksum = 0;
  2254. Flags = 0;
  2255. if (IF->Flags & IF_FLAG_FORWARDS)
  2256. Flags |= ND_NA_FLAG_ROUTER;
  2257. //
  2258. // We prevent loopback of all ND packets.
  2259. //
  2260. PC(AdvertPacket)->Flags = NDIS_FLAGS_DONT_LOOPBACK;
  2261. //
  2262. // Check source of solicitation to see where we should direct our
  2263. // advertisement (and determine what type of advertisement to send).
  2264. //
  2265. if (IsUnspecified(AlignAddr(&Packet->IP->Source))) {
  2266. //
  2267. // Solicitation came from an unspecified address (presumably a node
  2268. // undergoing initialization), so we need to multicast our response.
  2269. // We also don't set the solicited flag since we can't specify the
  2270. // specific node our advertisement is directed at.
  2271. //
  2272. AdvertIP->Dest = AllNodesOnLinkAddr;
  2273. PC(AdvertPacket)->Flags |= NDIS_FLAGS_MULTICAST_PACKET;
  2274. DestLinkAddress = alloca(IF->LinkAddressLength);
  2275. (*IF->ConvertAddr)(IF->LinkContext, &AllNodesOnLinkAddr,
  2276. DestLinkAddress);
  2277. } else {
  2278. //
  2279. // We know who sent the solicitation, so we can respond by unicasting
  2280. // our solicited advertisement back to the soliciter.
  2281. //
  2282. AdvertIP->Dest = Packet->IP->Source;
  2283. Flags |= ND_NA_FLAG_SOLICITED;
  2284. //
  2285. // Find link-level address for above. We should have it cached (note
  2286. // that it will be cached if it just came in on this solicitation).
  2287. //
  2288. if (SourceLinkAddress != NULL) {
  2289. //
  2290. // This is faster than checking the ND cache and
  2291. // it should be the common case. In fact, the RFC
  2292. // requires that senders include the SLLA option,
  2293. // except for point-to-point interfaces.
  2294. //
  2295. DestLinkAddress = (void *)SourceLinkAddress;
  2296. } else if (IF->Flags & IF_FLAG_P2P) {
  2297. //
  2298. // Use the link-layer address of the other endpoint,
  2299. // which follows our link-layer address in memory.
  2300. //
  2301. DestLinkAddress = IF->LinkAddress + IF->LinkAddressLength;
  2302. } else {
  2303. //
  2304. // We shouldn't get here, because senders MUST
  2305. // include the SLLA option. But make a best effort
  2306. // to reply anyway.
  2307. //
  2308. DestLinkAddress = alloca(IF->LinkAddressLength);
  2309. if (!NeighborCacheSearch(IF, AlignAddr(&Packet->IP->Source),
  2310. DestLinkAddress)) {
  2311. //
  2312. // No entry found in ND cache.
  2313. // Queuing for ND does not seem correct -
  2314. // just drop the solicit.
  2315. //
  2316. ICMPv6OutStats.icmps_errors++;
  2317. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  2318. "NeighborSolicitReceive: Didn't find NCE!?!\n"));
  2319. IPv6FreePacket(AdvertPacket);
  2320. goto Return;
  2321. }
  2322. }
  2323. }
  2324. if (IsNTE(TargetNTEorIF)) {
  2325. //
  2326. // Take our source address from the target NTE.
  2327. //
  2328. AdvertIP->Source = CastToNTE(TargetNTEorIF)->Address;
  2329. }
  2330. else {
  2331. NetTableEntry *BestNTE;
  2332. //
  2333. // Find the best source address for the destination.
  2334. //
  2335. BestNTE = FindBestSourceAddress(IF, AlignAddr(&AdvertIP->Dest));
  2336. if (BestNTE == NULL) {
  2337. ICMPv6OutStats.icmps_errors++;
  2338. goto Return;
  2339. }
  2340. AdvertIP->Source = BestNTE->Address;
  2341. ReleaseNTE(BestNTE);
  2342. }
  2343. //
  2344. // Take the target address from the solicitation.
  2345. //
  2346. AdvertTargetAddress = (IPv6Addr *)
  2347. ((char *)AdvertICMP + sizeof(ICMPv6Header) + sizeof(ulong));
  2348. *AdvertTargetAddress = *TargetAddress;
  2349. if (PayloadLength != 24) {
  2350. //
  2351. // Include target link-layer address option.
  2352. //
  2353. AdvertTargetOption = (void *)((char *)AdvertTargetAddress +
  2354. sizeof(IPv6Addr));
  2355. ((uchar *)AdvertTargetOption)[0] = ND_OPTION_TARGET_LINK_LAYER_ADDRESS;
  2356. ((uchar *)AdvertTargetOption)[1] = (uchar)((IF->LinkAddressLength + 2 + 7) >> 3);
  2357. (*IF->WriteLLOpt)(IF->LinkContext, AdvertTargetOption, IF->LinkAddress);
  2358. //
  2359. // We set the override flag when including the TLLA option,
  2360. // unless the target is an anycast address.
  2361. //
  2362. if (TargetType != ADE_ANYCAST)
  2363. Flags |= ND_NA_FLAG_OVERRIDE;
  2364. }
  2365. //
  2366. // Fill in Flags field in advertisement.
  2367. //
  2368. *(ulong UNALIGNED *)((char *)AdvertICMP + sizeof(ICMPv6Header)) =
  2369. net_long(Flags);
  2370. //
  2371. // Calculate the ICMPv6 checksum. It covers the entire ICMPv6 message
  2372. // starting with the ICMPv6 header, plus the IPv6 pseudo-header.
  2373. //
  2374. AdvertICMP->Checksum = ChecksumPacket(
  2375. AdvertPacket, Offset + sizeof *AdvertIP, NULL, PayloadLength,
  2376. AlignAddr(&AdvertIP->Source), AlignAddr(&AdvertIP->Dest),
  2377. IP_PROTOCOL_ICMPv6);
  2378. ASSERT(AdvertICMP->Checksum != 0);
  2379. ICMPv6OutStats.icmps_typecount[ICMPv6_NEIGHBOR_ADVERT]++;
  2380. if (TargetType == ADE_ANYCAST) {
  2381. LARGE_INTEGER Delay;
  2382. //
  2383. // Delay randomly before sending the Neighbor Advertisement.
  2384. //
  2385. Delay.QuadPart = - (LONGLONG)
  2386. RandomNumber(0, MAX_ANYCAST_DELAY_TIME * 10000000);
  2387. Status = IPv6SendLater(Delay,
  2388. IF, AdvertPacket, Offset, DestLinkAddress);
  2389. if (Status != NDIS_STATUS_SUCCESS)
  2390. IPv6SendComplete(NULL, AdvertPacket, IP_NO_RESOURCES);
  2391. }
  2392. else {
  2393. //
  2394. // Transmit the Neighbor Advertisement immediately.
  2395. //
  2396. IPv6SendLL(IF, AdvertPacket, Offset, DestLinkAddress);
  2397. }
  2398. Return:
  2399. if (IsNTE(TargetNTEorIF))
  2400. ReleaseNTE(CastToNTE(TargetNTEorIF));
  2401. else
  2402. ReleaseIF(CastToIF(TargetNTEorIF));
  2403. }
  2404. //* NeighborAdvertReceive - Handle Neighbor Advertisement messages.
  2405. //
  2406. // Validate message and update neighbor cache if necessary.
  2407. //
  2408. void
  2409. NeighborAdvertReceive(
  2410. IPv6Packet *Packet, // Packet handed to us by ICMPv6Receive.
  2411. ICMPv6Header UNALIGNED *ICMP) // ICMP header.
  2412. {
  2413. Interface *IF = Packet->NTEorIF->IF;
  2414. ulong Flags;
  2415. const IPv6Addr *TargetAddress;
  2416. const void *TargetLinkAddress;
  2417. NetTableEntryOrInterface *TargetNTEorIF;
  2418. ushort TargetType;
  2419. //
  2420. // Validate the advertisement.
  2421. // By the time we get here, any IPv6 Authentication Header will have
  2422. // already been checked, as will have the ICMPv6 checksum. Still need
  2423. // to check the IP Hop Limit, and the ICMP code and length.
  2424. //
  2425. if ((Packet->IP->HopLimit != 255) ||
  2426. (Packet->Flags & PACKET_TUNNELED)) {
  2427. //
  2428. // Packet was forwarded by a router, therefore it cannot be
  2429. // from a legitimate neighbor. Drop the packet.
  2430. //
  2431. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2432. "NeighborAdvertReceive: "
  2433. "Received a routed neighbor advertisement\n"));
  2434. return;
  2435. }
  2436. if (ICMP->Code != 0) {
  2437. //
  2438. // Bogus/corrupted neighbor advertisement message. Drop the packet.
  2439. //
  2440. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2441. "NeighborAdvertReceive: "
  2442. "Received a corrupted neighbor advertisement\n"));
  2443. return;
  2444. }
  2445. //
  2446. // Next we have a 4 byte field, then an IPv6 address.
  2447. //
  2448. if (! PacketPullup(Packet, 4 + sizeof(IPv6Addr),
  2449. __builtin_alignof(IPv6Addr), 0)) {
  2450. if (Packet->TotalSize < 4 + sizeof(IPv6Addr)) {
  2451. //
  2452. // Packet too short to contain minimal advertisement.
  2453. //
  2454. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2455. "NeighborAdvertReceive: "
  2456. "Received a too short advertisement\n"));
  2457. }
  2458. return;
  2459. }
  2460. //
  2461. // Next 4 bytes contains 3 bits of flags and 29 bits of "Reserved".
  2462. // Pull this out as a 32 bit long, we're required to ignore the "Reserved"
  2463. // bits. Get a pointer to the target address which follows, then skip
  2464. // over that.
  2465. //
  2466. Flags = net_long(*(ulong UNALIGNED *)Packet->Data);
  2467. TargetAddress = AlignAddr((IPv6Addr UNALIGNED *)
  2468. ((ulong *)Packet->Data + 1));
  2469. AdjustPacketParams(Packet, sizeof(ulong) + sizeof(IPv6Addr));
  2470. //
  2471. // Check that the target address is not a multicast address.
  2472. //
  2473. if (IsMulticast(TargetAddress)) {
  2474. //
  2475. // Nodes are not supposed to send neighbor advertisements for
  2476. // multicast addresses. We're required to drop any such advertisements
  2477. // we receive.
  2478. //
  2479. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2480. "NeighborAdvertReceive: "
  2481. "Received advertisement for a multicast address\n"));
  2482. return;
  2483. }
  2484. //
  2485. // Check that Solicited flag is zero
  2486. // if the destination address is multicast.
  2487. //
  2488. if ((Flags & ND_NA_FLAG_SOLICITED) &&
  2489. IsMulticast(AlignAddr(&Packet->IP->Dest))) {
  2490. //
  2491. // We're required to drop the advertisement.
  2492. //
  2493. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2494. "NeighborAdvertReceive: "
  2495. "Received solicited advertisement to a multicast address\n"));
  2496. return;
  2497. }
  2498. //
  2499. // The code below assumes a contiguous buffer for all the options
  2500. // (the remainder of the packet). If that isn't currently the
  2501. // case, do a pullup for the whole thing.
  2502. //
  2503. if (! PacketPullup(Packet, Packet->TotalSize, 1, 0)) {
  2504. // Can only fail if we run out of memory.
  2505. return;
  2506. }
  2507. ASSERT(Packet->ContigSize == Packet->TotalSize);
  2508. //
  2509. // Look for a target link-layer address option.
  2510. //
  2511. TargetLinkAddress = NULL;
  2512. while (Packet->ContigSize) {
  2513. uint OptionLength;
  2514. //
  2515. // Validate the option length.
  2516. //
  2517. if ((Packet->ContigSize < 8) ||
  2518. ((OptionLength = *((uchar *)Packet->Data + 1) << 3) == 0) ||
  2519. (OptionLength > Packet->ContigSize)) {
  2520. //
  2521. // Invalid option length. We MUST silently drop the packet.
  2522. //
  2523. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2524. "NeighborAdvertReceive: "
  2525. "Received option with bogus length\n"));
  2526. return;
  2527. }
  2528. if (*((uchar *)Packet->Data) == ND_OPTION_TARGET_LINK_LAYER_ADDRESS) {
  2529. //
  2530. // Some interfaces do not use SLLA and TLLA options.
  2531. // For example, see RFC 2893 section 3.8.
  2532. //
  2533. if (IF->ReadLLOpt != NULL) {
  2534. //
  2535. // Parse the link-layer address option.
  2536. //
  2537. TargetLinkAddress = (*IF->ReadLLOpt)(IF->LinkContext,
  2538. (uchar *)Packet->Data);
  2539. if (TargetLinkAddress == NULL) {
  2540. //
  2541. // Invalid option format. Drop the packet.
  2542. //
  2543. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2544. "NeighborAdvertReceive: "
  2545. "Received bogus ll option\n"));
  2546. return;
  2547. }
  2548. //
  2549. // Note that if there are multiple options for some bogus
  2550. // reason, we use the last one. We sanity-check all the
  2551. // options.
  2552. //
  2553. }
  2554. }
  2555. //
  2556. // Move forward to next option.
  2557. //
  2558. AdjustPacketParams(Packet, OptionLength);
  2559. }
  2560. //
  2561. // We've received and parsed a valid neighbor advertisement.
  2562. //
  2563. // First, we check our Duplicate Address Detection state.
  2564. // (See RFC 2461 section 5.4.4.)
  2565. //
  2566. TargetNTEorIF = FindAddressOnInterface(IF, TargetAddress, &TargetType);
  2567. if (TargetNTEorIF == NULL) {
  2568. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  2569. "NeighborAdvertReceive: disabled IF\n"));
  2570. return;
  2571. }
  2572. if (IsNTE(TargetNTEorIF)) {
  2573. NetTableEntry *TargetNTE = CastToNTE(TargetNTEorIF);
  2574. if (TargetType == ADE_UNICAST) {
  2575. ASSERT(IP6_ADDR_EQUAL(TargetAddress, &TargetNTE->Address));
  2576. //
  2577. // Someone out there appears to be using our address;
  2578. // they responded to our DAD solicit.
  2579. //
  2580. // The RFC says to declare a duplicate only if our address is
  2581. // tentative, whereas we also make our address duplicate whenever
  2582. // the override bit in the advertisement is set. This is because
  2583. // we redo DAD for existing addresses upon reconnection.
  2584. //
  2585. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  2586. "NeighborAdvertReceive: DAD found duplicate\n"));
  2587. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  2588. if (IsTentativeNTE(TargetNTE) || (Flags & ND_NA_FLAG_OVERRIDE))
  2589. AddrConfDuplicate(IF, TargetNTE);
  2590. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  2591. //
  2592. // We continue with normal processing.
  2593. // For example, we may have an invalid NTE for the address
  2594. // and we are trying to communicate with the address,
  2595. // which is currently assigned to another node.
  2596. //
  2597. }
  2598. ReleaseNTE(TargetNTE);
  2599. }
  2600. else {
  2601. Interface *TargetIF = CastToIF(TargetNTEorIF);
  2602. ASSERT(TargetType != ADE_UNICAST);
  2603. ASSERT(TargetIF == IF);
  2604. ReleaseIF(TargetIF);
  2605. }
  2606. //
  2607. // If this is a point-to-point interface,
  2608. // then we know the target link-layer address.
  2609. //
  2610. if ((TargetLinkAddress == NULL) &&
  2611. (IF->Flags & IF_FLAG_P2P)) {
  2612. //
  2613. // Use the link-layer address of the other endpoint,
  2614. // which follows our link-layer address in memory.
  2615. //
  2616. TargetLinkAddress = IF->LinkAddress + IF->LinkAddressLength;
  2617. }
  2618. //
  2619. // Process the advertisement.
  2620. //
  2621. NeighborCacheAdvert(IF, TargetAddress, TargetLinkAddress, Flags);
  2622. }
  2623. //* RedirectReceive - Handle Redirect messages.
  2624. //
  2625. // See RFC 1970, sections 8.1 and 8.3.
  2626. //
  2627. void
  2628. RedirectReceive(
  2629. IPv6Packet *Packet, // Packet handed to us by ICMPv6Receive.
  2630. ICMPv6Header UNALIGNED *ICMP) // ICMP header.
  2631. {
  2632. Interface *IF = Packet->NTEorIF->IF;
  2633. const IPv6Addr *TargetAddress;
  2634. const void *TargetLinkAddress;
  2635. const IPv6Addr *DestinationAddress;
  2636. NeighborCacheEntry *TargetNCE;
  2637. IP_STATUS Status;
  2638. //
  2639. // Ignore the redirect if this is a forwarding interface.
  2640. //
  2641. if (IF->Flags & IF_FLAG_FORWARDS)
  2642. return;
  2643. //
  2644. // Validate the redirect.
  2645. // By the time we get here, any IPv6 Authentication Header will have
  2646. // already been checked, as will have the ICMPv6 checksum. Still need
  2647. // to check the IP Hop Limit, and the ICMP code and length.
  2648. //
  2649. if ((Packet->IP->HopLimit != 255) ||
  2650. (Packet->Flags & PACKET_TUNNELED)) {
  2651. //
  2652. // Packet was forwarded by a router, therefore it cannot be
  2653. // from a legitimate neighbor. Drop the packet.
  2654. //
  2655. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2656. "RedirectReceive: Received a routed redirect\n"));
  2657. return;
  2658. }
  2659. if (ICMP->Code != 0) {
  2660. //
  2661. // Bogus/corrupted redirect message. Drop the packet.
  2662. //
  2663. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2664. "RedirectReceive: Received a corrupted redirect\n"));
  2665. return;
  2666. }
  2667. //
  2668. // Check that the source address is a link-local address.
  2669. // We need a link-local source address to identify the router
  2670. // that sent the redirect.
  2671. //
  2672. if (!IsLinkLocal(AlignAddr(&Packet->IP->Source))) {
  2673. //
  2674. // Drop the packet.
  2675. //
  2676. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2677. "RedirectReceive: "
  2678. "Received redirect from non-link-local source\n"));
  2679. return;
  2680. }
  2681. //
  2682. // Next we have a 4 byte reserved field, then two IPv6 addresses.
  2683. //
  2684. if (! PacketPullup(Packet, 4 + 2 * sizeof(IPv6Addr),
  2685. __builtin_alignof(IPv6Addr), 0)) {
  2686. if (Packet->TotalSize < 4 + 2 * sizeof(IPv6Addr)) {
  2687. //
  2688. // Packet too short to contain minimal redirect.
  2689. //
  2690. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2691. "RedirectReceive: Received a too short redirect\n"));
  2692. }
  2693. return;
  2694. }
  2695. //
  2696. // Skip over the 4 byte reserved field.
  2697. // Pick up the Target and Destination addresses.
  2698. //
  2699. AdjustPacketParams(Packet, 4);
  2700. TargetAddress = AlignAddr((IPv6Addr UNALIGNED *)Packet->Data);
  2701. DestinationAddress = TargetAddress + 1;
  2702. AdjustPacketParams(Packet, 2 * sizeof(IPv6Addr));
  2703. //
  2704. // Check that the destination address is not a multicast address.
  2705. //
  2706. if (IsMulticast(DestinationAddress)) {
  2707. //
  2708. // Drop the packet.
  2709. //
  2710. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2711. "RedirectReceive: "
  2712. "Received redirect for multicast address\n"));
  2713. return;
  2714. }
  2715. //
  2716. // Check that either the target address is link-local
  2717. // (redirecting to a router) or the target and the destination
  2718. // are the same (redirecting to an on-link destination).
  2719. //
  2720. if (!IsLinkLocal(TargetAddress) &&
  2721. !IP6_ADDR_EQUAL(TargetAddress, DestinationAddress)) {
  2722. //
  2723. // Drop the packet.
  2724. //
  2725. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2726. "RedirectReceive: "
  2727. "Received redirect with non-link-local target\n"));
  2728. return;
  2729. }
  2730. //
  2731. // The code below assumes a contiguous buffer for all the options
  2732. // (the remainder of the packet). If that isn't currently the
  2733. // case, do a pullup for the whole thing.
  2734. //
  2735. if (! PacketPullup(Packet, Packet->TotalSize, 1, 0)) {
  2736. // Can only fail if we run out of memory.
  2737. return;
  2738. }
  2739. ASSERT(Packet->ContigSize == Packet->TotalSize);
  2740. //
  2741. // Look for a target link-layer address option,
  2742. // checking that all included options have a valid length.
  2743. //
  2744. TargetLinkAddress = NULL;
  2745. while (Packet->ContigSize) {
  2746. uint OptionLength = 0;
  2747. //
  2748. // Validate the option length.
  2749. //
  2750. if ((Packet->ContigSize < 8) ||
  2751. ((OptionLength = *((uchar *)Packet->Data + 1) << 3) == 0) ||
  2752. (OptionLength > Packet->ContigSize)) {
  2753. //
  2754. // Invalid option length. We MUST silently drop the packet.
  2755. //
  2756. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2757. "RedirectReceive: Received option with length %u "
  2758. "while we only have %u data\n", OptionLength,
  2759. Packet->ContigSize));
  2760. return;
  2761. }
  2762. if (*(uchar *)Packet->Data == ND_OPTION_TARGET_LINK_LAYER_ADDRESS) {
  2763. //
  2764. // Some interfaces do not use SLLA and TLLA options.
  2765. // For example, see RFC 2893 section 3.8.
  2766. //
  2767. if (IF->ReadLLOpt != NULL) {
  2768. //
  2769. // Parse the link-layer address option.
  2770. //
  2771. TargetLinkAddress = (*IF->ReadLLOpt)(IF->LinkContext,
  2772. (uchar *)Packet->Data);
  2773. if (TargetLinkAddress == NULL) {
  2774. //
  2775. // Invalid option format. Drop the packet.
  2776. //
  2777. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  2778. "RedirectReceive: Received bogus ll option\n"));
  2779. return;
  2780. }
  2781. //
  2782. // Note that if there are multiple options for some bogus
  2783. // reason, we use the last one. We must sanity-check all
  2784. // option lengths.
  2785. //
  2786. }
  2787. }
  2788. //
  2789. // Move forward to next option.
  2790. //
  2791. AdjustPacketParams(Packet, OptionLength);
  2792. }
  2793. //
  2794. // We have a valid redirect message (except for checking that the
  2795. // source of the redirect is the current first-hop neighbor
  2796. // for the destination - RedirectRouteCache does that).
  2797. //
  2798. // First we get an NCE for the target of the redirect. Then we
  2799. // update the route cache. If RedirectRouteCache doesn't invalidate
  2800. // the redirect, then we update the neighbor cache.
  2801. //
  2802. //
  2803. // Get the Neighbor Cache Entry for the target.
  2804. //
  2805. TargetNCE = FindOrCreateNeighbor(IF, TargetAddress);
  2806. if (TargetNCE == NULL) {
  2807. //
  2808. // Couldn't find or create NCE. Drop the packet.
  2809. //
  2810. return;
  2811. }
  2812. //
  2813. // Update the route cache to reflect this redirect.
  2814. //
  2815. Status = RedirectRouteCache(AlignAddr(&Packet->IP->Source),
  2816. DestinationAddress,
  2817. IF, TargetNCE);
  2818. if (Status == IP_SUCCESS) {
  2819. //
  2820. // Update the Neighbor Cache Entry for the target.
  2821. // We know the target is a router if the target address
  2822. // is not the same as the destination address.
  2823. //
  2824. NeighborCacheUpdate(TargetNCE, TargetLinkAddress,
  2825. !IP6_ADDR_EQUAL(TargetAddress,
  2826. DestinationAddress));
  2827. }
  2828. ReleaseNCE(TargetNCE);
  2829. }
  2830. //* RouterSolicitSend
  2831. //
  2832. // Sends a Router Solicitation.
  2833. // The solicit is always sent to the all-routers multicast address.
  2834. // Chooses a valid source address for the interface.
  2835. //
  2836. // Called with no locks held.
  2837. //
  2838. void
  2839. RouterSolicitSend(Interface *IF)
  2840. {
  2841. NDIS_STATUS Status;
  2842. NDIS_PACKET *Packet;
  2843. int PayloadLength;
  2844. uint Offset;
  2845. void *Mem;
  2846. uint MemLen;
  2847. IPv6Header UNALIGNED *IP;
  2848. ICMPv6Header UNALIGNED *ICMP;
  2849. void *SourceOption;
  2850. void *LLDest;
  2851. IPv6Addr Source;
  2852. //
  2853. // Calculate the link-level destination address.
  2854. // (The IPv6 destination is a multicast address.)
  2855. // This can potentially fail, such as with ISATAP when
  2856. // no router is known.
  2857. //
  2858. LLDest = alloca(IF->LinkAddressLength);
  2859. if ((*IF->ConvertAddr)(IF->LinkContext, &AllRoutersOnLinkAddr, LLDest) ==
  2860. ND_STATE_INCOMPLETE) {
  2861. //
  2862. // Don't count this as an attempt or a failure. Just pretend
  2863. // that router discovery is disabled. This way, if you aren't
  2864. // using ISATAP, you don't see a high ICMP error count.
  2865. //
  2866. return;
  2867. }
  2868. ICMPv6OutStats.icmps_msgs++;
  2869. //
  2870. // Allocate a packet for solicitation.
  2871. // In addition to the 8 bytes for the solicit proper, leave space
  2872. // for source link-layer address option (round option length up to
  2873. // 8-byte multiple) IF we have a valid source address and ND is
  2874. // enabled. If ND is disabled, the router can presumably
  2875. // derive our link-layer address itself.
  2876. //
  2877. PayloadLength = 8;
  2878. if (GetLinkLocalAddress(IF, &Source) && (IF->WriteLLOpt != NULL)) {
  2879. PayloadLength += (IF->LinkAddressLength + 2 + 7) &~ 7;
  2880. }
  2881. Offset = IF->LinkHeaderSize;
  2882. MemLen = Offset + sizeof(IPv6Header) + PayloadLength;
  2883. Status = IPv6AllocatePacket(MemLen, &Packet, &Mem);
  2884. if (Status != NDIS_STATUS_SUCCESS) {
  2885. ICMPv6OutStats.icmps_errors++;
  2886. return;
  2887. }
  2888. //
  2889. // Prepare IP header of solicitation.
  2890. //
  2891. IP = (IPv6Header UNALIGNED *)((uchar *)Mem + Offset);
  2892. IP->VersClassFlow = IP_VERSION;
  2893. IP->PayloadLength = net_short((ushort)PayloadLength);
  2894. IP->NextHeader = IP_PROTOCOL_ICMPv6;
  2895. IP->HopLimit = 255;
  2896. IP->Source = Source;
  2897. IP->Dest = AllRoutersOnLinkAddr;
  2898. //
  2899. // Prepare ICMP header.
  2900. //
  2901. ICMP = (ICMPv6Header UNALIGNED *)(IP + 1);
  2902. ICMP->Type = ICMPv6_ROUTER_SOLICIT;
  2903. ICMP->Code = 0;
  2904. ICMP->Checksum = 0;
  2905. //
  2906. // Must zero the reserved field.
  2907. //
  2908. *(ulong UNALIGNED *)(ICMP + 1) = 0;
  2909. if (PayloadLength != 8) {
  2910. //
  2911. // Include source link-layer address option.
  2912. //
  2913. SourceOption = (void *)((ulong *)(ICMP + 1) + 1);
  2914. ((uchar *)SourceOption)[0] = ND_OPTION_SOURCE_LINK_LAYER_ADDRESS;
  2915. ((uchar *)SourceOption)[1] = (uchar)((IF->LinkAddressLength + 2 + 7) >> 3);
  2916. (*IF->WriteLLOpt)(IF->LinkContext, SourceOption, IF->LinkAddress);
  2917. }
  2918. //
  2919. // Calculate the ICMPv6 checksum. It covers the entire ICMPv6 message
  2920. // starting with the ICMPv6 header, plus the IPv6 pseudo-header.
  2921. //
  2922. ICMP->Checksum = ChecksumPacket(
  2923. Packet, Offset + sizeof *IP, NULL, PayloadLength,
  2924. AlignAddr(&IP->Source), AlignAddr(&IP->Dest),
  2925. IP_PROTOCOL_ICMPv6);
  2926. ASSERT(ICMP->Checksum != 0);
  2927. //
  2928. // We prevent loopback of all ND packets.
  2929. //
  2930. PC(Packet)->Flags = NDIS_FLAGS_MULTICAST_PACKET | NDIS_FLAGS_DONT_LOOPBACK;
  2931. //
  2932. // Transmit the packet.
  2933. //
  2934. ICMPv6OutStats.icmps_typecount[ICMPv6_ROUTER_SOLICIT]++;
  2935. IPv6SendLL(IF, Packet, Offset, LLDest);
  2936. }
  2937. //* RouterSolicitTimeout
  2938. //
  2939. // Called periodically from IPv6Timeout to handle timeouts
  2940. // for sending router solicitations for an interface.
  2941. //
  2942. // Callable from DPC context, not from thread context.
  2943. //
  2944. void
  2945. RouterSolicitTimeout(Interface *IF)
  2946. {
  2947. int SendRouterSolicit = FALSE;
  2948. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  2949. if (IF->RSTimer != 0) {
  2950. ASSERT(!IsDisabledIF(IF));
  2951. //
  2952. // Timer is running. Decrement and check for expiration.
  2953. //
  2954. if (--IF->RSTimer == 0) {
  2955. if (IF->RSCount < MAX_RTR_SOLICITATIONS) {
  2956. //
  2957. // Re-arm the timer and generate a router solicitation.
  2958. //
  2959. IF->RSTimer = RTR_SOLICITATION_INTERVAL;
  2960. IF->RSCount++;
  2961. SendRouterSolicit = TRUE;
  2962. }
  2963. else {
  2964. //
  2965. // If we are still in the reconnecting state,
  2966. // meaning we have not received an RA
  2967. // since reconnecting to the link,
  2968. // remove stale auto-configured state.
  2969. //
  2970. if (IF->Flags & IF_FLAG_MEDIA_RECONNECTED) {
  2971. IF->Flags &= ~IF_FLAG_MEDIA_RECONNECTED;
  2972. //
  2973. // Remove auto-configured addresses.
  2974. //
  2975. AddrConfResetAutoConfig(IF, 0);
  2976. //
  2977. // Similarly, remove auto-configured routes.
  2978. //
  2979. RouteTableResetAutoConfig(IF, 0);
  2980. //
  2981. // Restore interface parameters.
  2982. //
  2983. InterfaceResetAutoConfig(IF);
  2984. }
  2985. //
  2986. // On a non-multicast capable interface, we'll
  2987. // never get multicast RA's so change to infrequent
  2988. // RS polling.
  2989. //
  2990. if (!(IF->Flags & IF_FLAG_MULTICAST)) {
  2991. IF->RSTimer = SLOW_RTR_SOLICITATION_INTERVAL;
  2992. IF->RSCount++;
  2993. SendRouterSolicit = TRUE;
  2994. }
  2995. }
  2996. }
  2997. }
  2998. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  2999. if (SendRouterSolicit)
  3000. RouterSolicitSend(IF);
  3001. }
  3002. //* NeighborSolicitSend0
  3003. //
  3004. // Low-level version of NeighborSolicitSend -
  3005. // uses explicit source/destination/target addresses
  3006. // instead of an NCE.
  3007. //
  3008. void
  3009. NeighborSolicitSend0(
  3010. Interface *IF, // Interface for the solicit
  3011. void *LLDest, // Link-level destination
  3012. const IPv6Addr *Source, // IP-level source
  3013. const IPv6Addr *Dest, // IP-level destination
  3014. const IPv6Addr *Target) // IP-level target of the solicit
  3015. {
  3016. NDIS_STATUS Status;
  3017. NDIS_PACKET *Packet;
  3018. int PayloadLength;
  3019. uint Offset;
  3020. void *Mem;
  3021. uint MemLen;
  3022. IPv6Header UNALIGNED *IP;
  3023. ICMPv6Header UNALIGNED *ICMP;
  3024. IPv6Addr *TargetAddress;
  3025. void *SourceOption;
  3026. ICMPv6OutStats.icmps_msgs++;
  3027. //
  3028. // Allocate a packet for solicitation.
  3029. // In addition to the 24 bytes for the solicit proper, leave space
  3030. // for source link-layer address option (round option length up to
  3031. // 8-byte multiple) IF we have a valid source address.
  3032. //
  3033. PayloadLength = 24;
  3034. if (!IsUnspecified(Source) && (IF->WriteLLOpt != NULL))
  3035. PayloadLength += (IF->LinkAddressLength + 2 + 7) &~ 7;
  3036. Offset = IF->LinkHeaderSize;
  3037. MemLen = Offset + sizeof(IPv6Header) + PayloadLength;
  3038. Status = IPv6AllocatePacket(MemLen, &Packet, &Mem);
  3039. if (Status != NDIS_STATUS_SUCCESS) {
  3040. ICMPv6OutStats.icmps_errors++;
  3041. return;
  3042. }
  3043. //
  3044. // Prepare IP header of solicitation.
  3045. //
  3046. IP = (IPv6Header UNALIGNED *)((uchar *)Mem + Offset);
  3047. IP->VersClassFlow = IP_VERSION;
  3048. IP->PayloadLength = net_short((ushort)PayloadLength);
  3049. IP->NextHeader = IP_PROTOCOL_ICMPv6;
  3050. IP->HopLimit = 255;
  3051. IP->Source = *Source;
  3052. IP->Dest = *Dest;
  3053. //
  3054. // Prepare ICMP header.
  3055. //
  3056. ICMP = (ICMPv6Header UNALIGNED *)(IP + 1);
  3057. ICMP->Type = ICMPv6_NEIGHBOR_SOLICIT;
  3058. ICMP->Code = 0;
  3059. ICMP->Checksum = 0;
  3060. //
  3061. // Must zero the reserved field.
  3062. //
  3063. *(ulong UNALIGNED *)(ICMP + 1) = 0;
  3064. //
  3065. // Initialize the target address.
  3066. //
  3067. TargetAddress = (IPv6Addr *)((ulong *)(ICMP + 1) + 1);
  3068. *TargetAddress = *Target;
  3069. if (PayloadLength != 24) {
  3070. //
  3071. // Include source link-layer address option.
  3072. //
  3073. SourceOption = (void *)(TargetAddress + 1);
  3074. ((uchar *)SourceOption)[0] = ND_OPTION_SOURCE_LINK_LAYER_ADDRESS;
  3075. ((uchar *)SourceOption)[1] = (uchar)((IF->LinkAddressLength + 2 + 7) >> 3);
  3076. (*IF->WriteLLOpt)(IF->LinkContext, SourceOption, IF->LinkAddress);
  3077. }
  3078. //
  3079. // Calculate the ICMPv6 checksum. It covers the entire ICMPv6 message
  3080. // starting with the ICMPv6 header, plus the IPv6 pseudo-header.
  3081. //
  3082. ICMP->Checksum = ChecksumPacket(
  3083. Packet, Offset + sizeof *IP, NULL, PayloadLength,
  3084. AlignAddr(&IP->Source), AlignAddr(&IP->Dest),
  3085. IP_PROTOCOL_ICMPv6);
  3086. ASSERT(ICMP->Checksum != 0);
  3087. //
  3088. // Is this a multicast packet?
  3089. // But we inhibit loopback of unicast packets too -
  3090. // this prevents rare races in which we receive
  3091. // our own ND packets.
  3092. //
  3093. PC(Packet)->Flags = NDIS_FLAGS_DONT_LOOPBACK;
  3094. if (IsMulticast(Dest))
  3095. PC(Packet)->Flags |= NDIS_FLAGS_MULTICAST_PACKET;
  3096. //
  3097. // Transmit the packet.
  3098. //
  3099. ICMPv6OutStats.icmps_typecount[ICMPv6_NEIGHBOR_SOLICIT]++;
  3100. IPv6SendLL(IF, Packet, Offset, LLDest);
  3101. }
  3102. //* NeighborSolicitSend - Send a Neighbor Solicitation message.
  3103. //
  3104. // Chooses source/destination/target addresses depending
  3105. // on the NCE state and sends the solicit packet.
  3106. //
  3107. // Called with NO locks held.
  3108. // Callable from thread or DPC context.
  3109. //
  3110. void
  3111. NeighborSolicitSend(
  3112. NeighborCacheEntry *NCE, // Neighbor to solicit.
  3113. const IPv6Addr *Source) // Source address to send from (optional).
  3114. {
  3115. Interface *IF = NCE->IF;
  3116. IPv6Addr Dest;
  3117. void *LLDest;
  3118. IPv6Addr LinkLocal;
  3119. //
  3120. // Check Neighbor Discovery protocol state of our neighbor in order to
  3121. // determine whether we should multicast or unicast our solicitation.
  3122. //
  3123. // Note that we do not take the neighbor cache lock to make this check.
  3124. // The worst that can happen is that we'll think the NDState is not
  3125. // incomplete and then use a bogus/changing LinkAddress.
  3126. // This is rare enough and benign enough to be OK.
  3127. // Similar reasoning in IPv6SendND.
  3128. //
  3129. if (NCE->NDState == ND_STATE_INCOMPLETE) {
  3130. //
  3131. // This is our initial solicitation to this neighbor, so we don't
  3132. // have a link-layer address cached. Multicast our solicitation
  3133. // to the solicited-node multicast address corresponding to our
  3134. // neighbor's address.
  3135. //
  3136. CreateSolicitedNodeMulticastAddress(&NCE->NeighborAddress, &Dest);
  3137. LLDest = alloca(IF->LinkAddressLength);
  3138. (*IF->ConvertAddr)(IF->LinkContext, &Dest, LLDest);
  3139. } else {
  3140. //
  3141. // We have a cached link-layer address that has gone stale.
  3142. // Probe this address via a unicast solicitation.
  3143. //
  3144. Dest = NCE->NeighborAddress;
  3145. LLDest = NCE->LinkAddress;
  3146. }
  3147. //
  3148. // If we were given a specific source address to use then do so (normal
  3149. // case for our initial multicasted solicit), otherwise use the outgoing
  3150. // interface's link-local address. If there is no valid link-local
  3151. // address, then we give up.
  3152. //
  3153. if (Source == NULL) {
  3154. if (!GetLinkLocalAddress(IF, &LinkLocal)) {
  3155. return;
  3156. }
  3157. Source = &LinkLocal;
  3158. }
  3159. //
  3160. // Now that we've determined the source/destination/target addresses,
  3161. // we can actually send the solicit.
  3162. //
  3163. NeighborSolicitSend0(IF, LLDest, Source, &Dest, &NCE->NeighborAddress);
  3164. }
  3165. //* DADSolicitSend - Sends a DAD Neighbor Solicit.
  3166. //
  3167. // Like NeighborSolicitSend, but specialized for DAD.
  3168. //
  3169. void
  3170. DADSolicitSend(NetTableEntry *NTE)
  3171. {
  3172. Interface *IF = NTE->IF;
  3173. IPv6Addr Dest;
  3174. void *LLDest;
  3175. //
  3176. // Multicast our solicitation to the solicited-node multicast
  3177. // address corresponding to our own address.
  3178. //
  3179. CreateSolicitedNodeMulticastAddress(&NTE->Address, &Dest);
  3180. //
  3181. // Convert the IP-level multicast destination address
  3182. // to a link-level multicast address.
  3183. //
  3184. LLDest = alloca(IF->LinkAddressLength);
  3185. (*IF->ConvertAddr)(IF->LinkContext, &Dest, LLDest);
  3186. //
  3187. // Now that we've created the destination addresses,
  3188. // we can actually send the solicit.
  3189. //
  3190. NeighborSolicitSend0(IF, LLDest, &UnspecifiedAddr,
  3191. &Dest, &NTE->Address);
  3192. }
  3193. //* DADTimeout - handle a Duplicate Address Detection timeout.
  3194. //
  3195. // Called from IPv6Timeout to handle DAD timeouts on an NTE.
  3196. //
  3197. void
  3198. DADTimeout(NetTableEntry *NTE)
  3199. {
  3200. Interface *IF = NTE->IF;
  3201. int SendDADSolicit = FALSE;
  3202. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  3203. if (NTE->DADTimer != 0) {
  3204. ASSERT(NTE->DADState != DAD_STATE_INVALID);
  3205. //
  3206. // Timer is running. Decrement and check for expiration.
  3207. //
  3208. if (--NTE->DADTimer == 0) {
  3209. //
  3210. // Timer went off.
  3211. //
  3212. if (NTE->DADCount == 0) {
  3213. //
  3214. // The address has passed Duplicate Address Detection.
  3215. // Because we have passed DAD, reset the failure count.
  3216. //
  3217. IF->DupAddrDetects = 0;
  3218. AddrConfNotDuplicate(IF, NTE);
  3219. }
  3220. else {
  3221. //
  3222. // Time to send another solicit.
  3223. //
  3224. NTE->DADCount--;
  3225. NTE->DADTimer = (ushort)IF->RetransTimer;
  3226. SendDADSolicit = TRUE;
  3227. }
  3228. }
  3229. }
  3230. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  3231. if (SendDADSolicit)
  3232. DADSolicitSend(NTE);
  3233. }
  3234. //* CalcReachableTime
  3235. //
  3236. // Calculate a pseudo-random ReachableTime from BaseReachableTime
  3237. // (this prevents synchronization of Neighbor Unreachability Detection
  3238. // messages from different hosts), and convert it to units of IPv6
  3239. // timer ticks (cheaper to do once here than at every packet send).
  3240. //
  3241. uint // IPv6 timer ticks
  3242. CalcReachableTime(
  3243. uint BaseReachableTime) // Learned from Router Advertisements (in ms).
  3244. {
  3245. uint Factor;
  3246. uint ReachableTime;
  3247. //
  3248. // Calculate a uniformly-distributed random value between
  3249. // MIN_RANDOM_FACTOR and MAX_RANDOM_FACTOR of the BaseReachableTime.
  3250. // To keep the arithmetic integer, *_RANDOM_FACTOR (and thus the
  3251. // 'Factor' variable) are defined as percentage values.
  3252. //
  3253. Factor = RandomNumber(MIN_RANDOM_FACTOR, MAX_RANDOM_FACTOR);
  3254. //
  3255. // Now that we have a random value picked out of our percentage spread,
  3256. // take that percentage of the BaseReachableTime.
  3257. //
  3258. // BaseReachableTime has a maximum value of 3,600,000 milliseconds
  3259. // (see RFC 1970, section 6.2.1), so Factor would have to exeed 1100 %
  3260. // in order to overflow a 32-bit unsigned integer.
  3261. //
  3262. ReachableTime = (BaseReachableTime * Factor) / 100;
  3263. //
  3264. // Convert from milliseconds (which is what BaseReachableTime is in) to
  3265. // IPv6 timer ticks (which is what we keep ReachableTime in).
  3266. //
  3267. return ConvertMillisToTicks(ReachableTime);
  3268. }
  3269. //* RedirectSend
  3270. //
  3271. // Send a Redirect message to a neighbor,
  3272. // telling it to use a better first-hop neighbor
  3273. // in the future for the specified destination.
  3274. //
  3275. // RecvNTEorIF (optionally) specifies a source address
  3276. // to use in the Redirect message.
  3277. //
  3278. // Packet (optionally) specifies data to include
  3279. // in a Redirected Header option.
  3280. //
  3281. // Called with NO locks held.
  3282. // Callable from thread or DPC context.
  3283. //
  3284. void
  3285. RedirectSend(
  3286. NeighborCacheEntry *NCE, // Neighbor getting the Redirect.
  3287. NeighborCacheEntry *TargetNCE, // Better first-hop to use
  3288. const IPv6Addr *Destination, // for this Destination address.
  3289. NetTableEntryOrInterface *NTEorIF, // Source of the Redirect.
  3290. PNDIS_PACKET FwdPacket, // Packet triggering the redirect.
  3291. uint FwdOffset,
  3292. uint FwdPayloadLength)
  3293. {
  3294. PNDIS_BUFFER FwdBuffer;
  3295. Interface *IF = NCE->IF;
  3296. NDIS_STATUS Status;
  3297. NDIS_PACKET *Packet;
  3298. uint PayloadLength;
  3299. uint TargetOptionLength;
  3300. uint RedirectOptionData;
  3301. uint RedirectOptionLength;
  3302. uint Offset;
  3303. void *Mem;
  3304. uint MemLen;
  3305. IPv6Header UNALIGNED *IP;
  3306. ICMPv6Header UNALIGNED *ICMP;
  3307. void *TargetLinkAddress;
  3308. KIRQL OldIrql;
  3309. const IPv6Addr *Source;
  3310. IPv6Addr LinkLocal;
  3311. int Ok;
  3312. ASSERT((IF == TargetNCE->IF) && (IF == NTEorIF->IF));
  3313. //
  3314. // If our caller specified a source address, use it.
  3315. // Otherwise (common case) we use our link-local address.
  3316. //
  3317. if (IsNTE(NTEorIF)) {
  3318. Source = &CastToNTE(NTEorIF)->Address;
  3319. }
  3320. else {
  3321. //
  3322. // We need a valid link-local address to send a redirect.
  3323. //
  3324. if (! GetLinkLocalAddress(IF, &LinkLocal))
  3325. return;
  3326. Source = &LinkLocal;
  3327. }
  3328. //
  3329. // Do we know the Target neighbor's link address?
  3330. //
  3331. KeAcquireSpinLock(&IF->LockNC, &OldIrql);
  3332. if (TargetNCE->NDState == ND_STATE_INCOMPLETE) {
  3333. TargetLinkAddress = NULL;
  3334. TargetOptionLength = 0;
  3335. }
  3336. else {
  3337. TargetLinkAddress = alloca(IF->LinkAddressLength);
  3338. RtlCopyMemory(TargetLinkAddress, TargetNCE->LinkAddress,
  3339. IF->LinkAddressLength);
  3340. TargetOptionLength = (IF->LinkAddressLength + 2 + 7) &~ 7;
  3341. }
  3342. KeReleaseSpinLock(&IF->LockNC, OldIrql);
  3343. //
  3344. // Calculate the Redirect's payload size,
  3345. // with space for a Target Link-Layer Address option.
  3346. //
  3347. PayloadLength = 40 + TargetOptionLength;
  3348. //
  3349. // Allow space for the Redirected Header option,
  3350. // without exceeding the MTU.
  3351. // Note that RFC 2461 4.6.3 explicitly specifies
  3352. // the IPv6 minimum MTU, not the link MTU.
  3353. // We can always include at least the option header and
  3354. // the IPv6 header from FwdPacket.
  3355. //
  3356. RedirectOptionLength = 8 + sizeof(IPv6Header);
  3357. if (sizeof(IPv6Header) + PayloadLength +
  3358. RedirectOptionLength + FwdPayloadLength > IPv6_MINIMUM_MTU) {
  3359. //
  3360. // Truncate FwdPacket to make it fit.
  3361. //
  3362. RedirectOptionLength = IPv6_MINIMUM_MTU -
  3363. (sizeof(IPv6Header) + PayloadLength);
  3364. RedirectOptionData = RedirectOptionLength - 8;
  3365. }
  3366. else {
  3367. //
  3368. // Include all of FwdPacket, plus possible padding.
  3369. //
  3370. RedirectOptionLength += (FwdPayloadLength + 7) &~ 7;
  3371. RedirectOptionData = sizeof(IPv6Header) + FwdPayloadLength;
  3372. }
  3373. PayloadLength += RedirectOptionLength;
  3374. //
  3375. // Allocate a packet for the Redirect.
  3376. //
  3377. Offset = IF->LinkHeaderSize;
  3378. MemLen = Offset + sizeof(IPv6Header) + PayloadLength;
  3379. Status = IPv6AllocatePacket(MemLen, &Packet, &Mem);
  3380. if (Status != NDIS_STATUS_SUCCESS) {
  3381. return;
  3382. }
  3383. //
  3384. // Prepare IP header of solicitation.
  3385. //
  3386. IP = (IPv6Header UNALIGNED *)((uchar *)Mem + Offset);
  3387. IP->VersClassFlow = IP_VERSION;
  3388. IP->PayloadLength = net_short((ushort)PayloadLength);
  3389. IP->NextHeader = IP_PROTOCOL_ICMPv6;
  3390. IP->HopLimit = 255;
  3391. IP->Dest = NCE->NeighborAddress;
  3392. IP->Source = *Source;
  3393. //
  3394. // Prepare ICMP header.
  3395. //
  3396. ICMP = (ICMPv6Header UNALIGNED *)(IP + 1);
  3397. ICMP->Type = ICMPv6_REDIRECT;
  3398. ICMP->Code = 0;
  3399. ICMP->Checksum = 0;
  3400. Mem = (void *)(ICMP + 1);
  3401. //
  3402. // Must zero the reserved field.
  3403. //
  3404. *(ulong UNALIGNED *)Mem = 0;
  3405. (ulong *)Mem += 1;
  3406. //
  3407. // Initialize the target and destination addresses.
  3408. //
  3409. ((IPv6Addr *)Mem)[0] = TargetNCE->NeighborAddress;
  3410. ((IPv6Addr *)Mem)[1] = *Destination;
  3411. (IPv6Addr *)Mem += 2;
  3412. if ((TargetLinkAddress != NULL) && (IF->WriteLLOpt != NULL)) {
  3413. void *TargetOption = Mem;
  3414. //
  3415. // Include a Target Link-Layer Address option.
  3416. //
  3417. ((uchar *)TargetOption)[0] = ND_OPTION_TARGET_LINK_LAYER_ADDRESS;
  3418. ((uchar *)TargetOption)[1] = TargetOptionLength >> 3;
  3419. (*IF->WriteLLOpt)(IF->LinkContext, TargetOption, TargetLinkAddress);
  3420. (uchar *)Mem += TargetOptionLength;
  3421. }
  3422. //
  3423. // Include a Redirected Header option.
  3424. //
  3425. ((uchar *)Mem)[0] = ND_OPTION_REDIRECTED_HEADER;
  3426. ((uchar *)Mem)[1] = RedirectOptionLength >> 3;
  3427. RtlZeroMemory(&((uchar *)Mem)[2], 6);
  3428. (uchar *)Mem += 8;
  3429. //
  3430. // Include as much of FwdPacket as will fit,
  3431. // zeroing any padding bytes.
  3432. //
  3433. NdisQueryPacket(FwdPacket, NULL, NULL, &FwdBuffer, NULL);
  3434. Ok = CopyNdisToFlat(Mem, FwdBuffer, FwdOffset, RedirectOptionData,
  3435. &FwdBuffer, &FwdOffset);
  3436. ASSERT(Ok);
  3437. (uchar *)Mem += RedirectOptionData;
  3438. RtlZeroMemory(Mem, RedirectOptionLength - (8 + RedirectOptionData));
  3439. //
  3440. // Calculate the ICMPv6 checksum. It covers the entire ICMPv6 message
  3441. // starting with the ICMPv6 header, plus the IPv6 pseudo-header.
  3442. //
  3443. ICMP->Checksum = ChecksumPacket(
  3444. Packet, Offset + sizeof *IP, NULL, PayloadLength,
  3445. AlignAddr(&IP->Source), AlignAddr(&IP->Dest),
  3446. IP_PROTOCOL_ICMPv6);
  3447. ASSERT(ICMP->Checksum != 0);
  3448. //
  3449. // We prevent loopback of all ND packets.
  3450. //
  3451. PC(Packet)->Flags = NDIS_FLAGS_DONT_LOOPBACK;
  3452. //
  3453. // Send the Redirect packet.
  3454. //
  3455. IPv6SendND(Packet, Offset, NCE, Source);
  3456. }
  3457. //* RouterAdvertTimeout
  3458. //
  3459. // Called periodically from IPv6Timeout to handle timeouts
  3460. // for sending router advertisements for an interface.
  3461. // Our caller checks IF->RATimer and only calls us
  3462. // if there is a high probability that we need to send an RA.
  3463. //
  3464. // Callable from DPC context, not from thread context.
  3465. //
  3466. void
  3467. RouterAdvertTimeout(Interface *IF, int Force)
  3468. {
  3469. uint Now;
  3470. int SendRouterAdvert = FALSE;
  3471. NetTableEntry *NTE;
  3472. IPv6Addr Source;
  3473. KeAcquireSpinLockAtDpcLevel(&IF->Lock);
  3474. if (IF->RATimer != 0) {
  3475. ASSERT(!IsDisabledIF(IF));
  3476. ASSERT(IF->Flags & IF_FLAG_ADVERTISES);
  3477. if (Force) {
  3478. //
  3479. // Enter "fast" mode if this is a forced RA.
  3480. //
  3481. IF->RACount = MAX_INITIAL_RTR_ADVERTISEMENTS;
  3482. goto GenerateRA;
  3483. }
  3484. //
  3485. // Timer is running. Decrement and check for expiration.
  3486. //
  3487. if (--IF->RATimer == 0) {
  3488. GenerateRA:
  3489. //
  3490. // Timer went off. Check if rate-limiting
  3491. // prevents us from sending an RA right now.
  3492. //
  3493. Now = IPv6TickCount;
  3494. if ((uint)(Now - IF->RALast) < MIN_DELAY_BETWEEN_RAS) {
  3495. //
  3496. // We can not send an RA quite yet.
  3497. // Re-arm the timer.
  3498. //
  3499. IF->RATimer = MIN_DELAY_BETWEEN_RAS - (uint)(Now - IF->RALast);
  3500. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  3501. "RouterAdvertTimeout(IF %p): "
  3502. "rate limit\n", IF));
  3503. }
  3504. else {
  3505. //
  3506. // Re-arm the timer.
  3507. //
  3508. IF->RATimer = RandomNumber(MinRtrAdvInterval,
  3509. MaxRtrAdvInterval);
  3510. //
  3511. // Do we have an appropriate source address?
  3512. // During boot, the link-local address
  3513. // might still be tentative in which case we delay.
  3514. //
  3515. NTE = GetLinkLocalNTE(IF);
  3516. if (NTE == NULL) {
  3517. NTE = IF->LinkLocalNTE;
  3518. if ((NTE != NULL) && IsTentativeNTE(NTE)) {
  3519. //
  3520. // Try again when DAD finishes.
  3521. //
  3522. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  3523. "RouterAdvertTimeout(IF %p): "
  3524. "wait for source\n", IF));
  3525. IF->RATimer = ((IF->RetransTimer * NTE->DADCount) +
  3526. NTE->DADTimer);
  3527. }
  3528. else {
  3529. //
  3530. // Skip this opportunity to send an RA.
  3531. //
  3532. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  3533. "RouterAdvertTimeout(IF %p): "
  3534. "no source\n", IF));
  3535. }
  3536. }
  3537. else {
  3538. //
  3539. // Generate a router advertisement.
  3540. //
  3541. SendRouterAdvert = TRUE;
  3542. Source = NTE->Address;
  3543. IF->RALast = Now;
  3544. //
  3545. // If we are in "fast" mode, then ensure
  3546. // that the next RA is sent quickly.
  3547. //
  3548. if (IF->RACount != 0) {
  3549. IF->RACount--;
  3550. if (IF->RATimer > MAX_INITIAL_RTR_ADVERT_INTERVAL)
  3551. IF->RATimer = MAX_INITIAL_RTR_ADVERT_INTERVAL;
  3552. }
  3553. }
  3554. }
  3555. }
  3556. }
  3557. KeReleaseSpinLockFromDpcLevel(&IF->Lock);
  3558. if (SendRouterAdvert)
  3559. RouterAdvertSend(IF, &Source, &AllNodesOnLinkAddr);
  3560. }