WinDis 32 Berkeley Packet Filter (BPF) Programming

 

Knowledge Base ID

KB11039904
Category INFORMATION

Effected Product

Rawether/WINDIS32  - Win32 NDIS Framework

Effected Versions

All
Effected Platforms Windows 95, Windows 98, Windows Millennium, Windows NT 4.0, Windows 2000

 

Remarks

Several PCAUSA customers have asked for additional information concerning development of BPF programs. Unfortunately, there is not a lot of additional information available.

This PCAUSA KB Article attempts to provide a little more information.

 

Additional BPF Program Fragments

The BPF Samples file contains some additional BPF program fragments.

 

Building BPF programs

The BPF mechanism is extremely useful. However, it is a little difficult to understand.

Most of the information about programming the BPF is contained these documents:

bulletThe paper "The BSD Packet Filter: A New Architecture for User-level Packet Capture", proceedings of the 1993 Winter USENIX Technical Conference, San Diego, CA.by Steven McCanne and Van Jacobson of the Lawrence Berkeley Laboratory.
bulletThe BPF.4 Unix Manual (exerts only) provides a more detailed description of the BPF pseudo machine instruction set.

Conceptually, the BPF pseudo-machine is a software emulation of a very simple processor with just enough capability to be useful in filtering packets. There's currently no compiler or interpretive language to assist in building BPF programs available on the Windows platform (at least, not from PCAUSA). However, there is a macro language. WinDis 32 includes a function which allows a BPF program to be displayed in various ways to help understand the data flow (see the HookPeek /d, /dd and /ddd options and the bpf_dump function).

The HookPeek application includes several sample BPF filters. In fact, the filters include: IP, TCP, UDP, ICMP, IGMP, ARP, RARP, AppleTalk, NETBIOS and SPX/IPX. The reason for providing so many is not to actually attempt to make HookPeek be a useful program. Instead, these filters are intended to provide several different BPF samples to aid developers in understanding how the BPF can be used.

Example BPF Filter

The following provides an additional example of building a BPF filter program using the BPF macros defined in BPF.H. The example starts out with the customer's requirement:

"We want to get all TCP packets with source port #A or destination port #B"

The following steps illustrate building a BPF program which meets this requirement

 

Setp 1. Accept Ethernet Internet Protocol (IP) Packets

On Ethernet packets are demultiplexed using the Ethernet type field, which is a two-byte value starting at offset 12 in the Ethernet link header. Internet Protocol (IP) packets have an Ethernet type of 0x0800.

The following set of BPF pseudo-machine instructions implements a simple filter which accepts Ethernet IP packets:

Step 1 Macro Reprepresentation BPF Dump Representation
// Handle Ethernet RFC 894 Case
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 1),

BPF_STMT(BPF_RET+BPF_K, (UINT )-1),
BPF_STMT(BPF_RET+BPF_K, 0 )
 

(000) ldh [12]
(001) jeq #0x800 jt 2  jf 3

(002) ret #-1
(003) ret #0
 
 
Step 2. Accept IP Transmission Control Protocol (TCP) Packets

The Internet Protocol (IP) encapsulates several IP protocols, notably including TCP, UDP, ICMP and IGMP. IP protocols are differentiated by the IP protocol type, which is a one-byte field at offset 9 into the IP header. The Ethernet link address header is 14 bytes long, so on Ethernet the IP protocol type is at offset 23 into the Ethernet packet.

The following set of BPF pseudo-machine instructions implements a simple filter which accepts IP packets which have the TCP IP protocol type. The first two BPF pseudo-machine instructions make the test to determine if the packet has Ethernet type 0x0800; these instructions are the same as those used in the simple IP filter described in the preceding section - EXCEPT that the false condition jump offset is increased by two to account for the two extra BFP instructions necessary to test for TCP.

The second two BPF pseudo machine instructions are executed ONLY if the packet is an IP packet. They check the IP protocol type byte at offset 14 + 9 = 23 into the Ethernet packet.

Step 2 Macro Reprepresentation BPF Dump Representation
// Check Ethernet Protocol At Offset 12
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 3),

// Check IP Protocol At Offset 14 + 9 = 23
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x06, 0, 1),

BPF_STMT(BPF_RET+BPF_K, (UINT )-1),
BPF_STMT(BPF_RET+BPF_K, 0 )

(000) ldh [12]
(001) jeq #0x800 jt 2  jf 5


(002) ldb [23]
(003) jeq #0x6 jt 4  jf 5

(004) ret #-1
(005) ret #0

 

Step 3. Reject All But First Fragment

TCP port numbers are found in the TCP header, and the TCP header is only present in the first fragment. So, it is necessary to reject all packets IP packets with a non-zero fragment offset. Two more BPF instructions must be added to test the fragment offset word at offset 14 + 6 = 20 into the Ethernet packet and reject the packet, if necessary.

The following set of BPF pseudo-machine instructions implements a simple filter which accepts IP packets which have the TCP IP protocol type and have the TCP header present (i.e., first fragment):

Step 3 Macro Reprepresentation BPF Dump Representation
// Check Ethernet Protocol Word At Offset 12
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 5),

// Check IP Fragment Offset Word At Offset 14 + 6 = 20
// Reject Any Packet With Non-Zero Fragment Offset
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1FFF, 3, 0),

// Check IP Protocol Byte At Offset 14 + 9 = 23
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x06, 0, 1),

BPF_STMT(BPF_RET+BPF_K, (UINT )-1),
BPF_STMT(BPF_RET+BPF_K, 0 )

(000) ldh  [12]
(001) jeq  #0x800 jt 2  jf 7



(002) ldh  [20]
(003) jset #0x1fff jt 7 jf 4


(004) ldb  [23]
(005) jeq  #0x6 jt 6  jf 7

(006) ret #-1
(007) ret #0

 

Step 4. Accept Packets With A Specified TCP Source Port

The following set of BPF pseudo-machine instructions implements a simple filter which accepts IP packets which have the TCP IP protocol type and have the TCP header present and the TCP source port is Echo (7):

Step 4 Macro Reprepresentation BPF Dump Representation
// Check Ethernet Protocol Word At Offset 12
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 8),

// Check IP Fragment Offset Word At Offset 14 + 6 = 20
// Reject Any Packet With Non-Zero Fragment Offset
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1FFF, 6, 0),

// Check IP Protocol Byte At Offset 14 + 9 = 23
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x06, 0, 4),

// Check TCP Source Port Word At Offset 0 Into TCP Header
// 14 + IPHeaderLen + 0 = Offset To TCP Source Port
BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 14),
BPF_STMT(BPF_LD+BPF_H+BPF_IND, 14),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x0007, 0, 1),// #A = Echo(7)

BPF_STMT(BPF_RET+BPF_K, (UINT )-1),
BPF_STMT(BPF_RET+BPF_K, 0 )

(000) ldh   [12]
(001) jeq   #0x800  jt 2  jf 10



(002) ldh   [20]
(003) jset  #0x1fff jt 10 jf 4


(004) ldb   [23]
(005) jeq   #0x6  jt 6  jf 10



(006) ldxb  4*([14]&0xf)
(007) ldh   [x + 14]
(008) jeq   #0x7  jt 9  jf 10

(009) ret   #-1
(010) ret   #0
 

 

Step 5. Accept Packets With A Specified TCP Source Port Or Specified TCP Destination Port

The following set of BPF pseudo-machine instructions implements a simple filter which accepts IP packets which have the TCP IP protocol type and have the TCP header present and the TCP source port or TCP destination port is Echo (7):

Step 5 Macro Reprepresentation BPF Dump Representation
// Check Ethernet Protocol Word At Offset 12
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 11),

// Check IP Fragment Offset Word At Offset 14 + 6 = 20
// Reject Any Packet With Non-Zero Fragment Offset
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1FFF, 9, 0),

// Check IP Protocol Byte At Offset 14 + 9 = 23
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x06, 0, 7),

// Check TCP Source Port Word At Offset 0 Into TCP Header
// 14 + IPHeaderLen + 0 = Offset To TCP Source Port
BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 14),
BPF_STMT(BPF_LD+BPF_H+BPF_IND, 14),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x0007, 3, 0),// #A = Echo(7)

// Check TCP Destination Port Word At Offset 2 Into TCP Header
// 14 + IPHeaderLen + 2 = Offset To TCP Destination Port
BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 14),
BPF_STMT(BPF_LD+BPF_H+BPF_IND, 16),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x0007, 0, 1),// #B = Echo(7)

BPF_STMT(BPF_RET+BPF_K, (UINT )-1),
BPF_STMT(BPF_RET+BPF_K, 0 )

(000) ldh  [12]
(001) jeq  #0x800  jt 2  jf 13



(002) ldh  [20]
(003) jset #0x1fff  jt 13  jf 4


(004) ldb  [23]
(005) jeq  #0x6  jt 6  jf 13



(006) ldxb 4*([14]&0xf)
(007) ldh  [x + 14]
(008) jeq  #0x7  jt 12  jf 9



(009) ldxb 4*([14]&0xf)
(010) ldh  [x + 16]
(011) jeq  #0x7  jt 12  jf 13


(012) ret  #-1
(013) ret  #0
 

 

Status

November 3, 1999 This topic is for information only.

 

Keywords RAWETHER, WINDIS32, INFORMATION
Created November 3, 1999
Last Reviewed September 23, 2000

 

Mailing Lists  · PCAUSA Newsletter · PCAUSA Discussion List
·
Privacy Statement · 
WinDis 32 is a trademark of Printing Communications Assoc., Inc. (PCAUSA).
Rawether for Windows and Rawether .NET are trademarks of Printing Communications Assoc., Inc. (PCAUSA).
Microsoft, MS, Windows, Windows 95, Windows 98, Windows Millennium, Windows 2000, Windows XP, and Win32 are registered trademarks and Visual C++ and Windows NT are trademarks of the Microsoft Corporation.
Send mail to rawether-webmaster@pcausa.com with questions or comments about this web site.
Copyright © 1996-2008 Printing Communications Assoc., Inc. (PCAUSA).
All rights reserved.
Last modified: December 31, 2007