2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: transport/rawip/rawip.c
5 * PURPOSE: User Datagram Protocol routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
13 NTSTATUS
AddGenericHeaderIPv4(
14 PIP_ADDRESS RemoteAddress
,
16 PIP_ADDRESS LocalAddress
,
24 * FUNCTION: Adds an IPv4 and RawIp header to an IP packet
26 * SendRequest = Pointer to send request
27 * LocalAddress = Pointer to our local address
28 * LocalPort = The port we send this datagram from
29 * IPPacket = Pointer to IP packet
34 PIPv4_HEADER IPHeader
;
37 TI_DbgPrint(MID_TRACE
, ("Packet: %x NdisPacket %x\n",
38 IPPacket
, IPPacket
->NdisPacket
));
40 BufferSize
= sizeof(IPv4_HEADER
) + ExtraLength
;
42 GetDataPtr( IPPacket
->NdisPacket
,
44 (PCHAR
*)&IPPacket
->Header
,
45 &IPPacket
->ContigSize
);
47 IPPacket
->HeaderSize
= 20;
49 TI_DbgPrint(MAX_TRACE
, ("Allocated %d bytes for headers at 0x%X.\n",
50 BufferSize
, IPPacket
->Header
));
51 TI_DbgPrint(MAX_TRACE
, ("Packet total length %d\n", IPPacket
->TotalSize
));
53 /* Build IPv4 header */
54 IPHeader
= (PIPv4_HEADER
)IPPacket
->Header
;
55 /* Version = 4, Length = 5 DWORDs */
56 IPHeader
->VerIHL
= 0x45;
57 /* Normal Type-of-Service */
59 /* Length of header and data */
60 IPHeader
->TotalLength
= WH2N((USHORT
)IPPacket
->TotalSize
);
62 IPHeader
->Id
= (USHORT
)Random();
63 /* One fragment at offset 0 */
64 IPHeader
->FlagsFragOfs
= 0;
65 /* Time-to-Live is 128 */
67 /* User Datagram Protocol */
68 IPHeader
->Protocol
= Protocol
;
69 /* Checksum is 0 (for later calculation of this) */
70 IPHeader
->Checksum
= 0;
72 IPHeader
->SrcAddr
= LocalAddress
->Address
.IPv4Address
;
73 /* Destination address. FIXME: IPv4 only */
74 IPHeader
->DstAddr
= RemoteAddress
->Address
.IPv4Address
;
76 /* Build RawIp header */
77 *NextHeader
= (((PCHAR
)IPHeader
) + sizeof(IPv4_HEADER
));
78 IPPacket
->Data
= ((PCHAR
)*NextHeader
) + ExtraLength
;
80 return STATUS_SUCCESS
;
84 NTSTATUS
BuildRawIpPacket(
86 PIP_ADDRESS RemoteAddress
,
88 PIP_ADDRESS LocalAddress
,
93 * FUNCTION: Builds an RawIp packet
95 * Context = Pointer to context information (DATAGRAM_SEND_REQUEST)
96 * LocalAddress = Pointer to our local address
97 * LocalPort = The port we send this datagram from
98 * IPPacket = Address of pointer to IP packet
100 * Status of operation
106 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
108 /* FIXME: Assumes IPv4 */
109 IPInitializePacket(Packet
, IP_ADDRESS_V4
);
111 Packet
->TotalSize
= sizeof(IPv4_HEADER
) + DataLen
;
114 Status
= AllocatePacketWithBuffer( &Packet
->NdisPacket
,
118 if( !NT_SUCCESS(Status
) ) return Status
;
120 TI_DbgPrint(MID_TRACE
, ("Allocated packet: %x\n", Packet
->NdisPacket
));
121 TI_DbgPrint(MID_TRACE
, ("Local Addr : %s\n", A2S(LocalAddress
)));
122 TI_DbgPrint(MID_TRACE
, ("Remote Addr: %s\n", A2S(RemoteAddress
)));
124 switch (RemoteAddress
->Type
) {
126 Status
= AddGenericHeaderIPv4
127 (RemoteAddress
, RemotePort
,
128 LocalAddress
, LocalPort
, Packet
, DataLen
,
130 0, (PVOID
*)&Payload
);
133 /* FIXME: Support IPv6 */
134 Status
= STATUS_UNSUCCESSFUL
;
135 TI_DbgPrint(MIN_TRACE
, ("IPv6 RawIp datagrams are not supported.\n"));
139 Status
= STATUS_UNSUCCESSFUL
;
140 TI_DbgPrint(MIN_TRACE
, ("Bad Address Type %d\n", RemoteAddress
->Type
));
144 if( !NT_SUCCESS(Status
) ) {
145 TI_DbgPrint(MIN_TRACE
, ("Cannot add header. Status = (0x%X)\n",
147 FreeNdisPacket(Packet
->NdisPacket
);
151 TI_DbgPrint(MID_TRACE
, ("Copying data (hdr %x data %x (%d))\n",
152 Packet
->Header
, Packet
->Data
,
153 (PCHAR
)Packet
->Data
- (PCHAR
)Packet
->Header
));
155 RtlCopyMemory( Packet
->Data
, DataBuffer
, DataLen
);
157 Packet
->Flags
|= IP_PACKET_FLAG_RAW
;
159 TI_DbgPrint(MID_TRACE
, ("Displaying packet\n"));
161 DISPLAY_IP_PACKET(Packet
);
163 TI_DbgPrint(MID_TRACE
, ("Leaving\n"));
165 return STATUS_SUCCESS
;
168 VOID RawIpSendPacketComplete
169 ( PVOID Context
, PNDIS_PACKET Packet
, NDIS_STATUS Status
) {
170 FreeNdisPacket( Packet
);
173 NTSTATUS
RawIPSendDatagram(
174 PADDRESS_FILE AddrFile
,
175 PTDI_CONNECTION_INFORMATION ConnInfo
,
180 * FUNCTION: Sends an RawIp datagram to a remote address
182 * Request = Pointer to TDI request
183 * ConnInfo = Pointer to connection information
184 * Buffer = Pointer to NDIS buffer with data
185 * DataSize = Size in bytes of data to be sent
187 * Status of operation
191 PTA_IP_ADDRESS RemoteAddressTa
= (PTA_IP_ADDRESS
)ConnInfo
->RemoteAddress
;
192 IP_ADDRESS RemoteAddress
, LocalAddress
;
195 PNEIGHBOR_CACHE_ENTRY NCE
;
197 TI_DbgPrint(MID_TRACE
,("Sending Datagram(%x %x %x %d)\n",
198 AddrFile
, ConnInfo
, BufferData
, DataSize
));
199 TI_DbgPrint(MID_TRACE
,("RemoteAddressTa: %x\n", RemoteAddressTa
));
201 switch( RemoteAddressTa
->Address
[0].AddressType
) {
202 case TDI_ADDRESS_TYPE_IP
:
203 RemoteAddress
.Type
= IP_ADDRESS_V4
;
204 RemoteAddress
.Address
.IPv4Address
=
205 RemoteAddressTa
->Address
[0].Address
[0].in_addr
;
206 RemotePort
= RemoteAddressTa
->Address
[0].Address
[0].sin_port
;
210 return STATUS_UNSUCCESSFUL
;
213 TI_DbgPrint(MID_TRACE
,("About to get route to destination\n"));
215 if(!(NCE
= RouteGetRouteToDestination( &RemoteAddress
)))
216 return STATUS_NETWORK_UNREACHABLE
;
218 LocalAddress
= AddrFile
->Address
;
219 if (AddrIsUnspecified(&LocalAddress
))
221 /* If the local address is unspecified (0),
222 * then use the unicast address of the
223 * interface we're sending over
225 LocalAddress
= NCE
->Interface
->Unicast
;
228 Status
= BuildRawIpPacket( &Packet
,
236 if( !NT_SUCCESS(Status
) )
239 TI_DbgPrint(MID_TRACE
,("About to send datagram\n"));
241 if (!NT_SUCCESS(Status
= IPSendDatagram( &Packet
, NCE
, RawIpSendPacketComplete
, NULL
)))
243 FreeNdisPacket(Packet
.NdisPacket
);
247 TI_DbgPrint(MID_TRACE
,("Leaving\n"));
249 return STATUS_SUCCESS
;
253 VOID
RawIpReceive(PIP_INTERFACE Interface
, PIP_PACKET IPPacket
)
255 * FUNCTION: Receives and queues a RawIp datagram
257 * NTE = Pointer to net table entry which the packet was received on
258 * IPPacket = Pointer to an IP packet that was received
260 * This is the low level interface for receiving RawIp datagrams. It strips
261 * the RawIp header from a packet and delivers the data to anyone that wants it
264 AF_SEARCH SearchContext
;
265 PIPv4_HEADER IPv4Header
;
266 PADDRESS_FILE AddrFile
;
267 PIP_ADDRESS DstAddress
, SrcAddress
;
270 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
272 switch (IPPacket
->Type
) {
275 IPv4Header
= IPPacket
->Header
;
276 DstAddress
= &IPPacket
->DstAddr
;
277 SrcAddress
= &IPPacket
->SrcAddr
;
278 DataSize
= IPPacket
->TotalSize
;
283 TI_DbgPrint(MIN_TRACE
, ("Discarded IPv6 datagram (%i bytes).\n", IPPacket
->TotalSize
));
285 /* FIXME: IPv6 is not supported */
292 /* Locate a receive request on destination address file object
293 and deliver the packet if one is found. If there is no receive
294 request on the address file object, call the associated receive
295 handler. If no receive handler is registered, drop the packet */
297 AddrFile
= AddrSearchFirst(DstAddress
,
299 IPv4Header
->Protocol
,
303 DGDeliverData(AddrFile
,
310 } while ((AddrFile
= AddrSearchNext(&SearchContext
)) != NULL
);
312 /* There are no open address files that will take this datagram */
313 /* FIXME: IPv4 only */
314 TI_DbgPrint(MID_TRACE
, ("Cannot deliver IPv4 raw datagram to address (0x%X).\n",
315 DN2H(DstAddress
->Address
.IPv4Address
)));
317 /* FIXME: Send ICMP reply */
319 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
323 NTSTATUS
RawIPStartup(VOID
)
325 * FUNCTION: Initializes the UDP subsystem
327 * Status of operation
331 RtlZeroMemory(&UDPStats
, sizeof(UDP_STATISTICS
));
334 /* Register this protocol with IP layer */
335 IPRegisterProtocol(IPPROTO_RAW
, RawIpReceive
);
337 return STATUS_SUCCESS
;
341 NTSTATUS
RawIPShutdown(VOID
)
343 * FUNCTION: Shuts down the UDP subsystem
345 * Status of operation
348 /* Deregister this protocol with IP layer */
349 IPRegisterProtocol(IPPROTO_RAW
, NULL
);
351 return STATUS_SUCCESS
;