ReactOS  0.4.15-dev-449-g64abd9f
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 
52 VOID
54  PADDRESS_FILE AddrFile,
55  PIP_ADDRESS SrcAddress,
56  PIP_ADDRESS DstAddress,
57  USHORT SrcPort,
58  USHORT DstPort,
59  PIP_PACKET IPPacket,
60  UINT DataSize)
61 /*
62  * FUNCTION: Delivers datagram data to a user
63  * ARGUMENTS:
64  * AddrFile = Address file to deliver data to
65  * Address = Remote address the packet came from
66  * IPPacket = Pointer to IP packet to deliver
67  * DataSize = Number of bytes in data area
68  * (incl. IP header for raw IP file objects)
69  * NOTES:
70  * If there is a receive request, then we copy the data to the
71  * buffer supplied by the user and complete the receive request.
72  * If no suitable receive request exists, then we call the event
73  * handler if it exists, otherwise we drop the packet.
74  */
75 {
76  KIRQL OldIrql;
77  LONG AddressLength;
79  ULONG BytesTaken;
81  PVOID DataBuffer;
82 
83  TI_DbgPrint(MIN_TRACE, ("Called.\n"));
84 
85  LockObject(AddrFile, &OldIrql);
86 
87  if (AddrFile->Protocol == IPPROTO_UDP)
88  {
89  DataBuffer = IPPacket->Data;
90  }
91  else if (AddrFile->HeaderIncl)
92  {
93  DataBuffer = IPPacket->Header;
94  }
95  else
96  {
97  DataBuffer = IPPacket->Data;
98  DataSize -= IPPacket->HeaderSize;
99  }
100 
101  if (!IsListEmpty(&AddrFile->ReceiveQueue))
102  {
103  PLIST_ENTRY CurrentEntry;
105  PTA_IP_ADDRESS RTAIPAddress;
106 
107  TI_DbgPrint(MAX_TRACE, ("There is a receive request.\n"));
108 
109  /* Search receive request list to find a match */
110  CurrentEntry = AddrFile->ReceiveQueue.Flink;
111  while (CurrentEntry != &AddrFile->ReceiveQueue)
112  {
113  Current = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
114  CurrentEntry = CurrentEntry->Flink;
115  if (DstPort == AddrFile->Port &&
116  (AddrIsEqual(DstAddress, &AddrFile->Address) ||
117  AddrIsUnspecified(&AddrFile->Address) ||
118  AddrIsUnspecified(DstAddress)))
119  {
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  PTDI_IND_RECEIVE_DATAGRAM ReceiveHandler = AddrFile->ReceiveDatagramHandler;
166  PVOID HandlerContext = AddrFile->ReceiveDatagramHandlerContext;
167  PVOID OptionsData = NULL;
168  INT32 OptionsSize = 0;
169 
170  TI_DbgPrint(MAX_TRACE, ("Calling receive event handler.\n"));
171 
172  if (SrcAddress->Type == IP_ADDRESS_V4)
173  {
174  AddressLength = sizeof(IPv4_RAW_ADDRESS);
175  SourceAddress = &SrcAddress->Address.IPv4Address;
176  OptionsSize = IPPacket->HeaderSize - sizeof(IPv4_HEADER);
177  if (OptionsSize > 0)
178  {
179  OptionsData = (PUCHAR)IPPacket->Header + sizeof(IPv4_HEADER);
180  }
181  }
182  else /* (Address->Type == IP_ADDRESS_V6) */
183  {
184  AddressLength = sizeof(IPv6_RAW_ADDRESS);
185  SourceAddress = SrcAddress->Address.IPv6Address;
186  }
187 
188  ReferenceObject(AddrFile);
189  UnlockObject(AddrFile, OldIrql);
190 
191  TI_DbgPrint(MIN_TRACE, ("OptionsSize %d DataSize: %u\n", OptionsSize, DataSize));
192 
193  Status = (*ReceiveHandler)(HandlerContext,
194  AddressLength,
196  OptionsSize,
197  OptionsData,
199  DataSize,
200  DataSize,
201  &BytesTaken,
202  DataBuffer,
203  NULL);
204 
205  if (STATUS_SUCCESS != Status)
206  TI_DbgPrint(MAX_TRACE, ("receive handler signaled failure with Status 0x%x\n", Status));
207 
208  DereferenceObject(AddrFile);
209  }
210  else
211  {
212  UnlockObject(AddrFile, OldIrql);
213  TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n"));
214  }
215 
216  TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
217 }
218 
220  PDATAGRAM_RECEIVE_REQUEST ReceiveRequest =
222  TI_DbgPrint(MAX_TRACE,("Called (%08x:%08x)\n", Status, Count));
223  ReceiveRequest->UserComplete( ReceiveRequest->UserContext, Status, Count );
224  ExFreePoolWithTag( ReceiveRequest, DATAGRAM_RECV_TAG );
225  TI_DbgPrint(MAX_TRACE,("Done\n"));
226 }
227 
229  PADDRESS_FILE AddrFile,
231  PCHAR BufferData,
232  ULONG ReceiveLength,
233  ULONG ReceiveFlags,
234  PTDI_CONNECTION_INFORMATION ReturnInfo,
235  PULONG BytesReceived,
237  PVOID Context,
238  PIRP Irp)
239 /*
240  * FUNCTION: Attempts to receive an DG datagram from a remote address
241  * ARGUMENTS:
242  * Request = Pointer to TDI request
243  * ConnInfo = Pointer to connection information
244  * Buffer = Pointer to NDIS buffer chain to store received data
245  * ReceiveLength = Maximum size to use of buffer, 0 if all can be used
246  * ReceiveFlags = Receive flags (None, Normal, Peek)
247  * ReturnInfo = Pointer to structure for return information
248  * BytesReceive = Pointer to structure for number of bytes received
249  * RETURNS:
250  * Status of operation
251  * NOTES:
252  * This is the high level interface for receiving DG datagrams
253  */
254 {
256  PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
257  KIRQL OldIrql;
258 
259  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
260 
261  LockObject(AddrFile, &OldIrql);
262 
265  if (ReceiveRequest)
266  {
267  /* Initialize a receive request */
268 
269  /* Extract the remote address filter from the request (if any) */
270  if ((ConnInfo->RemoteAddressLength != 0) &&
271  (ConnInfo->RemoteAddress))
272  {
273  Status = AddrGetAddress(ConnInfo->RemoteAddress,
274  &ReceiveRequest->RemoteAddress,
275  &ReceiveRequest->RemotePort);
276  if (!NT_SUCCESS(Status))
277  {
278  ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
279  UnlockObject(AddrFile, OldIrql);
280  return Status;
281  }
282  }
283  else
284  {
285  ReceiveRequest->RemotePort = 0;
286  AddrInitIPv4(&ReceiveRequest->RemoteAddress, 0);
287  }
288 
290 
291  ReceiveRequest->ReturnInfo = ReturnInfo;
292  ReceiveRequest->Buffer = BufferData;
293  ReceiveRequest->BufferSize = ReceiveLength;
294  ReceiveRequest->UserComplete = Complete;
295  ReceiveRequest->UserContext = Context;
296  ReceiveRequest->Complete =
298  ReceiveRequest->Context = ReceiveRequest;
299  ReceiveRequest->AddressFile = AddrFile;
300  ReceiveRequest->Irp = Irp;
301 
302  /* Queue receive request */
303  InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry);
304 
305  TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
306 
307  UnlockObject(AddrFile, OldIrql);
308 
309  return STATUS_PENDING;
310  }
311  else
312  {
313  UnlockObject(AddrFile, OldIrql);
315  }
316 
317  TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status));
318 
319  return Status;
320 }
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
unsigned char * PUCHAR
Definition: retypes.h:3
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:228
#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
union IP_ADDRESS::@1004 Address
#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
struct IPv4_HEADER IPv4_HEADER
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:120
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:219
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:790
#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:118
Status
Definition: gdiplustypes.h:24
UCHAR Type
Definition: ip.h:24
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#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
Definition: ip.h:37
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:53
NTSTATUS AddrGetAddress(PTRANSPORT_ADDRESS AddrList, PIP_ADDRESS Address, PUSHORT Port)
Definition: address.c:146
struct tagContext Context
Definition: acpixf.h:1034
unsigned int ULONG
Definition: retypes.h:1
signed int INT32
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define MIN_TRACE
Definition: debug.h:14
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:3014
PTDI_CONNECTION_INFORMATION ReturnInfo
Definition: titypes.h:99
IoMarkIrpPending(Irp)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1090
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751