Further information from our investigating developer:

I was finally able to download the latest sources of winpcap (see attached
file Read.c).
Everything about the DLL remains true, but the driver code seems to have
been fixed in a number of places.
So the scenario from the previous message will not fail just as it was
described because in the new source the order of 'free space' checks has
been corrected (Read.c, Packet_tap(), lines 351--368):
      New code:
   if((Ttail < Thead) && (Ttail+maxbufspace+1 >= Thead))
   {
    //the buffer is full: the incoming packet is lost
    Open->Dropped++;
    return NDIS_STATUS_NOT_ACCEPTED;
   }
   if(Ttail+maxbufspace >= Open->BufSize){
    if(Thead<=maxbufspace)
    {
     //the buffer is full: the packet is lost
     Open->Dropped++;
     return NDIS_STATUS_NOT_ACCEPTED;
    }
    else{
     Ttail=0;
    }
   }
  ---------------------------------------------
     Old Code:
   maxbufspace=fres+sizeof(struct bpf_hdr);
   if(Ttail+maxbufspace>=Open->BufSize){
    if(Thead<=maxbufspace)
    {
     //the buffer is full: the packet is lost
     Open->Dropped++;
     return NDIS_STATUS_NOT_ACCEPTED;
    }
    else{
     Ttail=0;
    }
   }

   if((Ttail<Thead)&&(Ttail+maxbufspace>=Thead))
   {
    //the buffer is full: the incoming packet is lost
    Open->Dropped++;
    return NDIS_STATUS_NOT_ACCEPTED;
   }

Nonetheless, it is still possible for the driver to get into an error prone
state.
Let's assume the buffer occupancy is:

  X X X X X X X X X * * * * * * * * * * X X X *
                    ^                   ^     ^
                    Bt                  Bh    Bl
where Bt = Btail, Bh = Bhead, Bl = BLastByte, X - occupied bytes, * - free
bytes.
If PacketRead and Packet_tap are called at the same time they retrieve those
pointers into each one's Txxx local variables.
Then PacketRead sends the wrapped portion of the buffer to the DLL while
Packet_tap appends a new packet to the buffer.
Assuming that PacketRead completes before Packet_tap, then Packet_tap moves
Btail forward and sets BLastByte to the old value because in its view head >
tail (lines 447--455):
  * * * * * * * * * Y Y Y Y Y Y Y Y Y * * * * *
                    ^                 ^       ^
                    Bh                Bt      Bl
where Y - new bytes.
Then another call to PacketRead sends the rest of data to the DLL but does
not change BLastByte (lines 189--196),
and a call to Packet_tap puts a new packet at the beginning of the buffer
(it does not fit at the end) but since again tail < head it does not change
BLastByte (line 450). The resulting buffer state is:
  X X X X X X * * * * * * * * * * * * * * * * *
              ^                       ^       ^
              Bt                      Bh      Bl
Now, if PacketRead is called it will read 'free' space, and chances are
garbage will be there.
As a summary I'd like to say that operations with BLastByte are not so
clear -- Packet_tap sets it after adding a packet to the buffer, while it
seems it should set BLastByte when the buffer wraps.

I hope the assumptions I made are correct.

Attachment: Read.c
Description: Binary data

Reply via email to