Inspecting NDIS 6 NB
Packet Headers

Introduction

Often the task to be performed in a NDIS 6 filter or protocol driver is to inspect the packet headers in NBs passed to the send or receive callback. In NDIS 6 Microsoft has defined some rules and provided support functions that make inspection easy and efficient (without requiring any copies...).

Here are the keys to understanding how to inspect NDIS 6 NB headers:

bulletNDIS 6 requires that each header structure reside as a contiguous array of bytes in one MDL.
bulletIP option or extension headers are separate headers and may or may not reside in the same MDL as an IP header.
bulletThe NDIS 6 NdisGetDataBuffer function provides access to any contiguous block of data from a NET_BUFFER structure.
bulletThe NDIS 6 Ndis(Advance/Retreat)NetBufferDataStart functions are used to move the start offset used by NdisGetDataBuffer,

A new developer may want to make dangerous assumptions about where headers begin or end in a NB. For example, a developer may note that in receive callbacks there is one one MDL in each NB. This isn't always the case. Don't make any assumption that isn't backed up by Microsoft documentation.

Of course you will need header structure definitions that match the headers that you are interested in inspecting. You'll have to define your own header structures or adopt definitions from an open source such as BSD Unix. Some skeleton structure definitions are provided here.

 

Example Packet Header Inspection

This example will inspect the Ethernet and IPv4 header of an NB. In your inspection function declare a few variables:

PNDF__ETH_HEADER pEthHeader;

PNDF_IPV4_HEADER pIPv4Header;

ULONG DataOffset = 0;

First fetch the Ethernet header:

// Fetch Ethernet Header

pEthHeader = (PNDF_ETH_HEADER )NdisGetDataBuffer(

                NetBuffer,

                                sizeof( NDF_ETH_HEADER ),

                NULL, // No storage provided or needed

                1, // No alignment requirement

                0

                );

Now you can examine the Ethernet header. It may be an IPv4 header. If so, then fetch the IPv4 header this way:

if( pEthHeader->EthType == RtlUShortByteSwap( ETHERTYPE_IP ) )

{

    // Move DataStart to Start of Outer IPv4 Header

    NdisAdvanceNetBufferDataStart( NetBuffer, sizeof( NDF_ETH_HEADER ), FALSE, NULL );

    DataOffset = sizeof( NDF_ETH_HEADER );

// Fetch IPv4 Header

pIPv4Header= (PNDF_IPV4_HEADER )NdisGetDataBuffer(

                NetBuffer,

                sizeof( NDF_IPV4_HEADER ),

                NULL, // No storage provided or needed

                1, // No alignment requirement

                0

                );

}

At this point you can examine the IPv4 header.

If the offset field in the IPv4 header is zero, then the TCP or UDP headers may be present. You can advance data start by the size of the IPv4 header and then use NdisGetDataPointer to fetch pointers to these headers using the same methodology.

Do keep careful track of DataOffset. When you are done you MUST retreat data start by the same amount that you advanced it:

NdisRetreatNetBufferDataStart( NetBuffer, DataOffset, 0, NULL );

I hope that this is helpful to some of you.

 

Topic Status

August 14, 2011 Information posted.
 

PCAUSA Home · Privacy Statement · Products · Ordering · Support · Utilities · Resources
Mailing Lists  · PCAUSA Newsletter · PCAUSA Discussion List
Rawether for Windows, Rawether .NET, WinDis 32 and NDIS Press are trademarks of Printing Communications Assoc., Inc. (PCAUSA)
Microsoft, MS, Windows, Windows Vista, Windows 95, Windows 98, Windows Millennium, Windows 2000, and Win32 are registered trademarks and Visual C++ and Windows NT are trademarks of the Microsoft Corporation.
Copyright © 1996-2012 Printing Communications Assoc., Inc. (PCAUSA)
Last modified: January 01, 2012