ReactOS  0.4.13-dev-249-gcba1a2f
transmit.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS TCP/IP protocol driver
4  * FILE: network/transmit.c
5  * PURPOSE: Internet Protocol transmit routines
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * REVISIONS:
8  * CSH 01/08-2000 Created
9  */
10 
11 #include "precomp.h"
12 
17 
19 (PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus)
20 /*
21  * FUNCTION: IP datagram fragment send completion handler
22  * ARGUMENTS:
23  * Context = Pointer to context information (IP_INTERFACE)
24  * Packet = Pointer to NDIS packet that was sent
25  * NdisStatus = NDIS status of operation
26  * NOTES:
27  * This routine is called when an IP datagram fragment has been sent
28  */
29 {
31 
33  (MAX_TRACE,
34  ("Called. Context (0x%X) NdisPacket (0x%X) NdisStatus (0x%X)\n",
35  Context, NdisPacket, NdisStatus));
36 
37  IFC->Status = NdisStatus;
38  KeSetEvent(&IFC->Event, 0, FALSE);
39 }
40 
42  PNDIS_PACKET NdisPacket,
45 /*
46  * FUNCTION: Sends an IP datagram fragment to a neighbor
47  * ARGUMENTS:
48  * NdisPacket = Pointer to an NDIS packet containing fragment
49  * NCE = Pointer to NCE for first hop to destination
50  * RETURNS:
51  * Status of operation
52  * NOTES:
53  * Lowest level IP send routine
54  */
55 {
56  TI_DbgPrint(MAX_TRACE, ("Called. NdisPacket (0x%X) NCE (0x%X).\n", NdisPacket, NCE));
57 
58  TI_DbgPrint(MAX_TRACE, ("NCE->State = %d.\n", NCE->State));
59  return NBQueuePacket(NCE, NdisPacket, IPSendComplete, IFC);
60 }
61 
64 /*
65  * FUNCTION: Prepares the next fragment of an IP datagram for transmission
66  * ARGUMENTS:
67  * IFC = Pointer to IP fragment context
68  * RETURNS:
69  * TRUE if a fragment was prepared for transmission, FALSE if
70  * there are no more fragments to send
71  */
72 {
73  UINT MaxData;
74  UINT DataSize;
76  BOOLEAN MoreFragments;
77  USHORT FragOfs;
78 
79  TI_DbgPrint(MAX_TRACE, ("Called. IFC (0x%X)\n", IFC));
80 
81  if (IFC->BytesLeft > 0) {
82 
83  TI_DbgPrint(MAX_TRACE, ("Preparing 1 fragment.\n"));
84 
85  MaxData = IFC->PathMTU - IFC->HeaderSize;
86  /* Make fragment a multiplum of 64bit */
87  MaxData -= MaxData % 8;
88  if (IFC->BytesLeft > MaxData) {
89  DataSize = MaxData;
90  MoreFragments = TRUE;
91  } else {
92  DataSize = IFC->BytesLeft;
93  MoreFragments = FALSE;
94  }
95 
96  TI_DbgPrint(MID_TRACE,("Copying data from %x to %x (%d)\n",
97  IFC->DatagramData, IFC->Data, DataSize));
98 
99  RtlCopyMemory(IFC->Data, IFC->DatagramData, DataSize); // SAFE
100 
101  /* Fragment offset is in 8 byte blocks */
102  FragOfs = (USHORT)(IFC->Position / 8);
103 
104  if (MoreFragments)
105  FragOfs |= IPv4_MF_MASK;
106  else
107  FragOfs &= ~IPv4_MF_MASK;
108 
109  Header = IFC->Header;
110  Header->FlagsFragOfs = WH2N(FragOfs);
111  Header->TotalLength = WH2N((USHORT)(DataSize + IFC->HeaderSize));
112 
113  /* FIXME: Handle options */
114 
115  /* Calculate checksum of IP header */
116  Header->Checksum = 0;
117  Header->Checksum = (USHORT)IPv4Checksum(Header, IFC->HeaderSize, 0);
118  TI_DbgPrint(MID_TRACE,("IP Check: %x\n", Header->Checksum));
119 
120  /* Update pointers */
122  IFC->Position += DataSize;
123  IFC->BytesLeft -= DataSize;
124 
125  return TRUE;
126  } else {
127  TI_DbgPrint(MAX_TRACE, ("No more fragments.\n"));
128  return FALSE;
129  }
130 }
131 
133  PIP_PACKET IPPacket,
135  UINT PathMTU)
136 /*
137  * FUNCTION: Fragments and sends the first fragment of an IP datagram
138  * ARGUMENTS:
139  * IPPacket = Pointer to an IP packet
140  * NCE = Pointer to NCE for first hop to destination
141  * PathMTU = Size of Maximum Transmission Unit of path
142  * RETURNS:
143  * Status of operation
144  * NOTES:
145  * IP datagram is larger than PathMTU when this is called
146  */
147 {
149  NDIS_STATUS NdisStatus;
150  PVOID Data;
151  UINT BufferSize = PathMTU, InSize;
152  PCHAR InData;
153 
154  TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X) PathMTU (%d).\n",
155  IPPacket, NCE, PathMTU));
156 
157  /* Make a smaller buffer if we will only send one fragment */
158  GetDataPtr( IPPacket->NdisPacket, IPPacket->Position, &InData, &InSize );
159  if( InSize < BufferSize ) BufferSize = InSize;
160 
161  TI_DbgPrint(MAX_TRACE, ("Fragment buffer is %d bytes\n", BufferSize));
162 
164  if (IFC == NULL)
165  {
166  IPPacket->Free(IPPacket);
168  }
169 
170  /* Allocate NDIS packet */
171  NdisStatus = AllocatePacketWithBuffer
172  ( &IFC->NdisPacket, NULL, BufferSize );
173 
174  if( !NT_SUCCESS(NdisStatus) ) {
175  IPPacket->Free(IPPacket);
176  ExFreePoolWithTag( IFC, IFC_TAG );
177  return NdisStatus;
178  }
179 
180  GetDataPtr( IFC->NdisPacket, 0, (PCHAR *)&Data, &InSize );
181 
182  IFC->Header = ((PCHAR)Data);
183  IFC->Datagram = IPPacket->NdisPacket;
184  IFC->DatagramData = ((PCHAR)IPPacket->Header) + IPPacket->HeaderSize;
185  IFC->HeaderSize = IPPacket->HeaderSize;
186  IFC->PathMTU = PathMTU;
187  IFC->NCE = NCE;
188  IFC->Position = 0;
189  IFC->BytesLeft = IPPacket->TotalSize - IPPacket->HeaderSize;
190  IFC->Data = (PVOID)((ULONG_PTR)IFC->Header + IPPacket->HeaderSize);
192 
193  TI_DbgPrint(MID_TRACE,("Copying header from %x to %x (%d)\n",
194  IPPacket->Header, IFC->Header,
195  IPPacket->HeaderSize));
196 
197  RtlCopyMemory( IFC->Header, IPPacket->Header, IPPacket->HeaderSize );
198 
199  while (PrepareNextFragment(IFC))
200  {
201  NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC);
202  if (NT_SUCCESS(NdisStatus))
203  {
205  Executive,
206  KernelMode,
207  FALSE,
208  NULL);
209  NdisStatus = IFC->Status;
210  }
211 
212  if (!NT_SUCCESS(NdisStatus))
213  break;
214  }
215 
218  IPPacket->Free(IPPacket);
219 
220  return NdisStatus;
221 }
222 
224 /*
225  * FUNCTION: Sends an IP datagram to a remote address
226  * ARGUMENTS:
227  * IPPacket = Pointer to an IP packet
228  * RCN = Pointer to route cache node
229  * RETURNS:
230  * Status of operation
231  * NOTES:
232  * This is the highest level IP send routine. It possibly breaks the packet
233  * into two or more fragments before passing it on to the next lower level
234  * send routine (IPSendFragment)
235  */
236 {
237  TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X)\n", IPPacket, NCE));
238 
239  DISPLAY_IP_PACKET(IPPacket);
240 
241  /* Fetch path MTU now, because it may change */
242  TI_DbgPrint(MID_TRACE,("PathMTU: %d\n", NCE->Interface->MTU));
243 
244  return SendFragments(IPPacket, NCE, NCE->Interface->MTU);
245 }
246 
247 /* EOF */
signed char * PCHAR
Definition: retypes.h:7
NTSTATUS SendFragments(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE, UINT PathMTU)
Definition: transmit.c:132
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
#define IFC_TAG
Definition: tags.h:30
#define DISPLAY_IP_PACKET(x)
Definition: routines.h:69
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define MID_TRACE
Definition: debug.h:15
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
Definition: neighbor.h:28
void GetDataPtr(PNDIS_PACKET Packet, UINT Offset, PCHAR *DataOut, PUINT Size)
Definition: routines.c:65
LONG NTSTATUS
Definition: precomp.h:26
#define WH2N(w)
Definition: addrconv.c:40
#define FreeNdisPacket(x)
Definition: memtrack.h:8
OBJECT_FREE_ROUTINE Free
Definition: ip.h:78
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
int NDIS_STATUS
Definition: ntddndis.h:445
uint32_t ULONG_PTR
Definition: typedefs.h:63
Definition: Header.h:8
#define IPv4Checksum(Data, Count, Seed)
Definition: checksum.h:30
#define AllocatePacketWithBuffer(x, y, z)
Definition: memtrack.h:7
PVOID Header
Definition: ip.h:83
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
UCHAR State
Definition: neighbor.h:30
void * PVOID
Definition: retypes.h:9
UINT MTU
Definition: ip.h:157
#define PCHAR
Definition: match.c:90
VOID IPSendComplete(PVOID Context, PNDIS_PACKET NdisPacket, NDIS_STATUS NdisStatus)
Definition: transmit.c:19
NTSTATUS IPSendFragment(PNDIS_PACKET NdisPacket, PNEIGHBOR_CACHE_ENTRY NCE, PIPFRAGMENT_CONTEXT IFC)
Definition: transmit.c:41
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define IPv4_MF_MASK
Definition: ip.h:66
UINT Position
Definition: ip.h:87
UINT TotalSize
Definition: ip.h:86
#define BufferSize
Definition: classpnp.h:419
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
PNDIS_PACKET Datagram
Definition: transmit.h:17
struct IPFRAGMENT_CONTEXT * PIPFRAGMENT_CONTEXT
UINT HeaderSize
Definition: ip.h:84
PNDIS_PACKET NdisPacket
Definition: transmit.h:20
BOOLEAN PrepareNextFragment(PIPFRAGMENT_CONTEXT IFC)
Definition: transmit.c:62
PIP_INTERFACE Interface
Definition: neighbor.h:33
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define MAX_TRACE
Definition: debug.h:16
PNEIGHBOR_CACHE_ENTRY NCE
Definition: transmit.h:27
unsigned short USHORT
Definition: pedump.c:61
unsigned int UINT
Definition: ndis.h:50
PNDIS_PACKET NdisPacket
Definition: ip.h:88
Definition: ip.h:37
NDIS_STATUS Status
Definition: transmit.h:29
BOOLEAN NBQueuePacket(PNEIGHBOR_CACHE_ENTRY NCE, PNDIS_PACKET NdisPacket, PNEIGHBOR_PACKET_COMPLETE PacketComplete, PVOID PacketContext)
Definition: neighbor.c:541
Definition: ip.h:77
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE)
Definition: transmit.c:223
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
PVOID DatagramData
Definition: transmit.h:18