Source code of Windows XP (NT5)
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.

695 lines
24 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. // Raw IP interface code. This file contains the code for the raw IP
  14. // interface functions, principally send and receive datagram.
  15. //
  16. #include "oscfg.h"
  17. #include "ndis.h"
  18. #include "ip6imp.h"
  19. #include "ip6def.h"
  20. #include "tdi.h"
  21. #include "tdistat.h"
  22. #include "tdint.h"
  23. #include "tdistat.h"
  24. #include "queue.h"
  25. #include "transprt.h"
  26. #include "addr.h"
  27. #include "raw.h"
  28. #include "info.h"
  29. #include "route.h"
  30. #include "security.h"
  31. #define NO_TCP_DEFS 1
  32. #include "tcpdeb.h"
  33. //
  34. // REVIEW: Shouldn't this be in an include file somewhere?
  35. //
  36. #ifdef POOL_TAGGING
  37. #ifdef ExAllocatePool
  38. #undef ExAllocatePool
  39. #endif
  40. #define ExAllocatePool(type, size) ExAllocatePoolWithTag(type, size, '6WAR')
  41. #endif // POOL_TAGGING
  42. extern KSPIN_LOCK AddrObjTableLock;
  43. //* RawSend - Send a raw datagram.
  44. //
  45. // The real send datagram routine. We assume that the busy bit is
  46. // set on the input AddrObj, and that the address of the SendReq
  47. // has been verified.
  48. //
  49. // We start by sending the input datagram, and we loop until there's
  50. // nothing left on the send queue.
  51. //
  52. void // Returns: Nothing.
  53. RawSend(
  54. AddrObj *SrcAO, // Address Object of endpoint doing the send.
  55. DGSendReq *SendReq) // Datagram send request describing the send.
  56. {
  57. KIRQL Irql0;
  58. RouteCacheEntry *RCE;
  59. NetTableEntryOrInterface *NTEorIF;
  60. NetTableEntry *NTE;
  61. Interface *IF;
  62. IPv6Header UNALIGNED *IP;
  63. PNDIS_PACKET Packet;
  64. PNDIS_BUFFER RawBuffer;
  65. void *Memory;
  66. IP_STATUS Status;
  67. NDIS_STATUS NdisStatus;
  68. TDI_STATUS ErrorValue;
  69. uint Offset;
  70. uint HeaderLength;
  71. int Hops;
  72. CHECK_STRUCT(SrcAO, ao);
  73. ASSERT(SrcAO->ao_usecnt != 0);
  74. //
  75. // Loop while we have something to send, and can get
  76. // the resources to send it.
  77. //
  78. for (;;) {
  79. CHECK_STRUCT(SendReq, dsr);
  80. //
  81. // Determine NTE to send on (if user cares).
  82. // We do this prior to allocating packet header buffers so
  83. // we know how much room to leave for the link-level header.
  84. //
  85. if (!IsUnspecified(&SrcAO->ao_addr)) {
  86. //
  87. // We need to get the NTE of this bound address.
  88. //
  89. NTE = FindNetworkWithAddress(&SrcAO->ao_addr, SrcAO->ao_scope_id);
  90. if (NTE == NULL) {
  91. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_USER_ERROR,
  92. "RawSend: Bad source address\n"));
  93. ErrorValue = TDI_INVALID_REQUEST;
  94. ReturnError:
  95. //
  96. // If possible, complete the request with an error.
  97. // Free the request structure.
  98. //
  99. if (SendReq->dsr_rtn != NULL)
  100. (*SendReq->dsr_rtn)(SendReq->dsr_context,
  101. ErrorValue, 0);
  102. KeAcquireSpinLock(&DGSendReqLock, &Irql0);
  103. FreeDGSendReq(SendReq);
  104. KeReleaseSpinLock(&DGSendReqLock, Irql0);
  105. goto SendComplete;
  106. }
  107. } else {
  108. //
  109. // We are not binding to any address.
  110. //
  111. NTE = NULL;
  112. }
  113. NTEorIF = CastFromNTE(NTE);
  114. //
  115. // If this is a multicast packet, check if the application
  116. // has specified an interface. Note that ao_mcast_if
  117. // overrides ao_addr if both are specified and they conflict.
  118. //
  119. if (IsMulticast(&SendReq->dsr_addr) && (SrcAO->ao_mcast_if != 0) &&
  120. ((NTE == NULL) || (NTE->IF->Index != SrcAO->ao_mcast_if))) {
  121. if (NTE != NULL) {
  122. ReleaseNTE(NTE);
  123. NTE = NULL;
  124. }
  125. IF = FindInterfaceFromIndex(SrcAO->ao_mcast_if);
  126. if (IF == NULL) {
  127. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_USER_ERROR,
  128. "RawSend: Bad mcast interface number\n"));
  129. ErrorValue = TDI_INVALID_REQUEST;
  130. goto ReturnError;
  131. }
  132. NTEorIF = CastFromIF(IF);
  133. } else {
  134. IF = NULL;
  135. }
  136. //
  137. // Get the route.
  138. //
  139. Status = RouteToDestination(&SendReq->dsr_addr, SendReq->dsr_scope_id,
  140. NTEorIF, RTD_FLAG_NORMAL, &RCE);
  141. if (IF != NULL)
  142. ReleaseIF(IF);
  143. if (Status != IP_SUCCESS) {
  144. //
  145. // Failed to get a route to the destination. Error out.
  146. //
  147. if ((Status == IP_PARAMETER_PROBLEM) ||
  148. (Status == IP_BAD_ROUTE))
  149. ErrorValue = TDI_BAD_ADDR;
  150. else if (Status == IP_NO_RESOURCES)
  151. ErrorValue = TDI_NO_RESOURCES;
  152. else
  153. ErrorValue = TDI_DEST_UNREACHABLE;
  154. if (NTE != NULL)
  155. ReleaseNTE(NTE);
  156. goto ReturnError;
  157. }
  158. //
  159. // If our address object didn't have a source address,
  160. // take the one of the sending net from the RCE.
  161. // Otherwise, use address from AO.
  162. //
  163. if (NTE == NULL) {
  164. NTE = RCE->NTE;
  165. AddRefNTE(NTE);
  166. }
  167. //
  168. // Allocate a packet header to anchor the buffer list.
  169. //
  170. NdisAllocatePacket(&NdisStatus, &Packet, IPv6PacketPool);
  171. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  172. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  173. "RawSend: Couldn't allocate packet header!?!\n"));
  174. //
  175. // If we can't get a packet header from the pool, we push
  176. // the send request back on the queue and queue the address
  177. // object for when we get resources.
  178. //
  179. OutOfResources:
  180. ReleaseRCE(RCE);
  181. ReleaseNTE(NTE);
  182. KeAcquireSpinLock(&SrcAO->ao_lock, &Irql0);
  183. PUSHQ(&SrcAO->ao_sendq, &SendReq->dsr_q);
  184. PutPendingQ(SrcAO);
  185. KeReleaseSpinLock(&SrcAO->ao_lock, Irql0);
  186. return;
  187. }
  188. InitializeNdisPacket(Packet);
  189. PC(Packet)->CompletionHandler = DGSendComplete;
  190. PC(Packet)->CompletionData = SendReq;
  191. //
  192. // Create our header buffer.
  193. // It will contain the link-level header and possibly the
  194. // IPv6 header. The user has the option of contributing
  195. // the IPv6 header, otherwise we generate it below.
  196. //
  197. Offset = HeaderLength = RCE->NCE->IF->LinkHeaderSize;
  198. if (!AO_HDRINCL(SrcAO))
  199. HeaderLength += sizeof(*IP);
  200. if (HeaderLength > 0) {
  201. Memory = ExAllocatePool(NonPagedPool, HeaderLength);
  202. if (Memory == NULL) {
  203. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  204. "RawSend: couldn't allocate header memory!?!\n"));
  205. NdisFreePacket(Packet);
  206. goto OutOfResources;
  207. }
  208. NdisAllocateBuffer(&NdisStatus, &RawBuffer, IPv6BufferPool,
  209. Memory, HeaderLength);
  210. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  211. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  212. "RawSend: couldn't allocate buffer!?!\n"));
  213. ExFreePool(Memory);
  214. NdisFreePacket(Packet);
  215. goto OutOfResources;
  216. }
  217. //
  218. // Link the data buffers from the send request onto the buffer
  219. // chain headed by our header buffer. Then attach this chain
  220. // to the packet.
  221. //
  222. NDIS_BUFFER_LINKAGE(RawBuffer) = SendReq->dsr_buffer;
  223. NdisChainBufferAtFront(Packet, RawBuffer);
  224. }
  225. else
  226. NdisChainBufferAtFront(Packet, SendReq->dsr_buffer);
  227. //
  228. // We now have all the resources we need to send.
  229. // Prepare the actual packet.
  230. //
  231. if (!AO_HDRINCL(SrcAO)) {
  232. //
  233. // We can not allow the user to supply extension headers.
  234. // IPv6Send assumes that any extension headers are
  235. // syntactically correct and resident in the first buffer.
  236. // Currently TCPCreate prevents the user from opening raw
  237. // sockets with extension header protocols.
  238. //
  239. ASSERT(!IsExtensionHeader(SrcAO->ao_prot));
  240. //
  241. // We need to provide the IPv6 header.
  242. // Place it after the link-layer header.
  243. //
  244. IP = (IPv6Header UNALIGNED *)((uchar *)Memory + Offset);
  245. IP->VersClassFlow = IP_VERSION;
  246. IP->NextHeader = SrcAO->ao_prot;
  247. IP->Source = NTE->Address;
  248. IP->Dest = SendReq->dsr_addr;
  249. //
  250. // Apply the multicast or unicast hop limit, as appropriate.
  251. //
  252. if (IsMulticast(AlignAddr(&IP->Dest))) {
  253. //
  254. // Also disable multicast loopback, if requested.
  255. //
  256. if (! SrcAO->ao_mcast_loop)
  257. PC(Packet)->Flags |= NDIS_FLAGS_DONT_LOOPBACK;
  258. Hops = SrcAO->ao_mcast_hops;
  259. }
  260. else
  261. Hops = SrcAO->ao_ucast_hops;
  262. if (Hops != -1)
  263. IP->HopLimit = (uchar) Hops;
  264. else
  265. IP->HopLimit = (uchar) RCE->NCE->IF->CurHopLimit;
  266. //
  267. // Everything's ready. Now send the packet.
  268. //
  269. // Note that IPv6Send does not return a status code.
  270. // Instead it *always* completes the packet
  271. // with an appropriate status code.
  272. //
  273. IPv6Send(Packet, Offset, IP, SendReq->dsr_size, RCE, 0,
  274. SrcAO->ao_prot, 0, 0);
  275. }
  276. else {
  277. //
  278. // Our header buffer contains only the link-level header.
  279. // The IPv6 header and any extension headers are expected to
  280. // be provided by the user. In some cases the kernel
  281. // will attempt to access the IPv6 header so we must
  282. // ensure that the mappings exist now.
  283. //
  284. if (! MapNdisBuffers(NdisFirstBuffer(Packet))) {
  285. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NTOS_ERROR,
  286. "RawSend(%p): buffer mapping failed\n",
  287. Packet));
  288. IPv6SendComplete(NULL, Packet, IP_GENERAL_FAILURE);
  289. }
  290. else {
  291. //
  292. // Everything's ready. Now send the packet.
  293. //
  294. IPv6SendND(Packet, HeaderLength,
  295. RCE->NCE, &(RCE->NTE->Address));
  296. }
  297. }
  298. UStats.us_outdatagrams++;
  299. //
  300. // Release the route.
  301. //
  302. ReleaseRCE(RCE);
  303. ReleaseNTE(NTE);
  304. SendComplete:
  305. //
  306. // Check the send queue for more to send.
  307. //
  308. KeAcquireSpinLock(&SrcAO->ao_lock, &Irql0);
  309. if (!EMPTYQ(&SrcAO->ao_sendq)) {
  310. //
  311. // More to go. Dequeue next request and loop back to top.
  312. //
  313. DEQUEUE(&SrcAO->ao_sendq, SendReq, DGSendReq, dsr_q);
  314. KeReleaseSpinLock(&SrcAO->ao_lock, Irql0);
  315. } else {
  316. //
  317. // Nothing more to send.
  318. //
  319. CLEAR_AO_REQUEST(SrcAO, AO_SEND);
  320. KeReleaseSpinLock(&SrcAO->ao_lock, Irql0);
  321. return;
  322. }
  323. }
  324. }
  325. //* RawDeliver - Deliver a datagram to a user.
  326. //
  327. // This routine delivers a datagram to a raw user. We're called with
  328. // the AddrObj to deliver on, and with the AddrObjTable lock held.
  329. // We try to find a receive on the specified AddrObj, and if we do
  330. // we remove it and copy the data into the buffer. Otherwise we'll
  331. // call the receive datagram event handler, if there is one. If that
  332. // fails we'll discard the datagram.
  333. //
  334. void // Returns: Nothing.
  335. RawDeliver(
  336. AddrObj *RcvAO, // Address object to receive the datagram.
  337. IPv6Packet *Packet, // Packet handed up by IP.
  338. uint SrcScopeId, // Scope id for source address.
  339. KIRQL Irql0) // IRQL prior to acquiring AddrObj table lock.
  340. {
  341. Queue *CurrentQ;
  342. KIRQL Irql1;
  343. DGRcvReq *RcvReq;
  344. uint BytesTaken = 0;
  345. uchar AddressBuffer[TCP_TA_SIZE];
  346. uint RcvdSize;
  347. EventRcvBuffer *ERB = NULL;
  348. uint Position = Packet->Position;
  349. uint Length = Packet->TotalSize;
  350. CHECK_STRUCT(RcvAO, ao);
  351. KeAcquireSpinLock(&RcvAO->ao_lock, &Irql1);
  352. KeReleaseSpinLock(&AddrObjTableLock, Irql1);
  353. if (AO_VALID(RcvAO)) {
  354. CurrentQ = QHEAD(&RcvAO->ao_rcvq);
  355. // Walk the list, looking for a receive buffer that matches.
  356. while (CurrentQ != QEND(&RcvAO->ao_rcvq)) {
  357. RcvReq = QSTRUCT(DGRcvReq, CurrentQ, drr_q);
  358. CHECK_STRUCT(RcvReq, drr);
  359. //
  360. // If this request is a wildcard request (accept from anywhere),
  361. // or matches the source IP address and scope id, deliver it.
  362. //
  363. if (IsUnspecified(&RcvReq->drr_addr) ||
  364. (IP6_ADDR_EQUAL(&RcvReq->drr_addr, Packet->SrcAddr) &&
  365. (RcvReq->drr_scope_id == SrcScopeId))) {
  366. TDI_STATUS Status;
  367. // Remove this from the queue.
  368. REMOVEQ(&RcvReq->drr_q);
  369. // We're done. We can free the AddrObj lock now.
  370. KeReleaseSpinLock(&RcvAO->ao_lock, Irql0);
  371. // Copy the data, and then complete the request.
  372. RcvdSize = CopyToBufferChain(RcvReq->drr_buffer, 0,
  373. Packet->NdisPacket,
  374. Position,
  375. Packet->FlatData,
  376. MIN(Length, RcvReq->drr_size));
  377. ASSERT(RcvdSize <= RcvReq->drr_size);
  378. Status = UpdateConnInfo(RcvReq->drr_conninfo, Packet->SrcAddr,
  379. SrcScopeId, 0);
  380. UStats.us_indatagrams++;
  381. (*RcvReq->drr_rtn)(RcvReq->drr_context, Status, RcvdSize);
  382. FreeDGRcvReq(RcvReq);
  383. return; // All done.
  384. }
  385. // Not a matching request. Get the next one off the queue.
  386. CurrentQ = QNEXT(CurrentQ);
  387. }
  388. //
  389. // We've walked the list, and not found a buffer.
  390. // Call the receive handler now, if we have one.
  391. //
  392. if (RcvAO->ao_rcvdg != NULL) {
  393. PRcvDGEvent RcvEvent = RcvAO->ao_rcvdg;
  394. PVOID RcvContext = RcvAO->ao_rcvdgcontext;
  395. TDI_STATUS RcvStatus;
  396. ULONG Flags = TDI_RECEIVE_COPY_LOOKAHEAD;
  397. int BufferSize = 0;
  398. PVOID BufferToSend = NULL;
  399. uchar *CurrPosition;
  400. REF_AO(RcvAO);
  401. KeReleaseSpinLock(&RcvAO->ao_lock, Irql0);
  402. BuildTDIAddress(AddressBuffer, Packet->SrcAddr, SrcScopeId, 0);
  403. UStats.us_indatagrams++;
  404. // If the IPV6_PKTINFO or IPV6_HOPLIMIT options were set, then
  405. // create the control information to be passed to the handler.
  406. // Currently this is the only place such options are filled in,
  407. // so we just have one buffer. If other places are added in the
  408. // future, we may want to support a list or array of buffers to
  409. // copy into the user's buffer.
  410. //
  411. if (AO_PKTINFO(RcvAO)) {
  412. BufferSize += TDI_CMSG_SPACE(sizeof(IN6_PKTINFO));
  413. }
  414. if (AO_RCV_HOPLIMIT(RcvAO)) {
  415. BufferSize += TDI_CMSG_SPACE(sizeof(int));
  416. }
  417. if (BufferSize > 0) {
  418. CurrPosition = BufferToSend = ExAllocatePool(NonPagedPool,
  419. BufferSize);
  420. if (BufferToSend == NULL) {
  421. BufferSize = 0;
  422. } else {
  423. if (AO_PKTINFO(RcvAO)) {
  424. DGFillIpv6PktInfo(&Packet->IP->Dest,
  425. Packet->NTEorIF->IF->Index,
  426. &CurrPosition);
  427. // Set the receive flag so the receive handler knows
  428. // we are passing up control info.
  429. //
  430. Flags |= TDI_RECEIVE_CONTROL_INFO;
  431. }
  432. if (AO_RCV_HOPLIMIT(RcvAO)) {
  433. DGFillIpv6HopLimit(Packet->IP->HopLimit, &CurrPosition);
  434. Flags |= TDI_RECEIVE_CONTROL_INFO;
  435. }
  436. }
  437. }
  438. RcvStatus = (*RcvEvent)(RcvContext, TCP_TA_SIZE,
  439. (PTRANSPORT_ADDRESS)AddressBuffer,
  440. BufferSize, BufferToSend, Flags,
  441. Packet->ContigSize, Length, &BytesTaken,
  442. Packet->Data, &ERB);
  443. if (BufferToSend) {
  444. ExFreePool(BufferToSend);
  445. }
  446. if (RcvStatus == TDI_MORE_PROCESSING) {
  447. PIO_STACK_LOCATION IrpSp;
  448. PTDI_REQUEST_KERNEL_RECEIVEDG DatagramInformation;
  449. //
  450. // We were passed back a receive buffer. Copy the data in now.
  451. // Receive event handler can't have taken more than was in the
  452. // indicated buffer, but in debug builds we'll check this.
  453. //
  454. ASSERT(ERB != NULL);
  455. ASSERT(BytesTaken <= Packet->ContigSize);
  456. //
  457. // For NT, ERBs are really IRPs.
  458. //
  459. IrpSp = IoGetCurrentIrpStackLocation(ERB);
  460. DatagramInformation = (PTDI_REQUEST_KERNEL_RECEIVEDG)
  461. &(IrpSp->Parameters);
  462. //
  463. // Copy data to the IRP, skipping the bytes
  464. // that were already taken.
  465. //
  466. Position += BytesTaken;
  467. Length -= BytesTaken;
  468. RcvdSize = CopyToBufferChain(ERB->MdlAddress, 0,
  469. Packet->NdisPacket,
  470. Position,
  471. Packet->FlatData,
  472. Length);
  473. //
  474. // Update the return address info.
  475. //
  476. RcvStatus = UpdateConnInfo(
  477. DatagramInformation->ReturnDatagramInformation,
  478. Packet->SrcAddr, SrcScopeId, 0);
  479. //
  480. // Complete the IRP.
  481. //
  482. ERB->IoStatus.Information = RcvdSize;
  483. ERB->IoStatus.Status = RcvStatus;
  484. IoCompleteRequest(ERB, 2);
  485. } else {
  486. ASSERT((RcvStatus == TDI_SUCCESS) ||
  487. (RcvStatus == TDI_NOT_ACCEPTED));
  488. ASSERT(ERB == NULL);
  489. }
  490. DELAY_DEREF_AO(RcvAO);
  491. return;
  492. } else
  493. UStats.us_inerrors++;
  494. //
  495. // When we get here, we didn't have a buffer to put this data into.
  496. // Fall through to the return case.
  497. //
  498. } else
  499. UStats.us_inerrors++;
  500. KeReleaseSpinLock(&RcvAO->ao_lock, Irql0);
  501. }
  502. //* RawReceive - Receive a Raw datagram.
  503. //
  504. // This routine is called by IP when a Raw datagram arrives. We
  505. // lookup the protocol/address pair in our address table, and deliver
  506. // the data to any users we find.
  507. //
  508. // Note that we'll only get here if all headers in the packet
  509. // preceeding the one we're filtering on were acceptable.
  510. //
  511. // We return TRUE if we find a receiver to take the packet, FALSE otherwise.
  512. //
  513. int
  514. RawReceive(
  515. IPv6Packet *Packet, // Packet IP handed up to us.
  516. uchar Protocol) // Protocol we think we're handling.
  517. {
  518. Interface *IF = Packet->NTEorIF->IF;
  519. KIRQL OldIrql;
  520. AddrObj *ReceivingAO;
  521. AOSearchContext Search;
  522. AOMCastAddr *AMA, *PrevAMA;
  523. int ReceiverFound = FALSE;
  524. uint SrcScopeId, DestScopeId;
  525. uint Loop;
  526. //
  527. // This being the raw receive routine, we perform no checks on
  528. // the packet data.
  529. //
  530. //
  531. // Verify IPSec was performed.
  532. //
  533. if (InboundSecurityCheck(Packet, Protocol, 0, 0, IF) != TRUE) {
  534. //
  535. // No policy was found or the policy found was to drop the packet.
  536. //
  537. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_NET_ERROR,
  538. "RawReceive: IPSec Policy caused packet to be refused\n"));
  539. return FALSE; // Drop packet.
  540. }
  541. //
  542. // Set the source's scope id value as appropriate.
  543. //
  544. SrcScopeId = DetermineScopeId(Packet->SrcAddr, IF);
  545. //
  546. // At this point, we've decided it's okay to accept the packet.
  547. // Figure out who to give this packet to.
  548. //
  549. if (IsMulticast(AlignAddr(&Packet->IP->Dest))) {
  550. //
  551. // This is a multicast packet, so we need to find all interested
  552. // AddrObj's. We get the AddrObjTable lock, and then loop through
  553. // all AddrObj's and give the packet to any who are listening to
  554. // this multicast address, interface & protocol.
  555. // REVIEW: We match on interface, NOT scope id. Multicast is weird.
  556. //
  557. KeAcquireSpinLock(&AddrObjTableLock, &OldIrql);
  558. for (Loop = 0; Loop < AddrObjTableSize; Loop++) {
  559. for (ReceivingAO = AddrObjTable[Loop]; ReceivingAO != NULL;
  560. ReceivingAO = ReceivingAO->ao_next) {
  561. CHECK_STRUCT(ReceivingAO, ao);
  562. if (ReceivingAO->ao_prot != Protocol)
  563. continue;
  564. if ((AMA = FindAOMCastAddr(ReceivingAO,
  565. AlignAddr(&Packet->IP->Dest),
  566. IF->Index, &PrevAMA,
  567. FALSE)) == NULL)
  568. continue;
  569. //
  570. // We have a matching address object. Hand it the packet.
  571. //
  572. RawDeliver(ReceivingAO, Packet, SrcScopeId, OldIrql);
  573. //
  574. // RawDeliver released the AddrObjTableLock, so grab it again.
  575. //
  576. KeAcquireSpinLock(&AddrObjTableLock, &OldIrql);
  577. ReceiverFound = TRUE;
  578. }
  579. }
  580. } else {
  581. //
  582. // This is a unicast packet. Try to find some AddrObj(s) to
  583. // give it to. We deliver to all matches, not just the first.
  584. //
  585. DestScopeId = DetermineScopeId(AlignAddr(&Packet->IP->Dest), IF);
  586. KeAcquireSpinLock(&AddrObjTableLock, &OldIrql);
  587. ReceivingAO = GetFirstAddrObj(AlignAddr(&Packet->IP->Dest),
  588. DestScopeId, 0,
  589. Protocol, &Search);
  590. for (; ReceivingAO != NULL; ReceivingAO = GetNextAddrObj(&Search)) {
  591. //
  592. // We have a matching address object. Hand it the packet.
  593. //
  594. RawDeliver(ReceivingAO, Packet, SrcScopeId, OldIrql);
  595. //
  596. // RawDeliver released the AddrObjTableLock, so grab it again.
  597. //
  598. KeAcquireSpinLock(&AddrObjTableLock, &OldIrql);
  599. ReceiverFound = TRUE;
  600. }
  601. }
  602. KeReleaseSpinLock(&AddrObjTableLock, OldIrql);
  603. return ReceiverFound;
  604. }