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

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