/* Unlink it from the list */
RemoveEntryList(CurrentEntry);
- TI_DbgPrint(DEBUG_IP, ("Freeing fragment data at (0x%X).\n", CurrentF->Data));
+ TI_DbgPrint(DEBUG_IP, ("Freeing fragment packet at (0x%X).\n", CurrentF->Packet));
/* Free the fragment data buffer */
- ExFreePoolWithTag(CurrentF->Data, FRAGMENT_DATA_TAG);
+ if (CurrentF->ReturnPacket)
+ {
+ NdisReturnPackets(&CurrentF->Packet, 1);
+ }
+ else
+ {
+ FreeNdisPacket(CurrentF->Packet);
+ }
TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF));
CurrentEntry = NextEntry;
}
+ if (IPDR->IPv4Header)
+ {
+ TI_DbgPrint(DEBUG_IP, ("Freeing IPDR header at (0x%X).\n", IPDR->IPv4Header));
+ ExFreePoolWithTag(IPDR->IPv4Header, PACKET_BUFFER_TAG);
+ }
+
TI_DbgPrint(DEBUG_IP, ("Freeing IPDR data at (0x%X).\n", IPDR));
ExFreeToNPagedLookasideList(&IPDRList, IPDR);
*/
{
PLIST_ENTRY CurrentEntry;
- PIP_FRAGMENT Current;
- PVOID Data;
+ PIP_FRAGMENT Fragment;
+ PCHAR Data;
+
+ PAGED_CODE();
TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR));
TI_DbgPrint(DEBUG_IP, ("IPDR->HeaderSize = %d\n", IPDR->HeaderSize));
TI_DbgPrint(DEBUG_IP, ("IPDR->DataSize = %d\n", IPDR->DataSize));
- TI_DbgPrint(DEBUG_IP, ("Fragment header:\n"));
- //OskitDumpBuffer((PCHAR)IPDR->IPv4Header, IPDR->HeaderSize);
-
IPPacket->TotalSize = IPDR->HeaderSize + IPDR->DataSize;
- IPPacket->ContigSize = IPPacket->TotalSize;
IPPacket->HeaderSize = IPDR->HeaderSize;
- /*IPPacket->Position = IPDR->HeaderSize;*/
RtlCopyMemory(&IPPacket->SrcAddr, &IPDR->SrcAddr, sizeof(IP_ADDRESS));
RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS));
/* Allocate space for full IP datagram */
- IPPacket->Header = ExAllocatePoolWithTag(NonPagedPool, IPPacket->TotalSize, PACKET_BUFFER_TAG);
+ IPPacket->Header = ExAllocatePoolWithTag(PagedPool, IPPacket->TotalSize, PACKET_BUFFER_TAG);
if (!IPPacket->Header) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
(*IPPacket->Free)(IPPacket);
return FALSE;
}
+ IPPacket->MappedHeader = FALSE;
/* Copy the header into the buffer */
- RtlCopyMemory(IPPacket->Header, &IPDR->IPv4Header, IPDR->HeaderSize);
+ RtlCopyMemory(IPPacket->Header, IPDR->IPv4Header, IPDR->HeaderSize);
Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPDR->HeaderSize);
IPPacket->Data = Data;
/* Copy data from all fragments into buffer */
CurrentEntry = IPDR->FragmentListHead.Flink;
while (CurrentEntry != &IPDR->FragmentListHead) {
- Current = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
-
- TI_DbgPrint(DEBUG_IP, ("Copying (%d) bytes of fragment data from (0x%X) to offset (%d).\n",
- Current->Size, Data, Current->Offset));
- /* Copy fragment data to the destination buffer at the correct offset */
- RtlCopyMemory((PVOID)((ULONG_PTR)Data + Current->Offset),
- Current->Data,
- Current->Size);
- //OskitDumpBuffer( Data, Current->Offset + Current->Size );
+ Fragment = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
+
+ /* Copy fragment data into datagram buffer */
+ CopyPacketToBuffer(Data + Fragment->Offset,
+ Fragment->Packet,
+ Fragment->PacketOffset,
+ Fragment->Size);
+
CurrentEntry = CurrentEntry->Flink;
}
TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n"));
/* We have a reassembly structure */
TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);
+
+ /* Reset the timeout since we received a fragment */
+ IPDR->TimeoutCount = 0;
} else {
TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n"));
/* 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));
+ IPDR->IPv4Header = ExAllocatePoolWithTag(NonPagedPool,
+ IPPacket->HeaderSize,
+ PACKET_BUFFER_TAG);
+ if (!IPDR->IPv4Header)
+ {
+ Cleanup(&IPDR->Lock, OldIrql, IPDR);
+ return;
+ }
+
+ RtlCopyMemory(IPDR->IPv4Header, IPPacket->Header, IPPacket->HeaderSize);
+ IPDR->HeaderSize = IPPacket->HeaderSize;
+
+ 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
TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));
Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize;
- Fragment->Data = ExAllocatePoolWithTag(NonPagedPool, Fragment->Size, FRAGMENT_DATA_TAG);
- if (!Fragment->Data) {
- /* We don't have the resources to process this packet, discard it */
- ExFreeToNPagedLookasideList(&IPFragmentList, Fragment);
- Cleanup(&IPDR->Lock, OldIrql, IPDR);
- 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->HeaderSize,
- Fragment->Size);
+ Fragment->Packet = IPPacket->NdisPacket;
+ Fragment->ReturnPacket = IPPacket->ReturnPacket;
+ Fragment->PacketOffset = IPPacket->Position + IPPacket->HeaderSize;
Fragment->Offset = FragFirst;
+ /* Disassociate the NDIS packet so it isn't freed upon return from IPReceive() */
+ IPPacket->NdisPacket = NULL;
+
/* If this is the last fragment, compute and save the datagram data size */
if (!MoreFragments)
IPDR->DataSize = FragFirst + Fragment->Size;
Assemble the datagram and pass it to an upper layer protocol */
TI_DbgPrint(DEBUG_IP, ("Complete datagram received.\n"));
+
+ RemoveIPDR(IPDR);
+ TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
/* FIXME: Assumes IPv4 */
IPInitializePacket(&Datagram, IP_ADDRESS_V4);
Success = ReassembleDatagram(&Datagram, IPDR);
- RemoveIPDR(IPDR);
- TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
-
FreeIPDR(IPDR);
if (!Success)
/* Give the packet to the protocol dispatcher */
IPDispatchProtocol(IF, &Datagram);
- IF->Stats.InBytes += Datagram.TotalSize;
-
/* We're done with this datagram */
- ExFreePoolWithTag(Datagram.Header, PACKET_BUFFER_TAG);
TI_DbgPrint(MAX_TRACE, ("Freeing datagram at (0x%X).\n", Datagram));
- (*Datagram.Free)(&Datagram);
+ Datagram.Free(&Datagram);
} else
TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
}
* IPPacket = Pointer to IP packet
*/
{
+ UCHAR FirstByte;
+ ULONG BytesCopied;
+
TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n"));
+
+ /* Read in the first IP header byte for size information */
+ BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
+ IPPacket->NdisPacket,
+ IPPacket->Position,
+ sizeof(UCHAR));
+ if (BytesCopied != sizeof(UCHAR))
+ {
+ TI_DbgPrint(MIN_TRACE, ("Failed to copy in first byte\n"));
+ /* Discard packet */
+ return;
+ }
- IPPacket->HeaderSize = (((PIPv4_HEADER)IPPacket->Header)->VerIHL & 0x0F) << 2;
+ IPPacket->HeaderSize = (FirstByte & 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",
+ TI_DbgPrint(MIN_TRACE, ("Datagram received with incorrect header size (%d).\n",
IPPacket->HeaderSize));
- /* Discard packet */
- return;
+ /* Discard packet */
+ return;
+ }
+
+ /* This is freed by IPPacket->Free() */
+ IPPacket->Header = ExAllocatePoolWithTag(NonPagedPool,
+ IPPacket->HeaderSize,
+ PACKET_BUFFER_TAG);
+ if (!IPPacket->Header)
+ {
+ TI_DbgPrint(MIN_TRACE, ("No resources to allocate header\n"));
+ /* Discard packet */
+ return;
+ }
+
+ IPPacket->MappedHeader = FALSE;
+
+ BytesCopied = CopyPacketToBuffer((PCHAR)IPPacket->Header,
+ IPPacket->NdisPacket,
+ IPPacket->Position,
+ IPPacket->HeaderSize);
+ if (BytesCopied != IPPacket->HeaderSize)
+ {
+ TI_DbgPrint(MIN_TRACE, ("Failed to copy in header\n"));
+ /* 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",
+ TI_DbgPrint(MIN_TRACE, ("Datagram received with bad checksum. Checksum field (0x%X)\n",
WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum)));
- /* Discard packet */
- return;
+ /* 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);
+ IPPacket->Position));
/* 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
}
* IPPacket = Pointer to IP packet
*/
{
- UINT Version;
-
- /* Check that IP header has a supported version */
- Version = (((PIPv4_HEADER)IPPacket->Header)->VerIHL >> 4);
+ UCHAR FirstByte;
+ UINT Version, BytesCopied;
+
+ /* Read in the first IP header byte for version information */
+ BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
+ IPPacket->NdisPacket,
+ IPPacket->Position,
+ sizeof(UCHAR));
+ if (BytesCopied != sizeof(UCHAR))
+ {
+ TI_DbgPrint(MIN_TRACE, ("Failed to copy in first byte\n"));
+ IPPacket->Free(IPPacket);
+ return;
+ }
- 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"));
- break;
- default:
- TI_DbgPrint(MIN_TRACE, ("Datagram has an unsupported IP version %d.\n", Version));
- break;
- }
+ /* Check that IP header has a supported version */
+ Version = (FirstByte >> 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"));
+ break;
+ default:
+ TI_DbgPrint(MIN_TRACE, ("Datagram has an unsupported IP version %d.\n", Version));
+ break;
+ }
- IPPacket->Free(IPPacket);
+ IPPacket->Free(IPPacket);
}
/* EOF */