Grenadille - Tag - tcpdumpStories from inside your kernel2018-12-11T19:55:21+01:00Martin Pieuchoturn:md5:59590DotclearDumping your USBurn:md5:67589bae21ccb5dcd4004c2d65f2492e2018-03-29T13:25:00+02:00mpiUSBkernelOpenBSDtcpdumpUSBUSBPcap<p>One of the many <a href="https://www.openbsd.org/63.html">new features</a>
of OpenBSD 6.3 is the possibility to dump USB traffic to userland via <a href="http://man.openbsd.org/bpf">bpf(4)</a>. This can be done with <a href="http://man.openbsd.org/tcpdump">tcpdump(8)</a> by specifying a USB bus as
interface:</p>
<pre>
# tcpdump -Xx -i usb0
tcpdump: listening on usb0, link-type USBPCAP
12:28:03.317945 bus 0 &lt; addr 1: ep1 intr 2
0000: 0400 ..
12:28:03.318018 bus 0 &gt; addr 1: ep0 ctrl 8
0000: 00a3 0000 0002 0004 00 .........
[...]
</pre> <p>As you might have noted I decided to implement the existing <a href="http://desowin.org/usbpcap/captureformat.html">USBPcap</a> capture format. A
capture format is required because USB packets do not include all the necessary
information to properly interpret them. I first thought I would implement
libpcap's <strong>DLT_USB</strong> but then I quickly realize that this was not
a standard. It is instead a FreeBSD specific format which has been since then
renamed <strong>DLT_USB_FREEBSD</strong>.</p>
<p>But I didn't want to embrace <a href="https://xkcd.com/927/">xkcd #927</a>,
so I look at the existing formats: <strong>DLT_USB_FREEBSD</strong>,
<strong>DLT_USB_LINUX</strong>, <strong>DLT_USB_LINUX_MMAPPED</strong>,
<strong>DLT_USB_DARWIN</strong> and <strong>DLT_USBPCAP</strong>. I was first a
bit sad to see that nobody could agree on a common format then I moved on and
picked the simplest one: USBPcap.</p>
<p>Implementing an already existing format gives us out-of-box support for all
the tools supporting it. That's why having common formats let us share our
energy. In the case of USBPcap it is already supported by <a href="https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8503">Wireshark</a>, so
you can already inspect your packet graphically. For that you need to first
capture raw packets:</p>
<pre>
# tcpdump -s 3303 -w usb.pcap -i usb0
tcpdump: listening on usb0, link-type USBPCAP
^C
208 packets received by filter
0 packets dropped by kernel
</pre>
<p>USB packets can be quite big, that's why I'm not using <a href="http://man.openbsd.org/tcpdump">tcpdump(8)</a>'s default packet size. In this
case, I want to make sure I can dump the complete <a href="http://man.openbsd.org/uaudio">uaudio(4)</a> frames.</p>
<p>Once the capture completed, time to look at it:</p>
<p><img src="http://www.grenadille.net/public/USBPCAP/.wireshark-usb_m.jpg" alt="wireshark-usb.jpg" title="wireshark-usb.jpg, Mar 2018" /></p>
<p>It is important to say that what is dumped to userland is what the USB stack
sees. Packets sent on the wire might differ, especially when it comes to
retries and timing. So this feature is not here to replace any USB analyser,
however I hope that it will help people understand how things work and what the
USB stack is doing. Even I found some <a href="https://marc.info/?l=openbsd-tech&amp;m=151913555218330&amp;w=2">interesting
timing issues</a> while implementing isochronous support.</p>