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, 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. All rights reserved.