mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[TCPIP] Implement IOCTL_ICMP_ECHO_REQUEST in tcpip.sys
Also clean up ICMP handling code in sdk/lib/drivers/ip CORE-10760
This commit is contained in:
parent
dd2ff41dfc
commit
740a859e92
9 changed files with 505 additions and 241 deletions
|
@ -17,6 +17,7 @@ list(APPEND SOURCE
|
||||||
tcpip/cinfo.c
|
tcpip/cinfo.c
|
||||||
tcpip/dispatch.c
|
tcpip/dispatch.c
|
||||||
tcpip/fileobjs.c
|
tcpip/fileobjs.c
|
||||||
|
tcpip/icmp.c
|
||||||
tcpip/iinfo.c
|
tcpip/iinfo.c
|
||||||
tcpip/info.c
|
tcpip/info.c
|
||||||
tcpip/lock.c
|
tcpip/lock.c
|
||||||
|
|
|
@ -7,12 +7,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <pshpack1.h>
|
||||||
typedef struct ICMP_HEADER {
|
typedef struct ICMP_HEADER {
|
||||||
UCHAR Type; /* ICMP message type */
|
UINT8 Type; /* ICMP message type */
|
||||||
UCHAR Code; /* ICMP message code */
|
UINT8 Code; /* ICMP message code */
|
||||||
USHORT Checksum; /* ICMP message checksum */
|
UINT16 Checksum; /* ICMP message checksum */
|
||||||
ULONG Unused; /* ICMP unused */
|
UINT16 Identifier; /* ICMP Echo message identifier */
|
||||||
|
UINT16 Seq; /* ICMP Echo message sequence num */
|
||||||
} ICMP_HEADER, *PICMP_HEADER;
|
} ICMP_HEADER, *PICMP_HEADER;
|
||||||
|
#include <poppack.h>
|
||||||
|
|
||||||
/* ICMP message types */
|
/* ICMP message types */
|
||||||
#define ICMP_TYPE_ECHO_REPLY 0 /* Echo reply */
|
#define ICMP_TYPE_ECHO_REPLY 0 /* Echo reply */
|
||||||
|
@ -48,6 +51,12 @@ typedef struct ICMP_HEADER {
|
||||||
/* ICMP codes for ICMP_TYPE_PARAMETER */
|
/* ICMP codes for ICMP_TYPE_PARAMETER */
|
||||||
#define ICMP_CODE_TP_POINTER 1 /* Pointer indicates the error */
|
#define ICMP_CODE_TP_POINTER 1 /* Pointer indicates the error */
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
DispEchoRequest(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PIO_STACK_LOCATION IrpSp);
|
||||||
|
|
||||||
NTSTATUS ICMPSendDatagram(
|
NTSTATUS ICMPSendDatagram(
|
||||||
PADDRESS_FILE AddrFile,
|
PADDRESS_FILE AddrFile,
|
||||||
PTDI_CONNECTION_INFORMATION ConnInfo,
|
PTDI_CONNECTION_INFORMATION ConnInfo,
|
||||||
|
@ -63,11 +72,6 @@ VOID ICMPReceive(
|
||||||
PIP_INTERFACE Interface,
|
PIP_INTERFACE Interface,
|
||||||
PIP_PACKET IPPacket);
|
PIP_PACKET IPPacket);
|
||||||
|
|
||||||
VOID ICMPTransmit(
|
|
||||||
PIP_PACKET IPPacket,
|
|
||||||
PIP_TRANSMIT_COMPLETE Complete,
|
|
||||||
PVOID Context);
|
|
||||||
|
|
||||||
VOID ICMPReply(
|
VOID ICMPReply(
|
||||||
PIP_INTERFACE Interface,
|
PIP_INTERFACE Interface,
|
||||||
PIP_PACKET IPPacket,
|
PIP_PACKET IPPacket,
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
#include <tilists.h>
|
#include <tilists.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include <interface.h>
|
#include <interface.h>
|
||||||
|
#include <fileobjs.h>
|
||||||
#include <chew/chew.h>
|
#include <chew/chew.h>
|
||||||
#include <pseh/pseh2.h>
|
#include <pseh/pseh2.h>
|
||||||
|
#include <psdk/ipexport.h>
|
||||||
|
|
||||||
#endif /* _TCPIP_PCH_ */
|
#endif /* _TCPIP_PCH_ */
|
||||||
|
|
|
@ -36,4 +36,14 @@ NTSTATUS AddGenericHeaderIPv4(
|
||||||
UINT ExtraLength,
|
UINT ExtraLength,
|
||||||
PVOID *NextHeader );
|
PVOID *NextHeader );
|
||||||
|
|
||||||
|
NTSTATUS BuildRawIpPacket(
|
||||||
|
PADDRESS_FILE AddrFile,
|
||||||
|
PIP_PACKET Packet,
|
||||||
|
PIP_ADDRESS RemoteAddress,
|
||||||
|
USHORT RemotePort,
|
||||||
|
PIP_ADDRESS LocalAddress,
|
||||||
|
USHORT LocalPort,
|
||||||
|
PCHAR DataBuffer,
|
||||||
|
UINT DataLen);
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
431
drivers/network/tcpip/tcpip/icmp.c
Normal file
431
drivers/network/tcpip/tcpip/icmp.c
Normal file
|
@ -0,0 +1,431 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS TCP/IP protocol driver
|
||||||
|
* LICENCE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: ICMP functions implementation
|
||||||
|
* COPYRIGHT: 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
#include <checksum.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define UINT16_MAX (65535U)
|
||||||
|
|
||||||
|
typedef struct _ICMP_PACKET_CONTEXT
|
||||||
|
{
|
||||||
|
TDI_REQUEST TdiRequest;
|
||||||
|
KDPC TimeoutDpc;
|
||||||
|
KEVENT InitializationFinishedEvent;
|
||||||
|
KEVENT DatagramProcessedEvent;
|
||||||
|
LARGE_INTEGER TimerResolution;
|
||||||
|
INT64 StartTicks;
|
||||||
|
PIRP Irp;
|
||||||
|
PUCHAR CurrentReply;
|
||||||
|
UINT32 RemainingSize;
|
||||||
|
LONG nReplies;
|
||||||
|
PIO_WORKITEM FinishWorker;
|
||||||
|
KTIMER TimeoutTimer;
|
||||||
|
} ICMP_PACKET_CONTEXT, *PICMP_PACKET_CONTEXT;
|
||||||
|
|
||||||
|
static volatile INT16 IcmpSequence = 0;
|
||||||
|
|
||||||
|
static
|
||||||
|
UINT32
|
||||||
|
GetReplyStatus(PICMP_HEADER IcmpHeader)
|
||||||
|
{
|
||||||
|
switch (IcmpHeader->Type)
|
||||||
|
{
|
||||||
|
case ICMP_TYPE_ECHO_REPLY:
|
||||||
|
return IP_SUCCESS;
|
||||||
|
case ICMP_TYPE_DEST_UNREACH:
|
||||||
|
switch (IcmpHeader->Code)
|
||||||
|
{
|
||||||
|
case ICMP_CODE_DU_NET_UNREACH:
|
||||||
|
return IP_DEST_NET_UNREACHABLE;
|
||||||
|
case ICMP_CODE_DU_HOST_UNREACH:
|
||||||
|
return IP_DEST_HOST_UNREACHABLE;
|
||||||
|
case ICMP_CODE_DU_PROTOCOL_UNREACH:
|
||||||
|
return IP_DEST_PROT_UNREACHABLE;
|
||||||
|
case ICMP_CODE_DU_PORT_UNREACH:
|
||||||
|
return IP_DEST_PORT_UNREACHABLE;
|
||||||
|
case ICMP_CODE_DU_FRAG_DF_SET:
|
||||||
|
return IP_DEST_NET_UNREACHABLE;
|
||||||
|
case ICMP_CODE_DU_SOURCE_ROUTE_FAILED:
|
||||||
|
return IP_BAD_ROUTE;
|
||||||
|
default:
|
||||||
|
return IP_DEST_NET_UNREACHABLE;
|
||||||
|
}
|
||||||
|
case ICMP_TYPE_SOURCE_QUENCH:
|
||||||
|
return IP_SOURCE_QUENCH;
|
||||||
|
case ICMP_TYPE_TIME_EXCEEDED:
|
||||||
|
if (IcmpHeader->Code == ICMP_CODE_TE_REASSEMBLY)
|
||||||
|
return IP_TTL_EXPIRED_REASSEM;
|
||||||
|
else
|
||||||
|
return IP_TTL_EXPIRED_TRANSIT;
|
||||||
|
case ICMP_TYPE_PARAMETER:
|
||||||
|
return IP_PARAM_PROBLEM;
|
||||||
|
default:
|
||||||
|
return IP_REQ_TIMED_OUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
ClearReceiveHandler(
|
||||||
|
_In_ PADDRESS_FILE AddrFile)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
LockObject(AddrFile, &OldIrql);
|
||||||
|
AddrFile->RegisteredReceiveDatagramHandler = FALSE;
|
||||||
|
UnlockObject(AddrFile, OldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_WORKITEM_ROUTINE EndRequestHandler;
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
EndRequestHandler(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PVOID _Context)
|
||||||
|
{
|
||||||
|
PICMP_PACKET_CONTEXT Context = (PICMP_PACKET_CONTEXT)_Context;
|
||||||
|
PIO_STACK_LOCATION CurrentStack;
|
||||||
|
PIRP Irp;
|
||||||
|
UINT32 nReplies;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
KeWaitForSingleObject(&Context->DatagramProcessedEvent, Executive, KernelMode, FALSE, NULL);
|
||||||
|
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("Finishing request Context: %p\n", Context));
|
||||||
|
|
||||||
|
Irp = Context->Irp;
|
||||||
|
CurrentStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
if (Context->nReplies > 0)
|
||||||
|
{
|
||||||
|
((PICMP_ECHO_REPLY)Irp->AssociatedIrp.SystemBuffer)->Reserved = Context->nReplies;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = CurrentStack->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PICMP_ECHO_REPLY ReplyBuffer = (PICMP_ECHO_REPLY)Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
RtlZeroMemory(ReplyBuffer, sizeof(*ReplyBuffer));
|
||||||
|
ReplyBuffer->Status = IP_REQ_TIMED_OUT;
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_TIMEOUT;
|
||||||
|
Irp->IoStatus.Information = sizeof(*ReplyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for debugging
|
||||||
|
nReplies = ((PICMP_ECHO_REPLY)Irp->AssociatedIrp.SystemBuffer)->Reserved;
|
||||||
|
|
||||||
|
// taken from dispatch.c:IRPFinish
|
||||||
|
IoAcquireCancelSpinLock(&OldIrql);
|
||||||
|
IoSetCancelRoutine(Irp, NULL);
|
||||||
|
IoReleaseCancelSpinLock(OldIrql);
|
||||||
|
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
|
||||||
|
|
||||||
|
{
|
||||||
|
NTSTATUS _Status = FileCloseAddress(&Context->TdiRequest);
|
||||||
|
ASSERT(NT_SUCCESS(_Status));
|
||||||
|
}
|
||||||
|
|
||||||
|
IoFreeWorkItem(Context->FinishWorker);
|
||||||
|
ExFreePoolWithTag(Context, OUT_DATA_TAG);
|
||||||
|
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("Leaving, nReplies: %u\n", nReplies));
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ReceiveDatagram(
|
||||||
|
_In_opt_ PVOID TdiEventContext,
|
||||||
|
_In_ LONG SourceAddressLength,
|
||||||
|
_In_reads_bytes_(SourceAddressLength) PVOID SourceAddress,
|
||||||
|
_In_ LONG OptionsLength,
|
||||||
|
_In_reads_bytes_opt_(OptionsLength) PVOID Options,
|
||||||
|
_In_ ULONG ReceiveDatagramFlags,
|
||||||
|
_In_ ULONG BytesIndicated,
|
||||||
|
_In_ ULONG BytesAvailable,
|
||||||
|
_Out_ ULONG *OutBytesTaken,
|
||||||
|
_In_ PVOID Tsdu,
|
||||||
|
_Out_opt_ PIRP *IoRequestPacket)
|
||||||
|
{
|
||||||
|
PICMP_PACKET_CONTEXT Context = TdiEventContext;
|
||||||
|
PIPv4_HEADER IpHeader = Tsdu;
|
||||||
|
UINT16 IpHeaderSize = sizeof(IPv4_HEADER) + OptionsLength;
|
||||||
|
PICMP_HEADER IcmpHeader = (PICMP_HEADER)((PUCHAR)Tsdu + IpHeaderSize);
|
||||||
|
|
||||||
|
PVOID DataBuffer = (PUCHAR)Tsdu + IpHeaderSize + sizeof(ICMP_HEADER);
|
||||||
|
INT32 DataSize = min(BytesAvailable, UINT16_MAX) - IpHeaderSize - sizeof(ICMP_HEADER);
|
||||||
|
|
||||||
|
INT64 CurrentTime;
|
||||||
|
UINT32 RoundTripTime;
|
||||||
|
PICMP_ECHO_REPLY CurrentReply;
|
||||||
|
PUCHAR CurrentUserBuffer;
|
||||||
|
|
||||||
|
// do not handle echo requests
|
||||||
|
if (DataSize >= 0 && IcmpHeader->Type == ICMP_TYPE_ECHO_REQUEST)
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeWaitForSingleObject(&Context->InitializationFinishedEvent, Executive, KernelMode, FALSE, NULL);
|
||||||
|
KeClearEvent(&Context->DatagramProcessedEvent);
|
||||||
|
|
||||||
|
ASSERT(SourceAddressLength == sizeof(IPAddr));
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("Received datagram Context: 0x%p\n", TdiEventContext));
|
||||||
|
|
||||||
|
CurrentTime = KeQueryPerformanceCounter(NULL).QuadPart;
|
||||||
|
RoundTripTime = (CurrentTime - Context->StartTicks) * 1000 / Context->TimerResolution.QuadPart;
|
||||||
|
CurrentReply = (PICMP_ECHO_REPLY)Context->CurrentReply;
|
||||||
|
|
||||||
|
if (Context->RemainingSize >= sizeof(ICMP_ECHO_REPLY) && DataSize >= 0)
|
||||||
|
{
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("RemainingSize: %u, RoundTripTime: %u\n", Context->RemainingSize, RoundTripTime));
|
||||||
|
|
||||||
|
memcpy(&CurrentReply->Address, SourceAddress, sizeof(CurrentReply->Address));
|
||||||
|
CurrentReply->Status = GetReplyStatus(IcmpHeader);
|
||||||
|
CurrentReply->RoundTripTime = RoundTripTime;
|
||||||
|
CurrentReply->Reserved = 0;
|
||||||
|
CurrentReply->Data = NULL;
|
||||||
|
CurrentReply->DataSize = 0;
|
||||||
|
CurrentReply->Options.Ttl = IpHeader->Ttl;
|
||||||
|
CurrentReply->Options.Tos = IpHeader->Tos;
|
||||||
|
CurrentReply->Options.Flags = IpHeader->FlagsFragOfs >> 13;
|
||||||
|
CurrentReply->Options.OptionsData = NULL;
|
||||||
|
CurrentReply->Options.OptionsSize = 0;
|
||||||
|
|
||||||
|
Context->RemainingSize -= sizeof(ICMP_ECHO_REPLY);
|
||||||
|
Context->CurrentReply += sizeof(ICMP_ECHO_REPLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentUserBuffer = (PUCHAR)Context->Irp->UserBuffer + (Context->CurrentReply - (PUCHAR)Context->Irp->AssociatedIrp.SystemBuffer);
|
||||||
|
|
||||||
|
if (DataSize > 0 && Context->RemainingSize > 0)
|
||||||
|
{
|
||||||
|
UINT32 _DataSize = min(Context->RemainingSize, DataSize);
|
||||||
|
|
||||||
|
memcpy(Context->CurrentReply + Context->RemainingSize - _DataSize, DataBuffer, _DataSize);
|
||||||
|
CurrentReply->Data = CurrentUserBuffer + Context->RemainingSize - _DataSize;
|
||||||
|
CurrentReply->DataSize = _DataSize;
|
||||||
|
|
||||||
|
Context->RemainingSize -= _DataSize;
|
||||||
|
// Context->ReplyBuffer += _DataSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("RemainingSize: %u, DataSize: %d\n", Context->RemainingSize, DataSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OptionsLength > 0 && Context->RemainingSize > 0)
|
||||||
|
{
|
||||||
|
UINT32 _OptSize = min(Context->RemainingSize, OptionsLength);
|
||||||
|
|
||||||
|
memcpy(Context->CurrentReply + Context->RemainingSize + _OptSize, Options, _OptSize);
|
||||||
|
CurrentReply->Options.OptionsData = CurrentUserBuffer + Context->RemainingSize + _OptSize;
|
||||||
|
CurrentReply->Options.OptionsSize = _OptSize;
|
||||||
|
|
||||||
|
Context->RemainingSize -= _OptSize;
|
||||||
|
// Context->ReplyBuffer += _OptSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("RemainingSize: %u, OptSize: %d\n", Context->RemainingSize, OptionsLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->nReplies++;
|
||||||
|
|
||||||
|
if (Context->RemainingSize < sizeof(ICMP_ECHO_REPLY))
|
||||||
|
{
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("The space is over: %u\n", Context->RemainingSize));
|
||||||
|
|
||||||
|
// if the timer was inserted, that means DPC has not been queued yet
|
||||||
|
if (KeCancelTimer(&Context->TimeoutTimer))
|
||||||
|
{
|
||||||
|
PADDRESS_FILE AddrFile = (PADDRESS_FILE)Context->TdiRequest.Handle.AddressHandle;
|
||||||
|
ClearReceiveHandler(AddrFile);
|
||||||
|
|
||||||
|
IoQueueWorkItem(Context->FinishWorker, &EndRequestHandler, DelayedWorkQueue, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeSetEvent(&Context->DatagramProcessedEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KDEFERRED_ROUTINE TimeoutHandler;
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
TimeoutHandler(
|
||||||
|
_In_ PKDPC Dpc,
|
||||||
|
_In_opt_ PVOID _Context,
|
||||||
|
_In_opt_ PVOID SystemArgument1,
|
||||||
|
_In_opt_ PVOID SystemArgument2)
|
||||||
|
{
|
||||||
|
PICMP_PACKET_CONTEXT Context = (PICMP_PACKET_CONTEXT)_Context;
|
||||||
|
PADDRESS_FILE AddrFile = (PADDRESS_FILE)Context->TdiRequest.Handle.AddressHandle;
|
||||||
|
ClearReceiveHandler(AddrFile);
|
||||||
|
|
||||||
|
IoQueueWorkItem(Context->FinishWorker, &EndRequestHandler, DelayedWorkQueue, _Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
DispEchoRequest(
|
||||||
|
_In_ PDEVICE_OBJECT DeviceObject,
|
||||||
|
_In_ PIRP Irp,
|
||||||
|
_In_ PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PICMP_ECHO_REQUEST Request = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
UINT32 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
|
UINT32 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
NTSTATUS Status;
|
||||||
|
TDI_CONNECTION_INFORMATION ConnectionInfo;
|
||||||
|
TA_IP_ADDRESS RemoteAddressTa, LocalAddressTa;
|
||||||
|
PADDRESS_FILE AddrFile;
|
||||||
|
ULONG DataUsed;
|
||||||
|
PUCHAR Buffer;
|
||||||
|
UINT16 RequestSize;
|
||||||
|
PICMP_PACKET_CONTEXT SendContext;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
LARGE_INTEGER RequestTimeout;
|
||||||
|
UINT8 SavedTtl;
|
||||||
|
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("About to send datagram, OutputBufferLength: %u, SystemBuffer: %p\n", OutputBufferLength, Irp->AssociatedIrp.SystemBuffer));
|
||||||
|
|
||||||
|
// check buffers
|
||||||
|
if (OutputBufferLength < sizeof(ICMP_ECHO_REPLY) || InputBufferLength < sizeof(ICMP_ECHO_REQUEST))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check request parameters
|
||||||
|
if ((Request->DataSize > UINT16_MAX - sizeof(ICMP_HEADER) - sizeof(IPv4_HEADER)) ||
|
||||||
|
((UINT32)Request->DataOffset + Request->DataSize > InputBufferLength) ||
|
||||||
|
((UINT32)Request->OptionsOffset + Request->OptionsSize > InputBufferLength))
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(*SendContext), OUT_DATA_TAG);
|
||||||
|
if (!SendContext)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(&SendContext->TdiRequest, sizeof(SendContext->TdiRequest));
|
||||||
|
SendContext->TdiRequest.RequestContext = Irp;
|
||||||
|
|
||||||
|
// setting up everything needed for sending the packet
|
||||||
|
|
||||||
|
RtlZeroMemory(&RemoteAddressTa, sizeof(RemoteAddressTa));
|
||||||
|
RtlZeroMemory(&LocalAddressTa, sizeof(LocalAddressTa));
|
||||||
|
RtlZeroMemory(&ConnectionInfo, sizeof(ConnectionInfo));
|
||||||
|
|
||||||
|
RemoteAddressTa.TAAddressCount = 1;
|
||||||
|
RemoteAddressTa.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
|
||||||
|
RemoteAddressTa.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
||||||
|
RemoteAddressTa.Address[0].Address[0].in_addr = Request->Address;
|
||||||
|
|
||||||
|
LocalAddressTa.TAAddressCount = 1;
|
||||||
|
LocalAddressTa.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
|
||||||
|
LocalAddressTa.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
|
||||||
|
LocalAddressTa.Address[0].Address[0].in_addr = 0;
|
||||||
|
|
||||||
|
Status = FileOpenAddress(&SendContext->TdiRequest, &LocalAddressTa, IPPROTO_ICMP, FALSE, NULL);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("Failed to open address file status: 0x%x\n", Status));
|
||||||
|
|
||||||
|
ExFreePoolWithTag(SendContext, OUT_DATA_TAG);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddrFile = (PADDRESS_FILE)SendContext->TdiRequest.Handle.AddressHandle;
|
||||||
|
|
||||||
|
// setting up the context
|
||||||
|
|
||||||
|
KeQueryPerformanceCounter(&SendContext->TimerResolution);
|
||||||
|
SendContext->Irp = Irp;
|
||||||
|
SendContext->CurrentReply = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
SendContext->RemainingSize = OutputBufferLength;
|
||||||
|
SendContext->nReplies = 0;
|
||||||
|
SendContext->FinishWorker = IoAllocateWorkItem(DeviceObject);
|
||||||
|
KeInitializeEvent(&SendContext->InitializationFinishedEvent, NotificationEvent, FALSE);
|
||||||
|
KeInitializeEvent(&SendContext->DatagramProcessedEvent, NotificationEvent, TRUE);
|
||||||
|
|
||||||
|
KeInitializeDpc(&SendContext->TimeoutDpc, &TimeoutHandler, SendContext);
|
||||||
|
KeInitializeTimerEx(&SendContext->TimeoutTimer, SynchronizationTimer);
|
||||||
|
|
||||||
|
RequestTimeout.QuadPart = (-1LL) * 10 * 1000 * Request->Timeout;
|
||||||
|
|
||||||
|
ConnectionInfo.RemoteAddress = &RemoteAddressTa;
|
||||||
|
ConnectionInfo.RemoteAddressLength = sizeof(RemoteAddressTa);
|
||||||
|
|
||||||
|
RequestSize = sizeof(ICMP_HEADER) + Request->DataSize;
|
||||||
|
|
||||||
|
// making up the request packet
|
||||||
|
Buffer = ExAllocatePoolWithTag(NonPagedPool, RequestSize, OUT_DATA_TAG);
|
||||||
|
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
ExFreePoolWithTag(SendContext, OUT_DATA_TAG);
|
||||||
|
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
((PICMP_HEADER)Buffer)->Type = ICMP_TYPE_ECHO_REQUEST;
|
||||||
|
((PICMP_HEADER)Buffer)->Code = ICMP_TYPE_ECHO_REPLY;
|
||||||
|
((PICMP_HEADER)Buffer)->Checksum = 0;
|
||||||
|
((PICMP_HEADER)Buffer)->Identifier = (UINT_PTR)PsGetCurrentProcessId() & UINT16_MAX;
|
||||||
|
((PICMP_HEADER)Buffer)->Seq = InterlockedIncrement16(&IcmpSequence);
|
||||||
|
memcpy(Buffer + sizeof(ICMP_HEADER), (PUCHAR)Request + Request->DataOffset, Request->DataSize);
|
||||||
|
((PICMP_HEADER)Buffer)->Checksum = IPv4Checksum(Buffer, RequestSize, 0);
|
||||||
|
SavedTtl = Request->Ttl;
|
||||||
|
|
||||||
|
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, OutputBufferLength);
|
||||||
|
|
||||||
|
LockObject(AddrFile, &OldIrql);
|
||||||
|
|
||||||
|
AddrFile->TTL = SavedTtl;
|
||||||
|
AddrFile->ReceiveDatagramHandlerContext = SendContext;
|
||||||
|
AddrFile->ReceiveDatagramHandler = ReceiveDatagram;
|
||||||
|
AddrFile->RegisteredReceiveDatagramHandler = TRUE;
|
||||||
|
|
||||||
|
UnlockObject(AddrFile, OldIrql);
|
||||||
|
|
||||||
|
Status = AddrFile->Send(AddrFile, &ConnectionInfo, (PCHAR)Buffer, RequestSize, &DataUsed);
|
||||||
|
|
||||||
|
// From this point we may receive a reply packet.
|
||||||
|
// But we are not ready for it thus InitializationFinishedEvent is needed (see below)
|
||||||
|
|
||||||
|
SendContext->StartTicks = KeQueryPerformanceCounter(NULL).QuadPart;
|
||||||
|
|
||||||
|
ExFreePoolWithTag(Buffer, OUT_DATA_TAG);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
NTSTATUS _Status;
|
||||||
|
|
||||||
|
ClearReceiveHandler(AddrFile);
|
||||||
|
_Status = FileCloseAddress(&SendContext->TdiRequest);
|
||||||
|
ASSERT(NT_SUCCESS(_Status));
|
||||||
|
|
||||||
|
IoFreeWorkItem(SendContext->FinishWorker);
|
||||||
|
ExFreePoolWithTag(SendContext, OUT_DATA_TAG);
|
||||||
|
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("Failed to send a datagram: 0x%x\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
KeSetTimer(&SendContext->TimeoutTimer, RequestTimeout, &SendContext->TimeoutDpc);
|
||||||
|
KeSetEvent(&SendContext->InitializationFinishedEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
|
@ -475,12 +475,12 @@ TiDispatchInternal(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
|
* @brief Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
|
||||||
*
|
*
|
||||||
* @param[in] DeviceObject
|
* @param[in] DeviceObject
|
||||||
* Pointer to a device object for this driver
|
* Pointer to a device object for this driver
|
||||||
* @param[in] Irp
|
* @param[in] Irp
|
||||||
* Pointer to a I/O request packet
|
* Pointer to a I/O request packet
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* Status of the operation
|
* Status of the operation
|
||||||
*/
|
*/
|
||||||
|
@ -538,6 +538,11 @@ TiDispatch(
|
||||||
Status = DispTdiQueryIpHwAddress(DeviceObject, Irp, IrpSp);
|
Status = DispTdiQueryIpHwAddress(DeviceObject, Irp, IrpSp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IOCTL_ICMP_ECHO_REQUEST:
|
||||||
|
TI_DbgPrint(MIN_TRACE, ("ICMP_ECHO_REQUEST\n"));
|
||||||
|
Status = DispEchoRequest(DeviceObject, Irp, IrpSp);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
|
TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
|
||||||
IrpSp->Parameters.DeviceIoControl.IoControlCode));
|
IrpSp->Parameters.DeviceIoControl.IoControlCode));
|
||||||
|
|
|
@ -270,7 +270,6 @@ gdi32 -
|
||||||
dll/win32/gdi32/objects/linedda.c # Synced at 20090410
|
dll/win32/gdi32/objects/linedda.c # Synced at 20090410
|
||||||
|
|
||||||
iphlpapi -
|
iphlpapi -
|
||||||
dll/win32/iphlpapi/icmp.c # Synced to WineStaging-1.7.55
|
|
||||||
modules/rostests/winetests/iphlpapi # Synced to WineStaging-1.9.11
|
modules/rostests/winetests/iphlpapi # Synced to WineStaging-1.9.11
|
||||||
|
|
||||||
kernel32 -
|
kernel32 -
|
||||||
|
|
|
@ -26,95 +26,6 @@ NTSTATUS ICMPShutdown()
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN PrepareICMPPacket(
|
|
||||||
PADDRESS_FILE AddrFile,
|
|
||||||
PIP_INTERFACE Interface,
|
|
||||||
PIP_PACKET IPPacket,
|
|
||||||
PIP_ADDRESS Destination,
|
|
||||||
PCHAR Data,
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
PNDIS_PACKET NdisPacket;
|
|
||||||
NDIS_STATUS NdisStatus;
|
|
||||||
PIPv4_HEADER IPHeader;
|
|
||||||
ULONG Size;
|
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("Called. DataSize (%d).\n", DataSize));
|
|
||||||
|
|
||||||
IPInitializePacket(IPPacket, IP_ADDRESS_V4);
|
|
||||||
|
|
||||||
/* No special flags */
|
|
||||||
IPPacket->Flags = 0;
|
|
||||||
|
|
||||||
Size = sizeof(IPv4_HEADER) + DataSize;
|
|
||||||
|
|
||||||
/* Allocate NDIS packet */
|
|
||||||
NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Size );
|
|
||||||
|
|
||||||
if( !NT_SUCCESS(NdisStatus) ) return FALSE;
|
|
||||||
|
|
||||||
IPPacket->NdisPacket = NdisPacket;
|
|
||||||
IPPacket->MappedHeader = TRUE;
|
|
||||||
|
|
||||||
GetDataPtr( IPPacket->NdisPacket, 0,
|
|
||||||
(PCHAR *)&IPPacket->Header, &IPPacket->TotalSize );
|
|
||||||
ASSERT(IPPacket->TotalSize == Size);
|
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("Size (%d). Data at (0x%X).\n", Size, Data));
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("NdisPacket at (0x%X).\n", NdisPacket));
|
|
||||||
|
|
||||||
IPPacket->HeaderSize = sizeof(IPv4_HEADER);
|
|
||||||
IPPacket->Data = ((PCHAR)IPPacket->Header) + IPPacket->HeaderSize;
|
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("Copying Address: %x -> %x\n",
|
|
||||||
&IPPacket->DstAddr, Destination));
|
|
||||||
|
|
||||||
RtlCopyMemory(&IPPacket->DstAddr, Destination, sizeof(IP_ADDRESS));
|
|
||||||
RtlCopyMemory(IPPacket->Data, Data, DataSize);
|
|
||||||
|
|
||||||
/* 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));
|
|
||||||
/* Identification */
|
|
||||||
IPHeader->Id = (USHORT)Random();
|
|
||||||
/* One fragment at offset 0 */
|
|
||||||
IPHeader->FlagsFragOfs = 0;
|
|
||||||
/* Set TTL */
|
|
||||||
if (AddrFile)
|
|
||||||
IPHeader->Ttl = AddrFile->TTL;
|
|
||||||
else
|
|
||||||
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 = Interface->Unicast.Address.IPv4Address;
|
|
||||||
/* Destination address */
|
|
||||||
IPHeader->DstAddr = Destination->Address.IPv4Address;
|
|
||||||
|
|
||||||
|
|
||||||
TI_DbgPrint(MID_TRACE,("Leaving\n"));
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS ICMPSendDatagram(
|
NTSTATUS ICMPSendDatagram(
|
||||||
PADDRESS_FILE AddrFile,
|
PADDRESS_FILE AddrFile,
|
||||||
PTDI_CONNECTION_INFORMATION ConnInfo,
|
PTDI_CONNECTION_INFORMATION ConnInfo,
|
||||||
|
@ -132,79 +43,10 @@ NTSTATUS ICMPSendDatagram(
|
||||||
* Status of operation
|
* Status of operation
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
IP_PACKET Packet;
|
TI_DbgPrint(DEBUG_ICMP, ("Sending ICMP datagram (0x%x)\n", AddrFile));
|
||||||
PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress;
|
|
||||||
IP_ADDRESS RemoteAddress, LocalAddress;
|
|
||||||
NTSTATUS Status;
|
|
||||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
|
/* just forward the call to RawIP handler */
|
||||||
AddrFile, ConnInfo, BufferData, DataSize));
|
return RawIPSendDatagram(AddrFile, ConnInfo, BufferData, DataSize, DataUsed);
|
||||||
TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa));
|
|
||||||
|
|
||||||
switch( RemoteAddressTa->Address[0].AddressType ) {
|
|
||||||
case TDI_ADDRESS_TYPE_IP:
|
|
||||||
RemoteAddress.Type = IP_ADDRESS_V4;
|
|
||||||
RemoteAddress.Address.IPv4Address =
|
|
||||||
RemoteAddressTa->Address[0].Address[0].in_addr;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TI_DbgPrint(MID_TRACE,("About to get route to destination\n"));
|
|
||||||
|
|
||||||
LockObject(AddrFile, &OldIrql);
|
|
||||||
|
|
||||||
LocalAddress = AddrFile->Address;
|
|
||||||
if (AddrIsUnspecified(&LocalAddress))
|
|
||||||
{
|
|
||||||
/* If the local address is unspecified (0),
|
|
||||||
* then use the unicast address of the
|
|
||||||
* interface we're sending over
|
|
||||||
*/
|
|
||||||
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress )))
|
|
||||||
{
|
|
||||||
UnlockObject(AddrFile, OldIrql);
|
|
||||||
return STATUS_NETWORK_UNREACHABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalAddress = NCE->Interface->Unicast;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL )))
|
|
||||||
{
|
|
||||||
UnlockObject(AddrFile, OldIrql);
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = PrepareICMPPacket( AddrFile,
|
|
||||||
NCE->Interface,
|
|
||||||
&Packet,
|
|
||||||
&RemoteAddress,
|
|
||||||
BufferData,
|
|
||||||
DataSize );
|
|
||||||
|
|
||||||
UnlockObject(AddrFile, OldIrql);
|
|
||||||
|
|
||||||
if( !NT_SUCCESS(Status) )
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
TI_DbgPrint(MID_TRACE,("About to send datagram\n"));
|
|
||||||
|
|
||||||
Status = IPSendDatagram(&Packet, NCE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
*DataUsed = DataSize;
|
|
||||||
|
|
||||||
TI_DbgPrint(MID_TRACE,("Leaving\n"));
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,81 +60,34 @@ VOID ICMPReceive(
|
||||||
* IPPacket = Pointer to an IP packet that was received
|
* IPPacket = Pointer to an IP packet that was received
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PICMP_HEADER ICMPHeader;
|
PICMP_HEADER ICMPHeader = (PICMP_HEADER)IPPacket->Data;
|
||||||
|
UINT32 DataSize = IPPacket->TotalSize - IPPacket->HeaderSize;
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("Called.\n"));
|
TI_DbgPrint(DEBUG_ICMP, ("ICMPReceive: Size (%d) HeaderSize (%d) Type (%d) Code (%d) Checksum (0x%x)\n",
|
||||||
|
IPPacket->TotalSize, IPPacket->HeaderSize, ICMPHeader->Type, ICMPHeader->Code, ICMPHeader->Checksum));
|
||||||
|
|
||||||
ICMPHeader = (PICMP_HEADER)IPPacket->Data;
|
/* Discard too short packets */
|
||||||
|
if (DataSize < sizeof(ICMP_HEADER))
|
||||||
|
{
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("Packet doesn't fit ICMP header. Discarded\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("Size (%d).\n", IPPacket->TotalSize));
|
/* Discard packets with bad checksum */
|
||||||
|
if (!IPv4CorrectChecksum(IPPacket->Data, DataSize))
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("HeaderSize (%d).\n", IPPacket->HeaderSize));
|
{
|
||||||
|
TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum. Packet discarded\n"));
|
||||||
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 (!IPv4CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n"));
|
|
||||||
/* Discard packet */
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawIpReceive(Interface, IPPacket);
|
RawIpReceive(Interface, IPPacket);
|
||||||
|
|
||||||
switch (ICMPHeader->Type) {
|
if (ICMPHeader->Type == ICMP_TYPE_ECHO_REQUEST)
|
||||||
case ICMP_TYPE_ECHO_REQUEST:
|
{
|
||||||
ICMPReply( Interface, IPPacket, ICMP_TYPE_ECHO_REPLY, 0 );
|
ICMPReply(Interface, IPPacket, ICMP_TYPE_ECHO_REPLY, 0);
|
||||||
break;
|
|
||||||
|
|
||||||
case ICMP_TYPE_ECHO_REPLY:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
TI_DbgPrint(DEBUG_ICMP,
|
|
||||||
("Discarded ICMP datagram of unknown type %d.\n",
|
|
||||||
ICMPHeader->Type));
|
|
||||||
/* Discard packet */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID ICMPTransmit(
|
|
||||||
PIP_PACKET IPPacket,
|
|
||||||
PIP_TRANSMIT_COMPLETE Complete,
|
|
||||||
PVOID Context)
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
PNEIGHBOR_CACHE_ENTRY NCE;
|
|
||||||
|
|
||||||
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 ((NCE = RouteGetRouteToDestination(&IPPacket->DstAddr))) {
|
|
||||||
/* Send the packet */
|
|
||||||
IPSendDatagram(IPPacket, NCE);
|
|
||||||
} else {
|
|
||||||
/* No route to destination (or no free resources) */
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("No route to destination address 0x%X.\n",
|
|
||||||
IPPacket->DstAddr.Address.IPv4Address));
|
|
||||||
IPPacket->Free(IPPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID ICMPReply(
|
VOID ICMPReply(
|
||||||
PIP_INTERFACE Interface,
|
PIP_INTERFACE Interface,
|
||||||
PIP_PACKET IPPacket,
|
PIP_PACKET IPPacket,
|
||||||
|
@ -314,19 +109,36 @@ VOID ICMPReply(
|
||||||
{
|
{
|
||||||
UINT DataSize;
|
UINT DataSize;
|
||||||
IP_PACKET NewPacket;
|
IP_PACKET NewPacket;
|
||||||
|
ADDRESS_FILE FakeAddrFile;
|
||||||
|
PNEIGHBOR_CACHE_ENTRY NCE;
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_ICMP, ("Called. Type (%d) Code (%d).\n", Type, Code));
|
TI_DbgPrint(DEBUG_ICMP, ("Called. Type (%d) Code (%d).\n", Type, Code));
|
||||||
|
|
||||||
DataSize = IPPacket->TotalSize - IPPacket->HeaderSize;
|
DataSize = IPPacket->TotalSize - IPPacket->HeaderSize;
|
||||||
|
|
||||||
if( !PrepareICMPPacket(NULL, Interface, &NewPacket, &IPPacket->SrcAddr,
|
/* First check if we have a route to sender */
|
||||||
IPPacket->Data, DataSize) ) return;
|
NCE = RouteGetRouteToDestination(&IPPacket->SrcAddr);
|
||||||
|
if (!NCE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the only data needed to generate a packet */
|
||||||
|
FakeAddrFile.Protocol = IPPROTO_ICMP;
|
||||||
|
FakeAddrFile.TTL = 128;
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(BuildRawIpPacket(
|
||||||
|
&FakeAddrFile, &NewPacket, &IPPacket->SrcAddr, 0, &Interface->Unicast, 0, IPPacket->Data, DataSize)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
((PICMP_HEADER)NewPacket.Data)->Type = Type;
|
((PICMP_HEADER)NewPacket.Data)->Type = Type;
|
||||||
((PICMP_HEADER)NewPacket.Data)->Code = Code;
|
((PICMP_HEADER)NewPacket.Data)->Code = Code;
|
||||||
((PICMP_HEADER)NewPacket.Data)->Checksum = 0;
|
((PICMP_HEADER)NewPacket.Data)->Checksum = 0;
|
||||||
|
((PICMP_HEADER)NewPacket.Data)->Checksum = (USHORT)IPv4Checksum(NewPacket.Data, DataSize, 0);
|
||||||
|
|
||||||
ICMPTransmit(&NewPacket, NULL, NULL);
|
IPSendDatagram(&NewPacket, NCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -46,7 +46,7 @@ NTSTATUS AddGenericHeaderIPv4(
|
||||||
&IPPacket->TotalSize );
|
&IPPacket->TotalSize );
|
||||||
IPPacket->MappedHeader = TRUE;
|
IPPacket->MappedHeader = TRUE;
|
||||||
|
|
||||||
IPPacket->HeaderSize = 20;
|
IPPacket->HeaderSize = sizeof(IPv4_HEADER);
|
||||||
|
|
||||||
TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n",
|
TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n",
|
||||||
BufferSize, IPPacket->Header));
|
BufferSize, IPPacket->Header));
|
||||||
|
|
Loading…
Reference in a new issue