windows-nt/Source/XPSP1/NT/net/qos/tools/timestmp/timestmp.c
2020-09-26 16:20:57 +08:00

1817 lines
58 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1996-1999 Microsoft Corporation
Module Name:
timestmp.c
Abstract:
Timestamper module
Author:
Shreedhar Madhavapeddi (shreem)
Revision History:
--*/
#include <timestmp.h>
//
// The following struct has to be in ssync with
// ndis\trfccntl\tools\qtcp\qtcp.c
//
typedef struct _LOG_RECORD{
UINT64 TimeSent;
UINT64 TimeReceived;
UINT64 TimeSentWire; // These fields are used by the kernel timestamper
UINT64 TimeReceivedWire; // These fields are used by the kernel timestamper
UINT64 Latency;
INT BufferSize;
INT SequenceNumber;
} LOG_RECORD, *PLOG_RECORD;
ULONG GlobalSequenceNumber = 0;
// 321618 needs checking for PSCHED's existence.
NDIS_STRING PschedDriverName = NDIS_STRING_CONST("\\Device\\PSched");
HANDLE PschedHandle;
NTSTATUS CheckForPsched(VOID);
//
// TCP Headers (redefined here, since there are no exported headers
//
#define IP_OFFSET_MASK ~0x00E0 // Mask for extracting offset field.
#define net_short(x) ((((x)&0xff) << 8) | (((x)&0xff00) >> 8))
/*
* Protocols (from winsock.h)
*/
#define IPPROTO_IP 0 /* dummy for IP */
#define IPPROTO_ICMP 1 /* control message protocol */
#define IPPROTO_IGMP 2 /* group management protocol */
#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
#define IPPROTO_TCP 6 /* tcp */
#define IPPROTO_PUP 12 /* pup */
#define IPPROTO_UDP 17 /* user datagram protocol */
#define IPPROTO_IDP 22 /* xns idp */
#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */
#define IPPROTO_IPSEC 51 /* ???????? */
#define IPPROTO_RAW 255 /* raw IP packet */
#define IPPROTO_MAX 256
#define IP_MF_FLAG 0x0020 // 'More fragments flag'
#define IP_VERSION 0x40
#define IP_VER_FLAG 0xF0
#define TCP_OFFSET_MASK 0xf0
#define TCP_HDR_SIZE(t) (uint)(((*(uchar *)&(t)->tcp_flags) & TCP_OFFSET_MASK) >> 2)
typedef int SeqNum; // A sequence number.
struct TCPHeader {
ushort tcp_src; // Source port.
ushort tcp_dest; // Destination port.
SeqNum tcp_seq; // Sequence number.
SeqNum tcp_ack; // Ack number.
ushort tcp_flags; // Flags and data offset.
ushort tcp_window; // Window offered.
ushort tcp_xsum; // Checksum.
ushort tcp_urgent; // Urgent pointer.
};
typedef struct TCPHeader TCPHeader;
struct UDPHeader {
ushort uh_src; // Source port.
ushort uh_dest; // Destination port.
ushort uh_length; // Length
ushort uh_xsum; // Checksum.
}; /* UDPHeader */
typedef struct UDPHeader UDPHeader;
#ifdef DBG
//
// Define the Trace Level.
//
#define TS_DBG_DEATH 1
#define TS_DBG_TRACE 2
//
// Masks
//
#define TS_DBG_PIPE 0x00000001
#define TS_DBG_FLOW 0x00000002
#define TS_DBG_SEND 0x00000004
#define TS_DBG_RECV 0x00000008
#define TS_DBG_INIT 0x00000010
#define TS_DBG_OID 0x00000020
#define TS_DBG_CLASS_MAP 0x00000040
ULONG DbgTraceLevel = 1;
ULONG DbgTraceMask = 0x8;
#define TimeStmpTrace(_DebugLevel, _DebugMask, _Out) \
if ((DbgTraceLevel >= _DebugLevel) && \
((_DebugMask) & DbgTraceMask)){ \
DbgPrint("TimeStamp: "); \
DbgPrint _Out; \
}
#else // DBG
#define TimeStmpTrace
#endif
#define PORT_RANGE 20
USHORT IPIDList[PORT_RANGE];
NDIS_SPIN_LOCK IPIDListLock;
#define PORT_RANGE 20
USHORT IPIDListRecv[PORT_RANGE];
NDIS_SPIN_LOCK IPIDListLockRecv;
/*
Let's create a driver unload function, so that timestmp is stoppable via net sto
p timestmp
*/
VOID
TimeStmpUnload(
IN PDRIVER_OBJECT DriverObject
)
{
IoctlCleanup();
return;
}
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;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_PIPE, ("[TimeStmpIndicatePipe]: \n"));
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;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_PIPE, ("[TimeStmpModifyPipe]: \n"));
return (*Pipe->NextComponent->ModifyPipe)(
Pipe->NextComponentContext, PipeParameters);
}
VOID
TimeStmpDeletePipe (
IN PPS_PIPE_CONTEXT PipeContext
)
{
PPS_PIPE_CONTEXT Pipe = PipeContext;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_PIPE, ("[TimeStmpDeletePipe]: \n"));
(*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;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_FLOW, ("[TimeStmpCreateFlow]: \n"));
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;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_FLOW, ("[TimeStmpModifyFlow]: \n"));
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;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_FLOW, ("[TimeStmpDeleteFlow]: \n"));
(*Pipe->NextComponent->DeleteFlow)(
Pipe->NextComponentContext,
FlowContext->NextComponentContext);
}
BOOLEAN
TimeStmpSubmitPacket (
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext,
IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
IN PPACKET_INFO_BLOCK PacketInfo
)
{
PPS_PIPE_CONTEXT Pipe = PipeContext;
LARGE_INTEGER CurrentTime;
IPHeader UNALIGNED *IPH = NULL;
TCPHeader UNALIGNED *TCPH = NULL;
UDPHeader UNALIGNED *UDPH = NULL;
PVOID ArpH = NULL, GeneralVA = NULL, Data = NULL;
IPAddr Src, Dst;
PNDIS_BUFFER ArpBuf = NULL, IpBuf = NULL, TcpBuf = NULL, DataBuf = NULL, UdpBuf = NULL;
ULONG ArpLen = 0, IpLen = 0, IpHdrLen = 0, TcpLen = 0, DataLen = 0, TotalLen = 0, TcpHeaderOffset = 0;
ULONG UdpLen = 0;
USHORT SrcPort = 0, DstPort = 0, IPID = 0, FragOffset = 0;
PLIST_ENTRY CurrentEntry = NULL, LastEntry = NULL;
BOOLEAN bFragment, bFirstFragment, bLastFragment;
ULONG i = 0;
PLOG_RECORD pRecord = NULL;
PNDIS_PACKET Packet = PacketInfo->NdisPacket;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_SEND, ("[TimeStmpSubmitPacket]: \n"));
//
// Steps
// Parse the IP Packet.
// Look for the appropriate ports.
// Look for the data portion and put in the Time & length there.
//
NdisGetFirstBufferFromPacket(
Packet,
&ArpBuf,
&ArpH,
&ArpLen,
&TotalLen
);
//
// We are guaranteed that the ARP buffer if always a different MDL, so
// jump to the next MDL
//
NdisGetNextBuffer(ArpBuf, &IpBuf)
if (IpBuf) {
NdisQueryBuffer(IpBuf,
&GeneralVA,
&IpLen
);
IPH = (IPHeader *) GeneralVA;
if (!IPH) {
goto FAILURE;
}
Src = net_short(IPH->iph_src);
Dst = net_short(IPH->iph_dest);
IPID = net_short(IPH->iph_id);
//IpHdrLen = 8 * 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);
bFirstFragment = bFragment && (FragOffset == 0);
bLastFragment = bFragment && (!(IPH->iph_offset & IP_MF_FLAG));
if (bFragment && (!bFirstFragment)) {
//
// Its a fragment alright and NOT the first one.
//
NdisAcquireSpinLock(&IPIDListLock);
for (i = 0; i < PORT_RANGE; i++) {
//
// Found the match...
//
if (IPIDList[i] == IPID) {
if (bLastFragment) {
//
// Since it is the last fragment, recall
// the IP ID.
//
IPIDList[i] = 0xffff;
}
NdisReleaseSpinLock(&IPIDListLock);
//
// Is the data in the same buffer?
//
if (IpLen <= IpHdrLen) {
NdisGetNextBuffer(IpBuf, &DataBuf);
if(DataBuf) {
NdisQueryBuffer(DataBuf,
&Data,
&DataLen
);
goto TimeStamp;
} else {
goto FAILURE;
}
} else {
//
// The Data Offsets need to be primed now.
//
DataLen = IpLen - FragOffset;
Data = ((PUCHAR) GeneralVA) + IpHdrLen;
goto TimeStamp;
}
}
}
NdisReleaseSpinLock(&IPIDListLock);
//
// If we are here, we dont care about this IPID for this fragment.
// Just return TRUE to continue processing.
//
//
// Ready to go.
//
PacketInfo->FlowContext = FlowContext;
PacketInfo->ClassMapContext = ClassMapContext;
return (*Pipe->NextComponent->SubmitPacket)(
Pipe->NextComponentContext,
FlowContext->NextComponentContext,
ClassMapContext?ClassMapContext->NextComponentContext:0,
PacketInfo);
}
//
// If it is not a fragment, depending upon the protocol, process differently
//
switch (IPH->iph_protocol) {
case IPPROTO_TCP :
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_SEND, ("[TimeStmpSubmitPacket]: Procol TCP\n"));
if (IPH && ((USHORT)IpLen > IpHdrLen)) {
//
// We have more than the IP Header in this MDL.
//
TCPH = (TCPHeader *) ((PUCHAR)GeneralVA + IpHdrLen);
TcpLen = IpLen - IpHdrLen;
TcpBuf = IpBuf;
} else {
//
// TCP Header is in the next MDL
//
NdisGetNextBuffer(IpBuf, &TcpBuf);
if(TcpBuf) {
GeneralVA = NULL;
NdisQueryBuffer(TcpBuf,
&GeneralVA,
&TcpLen
);
TCPH = (TCPHeader *) GeneralVA;
} else {
goto FAILURE;
}
}
//
// 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) {
GeneralVA = NULL;
NdisQueryBuffer(DataBuf,
&Data,
&DataLen
);
} else {
goto FAILURE;
}
}
if (CheckInPortList(DstPort) && bFirstFragment) {
NdisAcquireSpinLock(&IPIDListLock);
// need new Entry for IPID
for (i = 0; i < PORT_RANGE; i++) {
//
// Look for a free slot
//
if (0xffff == IPIDList[i]) {
IPIDList[i] = IPID;
break;
}
}
NdisReleaseSpinLock(&IPIDListLock);
if (i == PORT_RANGE) {
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_SEND, ("Couldn't find an empty IPID - Bailing \n"));
goto FAILURE;
}
//DbgBreakPoint();
}
//
// Let's timestmp this now.
//
if (CheckInPortList(DstPort)) {
goto TimeStamp;
} else {
//
// This is not one of our packet, get out.
//
goto FAILURE;
}
break;
case IPPROTO_UDP:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_SEND, ("[TimeStmpSubmitPacket]: Protocol UDP\n"));
if (IPH && (IpLen > IpHdrLen)) {
//
// We have more than the IP Header in this MDL.
//
UDPH = (UDPHeader *) ((PUCHAR)GeneralVA + IpHdrLen);
UdpLen = IpLen - IpHdrLen;
UdpBuf = IpBuf;
} else {
//
// UDP Header is in the next MDL
//
NdisGetNextBuffer(IpBuf, &UdpBuf);
if(UdpBuf) {
GeneralVA = NULL;
NdisQueryBuffer(UdpBuf,
&GeneralVA,
&UdpLen
);
UDPH = (UDPHeader *) GeneralVA;
} else {
goto FAILURE;
}
}
SrcPort = net_short(UDPH->uh_src); // Source port.
DstPort = net_short(UDPH->uh_dest); // Destination port.
//
// 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) {
GeneralVA = NULL;
NdisQueryBuffer(DataBuf,
&Data,
&DataLen
);
} else {
goto FAILURE;
}
}
if (CheckInPortList(DstPort) && bFirstFragment) {
NdisAcquireSpinLock(&IPIDListLock);
// need new Entry for IPID
for (i = 0; i < PORT_RANGE; i++) {
//
// Look for a free slot
//
if (0xffff == IPIDList[i]) {
IPIDList[i] = IPID;
break;
}
ASSERT(FALSE);
}
NdisReleaseSpinLock(&IPIDListLock);
//
// Couldnt find a free IPID place holder, lets bail.
//
if (PORT_RANGE == i) {
goto FAILURE;
}
}
//
// Let's timestmp this now.
//
if (CheckInPortList(DstPort)) {
goto TimeStamp;
} else {
//
// This is not one of our packet, get out.
//
goto FAILURE;
}
break;
case IPPROTO_RAW:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_SEND, ("[TimeStmpSubmitPacket]: Protocol RAW\n"));
goto FAILURE;
break;
case IPPROTO_IGMP:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_SEND, ("[TimeStmpSubmitPacket]: Protocol IGMP\n"));
goto FAILURE;
break;
case IPPROTO_ICMP:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_SEND, ("[TimeStmpSubmitPacket]: Protocol TCMP\n"));
goto FAILURE;
break;
default:
//TimeStmpTrace(TS_DBG_DEATH, TS_DBG_SEND, ("[TimeStmpSubmitPacket]: Protocol - UNKNOWN (%d)\n", IPH->iph_protocol));
goto FAILURE;
//DbgBreakPoint();
}
} else {
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_SEND, ("[TimeStmpSubmitPacket]: NO Buffer beyond MAC Header\n"));
goto FAILURE;
}
TimeStamp:
//
// If we get here, the Data and DataLen variables have been primed.
// Set the Time and Length.
//
if (Data) {
pRecord = (PLOG_RECORD) Data;
if (DataLen > sizeof (LOG_RECORD)) {
LARGE_INTEGER PerfFrequency;
UINT64 Freq;
//
// Set the fields accordingly
pRecord->BufferSize = DataLen;
//pRecord->SequenceNumber = InterlockedIncrement(&GlobalSequenceNumber);
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->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;
}
}
//
// Ready to go.
//
PacketInfo->FlowContext = FlowContext;
PacketInfo->ClassMapContext = ClassMapContext;
return (*Pipe->NextComponent->SubmitPacket)(
Pipe->NextComponentContext,
FlowContext->NextComponentContext,
ClassMapContext?ClassMapContext->NextComponentContext:0,
PacketInfo);
FAILURE:
//
// Ready to go.
//
PacketInfo->FlowContext = FlowContext;
PacketInfo->ClassMapContext = ClassMapContext;
return (*Pipe->NextComponent->SubmitPacket)(
Pipe->NextComponentContext,
FlowContext->NextComponentContext,
ClassMapContext?ClassMapContext->NextComponentContext:0,
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 = 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, Size = 0;
ULONG TotalUdpLen = 0, UdpDataLen = 0, UdpHdrLen = 0;
USHORT SrcPort = 0, DstPort = 0, IPID = 0, FragOffset = 0;
BOOLEAN bFragment, bFirstFragment, bLastFragment;
ULONG i = 0;
PLOG_RECORD pRecord = NULL;
UINT HeaderBufferSize = NDIS_GET_PACKET_HEADER_SIZE(Packet);
ushort type; // Protocol type
uint ProtOffset; // Offset in Data to non-media info.
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceivePacket]: \n"));
NdisGetFirstBufferFromPacket(Packet, // packet
&pFirstBuffer, // first buffer descriptor
&headerBuffer, // ptr to the start of packet
&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. If any of these
// checks fail silently discard the packet.
HeaderLength = ((IPH->iph_verlen & (uchar)~IP_VER_FLAG) << 2);
if (HeaderLength >= sizeof(IPHeader) && HeaderLength <= bufferLength) {
//
// 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 <= bufferLength) {
Src = net_short(IPH->iph_src);
Dst = net_short(IPH->iph_dest);
IPID = net_short(IPH->iph_id);
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 && !bFirstFragment) {
NdisAcquireSpinLock(&IPIDListLockRecv);
for (i = 0; i < PORT_RANGE; i++) {
if (IPID == IPIDListRecv[i]) {
if (bLastFragment) {
//
// If its the last fragment, release the slot.
//
IPIDListRecv[i] = 0xffff;
}
break;
}
}
NdisReleaseSpinLock(&IPIDListLockRecv);
if (i == PORT_RANGE) {
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("Couldnt find an IPID that we care about, get outta here.\n"));
goto RECV_FAILURE;
}
//
// So we found a IPID that matches - set the timestamp and get out after this.
//
TotalLen = TotalIpLen - FragOffset;
pData = ((PUCHAR) IPH) + IpHdrLen;
if (TotalLen > sizeof (LOG_RECORD)) {
LARGE_INTEGER PerfFrequency;
UINT64 RecdTime, Freq;
pRecord = (LOG_RECORD *) pData;
CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
//
// Convert the perffrequency into 100ns interval.
//
Freq = 0;
Freq |= PerfFrequency.HighPart;
Freq = Freq << 32;
Freq |= PerfFrequency.LowPart;
//convert from Largeinteger 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;
}
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);
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceivePacket]: *TCP* Address: SRC = %x DST = %x, Port S : %x, Port D: %x\n",
IPH->iph_src,
IPH->iph_dest,
SrcPort,
DstPort));
TcpHeaderOffset = TCP_HDR_SIZE(TCPH);
pData = (PUCHAR) TCPH + TcpHeaderOffset;
TcpDataLen = TotalTcpLen - TcpHeaderOffset;
if ((CheckInPortList(DstPort)) && (TcpDataLen > sizeof (LOG_RECORD))) {
LARGE_INTEGER PerfFrequency;
UINT64 RecdTime, Freq;
pRecord = (LOG_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;
} else if (CheckInPortList(DstPort)) {
if (TcpDataLen < sizeof(LOG_RECORD))
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("The Datagram was too small!! IpLen:%d, Tcplen:%d HeaderOff(tcp):%d log_record:%d\n", TotalIpLen, TotalTcpLen, TcpHeaderOffset, sizeof (LOG_RECORD)));
}
//
// If its the first fragment, keep a place holder so we know which
// subsequent IP fragments to timestamp.
//
if ((CheckInPortList(DstPort)) && bFirstFragment) {
NdisAcquireSpinLock(&IPIDListLockRecv);
// need new Entry for IPID
for (i = 0; i < PORT_RANGE; i++) {
//
// Look for a free slot
//
if (0xffff == IPIDListRecv[i]) {
IPIDListRecv[i] = IPID;
break;
}
}
NdisReleaseSpinLock(&IPIDListLockRecv);
if (i == PORT_RANGE) {
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("Couldn't find an empty IPID - Bailing \n"));
}
}
break;
case IPPROTO_UDP:
TotalUdpLen = TotalIpLen - HeaderLength;
UDPH = (UDPHeader *) (((PUCHAR)IPH) + HeaderLength);
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("PAcket %x, IPH = %x, UDPH = %x, HeaderLength = %x\n", Packet, IPH, UDPH, HeaderLength));
UdpDataLen = TotalUdpLen - sizeof(UDPHeader);
pData = ((PUCHAR) UDPH) + sizeof (UDPHeader);
SrcPort = net_short(UDPH->uh_src); // Source port.
DstPort = net_short(UDPH->uh_dest); // Destination port.
if (UdpDataLen < sizeof(UDPHeader)) {
return TRUE;
}
if ((CheckInPortList(DstPort)) && (UdpDataLen > sizeof(LOG_RECORD))) {
LARGE_INTEGER PerfFrequency;
UINT64 RecdTime, Freq;
pRecord = (LOG_RECORD *) pData;
CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
//
// Convert the perffrequency into 100ns interval.
//
Freq = 0;
Freq |= PerfFrequency.HighPart;
Freq = Freq << 32;
Freq |= PerfFrequency.LowPart;
// convert 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;
//
// Dont want to get rejected due to bad xsum ...
//
UDPH->uh_xsum = 0;
} else if (CheckInPortList(DstPort)) {
if ((UdpDataLen) < sizeof(LOG_RECORD))
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_RECV, ("The Datagram was too small (UDP)!! IpLen:%d, Size:%d log_record:%d\n",
TotalIpLen, UdpDataLen, sizeof (LOG_RECORD)));
}
if ((CheckInPortList(DstPort)) && bFirstFragment) {
NdisAcquireSpinLock(&IPIDListLockRecv);
// need new Entry for IPID
for (i = 0; i < PORT_RANGE; i++) {
//
// Look for a free slot
//
if (0xffff == IPIDListRecv[i]) {
IPIDListRecv[i] = IPID;
break;
}
}
NdisReleaseSpinLock(&IPIDListLockRecv);
if (i == PORT_RANGE) {
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_RECV, ("Couldn't find an empty IPID - Bailing \n"));
}
}
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceivePacket]: *UDP* Address: SRC = %x DST = %x, Port S : %x, Port D: %x\n",
IPH->iph_src,
IPH->iph_dest,
UDPH->uh_src,
UDPH->uh_dest));
break;
case IPPROTO_RAW:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceivePacket]: Protocol RAW\n"));
break;
case IPPROTO_IGMP:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceivePacket]: Protocol IGMP\n"));
break;
case IPPROTO_ICMP:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceivePacket]: Protocol TCMP\n"));
break;
default:
;
//TimeStmpTrace(TS_DBG_DEATH, TS_DBG_RECV, ("[TimeStmpReceivePacket]: Protocol - UNKNOWN (%d)\n", IPH->iph_protocol));
//DbgBreakPoint();
}
}
}
RECV_FAILURE:
return TRUE;
}
//
// 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, Size = 0;
ULONG TotalUdpLen = 0, UdpDataLen = 0, UdpHdrLen = 0;
USHORT SrcPort = 0, DstPort = 0, IPID = 0, FragOffset = 0;
BOOLEAN bFragment, bFirstFragment, bLastFragment;
ULONG i = 0;
PLOG_RECORD pRecord = NULL;
ushort type; // Protocol type
uint ProtOffset; // Offset in Data to non-media info.
UINT MoreHeaderInLookAhead = 0;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceiveIndication]: \n"));
//
// 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 = net_short(IPH->iph_src);
Dst = net_short(IPH->iph_dest);
IPID = net_short(IPH->iph_id);
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 && !bFirstFragment) {
NdisAcquireSpinLock(&IPIDListLockRecv);
for (i = 0; i < PORT_RANGE; i++) {
if (IPID == IPIDListRecv[i]) {
if (bLastFragment) {
//
// If its the last fragment, release the slot.
//
IPIDListRecv[i] = 0xffff;
}
break;
}
}
NdisReleaseSpinLock(&IPIDListLockRecv);
if (i == PORT_RANGE) {
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("Couldnt find an IPID that we care about, get outta here.\n"));
goto RECV_FAILURE;
}
//
// So we found a IPID that matches - set the timestamp and get out after this.
//
TotalLen = TotalIpLen - FragOffset;
pData = ((PUCHAR) IPH) + IpHdrLen;
if (TotalLen >= sizeof (LOG_RECORD)) {
LARGE_INTEGER PerfFrequency;
UINT64 RecdTime, Freq;
pRecord = (LOG_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;
}
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);
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceiveIndication]: *TCP* Address: SRC = %x DST = %x, Port S : %x, Port D: %x\n",
IPH->iph_src,
IPH->iph_dest,
SrcPort,
DstPort));
TcpHeaderOffset = TCP_HDR_SIZE(TCPH);
pData = (PUCHAR) TCPH + TcpHeaderOffset;
TcpDataLen = TotalTcpLen - TcpHeaderOffset;
if ((CheckInPortList(DstPort)) && (TcpDataLen > sizeof (LOG_RECORD))) {
LARGE_INTEGER PerfFrequency;
UINT64 RecdTime, Freq;
pRecord = (LOG_RECORD *) pData;
CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
//
// Convert the perffrequency into 100ns interval.
//
Freq = 0;
Freq |= PerfFrequency.HighPart;
Freq = Freq << 32;
Freq |= PerfFrequency.LowPart;
// convert 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;
//
//pRecord->TimeReceivedWire);
//
} else if (CheckInPortList(DstPort)) {
if (TcpDataLen < sizeof(LOG_RECORD))
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV,
("The Datagram was too small!! IpLen:%d, Tcplen:%d HeaderOff(tcp):%d log_record:%d\n", TotalIpLen, TotalTcpLen, TcpHeaderOffset, sizeof (LOG_RECORD)));
}
//
// If its the first fragment, keep a place holder so we know which
// subsequent IP fragments to timestamp.
//
if ((CheckInPortList(DstPort)) && bFirstFragment) {
NdisAcquireSpinLock(&IPIDListLockRecv);
// need new Entry for IPID
for (i = 0; i < PORT_RANGE; i++) {
//
// Look for a free slot
//
if (0xffff == IPIDListRecv[i]) {
IPIDListRecv[i] = IPID;
break;
}
}
NdisReleaseSpinLock(&IPIDListLockRecv);
if (i == PORT_RANGE) {
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("Couldn't find an empty IPID - Bailing \n"));
}
}
break;
case IPPROTO_UDP:
TotalUdpLen = TotalIpLen - HeaderLength;
UDPH = (UDPHeader *) (((PUCHAR)IPH) + HeaderLength);
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("PAcket %x, IPH = %x, UDPH = %x, HeaderLength = %x\n", LookAheadBuffer, IPH, UDPH, HeaderLength));
UdpDataLen = TotalUdpLen - sizeof(UDPHeader);
pData = ((PUCHAR) UDPH) + sizeof (UDPHeader);
SrcPort = net_short(UDPH->uh_src); // Source port.
DstPort = net_short(UDPH->uh_dest); // Destination port.
if (UdpDataLen < sizeof(UDPHeader)) {
return TRUE;
}
if ((CheckInPortList(DstPort)) && (UdpDataLen > sizeof(LOG_RECORD))) {
LARGE_INTEGER PerfFrequency;
UINT64 RecdTime, Freq;
pRecord = (LOG_RECORD *) pData;
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;
//
// Dont want to get rejected due to bad xsum ...
//
UDPH->uh_xsum = 0;
} else if (CheckInPortList(DstPort)) {
if ((UdpDataLen) < sizeof(LOG_RECORD))
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_RECV, ("The Datagram was too small (UDP)!! IpLen:%d, Size:%d log_record:%d\n",
TotalIpLen, UdpDataLen, sizeof (LOG_RECORD)));
}
if ((CheckInPortList(DstPort)) && bFirstFragment) {
NdisAcquireSpinLock(&IPIDListLockRecv);
// need new Entry for IPID
for (i = 0; i < PORT_RANGE; i++) {
//
// Look for a free slot
//
if (0xffff == IPIDListRecv[i]) {
IPIDListRecv[i] = IPID;
break;
}
}
NdisReleaseSpinLock(&IPIDListLockRecv);
if (i == PORT_RANGE) {
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_RECV, ("Couldn't find an empty IPID - Bailing \n"));
}
}
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceiveIndication]: *UDP* Address: SRC = %x DST = %x, Port S : %x, Port D: %x\n",
IPH->iph_src,
IPH->iph_dest,
UDPH->uh_src,
UDPH->uh_dest));
break;
case IPPROTO_RAW:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceiveIndication]: Protocol RAW\n"));
break;
case IPPROTO_IGMP:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceiveIndication]: Protocol IGMP\n"));
break;
case IPPROTO_ICMP:
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_RECV, ("[TimeStmpReceiveIndication]: Protocol TCMP\n"));
break;
default:
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_RECV, ("[TimeStmpReceiveIndication]: Protocol - UNKNOWN (%d)\n", IPH->iph_protocol));
//DbgBreakPoint();
}
}
}
}
RECV_FAILURE:
return TRUE;
}
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;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_OID, ("[TimeStmpSetInformation]:\n"));
(*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;
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_OID, ("[TimeStmpQueryInformation]:\n"));
(*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
)
{
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_CLASS_MAP, ("[TimeStmpCreateClassMap]: \n"));
return (*PipeContext->NextComponent->CreateClassMap)(
PipeContext->NextComponentContext,
PsClassMapContext,
ClassMap,
ComponentClassMapContext->NextComponentContext);
}
NDIS_STATUS
TimeStmpDeleteClassMap (
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext
)
{
TimeStmpTrace(TS_DBG_TRACE, TS_DBG_CLASS_MAP, ("[TimeStmpDeleteClassMap]: \n"));
return (*PipeContext->NextComponent->DeleteClassMap)(
PipeContext->NextComponentContext,
ComponentClassMapContext->NextComponentContext);
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PSI_INFO Component;
NDIS_HANDLE ConfigHandle;
NDIS_STATUS Status;
NDIS_STRING ComponentKey = NDIS_STRING_CONST("DisplayName");
NDIS_STRING ComponentName = NDIS_STRING_CONST("TimeStmp");
PNDIS_CONFIGURATION_PARAMETER pConfigParam;
NDIS_STRING PsParamKey;
PWSTR p = RegistryPath->Buffer + RegistryPath->Length;
PS_DEBUG_INFO Dbg;
ULONG i = 0;
// The last word of Registry Path points to the driver name.
// NdisOpenProtocol needs that name!
while(p != RegistryPath->Buffer && *p != L'\\')
p-- ;
p++;
RtlInitUnicodeString(&PsParamKey, p);
DbgPrint("PsParamKey:%s\n", PsParamKey);
NdisOpenProtocolConfiguration(&Status, &ConfigHandle, &PsParamKey);
DbgPrint("Status of NdisOpenProtocol:%x\n", Status);
if (!NT_SUCCESS(Status)) {
goto failure;
}
//
// Check if psched is installed by opening it.
// If it fails, we dont load either.
//
Status = CheckForPsched();
if (!NT_SUCCESS(Status)) {
DbgPrint("PSCHED is NOT installed. Timestmp is bailing too\n");
goto failure;
}
IoctlInitialize(DriverObject);
// this list maintains a list of all ports that need to be timestamped.
InitializeListHead(&PortList);
NdisAllocateSpinLock(&PortSpinLock);
DriverObject->DriverUnload = TimeStmpUnload;
//
// We need to keep track of IPIDs for dealing with fragments
// that we need to stamp...
//
for (i = 0; i < PORT_RANGE; i++) {
IPIDList[i] = 0xffff;
}
NdisAllocateSpinLock(&IPIDListLock);
//
// Do the same for the receive side.
//
for (i = 0; i < PORT_RANGE; i++) {
IPIDListRecv[i] = 0xffff;
}
NdisAllocateSpinLock(&IPIDListLockRecv);
if ( NT_SUCCESS( Status ))
{
// Read the name of the component from the registry
#if 0
NdisReadConfiguration( &Status,
&pConfigParam,
ConfigHandle,
&ComponentKey,
NdisParameterString);
if( NT_SUCCESS( Status ))
{
RtlInitUnicodeString(&Component.ComponentName,
pConfigParam->ParameterData.StringData.Buffer);
#else
RtlInitUnicodeString(&Component.ComponentName, ComponentName.Buffer);
#endif
Component.Version = PS_COMPONENT_CURRENT_VERSION;
Component.PacketReservedLength = 0;
Component.PipeContextLength = sizeof(PS_PIPE_CONTEXT);
Component.FlowContextLength = sizeof(PS_FLOW_CONTEXT);
Component.ClassMapContextLength = sizeof(PS_CLASS_MAP_CONTEXT);
Component.SupportedOidsLength = 0;
Component.SupportedOidList = 0;
Component.SupportedGuidsLength = 0;
Component.SupportedGuidList = 0;
Component.InitializePipe = TimeStmpInitializePipe;
Component.ModifyPipe = TimeStmpModifyPipe;
Component.DeletePipe = TimeStmpDeletePipe;
Component.CreateFlow = TimeStmpCreateFlow;
Component.ModifyFlow = TimeStmpModifyFlow;
Component.DeleteFlow = TimeStmpDeleteFlow;
Component.CreateClassMap = TimeStmpCreateClassMap;
Component.DeleteClassMap = TimeStmpDeleteClassMap;
Component.SubmitPacket = TimeStmpSubmitPacket;
Component.ReceivePacket = TimeStmpReceivePacket;
Component.ReceiveIndication = TimeStmpReceiveIndication;
Component.SetInformation = TimeStmpSetInformation;
Component.QueryInformation = TimeStmpQueryInformation;
//
// Call Psched's RegisterPsComponent
//
Status = RegisterPsComponent(&Component, sizeof(Component),
&Dbg);
if(Status != NDIS_STATUS_SUCCESS)
{
DbgPrint("Status of RegisterPsComponent%x\n", Status);
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_INIT,
("DriverEntry: RegisterPsComponent Failed \n"));
}
else
{
DbgPrint("Status of RegisterPsComponent:%x\n", Status);
}
#if 0
}
else
{
DbgPrint("Status of NdisReadProtocol:%x\n", Status);
DbgBreakPoint();
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_INIT,
("DriverEntry: ComponentName not specified \n"));
}
#endif
}
else
{
DbgPrint("Status of NdisOpenProtocol:%x\n", Status);
TimeStmpTrace(TS_DBG_DEATH, TS_DBG_INIT,
("DriverEntry: Can't read driver information in registry"
"\n"));
}
failure:
return Status;
}
//
// The following function checks for the existence of PSCHED on the machine.
// The assumption being that PSCHED gets loaded before TimeStmp on a system.
// If we can open the device, it means that PSCHED is on, otherwise, we bail.
// This fix is for Bug - 321618
//
NTSTATUS
CheckForPsched(
VOID
)
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatusBlock;
OBJECT_ATTRIBUTES objectAttr;
InitializeObjectAttributes(
&objectAttr,
&PschedDriverName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
status = NtCreateFile(
&PschedHandle,
GENERIC_READ,
&objectAttr,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0L);
if (!NT_SUCCESS(status)) {
return status;
} else {
NtClose(PschedHandle);
}
return status;
}
PPORT_ENTRY
CheckInPortList(USHORT Port) {
PLIST_ENTRY ListEntry;
PPORT_ENTRY pPortEntry;
NdisAcquireSpinLock(&PortSpinLock);
ListEntry = PortList.Flink;
while (ListEntry != &PortList) {
pPortEntry = CONTAINING_RECORD(ListEntry, PORT_ENTRY, Linkage);
if (Port == pPortEntry->Port) {
//DbgPrint("Found Port%d\n", Port);
NdisReleaseSpinLock(&PortSpinLock);
return pPortEntry;
} else {
ListEntry = ListEntry->Flink;
//DbgPrint("NOT Found Trying NEXT\n");
}
}
NdisReleaseSpinLock(&PortSpinLock);
//DbgPrint("NOT Found returning from function\n");
return NULL;
}