メイン   モ ジュール   デー タ構造   ファイルリスト   データフィールド   グローバル   関連ページ   注意事項   English

dump.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999, 2000
00003  *  Politecnico di Torino.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that: (1) source code distributions
00007  * retain the above copyright notice and this paragraph in its entirety, (2)
00008  * distributions including binary code include the above copyright notice and
00009  * this paragraph in its entirety in the documentation or other materials
00010  * provided with the distribution, and (3) all advertising materials mentioning
00011  * features or use of this software display the following acknowledgement:
00012  * ``This product includes software developed by the Politecnico
00013  * di Torino, and its contributors.'' Neither the name of
00014  * the University nor the names of its contributors may be used to endorse
00015  * or promote products derived from this software without specific prior
00016  * written permission.
00017  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00018  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00020  */
00021 
00022 #include <stdarg.h>
00023 #include <ntddk.h>
00024 #include <ntiologc.h>
00025 #include <ndis.h>
00026 #include "debug.h"
00027 #include "packet.h"
00028 
00029 #include "win_bpf.h"
00030 
00031 //-------------------------------------------------------------------
00032 
00033 NTSTATUS
00034 NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
00035 {
00036     NTSTATUS ntStatus;
00037     IO_STATUS_BLOCK IoStatus;
00038     OBJECT_ATTRIBUTES ObjectAttributes;
00039     PWCHAR PathPrefix;
00040     USHORT PathLen;
00041     UNICODE_STRING FullFileName;
00042     ULONG FullFileNameLength;
00043     PDEVICE_OBJECT fsdDevice;
00044 
00045     FILE_STANDARD_INFORMATION StandardInfo;
00046     
00047     IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
00048 
00049     if(fileName->Buffer[0] == L'\\' &&
00050         fileName->Buffer[1] == L'?' &&
00051         fileName->Buffer[2] == L'?' &&
00052         fileName->Buffer[3] == L'\\'
00053     ){
00054         PathLen = 0;
00055     }
00056     else{
00057         PathPrefix = L"\\??\\";
00058         PathLen = 8;
00059     }
00060     
00061     // Insert the correct path prefix.
00062     FullFileNameLength = PathLen + fileName->MaximumLength;
00063     
00064     FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 
00065         FullFileNameLength,
00066         '0DWA');
00067     
00068     if (FullFileName.Buffer == NULL) {
00069         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00070         return ntStatus;
00071     }
00072     
00073     FullFileName.Length = PathLen;
00074     FullFileName.MaximumLength = (USHORT)FullFileNameLength;
00075     
00076     if(PathLen)
00077         RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
00078     
00079     RtlAppendUnicodeStringToString (&FullFileName, fileName);
00080     
00081     IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
00082     
00083     InitializeObjectAttributes ( &ObjectAttributes,
00084         &FullFileName,
00085         OBJ_CASE_INSENSITIVE,
00086         NULL,
00087         NULL );
00088     
00089     // Create the dump file
00090     ntStatus = ZwCreateFile( &Open->DumpFileHandle,
00091         SYNCHRONIZE | FILE_WRITE_DATA,
00092         &ObjectAttributes,
00093         &IoStatus,
00094         NULL,
00095         FILE_ATTRIBUTE_NORMAL,
00096         FILE_SHARE_READ,
00097         (Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
00098         FILE_SYNCHRONOUS_IO_NONALERT,
00099         NULL,
00100         0 );
00101 
00102     if ( !NT_SUCCESS( ntStatus ) )
00103     {
00104         IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
00105         
00106         ExFreePool(FullFileName.Buffer);
00107         Open->DumpFileHandle=NULL;
00108         ntStatus = STATUS_NO_SUCH_FILE;
00109         return ntStatus;
00110     }
00111     
00112     ExFreePool(FullFileName.Buffer);
00113     
00114     ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
00115         FILE_WRITE_ACCESS,
00116         *IoFileObjectType,
00117         KernelMode,
00118         &Open->DumpFileObject,
00119         0);
00120     
00121     if ( !NT_SUCCESS( ntStatus ) )
00122     {
00123         IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
00124             
00125         ZwClose( Open->DumpFileHandle );
00126         Open->DumpFileHandle=NULL;
00127         
00128         ntStatus = STATUS_NO_SUCH_FILE;
00129         return ntStatus;
00130     }
00131     
00132     fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
00133 
00134     IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
00135 
00136     return ntStatus;
00137 }   
00138 
00139 //-------------------------------------------------------------------
00140 
00141 NTSTATUS
00142 NPF_StartDump(POPEN_INSTANCE Open)
00143 {
00144     NTSTATUS ntStatus;
00145     struct packet_file_header hdr;
00146     IO_STATUS_BLOCK IoStatus;
00147     NDIS_REQUEST pRequest;
00148     ULONG MediaType;
00149     OBJECT_ATTRIBUTES ObjectAttributes;
00150 
00151     IF_LOUD(DbgPrint("NPF: StartDump.\n");)
00152 
00153     // Init the file header
00154     hdr.magic = TCPDUMP_MAGIC;
00155     hdr.version_major = PCAP_VERSION_MAJOR;
00156     hdr.version_minor = PCAP_VERSION_MINOR;
00157     hdr.thiszone = 0; /*Currently not set*/
00158     hdr.snaplen = 1514;
00159     hdr.sigfigs = 0;
00160 
00161     // Detect the medium type
00162     switch (Open->Medium){
00163         
00164     case NdisMediumWan:
00165         hdr.linktype = DLT_EN10MB;
00166         break;
00167         
00168     case NdisMedium802_3:
00169         hdr.linktype = DLT_EN10MB;
00170         break;
00171         
00172     case NdisMediumFddi:
00173         hdr.linktype = DLT_FDDI;
00174         break;
00175         
00176     case NdisMedium802_5:           
00177         hdr.linktype = DLT_IEEE802; 
00178         break;
00179         
00180     case NdisMediumArcnet878_2:
00181         hdr.linktype = DLT_ARCNET;
00182         break;
00183         
00184     case NdisMediumAtm:
00185         hdr.linktype = DLT_ATM_RFC1483;
00186         break;
00187         
00188     default:
00189         hdr.linktype = DLT_EN10MB;
00190     }
00191 
00192     // Write the header.
00193     // We can use ZwWriteFile because we are in the context of the application
00194     ntStatus = ZwWriteFile(Open->DumpFileHandle,
00195         NULL,
00196         NULL,
00197         NULL,
00198         &IoStatus,
00199         &hdr,
00200         sizeof(hdr),
00201         NULL,
00202         NULL );
00203 
00204     
00205     if ( !NT_SUCCESS( ntStatus ) )
00206     {
00207         IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
00208         
00209         ZwClose( Open->DumpFileHandle );
00210         Open->DumpFileHandle=NULL;
00211         
00212         ntStatus = STATUS_NO_SUCH_FILE;
00213         return ntStatus;
00214     }
00215 
00216     Open->DumpOffset.QuadPart=24;
00217             
00218     ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
00219         THREAD_ALL_ACCESS,
00220         (ACCESS_MASK)0L,
00221         0,
00222         0,
00223         NPF_DumpThread,
00224         Open);
00225     
00226     if ( !NT_SUCCESS( ntStatus ) )
00227     {
00228         IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
00229         
00230         ZwClose( Open->DumpFileHandle );
00231         Open->DumpFileHandle=NULL;
00232 
00233         return ntStatus;
00234     }  
00235 
00236     ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
00237         THREAD_ALL_ACCESS,
00238         NULL,
00239         KernelMode,
00240         &Open->DumpThreadObject,
00241         0);
00242 
00243     if ( !NT_SUCCESS( ntStatus ) )
00244     {
00245         IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
00246         
00247         ObDereferenceObject(Open->DumpFileObject);
00248         ZwClose( Open->DumpFileHandle );
00249         Open->DumpFileHandle=NULL;
00250 
00251         return ntStatus;
00252     }  
00253 
00254     
00255     return ntStatus;
00256     
00257 }
00258 
00259 //-------------------------------------------------------------------
00260 // Dump Thread
00261 //-------------------------------------------------------------------
00262 
00263 VOID NPF_DumpThread(POPEN_INSTANCE Open)
00264 {
00265     ULONG       FrozenNic;
00266 
00267     IF_LOUD(DbgPrint("NPF: In the work routine.  Parameter = 0x%0x\n",Open);)
00268 
00269     while(TRUE){
00270 
00271         // Wait until some packets arrive or the timeout expires
00272         NdisWaitEvent(&Open->DumpEvent, 5000);  
00273 
00274         IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");)
00275             
00276         if(Open->DumpLimitReached ||
00277             Open->Size==0){     // BufSize=0 means that this instance was closed, or that the buffer is too
00278                                     // small for any capture. In both cases it is better to end the dump
00279 
00280             IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
00281             IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
00282 
00283             PsTerminateSystemThread(STATUS_SUCCESS);
00284             return;
00285         }
00286         
00287         NdisResetEvent(&Open->DumpEvent);
00288 
00289         // Write the content of the buffer to the file
00290         if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
00291             PsTerminateSystemThread(STATUS_SUCCESS);
00292             return;
00293         }
00294     
00295     }
00296 
00297 }
00298 
00299 //-------------------------------------------------------------------
00300 
00301 NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
00302 {
00303     UINT        Thead;
00304     UINT        Ttail;
00305     UINT        TLastByte;
00306     PUCHAR      CurrBuff;
00307     NTSTATUS    ntStatus;
00308     IO_STATUS_BLOCK IoStatus;
00309     PMDL        lMdl;
00310     UINT        SizeToDump;
00311 
00312 #if 0
00313 
00314     Thead=Open->Bhead;
00315     Ttail=Open->Btail;
00316     TLastByte=Open->BLastByte;
00317     
00318     IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
00319 
00320     // Get the address of the buffer
00321     CurrBuff=Open->Buffer;
00322     //
00323     // Fill the application buffer
00324     //
00325     if( Ttail < Thead )
00326     {
00327         if(Open->MaxDumpBytes &&
00328             (UINT)Open->DumpOffset.QuadPart /*+ GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
00329         {
00330             // Size limit reached
00331             UINT PktLen;
00332             
00333             SizeToDump = 0;
00334             
00335             // Scan the buffer to detect the exact amount of data to save
00336             while(TRUE){
00337                 PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
00338                 
00339                 if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
00340                     break;
00341                 
00342                 SizeToDump += PktLen;
00343             }
00344             
00345         }
00346         else
00347             SizeToDump = TLastByte-Thead;
00348         
00349         lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
00350         if (lMdl == NULL)
00351         {
00352             // No memory: stop dump
00353             IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
00354             return STATUS_UNSUCCESSFUL;
00355         }
00356         
00357         MmBuildMdlForNonPagedPool(lMdl);
00358         
00359         // Write to disk
00360         NPF_WriteDumpFile(Open->DumpFileObject,
00361             &Open->DumpOffset,
00362             SizeToDump,
00363             lMdl,
00364             &IoStatus);
00365         
00366         IoFreeMdl(lMdl);
00367         
00368         if(!NT_SUCCESS(IoStatus.Status)){
00369             // Error
00370             return STATUS_UNSUCCESSFUL;
00371         }
00372         
00373         if(SizeToDump != TLastByte-Thead){
00374             // Size limit reached.
00375             Open->DumpLimitReached = TRUE;
00376     
00377             // Awake the application
00378             KeSetEvent(Open->ReadEvent,0,FALSE);
00379 
00380             return STATUS_UNSUCCESSFUL;
00381         }
00382         
00383         // Update the packet buffer
00384         Open->DumpOffset.QuadPart+=(TLastByte-Thead);
00385         Open->BLastByte=Ttail;
00386         Open->Bhead=0;
00387     }
00388 
00389     if( Ttail > Thead ){
00390         
00391         if(Open->MaxDumpBytes &&
00392             (UINT)Open->DumpOffset.QuadPart /* +GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
00393         {
00394             // Size limit reached
00395             UINT PktLen;
00396                         
00397             SizeToDump = 0;
00398             
00399             // Scan the buffer to detect the exact amount of data to save
00400             while(Thead + SizeToDump < Ttail){
00401 
00402                 PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
00403                 
00404                 if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
00405                     break;
00406                 
00407                 SizeToDump += PktLen;
00408             }
00409             
00410         }
00411         else
00412             SizeToDump = Ttail-Thead;
00413                 
00414         lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
00415         if (lMdl == NULL)
00416         {
00417             // No memory: stop dump
00418             IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
00419             return STATUS_UNSUCCESSFUL;
00420         }
00421         
00422         MmBuildMdlForNonPagedPool(lMdl);
00423         
00424         // Write to disk
00425         NPF_WriteDumpFile(Open->DumpFileObject,
00426             &Open->DumpOffset,
00427             SizeToDump,
00428             lMdl,
00429             &IoStatus);
00430         
00431         IoFreeMdl(lMdl);
00432         
00433         if(!NT_SUCCESS(IoStatus.Status)){
00434             // Error
00435             return STATUS_UNSUCCESSFUL;
00436         }
00437         
00438         if(SizeToDump != Ttail-Thead){
00439             // Size limit reached.
00440             Open->DumpLimitReached = TRUE;
00441 
00442             // Awake the application
00443             KeSetEvent(Open->ReadEvent,0,FALSE);
00444             
00445             return STATUS_UNSUCCESSFUL;
00446         }
00447         
00448         // Update the packet buffer
00449         Open->DumpOffset.QuadPart+=(Ttail-Thead);           
00450         Open->Bhead=Ttail;
00451         
00452     }
00453 #endif
00454     return STATUS_SUCCESS;
00455 }
00456 
00457 //-------------------------------------------------------------------
00458 
00459 NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
00460     NTSTATUS    ntStatus;
00461     IO_STATUS_BLOCK IoStatus;
00462     PMDL        WriteMdl;
00463     PUCHAR      VMBuff;
00464     UINT        VMBufLen;
00465 
00466 #if 0
00467     IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
00468     IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
00469 
00470 DbgPrint("1\n");
00471     // Consistency check
00472     if(Open->DumpFileHandle == NULL)
00473         return STATUS_UNSUCCESSFUL;
00474 
00475 DbgPrint("2\n");
00476     ZwClose( Open->DumpFileHandle );
00477 
00478     ObDereferenceObject(Open->DumpFileObject);
00479 /*
00480     if(Open->DumpLimitReached == TRUE)
00481         // Limit already reached: don't save the rest of the buffer.
00482         return STATUS_SUCCESS;
00483 */
00484 DbgPrint("3\n");
00485 
00486     NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
00487 
00488     // Flush the buffer to file 
00489     NPF_SaveCurrentBuffer(Open);
00490 
00491     // Close The file
00492     ObDereferenceObject(Open->DumpFileObject);
00493     ZwClose( Open->DumpFileHandle );
00494     
00495     Open->DumpFileHandle = NULL;
00496 
00497     ObDereferenceObject(Open->DumpFileObject);
00498 #endif
00499     return STATUS_SUCCESS;
00500 }
00501 
00502 //-------------------------------------------------------------------
00503 
00504 static NTSTATUS PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
00505                                 PIRP Irp,
00506                                 PVOID Context)
00507 {
00508 
00509     // Copy the status information back into the "user" IOSB
00510     *Irp->UserIosb = Irp->IoStatus;
00511     
00512     // Wake up the mainline code
00513     KeSetEvent(Irp->UserEvent, 0, FALSE);
00514           
00515     return STATUS_MORE_PROCESSING_REQUIRED;
00516 }
00517 
00518 //-------------------------------------------------------------------
00519 
00520 VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
00521                                 PLARGE_INTEGER Offset,
00522                                 ULONG Length,
00523                                 PMDL Mdl,
00524                                 PIO_STATUS_BLOCK IoStatusBlock)
00525 {
00526     PIRP irp;
00527     KEVENT event;
00528     PIO_STACK_LOCATION ioStackLocation;
00529     PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
00530     NTSTATUS Status;
00531  
00532     // Set up the event we'll use
00533     KeInitializeEvent(&event, SynchronizationEvent, FALSE);
00534     
00535     // Allocate and build the IRP we'll be sending to the FSD
00536     irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
00537 
00538     if (!irp) {
00539         // Allocation failed, presumably due to memory allocation failure
00540         IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
00541         IoStatusBlock->Information = 0;
00542 
00543         return;
00544     }
00545     
00546     irp->MdlAddress = Mdl;
00547     irp->UserEvent = &event;
00548     irp->UserIosb = IoStatusBlock;
00549     irp->Tail.Overlay.Thread = PsGetCurrentThread();
00550     irp->Tail.Overlay.OriginalFileObject= FileObject;    
00551     irp->RequestorMode = KernelMode;
00552     
00553     // Indicate that this is a WRITE operation
00554     irp->Flags = IRP_WRITE_OPERATION;    
00555     
00556     // Set up the next I/O stack location
00557     ioStackLocation = IoGetNextIrpStackLocation(irp);
00558     ioStackLocation->MajorFunction = IRP_MJ_WRITE;
00559     ioStackLocation->MinorFunction = 0;
00560     ioStackLocation->DeviceObject = fsdDevice;
00561     ioStackLocation->FileObject = FileObject;
00562     IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);    
00563     ioStackLocation->Parameters.Write.Length = Length;    
00564     ioStackLocation->Parameters.Write.ByteOffset = *Offset;
00565     
00566 
00567     // Send it on.  Ignore the return code
00568     (void) IoCallDriver(fsdDevice, irp);
00569      
00570     // Wait for the I/O to complete.
00571     KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
00572 
00573     // Free the IRP now that we are done with it
00574     IoFreeIrp(irp);
00575 
00576     return;
00577 
00578 }

documentation. Copyright (c) 2002-2003 Politecnico di Torino.
2005 translated by Telebusiness,Inc.
 All rights reserved.