<div dir="ltr">Hi Guy,<div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 9, 2015 at 6:25 PM, Guy Harris <span dir="ltr"><<a href="mailto:guy@alum.mit.edu" target="_blank">guy@alum.mit.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class=""><br>
On Sep 8, 2015, at 7:45 PM, 食肉大灰兔V5 <<a href="mailto:hsluoyz@gmail.com">hsluoyz@gmail.com</a>> wrote:<br>
<br>
> On Wed, Sep 9, 2015 at 8:12 AM, Guy Harris <<a href="mailto:guy@alum.mit.edu">guy@alum.mit.edu</a>> wrote:<br>
><br>
>> 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.<br>
><br>
> 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 <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff563246(v=vs.85).aspx" rel="noreferrer" target="_blank">https://msdn.microsoft.com/en-us/library/windows/hardware/ff563246(v=vs.85).aspx</a>).<br>
<br>
</span>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.<br></blockquote><div><br></div><div>OK. I thought LookaheadBuffer will always start from the end of HeaderBuffer before this post. I looked twice at the MSDN and found Microsoft never promised this assumption in NDIS 5, so it's reasonable for WinPcap to split this into 2 conditions. Although for NDIS 6, **usually** MAC, IP and TCP headers are carried in the same buffer (I confirmed this in Npcap, also see the figure in: <a href="http://codemachine.com/article_ndis6nbls.html">http://codemachine.com/article_ndis6nbls.html</a>), but Microsoft never guarantees it.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Apparently OpenVPN has both NDIS 5 and NDIS 6 drivers:<br>
<br>
        <a href="https://community.openvpn.net/openvpn/wiki/CodeRepositories" rel="noreferrer" target="_blank">https://community.openvpn.net/openvpn/wiki/CodeRepositories</a><br>
<br>
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.<br></blockquote><div><br></div><div>I have a glance at the repo, and I think the NDIS 6 version OpenVPN driver is a NDIS 6 miniport. A miniport is really far away with a protocol (NDIS 5 or 6) (see: <a href="http://stackoverflow.com/questions/18257048/ndis-filter-driver-filterreceivenetbufferlists-handler-isnt-called?noredirect=1#comment27011779_18257048">http://stackoverflow.com/questions/18257048/ndis-filter-driver-filterreceivenetbufferlists-handler-isnt-called?noredirect=1#comment27011779_18257048</a>). So it's weird that OpenVPN could affect the WinPcap driver. A miniport should be transparent to a protocol.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span class=""><br>
> 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).<br>
<br>
</span>I think what it's doing is clearer if it's written as<br>
<br>
        if((PUCHAR)LookaheadBuffer != ((PUCHAR)HeaderBuffer)+HeaderBufferSize)<br>
<br>
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:<br>
<br>
        //<br>
        //Check if the lookahead buffer follows the mac header.<br>
        //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is<br>
        //executed on the packet.<br>
        //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or<br>
        //things like this) bpf_filter_with_2_buffers() is executed.<br>
        //<br>
<span class=""><br>
> I think the caller of ProtocolReceive routine only guarantees that the HeaderBuffer and LookaheadBuffer together cover till the TCP header.<br>
<br>
</span>Meaning that they will cover the TCP header, or that they only guarantee that the stuff *before* the TCP header is provided?<br></blockquote><div><br></div><div>Sorry for my english, which I mean NDIS will guarantee the TCP header is contained in LookaheadBuffer (see: <a href="http://www.verycomputer.com/5_8593f09f8b078987_1.htm">http://www.verycomputer.com/5_8593f09f8b078987_1.htm</a>)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
If it's the latter, then:<br>
<span class=""><br>
> So it's enough to make a decision for a BPF filter.<br>
<br>
</span>...that's not enough for a BPF filter such as "tcp port 80" that tests fields in the TCP header.<br>
<br>
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".<br></blockquote><div><br></div><div>You are right, if an application layer filter (like HTTP or FTP) is set, I don't think the current WinPcap implementation will function well, as I didn't see any Microsoft document said they will promise the length of LookaheadBuffer up to application layer. So WinPcap's PacketTransferDataComplete should also do some kind of BPF filter work if NPF_Tap's filter fails with inadequate buffer length.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
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.<br></blockquote><div><br></div><div>Possible.</div><div><br></div><div> </div><div>Cheers,</div><div>Yang</div></div></div></div>