Capture Filters and Offsets

A couple of questions have come up on the wireshark-users mailing list recently about using capture filters for MPLS and VLANs. Each user was having the same problem yet these are different network technologies — what do they have to do with each other?

The answer is offsets.

Let’s take an up-close and personal look at the capture filter “ip src host 10.16.32.48”. We can do this by running tcpdump -d, which takes a filter, compiles it, and dumps out the result. The dump of our filter looks like this:

(000) ldh      [12]
(001) jeq      #0x800           jt 2    jf 5
(002) ld       [26]
(003) jeq      #0xa102030       jt 4    jf 5
(004) ret      #96
(005) ret      #0

If this makes no sense don’t worry. You just need to know that the first two lines look for the IP ethertype (0x800) starting at byte 12 and the next two lines look for the IP address 10.16.32.48 (0xa102030) starting at byte 26. This is the minimum amount of checking required for that capture filter if you’re running IP over Ethernet.

What happens if you’re using 802.1q?

802.1q inserts an extra four bytes in front of the ethertype, so this filter won’t do what you want. The ethertype will be at offset 16 instead of 12, and the IP source address will be at offset 30 instead of 26. Libpcap and WinPcap don’t know you’re using .1q, and adding a check to the filter code would add a lot of unnecessary overhead. We have to add the word “vlan” to our filter to get the right offsets, e.g. “vlan and ip src host 10.16.32.48”:

(000) ldh      [12]
(001) jeq      #0x8100          jt 2    jf 7
(002) ldh      [16]
(003) jeq      #0x800           jt 4    jf 7
(004) ld       [30]
(005) jeq      #0xa102030       jt 6    jf 7
(006) ret      #96
(007) ret      #0

There’s a gotcha here, though. What if we change the “and” to an “or”?

(000) ldh      [12]
(001) jeq      #0x8100          jt 6    jf 2
(002) ldh      [16]
(003) jeq      #0x800           jt 4    jf 7
(004) ld       [30]
(005) jeq      #0xa102030       jt 6    jf 7
(006) ret      #96
(007) ret      #0

We’re looking for the IP address at byte 30. Shouldn’t we be looking at both 26 and 30?

The filter compiler uses a base offset for fetching data from the packet. Any time you use “vlan”, “mpls”, or “pppoes” in a capture filter, this offset is increased from that point on. It’s also cumulative. That is, while all of these filters are logically equivalent, they’re not in practice:

ip src host 10.16.32.48 or vlan or vlan (Looks for 10.16.32.48 at offset 26)

vlan or ip src host 10.16.32.48 or vlan (Now it’s looking at offset 30)

vlan or vlan or ip src host 10.16.32.48 (Offset 34. When will it ever end?)

“vlan” and “mpls” increase the base offset by 4. “pppoes” increases it by 8.