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

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