[Winpcap-users] Is an NDIS 5 PacketReceive routine guaranteed to be handed the *full* packet on a system using NDIS 5?

Guy Harris guy at alum.mit.edu
Wed Sep 9 10:25:58 UTC 2015


On Sep 8, 2015, at 7:45 PM, 食肉大灰兔V5 <hsluoyz at gmail.com> wrote:

> On Wed, Sep 9, 2015 at 8:12 AM, Guy Harris <guy at alum.mit.edu> wrote:
> 
>> In NPF_tap(), the BPF filter routine is called only with data from the header buffer (HeaderBuffer) if the difference between LookaheadBuffer and HeaderBuffer is equal to HeaderBufferSize (this appears to assume that the packet will be contained in a single buffer in this case, and that the header buffer contains the entire packet), and, otherwise, called with data from the header buffer and the lookahead buffer.
> 
> In fact, I didn't quite understand this part when I am doing the porting job to NDIS 6. AFAIK, like for an Ethernet packet, HeaderBuffer is the Ethernet header data, and LookaheadBuffer is the data beginning from IP header. If PacketSize is less than or equal to the given LookaheadBufferSize, the lookahead buffer contains the entire packet (see https://msdn.microsoft.com/en-us/library/windows/hardware/ff563246(v=vs.85).aspx).

That's the NDIS 5 version of the documentation for the PacketReceive function.  It would be an ugly incompatibility if NDIS 6's NDIS 5 shims didn't preserve that behavior, but it's possible that it does.

Apparently OpenVPN has both NDIS 5 and NDIS 6 drivers:

	https://community.openvpn.net/openvpn/wiki/CodeRepositories

I'm guessing that the NDIS 6 driver is being used on his Windows 10 system; perhaps it does something that the NDIS 6 -> NDIS 5 shim doesn't handle correctly.

> I don't know why there is a compare between LookaheadBuffer - HeaderBuffer with HeaderBufferSize. HeaderBuffer can't contain the entire packet (as there won't be a packet with only Ethernet header and have no content).

I think what it's doing is clearer if it's written as

	if((PUCHAR)LookaheadBuffer != ((PUCHAR)HeaderBuffer)+HeaderBufferSize)

which tests whether the lookahead buffer begins immediately after the end of the header buffer, i.e. that there's really only one buffer; the comment before it indicates that:

	//
	//Check if the lookahead buffer follows the mac header.
	//If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
	//executed on the packet.
	//Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
	//things like this) bpf_filter_with_2_buffers() is executed.
	//

> I think the caller of ProtocolReceive routine only guarantees that the HeaderBuffer and LookaheadBuffer together cover till the TCP header.

Meaning that they will cover the TCP header, or that they only guarantee that the stuff *before* the TCP header is provided?

If it's the latter, then:

> So it's enough to make a decision for a BPF filter.

...that's not enough for a BPF filter such as "tcp port 80" that tests fields in the TCP header.

If it's the former, even that's not enough for BPF filters that explicitly test past the end of the TCP header, which *is* possible, and even supported by the libpcap filter language by using the general expression mechanism.  But that wouldn't cause a problem with "tcp port 80".

I suspect that the NDIS 6 -> NDIS 5 shim in Windows 10 might not be handling packets provided by the OpenVPN driver - perhaps that driver is providing packets in a form that the shim can't properly map to something to hand to an NDIS 5 protocol driver like the WinPcap driver; Npcap is an NDIS 6 driver, so the shim isn't in the way.


More information about the Winpcap-users mailing list