add winpcap 4.0.2 from url http://www.winpcap.org/
[natblaster.git] / winpcap / Packet9x / VXD / Read.c
blob3bdfae8b927cd19202c835b57a26acb3e91e5839
1 /*
2 * Copyright (c) 1999 - 2003
3 * NetGroup, Politecnico di Torino (Italy)
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <basedef.h>
35 #include <vmm.h>
36 #include <vwin32.h>
37 #include <winerror.h>
38 #include <ndis.h>
39 #include "debug.h"
40 #include "packet.h"
41 #include <ntddpack.h>
42 #pragma VxD_LOCKED_CODE_SEG
43 #pragma VxD_LOCKED_DATA_SEG
44 DWORD _stdcall MyPageLock(DWORD, DWORD);
45 void _stdcall MyPageUnlock(DWORD, DWORD);
47 /************************************************************
48 Allocates the space for a packet, extracting it from the
49 buffer reserved for the driver
50 ************************************************************/
51 VOID
52 PacketAllocatePacketBuffer( PNDIS_STATUS pStatus,
53 POPEN_INSTANCE pOpen,
54 PNDIS_PACKET *lplpPacket,
55 PDIOCPARAMETERS pDiocParms,
56 DWORD FunctionCode )
58 PNDIS_BUFFER pNdisBuffer;
59 PPACKET_RESERVED pReserved;
62 TRACE_ENTER( "PacketAllocatePacket" );
63 NdisAllocatePacket( pStatus, lplpPacket, pOpen->PacketPool );
64 if ( *pStatus != NDIS_STATUS_SUCCESS )
66 IF_VERY_LOUD( "Read- No free packets" );
67 *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
68 return;
70 InitializeListHead( &(RESERVED(*lplpPacket)->ListElement) );
71 pReserved = RESERVED(*lplpPacket);
72 switch ( FunctionCode )
74 case IOCTL_PROTOCOL_READ:
75 pReserved->lpBuffer = (PVOID)PacketPageLock( (PVOID)pDiocParms->lpvOutBuffer,
76 pDiocParms->cbOutBuffer );
77 pReserved->cbBuffer = pDiocParms->cbOutBuffer;
78 break;
79 case IOCTL_PROTOCOL_WRITE:
80 pReserved->lpBuffer = (PVOID)PacketPageLock( pDiocParms->lpvInBuffer,
81 pDiocParms->cbInBuffer );
82 pReserved->cbBuffer = pDiocParms->cbInBuffer;
83 break;
84 default:
85 /*function not valid, free the resource*/
86 IF_TRACE_MSG( "Allocate- Invalid FunctionCode %x", FunctionCode );
87 NdisReinitializePacket( *lplpPacket );
88 NdisFreePacket( *lplpPacket );
89 *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
90 *pStatus = NDIS_STATUS_NOT_ACCEPTED;
91 return;
93 pReserved->lpcbBytesReturned =
94 (PVOID)PacketPageLock( (PVOID)pDiocParms->lpcbBytesReturned, sizeof(DWORD) );
95 pReserved->lpoOverlapped =
97 (PVOID)PacketPageLock( (PVOID)pDiocParms->lpoOverlapped, sizeof(OVERLAPPED) );
99 NdisAllocateBuffer( pStatus,
100 &pNdisBuffer,
101 pOpen->BufferPool,
102 (PVOID)pReserved->lpBuffer,
103 pDiocParms->cbOutBuffer );
104 if ( *pStatus != NDIS_STATUS_SUCCESS )
106 IF_TRACE( "Read- No free buffers" );
107 NdisReinitializePacket(*lplpPacket);
108 NdisFreePacket(*lplpPacket);
109 *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
110 return;
112 NdisChainBufferAtFront( *lplpPacket, pNdisBuffer );
113 IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD )
115 IF_TRACE_MSG( " lplpPacket : %lx", lplpPacket );
116 IF_TRACE_MSG( " lpPacket : %lx", *lplpPacket );
117 IF_TRACE_MSG3( "pNdisBuffer : %lx %lx %lx", pNdisBuffer, (*lplpPacket)->Private.Head, (*lplpPacket)->Private.Tail );
118 IF_TRACE_MSG( " Reserved : %lx", pReserved );
119 IF_TRACE_MSG4( " lpBuffer : %lx %lx %lx %lx", pReserved->lpBuffer, pNdisBuffer->VirtualAddress, pDiocParms->lpvOutBuffer, pDiocParms->lpvInBuffer );
120 IF_TRACE_MSG3( " cbBuffer : %lx %lx %lx", pReserved->cbBuffer, pDiocParms->cbOutBuffer, pDiocParms->cbInBuffer );
121 IF_TRACE_MSG2( " lpcbBytes : %lx %lx", pReserved->lpcbBytesReturned, pDiocParms->lpcbBytesReturned );
122 IF_TRACE_MSG2( " lpoOverlap : %lx %lx", pReserved->lpoOverlapped, pDiocParms->lpoOverlapped );
124 PACKETASSERT( pReserved->lpBuffer );
125 PACKETASSERT( pReserved->cbBuffer );
126 PACKETASSERT( pReserved->lpcbBytesReturned );
127 PACKETASSERT( pReserved->lpoOverlapped );
128 PACKETASSERT( pNdisBuffer == (*lplpPacket)->Private.Head );
129 PACKETASSERT( pNdisBuffer->VirtualAddress == pReserved->lpBuffer );
130 TRACE_LEAVE( "PacketAllocatePacket" );
131 return;
134 /************************************************************
135 Move a portion of the circular buffer
136 updating the head every 1024 bytes
137 ************************************************************/
139 void PacketMoveMem(PVOID Destination,
140 PVOID Source,
141 ULONG Length,
142 UINT *Bhead)
144 ULONG WordLength;
145 UINT n,i,NBlocks;
147 WordLength=Length>>2;
148 NBlocks=WordLength>>8;
150 for(n=0;n<NBlocks;n++){
151 for(i=0;i<256;i++){
152 *((PULONG)Destination)++=*((PULONG)Source)++;
154 *Bhead+=1024;
157 n=WordLength-(NBlocks<<8);
158 for(i=0;i<n;i++){
159 *((PULONG)Destination)++=*((PULONG)Source)++;
161 *Bhead+=n<<2;
163 n=Length-(WordLength<<2);
164 for(i=0;i<n;i++){
165 *((PUCHAR)Destination)++=*((PUCHAR)Source)++;
167 *Bhead+=n;
170 /************************************************************
171 Start a read
172 ************************************************************/
173 DWORD
174 PacketRead( POPEN_INSTANCE Open,
175 DWORD dwDDB,
176 DWORD hDevice,
177 PDIOCPARAMETERS pDiocParms
180 NDIS_STATUS Status;
181 PNDIS_PACKET pPacket;
182 PUCHAR packp;//buffer that maps the application memory
183 UINT i;
184 ULONG Input_Buffer_Length;
185 UINT Thead;
186 UINT Ttail;
187 UINT TLastByte;
188 PUCHAR CurrBuff;
189 UINT cplen;
190 UINT CpStart;
191 DWORD TEvent;
194 TRACE_ENTER( "PacketRead" );
195 if ( pDiocParms->cbOutBuffer < ETHERNET_HEADER_LENGTH )
197 /*the application's buffer if too small to contain the packet*/
198 *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
199 IF_VERY_LOUD( "Read- Buffer too small" );
200 TRACE_LEAVE( "ReadPacket" );
201 return NDIS_STATUS_FAILURE;
204 /*See if there are packets in the buffer*/
206 Thead=Open->Bhead;
207 Ttail=Open->Btail;
208 TLastByte=Open->BLastByte;
210 if (Thead == Ttail)
213 /*there aren't buffered packet but there is no timeout */
214 if(Open->TimeOut == -1){
215 *(DWORD *)(pDiocParms->lpcbBytesReturned)=0;
216 return(NDIS_STATUS_SUCCESS);
219 /*there aren't buffered packet and there is a timeout: the application must wait*/
220 PacketAllocatePacketBuffer( &Status, Open, &pPacket, pDiocParms, IOCTL_PROTOCOL_READ );
221 if ( Status == NDIS_STATUS_SUCCESS )
223 PACKETASSERT( Open != NULL );
224 PACKETASSERT( pPacket != NULL );
226 NdisAcquireSpinLock( &Open->RcvQSpinLock );
227 InsertTailList( &Open->RcvList, &RESERVED(pPacket)->ListElement );
228 NdisReleaseSpinLock( &Open->RcvQSpinLock );
230 /*set the timeout on the read*/
231 Open->ReadTimeoutTimer=SetReadTimeOut(ReadTimeout,Open->TimeOut,Open);
233 IF_TRACE_MSG2( "RcvList Link : %lx %lx", Open->RcvList.Blink, &RESERVED(pPacket)->ListElement );
234 PACKETASSERT( Open->RcvList.Blink == &RESERVED(pPacket)->ListElement );
235 PACKETASSERT( &(Open->RcvList) == RESERVED(pPacket)->ListElement.Flink );
238 TRACE_LEAVE( "PacketRead" );
239 return(-1); /*Communicate that the operation is asynchronous*/
242 /*there is at least a buffered packet: the read call can be completed*/
244 Input_Buffer_Length=pDiocParms->cbOutBuffer;
245 packp=(PUCHAR)pDiocParms->lpvOutBuffer;
246 i=0;
247 /*get the address of the buffer*/
248 CurrBuff=Open->Buffer;
250 /*fill the application buffer*/
252 /*first of all see if it we can copy all the buffer in one time*/
253 if(Ttail>Thead){
254 if((Ttail-Thead)<Input_Buffer_Length){
255 PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
256 *(DWORD *)(pDiocParms->lpcbBytesReturned)=Ttail-Thead;
258 // The buffer is empty: reset the read event
259 TEvent=Open->ReadEvent;
260 _asm mov eax,TEvent;
261 VxDCall(_VWIN32_ResetWin32Event);
263 return(NDIS_STATUS_SUCCESS);
266 else if((TLastByte-Thead)<Input_Buffer_Length){
267 PacketMoveMem(packp,CurrBuff+Thead,TLastByte-Thead,&(Open->Bhead));
268 Open->BLastByte=Ttail;
269 Open->Bhead=0;
270 *(DWORD *)(pDiocParms->lpcbBytesReturned)=TLastByte-Thead;
271 return(NDIS_STATUS_SUCCESS);
274 /*scan the buffer*/
275 CpStart=Thead;
276 while(TRUE){
277 if(Thead==Ttail)break;
278 if(Thead==TLastByte){
279 PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead));
280 packp+=(Thead-CpStart);
281 Open->Bhead=0;
282 Thead=0;
283 CpStart=0;
285 cplen=((struct bpf_hdr*)(CurrBuff+Thead))->bh_caplen+sizeof(struct bpf_hdr);
286 if((i+cplen > Input_Buffer_Length))break; //no more space in the application buffer
287 cplen=Packet_WORDALIGN(cplen);
288 i+=cplen;
289 Thead+=cplen;
292 PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead));
294 *(DWORD *)(pDiocParms->lpcbBytesReturned)=i;
295 return(NDIS_STATUS_SUCCESS);
299 /************************************************************
300 Callback routine called by NDIS when the adapter receives a
301 packet
302 ************************************************************/
303 NDIS_STATUS NDIS_API
304 Packet_tap ( IN NDIS_HANDLE ProtocolBindingContext,
305 IN NDIS_HANDLE MacReceiveContext,
306 IN PVOID pvHeaderBuffer,
307 IN UINT uiHeaderBufferSize,
308 IN PVOID pvLookAheadBuffer,
309 IN UINT uiLookaheadBufferSize,
310 IN UINT uiPacketSize
312 #define pOpen ((POPEN_INSTANCE)ProtocolBindingContext)
314 PLIST_ENTRY PacketListEntry;
315 PNDIS_PACKET pPacket;
316 ULONG ulSizeToTransfer;
317 NDIS_STATUS Status;
318 UINT uiBytesTransferred;
319 PPACKET_RESERVED pReserved;
320 PNDIS_BUFFER pNdisBuffer;
321 PVOID pvActualVirtualAddress;
322 UINT uiActualLength;
323 PUCHAR CurrBuff;
324 UINT Thead;
325 UINT Ttail;
326 UINT TLastByte;
327 PNDIS_PACKET pPacketb;
328 struct bpf_hdr *header;
329 LARGE_INTEGER CapTime;
330 __int64 lCapTime;
331 UINT fres; //filter result
332 UINT maxbufspace;
333 UINT to;
334 DWORD TEvent;
336 TRACE_ENTER( "Packet_tap" );
338 PACKETASSERT( (pOpen != NULL) );
341 pOpen->Received++; /*number of packets received by filter ++*/
344 Check if the lookahead buffer follows the mac header.
345 If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
346 executed on the packet.
347 Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
348 stuff like this) bpf_filter_with_2_buffers() is executed.
351 if((int)pvLookAheadBuffer-(int)pvHeaderBuffer != uiHeaderBufferSize)
352 fres=bpf_filter_with_2_buffers((struct bpf_insn*)(pOpen->bpfprogram),
353 pvHeaderBuffer,
354 pvLookAheadBuffer,
355 uiHeaderBufferSize,
356 uiPacketSize+uiHeaderBufferSize,
357 uiLookaheadBufferSize+uiHeaderBufferSize);
358 else
359 fres=bpf_filter((struct bpf_insn*)(pOpen->bpfprogram),
360 pvHeaderBuffer,
361 uiPacketSize+uiHeaderBufferSize,
362 uiLookaheadBufferSize+uiHeaderBufferSize);
364 if(fres==0)return NDIS_STATUS_NOT_ACCEPTED;
365 if( fres==-1)fres=uiPacketSize+uiHeaderBufferSize; //if the filter returns -1 the whole packet must be accepted
368 if(pOpen->mode==1){
369 /*statistics mode*/
370 NdisAcquireSpinLock( &pOpen->CountersLock );
372 pOpen->Npackets++;
374 if(uiPacketSize+uiHeaderBufferSize<60)
375 pOpen->Nbytes+=60;
376 else
377 pOpen->Nbytes+=uiPacketSize+uiHeaderBufferSize;
379 /*add preamble+SFD+FCS to the packet
380 these values must be considered because are not part of the packet received from NDIS*/
381 pOpen->Nbytes+=12;
383 NdisReleaseSpinLock( &pOpen->CountersLock );
385 return NDIS_STATUS_NOT_ACCEPTED; //it should be quicker
389 /*see if there are pending requests*/
390 NdisAcquireSpinLock( &pOpen->RcvQSpinLock );
391 PacketListEntry = PacketRemoveHeadList( &pOpen->RcvList );
392 NdisReleaseSpinLock( &pOpen->RcvQSpinLock );
394 if ( PacketListEntry == NULL )
396 /*no requests. This means that the application is not performing a read in this
397 moment: the packet must go in the buffer*/
399 TRACE_ENTER( "IndicateReceive" );
401 if(pOpen->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
403 Thead=pOpen->Bhead;
404 Ttail=pOpen->Btail;
405 TLastByte=pOpen->BLastByte;
408 maxbufspace=fres+sizeof(struct bpf_hdr);
409 if(Ttail+maxbufspace>=pOpen->BufSize){
410 if(Thead<=maxbufspace)
412 /*the buffer is full: the packet is lost*/
413 pOpen->Dropped++;
414 return NDIS_STATUS_NOT_ACCEPTED;
416 else{
417 Ttail=0;
421 if((Ttail<Thead)&&(Ttail+maxbufspace>=Thead))
423 /*the buffer is full: the packet is lost*/
424 pOpen->Dropped++;
425 return NDIS_STATUS_NOT_ACCEPTED;
427 CurrBuff=pOpen->Buffer+Ttail;
430 /*allocate the ndis buffer*/
431 NdisAllocateBuffer( &Status,
432 &pNdisBuffer,
433 pOpen->BufferPool,
434 CurrBuff+sizeof(struct bpf_hdr),
435 fres);
437 if (Status != NDIS_STATUS_SUCCESS)
439 pOpen->Dropped++;
440 return NDIS_STATUS_NOT_ACCEPTED;
443 /*allocate the packet from NDIS*/
444 NdisAllocatePacket(&Status,&pPacketb,pOpen->PacketPool);
445 if (Status != NDIS_STATUS_SUCCESS)
447 NdisFreeBuffer( pNdisBuffer );
448 pOpen->Dropped++;
449 return NDIS_STATUS_NOT_ACCEPTED;
451 /*link the buffer to the packet*/
452 NdisChainBufferAtFront(pPacketb,pNdisBuffer);
454 if ( uiHeaderBufferSize > 0 )
456 if ( uiHeaderBufferSize > pNdisBuffer->Length )
457 uiHeaderBufferSize = pNdisBuffer->Length;
458 /*copy the header*/
459 NdisMoveMemory(pNdisBuffer->VirtualAddress, pvHeaderBuffer, uiHeaderBufferSize );
460 uiBytesTransferred = uiHeaderBufferSize;
461 (BYTE *)(pNdisBuffer->VirtualAddress) += uiHeaderBufferSize;
462 pNdisBuffer->Length -= uiHeaderBufferSize;
465 ulSizeToTransfer = uiPacketSize;
466 if ( ulSizeToTransfer > pNdisBuffer->Length )
467 ulSizeToTransfer = pNdisBuffer->Length;
469 /*Copy the remaining part of the packet*/
470 NdisTransferData( &Status,
471 pOpen->AdapterHandle,
472 MacReceiveContext,
474 ulSizeToTransfer,
475 pPacketb,
476 &uiBytesTransferred );
478 uiBytesTransferred+=uiHeaderBufferSize;
481 /*get the capture time*/
482 lCapTime=QuerySystemTime();
484 /*fill the bpf header for this packet*/
485 if( fres>uiBytesTransferred )fres=uiBytesTransferred;
486 lCapTime+=pOpen->StartTime;
487 header=(struct bpf_hdr*)CurrBuff;
488 header->bh_tstamp.tv_usec=(long)((lCapTime%1193182)*1000000/1193182);
489 header->bh_tstamp.tv_sec=(long)((lCapTime)/1193182);
490 header->bh_caplen=(UINT)fres;
491 header->bh_datalen=(UINT)uiPacketSize+uiHeaderBufferSize;
492 header->bh_hdrlen=sizeof(struct bpf_hdr);
494 /*update the buffer*/
495 Ttail+=Packet_WORDALIGN(fres+sizeof(struct bpf_hdr));
496 if(Ttail>Thead)TLastByte=Ttail;
497 pOpen->Btail=Ttail;
498 pOpen->BLastByte=TLastByte;
500 /*free the allocated buffer*/
501 NdisFreeBuffer( pNdisBuffer );
502 /*recylcle the packet*/
503 NdisReinitializePacket(pPacketb);
504 /*Put the packet on the free queue*/
505 NdisFreePacket(pPacketb);
507 TEvent=pOpen->ReadEvent;
508 _asm mov eax,TEvent;
509 VxDCall(_VWIN32_SetWin32Event);
511 TRACE_LEAVE( "Packet_tap" );
512 return NDIS_STATUS_SUCCESS;
517 /*cancel the timeout on this read call*/
518 to=pOpen->ReadTimeoutTimer;
519 _asm push esi;
520 _asm mov esi,to;
521 CancelReadTimeOut();
522 _asm pop esi;
523 pOpen->ReadTimeoutTimer=0;
526 pReserved = CONTAINING_RECORD( PacketListEntry, PACKET_RESERVED, ListElement );
527 pPacket = CONTAINING_RECORD( pReserved, NDIS_PACKET, ProtocolReserved );
528 IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD )
530 IF_TRACE_MSG( " Reserved : %lx", pReserved );
531 IF_TRACE_MSG( " pPacket : %lx", pPacket );
532 IF_TRACE_MSG2( " Header : %lx %lx", pvHeaderBuffer, uiHeaderBufferSize );
533 IF_TRACE_MSG2( " LookAhead : %lx %lx", pvLookAheadBuffer, uiLookaheadBufferSize );
534 IF_TRACE_MSG( " PacketSize : %lx", uiPacketSize );
536 PACKETASSERT( (pReserved != NULL) );
537 PACKETASSERT( (pPacket != NULL) );
539 pNdisBuffer = pPacket->Private.Head;
540 /*virtual address of the buffer that will contain the packet*/
541 pvActualVirtualAddress = pNdisBuffer->VirtualAddress;
542 uiActualLength = pNdisBuffer->Length;
544 CurrBuff=pNdisBuffer->VirtualAddress;
545 (BYTE *)(pNdisBuffer->VirtualAddress) += sizeof(struct bpf_hdr);
548 if ( uiHeaderBufferSize > 0 )
550 if ( uiHeaderBufferSize > pNdisBuffer->Length )
551 uiHeaderBufferSize = pNdisBuffer->Length;
552 /*copy the header*/
553 NdisMoveMemory(pNdisBuffer->VirtualAddress, pvHeaderBuffer, uiHeaderBufferSize );
554 uiBytesTransferred = uiHeaderBufferSize;
555 (BYTE *)(pNdisBuffer->VirtualAddress) += uiHeaderBufferSize;
556 pNdisBuffer->Length -= uiHeaderBufferSize;
559 ulSizeToTransfer = uiPacketSize/*uiPacketSize - uiLookaheadBufferSize*/;
560 if ( ulSizeToTransfer > pNdisBuffer->Length )
561 ulSizeToTransfer = pNdisBuffer->Length;
563 /*Copy the remaining part of the packet*/
564 NdisTransferData( &Status,
565 pOpen->AdapterHandle,
566 MacReceiveContext,
568 ulSizeToTransfer,
569 pPacket,
570 &uiBytesTransferred );
572 uiBytesTransferred+=uiHeaderBufferSize;
575 pNdisBuffer->VirtualAddress = pvActualVirtualAddress;
576 pNdisBuffer->Length = uiActualLength;
577 if ( Status != NDIS_STATUS_PENDING )
580 /*store the capture time*/
581 lCapTime=QuerySystemTime();
583 /*fill the bpf header for this packet*/
584 if( fres>uiBytesTransferred )fres=uiBytesTransferred;
585 lCapTime+=pOpen->StartTime;
586 header=(struct bpf_hdr*)CurrBuff;
587 header->bh_tstamp.tv_usec=(long)((lCapTime%1193182)*1000000/1193182);
588 header->bh_tstamp.tv_sec=(long)((lCapTime)/1193182);
589 header->bh_caplen=(UINT)fres;
590 header->bh_datalen=(UINT)uiPacketSize+uiHeaderBufferSize;
591 header->bh_hdrlen=sizeof(struct bpf_hdr);
592 /*call the completion routine*/
593 PacketTransferDataComplete( pOpen,
594 pPacket,
595 Status,
596 fres);
599 else
601 Status = NDIS_STATUS_SUCCESS;
602 PacketTransferDataComplete( pOpen,
603 pPacket,
604 Status,
605 0 );
608 TRACE_LEAVE( "Packet_tap" );
609 return NDIS_STATUS_SUCCESS;
612 /*Ends the transfer started with the Packet_tap function*/
613 VOID NDIS_API
614 PacketTransferDataComplete ( IN NDIS_HANDLE ProtocolBindingContext,
615 IN PNDIS_PACKET pPacket,
616 IN NDIS_STATUS Status,
617 IN UINT uiBytesTransferred
620 PPACKET_RESERVED pReserved;
621 OVERLAPPED* pOverlap;
622 PNDIS_BUFFER pNdisBuffer;
623 TRACE_ENTER( "TransferDataComplete" );
624 pReserved = (PPACKET_RESERVED) pPacket->ProtocolReserved;
625 pOverlap = (OVERLAPPED *) pReserved->lpoOverlapped;
626 PACKETASSERT( (pOpen != NULL) );
627 PACKETASSERT( (pReserved != NULL) );
628 PACKETASSERT( (pOverlap != NULL) );
630 IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD )
632 IF_TRACE_MSG( " Status : %lx", Status );
633 IF_TRACE_MSG( "BytesXfered : %lx", uiBytesTransferred );
634 IF_TRACE_MSG( "Byte Offset : %lx", *(pReserved->lpcbBytesReturned) );
637 NdisUnchainBufferAtFront( pPacket, &pNdisBuffer );
638 PACKETASSERT( (pNdisBuffer != NULL) );
639 if ( pNdisBuffer )
640 NdisFreeBuffer( pNdisBuffer );
642 *(pReserved->lpcbBytesReturned) = uiBytesTransferred+sizeof(struct bpf_hdr);
643 pOverlap->O_InternalHigh = *(pReserved->lpcbBytesReturned);
644 /*wakes the application process*/
645 VWIN32_DIOCCompletionRoutine( pOverlap->O_Internal );
647 PacketPageUnlock( pReserved->lpBuffer, pReserved->cbBuffer );
648 PacketPageUnlock( pReserved->lpcbBytesReturned, sizeof(DWORD) );
649 PacketPageUnlock( pReserved->lpoOverlapped, sizeof(OVERLAPPED) );
651 NdisReinitializePacket( pPacket );
653 NdisFreePacket( pPacket );
654 TRACE_LEAVE( "TransferDataComplete" );
655 return;
658 VOID NDIS_API
659 PacketReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext )
661 IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD )
663 TRACE_ENTER( "ReceiveComplete" );
664 TRACE_LEAVE( "ReceiveComplete" );
666 return;
669 /************************************************************
670 Routine called by the kernel when the timeout set in the
671 PacketRead function expires
672 ************************************************************/
673 void _cdecl ReadTimeout(void)
675 POPEN_INSTANCE Open;
676 PLIST_ENTRY PacketListEntry;
677 PNDIS_PACKET pPacket;
678 PPACKET_RESERVED Reserved;
679 OVERLAPPED* pOverlap;
680 PNDIS_BUFFER pNdisBuffer;
681 PUCHAR CurrBuff;
682 struct bpf_hdr *header;
683 UINT to;
684 __int64 lCapTime;
686 //the parameter is in edx
687 _asm{
688 mov Open,edx
691 NdisAcquireSpinLock( &Open->RcvQSpinLock );
692 PacketListEntry = PacketRemoveHeadList( &Open->RcvList );
693 NdisReleaseSpinLock( &Open->RcvQSpinLock );
694 Open->ReadTimeoutTimer=0;
696 if (PacketListEntry == NULL)
698 return;
701 Reserved=CONTAINING_RECORD(PacketListEntry,PACKET_RESERVED,ListElement);
702 pPacket=CONTAINING_RECORD(Reserved,NDIS_PACKET,ProtocolReserved);
704 Reserved = (PPACKET_RESERVED) pPacket->ProtocolReserved;
705 pOverlap = (OVERLAPPED *) Reserved->lpoOverlapped;
707 if(Open->mode==1){
708 //count mode
709 pNdisBuffer = pPacket->Private.Head;
710 CurrBuff=pNdisBuffer->VirtualAddress;
712 /*get system time*/
713 lCapTime=QuerySystemTime();
714 /*fill the bpf header for this packet*/
715 lCapTime+=Open->StartTime;
716 header=(struct bpf_hdr*)CurrBuff;
717 header->bh_tstamp.tv_usec=(long)((lCapTime%1193182)*1000000/1193182);
718 header->bh_tstamp.tv_sec=(long)((lCapTime)/1193182);
719 header->bh_caplen=(UINT)16;
720 header->bh_datalen=(UINT)16;
721 header->bh_hdrlen=sizeof(struct bpf_hdr);
723 *(__int64*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets;
724 *(__int64*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes;
726 //reset the countetrs
727 Open->Npackets=0;
728 Open->Nbytes=0;
730 NdisUnchainBufferAtFront( pPacket, &pNdisBuffer );
731 if ( pNdisBuffer )
732 NdisFreeBuffer( pNdisBuffer );
734 *(Reserved->lpcbBytesReturned) = 16 + sizeof(struct bpf_hdr);
735 pOverlap->O_InternalHigh = 16 + sizeof(struct bpf_hdr);
736 VWIN32_DIOCCompletionRoutine( pOverlap->O_Internal );
738 PacketPageUnlock( Reserved->lpBuffer, Reserved->cbBuffer );
739 PacketPageUnlock( Reserved->lpcbBytesReturned, sizeof(DWORD) );
740 PacketPageUnlock( Reserved->lpoOverlapped, sizeof(OVERLAPPED) );
742 NdisReinitializePacket( pPacket );
744 NdisFreePacket( pPacket );
746 return;
749 NdisUnchainBufferAtFront( pPacket, &pNdisBuffer );
750 if ( pNdisBuffer )
751 NdisFreeBuffer( pNdisBuffer );
753 //wakes the application process
754 *(Reserved->lpcbBytesReturned) = 0;
755 pOverlap->O_InternalHigh = *(Reserved->lpcbBytesReturned);
757 VWIN32_DIOCCompletionRoutine( pOverlap->O_Internal );
759 PacketPageUnlock( Reserved->lpBuffer, Reserved->cbBuffer );
760 PacketPageUnlock( Reserved->lpcbBytesReturned, sizeof(DWORD) );
761 PacketPageUnlock( Reserved->lpoOverlapped, sizeof(OVERLAPPED) );
763 NdisReinitializePacket( pPacket );
765 NdisFreePacket( pPacket );
767 return;