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

icmp.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:        network/icmp.c
00005  * PURPOSE:     Internet Control Message 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 NTSTATUS ICMPStartup()
00014 {
00015     IPRegisterProtocol(IPPROTO_ICMP, ICMPReceive);
00016 
00017     return STATUS_SUCCESS;
00018 }
00019 
00020 NTSTATUS ICMPShutdown()
00021 {
00022     IPRegisterProtocol(IPPROTO_ICMP, NULL);
00023 
00024     return STATUS_SUCCESS;
00025 }
00026 
00027 BOOLEAN PrepareICMPPacket(
00028     PADDRESS_FILE AddrFile,
00029     PIP_INTERFACE Interface,
00030     PIP_PACKET IPPacket,
00031     PIP_ADDRESS Destination,
00032     PCHAR Data,
00033     UINT DataSize)
00034 /*
00035  * FUNCTION: Prepares an ICMP packet
00036  * ARGUMENTS:
00037  *     NTE         = Pointer to net table entry to use
00038  *     Destination = Pointer to destination address
00039  *     DataSize    = Size of dataarea
00040  * RETURNS:
00041  *     Pointer to IP packet, NULL if there is not enough free resources
00042  */
00043 {
00044     PNDIS_PACKET NdisPacket;
00045     NDIS_STATUS NdisStatus;
00046     PIPv4_HEADER IPHeader;
00047     ULONG Size;
00048 
00049     TI_DbgPrint(DEBUG_ICMP, ("Called. DataSize (%d).\n", DataSize));
00050 
00051     IPInitializePacket(IPPacket, IP_ADDRESS_V4);
00052 
00053     /* No special flags */
00054     IPPacket->Flags = 0;
00055 
00056     Size = sizeof(IPv4_HEADER) + DataSize;
00057 
00058     /* Allocate NDIS packet */
00059     NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Size );
00060 
00061     if( !NT_SUCCESS(NdisStatus) ) return FALSE;
00062 
00063     IPPacket->NdisPacket = NdisPacket;
00064     IPPacket->MappedHeader = TRUE;
00065 
00066     GetDataPtr( IPPacket->NdisPacket, 0,
00067         (PCHAR *)&IPPacket->Header, &IPPacket->TotalSize );
00068     ASSERT(IPPacket->TotalSize == Size);
00069 
00070     TI_DbgPrint(DEBUG_ICMP, ("Size (%d). Data at (0x%X).\n", Size, Data));
00071     TI_DbgPrint(DEBUG_ICMP, ("NdisPacket at (0x%X).\n", NdisPacket));
00072 
00073     IPPacket->HeaderSize = sizeof(IPv4_HEADER);
00074     IPPacket->Data = ((PCHAR)IPPacket->Header) + IPPacket->HeaderSize;
00075 
00076     TI_DbgPrint(DEBUG_ICMP, ("Copying Address: %x -> %x\n",
00077                  &IPPacket->DstAddr, Destination));
00078 
00079     RtlCopyMemory(&IPPacket->DstAddr, Destination, sizeof(IP_ADDRESS));
00080     RtlCopyMemory(IPPacket->Data, Data, DataSize);
00081 
00082     /* Build IPv4 header. FIXME: IPv4 only */
00083 
00084     IPHeader = (PIPv4_HEADER)IPPacket->Header;
00085 
00086     /* Version = 4, Length = 5 DWORDs */
00087     IPHeader->VerIHL = 0x45;
00088     /* Normal Type-of-Service */
00089     IPHeader->Tos = 0;
00090     /* Length of data and header */
00091     IPHeader->TotalLength = WH2N((USHORT)DataSize + sizeof(IPv4_HEADER));
00092     /* Identification */
00093     IPHeader->Id = (USHORT)Random();
00094     /* One fragment at offset 0 */
00095     IPHeader->FlagsFragOfs = 0;
00096     /* Set TTL */
00097     if (AddrFile)
00098         IPHeader->Ttl = AddrFile->TTL;
00099     else
00100         IPHeader->Ttl = 128;
00101     /* Internet Control Message Protocol */
00102     IPHeader->Protocol = IPPROTO_ICMP;
00103     /* Checksum is 0 (for later calculation of this) */
00104     IPHeader->Checksum = 0;
00105     /* Source address */
00106     IPHeader->SrcAddr = Interface->Unicast.Address.IPv4Address;
00107     /* Destination address */
00108     IPHeader->DstAddr = Destination->Address.IPv4Address;
00109 
00110 
00111     TI_DbgPrint(MID_TRACE,("Leaving\n"));
00112 
00113     return TRUE;
00114 }
00115 
00116 NTSTATUS ICMPSendDatagram(
00117     PADDRESS_FILE AddrFile,
00118     PTDI_CONNECTION_INFORMATION ConnInfo,
00119     PCHAR BufferData,
00120     ULONG DataSize,
00121     PULONG DataUsed )
00122 /*
00123  * FUNCTION: Sends an ICMP datagram to a remote address
00124  * ARGUMENTS:
00125  *     Request   = Pointer to TDI request
00126  *     ConnInfo  = Pointer to connection information
00127  *     Buffer    = Pointer to NDIS buffer with data
00128  *     DataSize  = Size in bytes of data to be sent
00129  * RETURNS:
00130  *     Status of operation
00131  */
00132 {
00133     IP_PACKET Packet;
00134     PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress;
00135     IP_ADDRESS RemoteAddress,  LocalAddress;
00136     NTSTATUS Status;
00137     PNEIGHBOR_CACHE_ENTRY NCE;
00138     KIRQL OldIrql;
00139 
00140     TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
00141                AddrFile, ConnInfo, BufferData, DataSize));
00142     TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa));
00143 
00144     switch( RemoteAddressTa->Address[0].AddressType ) {
00145         case TDI_ADDRESS_TYPE_IP:
00146             RemoteAddress.Type = IP_ADDRESS_V4;
00147             RemoteAddress.Address.IPv4Address =
00148                 RemoteAddressTa->Address[0].Address[0].in_addr;
00149             break;
00150 
00151         default:
00152             return STATUS_UNSUCCESSFUL;
00153     }
00154 
00155     TI_DbgPrint(MID_TRACE,("About to get route to destination\n"));
00156 
00157     LockObject(AddrFile, &OldIrql);
00158 
00159     LocalAddress = AddrFile->Address;
00160     if (AddrIsUnspecified(&LocalAddress))
00161     {
00162         /* If the local address is unspecified (0),
00163          * then use the unicast address of the
00164          * interface we're sending over
00165          */
00166         if(!(NCE = RouteGetRouteToDestination( &RemoteAddress )))
00167         {
00168             UnlockObject(AddrFile, OldIrql);
00169             return STATUS_NETWORK_UNREACHABLE;
00170         }
00171 
00172         LocalAddress = NCE->Interface->Unicast;
00173     }
00174     else
00175     {
00176         if(!(NCE = NBLocateNeighbor( &LocalAddress )))
00177         {
00178             UnlockObject(AddrFile, OldIrql);
00179             return STATUS_INVALID_PARAMETER;
00180         }
00181     }
00182 
00183     Status = PrepareICMPPacket( AddrFile,
00184                                 NCE->Interface,
00185                                 &Packet,
00186                                 &RemoteAddress,
00187                                 BufferData,
00188                                 DataSize );
00189 
00190     UnlockObject(AddrFile, OldIrql);
00191 
00192     if( !NT_SUCCESS(Status) )
00193         return Status;
00194 
00195     TI_DbgPrint(MID_TRACE,("About to send datagram\n"));
00196 
00197     Status = IPSendDatagram(&Packet, NCE);
00198     if (!NT_SUCCESS(Status))
00199         return Status;
00200     
00201     *DataUsed = DataSize;
00202 
00203     TI_DbgPrint(MID_TRACE,("Leaving\n"));
00204 
00205     return STATUS_SUCCESS;
00206 }
00207 
00208 
00209 VOID ICMPReceive(
00210     PIP_INTERFACE Interface,
00211     PIP_PACKET IPPacket)
00212 /*
00213  * FUNCTION: Receives an ICMP packet
00214  * ARGUMENTS:
00215  *     NTE      = Pointer to net table entry which the packet was received on
00216  *     IPPacket = Pointer to an IP packet that was received
00217  */
00218 {
00219     PICMP_HEADER ICMPHeader;
00220 
00221     TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
00222 
00223     ICMPHeader = (PICMP_HEADER)IPPacket->Data;
00224 
00225     TI_DbgPrint(DEBUG_ICMP, ("Size (%d).\n", IPPacket->TotalSize));
00226 
00227     TI_DbgPrint(DEBUG_ICMP, ("HeaderSize (%d).\n", IPPacket->HeaderSize));
00228 
00229     TI_DbgPrint(DEBUG_ICMP, ("Type (%d).\n", ICMPHeader->Type));
00230 
00231     TI_DbgPrint(DEBUG_ICMP, ("Code (%d).\n", ICMPHeader->Code));
00232 
00233     TI_DbgPrint(DEBUG_ICMP, ("Checksum (0x%X).\n", ICMPHeader->Checksum));
00234 
00235     /* Checksum ICMP header and data */
00236     if (!IPv4CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
00237         TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n"));
00238         /* Discard packet */
00239         return;
00240     }
00241 
00242     RawIpReceive(Interface, IPPacket);
00243 
00244     switch (ICMPHeader->Type) {
00245         case ICMP_TYPE_ECHO_REQUEST:
00246             ICMPReply( Interface, IPPacket, ICMP_TYPE_ECHO_REPLY, 0 );
00247             break;
00248 
00249         case ICMP_TYPE_ECHO_REPLY:
00250             break;
00251 
00252         default:
00253             TI_DbgPrint(DEBUG_ICMP,
00254                         ("Discarded ICMP datagram of unknown type %d.\n",
00255                          ICMPHeader->Type));
00256             /* Discard packet */
00257             break;
00258     }
00259 }
00260 
00261 
00262 VOID ICMPTransmit(
00263     PIP_PACKET IPPacket,
00264     PIP_TRANSMIT_COMPLETE Complete,
00265     PVOID Context)
00266 /*
00267  * FUNCTION: Transmits an ICMP packet
00268  * ARGUMENTS:
00269  *     NTE      = Pointer to net table entry to use (NULL if don't care)
00270  *     IPPacket = Pointer to IP packet to transmit
00271  */
00272 {
00273     PNEIGHBOR_CACHE_ENTRY NCE;
00274 
00275     TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
00276 
00277     /* Calculate checksum of ICMP header and data */
00278     ((PICMP_HEADER)IPPacket->Data)->Checksum = (USHORT)
00279         IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0);
00280 
00281     /* Get a route to the destination address */
00282     if ((NCE = RouteGetRouteToDestination(&IPPacket->DstAddr))) {
00283         /* Send the packet */
00284         IPSendDatagram(IPPacket, NCE);
00285     } else {
00286         /* No route to destination (or no free resources) */
00287         TI_DbgPrint(DEBUG_ICMP, ("No route to destination address 0x%X.\n",
00288                                  IPPacket->DstAddr.Address.IPv4Address));
00289         IPPacket->Free(IPPacket);
00290     }
00291 }
00292 
00293 
00294 VOID ICMPReply(
00295     PIP_INTERFACE Interface,
00296     PIP_PACKET IPPacket,
00297     UCHAR Type,
00298     UCHAR Code)
00299 /*
00300  * FUNCTION: Transmits an ICMP packet in response to an incoming packet
00301  * ARGUMENTS:
00302  *     NTE      = Pointer to net table entry to use
00303  *     IPPacket = Pointer to IP packet that was received
00304  *     Type     = ICMP message type
00305  *     Code     = ICMP message code
00306  * NOTES:
00307  *     We have received a packet from someone and is unable to
00308  *     process it due to error(s) in the packet or we have run out
00309  *     of resources. We transmit an ICMP message to the host to
00310  *     notify him of the problem
00311  */
00312 {
00313     UINT DataSize;
00314     IP_PACKET NewPacket;
00315 
00316     TI_DbgPrint(DEBUG_ICMP, ("Called. Type (%d)  Code (%d).\n", Type, Code));
00317 
00318     DataSize = IPPacket->TotalSize - IPPacket->HeaderSize;
00319 
00320     if( !PrepareICMPPacket(NULL, Interface, &NewPacket, &IPPacket->SrcAddr,
00321                IPPacket->Data, DataSize) ) return;
00322 
00323     ((PICMP_HEADER)NewPacket.Data)->Type     = Type;
00324     ((PICMP_HEADER)NewPacket.Data)->Code     = Code;
00325     ((PICMP_HEADER)NewPacket.Data)->Checksum = 0;
00326 
00327     ICMPTransmit(&NewPacket, NULL, NULL);
00328 }
00329 
00330 /* EOF */

Generated on Sat May 26 2012 04:34:53 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.