ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

udp.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.