Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenudp.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS TCP/IP protocol driver 00004 * FILE: transport/udp/udp.c 00005 * PURPOSE: User Datagram Protocol routines 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * REVISIONS: 00008 * CSH 01/08-2000 Created 00009 */ 00010 00011 #include "precomp.h" 00012 00013 BOOLEAN UDPInitialized = FALSE; 00014 PORT_SET UDPPorts; 00015 00016 NTSTATUS AddUDPHeaderIPv4( 00017 PADDRESS_FILE AddrFile, 00018 PIP_ADDRESS RemoteAddress, 00019 USHORT RemotePort, 00020 PIP_ADDRESS LocalAddress, 00021 USHORT LocalPort, 00022 PIP_PACKET IPPacket, 00023 PVOID Data, 00024 UINT DataLength) 00025 /* 00026 * FUNCTION: Adds an IPv4 and UDP header to an IP packet 00027 * ARGUMENTS: 00028 * SendRequest = Pointer to send request 00029 * LocalAddress = Pointer to our local address 00030 * LocalPort = The port we send this datagram from 00031 * IPPacket = Pointer to IP packet 00032 * RETURNS: 00033 * Status of operation 00034 */ 00035 { 00036 PUDP_HEADER UDPHeader; 00037 NTSTATUS Status; 00038 00039 TI_DbgPrint(MID_TRACE, ("Packet: %x NdisPacket %x\n", 00040 IPPacket, IPPacket->NdisPacket)); 00041 00042 Status = AddGenericHeaderIPv4 00043 ( AddrFile, RemoteAddress, RemotePort, 00044 LocalAddress, LocalPort, 00045 IPPacket, DataLength, IPPROTO_UDP, 00046 sizeof(UDP_HEADER), (PVOID *)&UDPHeader ); 00047 00048 if (!NT_SUCCESS(Status)) 00049 return Status; 00050 00051 /* Port values are already big-endian values */ 00052 UDPHeader->SourcePort = LocalPort; 00053 UDPHeader->DestPort = RemotePort; 00054 UDPHeader->Checksum = 0; 00055 /* Length of UDP header and data */ 00056 UDPHeader->Length = WH2N(DataLength + sizeof(UDP_HEADER)); 00057 00058 TI_DbgPrint(MID_TRACE, ("Copying data (hdr %x data %x (%d))\n", 00059 IPPacket->Header, IPPacket->Data, 00060 (PCHAR)IPPacket->Data - (PCHAR)IPPacket->Header)); 00061 00062 RtlCopyMemory(IPPacket->Data, Data, DataLength); 00063 00064 UDPHeader->Checksum = UDPv4ChecksumCalculate((PIPv4_HEADER)IPPacket->Header, 00065 (PUCHAR)UDPHeader, 00066 DataLength + sizeof(UDP_HEADER)); 00067 UDPHeader->Checksum = WH2N(UDPHeader->Checksum); 00068 00069 TI_DbgPrint(MID_TRACE, ("Packet: %d ip %d udp %d payload\n", 00070 (PCHAR)UDPHeader - (PCHAR)IPPacket->Header, 00071 (PCHAR)IPPacket->Data - (PCHAR)UDPHeader, 00072 DataLength)); 00073 00074 return STATUS_SUCCESS; 00075 } 00076 00077 00078 NTSTATUS BuildUDPPacket( 00079 PADDRESS_FILE AddrFile, 00080 PIP_PACKET Packet, 00081 PIP_ADDRESS RemoteAddress, 00082 USHORT RemotePort, 00083 PIP_ADDRESS LocalAddress, 00084 USHORT LocalPort, 00085 PCHAR DataBuffer, 00086 UINT DataLen ) 00087 /* 00088 * FUNCTION: Builds an UDP packet 00089 * ARGUMENTS: 00090 * Context = Pointer to context information (DATAGRAM_SEND_REQUEST) 00091 * LocalAddress = Pointer to our local address 00092 * LocalPort = The port we send this datagram from 00093 * IPPacket = Address of pointer to IP packet 00094 * RETURNS: 00095 * Status of operation 00096 */ 00097 { 00098 NTSTATUS Status; 00099 00100 TI_DbgPrint(MAX_TRACE, ("Called.\n")); 00101 00102 /* FIXME: Assumes IPv4 */ 00103 IPInitializePacket(Packet, IP_ADDRESS_V4); 00104 00105 Packet->TotalSize = sizeof(IPv4_HEADER) + sizeof(UDP_HEADER) + DataLen; 00106 00107 /* Prepare packet */ 00108 Status = AllocatePacketWithBuffer(&Packet->NdisPacket, 00109 NULL, 00110 Packet->TotalSize ); 00111 00112 if( !NT_SUCCESS(Status) ) 00113 { 00114 Packet->Free(Packet); 00115 return Status; 00116 } 00117 00118 TI_DbgPrint(MID_TRACE, ("Allocated packet: %x\n", Packet->NdisPacket)); 00119 TI_DbgPrint(MID_TRACE, ("Local Addr : %s\n", A2S(LocalAddress))); 00120 TI_DbgPrint(MID_TRACE, ("Remote Addr: %s\n", A2S(RemoteAddress))); 00121 00122 switch (RemoteAddress->Type) { 00123 case IP_ADDRESS_V4: 00124 Status = AddUDPHeaderIPv4(AddrFile, RemoteAddress, RemotePort, 00125 LocalAddress, LocalPort, Packet, DataBuffer, DataLen); 00126 break; 00127 case IP_ADDRESS_V6: 00128 /* FIXME: Support IPv6 */ 00129 TI_DbgPrint(MIN_TRACE, ("IPv6 UDP datagrams are not supported.\n")); 00130 default: 00131 Status = STATUS_UNSUCCESSFUL; 00132 break; 00133 } 00134 if (!NT_SUCCESS(Status)) { 00135 TI_DbgPrint(MIN_TRACE, ("Cannot add UDP header. Status = (0x%X)\n", 00136 Status)); 00137 Packet->Free(Packet); 00138 return Status; 00139 } 00140 00141 TI_DbgPrint(MID_TRACE, ("Displaying packet\n")); 00142 00143 DISPLAY_IP_PACKET(Packet); 00144 00145 TI_DbgPrint(MID_TRACE, ("Leaving\n")); 00146 00147 return STATUS_SUCCESS; 00148 } 00149 00150 NTSTATUS UDPSendDatagram( 00151 PADDRESS_FILE AddrFile, 00152 PTDI_CONNECTION_INFORMATION ConnInfo, 00153 PCHAR BufferData, 00154 ULONG DataSize, 00155 PULONG DataUsed ) 00156 /* 00157 * FUNCTION: Sends an UDP datagram to a remote address 00158 * ARGUMENTS: 00159 * Request = Pointer to TDI request 00160 * ConnInfo = Pointer to connection information 00161 * Buffer = Pointer to NDIS buffer with data 00162 * DataSize = Size in bytes of data to be sent 00163 * RETURNS: 00164 * Status of operation 00165 */ 00166 { 00167 IP_PACKET Packet; 00168 PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress; 00169 IP_ADDRESS RemoteAddress; 00170 IP_ADDRESS LocalAddress; 00171 USHORT RemotePort; 00172 NTSTATUS Status; 00173 PNEIGHBOR_CACHE_ENTRY NCE; 00174 KIRQL OldIrql; 00175 00176 LockObject(AddrFile, &OldIrql); 00177 00178 TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n", 00179 AddrFile, ConnInfo, BufferData, DataSize)); 00180 TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa)); 00181 00182 switch( RemoteAddressTa->Address[0].AddressType ) { 00183 case TDI_ADDRESS_TYPE_IP: 00184 RemoteAddress.Type = IP_ADDRESS_V4; 00185 RemoteAddress.Address.IPv4Address = 00186 RemoteAddressTa->Address[0].Address[0].in_addr; 00187 RemotePort = RemoteAddressTa->Address[0].Address[0].sin_port; 00188 break; 00189 00190 default: 00191 UnlockObject(AddrFile, OldIrql); 00192 return STATUS_UNSUCCESSFUL; 00193 } 00194 00195 LocalAddress = AddrFile->Address; 00196 if (AddrIsUnspecified(&LocalAddress)) 00197 { 00198 /* If the local address is unspecified (0), 00199 * then use the unicast address of the 00200 * interface we're sending over 00201 */ 00202 if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) { 00203 UnlockObject(AddrFile, OldIrql); 00204 return STATUS_NETWORK_UNREACHABLE; 00205 } 00206 00207 LocalAddress = NCE->Interface->Unicast; 00208 } 00209 else 00210 { 00211 if(!(NCE = NBLocateNeighbor( &LocalAddress ))) { 00212 UnlockObject(AddrFile, OldIrql); 00213 return STATUS_INVALID_PARAMETER; 00214 } 00215 } 00216 00217 Status = BuildUDPPacket( AddrFile, 00218 &Packet, 00219 &RemoteAddress, 00220 RemotePort, 00221 &LocalAddress, 00222 AddrFile->Port, 00223 BufferData, 00224 DataSize ); 00225 00226 UnlockObject(AddrFile, OldIrql); 00227 00228 if( !NT_SUCCESS(Status) ) 00229 return Status; 00230 00231 Status = IPSendDatagram(&Packet, NCE); 00232 if (!NT_SUCCESS(Status)) 00233 return Status; 00234 00235 *DataUsed = DataSize; 00236 00237 return STATUS_SUCCESS; 00238 } 00239 00240 00241 VOID UDPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket) 00242 /* 00243 * FUNCTION: Receives and queues a UDP datagram 00244 * ARGUMENTS: 00245 * NTE = Pointer to net table entry which the packet was received on 00246 * IPPacket = Pointer to an IP packet that was received 00247 * NOTES: 00248 * This is the low level interface for receiving UDP datagrams. It strips 00249 * the UDP header from a packet and delivers the data to anyone that wants it 00250 */ 00251 { 00252 AF_SEARCH SearchContext; 00253 PIPv4_HEADER IPv4Header; 00254 PADDRESS_FILE AddrFile; 00255 PUDP_HEADER UDPHeader; 00256 PIP_ADDRESS DstAddress, SrcAddress; 00257 UINT DataSize, i; 00258 00259 TI_DbgPrint(MAX_TRACE, ("Called.\n")); 00260 00261 switch (IPPacket->Type) { 00262 /* IPv4 packet */ 00263 case IP_ADDRESS_V4: 00264 IPv4Header = IPPacket->Header; 00265 DstAddress = &IPPacket->DstAddr; 00266 SrcAddress = &IPPacket->SrcAddr; 00267 break; 00268 00269 /* IPv6 packet */ 00270 case IP_ADDRESS_V6: 00271 TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 UDP datagram (%i bytes).\n", IPPacket->TotalSize)); 00272 00273 /* FIXME: IPv6 is not supported */ 00274 return; 00275 00276 default: 00277 return; 00278 } 00279 00280 UDPHeader = (PUDP_HEADER)IPPacket->Data; 00281 00282 /* Calculate and validate UDP checksum */ 00283 i = UDPv4ChecksumCalculate(IPv4Header, 00284 (PUCHAR)UDPHeader, 00285 WH2N(UDPHeader->Length)); 00286 if (i != DH2N(0x0000FFFF) && UDPHeader->Checksum != 0) 00287 { 00288 TI_DbgPrint(MIN_TRACE, ("Bad checksum on packet received.\n")); 00289 return; 00290 } 00291 00292 /* Sanity checks */ 00293 i = WH2N(UDPHeader->Length); 00294 if ((i < sizeof(UDP_HEADER)) || (i > IPPacket->TotalSize - IPPacket->Position)) { 00295 /* Incorrect or damaged packet received, discard it */ 00296 TI_DbgPrint(MIN_TRACE, ("Incorrect or damaged UDP packet received.\n")); 00297 return; 00298 } 00299 00300 DataSize = i - sizeof(UDP_HEADER); 00301 00302 /* Go to UDP data area */ 00303 IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Data + sizeof(UDP_HEADER)); 00304 00305 /* Locate a receive request on destination address file object 00306 and deliver the packet if one is found. If there is no receive 00307 request on the address file object, call the associated receive 00308 handler. If no receive handler is registered, drop the packet */ 00309 00310 AddrFile = AddrSearchFirst(DstAddress, 00311 UDPHeader->DestPort, 00312 IPPROTO_UDP, 00313 &SearchContext); 00314 if (AddrFile) { 00315 do { 00316 DGDeliverData(AddrFile, 00317 SrcAddress, 00318 DstAddress, 00319 UDPHeader->SourcePort, 00320 UDPHeader->DestPort, 00321 IPPacket, 00322 DataSize); 00323 } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); 00324 } else { 00325 /* There are no open address files that will take this datagram */ 00326 /* FIXME: IPv4 only */ 00327 TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 UDP datagram to address (0x%X).\n", 00328 DN2H(DstAddress->Address.IPv4Address))); 00329 00330 /* FIXME: Send ICMP reply */ 00331 } 00332 TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); 00333 } 00334 00335 00336 NTSTATUS UDPStartup( 00337 VOID) 00338 /* 00339 * FUNCTION: Initializes the UDP subsystem 00340 * RETURNS: 00341 * Status of operation 00342 */ 00343 { 00344 NTSTATUS Status; 00345 00346 #ifdef __NTDRIVER__ 00347 RtlZeroMemory(&UDPStats, sizeof(UDP_STATISTICS)); 00348 #endif 00349 00350 Status = PortsStartup( &UDPPorts, 1, UDP_STARTING_PORT + UDP_DYNAMIC_PORTS ); 00351 00352 if( !NT_SUCCESS(Status) ) return Status; 00353 00354 /* Register this protocol with IP layer */ 00355 IPRegisterProtocol(IPPROTO_UDP, UDPReceive); 00356 00357 UDPInitialized = TRUE; 00358 00359 return STATUS_SUCCESS; 00360 } 00361 00362 00363 NTSTATUS UDPShutdown( 00364 VOID) 00365 /* 00366 * FUNCTION: Shuts down the UDP subsystem 00367 * RETURNS: 00368 * Status of operation 00369 */ 00370 { 00371 if (!UDPInitialized) 00372 return STATUS_SUCCESS; 00373 00374 PortsShutdown( &UDPPorts ); 00375 00376 /* Deregister this protocol with IP layer */ 00377 IPRegisterProtocol(IPPROTO_UDP, NULL); 00378 00379 UDPInitialized = FALSE; 00380 00381 return STATUS_SUCCESS; 00382 } 00383 00384 UINT UDPAllocatePort( UINT HintPort ) { 00385 if( HintPort ) { 00386 if( AllocatePort( &UDPPorts, HintPort ) ) return HintPort; 00387 else return (UINT)-1; 00388 } else return AllocatePortFromRange 00389 ( &UDPPorts, UDP_STARTING_PORT, 00390 UDP_STARTING_PORT + UDP_DYNAMIC_PORTS ); 00391 } 00392 00393 VOID UDPFreePort( UINT Port ) { 00394 DeallocatePort( &UDPPorts, Port ); 00395 } 00396 00397 /* EOF */ Generated on Sat May 26 2012 04:34:54 for ReactOS by
1.7.6.1
|