Date: 17 Aug 2000 15:31:39 -0000 From: mlea@atomicbluebear.org To: FreeBSD-gnats-submit@freebsd.org Subject: kern/20686: bpf filter broken with tun interface Message-ID: <20000817153139.1304.qmail@meltdown.atomicbluebear.org>
next in thread | raw e-mail | index | archive | help
>Number: 20686
>Category: kern
>Synopsis: bpf filters do not behave as expected with tun interfaces
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu Aug 17 08:40:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator: Michael Lea
>Release: FreeBSD 5.0-CURRENT i386
>Organization:
private user
>Environment:
$ uname -a
FreeBSD meltdown.atomicbluebear.org 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Wed Aug 16 22:05:28 CDT 2000 mlea@meltdown.atomicbluebear.org:/usr/obj/usr/src/sys/PLANCK i386
$ ifconfig -a
ed0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1400
inet 172.31.254.2 netmask 0xffffff00 broadcast 172.31.254.255
ether 00:40:05:5d:d6:d9
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
inet 127.0.0.1 netmask 0xff000000
tun0: flags=8151<UP,POINTOPOINT,RUNNING,PROMISC,MULTICAST> mtu 1400
inet 64.4.94.80 --> 64.4.82.5 netmask 0xffffffff
Opened by PID 1215
>Description:
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.*
>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
>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.
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000817153139.1304.qmail>
