2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/routines.c
5 * PURPOSE: Common routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
15 UINT RandomNumber = 0x12345678;
18 inline NTSTATUS BuildDatagramSendRequest(
19 PDATAGRAM_SEND_REQUEST *SendRequest,
20 PIP_ADDRESS RemoteAddress,
24 DATAGRAM_COMPLETION_ROUTINE Complete,
26 DATAGRAM_BUILD_ROUTINE Build,
29 * FUNCTION: Allocates and intializes a datagram send request
31 * SendRequest = Pointer to datagram send request
32 * RemoteAddress = Pointer to remote IP address
33 * RemotePort = Remote port number
34 * Buffer = Pointer to NDIS buffer to send
35 * BufferSize = Size of Buffer
36 * Complete = Completion routine
37 * Context = Pointer to context information
38 * Build = Datagram build routine
39 * Flags = Protocol specific flags
44 PDATAGRAM_SEND_REQUEST Request;
46 Request = ExAllocatePool(NonPagedPool, sizeof(DATAGRAM_SEND_REQUEST));
48 return STATUS_INSUFFICIENT_RESOURCES;
50 InitializeDatagramSendRequest(
61 *SendRequest = Request;
63 return STATUS_SUCCESS;
67 inline NTSTATUS BuildTCPSendRequest(
68 PTCP_SEND_REQUEST *SendRequest,
69 DATAGRAM_COMPLETION_ROUTINE Complete,
71 PVOID ProtocolContext)
73 * FUNCTION: Allocates and intializes a TCP send request
75 * SendRequest = Pointer to TCP send request
76 * Complete = Completion routine
77 * Context = Pointer to context information
78 * ProtocolContext = Protocol specific context
83 PTCP_SEND_REQUEST Request;
85 Request = ExAllocatePool(NonPagedPool, sizeof(TCP_SEND_REQUEST));
87 return STATUS_INSUFFICIENT_RESOURCES;
89 InitializeTCPSendRequest(
95 *SendRequest = Request;
97 return STATUS_SUCCESS;
104 * FUNCTION: Returns a pseudo random number
106 * Pseudo random number
109 RandomNumber ^= 0x78563412;
115 __inline INT SkipToOffset(
121 * FUNCTION: Skip Offset bytes into a buffer chain
123 * Buffer = Pointer to NDIS buffer
124 * Offset = Number of bytes to skip
125 * Data = Address of a pointer that on return will contain the
126 * address of the offset in the buffer
127 * Size = Address of a pointer that on return will contain the
128 * size of the destination buffer
130 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
140 NdisQueryBuffer(Buffer, Data, Size);
142 if (Offset < *Size) {
143 ((ULONG_PTR)*Data) += Offset;
150 NdisGetNextBuffer(Buffer, &Buffer);
157 UINT CopyBufferToBufferChain(
158 PNDIS_BUFFER DstBuffer,
163 * FUNCTION: Copies data from a buffer to an NDIS buffer chain
165 * DstBuffer = Pointer to destination NDIS buffer
166 * DstOffset = Destination start offset
167 * SrcData = Pointer to source buffer
168 * Length = Number of bytes to copy
170 * Number of bytes copied to destination buffer
172 * The number of bytes copied may be limited by the destination
176 UINT BytesCopied, BytesToCopy, DstSize;
179 TI_DbgPrint(DEBUG_BUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length));
181 /* Skip DstOffset bytes in the destination buffer chain */
182 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
185 /* Start copying the data */
188 BytesToCopy = MIN(DstSize, Length);
190 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
191 BytesCopied += BytesToCopy;
192 (ULONG_PTR)SrcData += BytesToCopy;
194 Length -= BytesToCopy;
198 DstSize -= BytesToCopy;
200 /* No more bytes in desination buffer. Proceed to
201 the next buffer in the destination buffer chain */
202 NdisGetNextBuffer(DstBuffer, &DstBuffer);
206 NdisQueryBuffer(DstBuffer, &DstData, &DstSize);
214 UINT CopyBufferChainToBuffer(
216 PNDIS_BUFFER SrcBuffer,
220 * FUNCTION: Copies data from an NDIS buffer chain to a buffer
222 * DstData = Pointer to destination buffer
223 * SrcBuffer = Pointer to source NDIS buffer
224 * SrcOffset = Source start offset
225 * Length = Number of bytes to copy
227 * Number of bytes copied to destination buffer
229 * The number of bytes copied may be limited by the source
233 UINT BytesCopied, BytesToCopy, SrcSize;
236 TI_DbgPrint(DEBUG_BUFFER, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length));
238 /* Skip SrcOffset bytes in the source buffer chain */
239 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
242 /* Start copying the data */
245 BytesToCopy = MIN(SrcSize, Length);
247 TI_DbgPrint(DEBUG_BUFFER, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData));
249 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
250 BytesCopied += BytesToCopy;
251 (ULONG_PTR)DstData += BytesToCopy;
253 Length -= BytesToCopy;
257 SrcSize -= BytesToCopy;
259 /* No more bytes in source buffer. Proceed to
260 the next buffer in the source buffer chain */
261 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
265 NdisQueryBuffer(SrcBuffer, &SrcData, &SrcSize);
273 UINT CopyPacketToBuffer(
275 PNDIS_PACKET SrcPacket,
279 * FUNCTION: Copies data from an NDIS packet to a buffer
281 * DstData = Pointer to destination buffer
282 * SrcPacket = Pointer to source NDIS packet
283 * SrcOffset = Source start offset
284 * Length = Number of bytes to copy
286 * Number of bytes copied to destination buffer
288 * The number of bytes copied may be limited by the source
292 PNDIS_BUFFER FirstBuffer;
297 TI_DbgPrint(DEBUG_BUFFER, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length));
299 NdisGetFirstBufferFromPacket(SrcPacket,
305 return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length);
309 UINT CopyPacketToBufferChain(
310 PNDIS_BUFFER DstBuffer,
312 PNDIS_PACKET SrcPacket,
316 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
318 * DstBuffer = Pointer to destination NDIS buffer
319 * DstOffset = Destination start offset
320 * SrcPacket = Pointer to source NDIS packet
321 * SrcOffset = Source start offset
322 * Length = Number of bytes to copy
324 * Number of bytes copied to destination buffer
326 * The number of bytes copied may be limited by the source and
327 * destination buffer sizes
330 PNDIS_BUFFER SrcBuffer;
331 PUCHAR DstData, SrcData;
332 UINT DstSize, SrcSize;
335 TI_DbgPrint(DEBUG_BUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length));
337 /* Skip DstOffset bytes in the destination buffer chain */
338 NdisQueryBuffer(DstBuffer, &DstData, &DstSize);
339 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
342 /* Skip SrcOffset bytes in the source packet */
343 NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, &SrcData, &SrcSize, &Total);
344 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
349 /* Find out how many bytes we can copy at one time */
350 if (Length < SrcSize)
357 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);
366 /* No more bytes in destination buffer. Proceed to
367 the next buffer in the destination buffer chain */
368 NdisGetNextBuffer(DstBuffer, &DstBuffer);
372 NdisQueryBuffer(DstBuffer, &DstData, &DstSize);
377 /* No more bytes in source buffer. Proceed to
378 the next buffer in the source buffer chain */
379 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
383 NdisQueryBuffer(SrcBuffer, &SrcData, &SrcSize);
394 * FUNCTION: Frees an NDIS packet
396 * Packet = Pointer to NDIS packet to be freed
399 PNDIS_BUFFER Buffer, NextBuffer;
401 TI_DbgPrint(DEBUG_BUFFER, ("Packet (0x%X)\n", Packet));
403 /* Free all the buffers in the packet first */
404 NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
405 for (; Buffer != NULL; Buffer = NextBuffer) {
409 NdisGetNextBuffer(Buffer, &NextBuffer);
410 NdisQueryBuffer(Buffer, &Data, &Length);
411 NdisFreeBuffer(Buffer);
415 /* Finally free the NDIS packet discriptor */
416 NdisFreePacket(Packet);
425 * FUNCTION: Adjusts the amount of unused space at the beginning of the packet
427 * Packet = Pointer to packet
428 * Available = Number of bytes available at start of first buffer
429 * Needed = Number of bytes needed for the header
431 * Pointer to start of packet
434 PNDIS_BUFFER NdisBuffer;
437 TI_DbgPrint(DEBUG_BUFFER, ("Available = %d, Needed = %d.\n", Available, Needed));
439 Adjust = Available - Needed;
441 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
443 /* If Adjust is zero there is no need to adjust this packet as
444 there is no additional space at start the of first buffer */
446 (ULONG_PTR)(NdisBuffer->MappedSystemVa) += Adjust;
447 NdisBuffer->ByteOffset += Adjust;
448 NdisBuffer->ByteCount -= Adjust;
451 return NdisBuffer->MappedSystemVa;
459 * FUNCTION: Resizes an NDIS packet
461 * Packet = Pointer to packet
462 * Size = Number of bytes in first buffer
464 * Previous size of first buffer
467 PNDIS_BUFFER NdisBuffer;
470 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
472 OldSize = NdisBuffer->ByteCount;
475 NdisBuffer->ByteCount = Size;
482 VOID DisplayIPPacket(
489 PNDIS_BUFFER NextBuffer;
491 if ((DebugTraceLevel & DEBUG_BUFFER) == 0) {
496 TI_DbgPrint(MIN_TRACE, ("Cannot display null packet.\n"));
500 TI_DbgPrint(MIN_TRACE, ("IPPacket is at (0x%X).\n", IPPacket));
501 TI_DbgPrint(MIN_TRACE, ("Header buffer is at (0x%X).\n", IPPacket->Header));
502 TI_DbgPrint(MIN_TRACE, ("Header size is (%d).\n", IPPacket->HeaderSize));
503 TI_DbgPrint(MIN_TRACE, ("TotalSize (%d).\n", IPPacket->TotalSize));
504 TI_DbgPrint(MIN_TRACE, ("ContigSize (%d).\n", IPPacket->ContigSize));
505 TI_DbgPrint(MIN_TRACE, ("NdisPacket (0x%X).\n", IPPacket->NdisPacket));
507 if (IPPacket->NdisPacket) {
508 NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, &Buffer, NULL);
509 for (; Buffer != NULL; Buffer = NextBuffer) {
510 NdisGetNextBuffer(Buffer, &NextBuffer);
511 NdisQueryBuffer(Buffer, (PVOID)&p, &Length);
513 for (i = 0; i < Length; i++) {
516 DbgPrint("%02X ", (p[i]) & 0xFF);
521 p = IPPacket->Header;
522 Length = IPPacket->ContigSize;
523 for (i = 0; i < Length; i++) {
526 DbgPrint("%02X ", (p[i]) & 0xFF);