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.

1558 lines
50 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // Internet Control Message Protocol for Internet Protocol Version 6.
  14. // See RFC 1885 for details.
  15. //
  16. #include "oscfg.h"
  17. #include "ndis.h"
  18. #include "ip6imp.h"
  19. #include "ip6def.h"
  20. #include "route.h"
  21. #include "icmp.h"
  22. #include "ntddip6.h"
  23. #include "neighbor.h"
  24. #include "mld.h"
  25. #include "security.h"
  26. //
  27. // Ping support. We have a list of EchoControl blocks, one per outstanding
  28. // echo request message. Incoming echo replies are matched to requests via
  29. // a unique sequence number.
  30. //
  31. KSPIN_LOCK ICMPv6EchoLock;
  32. EchoControl *ICMPv6OutstandingEchos;
  33. long ICMPv6EchoSeq; // Protected with interlocked operations.
  34. //
  35. // Statistics kept for netstat and MIBs.
  36. //
  37. ICMPv6Stats ICMPv6InStats;
  38. ICMPv6Stats ICMPv6OutStats;
  39. //* ICMPv6Init - Initialize ICMPv6.
  40. //
  41. // Set the starting values of various things.
  42. //
  43. void
  44. ICMPv6Init(void)
  45. {
  46. //
  47. // Initialize in-kernel ping support.
  48. //
  49. ICMPv6OutstandingEchos = NULL;
  50. ICMPv6EchoSeq = 0;
  51. KeInitializeSpinLock(&ICMPv6EchoLock);
  52. //
  53. // Initialize Multicast Listener Discovery protocol.
  54. //
  55. MLDInit();
  56. }
  57. //* ICMPv6Send - Low-level send routine for ICMPv6 packets.
  58. //
  59. // Common ICMPv6 message transmission functionality is performed here.
  60. // The message is expected to be completely formed (with the exception
  61. // of the checksum) when this routine is called.
  62. //
  63. // Used for all ICMP packets, except for Neighbor Discovery.
  64. //
  65. void
  66. ICMPv6Send(
  67. RouteCacheEntry *RCE, // RCE to send on
  68. PNDIS_PACKET Packet, // Packet to send.
  69. uint IPv6Offset, // Offset to IPv6 header in packet.
  70. uint ICMPv6Offset, // Offset to ICMPv6 header in packet.
  71. IPv6Header UNALIGNED *IP, // Pointer to IPv6 header.
  72. uint PayloadLength, // Length of IPv6 payload in bytes.
  73. ICMPv6Header UNALIGNED *ICMP) // Pointer to ICMPv6 header.
  74. {
  75. uint ChecksumDataLength;
  76. ICMPv6OutStats.icmps_msgs++;
  77. //
  78. // Calculate the ICMPv6 checksum. It covers the entire ICMPv6 message
  79. // starting with the ICMPv6 header, plus the IPv6 pseudo-header.
  80. //
  81. // Recalculate the payload length to exclude any option headers.
  82. //
  83. ChecksumDataLength = PayloadLength -
  84. (ICMPv6Offset - IPv6Offset) + sizeof(IPv6Header);
  85. ICMP->Checksum = 0;
  86. ICMP->Checksum = ChecksumPacket(Packet, ICMPv6Offset, NULL,
  87. ChecksumDataLength,
  88. AlignAddr(&IP->Source),
  89. AlignAddr(&IP->Dest),
  90. IP_PROTOCOL_ICMPv6);
  91. if (ICMP->Checksum == 0) {
  92. //
  93. // ChecksumPacket failed, so abort the transmission.
  94. //
  95. ICMPv6OutStats.icmps_errors++;
  96. IPv6SendComplete(NULL, Packet, IP_NO_RESOURCES);
  97. return;
  98. }
  99. ICMPv6OutStats.icmps_typecount[ICMP->Type]++;
  100. //
  101. // Hand the packet down to IP for transmission.
  102. //
  103. IPv6Send(Packet, IPv6Offset, IP, PayloadLength, RCE, 0,
  104. IP_PROTOCOL_ICMPv6, 0, 0);
  105. }
  106. //* ICMPv6SendEchoReply - Send an Echo Reply message.
  107. //
  108. // Basically what we do here is slap an ICMPv6 header on the front
  109. // of the invoking packet and send it back where it came from.
  110. //
  111. void
  112. ICMPv6SendEchoReply(
  113. IPv6Packet *Packet) // Packet handed to us by ICMPv6Receive.
  114. {
  115. NDIS_STATUS NdisStatus;
  116. PNDIS_PACKET ReplyPacket;
  117. uint Offset;
  118. uchar *Mem;
  119. uint MemLen;
  120. uint ICMPLength;
  121. uint DataLength;
  122. IPv6Header UNALIGNED *ReplyIP;
  123. ICMPv6Header UNALIGNED *ReplyICMP;
  124. const IPv6Addr *Dest;
  125. IP_STATUS Status;
  126. RouteCacheEntry *RCE;
  127. //
  128. // Take our reply's destination address from the source address
  129. // of the incoming packet.
  130. //
  131. // Note that the specs specifically say that we're not to reverse
  132. // the path on source routed packets. Just reply directly.
  133. //
  134. // IPv6HeaderReceive should protect us from replying to most forms
  135. // of bogus addresses. We ASSERT this in checked builds.
  136. //
  137. Dest = Packet->SrcAddr;
  138. ASSERT(!IsInvalidSourceAddress(Dest));
  139. //
  140. // Get the reply route to the destination.
  141. // Under normal circumstances, the reply will go out
  142. // the incoming interface. RouteToDestination
  143. // will figure out the appropriate ScopeId.
  144. //
  145. Status = RouteToDestination(Dest, 0, Packet->NTEorIF,
  146. RTD_FLAG_NORMAL, &RCE);
  147. if (Status != IP_SUCCESS) {
  148. //
  149. // No route - drop the packet.
  150. //
  151. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  152. "ICMPv6SendEchoReply - no route: %x\n", Status));
  153. return;
  154. }
  155. //
  156. // Calculate the length of the ICMP header
  157. // and how much data we will include following the ICMP header.
  158. //
  159. ICMPLength = sizeof(ICMPv6Header);
  160. DataLength = Packet->TotalSize;
  161. Offset = RCE->NCE->IF->LinkHeaderSize;
  162. MemLen = Offset + sizeof(IPv6Header) + ICMPLength + DataLength;
  163. //
  164. // Allocate the reply packet.
  165. //
  166. NdisStatus = IPv6AllocatePacket(MemLen, &ReplyPacket, &Mem);
  167. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  168. ReleaseRCE(RCE);
  169. return;
  170. }
  171. //
  172. // Prepare IP header of reply packet.
  173. //
  174. ReplyIP = (IPv6Header UNALIGNED *)(Mem + Offset);
  175. ReplyIP->VersClassFlow = IP_VERSION;
  176. ReplyIP->NextHeader = IP_PROTOCOL_ICMPv6;
  177. ReplyIP->HopLimit = (uchar)RCE->NCE->IF->CurHopLimit;
  178. //
  179. // Take our reply's source address from the receiving NTE,
  180. // or use the best source address for this destination
  181. // if we don't have a receiving NTE.
  182. //
  183. ReplyIP->Source = (IsNTE(Packet->NTEorIF) ?
  184. CastToNTE(Packet->NTEorIF) : RCE->NTE)
  185. ->Address;
  186. ReplyIP->Dest = *Dest;
  187. //
  188. // Prepare ICMP header.
  189. //
  190. // REVIEW: Do this in ICMPv6Send?
  191. //
  192. ReplyICMP = (ICMPv6Header UNALIGNED *)(ReplyIP + 1);
  193. ReplyICMP->Type = ICMPv6_ECHO_REPLY;
  194. ReplyICMP->Code = 0;
  195. // ReplyICMP->Checksum - ICMPv6Send will calculate.
  196. //
  197. // Copy incoming packet data to outgoing.
  198. //
  199. CopyPacketToBuffer((uchar *)(ReplyICMP + 1), Packet, DataLength,
  200. Packet->Position);
  201. ICMPv6Send(RCE, ReplyPacket, Offset,
  202. Offset + sizeof(IPv6Header), ReplyIP,
  203. ICMPLength + DataLength, ReplyICMP);
  204. ReleaseRCE(RCE);
  205. }
  206. //* ICMPv6CheckError
  207. //
  208. // Check if a packet is an ICMP error message.
  209. // This is a "best effort" check, given that
  210. // the packet may well have syntactical errors.
  211. //
  212. // We return FALSE if we can't tell.
  213. //
  214. int
  215. ICMPv6CheckError(IPv6Packet *Packet, uint NextHeader)
  216. {
  217. for (;;) {
  218. uint HdrLen;
  219. switch (NextHeader) {
  220. case IP_PROTOCOL_HOP_BY_HOP:
  221. case IP_PROTOCOL_DEST_OPTS:
  222. case IP_PROTOCOL_ROUTING: {
  223. ExtensionHeader *Hdr;
  224. if (! PacketPullup(Packet, sizeof *Hdr,
  225. __builtin_alignof(ExtensionHeader), 0)) {
  226. //
  227. // Pullup failed. We can't continue parsing.
  228. //
  229. return FALSE;
  230. }
  231. Hdr = (ExtensionHeader *) Packet->Data;
  232. HdrLen = (Hdr->HeaderExtLength + 1) * EXT_LEN_UNIT;
  233. //
  234. // REVIEW - We don't actually want to look at the remaining
  235. // data in the extension header. Perhaps use PositionPacketAt?
  236. //
  237. if (! PacketPullup(Packet, HdrLen, 1, 0)) {
  238. //
  239. // Pullup failed. We can't continue parsing.
  240. //
  241. return FALSE;
  242. }
  243. NextHeader = Hdr->NextHeader;
  244. break;
  245. }
  246. case IP_PROTOCOL_FRAGMENT: {
  247. FragmentHeader UNALIGNED *Hdr;
  248. if (! PacketPullup(Packet, sizeof *Hdr, 1, 0)) {
  249. //
  250. // Pullup failed. We can't continue parsing.
  251. //
  252. return FALSE;
  253. }
  254. Hdr = (FragmentHeader UNALIGNED *) Packet->Data;
  255. //
  256. // We can only continue parsing if this is the first fragment.
  257. //
  258. if ((Hdr->OffsetFlag & FRAGMENT_OFFSET_MASK) != 0)
  259. return FALSE;
  260. HdrLen = sizeof *Hdr;
  261. NextHeader = Hdr->NextHeader;
  262. break;
  263. }
  264. case IP_PROTOCOL_ICMPv6: {
  265. ICMPv6Header *Hdr;
  266. if (! PacketPullup(Packet, sizeof *Hdr,
  267. __builtin_alignof(ICMPv6Header), 0)) {
  268. //
  269. // Pullup failed. We can't continue parsing.
  270. //
  271. return FALSE;
  272. }
  273. //
  274. // This is an ICMPv6 message, so we can check
  275. // to see if it is an error message.
  276. // We treat Redirects as errors here.
  277. //
  278. Hdr = (ICMPv6Header *) Packet->Data;
  279. return (ICMPv6_ERROR_TYPE(Hdr->Type) ||
  280. (Hdr->Type == ICMPv6_REDIRECT));
  281. }
  282. default:
  283. return FALSE;
  284. }
  285. //
  286. // Move past this extension header.
  287. //
  288. AdjustPacketParams(Packet, HdrLen);
  289. }
  290. }
  291. //* ICMPv6RateLimit
  292. //
  293. // Returns TRUE if an ICMP error should NOT be sent to this destination
  294. // because of rate-limiting.
  295. //
  296. int
  297. ICMPv6RateLimit(RouteCacheEntry *RCE)
  298. {
  299. uint Now = IPv6TickCount;
  300. //
  301. // This arithmetic will handle wraps of the IPv6 tick counter.
  302. //
  303. if ((uint)(Now - RCE->LastError) < ICMP_MIN_ERROR_INTERVAL)
  304. return TRUE;
  305. RCE->LastError = Now;
  306. return FALSE;
  307. }
  308. //* ICMPv6SendError - Generate an error in response to an incoming packet.
  309. //
  310. // Send an ICMPv6 message of the given Type and Code to the source of the
  311. // offending/invoking packet. The reply includes as much of the incoming
  312. // packet as will fit inside the minimal IPv6 MTU.
  313. //
  314. // Basically what we do here is slap an ICMPv6 header on the front
  315. // of the invoking packet and send it back where it came from.
  316. //
  317. // REVIEW - Much of the code looks like ICMPv6SendEchoReply.
  318. // Could it be shared?
  319. //
  320. // The current position in the Packet must be at a header boundary.
  321. // The NextHeader parameter specifies the type of header following.
  322. // This information is used to parse the remainder of the invoking Packet,
  323. // to see if it is an ICMP error. We MUST avoid sending an error
  324. // in response to an error. NextHeader may be IP_PROTOCOL_NONE.
  325. //
  326. // The MulticastOverride parameter allows override of another check.
  327. // Normally we MUST avoid sending an error in response to a packet
  328. // sent to a multicast destination. But there are a couple exceptions.
  329. //
  330. void
  331. ICMPv6SendError(
  332. IPv6Packet *Packet, // Offending/Invoking packet.
  333. uchar ICMPType, // ICMP error type.
  334. uchar ICMPCode, // ICMP error code.
  335. ulong ErrorParameter, // Parameter for error message.
  336. uint NextHeader, // Type of hdr following in Packet.
  337. int MulticastOverride) // Allow replies to mcast packets?
  338. {
  339. NDIS_STATUS NdisStatus;
  340. PNDIS_PACKET ReplyPacket;
  341. uint Offset;
  342. uchar *Mem;
  343. uint MemLen;
  344. uint ICMPLength;
  345. uint DataLength;
  346. IPv6Header UNALIGNED *ReplyIP;
  347. ICMPv6Header UNALIGNED *ReplyICMP;
  348. const IPv6Addr *Dest;
  349. IP_STATUS Status;
  350. RouteCacheEntry *RCE;
  351. //
  352. // We must not send an ICMP error message
  353. // as a result of an ICMP error.
  354. //
  355. if ((Packet->Flags & PACKET_ICMP_ERROR) ||
  356. ICMPv6CheckError(Packet, NextHeader)) {
  357. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  358. "ICMPv6SendError: no reply to error\n"));
  359. return;
  360. }
  361. //
  362. // We must not send an ICMP error message as a result
  363. // of receiving any kind of multicast or broadcast.
  364. // There are a couple exceptions so we have MulticastOverride.
  365. //
  366. if (IsMulticast(AlignAddr(&Packet->IP->Dest)) ||
  367. (Packet->Flags & PACKET_NOT_LINK_UNICAST)) {
  368. if (!MulticastOverride) {
  369. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  370. "ICMPv6SendError: no reply to broadcast/multicast\n"));
  371. return;
  372. }
  373. }
  374. //
  375. // Take our reply's destination address from the source address
  376. // of the incoming packet.
  377. //
  378. // Note that the specs specifically say that we're not to reverse
  379. // the path on source routed packets. Just reply directly.
  380. //
  381. // IPv6HeaderReceive should protect us from replying to most forms
  382. // of bogus addresses. We ASSERT this in checked builds.
  383. //
  384. Dest = Packet->SrcAddr;
  385. ASSERT(!IsInvalidSourceAddress(Dest));
  386. //
  387. // Get the reply route to the destination.
  388. // Under normal circumstances, the reply will go out
  389. // the incoming interface. RouteToDestination
  390. // will figure out the appropriate ScopeId.
  391. //
  392. Status = RouteToDestination(Dest, 0, Packet->NTEorIF,
  393. RTD_FLAG_NORMAL, &RCE);
  394. if (Status != IP_SUCCESS) {
  395. //
  396. // No route - drop the packet.
  397. //
  398. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  399. "ICMPv6SendError - no route: %x\n", Status));
  400. return;
  401. }
  402. //
  403. // We must rate-limit ICMP error messages.
  404. //
  405. if (ICMPv6RateLimit(RCE)) {
  406. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  407. "ICMPv6SendError - rate limit %s\n",
  408. FormatV6Address(&RCE->Destination)));
  409. ReleaseRCE(RCE);
  410. return;
  411. }
  412. //
  413. // Calculate the length of the ICMP header
  414. // and how much data we will include following the ICMP header.
  415. // Include space for an error value after the header proper.
  416. //
  417. ICMPLength = sizeof(ICMPv6Header) + sizeof(uint);
  418. //
  419. // We want to include data from the IP header on.
  420. //
  421. DataLength = Packet->TotalSize +
  422. (Packet->Position - Packet->IPPosition);
  423. //
  424. // But limit the error packet size.
  425. //
  426. if (DataLength > ICMPv6_ERROR_MAX_DATA_LEN)
  427. DataLength = ICMPv6_ERROR_MAX_DATA_LEN;
  428. //
  429. // Calculate buffer length.
  430. //
  431. Offset = RCE->NCE->IF->LinkHeaderSize;
  432. MemLen = Offset + sizeof(IPv6Header) + ICMPLength + DataLength;
  433. ASSERT(MemLen - Offset <= IPv6_MINIMUM_MTU);
  434. //
  435. // Allocate the reply packet.
  436. //
  437. NdisStatus = IPv6AllocatePacket(MemLen, &ReplyPacket, &Mem);
  438. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  439. ReleaseRCE(RCE);
  440. return;
  441. }
  442. //
  443. // Prepare IP header of reply packet.
  444. //
  445. ReplyIP = (IPv6Header UNALIGNED *)(Mem + Offset);
  446. ReplyIP->VersClassFlow = IP_VERSION;
  447. ReplyIP->NextHeader = IP_PROTOCOL_ICMPv6;
  448. ReplyIP->HopLimit = (uchar)RCE->NCE->IF->CurHopLimit;
  449. //
  450. // Take our reply's source address from the receiving NTE,
  451. // or use the best source address for this destination
  452. // if we don't have a receiving NTE.
  453. //
  454. ReplyIP->Source = (IsNTE(Packet->NTEorIF) ?
  455. CastToNTE(Packet->NTEorIF) : RCE->NTE)
  456. ->Address;
  457. ReplyIP->Dest = *Dest;
  458. //
  459. // Prepare ICMP header.
  460. //
  461. // REVIEW: Do this in ICMPv6Send?
  462. //
  463. ReplyICMP = (ICMPv6Header UNALIGNED *)(ReplyIP + 1);
  464. ReplyICMP->Type = ICMPType;
  465. ReplyICMP->Code = ICMPCode;
  466. // ReplyICMP->Checksum - ICMPv6Send will calculate.
  467. //
  468. // ICMP Error Messages have a 32-bit field (content of which
  469. // varies depending upon the error type) following the ICMP header.
  470. //
  471. *(ulong UNALIGNED *)(ReplyICMP + 1) = net_long(ErrorParameter);
  472. //
  473. // Copy invoking packet (from IPv6 header onward) to outgoing.
  474. //
  475. CopyPacketToBuffer((uchar *)(ReplyICMP + 1) + sizeof(ErrorParameter),
  476. Packet, DataLength, Packet->IPPosition);
  477. ICMPv6Send(RCE, ReplyPacket, Offset,
  478. Offset + sizeof(IPv6Header), ReplyIP,
  479. ICMPLength + DataLength, ReplyICMP);
  480. ReleaseRCE(RCE);
  481. }
  482. //* ICMPv6ProcessTunnelError
  483. //
  484. // Called when we receive an ICMPv4 error and there is insufficient
  485. // information to translate to an ICMPv6 error. We make a best effort
  486. // to complete outstanding echo requests that were sent to the IPv4
  487. // address that was the original IPv4 tunnel destination.
  488. //
  489. void
  490. ICMPv6ProcessTunnelError(
  491. IPAddr V4Dest, // Destination of our tunneled packet.
  492. IPv6Addr *V6Src, // Address to use as the source of the error.
  493. uint ScopeId, // Scope-id of V6Src.
  494. IP_STATUS Status) // Status of the response.
  495. {
  496. EchoControl *This, **PrevPtr;
  497. EchoControl *List = NULL;
  498. KIRQL OldIrql;
  499. //
  500. // Find the EchoControl blocks on our list of outstanding echoes that
  501. // have a matching IPv4 destination and call their completion function.
  502. // We do not have sufficient information to identify a unique request.
  503. //
  504. KeAcquireSpinLock(&ICMPv6EchoLock, &OldIrql);
  505. PrevPtr = &ICMPv6OutstandingEchos;
  506. while ((This = *PrevPtr) != NULL) {
  507. if (This->V4Dest == V4Dest) {
  508. //
  509. // Found matching control block. Extract it from the list
  510. // and put it on our own list.
  511. //
  512. *PrevPtr = This->Next;
  513. This->Next = List;
  514. List = This;
  515. }
  516. else
  517. PrevPtr = &This->Next;
  518. }
  519. KeReleaseSpinLock(&ICMPv6EchoLock, OldIrql);
  520. while ((This = List) != NULL) {
  521. //
  522. // Remove this request from our list.
  523. //
  524. List = This->Next;
  525. //
  526. // Call OS-specific completion routine.
  527. //
  528. (*This->CompleteRoutine)(This, Status,
  529. V6Src, ScopeId,
  530. NULL, 0);
  531. }
  532. }
  533. //* ICMPv6ProcessEchoReply
  534. //
  535. // Called either when an echo reply arrives, or
  536. // a hop-count-exceeded error responding to an echo request arrives.
  537. //
  538. // Looks up the echo request structure and completes
  539. // the echo request operation.
  540. //
  541. // Note that the echo reply payload data must be contiguous.
  542. // Callers should use PacketPullup if necessary.
  543. //
  544. void
  545. ICMPv6ProcessEchoReply(
  546. ulong Seq, // Echo sequence number.
  547. IP_STATUS Status, // Status of the response.
  548. IPv6Packet *Packet, // Echo reply packet.
  549. void *Current, // Pointer to the buffered data area.
  550. uint PayloadLength) // Size of remaining payload data.
  551. {
  552. EchoControl *This, **PrevPtr;
  553. KIRQL OldIrql;
  554. uint ICMPPosition;
  555. //
  556. // Find the EchoControl block on our list of outstanding echoes that
  557. // has a matching sequence number and call it's completion function.
  558. //
  559. KeAcquireSpinLock(&ICMPv6EchoLock, &OldIrql);
  560. PrevPtr = &ICMPv6OutstandingEchos;
  561. while ((This = *PrevPtr) != NULL) {
  562. if (This->Seq == Seq) {
  563. //
  564. // Found matching control block. Extract it from list.
  565. //
  566. *PrevPtr = This->Next;
  567. break;
  568. }
  569. PrevPtr = &This->Next;
  570. }
  571. KeReleaseSpinLock(&ICMPv6EchoLock, OldIrql);
  572. //
  573. // Check to see if we ran off the end of the outstanding echoes list.
  574. //
  575. if (This == NULL) {
  576. //
  577. // We received a response with a sequence number that doesn't match
  578. // one of the echo requests we still have outstanding. Drop it.
  579. //
  580. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  581. "ICMPv6ProcessEchoReply: Received echo response "
  582. "with bogus/expired sequence number 0x%x\n", Seq));
  583. if (Current != NULL) {
  584. //
  585. // If this is a normal Echo Reply (not a error message sent in
  586. // response to one of our Echo Replies) first see if any raw
  587. // receivers want to look at it.
  588. //
  589. ICMPPosition = Packet->Position - sizeof(ICMPv6Header)
  590. - sizeof(Seq);
  591. PositionPacketAt(Packet, ICMPPosition);
  592. (void) RawReceive(Packet, IP_PROTOCOL_ICMPv6);
  593. }
  594. return;
  595. }
  596. //
  597. // Call OS-specific completion routine.
  598. //
  599. (*This->CompleteRoutine)(This, Status,
  600. Packet->SrcAddr,
  601. DetermineScopeId(Packet->SrcAddr,
  602. Packet->NTEorIF->IF),
  603. Current, PayloadLength);
  604. }
  605. //* ICMPv6EchoReplyReceive - Receive a reply to an earlier echo of our's.
  606. //
  607. // Called by ICMPv6Receive when an echo reply message arrives.
  608. //
  609. // REVIEW: Should we also verify the receiving NTE is the same as the one
  610. // REVIEW: we sent on?
  611. //
  612. void
  613. ICMPv6EchoReplyReceive(IPv6Packet *Packet)
  614. {
  615. ulong Seq;
  616. //
  617. // The next four bytes should consist of a two byte Identifier field
  618. // and a two byte Sequence Number. We just treat the whole thing as
  619. // a four byte sequence number. Make sure these bytes are contiguous.
  620. //
  621. if (! PacketPullup(Packet, sizeof Seq, 1, 0)) {
  622. // Pullup failed.
  623. if (Packet->TotalSize < sizeof(Seq)) {
  624. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  625. "ICMPv6: Received small Echo Reply %u\n",
  626. Packet->TotalSize));
  627. ICMPv6SendError(Packet,
  628. ICMPv6_PARAMETER_PROBLEM,
  629. ICMPv6_ERRONEOUS_HEADER_FIELD,
  630. FIELD_OFFSET(IPv6Header, PayloadLength),
  631. IP_PROTOCOL_NONE, FALSE);
  632. }
  633. return; // Drop packet.
  634. }
  635. //
  636. // We're received a reply message to one of our echo requests.
  637. // Extract its sequence number so that we can identify it.
  638. //
  639. Seq = net_long(*(ulong UNALIGNED *)Packet->Data);
  640. AdjustPacketParams(Packet, sizeof Seq);
  641. //
  642. // REVIEW: The ICMPv6ProcessEchoReply interface expects a contiguous data
  643. // REVIEW: region for the rest of the packet. This requires us to
  644. // REVIEW: pullup the remainder of the packet here. Fix this someday.
  645. //
  646. if (! PacketPullup(Packet, Packet->TotalSize, 1, 0)) {
  647. // Pullup failed.
  648. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  649. "ICMPv6: Couldn't pullup echo data\n"));
  650. return; // Drop packet.
  651. }
  652. ICMPv6ProcessEchoReply(Seq, IP_SUCCESS, Packet,
  653. Packet->Data, Packet->TotalSize);
  654. }
  655. //* ICMPv6ErrorReceive - Generic ICMPv6 error processing.
  656. //
  657. // Called by ICMPv6Receive when an error message arrives.
  658. // Returns FALSE if we were unable to process it for some reason.
  659. //
  660. int
  661. ICMPv6ErrorReceive(
  662. IPv6Packet *Packet, // Packet handed to us by ICMPv6Receive.
  663. ICMPv6Header UNALIGNED *ICMP) // ICMP Header.
  664. {
  665. ulong Parameter;
  666. IP_STATUS Status;
  667. StatusArg StatArg;
  668. IPv6Header UNALIGNED *InvokingIP;
  669. ProtoControlRecvProc *Handler = NULL;
  670. uchar NextHeader;
  671. int Handled = TRUE;
  672. //
  673. // First mark the packet as an ICMP error.
  674. // This will inhibit any generation of ICMP errors
  675. // as a result of this packet.
  676. //
  677. Packet->Flags |= PACKET_ICMP_ERROR;
  678. //
  679. // All ICMPv6 error messages consist of the base ICMPv6 header,
  680. // followed by a 32 bit type-specific field, followed by as much
  681. // of the invoking packet as fit without causing this ICMPv6 packet
  682. // to exceed 576 octets.
  683. //
  684. // We already consumed the base ICMPv6 header back in ICMPv6Receive.
  685. // Pull out the 32 bit type-specific field in case the upper layer's
  686. // ControlReceive routine cares about it.
  687. //
  688. if (! PacketPullup(Packet, sizeof Parameter, 1, 0)) {
  689. // Pullup failed.
  690. if (Packet->TotalSize < sizeof Parameter)
  691. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  692. "ICMPv6ErrorReceive: "
  693. "Packet too small to contain error field\n"));
  694. return FALSE; // Drop packet.
  695. }
  696. Parameter = *(ulong UNALIGNED *)Packet->Data;
  697. AdjustPacketParams(Packet, sizeof Parameter);
  698. //
  699. // Next up should be the IPv6 header of the invoking packet.
  700. //
  701. if (! PacketPullup(Packet, sizeof *InvokingIP,
  702. __builtin_alignof(IPv6Addr), 0)) {
  703. // Pullup failed.
  704. if (Packet->TotalSize < sizeof *InvokingIP)
  705. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  706. "ICMPv6ErrorReceive (from %s): "
  707. "Packet too small to contain IPv6 "
  708. "header from invoking packet\n",
  709. FormatV6Address(AlignAddr(&Packet->IP->Source))));
  710. return FALSE; // Drop packet.
  711. }
  712. InvokingIP = (IPv6Header UNALIGNED *)Packet->Data;
  713. AdjustPacketParams(Packet, sizeof *InvokingIP);
  714. //
  715. // First we perform any specific processing of the error,
  716. // and convert the error type/code to a status value.
  717. //
  718. switch (ICMP->Type) {
  719. case ICMPv6_DESTINATION_UNREACHABLE:
  720. switch (ICMP->Code) {
  721. case ICMPv6_NO_ROUTE_TO_DESTINATION:
  722. Status = IP_DEST_NO_ROUTE;
  723. break;
  724. case ICMPv6_COMMUNICATION_PROHIBITED:
  725. Status = IP_DEST_PROHIBITED;
  726. break;
  727. case ICMPv6_SCOPE_MISMATCH:
  728. Status = IP_DEST_SCOPE_MISMATCH;
  729. break;
  730. case ICMPv6_ADDRESS_UNREACHABLE:
  731. Status = IP_DEST_ADDR_UNREACHABLE;
  732. break;
  733. case ICMPv6_PORT_UNREACHABLE:
  734. Status = IP_DEST_PORT_UNREACHABLE;
  735. break;
  736. default:
  737. Status = IP_DEST_UNREACHABLE;
  738. break;
  739. }
  740. break;
  741. case ICMPv6_PACKET_TOO_BIG: {
  742. uint PMTU;
  743. //
  744. // Packet Too Big messages contain the bottleneck MTU value.
  745. // Update the path MTU in the route cache.
  746. // Change Parameter value to indicate whether PMTU changed.
  747. //
  748. PMTU = net_long(Parameter);
  749. Parameter = UpdatePathMTU(Packet->NTEorIF->IF,
  750. AlignAddr(&InvokingIP->Dest), PMTU);
  751. Status = IP_PACKET_TOO_BIG;
  752. break;
  753. }
  754. case ICMPv6_TIME_EXCEEDED:
  755. switch (ICMP->Code) {
  756. case ICMPv6_HOP_LIMIT_EXCEEDED:
  757. Status = IP_HOP_LIMIT_EXCEEDED;
  758. break;
  759. case ICMPv6_REASSEMBLY_TIME_EXCEEDED:
  760. Status = IP_REASSEMBLY_TIME_EXCEEDED;
  761. break;
  762. default:
  763. Status = IP_TIME_EXCEEDED;
  764. break;
  765. }
  766. break;
  767. case ICMPv6_PARAMETER_PROBLEM:
  768. switch (ICMP->Code) {
  769. case ICMPv6_ERRONEOUS_HEADER_FIELD:
  770. Status = IP_BAD_HEADER;
  771. break;
  772. case ICMPv6_UNRECOGNIZED_NEXT_HEADER:
  773. Status = IP_UNRECOGNIZED_NEXT_HEADER;
  774. break;
  775. case ICMPv6_UNRECOGNIZED_OPTION:
  776. Status = IP_BAD_OPTION;
  777. break;
  778. default:
  779. Status = IP_PARAMETER_PROBLEM;
  780. break;
  781. }
  782. break;
  783. default:
  784. //
  785. // We don't understand this error type.
  786. //
  787. Status = IP_ICMP_ERROR;
  788. Handled = FALSE;
  789. break;
  790. }
  791. //
  792. // Deliver ICMP Error to higher layers. This is a MUST, even if we
  793. // don't recognize the specific error message.
  794. //
  795. // Iteratively switch out to the handler for each successive next header
  796. // until we reach a handler that reports no more headers follow it.
  797. //
  798. NextHeader = InvokingIP->NextHeader;
  799. while (NextHeader != IP_PROTOCOL_NONE) {
  800. //
  801. // Current header indicates that another header follows.
  802. // See if we have a handler for it.
  803. //
  804. Handler = ProtocolSwitchTable[NextHeader].ControlReceive;
  805. if (Handler == NULL) {
  806. //
  807. // If we don't have a handler for this header type,
  808. // we just drop the packet.
  809. //
  810. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  811. "IPv6ErrorReceive: No handler for NextHeader type %u.\n",
  812. NextHeader));
  813. break;
  814. }
  815. StatArg.Status = Status;
  816. StatArg.Arg = Parameter;
  817. StatArg.IP = InvokingIP;
  818. NextHeader = (*Handler)(Packet, &StatArg);
  819. }
  820. return Handled;
  821. }
  822. //* ICMPv6ControlReceive - handler for ICMPv6 control messages.
  823. //
  824. // This routine is called if we receive an ICMPv6 error message that
  825. // was generated by some remote site as a result of receiving an ICMPv6
  826. // packet from us.
  827. //
  828. uchar
  829. ICMPv6ControlReceive(
  830. IPv6Packet *Packet, // Packet handed to us by ICMPv6Receive.
  831. StatusArg *StatArg) // ICMP Error Code, etc.
  832. {
  833. ICMPv6Header *InvokingICMP;
  834. ulong Seq;
  835. //
  836. // The next thing in the packet should be the ICMP header of the
  837. // original packet which invoked this error.
  838. //
  839. if (! PacketPullup(Packet, sizeof *InvokingICMP,
  840. __builtin_alignof(ICMPv6Header), 0)) {
  841. // Pullup failed.
  842. if (Packet->TotalSize < sizeof *InvokingICMP)
  843. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  844. "ICMPv6: Packet too small to contain ICMPv6 header "
  845. "from invoking packet\n"));
  846. return IP_PROTOCOL_NONE; // Drop packet.
  847. }
  848. InvokingICMP = (ICMPv6Header *)Packet->Data;
  849. AdjustPacketParams(Packet, sizeof *InvokingICMP);
  850. //
  851. // All we currently handle is errors caused by echo requests.
  852. //
  853. if ((InvokingICMP->Type != ICMPv6_ECHO_REQUEST) ||
  854. (InvokingICMP->Code != 0))
  855. return IP_PROTOCOL_NONE; // Drop packet.
  856. //
  857. // The next four bytes should consist of a two byte Identifier field
  858. // and a two byte Sequence Number. We just treat the whole thing as
  859. // a four byte sequence number. Make sure these bytes are contiguous.
  860. //
  861. if (! PacketPullup(Packet, sizeof Seq, 1, 0)) {
  862. // Pullup failed.
  863. if (Packet->TotalSize < sizeof Seq)
  864. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  865. "ICMPv6: Packet too small to contain ICMPv6 header "
  866. "from invoking packet\n"));
  867. return IP_PROTOCOL_NONE; // Drop packet.
  868. }
  869. //
  870. // Extract the sequence number so that we can identify
  871. // the matching echo request.
  872. //
  873. Seq = net_long(*(ulong UNALIGNED *)Packet->Data);
  874. AdjustPacketParams(Packet, sizeof Seq);
  875. //
  876. // Complete the corresponding echo request with an error.
  877. //
  878. ICMPv6ProcessEchoReply(Seq, StatArg->Status, Packet,
  879. NULL, 0);
  880. return IP_PROTOCOL_NONE; // Done with packet.
  881. }
  882. //* ICMPv6Receive - Receive an incoming ICMPv6 packet.
  883. //
  884. // This is the routine called by IPv6 when it receives a complete IPv6
  885. // packet with a Next Header value of 58.
  886. //
  887. uchar
  888. ICMPv6Receive(
  889. IPv6Packet *Packet) // Packet handed to us by IPv6Receive.
  890. {
  891. ICMPv6Header *ICMP;
  892. ushort Checksum;
  893. uint ICMPPosition;
  894. ICMPv6InStats.icmps_msgs++;
  895. //
  896. // Verify IPSec was performed.
  897. //
  898. if (InboundSecurityCheck(Packet, IP_PROTOCOL_ICMPv6, 0, 0,
  899. Packet->NTEorIF->IF) != TRUE) {
  900. //
  901. // No policy was found or the policy indicated to drop the packet.
  902. //
  903. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  904. "ICMPv6: IPSec lookup failed\n"));
  905. ICMPv6InStats.icmps_errors++;
  906. return IP_PROTOCOL_NONE; // Drop packet.
  907. }
  908. //
  909. // Verify that we have enough contiguous data to overlay a ICMPv6Header
  910. // structure on the incoming packet. Then do so.
  911. //
  912. if (! PacketPullup(Packet, sizeof *ICMP,
  913. __builtin_alignof(ICMPv6Header), 0)) {
  914. // Pullup failed.
  915. ICMPv6InStats.icmps_errors++;
  916. if (Packet->TotalSize < sizeof *ICMP) {
  917. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  918. "ICMPv6: Packet too small to contain ICMP header\n"));
  919. ICMPv6SendError(Packet,
  920. ICMPv6_PARAMETER_PROBLEM,
  921. ICMPv6_ERRONEOUS_HEADER_FIELD,
  922. FIELD_OFFSET(IPv6Header, PayloadLength),
  923. IP_PROTOCOL_NONE, FALSE);
  924. }
  925. return IP_PROTOCOL_NONE; // Drop packet.
  926. }
  927. ICMP = (ICMPv6Header *)Packet->Data;
  928. ICMPPosition = Packet->Position;
  929. //
  930. // Verify checksum.
  931. //
  932. Checksum = ChecksumPacket(Packet->NdisPacket, Packet->Position,
  933. Packet->FlatData, Packet->TotalSize,
  934. Packet->SrcAddr, AlignAddr(&Packet->IP->Dest),
  935. IP_PROTOCOL_ICMPv6);
  936. if (Checksum != 0xffff) {
  937. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  938. "ICMPv6: Checksum failed %0x\n", Checksum));
  939. ICMPv6InStats.icmps_errors++;
  940. return IP_PROTOCOL_NONE; // Drop packet.
  941. }
  942. //
  943. // Skip over base ICMP header.
  944. //
  945. AdjustPacketParams(Packet, sizeof *ICMP);
  946. //
  947. // Ignore Neighbor Discovery packets
  948. // if the interface is so configured.
  949. // (Pseudo-interfaces don't do Neighbor Discovery.)
  950. //
  951. if (!(Packet->NTEorIF->IF->Flags & IF_FLAG_NEIGHBOR_DISCOVERS)) {
  952. if ((ICMP->Type == ICMPv6_NEIGHBOR_SOLICIT) ||
  953. (ICMP->Type == ICMPv6_NEIGHBOR_ADVERT)) {
  954. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  955. "ICMPv6Receive: ND on pseudo-interface\n"));
  956. ICMPv6InStats.icmps_errors++;
  957. return IP_PROTOCOL_NONE; // Drop packet.
  958. }
  959. }
  960. //
  961. // Ignore Router Discovery packets
  962. // if the interface is so configured.
  963. //
  964. if (!(Packet->NTEorIF->IF->Flags & IF_FLAG_ROUTER_DISCOVERS)) {
  965. if ((ICMP->Type == ICMPv6_ROUTER_SOLICIT) ||
  966. (ICMP->Type == ICMPv6_ROUTER_ADVERT) ||
  967. (ICMP->Type == ICMPv6_REDIRECT)) {
  968. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  969. "ICMPv6Receive: RD on pseudo-interface\n"));
  970. ICMPv6InStats.icmps_errors++;
  971. return IP_PROTOCOL_NONE; // Drop packet.
  972. }
  973. }
  974. ICMPv6InStats.icmps_typecount[ICMP->Type]++;
  975. //
  976. // We have a separate routine to handle error messages.
  977. //
  978. if (ICMPv6_ERROR_TYPE(ICMP->Type)) {
  979. if (!ICMPv6ErrorReceive(Packet, ICMP))
  980. goto unrecognized;
  981. return IP_PROTOCOL_NONE;
  982. }
  983. //
  984. // Handle specific informational message types.
  985. // Just use a switch statement for now. If this is later deemed to be
  986. // too inefficient, we can change it to use a type switch table instead.
  987. //
  988. switch(ICMP->Type) {
  989. case ICMPv6_ECHO_REQUEST:
  990. ICMPv6SendEchoReply(Packet);
  991. break;
  992. case ICMPv6_ECHO_REPLY:
  993. ICMPv6EchoReplyReceive(Packet);
  994. break;
  995. case ICMPv6_MULTICAST_LISTENER_QUERY:
  996. MLDQueryReceive(Packet);
  997. break;
  998. case ICMPv6_MULTICAST_LISTENER_REPORT:
  999. MLDReportReceive(Packet);
  1000. break;
  1001. case ICMPv6_MULTICAST_LISTENER_DONE:
  1002. break;
  1003. // Following are all Neighbor Discovery messages.
  1004. case ICMPv6_ROUTER_SOLICIT:
  1005. RouterSolicitReceive(Packet, ICMP);
  1006. break;
  1007. case ICMPv6_ROUTER_ADVERT:
  1008. RouterAdvertReceive(Packet, ICMP);
  1009. break;
  1010. case ICMPv6_NEIGHBOR_SOLICIT:
  1011. NeighborSolicitReceive(Packet, ICMP);
  1012. break;
  1013. case ICMPv6_NEIGHBOR_ADVERT:
  1014. NeighborAdvertReceive(Packet, ICMP);
  1015. break;
  1016. case ICMPv6_REDIRECT:
  1017. RedirectReceive(Packet, ICMP);
  1018. break;
  1019. default:
  1020. //
  1021. // Don't recognize the specific message type.
  1022. // This is an unknown informational message.
  1023. // We MUST silently discard it.
  1024. //
  1025. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_BAD_PACKET,
  1026. "ICMPv6: Received unknown informational message"
  1027. "(%u/%u) from %s\n", ICMP->Type, ICMP->Code,
  1028. FormatV6Address(AlignAddr(&Packet->IP->Source))));
  1029. //
  1030. // But first see if any raw receivers want to look at it.
  1031. // NOTE: We don't get any feedback from raw receivers,
  1032. // NOTE: so we can't tell if any of them knew this type.
  1033. //
  1034. unrecognized:
  1035. PositionPacketAt(Packet, ICMPPosition);
  1036. (void) RawReceive(Packet, IP_PROTOCOL_ICMPv6);
  1037. break;
  1038. }
  1039. return IP_PROTOCOL_NONE;
  1040. }
  1041. //* ICMPv6EchoRequest - Common dispatch routine for echo requests.
  1042. //
  1043. // This is the routine called by the OS-specific code on behalf of a user
  1044. // to issue an echo request. Validate the request, place control block
  1045. // on list of outstanding echo requests, and send echo request message.
  1046. //
  1047. void
  1048. ICMPv6EchoRequest(
  1049. void *InputBuffer, // Pointer to an ICMPV6_ECHO_REQUEST structure.
  1050. uint InputBufferLength, // Size in bytes of the InputBuffer.
  1051. EchoControl *ControlBlock, // Pointer to an EchoControl structure.
  1052. EchoRtn Callback) // Called when request responds or times out.
  1053. {
  1054. NetTableEntry *NTE = NULL;
  1055. PICMPV6_ECHO_REQUEST RequestBuffer;
  1056. KIRQL OldIrql;
  1057. IP_STATUS Status;
  1058. ulong Seq;
  1059. NDIS_STATUS NdisStatus;
  1060. PNDIS_PACKET Packet;
  1061. uint Offset;
  1062. uchar *Mem;
  1063. uint MemLen;
  1064. IPv6Header UNALIGNED *IP;
  1065. ICMPv6Header UNALIGNED *ICMP;
  1066. void *Data;
  1067. uint DataSize;
  1068. uint RtHdrSize;
  1069. RouteCacheEntry *RCE = NULL;
  1070. const IPv6Addr *FinalDest, *FirstDest;
  1071. const IPv6Addr *DstAddress, *SrcAddress;
  1072. uint DstScopeId, SrcScopeId;
  1073. ICMPv6OutStats.icmps_msgs++;
  1074. RequestBuffer = (PICMPV6_ECHO_REQUEST) InputBuffer;
  1075. //
  1076. // Validate the request.
  1077. //
  1078. if (InputBufferLength < sizeof *RequestBuffer) {
  1079. Status = IP_BUF_TOO_SMALL;
  1080. goto common_echo_exit;
  1081. }
  1082. //
  1083. // If InputBufferLength is too big, it could cause a
  1084. // buffer overflow later on in the computation for
  1085. // MemLen. Cap the value to MAXLONG.
  1086. //
  1087. if (InputBufferLength > (uint) MAXLONG) {
  1088. Status = IP_PARAM_PROBLEM;
  1089. goto common_echo_exit;
  1090. }
  1091. Data = RequestBuffer + 1;
  1092. DataSize = InputBufferLength - sizeof *RequestBuffer;
  1093. //
  1094. // Extract address information from the TDI addresses
  1095. // in the request.
  1096. //
  1097. DstAddress = (const IPv6Addr *) RequestBuffer->DstAddress.sin6_addr;
  1098. DstScopeId = RequestBuffer->DstAddress.sin6_scope_id;
  1099. SrcAddress = (const IPv6Addr *) RequestBuffer->SrcAddress.sin6_addr;
  1100. SrcScopeId = RequestBuffer->SrcAddress.sin6_scope_id;
  1101. //
  1102. // Determine which NTE will send the request,
  1103. // if the user has specified a source address.
  1104. //
  1105. if (! IsUnspecified(SrcAddress)) {
  1106. //
  1107. // Convert the source address to an NTE.
  1108. //
  1109. NTE = FindNetworkWithAddress(SrcAddress, SrcScopeId);
  1110. if (NTE == NULL) {
  1111. Status = IP_BAD_ROUTE;
  1112. goto common_echo_exit;
  1113. }
  1114. Status = RouteToDestination(DstAddress, DstScopeId,
  1115. CastFromNTE(NTE),
  1116. RTD_FLAG_NORMAL, &RCE);
  1117. if (Status != IP_SUCCESS)
  1118. goto common_echo_exit;
  1119. } else {
  1120. //
  1121. // Get the source address from the outgoing interface.
  1122. //
  1123. Status = RouteToDestination(DstAddress, DstScopeId,
  1124. NULL,
  1125. RTD_FLAG_NORMAL, &RCE);
  1126. if (Status != IP_SUCCESS)
  1127. goto common_echo_exit;
  1128. NTE = RCE->NTE;
  1129. AddRefNTE(NTE);
  1130. }
  1131. //
  1132. // Should we use a routing header to send
  1133. // a "round-trip" echo request to ourself?
  1134. //
  1135. if (RequestBuffer->Flags & ICMPV6_ECHO_REQUEST_FLAG_REVERSE) {
  1136. //
  1137. // Use a routing header.
  1138. //
  1139. FinalDest = &NTE->Address;
  1140. FirstDest = DstAddress;
  1141. RtHdrSize = sizeof(IPv6RoutingHeader) + sizeof(IPv6Addr);
  1142. }
  1143. else {
  1144. //
  1145. // No routing header.
  1146. //
  1147. FinalDest = FirstDest = DstAddress;
  1148. RtHdrSize = 0;
  1149. }
  1150. //
  1151. // Allocate the Echo Request packet.
  1152. //
  1153. Offset = RCE->NCE->IF->LinkHeaderSize;
  1154. MemLen = Offset + sizeof(IPv6Header) + RtHdrSize + sizeof(ICMPv6Header) +
  1155. sizeof Seq + DataSize;
  1156. NdisStatus = IPv6AllocatePacket(MemLen, &Packet, &Mem);
  1157. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  1158. Status = IP_NO_RESOURCES;
  1159. goto common_echo_exit;
  1160. }
  1161. //
  1162. // Prepare IP header of Echo Request packet.
  1163. //
  1164. IP = (IPv6Header UNALIGNED *)(Mem + Offset);
  1165. IP->VersClassFlow = IP_VERSION;
  1166. IP->NextHeader = IP_PROTOCOL_ICMPv6;
  1167. IP->Source = NTE->Address;
  1168. IP->Dest = *FirstDest;
  1169. IP->HopLimit = RequestBuffer->TTL;
  1170. if (IP->HopLimit == 0)
  1171. IP->HopLimit = (uchar)RCE->NCE->IF->CurHopLimit;
  1172. //
  1173. // Prepare the routing header.
  1174. // The packet will travel to the destination and then
  1175. // be routed back to the source.
  1176. //
  1177. if (RtHdrSize != 0) {
  1178. IPv6RoutingHeader *RtHdr = (IPv6RoutingHeader *)(IP + 1);
  1179. IP->NextHeader = IP_PROTOCOL_ROUTING;
  1180. RtHdr->NextHeader = IP_PROTOCOL_ICMPv6;
  1181. RtHdr->HeaderExtLength = 2;
  1182. RtHdr->RoutingType = 0;
  1183. RtHdr->SegmentsLeft = 1;
  1184. RtlZeroMemory(&RtHdr->Reserved, sizeof RtHdr->Reserved);
  1185. ((IPv6Addr *)(RtHdr + 1))[0] = *FinalDest;
  1186. }
  1187. //
  1188. // Prepare ICMP header.
  1189. //
  1190. ICMP = (ICMPv6Header UNALIGNED *)
  1191. ((uchar *)IP + sizeof(IPv6Header) + RtHdrSize);
  1192. ICMP->Type = ICMPv6_ECHO_REQUEST;
  1193. ICMP->Code = 0;
  1194. ICMP->Checksum = 0; // Calculated below.
  1195. //
  1196. // Insert Echo sequence number. Technically, this is 16 bits of
  1197. // "Identifier" and 16 bits of "Sequence Number", but we just treat
  1198. // the whole thing as one 32 bit sequence number field.
  1199. //
  1200. Seq = InterlockedIncrement(&ICMPv6EchoSeq);
  1201. Mem = (uchar *)(ICMP + 1);
  1202. *(ulong UNALIGNED *)Mem = net_long(Seq);
  1203. Mem += sizeof(ulong);
  1204. //
  1205. // Copy the user data into the packet.
  1206. //
  1207. RtlCopyMemory(Mem, Data, DataSize);
  1208. //
  1209. // We calculate the checksum here, because
  1210. // of routing header complications -
  1211. // we need to use the final destination.
  1212. //
  1213. ICMP->Checksum = ChecksumPacket(
  1214. NULL, 0, (uchar *)ICMP, sizeof(ICMPv6Header) + sizeof Seq + DataSize,
  1215. AlignAddr(&IP->Source), FinalDest, IP_PROTOCOL_ICMPv6);
  1216. if (ICMP->Checksum == 0) {
  1217. //
  1218. // ChecksumPacket failed, so abort the transmission.
  1219. //
  1220. IPv6FreePacket(Packet);
  1221. Status = IP_NO_RESOURCES;
  1222. goto common_echo_exit;
  1223. }
  1224. //
  1225. // If this Echo Request is being tunneled to an IPv4 destination,
  1226. // remember the IPv4 destination address. We use this later
  1227. // if we receive an ICMPv4 error with insufficient information
  1228. // to translate to an ICMPv6 error.
  1229. //
  1230. ControlBlock->V4Dest = GetV4Destination(RCE);
  1231. //
  1232. // Prepare the control block and link it onto the list.
  1233. // Once we've unlocked the list, the control block might
  1234. // be completed at any time. Hence it's very important
  1235. // that we not access RequestBuffer after this point.
  1236. // Also we can not return a failure code. To clean up the
  1237. // outstanding request properly, we must use ICMPv6ProcessEchoReply.
  1238. //
  1239. ControlBlock->TimeoutTimer = ConvertMillisToTicks(RequestBuffer->Timeout);
  1240. ControlBlock->CompleteRoutine = Callback;
  1241. ControlBlock->Seq = Seq;
  1242. if (ControlBlock->TimeoutTimer == 0) {
  1243. IPv6FreePacket(Packet);
  1244. Status = IP_REQ_TIMED_OUT;
  1245. goto common_echo_exit;
  1246. }
  1247. KeAcquireSpinLock(&ICMPv6EchoLock, &OldIrql);
  1248. ControlBlock->Next = ICMPv6OutstandingEchos;
  1249. ICMPv6OutstandingEchos = ControlBlock;
  1250. KeReleaseSpinLock(&ICMPv6EchoLock, OldIrql);
  1251. ICMPv6OutStats.icmps_typecount[ICMPv6_ECHO_REQUEST]++;
  1252. //
  1253. // Hand the packet down to IP for transmission.
  1254. // We can't use ICMPv6Send
  1255. // because of routing header complications.
  1256. //
  1257. IPv6Send(Packet, Offset, IP,
  1258. RtHdrSize + sizeof(ICMPv6Header) + sizeof Seq + DataSize,
  1259. RCE, 0, IP_PROTOCOL_ICMPv6, 0, 0);
  1260. common_echo_cleanup:
  1261. if (RCE != NULL)
  1262. ReleaseRCE(RCE);
  1263. if (NTE != NULL)
  1264. ReleaseNTE(NTE);
  1265. return;
  1266. common_echo_exit:
  1267. //
  1268. // Complete the echo request with an error,
  1269. // before it has been placed on our outstanding echoes list.
  1270. //
  1271. ICMPv6OutStats.icmps_errors++;
  1272. (*Callback)(ControlBlock, Status, &UnspecifiedAddr, 0, NULL, 0);
  1273. goto common_echo_cleanup;
  1274. } // ICMPv6EchoRequest
  1275. //* ICMPv6EchoComplete - Common completion routine for echo requests.
  1276. //
  1277. // This is the routine is called by the OS-specific code to process an
  1278. // ICMP echo response.
  1279. //
  1280. NTSTATUS
  1281. ICMPv6EchoComplete(
  1282. EchoControl *ControlBlock, // ControlBlock of completed request.
  1283. IP_STATUS Status, // Status of the reply.
  1284. const IPv6Addr *Address, // Source of the reply.
  1285. uint ScopeId, // Scope of the reply.
  1286. void *Data, // Reply data (may be NULL).
  1287. uint DataSize, // Amount of reply data.
  1288. ULONG_PTR *BytesReturned) // Total user bytes returned.
  1289. {
  1290. PICMPV6_ECHO_REPLY ReplyBuffer;
  1291. LARGE_INTEGER Now, Freq;
  1292. //
  1293. // Sanity check our reply buffer length.
  1294. //
  1295. if (ControlBlock->ReplyBufLen < sizeof *ReplyBuffer) {
  1296. *BytesReturned = 0;
  1297. return STATUS_BUFFER_TOO_SMALL;
  1298. }
  1299. ReplyBuffer = (PICMPV6_ECHO_REPLY) ControlBlock->ReplyBuf;
  1300. //
  1301. // Fill in fields to return.
  1302. //
  1303. ReplyBuffer->Address.sin6_port = 0;
  1304. ReplyBuffer->Address.sin6_flowinfo = 0;
  1305. RtlCopyMemory(ReplyBuffer->Address.sin6_addr, Address, sizeof *Address);
  1306. ReplyBuffer->Address.sin6_scope_id = ScopeId;
  1307. ReplyBuffer->Status = Status;
  1308. //
  1309. // Return the elapsed time in milliseconds.
  1310. //
  1311. Now = KeQueryPerformanceCounter(&Freq);
  1312. ReplyBuffer->RoundTripTime = (uint)
  1313. ((1000 * (Now.QuadPart - ControlBlock->WhenIssued.QuadPart)) /
  1314. Freq.QuadPart);
  1315. //
  1316. // Verify we have enough space in the reply buffer for the reply data.
  1317. //
  1318. if (ControlBlock->ReplyBufLen < sizeof *ReplyBuffer + DataSize) {
  1319. *BytesReturned = sizeof *ReplyBuffer;
  1320. return STATUS_BUFFER_TOO_SMALL;
  1321. }
  1322. //
  1323. // Copy the reply data to follow the reply buffer.
  1324. //
  1325. RtlCopyMemory(ReplyBuffer + 1, Data, DataSize);
  1326. *BytesReturned = sizeof *ReplyBuffer + DataSize;
  1327. return STATUS_SUCCESS;
  1328. } // ICMPv6EchoComplete
  1329. //* ICMPv6EchoTimeout - expire aging unanswered echo requests.
  1330. //
  1331. // IPv6Timeout calls this routine whenever it thinks we might have
  1332. // echo requests outstanding.
  1333. //
  1334. // Callable from DPC context, not from thread context.
  1335. // Called with no locks held.
  1336. //
  1337. void
  1338. ICMPv6EchoTimeout(void)
  1339. {
  1340. EchoControl *This, **PrevPtr, *TimedOut;
  1341. TimedOut = NULL;
  1342. //
  1343. // Grab the outstanding echo list lock and run through the list looking
  1344. // for requests that have timed out.
  1345. //
  1346. KeAcquireSpinLockAtDpcLevel(&ICMPv6EchoLock);
  1347. PrevPtr = &ICMPv6OutstandingEchos;
  1348. while ((This = *PrevPtr) != NULL) {
  1349. if (This->TimeoutTimer != 0) {
  1350. //
  1351. // Timer is running. Decrement and check for expiration.
  1352. //
  1353. if (--This->TimeoutTimer == 0) {
  1354. //
  1355. // This echo request has been sent and timed out without
  1356. // being answered. Move it to our timed out list.
  1357. //
  1358. *PrevPtr = This->Next;
  1359. This->Next = TimedOut;
  1360. TimedOut = This;
  1361. } else {
  1362. PrevPtr = &This->Next;
  1363. }
  1364. }
  1365. }
  1366. KeReleaseSpinLockFromDpcLevel(&ICMPv6EchoLock);
  1367. //
  1368. // Run through the list of timed out echoes, calling the completion
  1369. // routine on each. The completion routine is responsible for
  1370. // freeing the EchoControl block structure.
  1371. //
  1372. while (TimedOut != NULL) {
  1373. This = TimedOut;
  1374. TimedOut = This->Next;
  1375. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  1376. "ICMPv6EchoTimeout: seq number 0x%x timed out\n", This->Seq));
  1377. (*This->CompleteRoutine)(This, IP_REQ_TIMED_OUT,
  1378. &UnspecifiedAddr, 0, NULL, 0);
  1379. }
  1380. }