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