mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 10:01:43 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
247
sdk/lib/drivers/ip/network/transmit.c
Normal file
247
sdk/lib/drivers/ip/network/transmit.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS TCP/IP protocol driver
|
||||
* FILE: network/transmit.c
|
||||
* PURPOSE: Internet Protocol transmit routines
|
||||
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||
* REVISIONS:
|
||||
* CSH 01/08-2000 Created
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
BOOLEAN PrepareNextFragment(PIPFRAGMENT_CONTEXT IFC);
|
||||
NTSTATUS IPSendFragment(PNDIS_PACKET NdisPacket,
|
||||
PNEIGHBOR_CACHE_ENTRY NCE,
|
||||
PIPFRAGMENT_CONTEXT IFC);
|
||||
|
||||
VOID IPSendComplete
|
||||
(PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus)
|
||||
/*
|
||||
* FUNCTION: IP datagram fragment send completion handler
|
||||
* ARGUMENTS:
|
||||
* Context = Pointer to context information (IP_INTERFACE)
|
||||
* Packet = Pointer to NDIS packet that was sent
|
||||
* NdisStatus = NDIS status of operation
|
||||
* NOTES:
|
||||
* This routine is called when an IP datagram fragment has been sent
|
||||
*/
|
||||
{
|
||||
PIPFRAGMENT_CONTEXT IFC = (PIPFRAGMENT_CONTEXT)Context;
|
||||
|
||||
TI_DbgPrint
|
||||
(MAX_TRACE,
|
||||
("Called. Context (0x%X) NdisPacket (0x%X) NdisStatus (0x%X)\n",
|
||||
Context, NdisPacket, NdisStatus));
|
||||
|
||||
IFC->Status = NdisStatus;
|
||||
KeSetEvent(&IFC->Event, 0, FALSE);
|
||||
}
|
||||
|
||||
NTSTATUS IPSendFragment(
|
||||
PNDIS_PACKET NdisPacket,
|
||||
PNEIGHBOR_CACHE_ENTRY NCE,
|
||||
PIPFRAGMENT_CONTEXT IFC)
|
||||
/*
|
||||
* FUNCTION: Sends an IP datagram fragment to a neighbor
|
||||
* ARGUMENTS:
|
||||
* NdisPacket = Pointer to an NDIS packet containing fragment
|
||||
* NCE = Pointer to NCE for first hop to destination
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
* NOTES:
|
||||
* Lowest level IP send routine
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(MAX_TRACE, ("Called. NdisPacket (0x%X) NCE (0x%X).\n", NdisPacket, NCE));
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("NCE->State = %d.\n", NCE->State));
|
||||
return NBQueuePacket(NCE, NdisPacket, IPSendComplete, IFC);
|
||||
}
|
||||
|
||||
BOOLEAN PrepareNextFragment(
|
||||
PIPFRAGMENT_CONTEXT IFC)
|
||||
/*
|
||||
* FUNCTION: Prepares the next fragment of an IP datagram for transmission
|
||||
* ARGUMENTS:
|
||||
* IFC = Pointer to IP fragment context
|
||||
* RETURNS:
|
||||
* TRUE if a fragment was prepared for transmission, FALSE if
|
||||
* there are no more fragments to send
|
||||
*/
|
||||
{
|
||||
UINT MaxData;
|
||||
UINT DataSize;
|
||||
PIPv4_HEADER Header;
|
||||
BOOLEAN MoreFragments;
|
||||
USHORT FragOfs;
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Called. IFC (0x%X)\n", IFC));
|
||||
|
||||
if (IFC->BytesLeft > 0) {
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Preparing 1 fragment.\n"));
|
||||
|
||||
MaxData = IFC->PathMTU - IFC->HeaderSize;
|
||||
/* Make fragment a multiplum of 64bit */
|
||||
MaxData -= MaxData % 8;
|
||||
if (IFC->BytesLeft > MaxData) {
|
||||
DataSize = MaxData;
|
||||
MoreFragments = TRUE;
|
||||
} else {
|
||||
DataSize = IFC->BytesLeft;
|
||||
MoreFragments = FALSE;
|
||||
}
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("Copying data from %x to %x (%d)\n",
|
||||
IFC->DatagramData, IFC->Data, DataSize));
|
||||
|
||||
RtlCopyMemory(IFC->Data, IFC->DatagramData, DataSize); // SAFE
|
||||
|
||||
/* Fragment offset is in 8 byte blocks */
|
||||
FragOfs = (USHORT)(IFC->Position / 8);
|
||||
|
||||
if (MoreFragments)
|
||||
FragOfs |= IPv4_MF_MASK;
|
||||
else
|
||||
FragOfs &= ~IPv4_MF_MASK;
|
||||
|
||||
Header = IFC->Header;
|
||||
Header->FlagsFragOfs = WH2N(FragOfs);
|
||||
Header->TotalLength = WH2N((USHORT)(DataSize + IFC->HeaderSize));
|
||||
|
||||
/* FIXME: Handle options */
|
||||
|
||||
/* Calculate checksum of IP header */
|
||||
Header->Checksum = 0;
|
||||
Header->Checksum = (USHORT)IPv4Checksum(Header, IFC->HeaderSize, 0);
|
||||
TI_DbgPrint(MID_TRACE,("IP Check: %x\n", Header->Checksum));
|
||||
|
||||
/* Update pointers */
|
||||
IFC->DatagramData = (PVOID)((ULONG_PTR)IFC->DatagramData + DataSize);
|
||||
IFC->Position += DataSize;
|
||||
IFC->BytesLeft -= DataSize;
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
TI_DbgPrint(MAX_TRACE, ("No more fragments.\n"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS SendFragments(
|
||||
PIP_PACKET IPPacket,
|
||||
PNEIGHBOR_CACHE_ENTRY NCE,
|
||||
UINT PathMTU)
|
||||
/*
|
||||
* FUNCTION: Fragments and sends the first fragment of an IP datagram
|
||||
* ARGUMENTS:
|
||||
* IPPacket = Pointer to an IP packet
|
||||
* NCE = Pointer to NCE for first hop to destination
|
||||
* PathMTU = Size of Maximum Transmission Unit of path
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
* NOTES:
|
||||
* IP datagram is larger than PathMTU when this is called
|
||||
*/
|
||||
{
|
||||
PIPFRAGMENT_CONTEXT IFC;
|
||||
NDIS_STATUS NdisStatus;
|
||||
PVOID Data;
|
||||
UINT BufferSize = PathMTU, InSize;
|
||||
PCHAR InData;
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X) PathMTU (%d).\n",
|
||||
IPPacket, NCE, PathMTU));
|
||||
|
||||
/* Make a smaller buffer if we will only send one fragment */
|
||||
GetDataPtr( IPPacket->NdisPacket, IPPacket->Position, &InData, &InSize );
|
||||
if( InSize < BufferSize ) BufferSize = InSize;
|
||||
|
||||
TI_DbgPrint(MAX_TRACE, ("Fragment buffer is %d bytes\n", BufferSize));
|
||||
|
||||
IFC = ExAllocatePoolWithTag(NonPagedPool, sizeof(IPFRAGMENT_CONTEXT), IFC_TAG);
|
||||
if (IFC == NULL)
|
||||
{
|
||||
IPPacket->Free(IPPacket);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Allocate NDIS packet */
|
||||
NdisStatus = AllocatePacketWithBuffer
|
||||
( &IFC->NdisPacket, NULL, BufferSize );
|
||||
|
||||
if( !NT_SUCCESS(NdisStatus) ) {
|
||||
IPPacket->Free(IPPacket);
|
||||
ExFreePoolWithTag( IFC, IFC_TAG );
|
||||
return NdisStatus;
|
||||
}
|
||||
|
||||
GetDataPtr( IFC->NdisPacket, 0, (PCHAR *)&Data, &InSize );
|
||||
|
||||
IFC->Header = ((PCHAR)Data);
|
||||
IFC->Datagram = IPPacket->NdisPacket;
|
||||
IFC->DatagramData = ((PCHAR)IPPacket->Header) + IPPacket->HeaderSize;
|
||||
IFC->HeaderSize = IPPacket->HeaderSize;
|
||||
IFC->PathMTU = PathMTU;
|
||||
IFC->NCE = NCE;
|
||||
IFC->Position = 0;
|
||||
IFC->BytesLeft = IPPacket->TotalSize - IPPacket->HeaderSize;
|
||||
IFC->Data = (PVOID)((ULONG_PTR)IFC->Header + IPPacket->HeaderSize);
|
||||
KeInitializeEvent(&IFC->Event, NotificationEvent, FALSE);
|
||||
|
||||
TI_DbgPrint(MID_TRACE,("Copying header from %x to %x (%d)\n",
|
||||
IPPacket->Header, IFC->Header,
|
||||
IPPacket->HeaderSize));
|
||||
|
||||
RtlCopyMemory( IFC->Header, IPPacket->Header, IPPacket->HeaderSize );
|
||||
|
||||
while (PrepareNextFragment(IFC))
|
||||
{
|
||||
NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC);
|
||||
if (NT_SUCCESS(NdisStatus))
|
||||
{
|
||||
KeWaitForSingleObject(&IFC->Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
NdisStatus = IFC->Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(NdisStatus))
|
||||
break;
|
||||
}
|
||||
|
||||
FreeNdisPacket(IFC->NdisPacket);
|
||||
ExFreePoolWithTag(IFC, IFC_TAG);
|
||||
IPPacket->Free(IPPacket);
|
||||
|
||||
return NdisStatus;
|
||||
}
|
||||
|
||||
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE)
|
||||
/*
|
||||
* FUNCTION: Sends an IP datagram to a remote address
|
||||
* ARGUMENTS:
|
||||
* IPPacket = Pointer to an IP packet
|
||||
* RCN = Pointer to route cache node
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
* NOTES:
|
||||
* This is the highest level IP send routine. It possibly breaks the packet
|
||||
* into two or more fragments before passing it on to the next lower level
|
||||
* send routine (IPSendFragment)
|
||||
*/
|
||||
{
|
||||
TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X)\n", IPPacket, NCE));
|
||||
|
||||
DISPLAY_IP_PACKET(IPPacket);
|
||||
|
||||
/* Fetch path MTU now, because it may change */
|
||||
TI_DbgPrint(MID_TRACE,("PathMTU: %d\n", NCE->Interface->MTU));
|
||||
|
||||
return SendFragments(IPPacket, NCE, NCE->Interface->MTU);
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue