f7e1d0c8b5e439421dc6f8602d59563ecf77b276
[reactos.git] / reactos / drivers / lib / ip / transport / rawip / rawip.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: transport/rawip/rawip.c
5 * PURPOSE: Raw IP routines
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
14 BOOLEAN RawIPInitialized = FALSE;
15
16
17 NTSTATUS BuildRawIPPacket(
18 PIP_PACKET Packet,
19 UINT DataLength,
20 PIP_ADDRESS LocalAddress,
21 USHORT LocalPort )
22 /*
23 * FUNCTION: Builds an UDP packet
24 * ARGUMENTS:
25 * Context = Pointer to context information (DATAGRAM_SEND_REQUEST)
26 * LocalAddress = Pointer to our local address (NULL)
27 * LocalPort = The port we send this datagram from (0)
28 * IPPacket = Address of pointer to IP packet
29 * RETURNS:
30 * Status of operation
31 */
32 {
33 PVOID Header;
34 NDIS_STATUS NdisStatus;
35 PNDIS_BUFFER HeaderBuffer;
36 PNDIS_PACKET NdisPacket = Packet->NdisPacket;
37 /* Will be zeroed in packet by IPInitializePacket */
38
39 /* Prepare packet */
40 IPInitializePacket(Packet,IP_ADDRESS_V4);
41 Packet->Flags = IP_PACKET_FLAG_RAW; /* Don't touch IP header */
42 Packet->TotalSize = DataLength;
43 Packet->NdisPacket = NdisPacket;
44
45 if (MaxLLHeaderSize != 0) {
46 Header = ExAllocatePool(NonPagedPool, MaxLLHeaderSize);
47 if (!Header) {
48 TI_DbgPrint(MIN_TRACE, ("Cannot allocate memory for packet headers.\n"));
49 return STATUS_INSUFFICIENT_RESOURCES;
50 }
51
52 TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n",
53 MaxLLHeaderSize, Header));
54
55 /* Allocate NDIS buffer for maximum link level header */
56 NdisAllocateBuffer(&NdisStatus,
57 &HeaderBuffer,
58 GlobalBufferPool,
59 Header,
60 MaxLLHeaderSize);
61
62 if (NdisStatus != NDIS_STATUS_SUCCESS) {
63 TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS buffer for packet headers. NdisStatus = (0x%X)\n", NdisStatus));
64 ExFreePool(Header);
65 return STATUS_INSUFFICIENT_RESOURCES;
66 }
67
68 /* Chain header at front of packet */
69 NdisChainBufferAtFront(Packet->NdisPacket, HeaderBuffer);
70 }
71
72 DISPLAY_IP_PACKET(Packet);
73
74 return STATUS_SUCCESS;
75 }
76
77 VOID RawIPSendComplete
78 ( PVOID Context, PNDIS_PACKET Packet, NDIS_STATUS Status ) {
79 FreeNdisPacket( Packet );
80 }
81
82 NTSTATUS RawIPSendDatagram(
83 PADDRESS_FILE AddrFile,
84 PTDI_CONNECTION_INFORMATION ConnInfo,
85 PCHAR BufferData,
86 ULONG BufferLen,
87 PULONG DataUsed )
88 /*
89 * FUNCTION: Sends a raw IP datagram to a remote address
90 * ARGUMENTS:
91 * Request = Pointer to TDI request
92 * ConnInfo = Pointer to connection information
93 * Buffer = Pointer to NDIS buffer with data
94 * DataSize = Size in bytes of data to be sent
95 * RETURNS:
96 * Status of operation
97 */
98 {
99 NDIS_STATUS Status;
100 IP_PACKET Packet;
101 PROUTE_CACHE_NODE RCN;
102 IP_ADDRESS RemoteAddress;
103
104 Status = AllocatePacketWithBuffer( &Packet.NdisPacket,
105 BufferData,
106 BufferLen );
107
108 TI_DbgPrint(MID_TRACE,("Packet.NdisPacket %x\n", Packet.NdisPacket));
109
110 *DataUsed = BufferLen;
111
112 if( Status == NDIS_STATUS_SUCCESS )
113 Status = BuildRawIPPacket( &Packet,
114 BufferLen,
115 &AddrFile->ADE->Address,
116 AddrFile->Port );
117
118 if( Status == NDIS_STATUS_SUCCESS ) {
119 RemoteAddress.Type = IP_ADDRESS_V4;
120 RtlCopyMemory( &RemoteAddress.Address.IPv4Address,
121 BufferData + FIELD_OFFSET(IPv4_HEADER, DstAddr),
122 sizeof(IPv4_RAW_ADDRESS) );
123
124 Status = RouteGetRouteToDestination( &RemoteAddress, NULL, &RCN );
125
126 if( !NT_SUCCESS(Status) ) {
127 FreeNdisPacket( Packet.NdisPacket );
128 return Status;
129 }
130
131 IPSendDatagram( &Packet, RCN, RawIPSendComplete, NULL );
132 } else
133 FreeNdisPacket( Packet.NdisPacket );
134
135 return Status;
136 }
137
138
139 VOID RawIPReceive(
140 PNET_TABLE_ENTRY NTE,
141 PIP_PACKET IPPacket)
142 /*
143 * FUNCTION: Receives and queues a raw IP datagram
144 * ARGUMENTS:
145 * NTE = Pointer to net table entry which the packet was received on
146 * IPPacket = Pointer to an IP packet that was received
147 * NOTES:
148 * This is the low level interface for receiving ICMP datagrams.
149 * It delivers the packet header and data to anyone that wants it
150 * When we get here the datagram has already passed sanity checks
151 */
152 {
153 PIP_ADDRESS DstAddress;
154
155 TI_DbgPrint(MAX_TRACE, ("Called.\n"));
156
157 switch (IPPacket->Type) {
158 /* IPv4 packet */
159 case IP_ADDRESS_V4:
160 DstAddress = &IPPacket->DstAddr;
161 break;
162
163 /* IPv6 packet */
164 case IP_ADDRESS_V6:
165 TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 raw IP datagram (%i bytes).\n",
166 IPPacket->TotalSize));
167
168 /* FIXME: IPv6 is not supported */
169 return;
170
171 default:
172 return;
173 }
174
175 /* Locate a receive request on destination address file object
176 and deliver the packet if one is found. If there is no receive
177 request on the address file object, call the associated receive
178 handler. If no receive handler is registered, drop the packet */
179
180 #if 0 /* Decide what to do here */
181 AddrFile = AddrSearchFirst(DstAddress,
182 0,
183 IPPROTO_ICMP,
184 &SearchContext);
185 if (AddrFile) {
186 do {
187 DGDeliverData(AddrFile,
188 DstAddress,
189 IPPacket,
190 IPPacket->TotalSize);
191 } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL);
192 } else {
193 /* There are no open address files that will take this datagram */
194 /* FIXME: IPv4 only */
195 TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 ICMP datagram to address (0x%X).\n",
196 DN2H(DstAddress->Address.IPv4Address)));
197 }
198 #endif
199 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
200 }
201
202
203 NTSTATUS RawIPStartup(
204 VOID)
205 /*
206 * FUNCTION: Initializes the Raw IP subsystem
207 * RETURNS:
208 * Status of operation
209 */
210 {
211 RawIPInitialized = TRUE;
212
213 return STATUS_SUCCESS;
214 }
215
216
217 NTSTATUS RawIPShutdown(
218 VOID)
219 /*
220 * FUNCTION: Shuts down the Raw IP subsystem
221 * RETURNS:
222 * Status of operation
223 */
224 {
225 if (!RawIPInitialized)
226 return STATUS_SUCCESS;
227
228 return STATUS_SUCCESS;
229 }
230
231 /* EOF */