Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1300 lines
38 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. TimeStmp.c
  5. Abstract:
  6. TimeStamp module
  7. Author:
  8. Shreem, Sanjayka
  9. Environment:
  10. Kernel Mode
  11. Revision History:
  12. --*/
  13. #include "psched.h"
  14. #pragma hdrstop
  15. // The pipe information
  16. typedef struct _TS_PIPE
  17. {
  18. // ContextInfo - Generic context info
  19. PS_PIPE_CONTEXT ContextInfo;
  20. } TS_PIPE, *PTS_PIPE;
  21. // The flow information
  22. typedef struct _TS_FLOW
  23. {
  24. // ContextInfo - Generic context info
  25. PS_FLOW_CONTEXT ContextInfo;
  26. } TS_FLOW, *PTS_FLOW;
  27. /* Global variables */
  28. LIST_ENTRY TsList;
  29. NDIS_SPIN_LOCK TsSpinLock;
  30. ULONG TsCount;
  31. /* Static */
  32. /* Forward */
  33. NDIS_STATUS
  34. TimeStmpInitializePipe (
  35. IN HANDLE PsPipeContext,
  36. IN PPS_PIPE_PARAMETERS PipeParameters,
  37. IN PPS_PIPE_CONTEXT ComponentPipeContext,
  38. IN PPS_PROCS PsProcs,
  39. IN PPS_UPCALLS Upcalls
  40. );
  41. NDIS_STATUS
  42. TimeStmpModifyPipe (
  43. IN PPS_PIPE_CONTEXT PipeContext,
  44. IN PPS_PIPE_PARAMETERS PipeParameters
  45. );
  46. VOID
  47. TimeStmpDeletePipe (
  48. IN PPS_PIPE_CONTEXT PipeContext
  49. );
  50. NDIS_STATUS
  51. TimeStmpCreateFlow (
  52. IN PPS_PIPE_CONTEXT PipeContext,
  53. IN HANDLE PsFlowContext,
  54. IN PCO_CALL_PARAMETERS CallParameters,
  55. IN PPS_FLOW_CONTEXT ComponentFlowContext
  56. );
  57. NDIS_STATUS
  58. TimeStmpModifyFlow (
  59. IN PPS_PIPE_CONTEXT PipeContext,
  60. IN PPS_FLOW_CONTEXT FlowContext,
  61. IN PCO_CALL_PARAMETERS CallParameters
  62. );
  63. VOID
  64. TimeStmpDeleteFlow (
  65. IN PPS_PIPE_CONTEXT PipeContext,
  66. IN PPS_FLOW_CONTEXT FlowContext
  67. );
  68. VOID
  69. TimeStmpEmptyFlow (
  70. IN PPS_PIPE_CONTEXT PipeContext,
  71. IN PPS_FLOW_CONTEXT FlowContext
  72. );
  73. VOID
  74. TimeStmpSetInformation (
  75. IN PPS_PIPE_CONTEXT PipeContext,
  76. IN PPS_FLOW_CONTEXT FlowContext,
  77. IN NDIS_OID Oid,
  78. IN ULONG Len,
  79. IN void *Data);
  80. VOID
  81. TimeStmpQueryInformation (
  82. IN PPS_PIPE_CONTEXT PipeContext,
  83. IN PPS_FLOW_CONTEXT FlowContext,
  84. IN NDIS_OID Oid,
  85. IN ULONG Len,
  86. IN PVOID Data,
  87. IN OUT PULONG BytesWritten,
  88. IN OUT PULONG BytesNeeded,
  89. IN OUT PNDIS_STATUS Status);
  90. NDIS_STATUS
  91. TimeStmpCreateClassMap (
  92. IN PPS_PIPE_CONTEXT PipeContext,
  93. IN HANDLE PsClassMapContext,
  94. IN PTC_CLASS_MAP_FLOW ClassMap,
  95. IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext
  96. );
  97. NDIS_STATUS
  98. TimeStmpDeleteClassMap (
  99. IN PPS_PIPE_CONTEXT PipeContext,
  100. IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext
  101. );
  102. BOOLEAN
  103. TimeStmpSubmitPacket (
  104. IN PPS_PIPE_CONTEXT PipeContext,
  105. IN PPS_FLOW_CONTEXT FlowContext,
  106. IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
  107. IN PPACKET_INFO_BLOCK Packet
  108. );
  109. BOOLEAN
  110. TimeStmpReceivePacket (
  111. IN PPS_PIPE_CONTEXT PipeContext,
  112. IN PPS_FLOW_CONTEXT FlowContext,
  113. IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
  114. IN PNDIS_PACKET Packet,
  115. IN NDIS_MEDIUM Medium
  116. );
  117. BOOLEAN
  118. TimeStmpReceiveIndication(
  119. IN PPS_PIPE_CONTEXT PipeContext,
  120. IN PPS_FLOW_CONTEXT FlowContext,
  121. IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
  122. IN PVOID HeaderBuffer,
  123. IN UINT HeaderBufferSize,
  124. IN PVOID LookAheadBuffer,
  125. IN UINT LookAheadBufferSize,
  126. IN UINT PacketSize,
  127. IN UINT TransportHeaderOffset
  128. );
  129. /* End Forward */
  130. VOID
  131. InitializeTimeStmp( PPSI_INFO Info )
  132. {
  133. Info->PipeContextLength = ((sizeof(TS_PIPE)+7) & ~7);
  134. Info->FlowContextLength = ((sizeof(TS_FLOW)+7) & ~7);
  135. Info->ClassMapContextLength = sizeof(PS_CLASS_MAP_CONTEXT);
  136. Info->InitializePipe = TimeStmpInitializePipe;
  137. Info->ModifyPipe = TimeStmpModifyPipe;
  138. Info->DeletePipe = TimeStmpDeletePipe;
  139. Info->CreateFlow = TimeStmpCreateFlow;
  140. Info->ModifyFlow = TimeStmpModifyFlow;
  141. Info->DeleteFlow = TimeStmpDeleteFlow;
  142. Info->EmptyFlow = TimeStmpEmptyFlow;
  143. Info->CreateClassMap = TimeStmpCreateClassMap;
  144. Info->DeleteClassMap = TimeStmpDeleteClassMap;
  145. Info->SubmitPacket = TimeStmpSubmitPacket;
  146. Info->ReceivePacket = NULL;
  147. Info->ReceiveIndication = NULL;
  148. Info->SetInformation = TimeStmpSetInformation;
  149. Info->QueryInformation = TimeStmpQueryInformation;
  150. NdisAllocateSpinLock(&TsSpinLock);
  151. InitializeListHead( &TsList );
  152. TsCount = 0;
  153. }
  154. NDIS_STATUS
  155. TimeStmpInitializePipe (
  156. IN HANDLE PsPipeContext,
  157. IN PPS_PIPE_PARAMETERS PipeParameters,
  158. IN PPS_PIPE_CONTEXT ComponentPipeContext,
  159. IN PPS_PROCS PsProcs,
  160. IN PPS_UPCALLS Upcalls
  161. )
  162. {
  163. PPS_PIPE_CONTEXT Pipe = ComponentPipeContext;
  164. return (*Pipe->NextComponent->InitializePipe)(
  165. PsPipeContext,
  166. PipeParameters,
  167. Pipe->NextComponentContext,
  168. PsProcs,
  169. Upcalls);
  170. }
  171. NDIS_STATUS
  172. TimeStmpModifyPipe (
  173. IN PPS_PIPE_CONTEXT PipeContext,
  174. IN PPS_PIPE_PARAMETERS PipeParameters
  175. )
  176. {
  177. PPS_PIPE_CONTEXT Pipe = PipeContext;
  178. return (*Pipe->NextComponent->ModifyPipe)(
  179. Pipe->NextComponentContext, PipeParameters);
  180. }
  181. VOID
  182. TimeStmpDeletePipe (
  183. IN PPS_PIPE_CONTEXT PipeContext
  184. )
  185. {
  186. PPS_PIPE_CONTEXT Pipe = PipeContext;
  187. (*Pipe->NextComponent->DeletePipe)(Pipe->NextComponentContext);
  188. }
  189. NDIS_STATUS
  190. TimeStmpCreateFlow (
  191. IN PPS_PIPE_CONTEXT PipeContext,
  192. IN HANDLE PsFlowContext,
  193. IN PCO_CALL_PARAMETERS CallParameters,
  194. IN PPS_FLOW_CONTEXT ComponentFlowContext
  195. )
  196. {
  197. PPS_PIPE_CONTEXT Pipe = PipeContext;
  198. return (*Pipe->NextComponent->CreateFlow)(
  199. Pipe->NextComponentContext,
  200. PsFlowContext,
  201. CallParameters,
  202. ComponentFlowContext->NextComponentContext);
  203. }
  204. NDIS_STATUS
  205. TimeStmpModifyFlow (
  206. IN PPS_PIPE_CONTEXT PipeContext,
  207. IN PPS_FLOW_CONTEXT FlowContext,
  208. IN PCO_CALL_PARAMETERS CallParameters
  209. )
  210. {
  211. PPS_PIPE_CONTEXT Pipe = PipeContext;
  212. return (*Pipe->NextComponent->ModifyFlow)(
  213. Pipe->NextComponentContext,
  214. FlowContext->NextComponentContext,
  215. CallParameters);
  216. }
  217. VOID
  218. TimeStmpDeleteFlow (
  219. IN PPS_PIPE_CONTEXT PipeContext,
  220. IN PPS_FLOW_CONTEXT FlowContext
  221. )
  222. {
  223. PPS_PIPE_CONTEXT Pipe = PipeContext;
  224. (*Pipe->NextComponent->DeleteFlow)(
  225. Pipe->NextComponentContext,
  226. FlowContext->NextComponentContext);
  227. }
  228. VOID
  229. TimeStmpEmptyFlow (
  230. IN PPS_PIPE_CONTEXT PipeContext,
  231. IN PPS_FLOW_CONTEXT FlowContext
  232. )
  233. {
  234. PPS_PIPE_CONTEXT Pipe = PipeContext;
  235. (*Pipe->NextComponent->EmptyFlow)(
  236. Pipe->NextComponentContext,
  237. FlowContext->NextComponentContext);
  238. }
  239. VOID
  240. TimeStmpSetInformation (
  241. IN PPS_PIPE_CONTEXT PipeContext,
  242. IN PPS_FLOW_CONTEXT FlowContext,
  243. IN NDIS_OID Oid,
  244. IN ULONG Len,
  245. IN void *Data)
  246. {
  247. PPS_PIPE_CONTEXT Pipe = PipeContext;
  248. PPS_FLOW_CONTEXT Flow = FlowContext;
  249. (*Pipe->NextComponent->SetInformation)(
  250. Pipe->NextComponentContext,
  251. (Flow)?Flow->NextComponentContext:0,
  252. Oid,
  253. Len,
  254. Data);
  255. }
  256. VOID
  257. TimeStmpQueryInformation (
  258. IN PPS_PIPE_CONTEXT PipeContext,
  259. IN PPS_FLOW_CONTEXT FlowContext,
  260. IN NDIS_OID Oid,
  261. IN ULONG Len,
  262. IN PVOID Data,
  263. IN OUT PULONG BytesWritten,
  264. IN OUT PULONG BytesNeeded,
  265. IN OUT PNDIS_STATUS Status)
  266. {
  267. PPS_PIPE_CONTEXT Pipe = PipeContext;
  268. PPS_FLOW_CONTEXT Flow = FlowContext;
  269. (*Pipe->NextComponent->QueryInformation)(
  270. Pipe->NextComponentContext,
  271. (Flow)?Flow->NextComponentContext:0,
  272. Oid,
  273. Len,
  274. Data,
  275. BytesWritten,
  276. BytesNeeded,
  277. Status);
  278. }
  279. NDIS_STATUS
  280. TimeStmpCreateClassMap (
  281. IN PPS_PIPE_CONTEXT PipeContext,
  282. IN HANDLE PsClassMapContext,
  283. IN PTC_CLASS_MAP_FLOW ClassMap,
  284. IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext
  285. )
  286. {
  287. return (*PipeContext->NextComponent->CreateClassMap)(
  288. PipeContext->NextComponentContext,
  289. PsClassMapContext,
  290. ClassMap,
  291. ComponentClassMapContext->NextComponentContext);
  292. }
  293. NDIS_STATUS
  294. TimeStmpDeleteClassMap (
  295. IN PPS_PIPE_CONTEXT PipeContext,
  296. IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext
  297. )
  298. {
  299. return (*PipeContext->NextComponent->DeleteClassMap)(
  300. PipeContext->NextComponentContext,
  301. ComponentClassMapContext->NextComponentContext);
  302. }
  303. /* Routine Description:
  304. Checks to see if there is any application requesting time-stamping for these end-points
  305. Return Value:
  306. MARK_NONE, MARK_IN_PKT, MARK_IN_BUF
  307. */
  308. int
  309. CheckForMatch( ULONG SrcIp,
  310. ULONG DstIp,
  311. USHORT SrcPort,
  312. USHORT DstPort,
  313. USHORT Proto,
  314. USHORT IpId,
  315. USHORT Size,
  316. USHORT Direction)
  317. {
  318. PLIST_ENTRY ListEntry;
  319. PTS_ENTRY pEntry;
  320. int Status = MARK_NONE;
  321. NdisAcquireSpinLock(&TsSpinLock);
  322. ListEntry = TsList.Flink;
  323. while (ListEntry != &TsList)
  324. {
  325. pEntry = CONTAINING_RECORD(ListEntry, TS_ENTRY, Linkage);
  326. if( ((pEntry->SrcIp == UL_ANY) || (pEntry->SrcIp == SrcIp)) &&
  327. ((pEntry->SrcPort== US_ANY) || (pEntry->SrcPort == SrcPort)) &&
  328. ((pEntry->DstIp == UL_ANY) || (pEntry->DstIp == DstIp)) &&
  329. ((pEntry->DstPort == US_ANY) || (pEntry->DstPort == DstPort)) &&
  330. ((pEntry->Direction == US_ANY) || (pEntry->Direction == Direction)) &&
  331. ((pEntry->Proto == US_ANY) || (pEntry->Proto == Proto)))
  332. {
  333. if(pEntry->Type == MARK_IN_BUF)
  334. {
  335. LARGE_INTEGER PerfFrequency, CurrentTime;
  336. UINT64 RecdTime, Freq;
  337. MARK_IN_BUF_RECORD Record, *pRecord;
  338. Status = MARK_IN_BUF;
  339. if((int)( (char*)pEntry->pPacketStore - (char*)pEntry->pPacketStoreHead
  340. + sizeof(MARK_IN_BUF_RECORD) ) < PACKET_STORE_SIZE )
  341. {
  342. pEntry->pPacketStore->IpId = IpId;
  343. pEntry->pPacketStore->Size = Size;
  344. CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
  345. // Convert the perffrequency into 100ns interval. //
  346. Freq = 0;
  347. Freq |= PerfFrequency.HighPart;
  348. Freq = Freq << 32;
  349. Freq |= PerfFrequency.LowPart;
  350. pEntry->pPacketStore->TimeValue = 0;
  351. pEntry->pPacketStore->TimeValue |= CurrentTime.HighPart;
  352. pEntry->pPacketStore->TimeValue = pEntry->pPacketStore->TimeValue << 32;
  353. pEntry->pPacketStore->TimeValue |= CurrentTime.LowPart;
  354. // Normalize cycles with the frequency //
  355. pEntry->pPacketStore->TimeValue *= 10000000;
  356. pEntry->pPacketStore->TimeValue /= Freq;
  357. pEntry->pPacketStore = (PMARK_IN_BUF_RECORD)((char*)pEntry->pPacketStore + sizeof(MARK_IN_BUF_RECORD));
  358. }
  359. else
  360. {
  361. pEntry->pPacketStore = pEntry->pPacketStoreHead;
  362. }
  363. NdisReleaseSpinLock(&TsSpinLock);
  364. return Status;
  365. }
  366. else if(pEntry->Type == MARK_IN_PKT)
  367. {
  368. Status = MARK_IN_PKT;
  369. NdisReleaseSpinLock(&TsSpinLock);
  370. return Status;
  371. }
  372. }
  373. else
  374. {
  375. ListEntry = ListEntry->Flink;
  376. }
  377. }
  378. NdisReleaseSpinLock(&TsSpinLock);
  379. return Status;
  380. }
  381. /* Routine Description:
  382. Adds an end-point to the list of monitoring end-points
  383. Return Value:
  384. TRUE, FALSE
  385. */
  386. BOOL
  387. AddRequest( PFILE_OBJECT FileObject,
  388. ULONG SrcIp,
  389. USHORT SrcPort,
  390. ULONG DstIp,
  391. USHORT DstPort,
  392. USHORT Proto,
  393. USHORT Type,
  394. USHORT Direction)
  395. {
  396. PTS_ENTRY pEntry = NULL;
  397. PsAllocatePool(pEntry, sizeof(TS_ENTRY), TsTag);
  398. if( !pEntry )
  399. return FALSE;
  400. InitializeListHead(&pEntry->Linkage);
  401. pEntry->SrcIp = SrcIp;
  402. pEntry->SrcPort = SrcPort;
  403. pEntry->DstIp = DstIp;
  404. pEntry->DstPort = DstPort;
  405. pEntry->Proto = Proto;
  406. pEntry->Type = Type;
  407. pEntry->Direction = Direction;
  408. pEntry->FileObject = FileObject;
  409. pEntry->pPacketStore = NULL;
  410. pEntry->pPacketStoreHead = NULL;
  411. if(Type == MARK_IN_BUF)
  412. {
  413. PsAllocatePool( pEntry->pPacketStoreHead, PACKET_STORE_SIZE, TsTag );
  414. if( !pEntry->pPacketStoreHead)
  415. {
  416. PsFreePool( pEntry );
  417. return FALSE;
  418. }
  419. pEntry->pPacketStore = pEntry->pPacketStoreHead;
  420. }
  421. NdisAcquireSpinLock(&TsSpinLock);
  422. /* Need to check for duplication ..*/
  423. InsertHeadList(&TsList, &pEntry->Linkage);
  424. InterlockedIncrement( &TsCount );
  425. NdisReleaseSpinLock(&TsSpinLock);
  426. return TRUE;
  427. }
  428. /* Routine Description:
  429. Removes an end-point to the list of monitoring end-points
  430. Return Value:
  431. None
  432. Note:
  433. Here, 0xffffffff means, wild card => Don't have to match on that field */
  434. void
  435. RemoveRequest( PFILE_OBJECT FileObject,
  436. ULONG SrcIp,
  437. USHORT SrcPort,
  438. ULONG DstIp,
  439. USHORT DstPort,
  440. USHORT Proto)
  441. {
  442. PLIST_ENTRY ListEntry;
  443. PTS_ENTRY pEntry;
  444. NdisAcquireSpinLock(&TsSpinLock);
  445. ListEntry = TsList.Flink;
  446. while (ListEntry != &TsList)
  447. {
  448. pEntry = CONTAINING_RECORD(ListEntry, TS_ENTRY, Linkage);
  449. if( ((FileObject == ULongToPtr(UL_ANY)) || (pEntry->FileObject == FileObject)) &&
  450. ((SrcIp == UL_ANY) || (pEntry->SrcIp == SrcIp)) &&
  451. ((SrcPort == US_ANY) || (pEntry->SrcPort == SrcPort)) &&
  452. ((DstIp == UL_ANY) || (pEntry->DstIp == DstIp)) &&
  453. ((DstPort == US_ANY) || (pEntry->DstPort == SrcPort)) &&
  454. ((Proto== US_ANY) || (pEntry->Proto == Proto)))
  455. {
  456. RemoveEntryList(&pEntry->Linkage);
  457. if( pEntry->pPacketStoreHead)
  458. PsFreePool( pEntry->pPacketStoreHead );
  459. PsFreePool( pEntry );
  460. InterlockedDecrement( &TsCount );
  461. /* Need to go back to the beginning of the list againg.. */
  462. ListEntry = TsList.Flink;
  463. }
  464. else
  465. {
  466. ListEntry = ListEntry->Flink;
  467. }
  468. }
  469. NdisReleaseSpinLock(&TsSpinLock);
  470. }
  471. int
  472. CopyTimeStmps( PFILE_OBJECT FileObject, PVOID buf, ULONG Len)
  473. {
  474. PLIST_ENTRY ListEntry;
  475. PTS_ENTRY pEntry;
  476. ULONG DataLen;
  477. LARGE_INTEGER LargeLen;
  478. if( Len < PACKET_STORE_SIZE )
  479. return 0;
  480. NdisAcquireSpinLock(&TsSpinLock);
  481. ListEntry = TsList.Flink;
  482. while (ListEntry != &TsList)
  483. {
  484. pEntry = CONTAINING_RECORD(ListEntry, TS_ENTRY, Linkage);
  485. if( pEntry->FileObject == FileObject)
  486. {
  487. // Copy the data across and rest the pointers.. //
  488. LargeLen.QuadPart = ((char*)pEntry->pPacketStore) - ((char*)pEntry->pPacketStoreHead);
  489. DataLen = LargeLen.LowPart;
  490. NdisMoveMemory( buf, pEntry->pPacketStoreHead, DataLen);
  491. pEntry->pPacketStore = pEntry->pPacketStoreHead;
  492. NdisReleaseSpinLock(&TsSpinLock);
  493. return DataLen;
  494. }
  495. else
  496. {
  497. ListEntry = ListEntry->Flink;
  498. }
  499. }
  500. NdisReleaseSpinLock(&TsSpinLock);
  501. return 0;
  502. }
  503. VOID
  504. UnloadTimeStmp( )
  505. {
  506. // Clear all the Requests //
  507. RemoveRequest( ULongToPtr(UL_ANY),
  508. UL_ANY,
  509. US_ANY,
  510. UL_ANY,
  511. US_ANY,
  512. US_ANY);
  513. // Free the spin lock //
  514. NdisFreeSpinLock(&TsSpinLock);
  515. }
  516. BOOLEAN
  517. TimeStmpSubmitPacket (
  518. IN PPS_PIPE_CONTEXT PipeContext,
  519. IN PPS_FLOW_CONTEXT FlowContext,
  520. IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
  521. IN PPACKET_INFO_BLOCK PacketInfo
  522. )
  523. {
  524. PTS_PIPE Pipe = (PTS_PIPE)PipeContext;
  525. PTS_FLOW Flow = (PTS_FLOW)FlowContext;
  526. PNDIS_PACKET Packet = PacketInfo->NdisPacket;
  527. PNDIS_BUFFER ArpBuf , IpBuf , TcpBuf, UdpBuf, DataBuf;
  528. ULONG ArpLen , IpLen , IpHdrLen , TcpLen , UdpLen, DataLen , TotalLen , TcpHeaderOffset;
  529. VOID *ArpH;
  530. IPHeader UNALIGNED *IPH;
  531. TCPHeader UNALIGNED *TCPH;
  532. UDPHeader UNALIGNED *UDPH;
  533. IPAddr Src, Dst;
  534. BOOLEAN bFragment;
  535. USHORT SrcPort , DstPort , IPID, FragOffset ,Size;
  536. PVOID GeneralVA , Data;
  537. ULONG i, Ret;
  538. if( (TsCount == 0) ||
  539. (NDIS_GET_PACKET_PROTOCOL_TYPE(Packet) != NDIS_PROTOCOL_ID_TCP_IP))
  540. {
  541. goto SUBMIT_NEXT;
  542. }
  543. IpBuf = NULL;
  544. // Steps
  545. // Parse the IP Packet.
  546. // Look for the appropriate ports.
  547. // Look for the data portion and put in the Time & length there.
  548. if(1)
  549. {
  550. PVOID pAddr;
  551. PNDIS_BUFFER pNdisBuf1, pNdisBuf2;
  552. UINT Len;
  553. ULONG TransportHeaderOffset = 0;
  554. TransportHeaderOffset = PacketInfo->IPHeaderOffset;
  555. NdisGetFirstBufferFromPacket( Packet,
  556. &ArpBuf,
  557. &ArpH,
  558. &ArpLen,
  559. &TotalLen
  560. );
  561. pNdisBuf1 = Packet->Private.Head;
  562. NdisQueryBuffer(pNdisBuf1, &pAddr, &Len);
  563. while(Len <= TransportHeaderOffset)
  564. {
  565. TransportHeaderOffset -= Len;
  566. NdisGetNextBuffer(pNdisBuf1, &pNdisBuf2);
  567. NdisQueryBuffer(pNdisBuf2, &pAddr, &Len);
  568. pNdisBuf1 = pNdisBuf2;
  569. }
  570. /* Buffer Descriptor corresponding to Ip Packet */
  571. IpBuf = pNdisBuf1;
  572. /* Length of this Buffer (IP buffer) */
  573. IpLen = Len - TransportHeaderOffset;
  574. /* Starting Virtual Address for this buffer */
  575. GeneralVA = pAddr;
  576. /* Virtual Address of the IP Header */
  577. IPH = (IPHeader *)(((PUCHAR)pAddr) + TransportHeaderOffset);
  578. }
  579. if(!IpBuf)
  580. goto SUBMIT_NEXT;
  581. /* Let's try to parse the packet */
  582. Src = IPH->iph_src;
  583. Dst = IPH->iph_dest;
  584. IPID = net_short(IPH->iph_id);
  585. Size = net_short(IPH->iph_length);
  586. IpHdrLen = ((IPH->iph_verlen & (uchar)~IP_VER_FLAG) << 2);
  587. FragOffset = IPH->iph_offset & IP_OFFSET_MASK;
  588. FragOffset = net_short(FragOffset) * 8;
  589. bFragment = (IPH->iph_offset & IP_MF_FLAG) || (FragOffset > 0);
  590. // Don't want to deal with Fragmented packets right now..//
  591. if ( bFragment )
  592. goto SUBMIT_NEXT;
  593. switch (IPH->iph_protocol)
  594. {
  595. case IPPROTO_TCP :
  596. if (IPH && ((USHORT)IpLen > IpHdrLen))
  597. {
  598. // We have more than the IP Header in this MDL //
  599. TCPH = (TCPHeader *) ((PUCHAR)IPH + IpHdrLen);
  600. TcpLen = IpLen - IpHdrLen;
  601. TcpBuf = IpBuf;
  602. }
  603. else
  604. {
  605. // TCP Header is in the next MDL //
  606. NdisGetNextBuffer(IpBuf, &TcpBuf);
  607. if(!TcpBuf)
  608. goto SUBMIT_NEXT;
  609. GeneralVA = NULL;
  610. NdisQueryBuffer(TcpBuf,
  611. &GeneralVA,
  612. &TcpLen
  613. );
  614. TCPH = (TCPHeader *) GeneralVA;
  615. }
  616. /* At this point, TcpBuf, TCPH and TcpLen contain the proper values */
  617. // Get the port numbers out.
  618. SrcPort = net_short(TCPH->tcp_src);
  619. DstPort = net_short(TCPH->tcp_dest);
  620. // We have the TCP Buffer now. Get to the DATA //
  621. TcpHeaderOffset = TCP_HDR_SIZE(TCPH);
  622. if (TcpLen > TcpHeaderOffset)
  623. {
  624. // We have the DATA right here! //
  625. Data = (PUCHAR)TCPH + TcpHeaderOffset;
  626. DataLen = TcpLen - TcpHeaderOffset;
  627. }
  628. else
  629. {
  630. NdisGetNextBuffer(TcpBuf, &DataBuf);
  631. if(!DataBuf)
  632. goto SUBMIT_NEXT;
  633. GeneralVA = NULL;
  634. NdisQueryBuffer(DataBuf,
  635. &Data,
  636. &DataLen
  637. );
  638. }
  639. /* At this point, DataBuf, Data and DataLen contain the proper values */
  640. goto TimeStamp;
  641. break;
  642. case IPPROTO_UDP:
  643. if (IpLen > IpHdrLen)
  644. {
  645. // We have more than the IP Header in this MDL //
  646. UDPH = (UDPHeader *) ((PUCHAR)IPH + IpHdrLen);
  647. UdpLen = IpLen - IpHdrLen;
  648. UdpBuf = IpBuf;
  649. }
  650. else
  651. {
  652. // UDP Header is in the next MDL //
  653. NdisGetNextBuffer(IpBuf, &UdpBuf);
  654. if(!UdpBuf)
  655. goto SUBMIT_NEXT;
  656. GeneralVA = NULL;
  657. NdisQueryBuffer(UdpBuf,
  658. &GeneralVA,
  659. &UdpLen
  660. );
  661. UDPH = (UDPHeader *) GeneralVA;
  662. }
  663. /* At this point, UdpBuf, UDPH and UdpLen contain the proper values */
  664. SrcPort = net_short(UDPH->uh_src);
  665. DstPort = net_short(UDPH->uh_dest);
  666. // Get to the data. //
  667. if (UdpLen > sizeof (UDPHeader))
  668. {
  669. // We have the DATA right here! //
  670. Data = (PUCHAR) UDPH + sizeof (UDPHeader);
  671. DataLen = UdpLen - sizeof (UDPHeader);
  672. }
  673. else
  674. {
  675. NdisGetNextBuffer(UdpBuf, &DataBuf);
  676. if(!DataBuf)
  677. goto SUBMIT_NEXT;
  678. GeneralVA = NULL;
  679. NdisQueryBuffer(DataBuf,
  680. &Data,
  681. &DataLen
  682. );
  683. }
  684. /* At this point, DataBuf, Data and DataLen contain the proper values */
  685. goto TimeStamp;
  686. break;
  687. default:
  688. goto SUBMIT_NEXT;
  689. }
  690. TimeStamp:
  691. Ret = CheckForMatch( Src, Dst, SrcPort, DstPort, IPH->iph_protocol, IPID, Size, DIR_SEND);
  692. if( Ret == MARK_IN_PKT)
  693. {
  694. if (DataLen >= sizeof(MARK_IN_PKT_RECORD))
  695. {
  696. LARGE_INTEGER PerfFrequency, CurrentTime;
  697. UINT64 RecdTime, Freq;
  698. PMARK_IN_PKT_RECORD pRecord;
  699. pRecord = (PMARK_IN_PKT_RECORD) Data;
  700. CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
  701. pRecord->BufferSize = DataLen;
  702. // Convert the perffrequency into 100ns interval //
  703. Freq = 0;
  704. Freq |= PerfFrequency.HighPart;
  705. Freq = Freq << 32;
  706. Freq |= PerfFrequency.LowPart;
  707. // convert to uint64 //
  708. pRecord->TimeSentWire = 0;
  709. pRecord->TimeSentWire |= CurrentTime.HighPart;
  710. pRecord->TimeSentWire = pRecord->TimeSentWire << 32;
  711. pRecord->TimeSentWire |= CurrentTime.LowPart;
  712. // Normalize cycles with the frequency.
  713. pRecord->TimeSentWire *= 10000000;
  714. pRecord->TimeSentWire /= Freq;
  715. if(IPH->iph_protocol == IPPROTO_UDP)
  716. UDPH->uh_xsum = 0;
  717. }
  718. }
  719. else if( Ret == MARK_IN_BUF)
  720. {
  721. // Nothing more to be done..
  722. }
  723. SUBMIT_NEXT:
  724. return (*Pipe->ContextInfo.NextComponent->SubmitPacket)(
  725. Pipe->ContextInfo.NextComponentContext,
  726. Flow->ContextInfo.NextComponentContext,
  727. (ClassMapContext != NULL) ? ClassMapContext->NextComponentContext : NULL,
  728. PacketInfo);
  729. }
  730. BOOLEAN
  731. TimeStmpReceivePacket (
  732. IN PPS_PIPE_CONTEXT PipeContext,
  733. IN PPS_FLOW_CONTEXT FlowContext,
  734. IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
  735. IN PNDIS_PACKET Packet,
  736. IN NDIS_MEDIUM Medium
  737. )
  738. {
  739. PPS_PIPE_CONTEXT Pipe;
  740. LARGE_INTEGER CurrentTime;
  741. IPHeader UNALIGNED *IPH;
  742. TCPHeader UNALIGNED *TCPH;
  743. UDPHeader UNALIGNED *UDPH;
  744. IPAddr Src, Dst;
  745. PUCHAR headerBuffer, pData;
  746. PNDIS_BUFFER pFirstBuffer;
  747. ULONG firstbufferLength, bufferLength, HeaderLength;
  748. ULONG TotalIpLen, IPDataLength, IpHdrLen;
  749. ULONG TotalTcpLen, TcpDataLen, TotalLen, TcpHeaderOffset, i;
  750. int TotalUdpLen, UdpDataLen, UdpHdrLen, DataLen, Ret;
  751. USHORT SrcPort, DstPort, IPID, FragOffset, Size;
  752. BOOLEAN bFragment, bFirstFragment, bLastFragment;
  753. /* This will give the size of the "media-specific" header. So, this will be the offset to IP packet */
  754. UINT HeaderBufferSize ;
  755. ushort type; // Protocol type
  756. uint ProtOffset; // Offset in Data to non-media info.
  757. if( ( TsCount == 0) ||
  758. (NDIS_GET_PACKET_PROTOCOL_TYPE(Packet) == NDIS_PROTOCOL_ID_TCP_IP))
  759. {
  760. return TRUE;
  761. }
  762. Pipe = PipeContext;
  763. HeaderBufferSize = NDIS_GET_PACKET_HEADER_SIZE(Packet);
  764. NdisGetFirstBufferFromPacket(Packet, // packet
  765. &pFirstBuffer, // first buffer descriptor
  766. &headerBuffer, // VA of the first buffer
  767. &firstbufferLength, // length of the header+lookahead
  768. &bufferLength); // length of the bytes in the buffers
  769. IPH = (IPHeader *) ((PUCHAR)headerBuffer + HeaderBufferSize);
  770. // Check the header length and the version //
  771. HeaderLength = ((IPH->iph_verlen & (uchar)~IP_VER_FLAG) << 2);
  772. // If the HeaderLength seems to be incorrect, let's not try to parse //
  773. if( (HeaderLength < sizeof(IPHeader)) ||
  774. (HeaderLength > bufferLength) )
  775. return TRUE;
  776. // Get past the IP Header and get the rest of the stuff out //
  777. TotalIpLen = (uint)net_short(IPH->iph_length);
  778. // Make sure the version and IpData Len are correct //
  779. if( ((IPH->iph_verlen & IP_VER_FLAG) != IP_VERSION ) ||
  780. ( TotalIpLen < HeaderLength ) ||
  781. ( TotalIpLen > bufferLength ))
  782. return TRUE;
  783. // Let's try to parse the packet //
  784. Src = IPH->iph_src;
  785. Dst = IPH->iph_dest;
  786. IPID = net_short(IPH->iph_id);
  787. Size = net_short(IPH->iph_length);
  788. FragOffset = IPH->iph_offset & IP_OFFSET_MASK;
  789. FragOffset = net_short(FragOffset) * 8;
  790. bFragment = (IPH->iph_offset & IP_MF_FLAG) || (FragOffset > 0);
  791. bFirstFragment = bFragment && (FragOffset == 0);
  792. bLastFragment = bFragment && (!(IPH->iph_offset & IP_MF_FLAG));
  793. // If this is a fragment and NOT the first one, just put the Timestamp in here.
  794. // Otherwise, let it get to the protocols for processing.
  795. if (bFragment )
  796. return TRUE;
  797. // Do the protocol specific stuff //
  798. switch (IPH->iph_protocol)
  799. {
  800. case IPPROTO_TCP:
  801. TotalTcpLen = TotalIpLen - HeaderLength;
  802. TCPH = (TCPHeader *) (((PUCHAR)IPH) + HeaderLength);
  803. // For TCP, the data offset is part of the TCP Header */
  804. TcpHeaderOffset = TCP_HDR_SIZE(TCPH);
  805. DataLen = TotalTcpLen - TcpHeaderOffset;
  806. pData = (PUCHAR) TCPH + TcpHeaderOffset;
  807. SrcPort = net_short(TCPH->tcp_src);
  808. DstPort = net_short(TCPH->tcp_dest);
  809. goto TimeStmp;
  810. break;
  811. case IPPROTO_UDP:
  812. TotalUdpLen = TotalIpLen - HeaderLength;
  813. UDPH = (UDPHeader *) (((PUCHAR)IPH) + HeaderLength);
  814. // For UDP, the header size is fixed //
  815. DataLen = TotalUdpLen - sizeof(UDPHeader);
  816. pData = ((PUCHAR) UDPH) + sizeof (UDPHeader);
  817. SrcPort = net_short(UDPH->uh_src);
  818. DstPort = net_short(UDPH->uh_dest);
  819. goto TimeStmp;
  820. break;
  821. default:
  822. break;
  823. }
  824. return TRUE;
  825. TimeStmp:
  826. Ret = CheckForMatch( Src, Dst, SrcPort, DstPort, IPH->iph_protocol, IPID, Size, DIR_RECV);
  827. if( Ret == MARK_IN_PKT)
  828. {
  829. if (DataLen >= sizeof(MARK_IN_PKT_RECORD))
  830. {
  831. LARGE_INTEGER PerfFrequency, CurrentTime;
  832. UINT64 RecdTime, Freq;
  833. PMARK_IN_PKT_RECORD pRecord;
  834. pRecord = (PMARK_IN_PKT_RECORD) pData;
  835. CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
  836. // Convert the perffrequency into 100ns interval //
  837. Freq = 0;
  838. Freq |= PerfFrequency.HighPart;
  839. Freq = Freq << 32;
  840. Freq |= PerfFrequency.LowPart;
  841. //convert from large_integer to uint64
  842. pRecord->TimeReceivedWire = 0;
  843. pRecord->TimeReceivedWire |= CurrentTime.HighPart;
  844. pRecord->TimeReceivedWire = pRecord->TimeReceivedWire << 32;
  845. pRecord->TimeReceivedWire |= CurrentTime.LowPart;
  846. // Normalize cycles with the frequency.
  847. pRecord->TimeReceivedWire *= 10000000;
  848. pRecord->TimeReceivedWire /= Freq;
  849. if(IPH->iph_protocol == IPPROTO_UDP)
  850. UDPH->uh_xsum = 0;
  851. }
  852. }
  853. else if( Ret == MARK_IN_BUF)
  854. {
  855. }
  856. return TRUE;
  857. }
  858. #ifdef NEVER
  859. //
  860. // This function receives a buffer from NDIS which is indicated to the transport.
  861. // We use this function and work past the headers (tcp, ip) and get to the data.
  862. // Then, we timestamp and reset the checksum flags.
  863. // We make the assumption that the lookahead is atleast 128.
  864. // mac header ~ 8+8, ip header ~20, tcp/udp ~ 20+options, LOG_RECORD ~ 44
  865. // they all add up to less than 128. If this is not a good assumption, We will need
  866. // to get into MiniportTransferData and such.
  867. //
  868. BOOLEAN
  869. TimeStmpReceiveIndication(
  870. IN PPS_PIPE_CONTEXT PipeContext,
  871. IN PPS_FLOW_CONTEXT FlowContext,
  872. IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
  873. IN PVOID HeaderBuffer,
  874. IN UINT HeaderBufferSize,
  875. IN PVOID LookAheadBuffer,
  876. IN UINT LookAheadBufferSize,
  877. IN UINT PacketSize,
  878. IN UINT TransportHeaderOffset
  879. )
  880. {
  881. PPS_PIPE_CONTEXT Pipe = PipeContext;
  882. LARGE_INTEGER CurrentTime;
  883. IPHeader UNALIGNED *IPH = NULL;
  884. TCPHeader UNALIGNED *TCPH = NULL;
  885. UDPHeader UNALIGNED *UDPH = NULL;
  886. IPAddr Src, Dst;
  887. PUCHAR headerBuffer = NULL, pData = NULL;
  888. PNDIS_BUFFER pFirstBuffer = NULL;
  889. ULONG firstbufferLength = 0, bufferLength = 0, HeaderLength = 0;
  890. ULONG TotalIpLen = 0, IPDataLength = 0, IpHdrLen = 0;
  891. ULONG TotalTcpLen = 0, TcpDataLen = 0, TotalLen = 0, TcpHeaderOffset = 0;
  892. ULONG TotalUdpLen = 0, UdpDataLen = 0, UdpHdrLen = 0;
  893. USHORT SrcPort = 0, DstPort = 0, IPID = 0, FragOffset = 0, Size = 0;
  894. BOOLEAN bFragment, bFirstFragment, bLastFragment;
  895. ULONG i = 0;
  896. ushort type; // Protocol type
  897. uint ProtOffset; // Offset in Data to non-media info.
  898. UINT MoreHeaderInLookAhead = 0;
  899. // Don't know anything about the MAC headers, piggy back from PSCHED...
  900. // Calculate if the header is more than the standard HeaderBufferSize (i.e. SNAP header, etc.)
  901. //
  902. MoreHeaderInLookAhead = TransportHeaderOffset - HeaderBufferSize;
  903. if (MoreHeaderInLookAhead)
  904. {
  905. // Just munge these, so that we can actually get down to business //
  906. ((PUCHAR) LookAheadBuffer) += MoreHeaderInLookAhead;
  907. LookAheadBufferSize -= MoreHeaderInLookAhead;
  908. }
  909. if (LookAheadBufferSize > sizeof(IPHeader))
  910. {
  911. IPH = (IPHeader *) (PUCHAR)LookAheadBuffer;
  912. // Check the header length and the version. If any of these
  913. // checks fail silently discard the packet.
  914. HeaderLength = ((IPH->iph_verlen & (uchar)~IP_VER_FLAG) << 2);
  915. if (HeaderLength >= sizeof(IPHeader) && HeaderLength <= LookAheadBufferSize)
  916. {
  917. // Get past the IP Header and get the rest of the stuff out//
  918. TotalIpLen = (uint)net_short(IPH->iph_length);
  919. if ((IPH->iph_verlen & IP_VER_FLAG) == IP_VERSION &&
  920. TotalIpLen >= HeaderLength && TotalIpLen <= LookAheadBufferSize)
  921. {
  922. Src = IPH->iph_src;
  923. Dst = IPH->iph_dest;
  924. IPID = net_short(IPH->iph_id);
  925. Size = net_short(IPH->iph_length );
  926. FragOffset = IPH->iph_offset & IP_OFFSET_MASK;
  927. FragOffset = net_short(FragOffset) * 8;
  928. bFragment = (IPH->iph_offset & IP_MF_FLAG) || (FragOffset > 0);
  929. bFirstFragment = bFragment && (FragOffset == 0);
  930. bLastFragment = bFragment && (!(IPH->iph_offset & IP_MF_FLAG));
  931. // If this is a fragment and NOT the first one, just put the Timestamp in here.
  932. // Otherwise, let it get to the protocols for processing.
  933. if (bFragment )
  934. return TRUE;
  935. // Do the protocol specific stuff.//
  936. switch (IPH->iph_protocol)
  937. {
  938. case IPPROTO_TCP:
  939. TotalTcpLen = TotalIpLen - HeaderLength;
  940. TCPH = (TCPHeader *) (((PUCHAR)IPH) + HeaderLength);
  941. SrcPort = net_short(TCPH->tcp_src);
  942. DstPort = net_short(TCPH->tcp_dest);
  943. TcpHeaderOffset = TCP_HDR_SIZE(TCPH);
  944. pData = (PUCHAR) TCPH + TcpHeaderOffset;
  945. TcpDataLen = TotalTcpLen - TcpHeaderOffset;
  946. goto TimeStmp;
  947. break;
  948. case IPPROTO_UDP:
  949. TotalUdpLen = TotalIpLen - HeaderLength;
  950. UDPH = (UDPHeader *) (((PUCHAR)IPH) + HeaderLength);
  951. UdpDataLen = TotalUdpLen - sizeof(UDPHeader);
  952. pData = ((PUCHAR) UDPH) + sizeof (UDPHeader);
  953. SrcPort = net_short(UDPH->uh_src);
  954. DstPort = net_short(UDPH->uh_dest);
  955. if (UdpDataLen < sizeof(UDPHeader))
  956. return TRUE;
  957. goto TimeStmp;
  958. break;
  959. default:
  960. break;
  961. }
  962. }
  963. }
  964. }
  965. TimeStmp:
  966. CheckForMatch( Src, Dst, SrcPort, DstPort,0, IPID, Size, DIR_RECV);
  967. /*
  968. if (CheckInPortAndIpList(Src, DstPort))
  969. {
  970. LARGE_INTEGER PerfFrequency;
  971. UINT64 RecdTime, Freq;
  972. LOG_RECORD Record;
  973. pRecord = &Record;
  974. CurrentTime = KeQueryPerformanceCounter(&PerfFrequency);
  975. //
  976. // Convert the perffrequency into 100ns interval.
  977. //
  978. Freq = 0;
  979. Freq |= PerfFrequency.HighPart;
  980. Freq = Freq << 32;
  981. Freq |= PerfFrequency.LowPart;
  982. pRecord->TimeReceivedWire = 0;
  983. pRecord->TimeReceivedWire |= CurrentTime.HighPart;
  984. pRecord->TimeReceivedWire = pRecord->TimeReceivedWire << 32;
  985. pRecord->TimeReceivedWire |= CurrentTime.LowPart;
  986. // Normalize cycles with the frequency.
  987. pRecord->TimeReceivedWire *= 10000000;
  988. pRecord->TimeReceivedWire /= Freq;
  989. if( (int)( (char*)pPacketStore - (char*)pPacketStoreHead + sizeof(PACKET_RECORD) ) < PACKET_STORE_SIZE )
  990. {
  991. pPacketStore->IpId = IPID;
  992. pPacketStore->cSeperator1='y';
  993. pPacketStore->TimeValue = pRecord->TimeReceivedWire;
  994. pPacketStore->cSeperator2 = 'm';
  995. pPacketStore->Size = Size;
  996. pPacketStore->cSeperator3 = 'z';
  997. pPacketStore->cSeperator4 = 'z';
  998. pPacketStore = (PPACKET_RECORD)((char*)pPacketStore + sizeof(PACKET_RECORD));
  999. }
  1000. else
  1001. {
  1002. pPacketStore = pPacketStoreHead;
  1003. }
  1004. }
  1005. */
  1006. return TRUE;
  1007. }
  1008. #endif