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.