ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

transmit.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS TCP/IP protocol driver
00004  * FILE:        network/transmit.c
00005  * PURPOSE:     Internet Protocol transmit routines
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  * REVISIONS:
00008  *   CSH 01/08-2000 Created
00009  */
00010 
00011 #include "precomp.h"
00012 
00013 BOOLEAN PrepareNextFragment(PIPFRAGMENT_CONTEXT IFC);
00014 NTSTATUS IPSendFragment(PNDIS_PACKET NdisPacket,
00015             PNEIGHBOR_CACHE_ENTRY NCE,
00016             PIPFRAGMENT_CONTEXT IFC);
00017 
00018 VOID IPSendComplete
00019 (PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus)
00020 /*
00021  * FUNCTION: IP datagram fragment send completion handler
00022  * ARGUMENTS:
00023  *     Context    = Pointer to context information (IP_INTERFACE)
00024  *     Packet     = Pointer to NDIS packet that was sent
00025  *     NdisStatus = NDIS status of operation
00026  * NOTES:
00027  *    This routine is called when an IP datagram fragment has been sent
00028  */
00029 {
00030     PIPFRAGMENT_CONTEXT IFC = (PIPFRAGMENT_CONTEXT)Context;
00031 
00032     TI_DbgPrint
00033     (MAX_TRACE,
00034      ("Called. Context (0x%X)  NdisPacket (0x%X)  NdisStatus (0x%X)\n",
00035       Context, NdisPacket, NdisStatus));
00036       
00037     IFC->Status = NdisStatus;
00038     KeSetEvent(&IFC->Event, 0, FALSE);
00039 }
00040 
00041 NTSTATUS IPSendFragment(
00042     PNDIS_PACKET NdisPacket,
00043     PNEIGHBOR_CACHE_ENTRY NCE,
00044     PIPFRAGMENT_CONTEXT IFC)
00045 /*
00046  * FUNCTION: Sends an IP datagram fragment to a neighbor
00047  * ARGUMENTS:
00048  *     NdisPacket = Pointer to an NDIS packet containing fragment
00049  *     NCE        = Pointer to NCE for first hop to destination
00050  * RETURNS:
00051  *     Status of operation
00052  * NOTES:
00053  *     Lowest level IP send routine
00054  */
00055 {
00056     TI_DbgPrint(MAX_TRACE, ("Called. NdisPacket (0x%X)  NCE (0x%X).\n", NdisPacket, NCE));
00057 
00058     TI_DbgPrint(MAX_TRACE, ("NCE->State = %d.\n", NCE->State));
00059     return NBQueuePacket(NCE, NdisPacket, IPSendComplete, IFC);
00060 }
00061 
00062 BOOLEAN PrepareNextFragment(
00063     PIPFRAGMENT_CONTEXT IFC)
00064 /*
00065  * FUNCTION: Prepares the next fragment of an IP datagram for transmission
00066  * ARGUMENTS:
00067  *     IFC = Pointer to IP fragment context
00068  * RETURNS:
00069  *     TRUE if a fragment was prepared for transmission, FALSE if
00070  *     there are no more fragments to send
00071  */
00072 {
00073     UINT MaxData;
00074     UINT DataSize;
00075     PIPv4_HEADER Header;
00076     BOOLEAN MoreFragments;
00077     USHORT FragOfs;
00078 
00079     TI_DbgPrint(MAX_TRACE, ("Called. IFC (0x%X)\n", IFC));
00080 
00081     if (IFC->BytesLeft > 0) {
00082 
00083         TI_DbgPrint(MAX_TRACE, ("Preparing 1 fragment.\n"));
00084 
00085         MaxData  = IFC->PathMTU - IFC->HeaderSize;
00086         /* Make fragment a multiplum of 64bit */
00087         MaxData -= MaxData % 8;
00088         if (IFC->BytesLeft > MaxData) {
00089             DataSize      = MaxData;
00090             MoreFragments = TRUE;
00091         } else {
00092             DataSize      = IFC->BytesLeft;
00093             MoreFragments = FALSE;
00094         }
00095 
00096     TI_DbgPrint(MID_TRACE,("Copying data from %x to %x (%d)\n",
00097                    IFC->DatagramData, IFC->Data, DataSize));
00098 
00099         RtlCopyMemory(IFC->Data, IFC->DatagramData, DataSize); // SAFE
00100 
00101         /* Fragment offset is in 8 byte blocks */
00102         FragOfs = (USHORT)(IFC->Position / 8);
00103 
00104         if (MoreFragments)
00105             FragOfs |= IPv4_MF_MASK;
00106         else
00107             FragOfs &= ~IPv4_MF_MASK;
00108 
00109         Header = IFC->Header;
00110         Header->FlagsFragOfs = WH2N(FragOfs);
00111         Header->TotalLength = WH2N((USHORT)(DataSize + IFC->HeaderSize));
00112 
00113         /* FIXME: Handle options */
00114 
00115         /* Calculate checksum of IP header */
00116         Header->Checksum = 0;
00117         Header->Checksum = (USHORT)IPv4Checksum(Header, IFC->HeaderSize, 0);
00118     TI_DbgPrint(MID_TRACE,("IP Check: %x\n", Header->Checksum));
00119 
00120         /* Update pointers */
00121         IFC->DatagramData = (PVOID)((ULONG_PTR)IFC->DatagramData + DataSize);
00122         IFC->Position  += DataSize;
00123         IFC->BytesLeft -= DataSize;
00124 
00125         return TRUE;
00126     } else {
00127         TI_DbgPrint(MAX_TRACE, ("No more fragments.\n"));
00128         return FALSE;
00129     }
00130 }
00131 
00132 NTSTATUS SendFragments(
00133     PIP_PACKET IPPacket,
00134     PNEIGHBOR_CACHE_ENTRY NCE,
00135     UINT PathMTU)
00136 /*
00137  * FUNCTION: Fragments and sends the first fragment of an IP datagram
00138  * ARGUMENTS:
00139  *     IPPacket  = Pointer to an IP packet
00140  *     NCE       = Pointer to NCE for first hop to destination
00141  *     PathMTU   = Size of Maximum Transmission Unit of path
00142  * RETURNS:
00143  *     Status of operation
00144  * NOTES:
00145  *     IP datagram is larger than PathMTU when this is called
00146  */
00147 {
00148     PIPFRAGMENT_CONTEXT IFC;
00149     NDIS_STATUS NdisStatus;
00150     PVOID Data;
00151     UINT BufferSize = PathMTU, InSize;
00152     PCHAR InData;
00153 
00154     TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X)  NCE (0x%X)  PathMTU (%d).\n",
00155         IPPacket, NCE, PathMTU));
00156 
00157     /* Make a smaller buffer if we will only send one fragment */
00158     GetDataPtr( IPPacket->NdisPacket, IPPacket->Position, &InData, &InSize );
00159     if( InSize < BufferSize ) BufferSize = InSize;
00160 
00161     TI_DbgPrint(MAX_TRACE, ("Fragment buffer is %d bytes\n", BufferSize));
00162 
00163     IFC = ExAllocatePoolWithTag(NonPagedPool, sizeof(IPFRAGMENT_CONTEXT), IFC_TAG);
00164     if (IFC == NULL)
00165     {
00166         IPPacket->Free(IPPacket);
00167         return STATUS_INSUFFICIENT_RESOURCES;
00168     }
00169 
00170     /* Allocate NDIS packet */
00171     NdisStatus = AllocatePacketWithBuffer
00172     ( &IFC->NdisPacket, NULL, BufferSize );
00173 
00174     if( !NT_SUCCESS(NdisStatus) ) {
00175         IPPacket->Free(IPPacket);
00176         ExFreePoolWithTag( IFC, IFC_TAG );
00177         return NdisStatus;
00178     }
00179 
00180     GetDataPtr( IFC->NdisPacket, 0, (PCHAR *)&Data, &InSize );
00181 
00182     IFC->Header       = ((PCHAR)Data);
00183     IFC->Datagram     = IPPacket->NdisPacket;
00184     IFC->DatagramData = ((PCHAR)IPPacket->Header) + IPPacket->HeaderSize;
00185     IFC->HeaderSize   = IPPacket->HeaderSize;
00186     IFC->PathMTU      = PathMTU;
00187     IFC->NCE          = NCE;
00188     IFC->Position     = 0;
00189     IFC->BytesLeft    = IPPacket->TotalSize - IPPacket->HeaderSize;
00190     IFC->Data         = (PVOID)((ULONG_PTR)IFC->Header + IPPacket->HeaderSize);
00191     KeInitializeEvent(&IFC->Event, NotificationEvent, FALSE);
00192 
00193     TI_DbgPrint(MID_TRACE,("Copying header from %x to %x (%d)\n",
00194                IPPacket->Header, IFC->Header,
00195                IPPacket->HeaderSize));
00196 
00197     RtlCopyMemory( IFC->Header, IPPacket->Header, IPPacket->HeaderSize );
00198 
00199     while (PrepareNextFragment(IFC))
00200     {
00201         NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC);
00202         if (NT_SUCCESS(NdisStatus))
00203         {
00204             KeWaitForSingleObject(&IFC->Event,
00205                                   Executive,
00206                                   KernelMode,
00207                                   FALSE,
00208                                   NULL);
00209             NdisStatus = IFC->Status;
00210         }
00211 
00212         if (!NT_SUCCESS(NdisStatus))
00213             break;
00214     }
00215 
00216     FreeNdisPacket(IFC->NdisPacket);
00217     ExFreePoolWithTag(IFC, IFC_TAG);
00218     IPPacket->Free(IPPacket);
00219 
00220     return NdisStatus;
00221 }
00222 
00223 NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE)
00224 /*
00225  * FUNCTION: Sends an IP datagram to a remote address
00226  * ARGUMENTS:
00227  *     IPPacket = Pointer to an IP packet
00228  *     RCN      = Pointer to route cache node
00229  * RETURNS:
00230  *     Status of operation
00231  * NOTES:
00232  *     This is the highest level IP send routine. It possibly breaks the packet
00233  *     into two or more fragments before passing it on to the next lower level
00234  *     send routine (IPSendFragment)
00235  */
00236 {
00237     TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X)  NCE (0x%X)\n", IPPacket, NCE));
00238 
00239     DISPLAY_IP_PACKET(IPPacket);
00240 
00241     /* Fetch path MTU now, because it may change */
00242     TI_DbgPrint(MID_TRACE,("PathMTU: %d\n", NCE->Interface->MTU));
00243 
00244     return SendFragments(IPPacket, NCE, NCE->Interface->MTU);
00245 }
00246 
00247 /* EOF */

Generated on Sat May 26 2012 04:32:17 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.