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