Bug 20686

Summary: bpf filters do not behave as expected with tun interfaces
Product: Base System Reporter: mlea <mlea>
Component: kernAssignee: Brian Somers <brian>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.0-CURRENT   
Hardware: Any   
OS: Any   

Description mlea 2000-08-17 16:40:01 UTC
When running tcpdump with filter expressions, the filter only works as
expected on *outgoing* packets.

For example, given a simple "positive" filter, tcpdump will only capture
*outbound* packets. Given the inverse "negative" filter, tcpdump will capture
both inbound & outbound packets, *including inbound packets that should have
been captured in the positive filter.*

Fix: 

The problem appears to be a byte-order problem with the address family
on the incoming packet in /sys/net/if_tun.c. Examining the packets
captured by tcpdump in Ethereal shows an address family of 0x00000002
on the inbound packets and a family of 0x02000000 on the outbound
packets. Running tcpdump with the -e flag shows similar results.

The fix is to ensure that the address family is stored in the packet in
host byte order, since that is what tcpdump/libpcap is looking for. This
probably means mangling the inbound packets at around if_tun.c:649 since
the address family at this point will be in network byte order.
How-To-Repeat: 
1. Bring up a PPP connection using user-ppp.

2. Run two (or three) tcpdump sessions to watch traffic on the PPP link:
   a) no filters: tcpdump -n -i tun0
   b) positive filter: tcpdump -n -i tun0 icmp
   c) negative filter: tcpdump -n -i tun0 not icmp

3. Send controlled traffic over the PPP link (in this example, pings from a
   remote host and a failed TCP connection attempt).

***** REMOTE HOST *****

$ ping -c 5 64.4.94.80
PING 64.4.94.80 (64.4.94.80): 56 data bytes
64 bytes from 64.4.94.80: icmp_seq=0 ttl=255 time=97.491 ms
64 bytes from 64.4.94.80: icmp_seq=1 ttl=255 time=98.056 ms
64 bytes from 64.4.94.80: icmp_seq=2 ttl=255 time=99.096 ms
64 bytes from 64.4.94.80: icmp_seq=3 ttl=255 time=92.134 ms
64 bytes from 64.4.94.80: icmp_seq=4 ttl=255 time=96.834 ms

--- 64.4.94.80 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 92.134/96.722/99.096/2.411 ms
$ telnet 64.4.94.80 12345
Trying 64.4.94.80...
telnet: connect to address 64.4.94.80: Connection refused
telnet: Unable to connect to remote host

***** NO FILTER *****

# tcpdump -d -i tun0
(000) ret      #96
# tcpdump -n -i tun0
tcpdump: listening on tun0
09:45:08.749435 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:08.749639 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:09.770319 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:09.770668 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:10.798635 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:10.798837 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:11.807835 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:11.808142 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:12.832782 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:12.833094 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:19.831059 64.4.83.19.1653 > 64.4.94.80.12345: S 1748413850:1748413850(0) win 16384 <mss 1360> (DF) [tos 0x10]
09:45:19.831252 64.4.94.80.12345 > 64.4.83.19.1653: R 0:0(0) ack 1748413851 win 0
^C
12 packets received by filter
0 packets dropped by kernel

***** POSITIVE FILTER *****

# tcpdump -d -i tun0 icmp
(000) ld       [0]
(001) jeq      #0x2000000       jt 2    jf 5
(002) ldb      [13]
(003) jeq      #0x1             jt 4    jf 5
(004) ret      #96
(005) ret      #0
# tcpdump -n -i tun0 icmp
tcpdump: listening on tun0
09:45:08.749636 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:09.770664 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:10.798833 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:11.808138 64.4.94.80 > 64.4.83.19: icmp: echo reply
09:45:12.833089 64.4.94.80 > 64.4.83.19: icmp: echo reply
^C
12 packets received by filter
0 packets dropped by kernel

***** NEGATIVE FILTER *****

# tcpdump -d -i tun0 not icmp
(000) ld       [0]
(001) jeq      #0x2000000       jt 2    jf 5
(002) ldb      [13]
(003) jeq      #0x1             jt 4    jf 5
(004) ret      #0
(005) ret      #96
# tcpdump -n -i tun0 not icmp
tcpdump: listening on tun0
09:45:08.749423 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:09.770306 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:10.798627 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:11.807828 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:12.832771 64.4.83.19 > 64.4.94.80: icmp: echo request
09:45:19.831049 64.4.83.19.1653 > 64.4.94.80.12345: S 1748413850:1748413850(0) win 16384 <mss 1360> (DF) [tos 0x10]
09:45:19.831249 64.4.94.80.12345 > 64.4.83.19.1653: R 0:0(0) ack 1748413851 win 0
^C
12 packets received by filter
0 packets dropped by kernel
Comment 1 Sheldon Hearn freebsd_committer freebsd_triage 2000-08-17 17:58:51 UTC
Responsible Changed
From-To: freebsd-bugs->brian

Over to the maintainer.  I'm not sure that this is related to 
PR bin/20188, so I've left both open.
Comment 2 Brian Somers freebsd_committer freebsd_triage 2000-10-15 20:42:56 UTC
State Changed
From-To: open->closed

Fixed in -current.