メイン   モジュール   デー タ構造   ファイルリスト   データフィールド   グローバル   関連ページ   注意事項   English

Read.c

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

documentation. Copyright (c)2002-2003 Politecnico di Torino.
2005 translated by Telebusiness,Inc.
 All rights reserved.