ReactOS  0.4.14-dev-614-gbfd8a84
udp.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS TCP/IP protocol driver
4  * FILE: transport/udp/udp.c
5  * PURPOSE: User Datagram Protocol 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 
15 
17  PADDRESS_FILE AddrFile,
19  USHORT RemotePort,
21  USHORT LocalPort,
22  PIP_PACKET IPPacket,
23  PVOID Data,
25 /*
26  * FUNCTION: Adds an IPv4 and UDP header to an IP packet
27  * ARGUMENTS:
28  * SendRequest = Pointer to send request
29  * LocalAddress = Pointer to our local address
30  * LocalPort = The port we send this datagram from
31  * IPPacket = Pointer to IP packet
32  * RETURNS:
33  * Status of operation
34  */
35 {
36  PUDP_HEADER UDPHeader;
38 
39  TI_DbgPrint(MID_TRACE, ("Packet: %x NdisPacket %x\n",
40  IPPacket, IPPacket->NdisPacket));
41 
43  ( AddrFile, RemoteAddress, RemotePort,
44  LocalAddress, LocalPort,
45  IPPacket, DataLength, IPPROTO_UDP,
46  sizeof(UDP_HEADER), (PVOID *)&UDPHeader );
47 
48  if (!NT_SUCCESS(Status))
49  return Status;
50 
51  /* Port values are already big-endian values */
52  UDPHeader->SourcePort = LocalPort;
53  UDPHeader->DestPort = RemotePort;
54  UDPHeader->Checksum = 0;
55  /* Length of UDP header and data */
56  UDPHeader->Length = WH2N(DataLength + sizeof(UDP_HEADER));
57 
58  TI_DbgPrint(MID_TRACE, ("Copying data (hdr %x data %x (%d))\n",
59  IPPacket->Header, IPPacket->Data,
60  (PCHAR)IPPacket->Data - (PCHAR)IPPacket->Header));
61 
62  RtlCopyMemory(IPPacket->Data, Data, DataLength);
63 
64  UDPHeader->Checksum = UDPv4ChecksumCalculate((PIPv4_HEADER)IPPacket->Header,
65  (PUCHAR)UDPHeader,
66  DataLength + sizeof(UDP_HEADER));
67  UDPHeader->Checksum = WH2N(UDPHeader->Checksum);
68 
69  TI_DbgPrint(MID_TRACE, ("Packet: %d ip %d udp %d payload\n",
70  (PCHAR)UDPHeader - (PCHAR)IPPacket->Header,
71  (PCHAR)IPPacket->Data - (PCHAR)UDPHeader,
72  DataLength));
73 
74  return STATUS_SUCCESS;
75 }
76 
77 
79  PADDRESS_FILE AddrFile,
82  USHORT RemotePort,
84  USHORT LocalPort,
85  PCHAR DataBuffer,
86  UINT DataLen )
87 /*
88  * FUNCTION: Builds an UDP packet
89  * ARGUMENTS:
90  * Context = Pointer to context information (DATAGRAM_SEND_REQUEST)
91  * LocalAddress = Pointer to our local address
92  * LocalPort = The port we send this datagram from
93  * IPPacket = Address of pointer to IP packet
94  * RETURNS:
95  * Status of operation
96  */
97 {
99 
100  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
101 
102  /* FIXME: Assumes IPv4 */
104 
105  Packet->TotalSize = sizeof(IPv4_HEADER) + sizeof(UDP_HEADER) + DataLen;
106 
107  /* Prepare packet */
108  Status = AllocatePacketWithBuffer(&Packet->NdisPacket,
109  NULL,
110  Packet->TotalSize );
111 
112  if( !NT_SUCCESS(Status) )
113  {
114  Packet->Free(Packet);
115  return Status;
116  }
117 
118  TI_DbgPrint(MID_TRACE, ("Allocated packet: %x\n", Packet->NdisPacket));
119  TI_DbgPrint(MID_TRACE, ("Local Addr : %s\n", A2S(LocalAddress)));
120  TI_DbgPrint(MID_TRACE, ("Remote Addr: %s\n", A2S(RemoteAddress)));
121 
122  switch (RemoteAddress->Type) {
123  case IP_ADDRESS_V4:
124  Status = AddUDPHeaderIPv4(AddrFile, RemoteAddress, RemotePort,
125  LocalAddress, LocalPort, Packet, DataBuffer, DataLen);
126  break;
127  case IP_ADDRESS_V6:
128  /* FIXME: Support IPv6 */
129  TI_DbgPrint(MIN_TRACE, ("IPv6 UDP datagrams are not supported.\n"));
130  default:
132  break;
133  }
134  if (!NT_SUCCESS(Status)) {
135  TI_DbgPrint(MIN_TRACE, ("Cannot add UDP header. Status = (0x%X)\n",
136  Status));
137  Packet->Free(Packet);
138  return Status;
139  }
140 
141  TI_DbgPrint(MID_TRACE, ("Displaying packet\n"));
142 
144 
145  TI_DbgPrint(MID_TRACE, ("Leaving\n"));
146 
147  return STATUS_SUCCESS;
148 }
149 
151  PADDRESS_FILE AddrFile,
153  PCHAR BufferData,
154  ULONG DataSize,
155  PULONG DataUsed )
156 /*
157  * FUNCTION: Sends an UDP datagram to a remote address
158  * ARGUMENTS:
159  * Request = Pointer to TDI request
160  * ConnInfo = Pointer to connection information
161  * Buffer = Pointer to NDIS buffer with data
162  * DataSize = Size in bytes of data to be sent
163  * RETURNS:
164  * Status of operation
165  */
166 {
168  PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress;
171  USHORT RemotePort;
174  KIRQL OldIrql;
175 
176  LockObject(AddrFile, &OldIrql);
177 
178  TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
179  AddrFile, ConnInfo, BufferData, DataSize));
180  TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa));
181 
182  switch( RemoteAddressTa->Address[0].AddressType ) {
183  case TDI_ADDRESS_TYPE_IP:
185  RemoteAddress.Address.IPv4Address =
186  RemoteAddressTa->Address[0].Address[0].in_addr;
187  RemotePort = RemoteAddressTa->Address[0].Address[0].sin_port;
188  break;
189 
190  default:
191  UnlockObject(AddrFile, OldIrql);
192  return STATUS_UNSUCCESSFUL;
193  }
194 
195  LocalAddress = AddrFile->Address;
197  {
198  /* If the local address is unspecified (0),
199  * then use the unicast address of the
200  * interface we're sending over
201  */
202  if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
203  UnlockObject(AddrFile, OldIrql);
205  }
206 
207  LocalAddress = NCE->Interface->Unicast;
208  }
209  else
210  {
211  if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL ))) {
212  UnlockObject(AddrFile, OldIrql);
214  }
215  }
216 
217  Status = BuildUDPPacket( AddrFile,
218  &Packet,
219  &RemoteAddress,
220  RemotePort,
221  &LocalAddress,
222  AddrFile->Port,
223  BufferData,
224  DataSize );
225 
226  UnlockObject(AddrFile, OldIrql);
227 
228  if( !NT_SUCCESS(Status) )
229  return Status;
230 
231  Status = IPSendDatagram(&Packet, NCE);
232  if (!NT_SUCCESS(Status))
233  return Status;
234 
235  *DataUsed = DataSize;
236 
237  return STATUS_SUCCESS;
238 }
239 
240 
242 /*
243  * FUNCTION: Receives and queues a UDP datagram
244  * ARGUMENTS:
245  * NTE = Pointer to net table entry which the packet was received on
246 * IPPacket = Pointer to an IP packet that was received
247 * NOTES:
248 * This is the low level interface for receiving UDP datagrams. It strips
249 * the UDP header from a packet and delivers the data to anyone that wants it
250 */
251 {
252  AF_SEARCH SearchContext;
253  PIPv4_HEADER IPv4Header;
254  PADDRESS_FILE AddrFile;
255  PUDP_HEADER UDPHeader;
256  PIP_ADDRESS DstAddress, SrcAddress;
257  UINT DataSize, i;
258 
259  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
260 
261  switch (IPPacket->Type) {
262  /* IPv4 packet */
263  case IP_ADDRESS_V4:
264  IPv4Header = IPPacket->Header;
265  DstAddress = &IPPacket->DstAddr;
266  SrcAddress = &IPPacket->SrcAddr;
267  break;
268 
269  /* IPv6 packet */
270  case IP_ADDRESS_V6:
271  TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 UDP datagram (%i bytes).\n", IPPacket->TotalSize));
272 
273  /* FIXME: IPv6 is not supported */
274  return;
275 
276  default:
277  return;
278  }
279 
280  UDPHeader = (PUDP_HEADER)IPPacket->Data;
281 
282  /* Calculate and validate UDP checksum */
283  i = UDPv4ChecksumCalculate(IPv4Header,
284  (PUCHAR)UDPHeader,
285  WH2N(UDPHeader->Length));
286  if (i != DH2N(0x0000FFFF) && UDPHeader->Checksum != 0)
287  {
288  TI_DbgPrint(MIN_TRACE, ("Bad checksum on packet received.\n"));
289  return;
290  }
291 
292  /* Sanity checks */
293  i = WH2N(UDPHeader->Length);
294  if ((i < sizeof(UDP_HEADER)) || (i > IPPacket->TotalSize - IPPacket->Position)) {
295  /* Incorrect or damaged packet received, discard it */
296  TI_DbgPrint(MIN_TRACE, ("Incorrect or damaged UDP packet received.\n"));
297  return;
298  }
299 
300  DataSize = i - sizeof(UDP_HEADER);
301 
302  /* Go to UDP data area */
303  IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Data + sizeof(UDP_HEADER));
304 
305  /* Locate a receive request on destination address file object
306  and deliver the packet if one is found. If there is no receive
307  request on the address file object, call the associated receive
308  handler. If no receive handler is registered, drop the packet */
309 
310  AddrFile = AddrSearchFirst(DstAddress,
311  UDPHeader->DestPort,
312  IPPROTO_UDP,
313  &SearchContext);
314  if (AddrFile) {
315  do {
316  DGDeliverData(AddrFile,
317  SrcAddress,
318  DstAddress,
319  UDPHeader->SourcePort,
320  UDPHeader->DestPort,
321  IPPacket,
322  DataSize);
323  DereferenceObject(AddrFile);
324  } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL);
325  } else {
326  /* There are no open address files that will take this datagram */
327  /* FIXME: IPv4 only */
328  TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 UDP datagram to address (0x%X).\n",
329  DN2H(DstAddress->Address.IPv4Address)));
330 
331  /* FIXME: Send ICMP reply */
332  }
333  TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
334 }
335 
336 
338  VOID)
339 /*
340  * FUNCTION: Initializes the UDP subsystem
341  * RETURNS:
342  * Status of operation
343  */
344 {
346 
347 #ifdef __NTDRIVER__
349 #endif
350 
352 
353  if( !NT_SUCCESS(Status) ) return Status;
354 
355  /* Register this protocol with IP layer */
357 
359 
360  return STATUS_SUCCESS;
361 }
362 
363 
365  VOID)
366 /*
367  * FUNCTION: Shuts down the UDP subsystem
368  * RETURNS:
369  * Status of operation
370  */
371 {
372  if (!UDPInitialized)
373  return STATUS_SUCCESS;
374 
376 
377  /* Deregister this protocol with IP layer */
379 
381 
382  return STATUS_SUCCESS;
383 }
384 
385 UINT UDPAllocatePort( UINT HintPort ) {
386  if( HintPort ) {
387  if( AllocatePort( &UDPPorts, HintPort ) ) return HintPort;
388  else return (UINT)-1;
389  } else return AllocatePortFromRange
392 }
393 
396 }
397 
398 /* EOF */
BOOLEAN AddrIsUnspecified(PIP_ADDRESS Address)
Definition: address.c:113
signed char * PCHAR
Definition: retypes.h:7
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
CPPORT Port[4]
Definition: headless.c:34
IPv4_RAW_ADDRESS IPv4Address
Definition: ip.h:26
#define DISPLAY_IP_PACKET(x)
Definition: routines.h:69
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct UDP_HEADER UDP_HEADER
#define MID_TRACE
Definition: debug.h:15
NTSTATUS PortsStartup(PPORT_SET PortSet, UINT StartingPort, UINT PortsToManage)
Definition: ports.c:13
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1548
Definition: neighbor.h:28
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
USHORT DestPort
Definition: udp.h:17
unsigned char * PUCHAR
Definition: retypes.h:3
struct _TA_ADDRESS_IP * PTA_IP_ADDRESS
IP_ADDRESS SrcAddr
Definition: ip.h:89
LONG NTSTATUS
Definition: precomp.h:26
#define WH2N(w)
Definition: addrconv.c:40
PNEIGHBOR_CACHE_ENTRY RouteGetRouteToDestination(PIP_ADDRESS Destination)
Definition: router.c:300
PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor(PIP_ADDRESS Address, PIP_INTERFACE Interface)
Definition: neighbor.c:417
USHORT SourcePort
Definition: udp.h:16
VOID DGDeliverData(PADDRESS_FILE AddrFile, PIP_ADDRESS SrcAddress, PIP_ADDRESS DstAddress, USHORT SrcPort, USHORT DstPort, PIP_PACKET IPPacket, UINT DataSize)
Definition: datagram.c:52
VOID IPRegisterProtocol(UINT ProtocolNumber, IP_PROTOCOL_HANDLER Handler)
Definition: ip.c:390
VOID DeallocatePort(PPORT_SET PortSet, ULONG Port)
Definition: ports.c:35
ULONG UDPv4ChecksumCalculate(PIPv4_HEADER IPHeader, PUCHAR PacketBuffer, ULONG DataLength)
Definition: checksum.c:60
#define DereferenceObject(Object)
Definition: titypes.h:24
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define LockObject(Object, Irql)
Definition: titypes.h:34
PVOID Data
Definition: ip.h:85
Definition: ip.h:23
UCHAR KIRQL
Definition: env_spec_w32.h:591
PADDRESS_FILE AddrSearchFirst(PIP_ADDRESS Address, USHORT Port, USHORT Protocol, PAF_SEARCH SearchContext)
Definition: fileobjs.c:38
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
UINT UDPAllocatePort(UINT HintPort)
Definition: udp.c:385
#define IP_ADDRESS_V4
Definition: ip.h:32
NTSTATUS AddGenericHeaderIPv4(PADDRESS_FILE AddrFile, PIP_ADDRESS RemoteAddress, USHORT RemotePort, PIP_ADDRESS LocalAddress, USHORT LocalPort, PIP_PACKET IPPacket, UINT DataLength, UINT Protocol, UINT ExtraLength, PVOID *NextHeader)
Definition: rawip.c:13
PIP_PACKET IPInitializePacket(PIP_PACKET IPPacket, ULONG Type)
Definition: ip.c:92
#define UnlockObject(Object, OldIrql)
Definition: titypes.h:54
NTSTATUS IPSendDatagram(PIP_PACKET IPPacket, PNEIGHBOR_CACHE_ENTRY NCE)
Definition: transmit.c:223
#define AllocatePacketWithBuffer(x, y, z)
Definition: memtrack.h:7
PVOID Header
Definition: ip.h:83
unsigned char BOOLEAN
PORT_SET UDPPorts
Definition: udp.c:14
VOID UDPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
Definition: udp.c:241
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN AllocatePort(PPORT_SET PortSet, ULONG Port)
Definition: ports.c:47
#define UDP_DYNAMIC_PORTS
Definition: udp.h:11
struct _TA_ADDRESS_IP::_AddrIp Address[1]
void * PVOID
Definition: retypes.h:9
#define IP_ADDRESS_V6
Definition: ip.h:33
struct IPv4_HEADER IPv4_HEADER
USHORT Checksum
Definition: udp.h:19
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
Definition: udp.h:15
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
UINT Position
Definition: ip.h:87
#define UDP_STARTING_PORT
Definition: udp.h:10
UINT TotalSize
Definition: ip.h:86
UCHAR Type
Definition: ip.h:79
ULONG AllocatePortFromRange(PPORT_SET PortSet, ULONG Lowest, ULONG Highest)
Definition: ports.c:86
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
NTSTATUS UDPStartup(VOID)
Definition: udp.c:337
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
BOOLEAN UDPInitialized
Definition: udp.c:13
#define TDI_ADDRESS_TYPE_IP
Definition: tdi.h:345
UDP_STATISTICS UDPStats
Definition: main.c:26
NTSTATUS AddUDPHeaderIPv4(PADDRESS_FILE AddrFile, PIP_ADDRESS RemoteAddress, USHORT RemotePort, PIP_ADDRESS LocalAddress, USHORT LocalPort, PIP_PACKET IPPacket, PVOID Data, UINT DataLength)
Definition: udp.c:16
NTSTATUS UDPShutdown(VOID)
Definition: udp.c:364
Status
Definition: gdiplustypes.h:24
PADDRESS_FILE AddrSearchNext(PAF_SEARCH SearchContext)
Definition: fileobjs.c:231
USHORT Length
Definition: udp.h:18
NTSTATUS BuildUDPPacket(PADDRESS_FILE AddrFile, PIP_PACKET Packet, PIP_ADDRESS RemoteAddress, USHORT RemotePort, PIP_ADDRESS LocalAddress, USHORT LocalPort, PCHAR DataBuffer, UINT DataLen)
Definition: udp.c:78
#define MAX_TRACE
Definition: debug.h:16
unsigned short USHORT
Definition: pedump.c:61
IP_ADDRESS Address
Definition: titypes.h:136
struct UDP_HEADER * PUDP_HEADER
#define DN2H(dw)
Definition: addrconv.c:21
#define DH2N(dw)
Definition: addrconv.c:28
unsigned int * PULONG
Definition: retypes.h:1
unsigned int UINT
Definition: ndis.h:50
PNDIS_PACKET NdisPacket
Definition: ip.h:88
Definition: ip.h:37
VOID PortsShutdown(PPORT_SET PortSet)
Definition: ports.c:31
VOID UDPFreePort(UINT Port)
Definition: udp.c:394
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define MIN_TRACE
Definition: debug.h:14
IP_ADDRESS DstAddr
Definition: ip.h:90
Definition: ip.h:77
USHORT Port
Definition: titypes.h:139
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define STATUS_NETWORK_UNREACHABLE
Definition: ntstatus.h:690
NTSTATUS UDPSendDatagram(PADDRESS_FILE AddrFile, PTDI_CONNECTION_INFORMATION ConnInfo, PCHAR BufferData, ULONG DataSize, PULONG DataUsed)
Definition: udp.c:150
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
union IP_ADDRESS::@990 Address
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR RemoteAddress
Definition: wsk.h:170
PCHAR A2S(PIP_ADDRESS Address)
Definition: address.c:17
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR LocalAddress
Definition: wsk.h:170