Raw IP and ICMP fixes
[reactos.git] / reactos / drivers / net / afd / afd / dispatch.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver
4 * FILE: afd/dispatch.c
5 * PURPOSE: File object dispatch functions
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #include <afd.h>
11
12 NTSTATUS AfdDispBind(
13 PIRP Irp,
14 PIO_STACK_LOCATION IrpSp)
15 /*
16 * FUNCTION: Binds to an address
17 * ARGUMENTS:
18 * Irp = Pointer to I/O request packet
19 * IrpSp = Pointer to current stack location of Irp
20 * RETURNS:
21 * Status of operation
22 */
23 {
24 NTSTATUS Status;
25 UINT InputBufferLength;
26 UINT OutputBufferLength;
27 PFILE_REQUEST_BIND Request;
28 PFILE_REPLY_BIND Reply;
29 PAFDFCB FCB;
30
31 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
32 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
33
34 /* Validate parameters */
35 if ((InputBufferLength >= sizeof(FILE_REQUEST_BIND)) &&
36 (OutputBufferLength >= sizeof(FILE_REPLY_BIND))) {
37 FCB = IrpSp->FileObject->FsContext;
38
39 Request = (PFILE_REQUEST_BIND)Irp->AssociatedIrp.SystemBuffer;
40 Reply = (PFILE_REPLY_BIND)Irp->AssociatedIrp.SystemBuffer;
41
42 switch (Request->Name.sa_family) {
43 case AF_INET:
44 Status = TdiOpenAddressFileIPv4(&FCB->TdiDeviceName,
45 &Request->Name,
46 &FCB->TdiAddressObjectHandle,
47 &FCB->TdiAddressObject);
48 break;
49 default:
50 AFD_DbgPrint(MIN_TRACE, ("Bad address family (%d).\n", Request->Name.sa_family));
51 Status = STATUS_INVALID_PARAMETER;
52 }
53
54 if (NT_SUCCESS(Status)) {
55 AfdRegisterEventHandlers(FCB);
56 FCB->State = SOCKET_STATE_BOUND;
57 }
58 } else
59 Status = STATUS_INVALID_PARAMETER;
60
61 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
62
63 return Status;
64 }
65
66
67 NTSTATUS AfdDispListen(
68 PIRP Irp,
69 PIO_STACK_LOCATION IrpSp)
70 /*
71 * FUNCTION: Starts listening for connections
72 * ARGUMENTS:
73 * Irp = Pointer to I/O request packet
74 * IrpSp = Pointer to current stack location of Irp
75 * RETURNS:
76 * Status of operation
77 */
78 {
79 NTSTATUS Status;
80 UINT InputBufferLength;
81 UINT OutputBufferLength;
82 PFILE_REQUEST_LISTEN Request;
83 PFILE_REPLY_LISTEN Reply;
84 PAFDFCB FCB;
85
86 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
87 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
88
89 /* Validate parameters */
90 if ((InputBufferLength >= sizeof(FILE_REQUEST_LISTEN)) &&
91 (OutputBufferLength >= sizeof(FILE_REPLY_LISTEN))) {
92 FCB = IrpSp->FileObject->FsContext;
93
94 Request = (PFILE_REQUEST_LISTEN)Irp->AssociatedIrp.SystemBuffer;
95 Reply = (PFILE_REPLY_LISTEN)Irp->AssociatedIrp.SystemBuffer;
96 } else
97 Status = STATUS_INVALID_PARAMETER;
98
99 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
100
101 return Status;
102 }
103
104
105 NTSTATUS AfdDispSendTo(
106 PIRP Irp,
107 PIO_STACK_LOCATION IrpSp)
108 /*
109 * FUNCTION: Sends data to an address
110 * ARGUMENTS:
111 * Irp = Pointer to I/O request packet
112 * IrpSp = Pointer to current stack location of Irp
113 * RETURNS:
114 * Status of operation
115 */
116 {
117 NTSTATUS Status;
118 UINT InputBufferLength;
119 UINT OutputBufferLength;
120 PFILE_REQUEST_SENDTO Request;
121 PFILE_REPLY_SENDTO Reply;
122 PAFDFCB FCB;
123 PVOID SystemVirtualAddress;
124 PVOID DataBufferAddress;
125 ULONG BufferSize;
126 ULONG BytesCopied;
127 PMDL Mdl;
128
129 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
130 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
131
132 /* Validate parameters */
133 if ((InputBufferLength >= sizeof(FILE_REQUEST_SENDTO)) &&
134 (OutputBufferLength >= sizeof(FILE_REPLY_SENDTO))) {
135
136 AFD_DbgPrint(MAX_TRACE, ("FileObject at (0x%X).\n", IrpSp->FileObject));
137 AFD_DbgPrint(MAX_TRACE, ("FCB at (0x%X).\n", IrpSp->FileObject->FsContext));
138 AFD_DbgPrint(MAX_TRACE, ("CCB at (0x%X).\n", IrpSp->FileObject->FsContext2));
139
140 FCB = IrpSp->FileObject->FsContext;
141 Request = (PFILE_REQUEST_SENDTO)Irp->AssociatedIrp.SystemBuffer;
142 Reply = (PFILE_REPLY_SENDTO)Irp->AssociatedIrp.SystemBuffer;
143 BufferSize = WSABufferSize(Request->Buffers, Request->BufferCount);
144
145
146 /* FIXME: Should we handle special cases here? */
147 if ((FCB->SocketType == SOCK_RAW) && (FCB->AddressFamily == AF_INET)) {
148 BufferSize += sizeof(IPv4_HEADER);
149 }
150
151
152 if (BufferSize != 0) {
153 AFD_DbgPrint(MAX_TRACE, ("Allocating %d bytes for send buffer.\n", BufferSize));
154 SystemVirtualAddress = ExAllocatePool(NonPagedPool, BufferSize);
155 if (!SystemVirtualAddress) {
156 return STATUS_INSUFFICIENT_RESOURCES;
157 }
158
159 /* FIXME: Should we handle special cases here? */
160 if ((FCB->SocketType == SOCK_RAW) && (FCB->AddressFamily == AF_INET)) {
161 DataBufferAddress = SystemVirtualAddress + sizeof(IPv4_HEADER);
162
163 /* FIXME: Should TCP/IP driver assign source address for raw sockets? */
164 ((PSOCKADDR_IN)&FCB->SocketName)->sin_addr.S_un.S_addr = 0x0100007F;
165
166 BuildIPv4Header(
167 (PIPv4_HEADER)SystemVirtualAddress,
168 BufferSize,
169 FCB->Protocol,
170 &FCB->SocketName,
171 &Request->To);
172 } else {
173 DataBufferAddress = SystemVirtualAddress;
174 }
175
176 Status = MergeWSABuffers(
177 Request->Buffers,
178 Request->BufferCount,
179 DataBufferAddress,
180 BufferSize,
181 &BytesCopied);
182 if (!NT_SUCCESS(Status)) {
183 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
184 return Status;
185 }
186 } else {
187 SystemVirtualAddress = NULL;
188 BytesCopied = 0;
189 }
190
191 Mdl = IoAllocateMdl(
192 SystemVirtualAddress, /* Virtual address of buffer */
193 BufferSize, /* Length of buffer */
194 FALSE, /* Not secondary */
195 FALSE, /* Don't charge quota */
196 NULL); /* Don't use IRP */
197 if (!Mdl) {
198 ExFreePool(SystemVirtualAddress);
199 return STATUS_INSUFFICIENT_RESOURCES;
200 }
201
202 MmBuildMdlForNonPagedPool(Mdl);
203
204 AFD_DbgPrint(MAX_TRACE, ("System virtual address is (0x%X).\n", SystemVirtualAddress));
205 AFD_DbgPrint(MAX_TRACE, ("MDL for data buffer is at (0x%X).\n", Mdl));
206
207 AFD_DbgPrint(MAX_TRACE, ("AFD.SYS: NDIS data buffer is at (0x%X).\n", Mdl));
208 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer MdlFlags is (0x%X).\n", Mdl->MdlFlags));
209 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer Next is at (0x%X).\n", Mdl->Next));
210 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer Size is (0x%X).\n", Mdl->Size));
211 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer MappedSystemVa is (0x%X).\n", Mdl->MappedSystemVa));
212 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer StartVa is (0x%X).\n", Mdl->StartVa));
213 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteCount is (0x%X).\n", Mdl->ByteCount));
214 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteOffset is (0x%X).\n", Mdl->ByteOffset));
215
216 #if 0
217 #ifdef _MSC_VER
218 try {
219 #endif
220 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
221 #ifdef _MSC_VER
222 } except(EXCEPTION_EXECUTE_HANDLER) {
223 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
224 IoFreeMdl(Mdl);
225 if (BufferSize != 0) {
226 ExFreePool(SystemVirtualAddress);
227 }
228 return STATUS_UNSUCCESSFUL;
229 }
230 #endif
231 #endif
232
233 Status = TdiSendDatagram(FCB->TdiAddressObject,
234 &Request->To,
235 Mdl,
236 BufferSize);
237
238 /* FIXME: Assumes synchronous operation */
239 #if 0
240 MmUnlockPages(Mdl);
241 #endif
242
243 IoFreeMdl(Mdl);
244
245 if (BufferSize != 0) {
246 ExFreePool(SystemVirtualAddress);
247 }
248
249 Reply->NumberOfBytesSent = BufferSize;
250 Reply->Status = NO_ERROR;
251 } else
252 Status = STATUS_INVALID_PARAMETER;
253
254 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
255
256 return Status;
257 }
258
259
260 NTSTATUS AfdDispRecvFrom(
261 PIRP Irp,
262 PIO_STACK_LOCATION IrpSp)
263 /*
264 * FUNCTION: Receives data from an address
265 * ARGUMENTS:
266 * Irp = Pointer to I/O request packet
267 * IrpSp = Pointer to current stack location of Irp
268 * RETURNS:
269 * Status of operation
270 */
271 {
272 NTSTATUS Status;
273 UINT InputBufferLength;
274 UINT OutputBufferLength;
275 PFILE_REQUEST_RECVFROM Request;
276 PFILE_REPLY_RECVFROM Reply;
277 PAFD_READ_REQUEST ReadRequest;
278 KIRQL OldIrql;
279 PAFDFCB FCB;
280
281 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
282
283 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
284 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
285
286 /* Validate parameters */
287 if ((InputBufferLength >= sizeof(FILE_REQUEST_RECVFROM)) &&
288 (OutputBufferLength >= sizeof(FILE_REPLY_RECVFROM))) {
289 FCB = IrpSp->FileObject->FsContext;
290
291 Request = (PFILE_REQUEST_RECVFROM)Irp->AssociatedIrp.SystemBuffer;
292 Reply = (PFILE_REPLY_RECVFROM)Irp->AssociatedIrp.SystemBuffer;
293
294 KeAcquireSpinLock(&FCB->ReadRequestQueueLock, &OldIrql);
295
296 if (IsListEmpty(&FCB->ReadRequestQueue)) {
297 /* Queue request and return STATUS_PENDING */
298 ReadRequest->Irp = Irp;
299 ReadRequest->RecvFromRequest = Request;
300 ReadRequest->RecvFromReply = Reply;
301 InsertTailList(&FCB->ReadRequestQueue, &ReadRequest->ListEntry);
302 KeReleaseSpinLock(&FCB->ReadRequestQueueLock, OldIrql);
303 Status = STATUS_PENDING;
304 } else {
305 /* Satisfy the request at once */
306 Status = FillWSABuffers(
307 FCB,
308 Request->Buffers,
309 Request->BufferCount,
310 &Reply->NumberOfBytesRecvd);
311 KeReleaseSpinLock(&FCB->ReadRequestQueueLock, OldIrql);
312 Reply->Status = NO_ERROR;
313 }
314 } else
315 Status = STATUS_INVALID_PARAMETER;
316
317 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
318
319 return Status;
320 }
321
322
323 NTSTATUS AfdDispSelect(
324 PIRP Irp,
325 PIO_STACK_LOCATION IrpSp)
326 /*
327 * FUNCTION: Checks if sockets have data in the receive buffers
328 * ARGUMENTS:
329 * Irp = Pointer to I/O request packet
330 * IrpSp = Pointer to current stack location of Irp
331 * RETURNS:
332 * Status of operation
333 */
334 {
335 NTSTATUS Status;
336 UINT InputBufferLength;
337 UINT OutputBufferLength;
338 PFILE_REQUEST_SELECT Request;
339 PFILE_REPLY_SELECT Reply;
340 PAFDFCB FCB;
341
342 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
343 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
344
345 /* Validate parameters */
346 if ((InputBufferLength >= sizeof(FILE_REQUEST_SELECT)) &&
347 (OutputBufferLength >= sizeof(FILE_REPLY_SELECT))) {
348 FCB = IrpSp->FileObject->FsContext;
349
350 Request = (PFILE_REQUEST_SELECT)Irp->AssociatedIrp.SystemBuffer;
351 Reply = (PFILE_REPLY_SELECT)Irp->AssociatedIrp.SystemBuffer;
352 } else
353 Status = STATUS_INVALID_PARAMETER;
354
355 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
356
357 return Status;
358 }
359
360 /* EOF */