[DELAYIMP] Fix 2 Clang-Cl warnings about __pfnDliNotifyHook2Default and __pfnDliFailu...
[reactos.git] / sdk / lib / drivers / ip / transport / datagram / datagram.c
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
13 BOOLEAN DGRemoveIRP(
14 PADDRESS_FILE AddrFile,
15 PIRP Irp)
16 {
17 PLIST_ENTRY ListEntry;
18 PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
19 KIRQL OldIrql;
20 BOOLEAN Found = FALSE;
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 DGDeliverData(
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;
79 PVOID SourceAddress;
80 ULONG BytesTaken;
81 NTSTATUS Status;
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;
106 PDATAGRAM_RECEIVE_REQUEST Current = NULL;
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
126 TI_DbgPrint(MAX_TRACE,
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,
186 SourceAddress,
187 0,
188 NULL,
189 TDI_RECEIVE_ENTIRE_MESSAGE,
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
211 VOID DGReceiveComplete(PVOID Context, NTSTATUS Status, ULONG Count) {
212 PDATAGRAM_RECEIVE_REQUEST ReceiveRequest =
213 (PDATAGRAM_RECEIVE_REQUEST)Context;
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
220 NTSTATUS DGReceiveDatagram(
221 PADDRESS_FILE AddrFile,
222 PTDI_CONNECTION_INFORMATION ConnInfo,
223 PCHAR BufferData,
224 ULONG ReceiveLength,
225 ULONG ReceiveFlags,
226 PTDI_CONNECTION_INFORMATION ReturnInfo,
227 PULONG BytesReceived,
228 PDATAGRAM_COMPLETION_ROUTINE Complete,
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 {
247 NTSTATUS Status;
248 PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
249 KIRQL OldIrql;
250
251 TI_DbgPrint(MAX_TRACE, ("Called.\n"));
252
253 LockObject(AddrFile, &OldIrql);
254
255 ReceiveRequest = ExAllocatePoolWithTag(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST),
256 DATAGRAM_RECV_TAG);
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
281 IoMarkIrpPending(Irp);
282
283 ReceiveRequest->ReturnInfo = ReturnInfo;
284 ReceiveRequest->Buffer = BufferData;
285 ReceiveRequest->BufferSize = ReceiveLength;
286 ReceiveRequest->UserComplete = Complete;
287 ReceiveRequest->UserContext = Context;
288 ReceiveRequest->Complete =
289 (PDATAGRAM_COMPLETION_ROUTINE)DGReceiveComplete;
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);
306 Status = STATUS_INSUFFICIENT_RESOURCES;
307 }
308
309 TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status));
310
311 return Status;
312 }