Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/SoftEtherVPN_Stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
committerdnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
commit749497dde0a1dd08c434a73b9d4e93dc3e3326d9 (patch)
tree7c83a55919c0f1aa1267c4dbcd008f1644f961ee /src/See/dump.c
parentd433e567a561f8ae094a535025b02c7dc47026c6 (diff)
v4.03-9408-rtm
Diffstat (limited to 'src/See/dump.c')
-rw-r--r--src/See/dump.c570
1 files changed, 570 insertions, 0 deletions
diff --git a/src/See/dump.c b/src/See/dump.c
new file mode 100644
index 00000000..e60aa6cb
--- /dev/null
+++ b/src/See/dump.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include <stdarg.h>
+#include <ntddk.h>
+#include <ntiologc.h>
+#include <ndis.h>
+#include "debug.h"
+#include "packet.h"
+
+#include "win_bpf.h"
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
+{
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK IoStatus;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PWCHAR PathPrefix;
+ USHORT PathLen;
+ UNICODE_STRING FullFileName;
+ ULONG FullFileNameLength;
+ PDEVICE_OBJECT fsdDevice;
+
+ IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
+
+ if(fileName->Buffer[0] == L'\\' &&
+ fileName->Buffer[1] == L'?' &&
+ fileName->Buffer[2] == L'?' &&
+ fileName->Buffer[3] == L'\\'
+ ){
+ PathLen = 0;
+ }
+ else{
+ PathPrefix = L"\\??\\";
+ PathLen = 8;
+ }
+
+ // Insert the correct path prefix.
+ FullFileNameLength = PathLen + fileName->MaximumLength;
+
+ FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ FullFileNameLength,
+ '0DWA');
+
+ if (FullFileName.Buffer == NULL) {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ return ntStatus;
+ }
+
+ FullFileName.Length = PathLen;
+ FullFileName.MaximumLength = (USHORT)FullFileNameLength;
+
+ if(PathLen)
+ RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
+
+ RtlAppendUnicodeStringToString (&FullFileName, fileName);
+
+ IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
+
+ InitializeObjectAttributes ( &ObjectAttributes,
+ &FullFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ // Create the dump file
+ ntStatus = ZwCreateFile( &Open->DumpFileHandle,
+ SYNCHRONIZE | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatus,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ (Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
+
+ ExFreePool(FullFileName.Buffer);
+ Open->DumpFileHandle=NULL;
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ ExFreePool(FullFileName.Buffer);
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
+ FILE_WRITE_ACCESS,
+ *IoFileObjectType,
+ KernelMode,
+ &Open->DumpFileObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
+
+ IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
+
+ return ntStatus;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_StartDump(POPEN_INSTANCE Open)
+{
+ NTSTATUS ntStatus;
+ struct packet_file_header hdr;
+ IO_STATUS_BLOCK IoStatus;
+
+ IF_LOUD(DbgPrint("NPF: StartDump.\n");)
+
+ // Init the file header
+ hdr.magic = TCPDUMP_MAGIC;
+ hdr.version_major = PCAP_VERSION_MAJOR;
+ hdr.version_minor = PCAP_VERSION_MINOR;
+ hdr.thiszone = 0; /*Currently not set*/
+ hdr.snaplen = 1514;
+ hdr.sigfigs = 0;
+
+ // Detect the medium type
+ switch (Open->Medium){
+
+ case NdisMediumWan:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMedium802_3:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMediumFddi:
+ hdr.linktype = DLT_FDDI;
+ break;
+
+ case NdisMedium802_5:
+ hdr.linktype = DLT_IEEE802;
+ break;
+
+ case NdisMediumArcnet878_2:
+ hdr.linktype = DLT_ARCNET;
+ break;
+
+ case NdisMediumAtm:
+ hdr.linktype = DLT_ATM_RFC1483;
+ break;
+
+ default:
+ hdr.linktype = DLT_EN10MB;
+ }
+
+ // Write the header.
+ // We can use ZwWriteFile because we are in the context of the application
+ ntStatus = ZwWriteFile(Open->DumpFileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatus,
+ &hdr,
+ sizeof(hdr),
+ NULL,
+ NULL );
+
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ Open->DumpOffset.QuadPart=24;
+
+ ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ (ACCESS_MASK)0L,
+ 0,
+ 0,
+ NPF_DumpThread,
+ Open);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ KernelMode,
+ &Open->DumpThreadObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+
+ return ntStatus;
+
+}
+
+//-------------------------------------------------------------------
+// Dump Thread
+//-------------------------------------------------------------------
+
+VOID NPF_DumpThread(POPEN_INSTANCE Open)
+{
+// ULONG FrozenNic;
+
+ IF_LOUD(DbgPrint("NPF: In the work routine. Parameter = 0x%0x\n",Open);)
+
+ while(TRUE){
+
+ // Wait until some packets arrive or the timeout expires
+ NdisWaitEvent(&Open->DumpEvent, 5000);
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");)
+
+ if(Open->DumpLimitReached ||
+ Open->Size==0){ // BufSize=0 means that this instance was closed, or that the buffer is too
+ // small for any capture. In both cases it is better to end the dump
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
+ IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
+
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ NdisResetEvent(&Open->DumpEvent);
+
+ // Write the content of the buffer to the file
+ if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ }
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
+{
+#if 0
+
+ Thead=Open->Bhead;
+ Ttail=Open->Btail;
+ TLastByte=Open->BLastByte;
+
+ IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
+
+ // Get the address of the buffer
+ CurrBuff=Open->Buffer;
+ //
+ // Fill the application buffer
+ //
+ if( Ttail < Thead )
+ {
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart /*+ GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(TRUE){
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = TLastByte-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != TLastByte-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(TLastByte-Thead);
+ Open->BLastByte=Ttail;
+ Open->Bhead=0;
+ }
+
+ if( Ttail > Thead ){
+
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart /* +GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(Thead + SizeToDump < Ttail){
+
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = Ttail-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != Ttail-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(Ttail-Thead);
+ Open->Bhead=Ttail;
+
+ }
+#endif
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
+#if 0
+ IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
+ IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
+
+DbgPrint("1\n");
+ // Consistency check
+ if(Open->DumpFileHandle == NULL)
+ return STATUS_UNSUCCESSFUL;
+
+DbgPrint("2\n");
+ ZwClose( Open->DumpFileHandle );
+
+ ObDereferenceObject(Open->DumpFileObject);
+/*
+ if(Open->DumpLimitReached == TRUE)
+ // Limit already reached: don't save the rest of the buffer.
+ return STATUS_SUCCESS;
+*/
+DbgPrint("3\n");
+
+ NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
+
+ // Flush the buffer to file
+ NPF_SaveCurrentBuffer(Open);
+
+ // Close The file
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+
+ Open->DumpFileHandle = NULL;
+
+ ObDereferenceObject(Open->DumpFileObject);
+#endif
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+static NTSTATUS PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context)
+{
+
+ // Copy the status information back into the "user" IOSB
+ *Irp->UserIosb = Irp->IoStatus;
+
+ // Wake up the mainline code
+ KeSetEvent(Irp->UserEvent, 0, FALSE);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+ PLARGE_INTEGER Offset,
+ ULONG Length,
+ PMDL Mdl,
+ PIO_STATUS_BLOCK IoStatusBlock)
+{
+ PIRP irp;
+ KEVENT event;
+ PIO_STACK_LOCATION ioStackLocation;
+ PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
+
+ // Set up the event we'll use
+ KeInitializeEvent(&event, SynchronizationEvent, FALSE);
+
+ // Allocate and build the IRP we'll be sending to the FSD
+ irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
+
+ if (!irp) {
+ // Allocation failed, presumably due to memory allocation failure
+ IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoStatusBlock->Information = 0;
+
+ return;
+ }
+
+ irp->MdlAddress = Mdl;
+ irp->UserEvent = &event;
+ irp->UserIosb = IoStatusBlock;
+ irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ irp->Tail.Overlay.OriginalFileObject= FileObject;
+ irp->RequestorMode = KernelMode;
+
+ // Indicate that this is a WRITE operation
+ irp->Flags = IRP_WRITE_OPERATION;
+
+ // Set up the next I/O stack location
+ ioStackLocation = IoGetNextIrpStackLocation(irp);
+ ioStackLocation->MajorFunction = IRP_MJ_WRITE;
+ ioStackLocation->MinorFunction = 0;
+ ioStackLocation->DeviceObject = fsdDevice;
+ ioStackLocation->FileObject = FileObject;
+ IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);
+ ioStackLocation->Parameters.Write.Length = Length;
+ ioStackLocation->Parameters.Write.ByteOffset = *Offset;
+
+
+ // Send it on. Ignore the return code
+ (void) IoCallDriver(fsdDevice, irp);
+
+ // Wait for the I/O to complete.
+ KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
+
+ // Free the IRP now that we are done with it
+ IoFreeIrp(irp);
+
+ return;
+
+}