-/*\r
- * COPYRIGHT: See COPYING in the top level directory\r
- * PROJECT: ReactOS TCP/IP protocol driver\r
- * FILE: network/icmp.c\r
- * PURPOSE: Internet Control Message Protocol routines\r
- * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)\r
- * REVISIONS:\r
- * CSH 01/08-2000 Created\r
- */\r
-#include <tcpip.h>\r
-#include <icmp.h>\r
-#include <checksum.h>\r
-#include <routines.h>\r
-#include <transmit.h>\r
-#include <pool.h>\r
-\r
-\r
-VOID SendICMPComplete(\r
- PVOID Context,\r
- PNDIS_PACKET Packet,\r
- NDIS_STATUS NdisStatus)\r
-/*\r
- * FUNCTION: ICMP datagram transmit completion handler\r
- * ARGUMENTS:\r
- * Context = Pointer to context infomation (IP_PACKET)\r
- * Packet = Pointer to NDIS packet\r
- * NdisStatus = Status of transmit operation\r
- * NOTES:\r
- * This routine is called by IP when a ICMP send completes\r
- */\r
-{\r
- PIP_PACKET IPPacket = (PIP_PACKET)Context;\r
-\r
- TI_DbgPrint(MAX_TRACE, ("Called.\n"));\r
-\r
- TI_DbgPrint(MAX_TRACE, ("Freeing NDIS packet (%X).\n", Packet));\r
-\r
- /* Free packet */\r
- FreeNdisPacket(Packet);\r
-\r
- TI_DbgPrint(MAX_TRACE, ("Freeing IP packet at %X.\n", IPPacket));\r
-\r
- PoolFreeBuffer(IPPacket);\r
-}\r
-\r
-\r
-PIP_PACKET PrepareICMPPacket(\r
- PNET_TABLE_ENTRY NTE,\r
- PIP_ADDRESS Destination,\r
- UINT DataSize)\r
-/*\r
- * FUNCTION: Prepares an ICMP packet\r
- * ARGUMENTS:\r
- * NTE = Pointer to net table entry to use\r
- * Destination = Pointer to destination address\r
- * DataSize = Size of dataarea\r
- * RETURNS:\r
- * Pointer to IP packet, NULL if there is not enough free resources\r
- */\r
-{\r
- PIP_PACKET IPPacket;\r
- PNDIS_PACKET NdisPacket;\r
- PNDIS_BUFFER NdisBuffer;\r
- NDIS_STATUS NdisStatus;\r
- PIPv4_HEADER IPHeader;\r
- PVOID DataBuffer;\r
- ULONG Size;\r
-\r
- TI_DbgPrint(MAX_TRACE, ("Called. DataSize = %d.\n", DataSize));\r
-\r
- /* Prepare ICMP packet */\r
- IPPacket = PoolAllocateBuffer(sizeof(IP_PACKET));\r
- if (!IPPacket)\r
- return NULL;\r
-\r
- TI_DbgPrint(MAX_TRACE, ("IPPacket at %X.\n", IPPacket));\r
-\r
- Size = MaxLLHeaderSize + sizeof(IPv4_HEADER) +\r
- sizeof(ICMP_HEADER) + DataSize;\r
- DataBuffer = ExAllocatePool(NonPagedPool, Size);\r
- if (!DataBuffer) {\r
- PoolFreeBuffer(IPPacket);\r
- return NULL;\r
- }\r
-\r
- TI_DbgPrint(MAX_TRACE, ("Size = %d, Data at %X.\n", Size, DataBuffer));\r
-\r
- /* Allocate NDIS packet */\r
- NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool);\r
- if (NdisStatus != NDIS_STATUS_SUCCESS) {\r
- PoolFreeBuffer(IPPacket);\r
- ExFreePool(DataBuffer);\r
- return NULL;\r
- }\r
-\r
- TI_DbgPrint(MAX_TRACE, ("NdisPacket at %X.\n", NdisPacket));\r
-\r
- /* Allocate NDIS buffer for maximum link level header and ICMP packet */\r
- NdisAllocateBuffer(&NdisStatus, &NdisBuffer, GlobalBufferPool,\r
- DataBuffer, Size);\r
- if (NdisStatus != NDIS_STATUS_SUCCESS) {\r
- PoolFreeBuffer(IPPacket);\r
- NdisFreePacket(NdisPacket);\r
- ExFreePool(DataBuffer);\r
- return NULL;\r
- }\r
-\r
- TI_DbgPrint(MAX_TRACE, ("NdisBuffer at %X.\n", NdisBuffer));\r
-\r
- /* Link NDIS buffer into packet */\r
- NdisChainBufferAtFront(NdisPacket, NdisBuffer);\r
- IPPacket->NdisPacket = NdisPacket;\r
- IPPacket->Header = (PVOID)((ULONG_PTR)DataBuffer + MaxLLHeaderSize);\r
- IPPacket->Data = (PVOID)((ULONG_PTR)DataBuffer + MaxLLHeaderSize + sizeof(IPv4_HEADER));\r
-\r
- IPPacket->HeaderSize = sizeof(IPv4_HEADER);\r
- IPPacket->TotalSize = Size - MaxLLHeaderSize;\r
- RtlCopyMemory(&IPPacket->DstAddr, Destination, sizeof(IP_ADDRESS));\r
-\r
- /* Build IPv4 header. FIXME: IPv4 only */\r
-\r
- IPHeader = (PIPv4_HEADER)IPPacket->Header;\r
-\r
- /* Version = 4, Length = 5 DWORDs */\r
- IPHeader->VerIHL = 0x45;\r
- /* Normal Type-of-Service */\r
- IPHeader->Tos = 0;\r
- /* Length of data and header */\r
- IPHeader->TotalLength = WH2N((USHORT)DataSize +\r
- sizeof(IPv4_HEADER) + sizeof(ICMP_HEADER));\r
- /* Identification */\r
- IPHeader->Id = (USHORT)Random();\r
- /* One fragment at offset 0 */\r
- IPHeader->FlagsFragOfs = 0;\r
- /* Time-to-Live is 128 */\r
- IPHeader->Ttl = 128;\r
- /* Internet Control Message Protocol */\r
- IPHeader->Protocol = IPPROTO_ICMP;\r
- /* Checksum is 0 (for later calculation of this) */\r
- IPHeader->Checksum = 0;\r
- /* Source address */\r
- IPHeader->SrcAddr = NTE->Address->Address.IPv4Address;\r
- /* Destination address */\r
- IPHeader->DstAddr = Destination->Address.IPv4Address;\r
-\r
- /* Completion handler */\r
- PC(NdisPacket)->Complete = SendICMPComplete;\r
- PC(NdisPacket)->Context = IPPacket;\r
-\r
- return IPPacket;\r
-}\r
-\r
-\r
-VOID ICMPReceive(\r
- PNET_TABLE_ENTRY NTE,\r
- PIP_PACKET IPPacket)\r
-/*\r
- * FUNCTION: Receives an ICMP packet\r
- * ARGUMENTS:\r
- * NTE = Pointer to net table entry which the packet was received on\r
- * IPPacket = Pointer to an IP packet that was received\r
- */\r
-{\r
- PICMP_HEADER ICMPHeader;\r
- PIP_PACKET NewPacket;\r
- UINT DataSize;\r
- ULONG Checksum;\r
-\r
- TI_DbgPrint(MID_TRACE, ("Called.\n"));\r
-\r
- ICMPHeader = (PICMP_HEADER)IPPacket->Data;\r
-\r
- TI_DbgPrint(MID_TRACE, ("Size = %d.\n", IPPacket->TotalSize));\r
-\r
- TI_DbgPrint(MID_TRACE, ("HeaderSize = %d.\n", IPPacket->HeaderSize));\r
-\r
- TI_DbgPrint(MID_TRACE, ("Type = %d.\n", ICMPHeader->Type));\r
-\r
- TI_DbgPrint(MID_TRACE, ("Code = %d.\n", ICMPHeader->Code));\r
-\r
- TI_DbgPrint(MID_TRACE, ("Checksum = %X.\n", ICMPHeader->Checksum));\r
-\r
- /* Checksum ICMP header and data and compare */\r
- Checksum = DN2H(IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0));\r
- if (Checksum != 0xFFFF) {\r
- TI_DbgPrint(MIN_TRACE, ("Bad ICMP checksum (0x%X).\n", Checksum));\r
- /* Discard packet */\r
- return;\r
- }\r
-\r
- switch (ICMPHeader->Type) {\r
- case ICMP_TYPE_ECHO_REQUEST:\r
- /* Reply with an ICMP echo reply message */\r
- DataSize = IPPacket->TotalSize - IPPacket->HeaderSize - sizeof(ICMP_HEADER);\r
- NewPacket = PrepareICMPPacket(NTE, &IPPacket->SrcAddr, DataSize);\r
- if (!NewPacket)\r
- return;\r
-\r
- /* Copy ICMP header and data into new packet */\r
- RtlCopyMemory(NewPacket->Data, IPPacket->Data, DataSize + sizeof(ICMP_HEADER));\r
- ((PICMP_HEADER)NewPacket->Data)->Type = ICMP_TYPE_ECHO_REPLY;\r
- ((PICMP_HEADER)NewPacket->Data)->Code = 0;\r
- ((PICMP_HEADER)NewPacket->Data)->Checksum = 0;\r
-\r
- ICMPTransmit(NTE, NewPacket);\r
-\r
- TI_DbgPrint(MID_TRACE, ("Echo reply sent.\n"));\r
-\r
- return;\r
- default:\r
- TI_DbgPrint(MID_TRACE, ("Discarded ICMP datagram of unknown type.\n"));\r
- /* Discard packet */\r
- break;\r
- }\r
-}\r
-\r
-\r
-VOID ICMPTransmit(\r
- PNET_TABLE_ENTRY NTE,\r
- PIP_PACKET IPPacket)\r
-/*\r
- * FUNCTION: Transmits an ICMP packet\r
- * ARGUMENTS:\r
- * NTE = Pointer to net table entry to use (NULL if don't care)\r
- * IPPacket = Pointer to IP packet to transmit\r
- */\r
-{\r
- PROUTE_CACHE_NODE RCN;\r
-\r
- TI_DbgPrint(MID_TRACE, ("Called.\n"));\r
-\r
- /* Calculate checksum of ICMP header and data */\r
- ((PICMP_HEADER)IPPacket->Data)->Checksum = (USHORT)\r
- IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0);\r
-\r
- /* Get a route to the destination address */\r
- if (RouteGetRouteToDestination(&IPPacket->DstAddr, NTE, &RCN) == IP_SUCCESS) {\r
- /* Send the packet */\r
- if (IPSendDatagram(IPPacket, RCN) != STATUS_SUCCESS) {\r
- FreeNdisPacket(IPPacket->NdisPacket);\r
- PoolFreeBuffer(IPPacket);\r
- }\r
- /* We're done with the RCN */\r
- DereferenceObject(RCN);\r
- } else {\r
- TI_DbgPrint(MIN_TRACE, ("RCN at 0x%X.\n", RCN));\r
-\r
- /* No route to destination (or no free resources) */\r
- TI_DbgPrint(MIN_TRACE, ("No route to destination address 0x%X.\n",\r
- IPPacket->DstAddr.Address.IPv4Address));\r
- /* Discard packet */\r
- FreeNdisPacket(IPPacket->NdisPacket);\r
- PoolFreeBuffer(IPPacket);\r
- }\r
-}\r
-\r
-\r
-VOID ICMPReply(\r
- PNET_TABLE_ENTRY NTE,\r
- PIP_PACKET IPPacket,\r
- UCHAR Type,\r
- UCHAR Code)\r
-/*\r
- * FUNCTION: Transmits an ICMP packet in response to an incoming packet\r
- * ARGUMENTS:\r
- * NTE = Pointer to net table entry to use\r
- * IPPacket = Pointer to IP packet that was received\r
- * Type = ICMP message type\r
- * Code = ICMP message code\r
- * NOTES:\r
- * We have received a packet from someone and is unable to\r
- * process it due to error(s) in the packet or we have run out\r
- * of resources. We transmit an ICMP message to the host to\r
- * notify him of the problem\r
- */\r
-{\r
- UINT DataSize;\r
- PIP_PACKET NewPacket;\r
-\r
- TI_DbgPrint(MID_TRACE, ("Called (Type=%d, Code=%d).\n", Type, Code));\r
-\r
- DataSize = IPPacket->TotalSize;\r
- if ((DataSize) > (576 - sizeof(IPv4_HEADER) - sizeof(ICMP_HEADER)))\r
- DataSize = 576;\r
-\r
- NewPacket = PrepareICMPPacket(NTE, &IPPacket->SrcAddr, DataSize);\r
- if (!NewPacket)\r
- return;\r
-\r
- RtlCopyMemory((PVOID)((ULONG_PTR)NewPacket->Data + sizeof(ICMP_HEADER)),\r
- IPPacket->Header, DataSize);\r
- ((PICMP_HEADER)NewPacket->Data)->Type = Type;\r
- ((PICMP_HEADER)NewPacket->Data)->Code = Code;\r
- ((PICMP_HEADER)NewPacket->Data)->Checksum = 0;\r
-\r
- ICMPTransmit(NTE, NewPacket);\r
-}\r
-\r
-/* EOF */\r
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: network/icmp.c
+ * PURPOSE: Internet Control Message Protocol routines
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 01/08-2000 Created
+ */
+#include <tcpip.h>
+#include <icmp.h>
+#include <rawip.h>
+#include <checksum.h>
+#include <routines.h>
+#include <transmit.h>
+#include <pool.h>
+
+
+VOID SendICMPComplete(
+ PVOID Context,
+ PNDIS_PACKET Packet,
+ NDIS_STATUS NdisStatus)
+/*
+ * FUNCTION: ICMP datagram transmit completion handler
+ * ARGUMENTS:
+ * Context = Pointer to context infomation (IP_PACKET)
+ * Packet = Pointer to NDIS packet
+ * NdisStatus = Status of transmit operation
+ * NOTES:
+ * This routine is called by IP when a ICMP send completes
+ */
+{
+ PIP_PACKET IPPacket = (PIP_PACKET)Context;
+
+ TI_DbgPrint(DEBUG_ICMP, ("Freeing NDIS packet (%X).\n", Packet));
+
+ /* Free packet */
+ FreeNdisPacket(Packet);
+
+ TI_DbgPrint(DEBUG_ICMP, ("Freeing IP packet at %X.\n", IPPacket));
+
+ PoolFreeBuffer(IPPacket);
+}
+
+
+PIP_PACKET PrepareICMPPacket(
+ PNET_TABLE_ENTRY NTE,
+ PIP_ADDRESS Destination,
+ UINT DataSize)
+/*
+ * FUNCTION: Prepares an ICMP packet
+ * ARGUMENTS:
+ * NTE = Pointer to net table entry to use
+ * Destination = Pointer to destination address
+ * DataSize = Size of dataarea
+ * RETURNS:
+ * Pointer to IP packet, NULL if there is not enough free resources
+ */
+{
+ PIP_PACKET IPPacket;
+ PNDIS_PACKET NdisPacket;
+ PNDIS_BUFFER NdisBuffer;
+ NDIS_STATUS NdisStatus;
+ PIPv4_HEADER IPHeader;
+ PVOID DataBuffer;
+ ULONG Size;
+
+ TI_DbgPrint(DEBUG_ICMP, ("Called. DataSize (%d).\n", DataSize));
+
+ /* Prepare ICMP packet */
+ IPPacket = PoolAllocateBuffer(sizeof(IP_PACKET));
+ if (!IPPacket)
+ return NULL;
+
+ TI_DbgPrint(DEBUG_ICMP, ("IPPacket at (0x%X).\n", IPPacket));
+
+ /* No special flags */
+ IPPacket->Flags = 0;
+
+ Size = MaxLLHeaderSize + sizeof(IPv4_HEADER) +
+ sizeof(ICMP_HEADER) + DataSize;
+ DataBuffer = ExAllocatePool(NonPagedPool, Size);
+ if (!DataBuffer) {
+ PoolFreeBuffer(IPPacket);
+ return NULL;
+ }
+
+ TI_DbgPrint(DEBUG_ICMP, ("Size (%d). Data at (0x%X).\n", Size, DataBuffer));
+
+ /* Allocate NDIS packet */
+ NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool);
+ if (NdisStatus != NDIS_STATUS_SUCCESS) {
+ PoolFreeBuffer(IPPacket);
+ ExFreePool(DataBuffer);
+ return NULL;
+ }
+
+ TI_DbgPrint(MAX_TRACE, ("NdisPacket at (0x%X).\n", NdisPacket));
+
+ /* Allocate NDIS buffer for maximum link level header and ICMP packet */
+ NdisAllocateBuffer(&NdisStatus, &NdisBuffer, GlobalBufferPool,
+ DataBuffer, Size);
+ if (NdisStatus != NDIS_STATUS_SUCCESS) {
+ PoolFreeBuffer(IPPacket);
+ NdisFreePacket(NdisPacket);
+ ExFreePool(DataBuffer);
+ return NULL;
+ }
+
+ TI_DbgPrint(MAX_TRACE, ("NdisBuffer at (0x%X).\n", NdisBuffer));
+
+ /* Link NDIS buffer into packet */
+ NdisChainBufferAtFront(NdisPacket, NdisBuffer);
+ IPPacket->NdisPacket = NdisPacket;
+ IPPacket->Header = (PVOID)((ULONG_PTR)DataBuffer + MaxLLHeaderSize);
+ IPPacket->Data = (PVOID)((ULONG_PTR)DataBuffer + MaxLLHeaderSize + sizeof(IPv4_HEADER));
+
+ IPPacket->HeaderSize = sizeof(IPv4_HEADER);
+ IPPacket->TotalSize = Size - MaxLLHeaderSize;
+ RtlCopyMemory(&IPPacket->DstAddr, Destination, sizeof(IP_ADDRESS));
+
+ /* Build IPv4 header. FIXME: IPv4 only */
+
+ IPHeader = (PIPv4_HEADER)IPPacket->Header;
+
+ /* Version = 4, Length = 5 DWORDs */
+ IPHeader->VerIHL = 0x45;
+ /* Normal Type-of-Service */
+ IPHeader->Tos = 0;
+ /* Length of data and header */
+ IPHeader->TotalLength = WH2N((USHORT)DataSize +
+ sizeof(IPv4_HEADER) + sizeof(ICMP_HEADER));
+ /* Identification */
+ IPHeader->Id = (USHORT)Random();
+ /* One fragment at offset 0 */
+ IPHeader->FlagsFragOfs = 0;
+ /* Time-to-Live is 128 */
+ IPHeader->Ttl = 128;
+ /* Internet Control Message Protocol */
+ IPHeader->Protocol = IPPROTO_ICMP;
+ /* Checksum is 0 (for later calculation of this) */
+ IPHeader->Checksum = 0;
+ /* Source address */
+ IPHeader->SrcAddr = NTE->Address->Address.IPv4Address;
+ /* Destination address */
+ IPHeader->DstAddr = Destination->Address.IPv4Address;
+
+ /* Completion handler */
+ PC(NdisPacket)->Complete = SendICMPComplete;
+ PC(NdisPacket)->Context = IPPacket;
+
+ return IPPacket;
+}
+
+
+VOID ICMPReceive(
+ PNET_TABLE_ENTRY NTE,
+ PIP_PACKET IPPacket)
+/*
+ * FUNCTION: Receives an ICMP packet
+ * ARGUMENTS:
+ * NTE = Pointer to net table entry which the packet was received on
+ * IPPacket = Pointer to an IP packet that was received
+ */
+{
+ PICMP_HEADER ICMPHeader;
+ PIP_PACKET NewPacket;
+ UINT DataSize;
+
+ TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
+
+ ICMPHeader = (PICMP_HEADER)IPPacket->Data;
+
+ TI_DbgPrint(DEBUG_ICMP, ("Size (%d).\n", IPPacket->TotalSize));
+
+ TI_DbgPrint(DEBUG_ICMP, ("HeaderSize (%d).\n", IPPacket->HeaderSize));
+
+ TI_DbgPrint(DEBUG_ICMP, ("Type (%d).\n", ICMPHeader->Type));
+
+ TI_DbgPrint(DEBUG_ICMP, ("Code (%d).\n", ICMPHeader->Code));
+
+ TI_DbgPrint(DEBUG_ICMP, ("Checksum (0x%X).\n", ICMPHeader->Checksum));
+
+ /* Checksum ICMP header and data */
+ if (!CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
+ TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n"));
+ /* Discard packet */
+ return;
+ }
+
+ switch (ICMPHeader->Type) {
+ case ICMP_TYPE_ECHO_REQUEST:
+ /* Reply with an ICMP echo reply message */
+ DataSize = IPPacket->TotalSize - IPPacket->HeaderSize - sizeof(ICMP_HEADER);
+ NewPacket = PrepareICMPPacket(NTE, &IPPacket->SrcAddr, DataSize);
+ if (!NewPacket)
+ return;
+
+ /* Copy ICMP header and data into new packet */
+ RtlCopyMemory(NewPacket->Data, IPPacket->Data, DataSize + sizeof(ICMP_HEADER));
+ ((PICMP_HEADER)NewPacket->Data)->Type = ICMP_TYPE_ECHO_REPLY;
+ ((PICMP_HEADER)NewPacket->Data)->Code = 0;
+ ((PICMP_HEADER)NewPacket->Data)->Checksum = 0;
+
+ DisplayIPPacket(IPPacket);
+
+ DisplayIPPacket(NewPacket);
+
+ ICMPTransmit(NTE, NewPacket);
+
+ TI_DbgPrint(DEBUG_ICMP, ("Echo reply sent.\n"));
+ return;
+
+ case ICMP_TYPE_ECHO_REPLY:
+ break;
+
+ default:
+ TI_DbgPrint(DEBUG_ICMP, ("Discarded ICMP datagram of unknown type %d.\n",
+ ICMPHeader->Type));
+ /* Discard packet */
+ break;
+ }
+
+ /* Send datagram up the protocol stack */
+ RawIPReceive(NTE, IPPacket);
+}
+
+
+VOID ICMPTransmit(
+ PNET_TABLE_ENTRY NTE,
+ PIP_PACKET IPPacket)
+/*
+ * FUNCTION: Transmits an ICMP packet
+ * ARGUMENTS:
+ * NTE = Pointer to net table entry to use (NULL if don't care)
+ * IPPacket = Pointer to IP packet to transmit
+ */
+{
+ PROUTE_CACHE_NODE RCN;
+
+ TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
+
+ /* Calculate checksum of ICMP header and data */
+ ((PICMP_HEADER)IPPacket->Data)->Checksum = (USHORT)
+ IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0);
+
+ /* Get a route to the destination address */
+ if (RouteGetRouteToDestination(&IPPacket->DstAddr, NTE, &RCN) == IP_SUCCESS) {
+ /* Send the packet */
+ if (IPSendDatagram(IPPacket, RCN) != STATUS_SUCCESS) {
+ FreeNdisPacket(IPPacket->NdisPacket);
+ PoolFreeBuffer(IPPacket);
+ }
+ /* We're done with the RCN */
+ DereferenceObject(RCN);
+ } else {
+ TI_DbgPrint(MIN_TRACE, ("RCN at (0x%X).\n", RCN));
+
+ /* No route to destination (or no free resources) */
+ TI_DbgPrint(DEBUG_ICMP, ("No route to destination address 0x%X.\n",
+ IPPacket->DstAddr.Address.IPv4Address));
+ /* Discard packet */
+ FreeNdisPacket(IPPacket->NdisPacket);
+ PoolFreeBuffer(IPPacket);
+ }
+}
+
+
+VOID ICMPReply(
+ PNET_TABLE_ENTRY NTE,
+ PIP_PACKET IPPacket,
+ UCHAR Type,
+ UCHAR Code)
+/*
+ * FUNCTION: Transmits an ICMP packet in response to an incoming packet
+ * ARGUMENTS:
+ * NTE = Pointer to net table entry to use
+ * IPPacket = Pointer to IP packet that was received
+ * Type = ICMP message type
+ * Code = ICMP message code
+ * NOTES:
+ * We have received a packet from someone and is unable to
+ * process it due to error(s) in the packet or we have run out
+ * of resources. We transmit an ICMP message to the host to
+ * notify him of the problem
+ */
+{
+ UINT DataSize;
+ PIP_PACKET NewPacket;
+
+ TI_DbgPrint(DEBUG_ICMP, ("Called. Type (%d) Code (%d).\n", Type, Code));
+
+ DataSize = IPPacket->TotalSize;
+ if ((DataSize) > (576 - sizeof(IPv4_HEADER) - sizeof(ICMP_HEADER)))
+ DataSize = 576;
+
+ NewPacket = PrepareICMPPacket(NTE, &IPPacket->SrcAddr, DataSize);
+ if (!NewPacket) {
+ TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+ return;
+ }
+
+ RtlCopyMemory((PVOID)((ULONG_PTR)NewPacket->Data + sizeof(ICMP_HEADER)),
+ IPPacket->Header, DataSize);
+ ((PICMP_HEADER)NewPacket->Data)->Type = Type;
+ ((PICMP_HEADER)NewPacket->Data)->Code = Code;
+ ((PICMP_HEADER)NewPacket->Data)->Checksum = 0;
+
+ ICMPTransmit(NTE, NewPacket);
+}
+
+/* EOF */