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.