04b0f55ab3ebd45d75e1eed140f190d74a3d756c
[reactos.git] / reactos / drivers / lib / 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 VOID DGDeliverData(
14 PADDRESS_FILE AddrFile,
15 PIP_ADDRESS SrcAddress,
16 PIP_ADDRESS DstAddress,
17 USHORT SrcPort,
18 USHORT DstPort,
19 PIP_PACKET IPPacket,
20 UINT DataSize)
21 /*
22 * FUNCTION: Delivers datagram data to a user
23 * ARGUMENTS:
24 * AddrFile = Address file to deliver data to
25 * Address = Remote address the packet came from
26 * IPPacket = Pointer to IP packet to deliver
27 * DataSize = Number of bytes in data area
28 * (incl. IP header for raw IP file objects)
29 * NOTES:
30 * If there is a receive request, then we copy the data to the
31 * buffer supplied by the user and complete the receive request.
32 * If no suitable receive request exists, then we call the event
33 * handler if it exists, otherwise we drop the packet.
34 */
35 {
36 KIRQL OldIrql;
37 PTDI_IND_RECEIVE_DATAGRAM ReceiveHandler;
38 PVOID HandlerContext;
39 LONG AddressLength;
40 PVOID SourceAddress;
41 ULONG BytesTaken;
42 NTSTATUS Status;
43 PVOID DataBuffer;
44
45 TI_DbgPrint(MAX_TRACE, ("Called.\n"));
46
47 TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
48
49 if (AddrFile->Protocol == IPPROTO_UDP)
50 {
51 DataBuffer = IPPacket->Data;
52 }
53 else
54 {
55 /* Give client the IP header too if it is a raw IP file object */
56 DataBuffer = IPPacket->Header;
57 }
58
59 if (!IsListEmpty(&AddrFile->ReceiveQueue))
60 {
61 PLIST_ENTRY CurrentEntry;
62 PDATAGRAM_RECEIVE_REQUEST Current = NULL;
63 BOOLEAN Found;
64 PTA_IP_ADDRESS RTAIPAddress;
65
66 TI_DbgPrint(MAX_TRACE, ("There is a receive request.\n"));
67
68 /* Search receive request list to find a match */
69 Found = FALSE;
70 CurrentEntry = AddrFile->ReceiveQueue.Flink;
71 while((CurrentEntry != &AddrFile->ReceiveQueue) && (!Found)) {
72 Current = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
73
74 if( DstPort == AddrFile->Port ) {
75 Found = TRUE;
76 /* Remove the request from the queue */
77 RemoveEntryList(&Current->ListEntry);
78 break;
79 } else {
80 CurrentEntry = CurrentEntry->Flink;
81 }
82 }
83
84 TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
85
86 if (Found)
87 {
88 TI_DbgPrint(MAX_TRACE, ("Suitable receive request found.\n"));
89
90 TI_DbgPrint(MAX_TRACE,
91 ("Target Buffer: %x, Source Buffer: %x, Size %d\n",
92 Current->Buffer, DataBuffer, DataSize));
93
94 /* Copy the data into buffer provided by the user */
95 RtlCopyMemory( Current->Buffer,
96 DataBuffer,
97 DataSize );
98
99 RTAIPAddress = (PTA_IP_ADDRESS)Current->ReturnInfo->RemoteAddress;
100 RTAIPAddress->TAAddressCount = 1;
101 RTAIPAddress->Address->AddressType = TDI_ADDRESS_TYPE_IP;
102 RTAIPAddress->Address->Address->sin_port = SrcPort;
103
104 TI_DbgPrint(MAX_TRACE, ("(A: %08x) Addr %08x Port %04x\n",
105 RTAIPAddress,
106 SrcAddress->Address.IPv4Address, SrcPort));
107
108 RtlCopyMemory( &RTAIPAddress->Address->Address->in_addr,
109 &SrcAddress->Address.IPv4Address,
110 sizeof(SrcAddress->Address.IPv4Address) );
111
112 /* Complete the receive request */
113 Current->Complete(Current->Context, STATUS_SUCCESS, DataSize);
114 }
115 }
116 else if (AddrFile->RegisteredReceiveDatagramHandler)
117 {
118 TI_DbgPrint(MAX_TRACE, ("Calling receive event handler.\n"));
119
120 ReceiveHandler = AddrFile->ReceiveDatagramHandler;
121 HandlerContext = AddrFile->ReceiveDatagramHandlerContext;
122
123 TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
124
125 if (SrcAddress->Type == IP_ADDRESS_V4)
126 {
127 AddressLength = sizeof(IPv4_RAW_ADDRESS);
128 SourceAddress = &SrcAddress->Address.IPv4Address;
129 }
130 else /* (Address->Type == IP_ADDRESS_V6) */
131 {
132 AddressLength = sizeof(IPv6_RAW_ADDRESS);
133 SourceAddress = SrcAddress->Address.IPv6Address;
134 }
135
136 Status = (*ReceiveHandler)(HandlerContext,
137 AddressLength,
138 SourceAddress,
139 0,
140 NULL,
141 TDI_RECEIVE_ENTIRE_MESSAGE,
142 DataSize,
143 DataSize,
144 &BytesTaken,
145 DataBuffer,
146 NULL);
147 }
148 else
149 {
150 TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n"));
151 }
152
153 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
154 }
155