ReactOS  0.4.13-dev-99-g7e18b6d
datagram.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: transport/datagram/datagram.c
5  * PURPOSE: Routines for sending and receiving datagrams
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * REVISIONS:
8  * CSH 01/08-2000 Created
9  */
10 
11 #include "precomp.h"
12 
14  PADDRESS_FILE AddrFile,
15  PIRP Irp)
16 {
17  PLIST_ENTRY ListEntry;
18  PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
19  KIRQL OldIrql;
21 
22  TI_DbgPrint(MAX_TRACE, ("Called (Cancel IRP %08x for file %08x).\n",
23  Irp, AddrFile));
24 
25  LockObject(AddrFile, &OldIrql);
26 
27  for( ListEntry = AddrFile->ReceiveQueue.Flink;
28  ListEntry != &AddrFile->ReceiveQueue;
29  ListEntry = ListEntry->Flink )
30  {
31  ReceiveRequest = CONTAINING_RECORD
32  (ListEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
33 
34  TI_DbgPrint(MAX_TRACE, ("Request: %08x?\n", ReceiveRequest));
35 
36  if (ReceiveRequest->Irp == Irp)
37  {
38  RemoveEntryList(&ReceiveRequest->ListEntry);
39  ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
40  Found = TRUE;
41  break;
42  }
43  }
44 
45  UnlockObject(AddrFile, OldIrql);
46 
47  TI_DbgPrint(MAX_TRACE, ("Done.\n"));
48 
49  return Found;
50 }
51 
53  PADDRESS_FILE AddrFile,
54  PIP_ADDRESS SrcAddress,
55  PIP_ADDRESS DstAddress,
56  USHORT SrcPort,
57  USHORT DstPort,
58  PIP_PACKET IPPacket,
59  UINT DataSize)
60 /*
61  * FUNCTION: Delivers datagram data to a user
62  * ARGUMENTS:
63  * AddrFile = Address file to deliver data to
64  * Address = Remote address the packet came from
65  * IPPacket = Pointer to IP packet to deliver
66  * DataSize = Number of bytes in data area
67  * (incl. IP header for raw IP file objects)
68  * NOTES:
69  * If there is a receive request, then we copy the data to the
70  * buffer supplied by the user and complete the receive request.
71  * If no suitable receive request exists, then we call the event
72  * handler if it exists, otherwise we drop the packet.
73  */
74 {
75  KIRQL OldIrql;
76  PTDI_IND_RECEIVE_DATAGRAM ReceiveHandler;
77  PVOID HandlerContext;
78  LONG AddressLength;
80  ULONG BytesTaken;
82  PVOID DataBuffer;
83 
84  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
85 
86  LockObject(AddrFile, &OldIrql);
87 
88  if (AddrFile->Protocol == IPPROTO_UDP)
89  {
90  DataBuffer = IPPacket->Data;
91  }
92  else
93  {
94  if (AddrFile->HeaderIncl)
95  DataBuffer = IPPacket->Header;
96  else
97  {
98  DataBuffer = IPPacket->Data;
99  DataSize -= IPPacket->HeaderSize;
100  }
101  }
102 
103  if (!IsListEmpty(&AddrFile->ReceiveQueue))
104  {
105  PLIST_ENTRY CurrentEntry;
107  PTA_IP_ADDRESS RTAIPAddress;
108 
109  TI_DbgPrint(MAX_TRACE, ("There is a receive request.\n"));
110 
111  /* Search receive request list to find a match */
112  CurrentEntry = AddrFile->ReceiveQueue.Flink;
113  while(CurrentEntry != &AddrFile->ReceiveQueue) {
114  Current = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
115  CurrentEntry = CurrentEntry->Flink;
116  if( DstPort == AddrFile->Port &&
117  (AddrIsEqual(DstAddress, &AddrFile->Address) ||
118  AddrIsUnspecified(&AddrFile->Address) ||
119  AddrIsUnspecified(DstAddress))) {
120 
121  /* Remove the request from the queue */
122  RemoveEntryList(&Current->ListEntry);
123 
124  TI_DbgPrint(MAX_TRACE, ("Suitable receive request found.\n"));
125 
127  ("Target Buffer: %x, Source Buffer: %x, Size %d\n",
128  Current->Buffer, DataBuffer, DataSize));
129 
130  /* Copy the data into buffer provided by the user */
131  RtlCopyMemory( Current->Buffer,
132  DataBuffer,
133  MIN(Current->BufferSize, DataSize) );
134 
135  RTAIPAddress = (PTA_IP_ADDRESS)Current->ReturnInfo->RemoteAddress;
136  RTAIPAddress->TAAddressCount = 1;
137  RTAIPAddress->Address->AddressType = TDI_ADDRESS_TYPE_IP;
138  RTAIPAddress->Address->AddressLength = TDI_ADDRESS_LENGTH_IP;
139  RTAIPAddress->Address->Address->sin_port = SrcPort;
140  RTAIPAddress->Address->Address->in_addr = SrcAddress->Address.IPv4Address;
141  RtlZeroMemory(RTAIPAddress->Address->Address->sin_zero, 8);
142 
143  TI_DbgPrint(MAX_TRACE, ("(A: %08x) Addr %08x Port %04x\n",
144  RTAIPAddress,
145  SrcAddress->Address.IPv4Address, SrcPort));
146 
147  ReferenceObject(AddrFile);
148  UnlockObject(AddrFile, OldIrql);
149 
150  /* Complete the receive request */
151  if (Current->BufferSize < DataSize)
152  Current->Complete(Current->Context, STATUS_BUFFER_OVERFLOW, Current->BufferSize);
153  else
154  Current->Complete(Current->Context, STATUS_SUCCESS, DataSize);
155 
156  LockObject(AddrFile, &OldIrql);
157  DereferenceObject(AddrFile);
158  }
159  }
160 
161  UnlockObject(AddrFile, OldIrql);
162  }
163  else if (AddrFile->RegisteredReceiveDatagramHandler)
164  {
165  TI_DbgPrint(MAX_TRACE, ("Calling receive event handler.\n"));
166 
167  ReceiveHandler = AddrFile->ReceiveDatagramHandler;
168  HandlerContext = AddrFile->ReceiveDatagramHandlerContext;
169 
170  if (SrcAddress->Type == IP_ADDRESS_V4)
171  {
172  AddressLength = sizeof(IPv4_RAW_ADDRESS);
173  SourceAddress = &SrcAddress->Address.IPv4Address;
174  }
175  else /* (Address->Type == IP_ADDRESS_V6) */
176  {
177  AddressLength = sizeof(IPv6_RAW_ADDRESS);
178  SourceAddress = SrcAddress->Address.IPv6Address;
179  }
180 
181  ReferenceObject(AddrFile);
182  UnlockObject(AddrFile, OldIrql);
183 
184  Status = (*ReceiveHandler)(HandlerContext,
185  AddressLength,
187  0,
188  NULL,
190  DataSize,
191  DataSize,
192  &BytesTaken,
193  DataBuffer,
194  NULL);
195 
196  if (STATUS_SUCCESS != Status)
197  TI_DbgPrint(MAX_TRACE, ("receive handler signaled failure with Status 0x%x\n", Status));
198 
199  DereferenceObject(AddrFile);
200  }
201  else
202  {
203  UnlockObject(AddrFile, OldIrql);
204  TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n"));
205  }
206 
207  TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
208 }
209 
210 
212  PDATAGRAM_RECEIVE_REQUEST ReceiveRequest =
214  TI_DbgPrint(MAX_TRACE,("Called (%08x:%08x)\n", Status, Count));
215  ReceiveRequest->UserComplete( ReceiveRequest->UserContext, Status, Count );
216  ExFreePoolWithTag( ReceiveRequest, DATAGRAM_RECV_TAG );
217  TI_DbgPrint(MAX_TRACE,("Done\n"));
218 }
219 
221  PADDRESS_FILE AddrFile,
223  PCHAR BufferData,
224  ULONG ReceiveLength,
225  ULONG ReceiveFlags,
226  PTDI_CONNECTION_INFORMATION ReturnInfo,
227  PULONG BytesReceived,
229  PVOID Context,
230  PIRP Irp)
231 /*
232  * FUNCTION: Attempts to receive an DG datagram from a remote address
233  * ARGUMENTS:
234  * Request = Pointer to TDI request
235  * ConnInfo = Pointer to connection information
236  * Buffer = Pointer to NDIS buffer chain to store received data
237  * ReceiveLength = Maximum size to use of buffer, 0 if all can be used
238  * ReceiveFlags = Receive flags (None, Normal, Peek)
239  * ReturnInfo = Pointer to structure for return information
240  * BytesReceive = Pointer to structure for number of bytes received
241  * RETURNS:
242  * Status of operation
243  * NOTES:
244  * This is the high level interface for receiving DG datagrams
245  */
246 {
248  PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
249  KIRQL OldIrql;
250 
251  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
252 
253  LockObject(AddrFile, &OldIrql);
254 
257  if (ReceiveRequest)
258  {
259  /* Initialize a receive request */
260 
261  /* Extract the remote address filter from the request (if any) */
262  if ((ConnInfo->RemoteAddressLength != 0) &&
263  (ConnInfo->RemoteAddress))
264  {
265  Status = AddrGetAddress(ConnInfo->RemoteAddress,
266  &ReceiveRequest->RemoteAddress,
267  &ReceiveRequest->RemotePort);
268  if (!NT_SUCCESS(Status))
269  {
270  ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
271  UnlockObject(AddrFile, OldIrql);
272  return Status;
273  }
274  }
275  else
276  {
277  ReceiveRequest->RemotePort = 0;
278  AddrInitIPv4(&ReceiveRequest->RemoteAddress, 0);
279  }
280 
282 
283  ReceiveRequest->ReturnInfo = ReturnInfo;
284  ReceiveRequest->Buffer = BufferData;
285  ReceiveRequest->BufferSize = ReceiveLength;
286  ReceiveRequest->UserComplete = Complete;
287  ReceiveRequest->UserContext = Context;
288  ReceiveRequest->Complete =
290  ReceiveRequest->Context = ReceiveRequest;
291  ReceiveRequest->AddressFile = AddrFile;
292  ReceiveRequest->Irp = Irp;
293 
294  /* Queue receive request */
295  InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry);
296 
297  TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
298 
299  UnlockObject(AddrFile, OldIrql);
300 
301  return STATUS_PENDING;
302  }
303  else
304  {
305  UnlockObject(AddrFile, OldIrql);
307  }
308 
309  TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status));
310 
311  return Status;
312 }
BOOLEAN AddrIsUnspecified(PIP_ADDRESS Address)
Definition: address.c:113
signed char * PCHAR
Definition: retypes.h:7
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
LONG TAAddressCount
Definition: tdi.h:523
IPv4_RAW_ADDRESS IPv4Address
Definition: ip.h:26
ULONG IPv4_RAW_ADDRESS
Definition: ip.h:15
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
BOOLEAN RegisteredReceiveDatagramHandler
Definition: titypes.h:183
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
IPv6_RAW_ADDRESS IPv6Address
Definition: ip.h:27
_In_ PIRP Irp
Definition: csq.h:116
struct _TA_ADDRESS_IP * PTA_IP_ADDRESS
LONG NTSTATUS
Definition: precomp.h:26
USHORT Protocol
Definition: titypes.h:138
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
NTSTATUS DGReceiveDatagram(PADDRESS_FILE AddrFile, PTDI_CONNECTION_INFORMATION ConnInfo, PCHAR BufferData, ULONG ReceiveLength, ULONG ReceiveFlags, PTDI_CONNECTION_INFORMATION ReturnInfo, PULONG BytesReceived, PDATAGRAM_COMPLETION_ROUTINE Complete, PVOID Context, PIRP Irp)
Definition: datagram.c:220
#define TDI_RECEIVE_ENTIRE_MESSAGE
Definition: tdi.h:127
#define InsertTailList(ListHead, Entry)
DATAGRAM_COMPLETION_ROUTINE Complete
Definition: titypes.h:102
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define DereferenceObject(Object)
Definition: titypes.h:24
T MIN(T a, T b)
Definition: polytest.cpp:79
PVOID Data
Definition: ip.h:85
#define LockObject(Object, Irql)
Definition: titypes.h:34
Definition: ip.h:23
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
BOOLEAN DGRemoveIRP(PADDRESS_FILE AddrFile, PIRP Irp)
Definition: datagram.c:13
#define IP_ADDRESS_V4
Definition: ip.h:32
long LONG
Definition: pedump.c:60
#define UnlockObject(Object, OldIrql)
Definition: titypes.h:54
PVOID Header
Definition: ip.h:83
unsigned char BOOLEAN
DATAGRAM_COMPLETION_ROUTINE PDATAGRAM_COMPLETION_ROUTINE
Definition: titypes.h:92
smooth NULL
Definition: ftsmooth.c:416
struct _TA_ADDRESS_IP::_AddrIp Address[1]
return Found
Definition: dirsup.c:1270
PTDI_IND_RECEIVE_DATAGRAM ReceiveDatagramHandler
Definition: titypes.h:181
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
PVOID ReceiveDatagramHandlerContext
Definition: titypes.h:182
#define DATAGRAM_RECV_TAG
Definition: tags.h:16
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _ADDRESS_FILE * AddressFile
Definition: titypes.h:95
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define AddrInitIPv4(IPAddress, RawAddress)
Definition: address.h:16
LIST_ENTRY ListEntry
Definition: titypes.h:96
VOID DGReceiveComplete(PVOID Context, NTSTATUS Status, ULONG Count)
Definition: datagram.c:211
IP_ADDRESS RemoteAddress
Definition: titypes.h:97
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _DATAGRAM_RECEIVE_REQUEST * PDATAGRAM_RECEIVE_REQUEST
NTSTATUS(NTAPI * PTDI_IND_RECEIVE_DATAGRAM)(_In_opt_ PVOID TdiEventContext, _In_ LONG SourceAddressLength, _In_reads_bytes_(SourceAddressLength) PVOID SourceAddress, _In_ LONG OptionsLength, _In_reads_bytes_opt_(OptionsLength) PVOID Options, _In_ ULONG ReceiveDatagramFlags, _In_ ULONG BytesIndicated, _In_ ULONG BytesAvailable, _Out_ ULONG *BytesTaken, _In_ PVOID Tsdu, _Out_opt_ PIRP *IoRequestPacket)
Definition: tdikrnl.h:249
UINT HeaderSize
Definition: ip.h:84
BOOLEAN AddrIsEqual(PIP_ADDRESS Address1, PIP_ADDRESS Address2)
Definition: address.c:221
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
union IP_ADDRESS::@966 Address
#define TDI_ADDRESS_TYPE_IP
Definition: tdi.h:345
UINT HeaderIncl
Definition: titypes.h:144
#define ReferenceObject(Object)
Definition: titypes.h:14
Definition: typedefs.h:117
Status
Definition: gdiplustypes.h:24
UCHAR Type
Definition: ip.h:24
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
#define MAX_TRACE
Definition: debug.h:16
unsigned short USHORT
Definition: pedump.c:61
IP_ADDRESS Address
Definition: titypes.h:136
unsigned int * PULONG
Definition: retypes.h:1
unsigned int UINT
Definition: ndis.h:50
USHORT IPv6_RAW_ADDRESS[8]
Definition: ip.h:19
VOID DGDeliverData(PADDRESS_FILE AddrFile, PIP_ADDRESS SrcAddress, PIP_ADDRESS DstAddress, USHORT SrcPort, USHORT DstPort, PIP_PACKET IPPacket, UINT DataSize)
Definition: datagram.c:52
NTSTATUS AddrGetAddress(PTRANSPORT_ADDRESS AddrList, PIP_ADDRESS Address, PUSHORT Port)
Definition: address.c:146
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
DATAGRAM_COMPLETION_ROUTINE UserComplete
Definition: titypes.h:104
LIST_ENTRY ReceiveQueue
Definition: titypes.h:149
Definition: ip.h:77
USHORT Port
Definition: titypes.h:139
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define TDI_ADDRESS_LENGTH_IP
Definition: tdi.h:413
return STATUS_SUCCESS
Definition: btrfs.c:2725
PTDI_CONNECTION_INFORMATION ReturnInfo
Definition: titypes.h:99
IoMarkIrpPending(Irp)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1089
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4733