Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

Read.c

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

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