|
|
/*++
Copyright (c) 1996-1999 Microsoft Corporation
Module Name: TimeStmp.c
Abstract: TimeStamp module
Author: Shreem, Sanjayka
Environment: Kernel Mode
Revision History:
--*/
#include "psched.h"
#pragma hdrstop
// The pipe information
typedef struct _TS_PIPE { // ContextInfo - Generic context info
PS_PIPE_CONTEXT ContextInfo; } TS_PIPE, *PTS_PIPE;
// The flow information
typedef struct _TS_FLOW { // ContextInfo - Generic context info
PS_FLOW_CONTEXT ContextInfo; } TS_FLOW, *PTS_FLOW;
/* Global variables */ LIST_ENTRY TsList; NDIS_SPIN_LOCK TsSpinLock; ULONG TsCount;
/* Static */
/* Forward */
NDIS_STATUS TimeStmpInitializePipe ( IN HANDLE PsPipeContext, IN PPS_PIPE_PARAMETERS PipeParameters, IN PPS_PIPE_CONTEXT ComponentPipeContext, IN PPS_PROCS PsProcs, IN PPS_UPCALLS Upcalls );
NDIS_STATUS TimeStmpModifyPipe ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_PIPE_PARAMETERS PipeParameters );
VOID TimeStmpDeletePipe ( IN PPS_PIPE_CONTEXT PipeContext );
NDIS_STATUS TimeStmpCreateFlow ( IN PPS_PIPE_CONTEXT PipeContext, IN HANDLE PsFlowContext, IN PCO_CALL_PARAMETERS CallParameters, IN PPS_FLOW_CONTEXT ComponentFlowContext );
NDIS_STATUS TimeStmpModifyFlow ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN PCO_CALL_PARAMETERS CallParameters );
VOID TimeStmpDeleteFlow ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext );
VOID TimeStmpEmptyFlow ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext );
VOID TimeStmpSetInformation ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN NDIS_OID Oid, IN ULONG Len, IN void *Data);
VOID TimeStmpQueryInformation ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN NDIS_OID Oid, IN ULONG Len, IN PVOID Data, IN OUT PULONG BytesWritten, IN OUT PULONG BytesNeeded, IN OUT PNDIS_STATUS Status);
NDIS_STATUS TimeStmpCreateClassMap ( IN PPS_PIPE_CONTEXT PipeContext, IN HANDLE PsClassMapContext, IN PTC_CLASS_MAP_FLOW ClassMap, IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext );
NDIS_STATUS TimeStmpDeleteClassMap ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext );
BOOLEAN TimeStmpSubmitPacket ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN PPS_CLASS_MAP_CONTEXT ClassMapContext, IN PPACKET_INFO_BLOCK Packet );
BOOLEAN TimeStmpReceivePacket ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN PPS_CLASS_MAP_CONTEXT ClassMapContext, IN PNDIS_PACKET Packet, IN NDIS_MEDIUM Medium );
BOOLEAN TimeStmpReceiveIndication( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN PPS_CLASS_MAP_CONTEXT ClassMapContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize, IN UINT TransportHeaderOffset );
/* End Forward */
VOID InitializeTimeStmp( PPSI_INFO Info ) { Info->PipeContextLength = ((sizeof(TS_PIPE)+7) & ~7); Info->FlowContextLength = ((sizeof(TS_FLOW)+7) & ~7); Info->ClassMapContextLength = sizeof(PS_CLASS_MAP_CONTEXT); Info->InitializePipe = TimeStmpInitializePipe; Info->ModifyPipe = TimeStmpModifyPipe; Info->DeletePipe = TimeStmpDeletePipe; Info->CreateFlow = TimeStmpCreateFlow; Info->ModifyFlow = TimeStmpModifyFlow; Info->DeleteFlow = TimeStmpDeleteFlow; Info->EmptyFlow = TimeStmpEmptyFlow; Info->CreateClassMap = TimeStmpCreateClassMap; Info->DeleteClassMap = TimeStmpDeleteClassMap; Info->SubmitPacket = TimeStmpSubmitPacket; Info->ReceivePacket = NULL; Info->ReceiveIndication = NULL; Info->SetInformation = TimeStmpSetInformation; Info->QueryInformation = TimeStmpQueryInformation;
NdisAllocateSpinLock(&TsSpinLock); InitializeListHead( &TsList );
TsCount = 0; }
NDIS_STATUS TimeStmpInitializePipe ( IN HANDLE PsPipeContext, IN PPS_PIPE_PARAMETERS PipeParameters, IN PPS_PIPE_CONTEXT ComponentPipeContext, IN PPS_PROCS PsProcs, IN PPS_UPCALLS Upcalls ) { PPS_PIPE_CONTEXT Pipe = ComponentPipeContext;
return (*Pipe->NextComponent->InitializePipe)( PsPipeContext, PipeParameters, Pipe->NextComponentContext, PsProcs, Upcalls); }
NDIS_STATUS TimeStmpModifyPipe ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_PIPE_PARAMETERS PipeParameters ) { PPS_PIPE_CONTEXT Pipe = PipeContext;
return (*Pipe->NextComponent->ModifyPipe)( Pipe->NextComponentContext, PipeParameters); }
VOID TimeStmpDeletePipe ( IN PPS_PIPE_CONTEXT PipeContext ) { PPS_PIPE_CONTEXT Pipe = PipeContext;
(*Pipe->NextComponent->DeletePipe)(Pipe->NextComponentContext); }
NDIS_STATUS TimeStmpCreateFlow ( IN PPS_PIPE_CONTEXT PipeContext, IN HANDLE PsFlowContext, IN PCO_CALL_PARAMETERS CallParameters, IN PPS_FLOW_CONTEXT ComponentFlowContext ) { PPS_PIPE_CONTEXT Pipe = PipeContext;
return (*Pipe->NextComponent->CreateFlow)( Pipe->NextComponentContext, PsFlowContext, CallParameters, ComponentFlowContext->NextComponentContext); }
NDIS_STATUS TimeStmpModifyFlow ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN PCO_CALL_PARAMETERS CallParameters ) { PPS_PIPE_CONTEXT Pipe = PipeContext;
return (*Pipe->NextComponent->ModifyFlow)( Pipe->NextComponentContext, FlowContext->NextComponentContext, CallParameters); }
VOID TimeStmpDeleteFlow ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext ) { PPS_PIPE_CONTEXT Pipe = PipeContext;
(*Pipe->NextComponent->DeleteFlow)( Pipe->NextComponentContext, FlowContext->NextComponentContext); }
VOID TimeStmpEmptyFlow ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext ) { PPS_PIPE_CONTEXT Pipe = PipeContext;
(*Pipe->NextComponent->EmptyFlow)( Pipe->NextComponentContext, FlowContext->NextComponentContext); }
VOID TimeStmpSetInformation ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN NDIS_OID Oid, IN ULONG Len, IN void *Data) { PPS_PIPE_CONTEXT Pipe = PipeContext; PPS_FLOW_CONTEXT Flow = FlowContext;
(*Pipe->NextComponent->SetInformation)( Pipe->NextComponentContext, (Flow)?Flow->NextComponentContext:0, Oid, Len, Data); }
VOID TimeStmpQueryInformation ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN NDIS_OID Oid, IN ULONG Len, IN PVOID Data, IN OUT PULONG BytesWritten, IN OUT PULONG BytesNeeded, IN OUT PNDIS_STATUS Status) { PPS_PIPE_CONTEXT Pipe = PipeContext; PPS_FLOW_CONTEXT Flow = FlowContext;
(*Pipe->NextComponent->QueryInformation)( Pipe->NextComponentContext, (Flow)?Flow->NextComponentContext:0, Oid, Len, Data, BytesWritten, BytesNeeded, Status); }
NDIS_STATUS TimeStmpCreateClassMap ( IN PPS_PIPE_CONTEXT PipeContext, IN HANDLE PsClassMapContext, IN PTC_CLASS_MAP_FLOW ClassMap, IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext ) { return (*PipeContext->NextComponent->CreateClassMap)( PipeContext->NextComponentContext, PsClassMapContext, ClassMap, ComponentClassMapContext->NextComponentContext); }
NDIS_STATUS TimeStmpDeleteClassMap ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext ) { return (*PipeContext->NextComponent->DeleteClassMap)( PipeContext->NextComponentContext, ComponentClassMapContext->NextComponentContext); }
/* Routine Description:
Checks to see if there is any application requesting time-stamping for these end-points
Return Value: MARK_NONE, MARK_IN_PKT, MARK_IN_BUF */
int CheckForMatch( ULONG SrcIp, ULONG DstIp, USHORT SrcPort, USHORT DstPort, USHORT Proto, USHORT IpId, USHORT Size, USHORT Direction) { PLIST_ENTRY ListEntry; PTS_ENTRY pEntry; int Status = MARK_NONE;
NdisAcquireSpinLock(&TsSpinLock); ListEntry = TsList.Flink; while (ListEntry != &TsList) { pEntry = CONTAINING_RECORD(ListEntry, TS_ENTRY, Linkage);
if( ((pEntry->SrcIp == UL_ANY) || (pEntry->SrcIp == SrcIp)) && ((pEntry->SrcPort== US_ANY) || (pEntry->SrcPort == SrcPort)) && ((pEntry->DstIp == UL_ANY) || (pEntry->DstIp == DstIp)) && ((pEntry->DstPort == US_ANY) || (pEntry->DstPort == DstPort)) && ((pEntry->Direction == US_ANY) || (pEntry->Direction == Direction)) && ((pEntry->Proto == US_ANY) || (pEntry->Proto == Proto))) { if(pEntry->Type == MARK_IN_BUF) { LARGE_INTEGER PerfFrequency, CurrentTime; UINT64 RecdTime, Freq; MARK_IN_BUF_RECORD Record, *pRecord;
Status = MARK_IN_BUF;
if((int)( (char*)pEntry->pPacketStore - (char*)pEntry->pPacketStoreHead + sizeof(MARK_IN_BUF_RECORD) ) < PACKET_STORE_SIZE ) { pEntry->pPacketStore->IpId = IpId; pEntry->pPacketStore->Size = Size;
CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
// Convert the perffrequency into 100ns interval. //
Freq = 0; Freq |= PerfFrequency.HighPart; Freq = Freq << 32; Freq |= PerfFrequency.LowPart;
pEntry->pPacketStore->TimeValue = 0; pEntry->pPacketStore->TimeValue |= CurrentTime.HighPart; pEntry->pPacketStore->TimeValue = pEntry->pPacketStore->TimeValue << 32; pEntry->pPacketStore->TimeValue |= CurrentTime.LowPart; // Normalize cycles with the frequency //
pEntry->pPacketStore->TimeValue *= 10000000; pEntry->pPacketStore->TimeValue /= Freq;
pEntry->pPacketStore = (PMARK_IN_BUF_RECORD)((char*)pEntry->pPacketStore + sizeof(MARK_IN_BUF_RECORD)); } else { pEntry->pPacketStore = pEntry->pPacketStoreHead; }
NdisReleaseSpinLock(&TsSpinLock); return Status; } else if(pEntry->Type == MARK_IN_PKT) { Status = MARK_IN_PKT; NdisReleaseSpinLock(&TsSpinLock); return Status; } } else { ListEntry = ListEntry->Flink; } }
NdisReleaseSpinLock(&TsSpinLock); return Status; }
/* Routine Description:
Adds an end-point to the list of monitoring end-points Return Value: TRUE, FALSE */ BOOL AddRequest( PFILE_OBJECT FileObject, ULONG SrcIp, USHORT SrcPort, ULONG DstIp, USHORT DstPort, USHORT Proto, USHORT Type, USHORT Direction) { PTS_ENTRY pEntry = NULL;
PsAllocatePool(pEntry, sizeof(TS_ENTRY), TsTag);
if( !pEntry ) return FALSE; InitializeListHead(&pEntry->Linkage);
pEntry->SrcIp = SrcIp; pEntry->SrcPort = SrcPort; pEntry->DstIp = DstIp; pEntry->DstPort = DstPort; pEntry->Proto = Proto; pEntry->Type = Type; pEntry->Direction = Direction;
pEntry->FileObject = FileObject; pEntry->pPacketStore = NULL; pEntry->pPacketStoreHead = NULL;
if(Type == MARK_IN_BUF) { PsAllocatePool( pEntry->pPacketStoreHead, PACKET_STORE_SIZE, TsTag );
if( !pEntry->pPacketStoreHead) { PsFreePool( pEntry ); return FALSE; }
pEntry->pPacketStore = pEntry->pPacketStoreHead; }
NdisAcquireSpinLock(&TsSpinLock);
/* Need to check for duplication ..*/ InsertHeadList(&TsList, &pEntry->Linkage);
InterlockedIncrement( &TsCount );
NdisReleaseSpinLock(&TsSpinLock);
return TRUE; }
/* Routine Description:
Removes an end-point to the list of monitoring end-points Return Value: None Note: Here, 0xffffffff means, wild card => Don't have to match on that field */ void RemoveRequest( PFILE_OBJECT FileObject, ULONG SrcIp, USHORT SrcPort, ULONG DstIp, USHORT DstPort, USHORT Proto) { PLIST_ENTRY ListEntry; PTS_ENTRY pEntry;
NdisAcquireSpinLock(&TsSpinLock);
ListEntry = TsList.Flink;
while (ListEntry != &TsList) {
pEntry = CONTAINING_RECORD(ListEntry, TS_ENTRY, Linkage);
if( ((FileObject == ULongToPtr(UL_ANY)) || (pEntry->FileObject == FileObject)) && ((SrcIp == UL_ANY) || (pEntry->SrcIp == SrcIp)) && ((SrcPort == US_ANY) || (pEntry->SrcPort == SrcPort)) && ((DstIp == UL_ANY) || (pEntry->DstIp == DstIp)) && ((DstPort == US_ANY) || (pEntry->DstPort == SrcPort)) && ((Proto== US_ANY) || (pEntry->Proto == Proto))) { RemoveEntryList(&pEntry->Linkage);
if( pEntry->pPacketStoreHead) PsFreePool( pEntry->pPacketStoreHead ); PsFreePool( pEntry );
InterlockedDecrement( &TsCount );
/* Need to go back to the beginning of the list againg.. */ ListEntry = TsList.Flink; } else { ListEntry = ListEntry->Flink; } }
NdisReleaseSpinLock(&TsSpinLock); }
int CopyTimeStmps( PFILE_OBJECT FileObject, PVOID buf, ULONG Len) { PLIST_ENTRY ListEntry; PTS_ENTRY pEntry; ULONG DataLen; LARGE_INTEGER LargeLen;
if( Len < PACKET_STORE_SIZE ) return 0;
NdisAcquireSpinLock(&TsSpinLock);
ListEntry = TsList.Flink;
while (ListEntry != &TsList) {
pEntry = CONTAINING_RECORD(ListEntry, TS_ENTRY, Linkage);
if( pEntry->FileObject == FileObject) { // Copy the data across and rest the pointers.. //
LargeLen.QuadPart = ((char*)pEntry->pPacketStore) - ((char*)pEntry->pPacketStoreHead);
DataLen = LargeLen.LowPart; NdisMoveMemory( buf, pEntry->pPacketStoreHead, DataLen); pEntry->pPacketStore = pEntry->pPacketStoreHead;
NdisReleaseSpinLock(&TsSpinLock); return DataLen; } else { ListEntry = ListEntry->Flink; } }
NdisReleaseSpinLock(&TsSpinLock); return 0; }
VOID UnloadTimeStmp( ) { // Clear all the Requests //
RemoveRequest( ULongToPtr(UL_ANY), UL_ANY, US_ANY, UL_ANY, US_ANY, US_ANY);
// Free the spin lock //
NdisFreeSpinLock(&TsSpinLock); }
BOOLEAN TimeStmpSubmitPacket ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN PPS_CLASS_MAP_CONTEXT ClassMapContext, IN PPACKET_INFO_BLOCK PacketInfo ) { PTS_PIPE Pipe = (PTS_PIPE)PipeContext; PTS_FLOW Flow = (PTS_FLOW)FlowContext; PNDIS_PACKET Packet = PacketInfo->NdisPacket;
PNDIS_BUFFER ArpBuf , IpBuf , TcpBuf, UdpBuf, DataBuf; ULONG ArpLen , IpLen , IpHdrLen , TcpLen , UdpLen, DataLen , TotalLen , TcpHeaderOffset; VOID *ArpH; IPHeader UNALIGNED *IPH; TCPHeader UNALIGNED *TCPH; UDPHeader UNALIGNED *UDPH;
IPAddr Src, Dst; BOOLEAN bFragment; USHORT SrcPort , DstPort , IPID, FragOffset ,Size; PVOID GeneralVA , Data; ULONG i, Ret;
if( (TsCount == 0) || (NDIS_GET_PACKET_PROTOCOL_TYPE(Packet) != NDIS_PROTOCOL_ID_TCP_IP)) { goto SUBMIT_NEXT; }
IpBuf = NULL;
// Steps
// Parse the IP Packet.
// Look for the appropriate ports.
// Look for the data portion and put in the Time & length there.
if(1) { PVOID pAddr; PNDIS_BUFFER pNdisBuf1, pNdisBuf2; UINT Len; ULONG TransportHeaderOffset = 0;
TransportHeaderOffset = PacketInfo->IPHeaderOffset;
NdisGetFirstBufferFromPacket( Packet, &ArpBuf, &ArpH, &ArpLen, &TotalLen );
pNdisBuf1 = Packet->Private.Head; NdisQueryBuffer(pNdisBuf1, &pAddr, &Len);
while(Len <= TransportHeaderOffset) {
TransportHeaderOffset -= Len; NdisGetNextBuffer(pNdisBuf1, &pNdisBuf2); NdisQueryBuffer(pNdisBuf2, &pAddr, &Len); pNdisBuf1 = pNdisBuf2; }
/* Buffer Descriptor corresponding to Ip Packet */ IpBuf = pNdisBuf1;
/* Length of this Buffer (IP buffer) */ IpLen = Len - TransportHeaderOffset;
/* Starting Virtual Address for this buffer */ GeneralVA = pAddr; /* Virtual Address of the IP Header */ IPH = (IPHeader *)(((PUCHAR)pAddr) + TransportHeaderOffset); }
if(!IpBuf) goto SUBMIT_NEXT;
/* Let's try to parse the packet */ Src = IPH->iph_src; Dst = IPH->iph_dest; IPID = net_short(IPH->iph_id); Size = net_short(IPH->iph_length); IpHdrLen = ((IPH->iph_verlen & (uchar)~IP_VER_FLAG) << 2); FragOffset = IPH->iph_offset & IP_OFFSET_MASK; FragOffset = net_short(FragOffset) * 8;
bFragment = (IPH->iph_offset & IP_MF_FLAG) || (FragOffset > 0);
// Don't want to deal with Fragmented packets right now..//
if ( bFragment ) goto SUBMIT_NEXT;
switch (IPH->iph_protocol) { case IPPROTO_TCP :
if (IPH && ((USHORT)IpLen > IpHdrLen)) { // We have more than the IP Header in this MDL //
TCPH = (TCPHeader *) ((PUCHAR)IPH + IpHdrLen); TcpLen = IpLen - IpHdrLen; TcpBuf = IpBuf;
} else { // TCP Header is in the next MDL //
NdisGetNextBuffer(IpBuf, &TcpBuf);
if(!TcpBuf) goto SUBMIT_NEXT;
GeneralVA = NULL; NdisQueryBuffer(TcpBuf, &GeneralVA, &TcpLen ); TCPH = (TCPHeader *) GeneralVA; }
/* At this point, TcpBuf, TCPH and TcpLen contain the proper values */
// Get the port numbers out.
SrcPort = net_short(TCPH->tcp_src); DstPort = net_short(TCPH->tcp_dest);
// We have the TCP Buffer now. Get to the DATA //
TcpHeaderOffset = TCP_HDR_SIZE(TCPH);
if (TcpLen > TcpHeaderOffset) { // We have the DATA right here! //
Data = (PUCHAR)TCPH + TcpHeaderOffset; DataLen = TcpLen - TcpHeaderOffset;
} else { NdisGetNextBuffer(TcpBuf, &DataBuf);
if(!DataBuf) goto SUBMIT_NEXT;
GeneralVA = NULL;
NdisQueryBuffer(DataBuf, &Data, &DataLen ); }
/* At this point, DataBuf, Data and DataLen contain the proper values */ goto TimeStamp; break;
case IPPROTO_UDP: if (IpLen > IpHdrLen) { // We have more than the IP Header in this MDL //
UDPH = (UDPHeader *) ((PUCHAR)IPH + IpHdrLen); UdpLen = IpLen - IpHdrLen; UdpBuf = IpBuf; } else { // UDP Header is in the next MDL //
NdisGetNextBuffer(IpBuf, &UdpBuf);
if(!UdpBuf) goto SUBMIT_NEXT;
GeneralVA = NULL; NdisQueryBuffer(UdpBuf, &GeneralVA, &UdpLen );
UDPH = (UDPHeader *) GeneralVA; }
/* At this point, UdpBuf, UDPH and UdpLen contain the proper values */
SrcPort = net_short(UDPH->uh_src); DstPort = net_short(UDPH->uh_dest);
// Get to the data. //
if (UdpLen > sizeof (UDPHeader)) { // We have the DATA right here! //
Data = (PUCHAR) UDPH + sizeof (UDPHeader); DataLen = UdpLen - sizeof (UDPHeader); } else { NdisGetNextBuffer(UdpBuf, &DataBuf);
if(!DataBuf) goto SUBMIT_NEXT;
GeneralVA = NULL; NdisQueryBuffer(DataBuf, &Data, &DataLen ); }
/* At this point, DataBuf, Data and DataLen contain the proper values */ goto TimeStamp; break;
default: goto SUBMIT_NEXT; }
TimeStamp:
Ret = CheckForMatch( Src, Dst, SrcPort, DstPort, IPH->iph_protocol, IPID, Size, DIR_SEND); if( Ret == MARK_IN_PKT) { if (DataLen >= sizeof(MARK_IN_PKT_RECORD)) { LARGE_INTEGER PerfFrequency, CurrentTime; UINT64 RecdTime, Freq; PMARK_IN_PKT_RECORD pRecord;
pRecord = (PMARK_IN_PKT_RECORD) Data; CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
pRecord->BufferSize = DataLen;
// Convert the perffrequency into 100ns interval //
Freq = 0; Freq |= PerfFrequency.HighPart; Freq = Freq << 32; Freq |= PerfFrequency.LowPart;
// convert to uint64 //
pRecord->TimeSentWire = 0; pRecord->TimeSentWire |= CurrentTime.HighPart; pRecord->TimeSentWire = pRecord->TimeSentWire << 32; pRecord->TimeSentWire |= CurrentTime.LowPart;
// Normalize cycles with the frequency.
pRecord->TimeSentWire *= 10000000; pRecord->TimeSentWire /= Freq;
if(IPH->iph_protocol == IPPROTO_UDP) UDPH->uh_xsum = 0; } } else if( Ret == MARK_IN_BUF) { // Nothing more to be done..
} SUBMIT_NEXT: return (*Pipe->ContextInfo.NextComponent->SubmitPacket)( Pipe->ContextInfo.NextComponentContext, Flow->ContextInfo.NextComponentContext, (ClassMapContext != NULL) ? ClassMapContext->NextComponentContext : NULL, PacketInfo); }
BOOLEAN TimeStmpReceivePacket ( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN PPS_CLASS_MAP_CONTEXT ClassMapContext, IN PNDIS_PACKET Packet, IN NDIS_MEDIUM Medium ) { PPS_PIPE_CONTEXT Pipe; LARGE_INTEGER CurrentTime; IPHeader UNALIGNED *IPH; TCPHeader UNALIGNED *TCPH; UDPHeader UNALIGNED *UDPH; IPAddr Src, Dst; PUCHAR headerBuffer, pData; PNDIS_BUFFER pFirstBuffer; ULONG firstbufferLength, bufferLength, HeaderLength; ULONG TotalIpLen, IPDataLength, IpHdrLen; ULONG TotalTcpLen, TcpDataLen, TotalLen, TcpHeaderOffset, i; int TotalUdpLen, UdpDataLen, UdpHdrLen, DataLen, Ret; USHORT SrcPort, DstPort, IPID, FragOffset, Size; BOOLEAN bFragment, bFirstFragment, bLastFragment;
/* This will give the size of the "media-specific" header. So, this will be the offset to IP packet */ UINT HeaderBufferSize ;
ushort type; // Protocol type
uint ProtOffset; // Offset in Data to non-media info.
if( ( TsCount == 0) || (NDIS_GET_PACKET_PROTOCOL_TYPE(Packet) == NDIS_PROTOCOL_ID_TCP_IP)) { return TRUE; }
Pipe = PipeContext; HeaderBufferSize = NDIS_GET_PACKET_HEADER_SIZE(Packet);
NdisGetFirstBufferFromPacket(Packet, // packet
&pFirstBuffer, // first buffer descriptor
&headerBuffer, // VA of the first buffer
&firstbufferLength, // length of the header+lookahead
&bufferLength); // length of the bytes in the buffers
IPH = (IPHeader *) ((PUCHAR)headerBuffer + HeaderBufferSize); // Check the header length and the version //
HeaderLength = ((IPH->iph_verlen & (uchar)~IP_VER_FLAG) << 2);
// If the HeaderLength seems to be incorrect, let's not try to parse //
if( (HeaderLength < sizeof(IPHeader)) || (HeaderLength > bufferLength) ) return TRUE;
// Get past the IP Header and get the rest of the stuff out //
TotalIpLen = (uint)net_short(IPH->iph_length);
// Make sure the version and IpData Len are correct //
if( ((IPH->iph_verlen & IP_VER_FLAG) != IP_VERSION ) || ( TotalIpLen < HeaderLength ) || ( TotalIpLen > bufferLength )) return TRUE; // Let's try to parse the packet //
Src = IPH->iph_src; Dst = IPH->iph_dest; IPID = net_short(IPH->iph_id); Size = net_short(IPH->iph_length);
FragOffset = IPH->iph_offset & IP_OFFSET_MASK; FragOffset = net_short(FragOffset) * 8;
bFragment = (IPH->iph_offset & IP_MF_FLAG) || (FragOffset > 0); bFirstFragment = bFragment && (FragOffset == 0); bLastFragment = bFragment && (!(IPH->iph_offset & IP_MF_FLAG));
// If this is a fragment and NOT the first one, just put the Timestamp in here.
// Otherwise, let it get to the protocols for processing.
if (bFragment ) return TRUE;
// Do the protocol specific stuff //
switch (IPH->iph_protocol) { case IPPROTO_TCP:
TotalTcpLen = TotalIpLen - HeaderLength; TCPH = (TCPHeader *) (((PUCHAR)IPH) + HeaderLength);
// For TCP, the data offset is part of the TCP Header */
TcpHeaderOffset = TCP_HDR_SIZE(TCPH); DataLen = TotalTcpLen - TcpHeaderOffset; pData = (PUCHAR) TCPH + TcpHeaderOffset;
SrcPort = net_short(TCPH->tcp_src); DstPort = net_short(TCPH->tcp_dest);
goto TimeStmp; break;
case IPPROTO_UDP: TotalUdpLen = TotalIpLen - HeaderLength; UDPH = (UDPHeader *) (((PUCHAR)IPH) + HeaderLength);
// For UDP, the header size is fixed //
DataLen = TotalUdpLen - sizeof(UDPHeader); pData = ((PUCHAR) UDPH) + sizeof (UDPHeader);
SrcPort = net_short(UDPH->uh_src); DstPort = net_short(UDPH->uh_dest);
goto TimeStmp; break;
default: break; }
return TRUE;
TimeStmp:
Ret = CheckForMatch( Src, Dst, SrcPort, DstPort, IPH->iph_protocol, IPID, Size, DIR_RECV); if( Ret == MARK_IN_PKT) { if (DataLen >= sizeof(MARK_IN_PKT_RECORD)) { LARGE_INTEGER PerfFrequency, CurrentTime; UINT64 RecdTime, Freq; PMARK_IN_PKT_RECORD pRecord;
pRecord = (PMARK_IN_PKT_RECORD) pData; CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
// Convert the perffrequency into 100ns interval //
Freq = 0; Freq |= PerfFrequency.HighPart; Freq = Freq << 32; Freq |= PerfFrequency.LowPart;
//convert from large_integer to uint64
pRecord->TimeReceivedWire = 0; pRecord->TimeReceivedWire |= CurrentTime.HighPart; pRecord->TimeReceivedWire = pRecord->TimeReceivedWire << 32; pRecord->TimeReceivedWire |= CurrentTime.LowPart;
// Normalize cycles with the frequency.
pRecord->TimeReceivedWire *= 10000000; pRecord->TimeReceivedWire /= Freq;
if(IPH->iph_protocol == IPPROTO_UDP) UDPH->uh_xsum = 0; } } else if( Ret == MARK_IN_BUF) { }
return TRUE; }
#ifdef NEVER
//
// This function receives a buffer from NDIS which is indicated to the transport.
// We use this function and work past the headers (tcp, ip) and get to the data.
// Then, we timestamp and reset the checksum flags.
// We make the assumption that the lookahead is atleast 128.
// mac header ~ 8+8, ip header ~20, tcp/udp ~ 20+options, LOG_RECORD ~ 44
// they all add up to less than 128. If this is not a good assumption, We will need
// to get into MiniportTransferData and such.
//
BOOLEAN TimeStmpReceiveIndication( IN PPS_PIPE_CONTEXT PipeContext, IN PPS_FLOW_CONTEXT FlowContext, IN PPS_CLASS_MAP_CONTEXT ClassMapContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize, IN UINT TransportHeaderOffset ) { PPS_PIPE_CONTEXT Pipe = PipeContext; LARGE_INTEGER CurrentTime; IPHeader UNALIGNED *IPH = NULL; TCPHeader UNALIGNED *TCPH = NULL; UDPHeader UNALIGNED *UDPH = NULL; IPAddr Src, Dst; PUCHAR headerBuffer = NULL, pData = NULL; PNDIS_BUFFER pFirstBuffer = NULL; ULONG firstbufferLength = 0, bufferLength = 0, HeaderLength = 0; ULONG TotalIpLen = 0, IPDataLength = 0, IpHdrLen = 0; ULONG TotalTcpLen = 0, TcpDataLen = 0, TotalLen = 0, TcpHeaderOffset = 0; ULONG TotalUdpLen = 0, UdpDataLen = 0, UdpHdrLen = 0; USHORT SrcPort = 0, DstPort = 0, IPID = 0, FragOffset = 0, Size = 0; BOOLEAN bFragment, bFirstFragment, bLastFragment; ULONG i = 0; ushort type; // Protocol type
uint ProtOffset; // Offset in Data to non-media info.
UINT MoreHeaderInLookAhead = 0;
// Don't know anything about the MAC headers, piggy back from PSCHED...
// Calculate if the header is more than the standard HeaderBufferSize (i.e. SNAP header, etc.)
//
MoreHeaderInLookAhead = TransportHeaderOffset - HeaderBufferSize;
if (MoreHeaderInLookAhead) { // Just munge these, so that we can actually get down to business //
((PUCHAR) LookAheadBuffer) += MoreHeaderInLookAhead; LookAheadBufferSize -= MoreHeaderInLookAhead; }
if (LookAheadBufferSize > sizeof(IPHeader)) { IPH = (IPHeader *) (PUCHAR)LookAheadBuffer; // Check the header length and the version. If any of these
// checks fail silently discard the packet.
HeaderLength = ((IPH->iph_verlen & (uchar)~IP_VER_FLAG) << 2);
if (HeaderLength >= sizeof(IPHeader) && HeaderLength <= LookAheadBufferSize) { // Get past the IP Header and get the rest of the stuff out//
TotalIpLen = (uint)net_short(IPH->iph_length);
if ((IPH->iph_verlen & IP_VER_FLAG) == IP_VERSION && TotalIpLen >= HeaderLength && TotalIpLen <= LookAheadBufferSize) { Src = IPH->iph_src; Dst = IPH->iph_dest; IPID = net_short(IPH->iph_id); Size = net_short(IPH->iph_length );
FragOffset = IPH->iph_offset & IP_OFFSET_MASK; FragOffset = net_short(FragOffset) * 8;
bFragment = (IPH->iph_offset & IP_MF_FLAG) || (FragOffset > 0); bFirstFragment = bFragment && (FragOffset == 0); bLastFragment = bFragment && (!(IPH->iph_offset & IP_MF_FLAG));
// If this is a fragment and NOT the first one, just put the Timestamp in here.
// Otherwise, let it get to the protocols for processing.
if (bFragment ) return TRUE;
// Do the protocol specific stuff.//
switch (IPH->iph_protocol) { case IPPROTO_TCP: TotalTcpLen = TotalIpLen - HeaderLength; TCPH = (TCPHeader *) (((PUCHAR)IPH) + HeaderLength);
SrcPort = net_short(TCPH->tcp_src); DstPort = net_short(TCPH->tcp_dest);
TcpHeaderOffset = TCP_HDR_SIZE(TCPH); pData = (PUCHAR) TCPH + TcpHeaderOffset; TcpDataLen = TotalTcpLen - TcpHeaderOffset;
goto TimeStmp; break;
case IPPROTO_UDP: TotalUdpLen = TotalIpLen - HeaderLength; UDPH = (UDPHeader *) (((PUCHAR)IPH) + HeaderLength); UdpDataLen = TotalUdpLen - sizeof(UDPHeader); pData = ((PUCHAR) UDPH) + sizeof (UDPHeader);
SrcPort = net_short(UDPH->uh_src); DstPort = net_short(UDPH->uh_dest);
if (UdpDataLen < sizeof(UDPHeader)) return TRUE;
goto TimeStmp; break;
default: break; } } } } TimeStmp:
CheckForMatch( Src, Dst, SrcPort, DstPort,0, IPID, Size, DIR_RECV); /*
if (CheckInPortAndIpList(Src, DstPort)) { LARGE_INTEGER PerfFrequency; UINT64 RecdTime, Freq; LOG_RECORD Record;
pRecord = &Record; CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
//
// Convert the perffrequency into 100ns interval.
//
Freq = 0; Freq |= PerfFrequency.HighPart; Freq = Freq << 32; Freq |= PerfFrequency.LowPart;
pRecord->TimeReceivedWire = 0; pRecord->TimeReceivedWire |= CurrentTime.HighPart; pRecord->TimeReceivedWire = pRecord->TimeReceivedWire << 32; pRecord->TimeReceivedWire |= CurrentTime.LowPart;
// Normalize cycles with the frequency.
pRecord->TimeReceivedWire *= 10000000; pRecord->TimeReceivedWire /= Freq;
if( (int)( (char*)pPacketStore - (char*)pPacketStoreHead + sizeof(PACKET_RECORD) ) < PACKET_STORE_SIZE ) { pPacketStore->IpId = IPID; pPacketStore->cSeperator1='y'; pPacketStore->TimeValue = pRecord->TimeReceivedWire; pPacketStore->cSeperator2 = 'm'; pPacketStore->Size = Size; pPacketStore->cSeperator3 = 'z'; pPacketStore->cSeperator4 = 'z';
pPacketStore = (PPACKET_RECORD)((char*)pPacketStore + sizeof(PACKET_RECORD)); } else { pPacketStore = pPacketStoreHead; } } */
return TRUE; }
#endif
|