⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 receive.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
    TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n"));

    /* We don't have a reassembly structure, create one */
    IPDR = TcpipAllocateFromNPagedLookasideList(&IPDRList);
    if (!IPDR)
      /* We don't have the resources to process this packet, discard it */
      return;

    /* Create a descriptor spanning from zero to infinity.
       Actually, we use a value slightly greater than the
       maximum number of octets an IP datagram can contain */
    Hole = CreateHoleDescriptor(0, 65536);
    if (!Hole) {
      /* We don't have the resources to process this packet, discard it */
      TcpipFreeToNPagedLookasideList(&IPDRList, IPDR);
      return;
    }
    AddrInitIPv4(&IPDR->SrcAddr, IPv4Header->SrcAddr);
    AddrInitIPv4(&IPDR->DstAddr, IPv4Header->DstAddr);
    IPDR->Id         = IPv4Header->Id;
    IPDR->Protocol   = IPv4Header->Protocol;
    InitializeListHead(&IPDR->FragmentListHead);
    InitializeListHead(&IPDR->HoleListHead);
    InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry);
    CurrentEntry = IPDR->HoleListHead.Flink;

    TcpipInitializeSpinLock(&IPDR->Lock);

    TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);

    /* Update the reassembly list */
    TcpipInterlockedInsertTailList(
	&ReassemblyListHead,
	&IPDR->ListEntry,
	&ReassemblyListLock);
  }

  FragFirst     = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_FRAGOFS_MASK) << 3;
  FragLast      = FragFirst + WN2H(IPv4Header->TotalLength);
  MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0;

  for (;;) {
    if (CurrentEntry == &IPDR->HoleListHead)
      /* No more entries */
      break;

    TI_DbgPrint(DEBUG_IP, ("Comparing Fragment (%d,%d) to Hole (%d,%d).\n",
      FragFirst, FragLast, Hole->First, Hole->Last));

    if ((FragFirst > Hole->Last) || (FragLast < Hole->First)) {
      TI_DbgPrint(MID_TRACE, ("No overlap.\n"));
      /* The fragment does not overlap with the hole, try next
         descriptor in the list */

      CurrentEntry = CurrentEntry->Flink;
      if (CurrentEntry != &IPDR->HoleListHead)
          Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
      continue;
    }

    /* The fragment overlap with the hole, unlink the descriptor */
    RemoveEntryList(CurrentEntry);

    if (FragFirst > Hole->First) {
      NewHole = CreateHoleDescriptor(Hole->First, FragLast - 1);
      if (!NewHole) {
        /* We don't have the resources to process this packet, discard it */
        Cleanup(&IPDR->Lock, OldIrql, IPDR, Hole);
        return;
      }

      /* Put the new descriptor in the list */
      InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
    }

    if ((FragLast < Hole->Last) && (MoreFragments)) {
      /* We can reuse the descriptor for the new hole */
		  Hole->First = FragLast + 1;

		  /* Put the new hole descriptor in the list */
      InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry);
    } else
      TcpipFreeToNPagedLookasideList(&IPHoleList, Hole);

    /* If this is the first fragment, save the IP header */
    if (FragFirst == 0) {
      TI_DbgPrint(DEBUG_IP, ("First fragment found. Header buffer is at (0x%X). "
        "Header size is (%d).\n", &IPDR->IPv4Header, IPPacket->HeaderSize));

      RtlCopyMemory(&IPDR->IPv4Header, IPPacket->Header, IPPacket->HeaderSize);
      IPDR->HeaderSize = IPPacket->HeaderSize;
    }

    /* Create a buffer, copy the data into it and put it
       in the fragment list */

    Fragment = TcpipAllocateFromNPagedLookasideList(&IPFragmentList);
    if (!Fragment) {
      /* We don't have the resources to process this packet, discard it */
      Cleanup(&IPDR->Lock, OldIrql, IPDR, NULL);
      return;
    }

    TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));

    Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize;
    Fragment->Data = exAllocatePool(NonPagedPool, Fragment->Size);
    if (!Fragment->Data) {
      /* We don't have the resources to process this packet, discard it */
      Cleanup(&IPDR->Lock, OldIrql, IPDR, Fragment);
      return;
    }

    /* Position here is an offset from the NdisPacket start, not the header */
    TI_DbgPrint(DEBUG_IP, ("Fragment data buffer allocated at (0x%X)  Size (%d) Pos (%d).\n",
			   Fragment->Data, Fragment->Size, IPPacket->Position));

    /* Copy datagram data into fragment buffer */
    CopyPacketToBuffer(Fragment->Data,
		       IPPacket->NdisPacket,
		       IPPacket->Position,
		       Fragment->Size);
    Fragment->Offset = FragFirst;

    /* If this is the last fragment, compute and save the datagram data size */
    if (!MoreFragments)
      IPDR->DataSize = FragFirst + Fragment->Size;

    /* Put the fragment in the list */
    InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry);
	  break;
  }

  TI_DbgPrint(DEBUG_IP, ("Done searching for hole descriptor.\n"));

  if (IsListEmpty(&IPDR->HoleListHead)) {
    /* Hole list is empty which means a complete datagram can be assembled.
       Assemble the datagram and pass it to an upper layer protocol */

    TI_DbgPrint(DEBUG_IP, ("Complete datagram received.\n"));

    Datagram = ReassembleDatagram(IPDR);

    RemoveIPDR(IPDR);
    TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);

    FreeIPDR(IPDR);

    if (!Datagram)
      /* Not enough free resources, discard the packet */
      return;

    DISPLAY_IP_PACKET(Datagram);

    /* Give the packet to the protocol dispatcher */
    IPDispatchProtocol(IF, Datagram);

    /* We're done with this datagram */
    exFreePool(Datagram->Header);
    TI_DbgPrint(MAX_TRACE, ("Freeing datagram at (0x%X).\n", Datagram));
    (*Datagram->Free)(Datagram);
  } else
    TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
}


VOID IPFreeReassemblyList(
  VOID)
/*
 * FUNCTION: Frees all IP datagram reassembly structures in the list
 */
{
  KIRQL OldIrql;
  PLIST_ENTRY CurrentEntry;
  PIPDATAGRAM_REASSEMBLY Current;

  TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql);

  CurrentEntry = ReassemblyListHead.Flink;
  while (CurrentEntry != &ReassemblyListHead) {
	  Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
    /* Unlink it from the list */
    RemoveEntryList(CurrentEntry);

    /* And free the descriptor */
    FreeIPDR(Current);

    CurrentEntry = CurrentEntry->Flink;
  }

  TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
}


VOID IPDatagramReassemblyTimeout(
  VOID)
/*
 * FUNCTION: IP datagram reassembly timeout handler
 * NOTES:
 *     This routine is called by IPTimeout to free any resources used
 *     to hold IP fragments that have taken too long to reassemble
 */
{
}

VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
/*
 * FUNCTION: Receives an IPv4 datagram (or fragment)
 * ARGUMENTS:
 *     Context  = Pointer to context information (IP_INTERFACE)
 *     IPPacket = Pointer to IP packet
 */
{
    TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n"));

    IPPacket->HeaderSize = (((PIPv4_HEADER)IPPacket->Header)->VerIHL & 0x0F) << 2;
    TI_DbgPrint(DEBUG_IP, ("IPPacket->HeaderSize = %d\n", IPPacket->HeaderSize));

    if (IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE) {
	TI_DbgPrint
	    (MIN_TRACE,
	     ("Datagram received with incorrect header size (%d).\n",
	      IPPacket->HeaderSize));
	/* Discard packet */
	return;
    }

    /* Checksum IPv4 header */
    if (!IPv4CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
	TI_DbgPrint
	    (MIN_TRACE,
	     ("Datagram received with bad checksum. Checksum field (0x%X)\n",
	      WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum)));
	/* Discard packet */
	return;
    }

    IPPacket->TotalSize = WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength);

    AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr);
    AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);

    IPPacket->Position += IPPacket->HeaderSize;
    IPPacket->Data     = (PVOID)((ULONG_PTR)IPPacket->Header + IPPacket->HeaderSize);

    TI_DbgPrint(MID_TRACE,("IPPacket->Position = %d\n",
			   IPPacket->Position));

    //OskitDumpBuffer(IPPacket->Header, IPPacket->TotalSize);

    /* FIXME: Possibly forward packets with multicast addresses */

    /* FIXME: Should we allow packets to be received on the wrong interface? */
    /* XXX Find out if this packet is destined for us */
    ProcessFragment(IF, IPPacket);
#if 0
    } else {
	/* This packet is not destined for us. If we are a router,
	   try to find a route and forward the packet */

	/* FIXME: Check if acting as a router */
	NCE = NULL;
	if (NCE) {
	    PROUTE_CACHE_NODE RCN;

	    /* FIXME: Possibly fragment datagram */
	    /* Forward the packet */
	    if(!RouteGetRouteToDestination( &IPPacket->DstAddr, NULL, &RCN ))
		IPSendDatagram(IPPacket, RCN, ReflectPacketComplete, IPPacket);
	} else {
	    TI_DbgPrint(MIN_TRACE, ("No route to destination (0x%X).\n",
				    IPPacket->DstAddr.Address.IPv4Address));

	    /* FIXME: Send ICMP error code */
	}
    }
#endif
}


VOID IPReceive( PIP_INTERFACE IF, PIP_PACKET IPPacket )
/*
 * FUNCTION: Receives an IP datagram (or fragment)
 * ARGUMENTS:
 *     IF       = Interface
 *     IPPacket = Pointer to IP packet
 */
{
  UINT Version;

  /* Check that IP header has a supported version */
  Version = (((PIPv4_HEADER)IPPacket->Header)->VerIHL >> 4);

  switch (Version) {
  case 4:
    IPPacket->Type = IP_ADDRESS_V4;
    IPv4Receive(IF, IPPacket);
    break;
  case 6:
    IPPacket->Type = IP_ADDRESS_V6;
    TI_DbgPrint(MAX_TRACE, ("Datagram of type IPv6 discarded.\n"));
    return;
  default:
	  TI_DbgPrint(MIN_TRACE, ("Datagram has an unsupported IP version %d.\n", Version));
    return;
  }
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -