Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentransmit.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
1.7.6.1
|