xref: /openbsd-src/usr.sbin/tcpdump/print-usbpcap.c (revision 45d812a40f79dfc2990bdef9a5dd381409a171a0)
1*45d812a4Sclaudio /*	$OpenBSD: print-usbpcap.c,v 1.6 2023/03/13 13:36:56 claudio Exp $ */
226c7a136Sjasper 
3d00b8992Smpi /*
4d00b8992Smpi  * Copyright (c) 2018 Martin Pieuchot <mpi@openbsd.org>
5d00b8992Smpi  *
6d00b8992Smpi  * Permission to use, copy, modify, and distribute this software for any
7d00b8992Smpi  * purpose with or without fee is hereby granted, provided that the above
8d00b8992Smpi  * copyright notice and this permission notice appear in all copies.
9d00b8992Smpi  *
10d00b8992Smpi  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11d00b8992Smpi  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12d00b8992Smpi  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13d00b8992Smpi  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14d00b8992Smpi  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15d00b8992Smpi  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16d00b8992Smpi  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17d00b8992Smpi  */
18d00b8992Smpi 
19d00b8992Smpi #include <dev/usb/usb.h>
20d00b8992Smpi #include <dev/usb/usbpcap.h>
21d00b8992Smpi 
22d00b8992Smpi #include <pcap.h>
23d00b8992Smpi 
24d00b8992Smpi #include "interface.h"
25d00b8992Smpi 
26d00b8992Smpi #ifndef nitems
27d00b8992Smpi #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
28d00b8992Smpi #endif
29d00b8992Smpi 
30d00b8992Smpi const char *usbpcap_xfer_type[] = {"isoc", "intr", "ctrl", "bulk"};
31dccdc9acSpatrick const char *usbpcap_control_stages[] = {"setup", "data", "status"};
32386dd857Sjasper const char *usbpcap_request_codes[] = {
33386dd857Sjasper 	"GET_STATUS", "CLEAR_FEATURE", "?", "SET_FEATURE", "?", "SET_ADDRESS",
34386dd857Sjasper 	"GET_DESCRIPTOR", "SET_DESCRIPTOR", "GET_CONFIG", "SET_CONFIG",
35386dd857Sjasper 	"GET_INTERFACE", "SET_INTERFACE", "SYNCH_FRAME",
36386dd857Sjasper };
37386dd857Sjasper 
38386dd857Sjasper void	 usbpcap_print_descriptor(int);
39386dd857Sjasper void	 usbpcap_print_request_type(uByte);
40d00b8992Smpi 
41d00b8992Smpi void
usbpcap_if_print(u_char * user,const struct pcap_pkthdr * h,const u_char * p)42d00b8992Smpi usbpcap_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
43d00b8992Smpi {
44d00b8992Smpi 	u_int caplen = h->caplen;
45d00b8992Smpi 	const struct usbpcap_pkt_hdr *uph;
46d00b8992Smpi 	u_int16_t hdrlen;
47d00b8992Smpi 
48d00b8992Smpi 	ts_print(&h->ts);
49d00b8992Smpi 
50*45d812a4Sclaudio 	/* set required globals */
51*45d812a4Sclaudio 	snapend = p + caplen;
5226c7a136Sjasper 
53*45d812a4Sclaudio 	/* check length */
54d00b8992Smpi 	uph = (struct usbpcap_pkt_hdr *)p;
55*45d812a4Sclaudio 	TCHECK(uph->uph_hlen);
56d00b8992Smpi 	hdrlen = letoh16(uph->uph_hlen);
57d00b8992Smpi 	if (hdrlen < sizeof(*uph)) {
58d00b8992Smpi 		printf("[usb: invalid header length %u!]", hdrlen);
59d00b8992Smpi 		goto out;
60d00b8992Smpi 	}
61d00b8992Smpi 
62*45d812a4Sclaudio 	TCHECK(uph[0]);
63d00b8992Smpi 
64d00b8992Smpi 	printf("bus %u %c addr %u: ep%u",
65d00b8992Smpi 	    letoh16(uph->uph_bus),
66d00b8992Smpi 	     ((uph->uph_info & USBPCAP_INFO_DIRECTION_IN) ? '<' : '>'),
67d00b8992Smpi 	    letoh16(uph->uph_devaddr), UE_GET_ADDR(uph->uph_epaddr));
68d00b8992Smpi 
69d00b8992Smpi 	if (uph->uph_xfertype < nitems(usbpcap_xfer_type))
70d00b8992Smpi 		printf(" %s", usbpcap_xfer_type[uph->uph_xfertype]);
71d00b8992Smpi 	else
72d00b8992Smpi 		printf(" ??");
73d00b8992Smpi 
7426c7a136Sjasper 	printf(" dlen=%u", letoh32(uph->uph_dlen));
75d00b8992Smpi 
76*45d812a4Sclaudio 	TCHECK2(uph[0], hdrlen);
77*45d812a4Sclaudio 
78386dd857Sjasper 	if (uph->uph_xfertype == USBPCAP_TRANSFER_CONTROL) {
79386dd857Sjasper 		struct usbpcap_ctl_hdr *ctl_hdr = (struct usbpcap_ctl_hdr *)p;
80386dd857Sjasper 
81*45d812a4Sclaudio 		TCHECK(ctl_hdr->uch_stage);
82386dd857Sjasper 		if (ctl_hdr->uch_stage < nitems(usbpcap_control_stages))
83386dd857Sjasper 			printf(" stage=%s",
84386dd857Sjasper 			    usbpcap_control_stages[ctl_hdr->uch_stage]);
85386dd857Sjasper 		else
86386dd857Sjasper 			printf(" stage=?");
87386dd857Sjasper 
88386dd857Sjasper 		if (ctl_hdr->uch_stage == USBPCAP_CONTROL_STAGE_SETUP) {
89*45d812a4Sclaudio 			usb_device_request_t *req;
90*45d812a4Sclaudio 
91*45d812a4Sclaudio 			req = (usb_device_request_t *)
92*45d812a4Sclaudio 			    (p + sizeof(struct usbpcap_ctl_hdr));
93*45d812a4Sclaudio 
94386dd857Sjasper 			/* Setup packets must be 8 bytes in size as per
95386dd857Sjasper 			 * 9.3 USB Device Requests. */
96*45d812a4Sclaudio 			if (letoh32(uph->uph_dlen != 8)) {
97*45d812a4Sclaudio 				printf("[usb: invalid data length %u!]",
98*45d812a4Sclaudio 				   letoh32(uph->uph_dlen));
99*45d812a4Sclaudio 				goto out;
100*45d812a4Sclaudio 			}
101*45d812a4Sclaudio 			TCHECK(req[0]);
102386dd857Sjasper 
103386dd857Sjasper 			usbpcap_print_request_type(req->bmRequestType);
104386dd857Sjasper 
105386dd857Sjasper 			if (req->bRequest < nitems(usbpcap_request_codes))
106386dd857Sjasper 				printf(" bRequest=%s",
107386dd857Sjasper 				    usbpcap_request_codes[req->bRequest]);
108386dd857Sjasper 			else
109386dd857Sjasper 				printf(" bRequest=?");
110386dd857Sjasper 
111386dd857Sjasper 			if (req->bRequest == UR_GET_DESCRIPTOR)
112386dd857Sjasper 				usbpcap_print_descriptor(UGETW(req->wValue));
113386dd857Sjasper 			else
114386dd857Sjasper 				printf(" wValue=0x%04x", UGETW(req->wValue));
115386dd857Sjasper 
116386dd857Sjasper 			printf(" wIndex=%04x", UGETW(req->wIndex));
117386dd857Sjasper 			printf(" wLength=%u", UGETW(req->wLength));
118386dd857Sjasper 		}
119386dd857Sjasper 	}
120386dd857Sjasper 
121*45d812a4Sclaudio 	if (xflag) {
122*45d812a4Sclaudio 		if (eflag)
123*45d812a4Sclaudio 			default_print(p, caplen);
124*45d812a4Sclaudio 		else
125*45d812a4Sclaudio 			default_print(p + hdrlen, caplen - hdrlen);
126*45d812a4Sclaudio 	}
127d00b8992Smpi out:
128d00b8992Smpi 	putchar('\n');
12926c7a136Sjasper 	return;
13026c7a136Sjasper trunc:
131*45d812a4Sclaudio 	printf("[|usb]\n");
132d00b8992Smpi }
133386dd857Sjasper 
134386dd857Sjasper void
usbpcap_print_descriptor(int value)135386dd857Sjasper usbpcap_print_descriptor(int value)
136386dd857Sjasper {
137386dd857Sjasper 	printf(" type=");
138386dd857Sjasper 	switch (value >> 8) {
139386dd857Sjasper 	case UDESC_DEVICE:
140386dd857Sjasper 		printf("DEVICE");
141386dd857Sjasper 		break;
142386dd857Sjasper 	case UDESC_CONFIG:
143386dd857Sjasper 		printf("CONFIGURATION");
144386dd857Sjasper 		break;
145386dd857Sjasper 	case UDESC_STRING:
146386dd857Sjasper 		printf("STRING");
147386dd857Sjasper 		break;
148386dd857Sjasper 	case UDESC_INTERFACE:
149386dd857Sjasper 		printf("INTERFACE");
150386dd857Sjasper 		break;
151386dd857Sjasper 	case UDESC_ENDPOINT:
152386dd857Sjasper 		printf("ENDPOINT");
153386dd857Sjasper 		break;
154386dd857Sjasper 	case UDESC_DEVICE_QUALIFIER:
155386dd857Sjasper 		printf("DEVICE_QUALIFIER");
156386dd857Sjasper 		break;
157386dd857Sjasper 	case UDESC_OTHER_SPEED_CONFIGURATION:
158386dd857Sjasper 		printf("OTHER_SPEED_CONFIGURATION");
159386dd857Sjasper 		break;
160386dd857Sjasper 	case UDESC_INTERFACE_POWER:
161386dd857Sjasper 		printf("INTERFACE_POWER");
162386dd857Sjasper 		break;
163386dd857Sjasper 	case UDESC_OTG:
164386dd857Sjasper 		printf("OTG");
165386dd857Sjasper 		break;
166386dd857Sjasper 	case UDESC_DEBUG:
167386dd857Sjasper 		printf("DEBUG");
168386dd857Sjasper 		break;
169386dd857Sjasper 	case UDESC_IFACE_ASSOC:
170386dd857Sjasper 		printf("INTERFACE_ASSOCIATION");
171386dd857Sjasper 		break;
172386dd857Sjasper 	case UDESC_BOS:
173386dd857Sjasper 		printf("BOS");
174386dd857Sjasper 		break;
175386dd857Sjasper 	case UDESC_DEVICE_CAPABILITY:
176386dd857Sjasper 		printf("DEVICE_CAPABILITY");
177386dd857Sjasper 		break;
178386dd857Sjasper 	case UDESC_CS_DEVICE:
179386dd857Sjasper 		printf("CS_DEVICE");
180386dd857Sjasper 		break;
181386dd857Sjasper 	case UDESC_CS_CONFIG:
182386dd857Sjasper 		printf("CS_CONFIGURATION");
183386dd857Sjasper 		break;
184386dd857Sjasper 	case UDESC_CS_STRING:
185386dd857Sjasper 		printf("CS_STRING");
186386dd857Sjasper 		break;
187386dd857Sjasper 	case UDESC_CS_INTERFACE:
188386dd857Sjasper 		printf("CS_INTERFACE");
189386dd857Sjasper 		break;
190386dd857Sjasper 	case UDESC_CS_ENDPOINT:
191386dd857Sjasper 		printf("CS_ENDPOINT");
192386dd857Sjasper 		break;
193386dd857Sjasper 	case UDESC_HUB:
194386dd857Sjasper 		printf("HUB");
195386dd857Sjasper 		break;
196386dd857Sjasper 	case UDESC_SS_HUB:
197386dd857Sjasper 		printf("SS_HUB");
198386dd857Sjasper 		break;
199386dd857Sjasper 	case UDESC_ENDPOINT_SS_COMP:
200386dd857Sjasper 		printf("SS_COMPANION");
201386dd857Sjasper 		break;
202386dd857Sjasper 	default:
203386dd857Sjasper 		printf("?");
204386dd857Sjasper 	}
205386dd857Sjasper 
206386dd857Sjasper 	printf(" index=0x%02x", value & 0xff);
207386dd857Sjasper }
208386dd857Sjasper 
209386dd857Sjasper void
usbpcap_print_request_type(uByte request_type)210386dd857Sjasper usbpcap_print_request_type(uByte request_type)
211386dd857Sjasper {
212386dd857Sjasper 	printf(" bmRequestType=");
213386dd857Sjasper 
214386dd857Sjasper 	switch (request_type) {
215386dd857Sjasper 	case UT_READ_DEVICE:
216386dd857Sjasper 		printf("UT_READ_DEVICE");
217386dd857Sjasper 		break;
218386dd857Sjasper 	case UT_READ_INTERFACE:
219386dd857Sjasper 		printf("UT_READ_INTERFACE");
220386dd857Sjasper 		break;
221386dd857Sjasper 	case UT_READ_ENDPOINT:
222386dd857Sjasper 		printf("UT_READ_ENDPOINT");
223386dd857Sjasper 		break;
224386dd857Sjasper 	case UT_WRITE_DEVICE:
225386dd857Sjasper 		printf("UT_WRITE_DEVICE");
226386dd857Sjasper 		break;
227386dd857Sjasper 	case UT_WRITE_INTERFACE:
228386dd857Sjasper 		printf("UT_WRITE_INTERFACE");
229386dd857Sjasper 		break;
230386dd857Sjasper 	case UT_WRITE_ENDPOINT:
231386dd857Sjasper 		printf("UT_WRITE_ENDPOINT");
232386dd857Sjasper 		break;
233386dd857Sjasper 	case UT_READ_CLASS_DEVICE:
234386dd857Sjasper 		printf("UT_READ_CLASS_DEVICE");
235386dd857Sjasper 		break;
236386dd857Sjasper 	case UT_READ_CLASS_INTERFACE:
237386dd857Sjasper 		printf("UT_READ_CLASS_INTERFACE");
238386dd857Sjasper 		break;
239386dd857Sjasper 	case UT_READ_CLASS_OTHER:
240386dd857Sjasper 		printf("UT_READ_CLASS_OTHER");
241386dd857Sjasper 		break;
242386dd857Sjasper 	case UT_READ_CLASS_ENDPOINT:
243386dd857Sjasper 		printf("UT_READ_CLASS_ENDPOINT");
244386dd857Sjasper 		break;
245386dd857Sjasper 	case UT_WRITE_CLASS_DEVICE:
246386dd857Sjasper 		printf("UT_WRITE_CLASS_DEVICE");
247386dd857Sjasper 		break;
248386dd857Sjasper 	case UT_WRITE_CLASS_INTERFACE:
249386dd857Sjasper 		printf("UT_WRITE_CLASS_INTERFACE");
250386dd857Sjasper 		break;
251386dd857Sjasper 	case UT_WRITE_CLASS_OTHER:
252386dd857Sjasper 		printf("UT_WRITE_CLASS_OTHER");
253386dd857Sjasper 		break;
254386dd857Sjasper 	case UT_WRITE_CLASS_ENDPOINT:
255386dd857Sjasper 		printf("UT_WRITE_CLASS_ENDPOINT");
256386dd857Sjasper 		break;
257386dd857Sjasper 	case UT_READ_VENDOR_DEVICE:
258386dd857Sjasper 		printf("UT_READ_VENDOR_DEVICE");
259386dd857Sjasper 		break;
260386dd857Sjasper 	case UT_READ_VENDOR_INTERFACE:
261386dd857Sjasper 		printf("UT_READ_VENDOR_INTERFACE");
262386dd857Sjasper 		break;
263386dd857Sjasper 	case UT_READ_VENDOR_OTHER:
264386dd857Sjasper 		printf("UT_READ_VENDOR_OTHER");
265386dd857Sjasper 		break;
266386dd857Sjasper 	case UT_READ_VENDOR_ENDPOINT:
267386dd857Sjasper 		printf("UT_READ_VENDOR_ENDPOINT");
268386dd857Sjasper 		break;
269386dd857Sjasper 	case UT_WRITE_VENDOR_DEVICE:
270386dd857Sjasper 		printf("UT_WRITE_VENDOR_DEVICE");
271386dd857Sjasper 		break;
272386dd857Sjasper 	case UT_WRITE_VENDOR_INTERFACE:
273386dd857Sjasper 		printf("UT_WRITE_VENDOR_INTERFACE");
274386dd857Sjasper 		break;
275386dd857Sjasper 	case UT_WRITE_VENDOR_OTHER:
276386dd857Sjasper 		printf("UT_WRITE_VENDOR_OTHER");
277386dd857Sjasper 		break;
278386dd857Sjasper 	case UT_WRITE_VENDOR_ENDPOINT:
279386dd857Sjasper 		printf("UT_WRITE_VENDOR_ENDPOINT");
280386dd857Sjasper 		break;
281386dd857Sjasper 	default:
282386dd857Sjasper 		printf("?");
283386dd857Sjasper 	}
284386dd857Sjasper }
285