ReactOS 0.4.16-dev-297-gc569aee
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;
20
21 TI_DbgPrint(MAX_TRACE, ("Called (Cancel IRP %08x for file %08x).\n",
22 Irp, AddrFile));
23
24 LockObject(AddrFile);
25
26 for( ListEntry = AddrFile->ReceiveQueue.Flink;
27 ListEntry != &AddrFile->ReceiveQueue;
28 ListEntry = ListEntry->Flink )
29 {
30 ReceiveRequest = CONTAINING_RECORD
31 (ListEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
32
33 TI_DbgPrint(MAX_TRACE, ("Request: %08x?\n", ReceiveRequest));
34
35 if (ReceiveRequest->Irp == Irp)
36 {
37 RemoveEntryList(&ReceiveRequest->ListEntry);
38 ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
39 Found = TRUE;
40 break;
41 }
42 }
43
44 UnlockObject(AddrFile);
45
46 TI_DbgPrint(MAX_TRACE, ("Done.\n"));
47
48 return Found;
49}
50
51VOID
53 PADDRESS_FILE AddrFile,
54 PIP_ADDRESS SrcAddress,
55 PIP_ADDRESS DstAddress,
56 USHORT SrcPort,
57 USHORT DstPort,
58 PIP_PACKET IPPacket,
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 LONG AddressLength;
77 ULONG BytesTaken;
79 PVOID DataBuffer;
80
81 TI_DbgPrint(MIN_TRACE, ("Called.\n"));
82
83 LockObject(AddrFile);
84
85 if (AddrFile->Protocol == IPPROTO_UDP)
86 {
87 DataBuffer = IPPacket->Data;
88 }
89 else if (AddrFile->HeaderIncl)
90 {
91 DataBuffer = IPPacket->Header;
92 }
93 else
94 {
95 DataBuffer = IPPacket->Data;
96 DataSize -= IPPacket->HeaderSize;
97 }
98
99 if (!IsListEmpty(&AddrFile->ReceiveQueue))
100 {
101 PLIST_ENTRY CurrentEntry;
103 PTA_IP_ADDRESS RTAIPAddress;
104
105 TI_DbgPrint(MAX_TRACE, ("There is a receive request.\n"));
106
107 /* Search receive request list to find a match */
108 CurrentEntry = AddrFile->ReceiveQueue.Flink;
109 while (CurrentEntry != &AddrFile->ReceiveQueue)
110 {
111 Current = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
112 CurrentEntry = CurrentEntry->Flink;
113 if (DstPort == AddrFile->Port &&
114 (AddrIsEqual(DstAddress, &AddrFile->Address) ||
115 AddrIsUnspecified(&AddrFile->Address) ||
116 AddrIsUnspecified(DstAddress)))
117 {
118
119 /* Remove the request from the queue */
120 RemoveEntryList(&Current->ListEntry);
121
122 TI_DbgPrint(MAX_TRACE, ("Suitable receive request found.\n"));
123
125 ("Target Buffer: %x, Source Buffer: %x, Size %d\n",
126 Current->Buffer, DataBuffer, DataSize));
127
128 /* Copy the data into buffer provided by the user */
129 RtlCopyMemory(Current->Buffer,
130 DataBuffer,
131 MIN(Current->BufferSize, DataSize));
132
133 RTAIPAddress = (PTA_IP_ADDRESS)Current->ReturnInfo->RemoteAddress;
134 RTAIPAddress->TAAddressCount = 1;
135 RTAIPAddress->Address->AddressType = TDI_ADDRESS_TYPE_IP;
136 RTAIPAddress->Address->AddressLength = TDI_ADDRESS_LENGTH_IP;
137 RTAIPAddress->Address->Address->sin_port = SrcPort;
138 RTAIPAddress->Address->Address->in_addr = SrcAddress->Address.IPv4Address;
139 RtlZeroMemory(RTAIPAddress->Address->Address->sin_zero, 8);
140
141 TI_DbgPrint(MAX_TRACE, ("(A: %08x) Addr %08x Port %04x\n",
142 RTAIPAddress,
143 SrcAddress->Address.IPv4Address, SrcPort));
144
145 ReferenceObject(AddrFile);
146 UnlockObject(AddrFile);
147
148 /* Complete the receive request */
149 if (Current->BufferSize < DataSize)
150 Current->Complete(Current->Context, STATUS_BUFFER_OVERFLOW, Current->BufferSize);
151 else
152 Current->Complete(Current->Context, STATUS_SUCCESS, DataSize);
153
154 LockObject(AddrFile);
155 DereferenceObject(AddrFile);
156 }
157 }
158
159 UnlockObject(AddrFile);
160 }
161 else if (AddrFile->RegisteredReceiveDatagramHandler)
162 {
163 PTDI_IND_RECEIVE_DATAGRAM ReceiveHandler = AddrFile->ReceiveDatagramHandler;
164 PVOID HandlerContext = AddrFile->ReceiveDatagramHandlerContext;
165 PVOID OptionsData = NULL;
166 INT32 OptionsSize = 0;
167
168 TI_DbgPrint(MAX_TRACE, ("Calling receive event handler.\n"));
169
170 if (SrcAddress->Type == IP_ADDRESS_V4)
171 {
172 AddressLength = sizeof(IPv4_RAW_ADDRESS);
173 SourceAddress = &SrcAddress->Address.IPv4Address;
174 OptionsSize = IPPacket->HeaderSize - sizeof(IPv4_HEADER);
175 if (OptionsSize > 0)
176 {
177 OptionsData = (PUCHAR)IPPacket->Header + sizeof(IPv4_HEADER);
178 }
179 }
180 else /* (Address->Type == IP_ADDRESS_V6) */
181 {
182 AddressLength = sizeof(IPv6_RAW_ADDRESS);
183 SourceAddress = SrcAddress->Address.IPv6Address;
184 }
185
186 ReferenceObject(AddrFile);
187 UnlockObject(AddrFile);
188
189 TI_DbgPrint(MIN_TRACE, ("OptionsSize %d DataSize: %u\n", OptionsSize, DataSize));
190
191 Status = (*ReceiveHandler)(HandlerContext,
192 AddressLength,
194 OptionsSize,
195 OptionsData,
197 DataSize,
198 DataSize,
199 &BytesTaken,
200 DataBuffer,
201 NULL);
202
203 if (STATUS_SUCCESS != Status)
204 TI_DbgPrint(MAX_TRACE, ("receive handler signaled failure with Status 0x%x\n", Status));
205
206 DereferenceObject(AddrFile);
207 }
208 else
209 {
210 UnlockObject(AddrFile);
211 TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n"));
212 }
213
214 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
215}
216
218 PDATAGRAM_RECEIVE_REQUEST ReceiveRequest =
220 TI_DbgPrint(MAX_TRACE,("Called (%08x:%08x)\n", Status, Count));
221 ReceiveRequest->UserComplete( ReceiveRequest->UserContext, Status, Count );
222 ExFreePoolWithTag( ReceiveRequest, DATAGRAM_RECV_TAG );
223 TI_DbgPrint(MAX_TRACE,("Done\n"));
224}
225
227 PADDRESS_FILE AddrFile,
229 PCHAR BufferData,
230 ULONG ReceiveLength,
231 ULONG ReceiveFlags,
233 PULONG BytesReceived,
236 PIRP Irp)
237/*
238 * FUNCTION: Attempts to receive an DG datagram from a remote address
239 * ARGUMENTS:
240 * Request = Pointer to TDI request
241 * ConnInfo = Pointer to connection information
242 * Buffer = Pointer to NDIS buffer chain to store received data
243 * ReceiveLength = Maximum size to use of buffer, 0 if all can be used
244 * ReceiveFlags = Receive flags (None, Normal, Peek)
245 * ReturnInfo = Pointer to structure for return information
246 * BytesReceive = Pointer to structure for number of bytes received
247 * RETURNS:
248 * Status of operation
249 * NOTES:
250 * This is the high level interface for receiving DG datagrams
251 */
252{
254 PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
255
256 TI_DbgPrint(MAX_TRACE, ("Called.\n"));
257
258 LockObject(AddrFile);
259
262 if (ReceiveRequest)
263 {
264 /* Initialize a receive request */
265
266 /* Extract the remote address filter from the request (if any) */
267 if ((ConnInfo->RemoteAddressLength != 0) &&
268 (ConnInfo->RemoteAddress))
269 {
271 &ReceiveRequest->RemoteAddress,
272 &ReceiveRequest->RemotePort);
273 if (!NT_SUCCESS(Status))
274 {
275 ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
276 UnlockObject(AddrFile);
277 return Status;
278 }
279 }
280 else
281 {
282 ReceiveRequest->RemotePort = 0;
283 AddrInitIPv4(&ReceiveRequest->RemoteAddress, 0);
284 }
285
287
288 ReceiveRequest->ReturnInfo = ReturnInfo;
289 ReceiveRequest->Buffer = BufferData;
290 ReceiveRequest->BufferSize = ReceiveLength;
291 ReceiveRequest->UserComplete = Complete;
292 ReceiveRequest->UserContext = Context;
293 ReceiveRequest->Complete =
295 ReceiveRequest->Context = ReceiveRequest;
296 ReceiveRequest->AddressFile = AddrFile;
297 ReceiveRequest->Irp = Irp;
298
299 /* Queue receive request */
300 InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry);
301
302 TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
303
304 UnlockObject(AddrFile);
305
306 return STATUS_PENDING;
307 }
308 else
309 {
310 UnlockObject(AddrFile);
312 }
313
314 TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status));
315
316 return Status;
317}
signed int INT32
unsigned char BOOLEAN
#define AddrInitIPv4(IPAddress, RawAddress)
Definition: address.h:16
NTSTATUS AddrGetAddress(PTRANSPORT_ADDRESS AddrList, PIP_ADDRESS Address, PUSHORT Port)
Definition: address.c:146
BOOLEAN AddrIsUnspecified(PIP_ADDRESS Address)
Definition: address.c:113
BOOLEAN AddrIsEqual(PIP_ADDRESS Address1, PIP_ADDRESS Address2)
Definition: address.c:221
LONG NTSTATUS
Definition: precomp.h:26
#define MIN(x, y)
Definition: rdesktop.h:171
#define MIN_TRACE
Definition: debug.h:14
#define MAX_TRACE
Definition: debug.h:16
return Found
Definition: dirsup.c:1270
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
VOID DGDeliverData(PADDRESS_FILE AddrFile, PIP_ADDRESS SrcAddress, PIP_ADDRESS DstAddress, USHORT SrcPort, USHORT DstPort, PIP_PACKET IPPacket, UINT DataSize)
Definition: datagram.c:52
BOOLEAN DGRemoveIRP(PADDRESS_FILE AddrFile, PIRP Irp)
Definition: datagram.c:13
VOID DGReceiveComplete(PVOID Context, NTSTATUS Status, ULONG Count)
Definition: datagram.c:217
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:226
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
USHORT IPv6_RAW_ADDRESS[8]
Definition: ip.h:19
ULONG IPv4_RAW_ADDRESS
Definition: ip.h:15
#define IP_ADDRESS_V4
Definition: ip.h:32
#define IPPROTO_UDP
Definition: ip.h:197
#define DATAGRAM_RECV_TAG
Definition: tags.h:16
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define NonPagedPool
Definition: env_spec_w32.h:307
pRequest Complete(RequestStatus)
Status
Definition: gdiplustypes.h:25
IoMarkIrpPending(Irp)
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
unsigned int UINT
Definition: ndis.h:50
int Count
Definition: noreturn.cpp:7
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
Definition: ip.h:23
IPv6_RAW_ADDRESS IPv6Address
Definition: ip.h:27
UCHAR Type
Definition: ip.h:24
union IP_ADDRESS::@1014 Address
IPv4_RAW_ADDRESS IPv4Address
Definition: ip.h:26
UINT HeaderIncl
Definition: titypes.h:125
BOOLEAN RegisteredReceiveDatagramHandler
Definition: titypes.h:163
LIST_ENTRY ReceiveQueue
Definition: titypes.h:129
USHORT Port
Definition: titypes.h:120
IP_ADDRESS Address
Definition: titypes.h:117
PVOID ReceiveDatagramHandlerContext
Definition: titypes.h:162
PTDI_IND_RECEIVE_DATAGRAM ReceiveDatagramHandler
Definition: titypes.h:161
USHORT Protocol
Definition: titypes.h:119
DATAGRAM_COMPLETION_ROUTINE Complete
Definition: titypes.h:84
LIST_ENTRY ListEntry
Definition: titypes.h:78
struct _ADDRESS_FILE * AddressFile
Definition: titypes.h:77
PTDI_CONNECTION_INFORMATION ReturnInfo
Definition: titypes.h:81
DATAGRAM_COMPLETION_ROUTINE UserComplete
Definition: titypes.h:86
IP_ADDRESS RemoteAddress
Definition: titypes.h:79
Definition: ip.h:77
PVOID Data
Definition: ip.h:85
UINT HeaderSize
Definition: ip.h:84
PVOID Header
Definition: ip.h:83
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _TA_ADDRESS_IP::_AddrIp Address[1]
LONG TAAddressCount
Definition: tdi.h:523
struct _TA_ADDRESS_IP * PTA_IP_ADDRESS
#define TDI_RECEIVE_ENTIRE_MESSAGE
Definition: tdi.h:127
#define TDI_ADDRESS_LENGTH_IP
Definition: tdi.h:413
#define TDI_ADDRESS_TYPE_IP
Definition: tdi.h:345
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
DATAGRAM_COMPLETION_ROUTINE PDATAGRAM_COMPLETION_ROUTINE
Definition: titypes.h:74
#define UnlockObject(Object)
Definition: titypes.h:44
#define ReferenceObject(Object)
Definition: titypes.h:14
#define LockObject(Object)
Definition: titypes.h:34
#define DereferenceObject(Object)
Definition: titypes.h:24
struct _DATAGRAM_RECEIVE_REQUEST * PDATAGRAM_RECEIVE_REQUEST
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1127