2 * Copyright (c) 1999 - 2003
3 * NetGroup, Politecnico di Torino (Italy)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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 ************************************************************/
52 PacketAllocatePacketBuffer( PNDIS_STATUS pStatus
,
54 PNDIS_PACKET
*lplpPacket
,
55 PDIOCPARAMETERS pDiocParms
,
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;
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
;
79 case IOCTL_PROTOCOL_WRITE
:
80 pReserved
->lpBuffer
= (PVOID
)PacketPageLock( pDiocParms
->lpvInBuffer
,
81 pDiocParms
->cbInBuffer
);
82 pReserved
->cbBuffer
= pDiocParms
->cbInBuffer
;
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
;
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
,
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;
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" );
134 /************************************************************
135 Move a portion of the circular buffer
136 updating the head every 1024 bytes
137 ************************************************************/
139 void PacketMoveMem(PVOID Destination
,
147 WordLength
=Length
>>2;
148 NBlocks
=WordLength
>>8;
150 for(n
=0;n
<NBlocks
;n
++){
152 *((PULONG
)Destination
)++=*((PULONG
)Source
)++;
157 n
=WordLength
-(NBlocks
<<8);
159 *((PULONG
)Destination
)++=*((PULONG
)Source
)++;
163 n
=Length
-(WordLength
<<2);
165 *((PUCHAR
)Destination
)++=*((PUCHAR
)Source
)++;
170 /************************************************************
172 ************************************************************/
174 PacketRead( POPEN_INSTANCE Open
,
177 PDIOCPARAMETERS pDiocParms
181 PNDIS_PACKET pPacket
;
182 PUCHAR packp
;//buffer that maps the application memory
184 ULONG Input_Buffer_Length
;
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*/
208 TLastByte
=Open
->BLastByte
;
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
;
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*/
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
;
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
;
270 *(DWORD
*)(pDiocParms
->lpcbBytesReturned
)=TLastByte
-Thead
;
271 return(NDIS_STATUS_SUCCESS
);
277 if(Thead
==Ttail
)break;
278 if(Thead
==TLastByte
){
279 PacketMoveMem(packp
,CurrBuff
+CpStart
,Thead
-CpStart
,&(Open
->Bhead
));
280 packp
+=(Thead
-CpStart
);
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
);
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
302 ************************************************************/
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
,
312 #define pOpen ((POPEN_INSTANCE)ProtocolBindingContext)
314 PLIST_ENTRY PacketListEntry
;
315 PNDIS_PACKET pPacket
;
316 ULONG ulSizeToTransfer
;
318 UINT uiBytesTransferred
;
319 PPACKET_RESERVED pReserved
;
320 PNDIS_BUFFER pNdisBuffer
;
321 PVOID pvActualVirtualAddress
;
327 PNDIS_PACKET pPacketb
;
328 struct bpf_hdr
*header
;
329 LARGE_INTEGER CapTime
;
331 UINT fres
; //filter result
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
),
356 uiPacketSize
+uiHeaderBufferSize
,
357 uiLookaheadBufferSize
+uiHeaderBufferSize
);
359 fres
=bpf_filter((struct bpf_insn
*)(pOpen
->bpfprogram
),
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
370 NdisAcquireSpinLock( &pOpen
->CountersLock
);
374 if(uiPacketSize
+uiHeaderBufferSize
<60)
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*/
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
;
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*/
414 return NDIS_STATUS_NOT_ACCEPTED
;
421 if((Ttail
<Thead
)&&(Ttail
+maxbufspace
>=Thead
))
423 /*the buffer is full: the packet is lost*/
425 return NDIS_STATUS_NOT_ACCEPTED
;
427 CurrBuff
=pOpen
->Buffer
+Ttail
;
430 /*allocate the ndis buffer*/
431 NdisAllocateBuffer( &Status
,
434 CurrBuff
+sizeof(struct bpf_hdr
),
437 if (Status
!= NDIS_STATUS_SUCCESS
)
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
);
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
;
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
,
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
;
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
;
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
;
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
;
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
,
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
,
601 Status
= NDIS_STATUS_SUCCESS
;
602 PacketTransferDataComplete( pOpen
,
608 TRACE_LEAVE( "Packet_tap" );
609 return NDIS_STATUS_SUCCESS
;
612 /*Ends the transfer started with the Packet_tap function*/
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
) );
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" );
659 PacketReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext
)
661 IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD
)
663 TRACE_ENTER( "ReceiveComplete" );
664 TRACE_LEAVE( "ReceiveComplete" );
669 /************************************************************
670 Routine called by the kernel when the timeout set in the
671 PacketRead function expires
672 ************************************************************/
673 void _cdecl
ReadTimeout(void)
676 PLIST_ENTRY PacketListEntry
;
677 PNDIS_PACKET pPacket
;
678 PPACKET_RESERVED Reserved
;
679 OVERLAPPED
* pOverlap
;
680 PNDIS_BUFFER pNdisBuffer
;
682 struct bpf_hdr
*header
;
686 //the parameter is in edx
691 NdisAcquireSpinLock( &Open
->RcvQSpinLock
);
692 PacketListEntry
= PacketRemoveHeadList( &Open
->RcvList
);
693 NdisReleaseSpinLock( &Open
->RcvQSpinLock
);
694 Open
->ReadTimeoutTimer
=0;
696 if (PacketListEntry
== NULL
)
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
;
709 pNdisBuffer
= pPacket
->Private
.Head
;
710 CurrBuff
=pNdisBuffer
->VirtualAddress
;
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
730 NdisUnchainBufferAtFront( pPacket
, &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
);
749 NdisUnchainBufferAtFront( pPacket
, &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
);