Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenicmp.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
1.7.6.1
|