Main Page Modules Data Structures File List Data Fields Globals Related Pages

# Read.c

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 1999 - 2003
    00003  * NetGroup, Politecnico di Torino (Italy)
    00004  * All rights reserved.
    00005  *
    00006  * Redistribution and use in source and binary forms, with or without
    00007  * modification, are permitted provided that the following conditions
    00008  * are met:
    00009  *
    00010  * 1. Redistributions of source code must retain the above copyright
    00011  * notice, this list of conditions and the following disclaimer.
    00012  * 2. Redistributions in binary form must reproduce the above copyright
    00013  * notice, this list of conditions and the following disclaimer in the
    00014  * documentation and/or other materials provided with the distribution.
    00015  * 3. Neither the name of the Politecnico di Torino nor the names of its
    00016  * contributors may be used to endorse or promote products derived from
    00017  * this software without specific prior written permission.
    00018  *
    00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    00023  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00030  *
    00031  */
    00032
    00033 #include <stdarg.h>
    00034 #include "ntddk.h"
    00035 #include <ntiologc.h>
    00036 #include <ndis.h>
    00037 #include "debug.h"
    00038 #include "packet.h"
    00039 #include "win_bpf.h"
    00040
    00041 #include "tme.h"
    00042 #include "time_calls.h"
    00043
    00044 extern struct time_conv G_Start_Time; // from openclos.c
    00045
    00046 extern ULONG NCpu; //from packet.c
    00047
    00048 NTSTATUS NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
    00049 {
    00050     POPEN_INSTANCE      Open;
    00051     PIO_STACK_LOCATION  IrpSp;
    00052     PUCHAR              packp;
    00053     ULONG               Input_Buffer_Length;
    00054     UINT                Thead;
    00055     UINT                Ttail;
    00056     UINT                TLastByte;
    00057     PUCHAR              CurrBuff;
    00058     LARGE_INTEGER       CapTime;
    00059     LARGE_INTEGER       TimeFreq;
    00060     struct bpf_hdr      *header;
    00061     KIRQL               Irql;
    00062     PUCHAR              UserPointer;
    00063     ULONG               bytecopy;
    00064     UINT                SizeToCopy;
    00065     UINT                PktLen;
    00066     ULONG               copied,count,current_cpu,av,plen,increment,ToCopy,available;
    00067     CpuPrivateData      *LocalData;
    00068     ULONG               i;
    00069     ULONG               Occupation;
    00070     IF_LOUD(DbgPrint("NPF: Read\n");)
    00071
    00072     IrpSp = IoGetCurrentIrpStackLocation(Irp);
    00073     Open=IrpSp->FileObject->FsContext;
    00074
    00075     if( Open->Bound == FALSE ){
    00076         // The Network adapter was removed.
    00077         EXIT_FAILURE(0);
    00078     }
    00079
    00080     if (Open->Size == 0)
    00081     {
    00082         EXIT_FAILURE(0);
    00083     }
    00084
    00085     if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){
    00086         // this instance is in dump mode, but the dump file has still not been opened
    00087         EXIT_FAILURE(0);
    00088     }
    00089
    00090     Occupation=0;
    00091
    00092     for(i=0;i<NCpu;i++)
    00093         Occupation += (Open->Size - Open->CpuData[i].Free);
    00094
    00095     //See if the buffer is full enough to be copied
    00096     if( Occupation <= Open->MinToCopy*NCpu || Open->mode & MODE_DUMP )
    00097     {
    00098         //wait until some packets arrive or the timeout expires
    00099         if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
    00100             KeWaitForSingleObject(Open->ReadEvent,
    00101                 UserRequest,
    00102                 KernelMode,
    00103                 TRUE,
    00104                 (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
    00105
    00106         KeClearEvent(Open->ReadEvent);
    00107
    00108         if(Open->mode & MODE_STAT){   //this capture instance is in statistics mode
    00109             CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
    00110
    00111             //fill the bpf header for this packet
    00112             header=(struct bpf_hdr*)CurrBuff;
    00113             GET_TIME(&header->bh_tstamp,&G_Start_Time);
    00114
    00115             if(Open->mode & MODE_DUMP){
    00116                 *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
    00117                 header->bh_caplen=24;
    00118                 header->bh_datalen=24;
    00119                 Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
    00120             }
    00121             else{
    00122                 header->bh_caplen=16;
    00123                 header->bh_datalen=16;
    00124                 header->bh_hdrlen=sizeof(struct bpf_hdr);
    00125                 Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
    00126             }
    00127
    00128             *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
    00129             *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
    00130
    00131             //reset the countetrs
    00132             NdisAcquireSpinLock( &Open->CountersLock );
    00133             Open->Npackets.QuadPart=0;
    00134             Open->Nbytes.QuadPart=0;
    00135             NdisReleaseSpinLock( &Open->CountersLock );
    00136
    00137             Irp->IoStatus.Status = STATUS_SUCCESS;
    00138             IoCompleteRequest(Irp, IO_NO_INCREMENT);
    00139
    00140             return STATUS_SUCCESS;
    00141         }
    00142
    00143         if(Open->mode==MODE_MON)   //this capture instance is in monitor mode
    00144         {
    00145             PTME_DATA data;
    00146             ULONG cnt;
    00147             ULONG block_size;
    00148             PUCHAR tmp;
    00149
    00150             UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
    00151
    00152             if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
    00153             {
    00154                 EXIT_FAILURE(0);
    00155             }
    00156
    00157             header=(struct bpf_hdr*)UserPointer;
    00158
    00159             GET_TIME(&header->bh_tstamp,&G_Start_Time);
    00160
    00161
    00162             header->bh_hdrlen=sizeof(struct bpf_hdr);
    00163
    00164
    00165             //moves user memory pointer
    00166             UserPointer+=sizeof(struct bpf_hdr);
    00167
    00168             //calculus of data to be copied
    00169             //if the user buffer is smaller than data to be copied,
    00170             //only some data will be copied
    00171             data=&Open->tme.block_data[Open->tme.active_read];
    00172
    00173             if (data->last_read.tv_sec!=0)
    00174                 data->last_read=header->bh_tstamp;
    00175
    00176
    00177             bytecopy=data->block_size*data->filled_blocks;
    00178
    00179             if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
    00180                 bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
    00181             else
    00182                 bytecopy=data->filled_blocks;
    00183
    00184             tmp=data->shared_memory_base_address;
    00185             block_size=data->block_size;
    00186
    00187             for (cnt=0;cnt<bytecopy;cnt++)
    00188             {
    00189                 NdisAcquireSpinLock(&Open->MachineLock);
    00190                 RtlCopyMemory(UserPointer,tmp,block_size);
    00191                 NdisReleaseSpinLock(&Open->MachineLock);
    00192                 tmp+=block_size;
    00193                 UserPointer+=block_size;
    00194             }
    00195
    00196             bytecopy*=block_size;
    00197
    00198             header->bh_caplen=bytecopy;
    00199             header->bh_datalen=header->bh_caplen;
    00200
    00201             EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
    00202         }
    00203
    00204         Occupation=0;
    00205
    00206         for(i=0;i<NCpu;i++)
    00207             Occupation += (Open->Size - Open->CpuData[i].Free);
    00208
    00209
    00210         if ( Occupation == 0 || Open->mode & MODE_DUMP)
    00211             // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
    00212             // We must awake the application, returning an empty buffer.
    00213         {
    00214             EXIT_SUCCESS(0);
    00215         }
    00216
    00217     }
    00218
    00219
    00220
    00221
    00222 //------------------------------------------------------------------------------
    00223     copied=0;
    00224     count=0;
    00225     current_cpu=0;
    00226     available = IrpSp->Parameters.Read.Length;
    00227     packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
    00228
    00229     while (count < NCpu) //round robin on the CPUs, if count = NCpu there are no packets left to be copied
    00230     {
    00231         if (available == copied)
    00232         {
    00233             EXIT_SUCCESS(copied);
    00234         }
    00235
    00236         LocalData = &Open->CpuData[current_cpu];
    00237
    00238         if (LocalData->Free < Open->Size)
    00239         {  //there are some packets in the selected (aka LocalData) buffer
    00240             struct PacketHeader *Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->C);
    00241
    00242             if ( Header->SN == Open->ReaderSN)
    00243             {   //check if it the next one to be copied
    00244                 plen = Header->header.bh_caplen;
    00245                 if (plen + sizeof (struct bpf_hdr) > available-copied)
    00246                 {  //if the packet does not fit into the user buffer, we've ended copying packets
    00247                     EXIT_SUCCESS(copied);
    00248                 }
    00249
    00250                 *((struct bpf_hdr*)(&packp[copied]))=Header->header;
    00251
    00252                 copied += sizeof(struct bpf_hdr);
    00253                 LocalData->C += sizeof(struct PacketHeader);
    00254
    00255                 if (LocalData->C == Open->Size)
    00256                     LocalData->C = 0;
    00257
    00258                 if (Open->Size - LocalData->C < plen)
    00259                 {
    00260                     //the packet is fragmented in the buffer (i.e. it skips the buffer boundary)
    00261                     ToCopy = Open->Size - LocalData->C;
    00262                     RtlCopyMemory(packp + copied,LocalData->Buffer + LocalData->C,ToCopy);
    00263                     RtlCopyMemory(packp + copied + ToCopy,LocalData->Buffer,plen-ToCopy);
    00264                     LocalData->C = plen-ToCopy;
    00265                 }
    00266                 else
    00267                 {
    00268                     //the packet is not fragmented
    00269                     RtlCopyMemory(packp + copied ,LocalData->Buffer + LocalData->C ,plen);
    00270                     LocalData->C += plen;
    00271             //      if (c==size)  inutile, contemplato nell "header atomico"
    00272             //          c=0;
    00273                 }
    00274
    00275                 Open->ReaderSN++;
    00276                 copied+=Packet_WORDALIGN(plen);
    00277
    00278                 increment = plen + sizeof(struct PacketHeader);
    00279                 if ( Open->Size - LocalData->C < sizeof(struct PacketHeader))
    00280                 {   //the next packet would be saved at the end of the buffer, but the NewHeader struct would be fragmented
    00281                     //so the producer (--> the consumer) skips to the beginning of the buffer
    00282                     increment += Open->Size-LocalData->C;
    00283                     LocalData->C=0;
    00284                 }
    00285                 InterlockedExchangeAdd(&Open->CpuData[current_cpu].Free,increment);
    00286                 count=0;
    00287             }
    00288             else
    00289             {
    00290                 current_cpu=(current_cpu+1)%NCpu;
    00291                 count++;
    00292             }
    00293
    00294         }
    00295         else
    00296         {
    00297             current_cpu=(current_cpu+1)%NCpu;
    00298             count++;
    00299         }
    00300     }
    00301
    00302     {EXIT_SUCCESS(copied);}
    00303
    00304 //------------------------------------------------------------------------------
    00305
    00306 }
    00307
    00308 NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
    00309                         IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookaheadBuffer,
    00310                         IN UINT LookaheadBufferSize,IN UINT PacketSize)
    00311 {
    00312     POPEN_INSTANCE      Open;
    00313     PNDIS_PACKET        pPacket;
    00314     ULONG               SizeToTransfer;
    00315     NDIS_STATUS         Status;
    00316     UINT                BytesTransfered;
    00317     ULONG               BufferLength;
    00318     PMDL                pMdl1,pMdl2;
    00319     LARGE_INTEGER       CapTime;
    00320     LARGE_INTEGER       TimeFreq;
    00321     UINT                fres;
    00322     USHORT              NPFHdrSize;
    00323
    00324     CpuPrivateData      *LocalData;
    00325     ULONG               Cpu;
    00326     struct PacketHeader *Header;
    00327     ULONG               ToCopy;
    00328     ULONG               increment;
    00329     ULONG               i;
    00330     BOOLEAN             Flag;
    00331
    00332     IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
    00333     IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n",
    00334     HeaderBufferSize,
    00335     LookaheadBuffer,
    00336     LookaheadBufferSize,
    00337     PacketSize);)
    00338
    00339     Open= (POPEN_INSTANCE)ProtocolBindingContext;
    00340
    00341     if (Open->SkipProcessing == 1)  //some IoCtl is modifying some shared structure, we must drop the packet.
    00342         return NDIS_STATUS_NOT_ACCEPTED;
    00343
    00344     Cpu = KeGetCurrentProcessorNumber();
    00345     LocalData = &Open->CpuData[Cpu];
    00346
    00347     LocalData->Processing = 1;    //this tells the Ioctls that we are processing a packet, they cannot modify anything
    00348                                   //until ALL the Cpu have terminated their processing (aka, set their LocalData->processing to 0)
    00349     LocalData->Received++;
    00350     IF_LOUD(DbgPrint("Received on CPU %d \t%d\n",Cpu,LocalData->Received);)
    00351 //  Open->Received++;       // Number of packets received by filter ++
    00352
    00353     if (Open->mode == MODE_MON)
    00354     {
    00355         Flag = TRUE;
    00356         NdisAcquireSpinLock(&Open->MachineLock);
    00357     }
    00358     else
    00359         Flag = FALSE;
    00360
    00361     //
    00362     //Check if the lookahead buffer follows the mac header.
    00363     //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
    00364     //executed on the packet.
    00365     //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
    00366     //things like this) bpf_filter_with_2_buffers() is executed.
    00367     //
    00368     if((UINT)LookaheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
    00369         fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
    00370                                        HeaderBuffer,
    00371                                        LookaheadBuffer,
    00372                                        HeaderBufferSize,
    00373                                        PacketSize+HeaderBufferSize,
    00374                                        LookaheadBufferSize+HeaderBufferSize,
    00375                                        &Open->mem_ex,
    00376                                        &Open->tme,
    00377                                        &G_Start_Time);
    00378
    00379
    00380     else
    00381         if(Open->Filter != NULL)
    00382         {
    00383             if (Open->bpfprogram != NULL)
    00384             {
    00385                 fres=Open->Filter->Function(HeaderBuffer,
    00386                                     PacketSize+HeaderBufferSize,
    00387                                     LookaheadBufferSize+HeaderBufferSize);
    00388
    00389                 // Restore the stack.
    00390                 // I ignore the reason, but this instruction is needed only at kernel level
    00391                 _asm add esp,12
    00392             }
    00393             else
    00394                 fres = -1;
    00395         }
    00396         else
    00397             fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
    00398                         HeaderBuffer,
    00399                         PacketSize+HeaderBufferSize,
    00400                         LookaheadBufferSize+HeaderBufferSize,
    00401                         &Open->mem_ex,
    00402                         &Open->tme,
    00403                         &G_Start_Time);
    00404
    00405     if (Flag)
    00406         NdisReleaseSpinLock(&Open->MachineLock);
    00407
    00408     if(Open->mode==MODE_MON)
    00409     // we are in monitor mode
    00410     {
    00411         if (fres==1)
    00412             KeSetEvent(Open->ReadEvent,0,FALSE);
    00413         LocalData->Processing = 0;
    00414         return NDIS_STATUS_NOT_ACCEPTED;
    00415
    00416     }
    00417
    00418     if(fres==0)
    00419     {
    00420         // Packet not accepted by the filter, ignore it.
    00421         LocalData->Processing = 0;
    00422         return NDIS_STATUS_NOT_ACCEPTED;
    00423     }
    00424
    00425     //if the filter returns -1 the whole packet must be accepted
    00426     if(fres==-1 || fres > PacketSize+HeaderBufferSize)
    00427         fres = PacketSize+HeaderBufferSize;
    00428
    00429     if(Open->mode & MODE_STAT)
    00430     {
    00431     // we are in statistics mode
    00432         NdisAcquireSpinLock( &Open->CountersLock );
    00433
    00434         Open->Npackets.QuadPart++;
    00435
    00436         if(PacketSize+HeaderBufferSize<60)
    00437             Open->Nbytes.QuadPart+=60;
    00438         else
    00439             Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
    00440         // add preamble+SFD+FCS to the packet
    00441         // these values must be considered because are not part of the packet received from NDIS
    00442         Open->Nbytes.QuadPart+=12;
    00443
    00444         NdisReleaseSpinLock( &Open->CountersLock );
    00445
    00446         if(!(Open->mode & MODE_DUMP))
    00447         {
    00448             LocalData->Processing = 0;
    00449             return NDIS_STATUS_NOT_ACCEPTED;
    00450         }
    00451     }
    00452
    00453     if(Open->Size == 0)
    00454     {
    00455         LocalData->Dropped++;
    00456         LocalData->Processing = 0;
    00457         return NDIS_STATUS_NOT_ACCEPTED;
    00458     }
    00459
    00460     if(Open->mode & MODE_DUMP && Open->MaxDumpPacks)
    00461     {
    00462         ULONG Accepted=0;
    00463         for(i=0;i<NCpu;i++)
    00464             Accepted+=Open->CpuData[i].Accepted;
    00465
    00466         if(  Accepted > Open->MaxDumpPacks)
    00467         {
    00468             // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
    00469             Open->DumpLimitReached = TRUE; // This stops the thread
    00470             // Awake the dump thread
    00471             NdisSetEvent(&Open->DumpEvent);
    00472
    00473             // Awake the application
    00474             KeSetEvent(Open->ReadEvent,0,FALSE);
    00475
    00476             LocalData->Processing = 0;
    00477             return NDIS_STATUS_NOT_ACCEPTED;
    00478         }
    00479     }
    00480
    00482
    00483     if (fres + sizeof(struct PacketHeader) > LocalData->Free)
    00484     {
    00485         LocalData->Dropped++;
    00486         LocalData->Processing = 0;
    00487         return NDIS_STATUS_NOT_ACCEPTED;
    00488     }
    00489
    00490     if (LocalData->TransferMdl1 != NULL)
    00491     {
    00492         //if TransferMdl is not NULL, there is some TransferData pending (i.e. not having called TransferDataComplete, yet)
    00493         //in order to avoid buffer corruption, we drop the packet
    00494         LocalData->Dropped++;
    00495         LocalData->Processing = 0;
    00496         return NDIS_STATUS_NOT_ACCEPTED;
    00497     }
    00498
    00499     if (LookaheadBufferSize + HeaderBufferSize >= fres)
    00500     {
    00501         //we do not need to call NdisTransferData, either because we need only the HeaderBuffer, or because the LookaheadBuffer
    00502         //contains what we need
    00503
    00504         Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
    00505         LocalData->Accepted++;
    00506         GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
    00507         Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
    00508
    00509         Header->header.bh_caplen = fres;
    00510         Header->header.bh_datalen = PacketSize + HeaderBufferSize;
    00511         Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
    00512
    00513         LocalData->P +=sizeof(struct PacketHeader);
    00514         if (LocalData->P == Open->Size)
    00515             LocalData->P = 0;
    00516
    00517         if ( fres <= HeaderBufferSize || ( (ULONG)LookaheadBuffer - (ULONG)HeaderBuffer ) == HeaderBufferSize )
    00518         {
    00519             //we can consider the buffer contiguous, either because we use only the data
    00520             //present in the HeaderBuffer, or because HeaderBuffer and LookaheadBuffer are contiguous
    00521             // ;-))))))
    00522
    00523             if (Open->Size - LocalData->P < fres)
    00524             {
    00525                 //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
    00526                 //two copies!!
    00527                 ToCopy = Open->Size - LocalData->P;
    00528                 NdisMoveMappedMemory(LocalData->Buffer + LocalData->P,HeaderBuffer, ToCopy);
    00529                 NdisMoveMappedMemory(LocalData->Buffer + 0 , (PUCHAR)HeaderBuffer + ToCopy, fres - ToCopy);
    00530                 LocalData->P = fres-ToCopy;
    00531             }
    00532             else
    00533             {
    00534                 //the packet does not need to be fragmented in the buffer (aka, it doesn't skip the buffer boundary)
    00535                 // ;-)))))) only ONE copy
    00536                 NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, fres);
    00537                 LocalData->P += fres;
    00538             }
    00539         }
    00540         else
    00541         {
    00542             //HeaderBuffer and LookAhead buffer are NOT contiguous,
    00543             //AND, we need some bytes from the LookaheadBuffer, too
    00544             if (Open->Size - LocalData->P < fres)
    00545             {
    00546                 //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
    00547                 if (Open->Size - LocalData->P >= HeaderBufferSize)
    00548                 {
    00549                     //HeaderBuffer is NOT fragmented
    00550                     NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
    00551                     LocalData->P += HeaderBufferSize;
    00552
    00553                     if (LocalData->P == Open->Size)
    00554                     {
    00555                         //the fragmentation of the packet in the buffer is the same fragmentation
    00556                         //in HeaderBuffer+LookaheadBuffer
    00557                         LocalData->P=0;
    00558                         NdisMoveMappedMemory(LocalData->Buffer + 0, LookaheadBuffer, fres - HeaderBufferSize);
    00559                         LocalData->P += (fres - HeaderBufferSize);
    00560                     }
    00561                     else
    00562                     {
    00563                         //LookAheadBuffer is fragmented, two copies
    00564                         ToCopy = Open->Size - LocalData->P;
    00565                         NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, ToCopy);
    00566                         LocalData->P=0;
    00567                         NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer+ ToCopy, fres - HeaderBufferSize - ToCopy);
    00568                         LocalData->P = fres - HeaderBufferSize - ToCopy;
    00569                     }
    00570                 }
    00571                 else
    00572                 {
    00573                     //HeaderBuffer is fragmented in the buffer (aka, it will skip the buffer boundary)
    00574                     //two copies to copy the HeaderBuffer
    00575                     ToCopy = Open->Size - LocalData->P;
    00576                     NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, ToCopy);
    00577                     LocalData->P = 0;
    00578                     NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
    00579                     LocalData->P = HeaderBufferSize - ToCopy;
    00580
    00581                     //only one copy to copy the LookaheadBuffer
    00582                     NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres- HeaderBufferSize);
    00583                     LocalData->P += (fres - HeaderBufferSize);
    00584                 }
    00585             }
    00586             else
    00587             {
    00588                 //the packet won't be fragmented in the destination buffer (aka, it won't skip the buffer boundary)
    00589                 //two copies, the former to copy the HeaderBuffer, the latter to copy the LookaheadBuffer
    00590                 NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
    00591                 LocalData->P += HeaderBufferSize;
    00592                 NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres - HeaderBufferSize);
    00593                 LocalData->P += (fres - HeaderBufferSize);
    00594             }
    00595         }
    00596
    00597         increment = fres + sizeof(struct PacketHeader);
    00598         if (Open->Size - LocalData->P < sizeof(struct PacketHeader))  //we check that the available, AND contiguous, space in the buffer will fit
    00599         {                                                          //the NewHeader structure, at least, otherwise we skip the producer
    00600             increment += Open->Size-LocalData->P;                  //at the beginning of the buffer (p = 0), and decrement the free bytes appropriately
    00601             LocalData->P = 0;
    00602         }
    00603
    00604         InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
    00605         if(Open->Size - LocalData->Free >= Open->MinToCopy)
    00606         {
    00607             if(Open->mode & MODE_DUMP)
    00608                 NdisSetEvent(&Open->DumpEvent);
    00609             else
    00610                 KeSetEvent(Open->ReadEvent,0,FALSE);
    00611         }
    00612
    00613         LocalData->Processing = 0;
    00614         return NDIS_STATUS_NOT_ACCEPTED;
    00615     }
    00616     else
    00617     {
    00618         IF_LOUD(DbgPrint("TransferData!!\n");)
    00619         //ndisTransferData required
    00620         LocalData->NewP = LocalData->P;
    00621
    00622         LocalData->NewP +=sizeof(struct PacketHeader);
    00623         if (LocalData->NewP == Open->Size)
    00624             LocalData->NewP = 0;
    00625
    00626         //first of all, surely the header must be copied
    00627         if (Open->Size-LocalData->NewP >= HeaderBufferSize)
    00628         {
    00629             //1 copy!
    00630             NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, HeaderBufferSize);
    00631             LocalData->NewP += HeaderBufferSize;
    00632             if (LocalData->NewP == Open->Size)
    00633                 LocalData->NewP = 0;
    00634         }
    00635         else
    00636         {
    00637             ToCopy = Open->Size - LocalData->NewP;
    00638             NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, ToCopy);
    00639             NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
    00640             LocalData->NewP = HeaderBufferSize - ToCopy;
    00641         }
    00642
    00643         //then we copy the Lookahead buffer
    00644
    00645         if (Open->Size-LocalData->NewP >= LookaheadBufferSize)
    00646         {
    00647             //1 copy!
    00648             NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, LookaheadBufferSize);
    00649             LocalData->NewP += LookaheadBufferSize;
    00650             if (LocalData->NewP == Open->Size)
    00651                 LocalData->NewP = 0;
    00652         }
    00653         else
    00654         {
    00655             ToCopy = Open->Size - LocalData->NewP;
    00656             NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, ToCopy);
    00657             NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer + ToCopy, LookaheadBufferSize - ToCopy);
    00658             LocalData->NewP = LookaheadBufferSize - ToCopy;
    00659         }
    00660
    00661         //Now we must prepare the buffer(s) for the NdisTransferData
    00662         if ((Open->Size - LocalData->NewP) >= (fres - HeaderBufferSize - LookaheadBufferSize))
    00663         {
    00664             //only 1 buffer
    00665             pMdl1 = IoAllocateMdl(
    00666                 LocalData->Buffer + LocalData->NewP,
    00667                 fres - HeaderBufferSize - LookaheadBufferSize,
    00668                 FALSE,
    00669                 FALSE,
    00670                 NULL);
    00671
    00672             if (pMdl1 == NULL)
    00673             {
    00674                 IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
    00675                 LocalData->Dropped++;
    00676                 LocalData->Processing = 0;
    00677                 return NDIS_STATUS_NOT_ACCEPTED;
    00678             }
    00679
    00680             MmBuildMdlForNonPagedPool(pMdl1);
    00681             pMdl2=NULL;
    00682             LocalData->NewP += fres - HeaderBufferSize - LookaheadBufferSize;
    00683
    00684
    00685         }
    00686         else
    00687         {
    00688             //2 buffers
    00689             pMdl1 = IoAllocateMdl(
    00690                 LocalData->Buffer + LocalData->NewP,
    00691                 Open->Size - LocalData->NewP,
    00692                 FALSE,
    00693                 FALSE,
    00694                 NULL);
    00695
    00696             if (pMdl1 == NULL)
    00697             {
    00698                 IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
    00699                 LocalData->Dropped++;
    00700                 LocalData->Processing = 0;
    00701                 return NDIS_STATUS_NOT_ACCEPTED;
    00702             }
    00703
    00704             pMdl2 = IoAllocateMdl(
    00705                 LocalData->Buffer + 0,
    00706                 fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP),
    00707                 FALSE,
    00708                 FALSE,
    00709                 NULL);
    00710
    00711             if (pMdl2 == NULL)
    00712             {
    00713                 IF_LOUD(DbgPrint("Error allocating Mdl2\n");)
    00714                 IoFreeMdl(pMdl1);
    00715                 LocalData->Dropped++;
    00716                 LocalData->Processing = 0;
    00717                 return NDIS_STATUS_NOT_ACCEPTED;
    00718             }
    00719
    00720             LocalData->NewP = fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP);
    00721
    00722             MmBuildMdlForNonPagedPool(pMdl1);
    00723             MmBuildMdlForNonPagedPool(pMdl2);
    00724         }
    00725
    00726
    00727         NdisAllocatePacket(&Status, &pPacket, Open->PacketPool);
    00728
    00729         if (Status != NDIS_STATUS_SUCCESS)
    00730         {
    00731             IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
    00732             IoFreeMdl(pMdl1);
    00733             if (pMdl2 != NULL)
    00734                 IoFreeMdl(pMdl2);
    00735             LocalData->Dropped++;
    00736             LocalData->Processing = 0;
    00737             return NDIS_STATUS_NOT_ACCEPTED;
    00738         }
    00739
    00740         if (pMdl2 != NULL)
    00741             NdisChainBufferAtFront(pPacket,pMdl2);
    00742
    00743         NdisChainBufferAtFront(pPacket,pMdl1);
    00744
    00745         RESERVED(pPacket)->Cpu = Cpu;
    00746
    00747         LocalData->TransferMdl1 = pMdl1;
    00748         LocalData->TransferMdl2 = pMdl2;
    00749
    00750
    00751         Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
    00752         Header->header.bh_caplen = fres;
    00753         Header->header.bh_datalen = PacketSize + HeaderBufferSize;
    00754         Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
    00755
    00756         NdisTransferData(
    00757                 &Status,
    00758                 Open->AdapterHandle,
    00759                 MacReceiveContext,
    00760                 LookaheadBufferSize,
    00761                 fres - HeaderBufferSize - LookaheadBufferSize,
    00762                 pPacket,
    00763                 &BytesTransfered);
    00764
    00765         if (Status != NDIS_STATUS_PENDING)
    00766         {
    00767             IF_LOUD(DbgPrint("NdisTransferData, not pending!\n");)
    00768             LocalData->TransferMdl1 = NULL;
    00769             LocalData->TransferMdl2 = NULL;
    00770
    00771             IoFreeMdl(pMdl1);
    00772             if ( pMdl2 != NULL )
    00773                 IoFreeMdl(pMdl2);
    00774
    00775             NdisReinitializePacket(pPacket);
    00776             // Put the packet on the free queue
    00777             NdisFreePacket(pPacket);
    00778
    00779             LocalData->P = LocalData->NewP;
    00780
    00781             LocalData->Accepted++;
    00782             GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
    00783             Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
    00784
    00785             increment = fres + sizeof(struct PacketHeader);
    00786             if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
    00787             {
    00788                 increment += Open->Size-LocalData->P;
    00789                 LocalData->P = 0;
    00790             }
    00791
    00792             InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
    00793
    00794             if(Open->Size - LocalData->Free >= Open->MinToCopy)
    00795             {
    00796                 if(Open->mode & MODE_DUMP)
    00797                     NdisSetEvent(&Open->DumpEvent);
    00798                 else
    00799                     KeSetEvent(Open->ReadEvent,0,FALSE);
    00800             }
    00801
    00802             LocalData->Processing = 0;
    00803             return NDIS_STATUS_NOT_ACCEPTED;
    00804         }
    00805         else
    00806         {
    00807             DbgPrint("NdisTransferData, pending!\n");
    00808             return NDIS_STATUS_NOT_ACCEPTED;
    00809         }
    00810     }
    00811
    00812     return NDIS_STATUS_SUCCESS;
    00813
    00814 }
    00815
    00816 //-------------------------------------------------------------------
    00817
    00818 VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
    00819                                  IN NDIS_STATUS Status,IN UINT BytesTransfered)
    00820 {
    00821     POPEN_INSTANCE      Open;
    00822     ULONG               Cpu;
    00823     CpuPrivateData      *LocalData;
    00824     struct PacketHeader*    Header;
    00825     ULONG               increment;
    00826
    00827     IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
    00828
    00829     Open = (POPEN_INSTANCE)ProtocolBindingContext;
    00830
    00831     Cpu = RESERVED(pPacket)->Cpu;
    00832
    00833     LocalData = &Open->CpuData[Cpu];
    00834
    00835     IoFreeMdl(LocalData->TransferMdl1);
    00836     if ( LocalData->TransferMdl2 != NULL )
    00837         IoFreeMdl(LocalData->TransferMdl2);
    00838
    00839     NdisReinitializePacket(pPacket);
    00840     // Put the packet on the free queue
    00841     NdisFreePacket(pPacket);
    00842
    00843     //the packet has been successfully copied to the kernel buffer, we can prepend it with the PacketHeader,
    00844     //and obtain the sequence number and the timestamp
    00845
    00846     LocalData->Accepted++;
    00847     Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
    00848     GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
    00849     Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
    00850
    00851     LocalData->P = LocalData->NewP;
    00852
    00853     increment = Header->header.bh_caplen + sizeof(struct PacketHeader);
    00854     if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
    00855     {
    00856         increment += Open->Size-LocalData->P;
    00857         LocalData->P = 0;
    00858     }
    00859
    00860     InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
    00861
    00862     if(Open->Size - LocalData->Free >= Open->MinToCopy)
    00863     {
    00864         if(Open->mode & MODE_DUMP)
    00865             NdisSetEvent(&Open->DumpEvent);
    00866         else
    00867             KeSetEvent(Open->ReadEvent,0,FALSE);
    00868     }
    00869
    00870     LocalData->TransferMdl1 = NULL;
    00871     LocalData->TransferMdl2 = NULL;
    00872     LocalData->Processing = 0;
    00873
    00874 // Unfreeze the consumer
    00875     if(Open->Size - LocalData->Free > Open->MinToCopy)
    00876     {
    00877         if(Open->mode & MODE_DUMP)
    00878             NdisSetEvent(&Open->DumpEvent);
    00879         else
    00880             KeSetEvent(Open->ReadEvent,0,FALSE);
    00881     }
    00882     return;
    00883 }
    00884
    00885 //-------------------------------------------------------------------
    00886
    00887 VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
    00888 {
    00889     IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
    00890     return;
    00891 }

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.