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.