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