xref: /openbsd/usr.sbin/tcpdump/print-usbpcap.c (revision 45d812a4)
1 /*	$OpenBSD: print-usbpcap.c,v 1.6 2023/03/13 13:36:56 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2018 Martin Pieuchot <mpi@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <dev/usb/usb.h>
20 #include <dev/usb/usbpcap.h>
21 
22 #include <pcap.h>
23 
24 #include "interface.h"
25 
26 #ifndef nitems
27 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
28 #endif
29 
30 const char *usbpcap_xfer_type[] = {"isoc", "intr", "ctrl", "bulk"};
31 const char *usbpcap_control_stages[] = {"setup", "data", "status"};
32 const char *usbpcap_request_codes[] = {
33 	"GET_STATUS", "CLEAR_FEATURE", "?", "SET_FEATURE", "?", "SET_ADDRESS",
34 	"GET_DESCRIPTOR", "SET_DESCRIPTOR", "GET_CONFIG", "SET_CONFIG",
35 	"GET_INTERFACE", "SET_INTERFACE", "SYNCH_FRAME",
36 };
37 
38 void	 usbpcap_print_descriptor(int);
39 void	 usbpcap_print_request_type(uByte);
40 
41 void
usbpcap_if_print(u_char * user,const struct pcap_pkthdr * h,const u_char * p)42 usbpcap_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
43 {
44 	u_int caplen = h->caplen;
45 	const struct usbpcap_pkt_hdr *uph;
46 	u_int16_t hdrlen;
47 
48 	ts_print(&h->ts);
49 
50 	/* set required globals */
51 	snapend = p + caplen;
52 
53 	/* check length */
54 	uph = (struct usbpcap_pkt_hdr *)p;
55 	TCHECK(uph->uph_hlen);
56 	hdrlen = letoh16(uph->uph_hlen);
57 	if (hdrlen < sizeof(*uph)) {
58 		printf("[usb: invalid header length %u!]", hdrlen);
59 		goto out;
60 	}
61 
62 	TCHECK(uph[0]);
63 
64 	printf("bus %u %c addr %u: ep%u",
65 	    letoh16(uph->uph_bus),
66 	     ((uph->uph_info & USBPCAP_INFO_DIRECTION_IN) ? '<' : '>'),
67 	    letoh16(uph->uph_devaddr), UE_GET_ADDR(uph->uph_epaddr));
68 
69 	if (uph->uph_xfertype < nitems(usbpcap_xfer_type))
70 		printf(" %s", usbpcap_xfer_type[uph->uph_xfertype]);
71 	else
72 		printf(" ??");
73 
74 	printf(" dlen=%u", letoh32(uph->uph_dlen));
75 
76 	TCHECK2(uph[0], hdrlen);
77 
78 	if (uph->uph_xfertype == USBPCAP_TRANSFER_CONTROL) {
79 		struct usbpcap_ctl_hdr *ctl_hdr = (struct usbpcap_ctl_hdr *)p;
80 
81 		TCHECK(ctl_hdr->uch_stage);
82 		if (ctl_hdr->uch_stage < nitems(usbpcap_control_stages))
83 			printf(" stage=%s",
84 			    usbpcap_control_stages[ctl_hdr->uch_stage]);
85 		else
86 			printf(" stage=?");
87 
88 		if (ctl_hdr->uch_stage == USBPCAP_CONTROL_STAGE_SETUP) {
89 			usb_device_request_t *req;
90 
91 			req = (usb_device_request_t *)
92 			    (p + sizeof(struct usbpcap_ctl_hdr));
93 
94 			/* Setup packets must be 8 bytes in size as per
95 			 * 9.3 USB Device Requests. */
96 			if (letoh32(uph->uph_dlen != 8)) {
97 				printf("[usb: invalid data length %u!]",
98 				   letoh32(uph->uph_dlen));
99 				goto out;
100 			}
101 			TCHECK(req[0]);
102 
103 			usbpcap_print_request_type(req->bmRequestType);
104 
105 			if (req->bRequest < nitems(usbpcap_request_codes))
106 				printf(" bRequest=%s",
107 				    usbpcap_request_codes[req->bRequest]);
108 			else
109 				printf(" bRequest=?");
110 
111 			if (req->bRequest == UR_GET_DESCRIPTOR)
112 				usbpcap_print_descriptor(UGETW(req->wValue));
113 			else
114 				printf(" wValue=0x%04x", UGETW(req->wValue));
115 
116 			printf(" wIndex=%04x", UGETW(req->wIndex));
117 			printf(" wLength=%u", UGETW(req->wLength));
118 		}
119 	}
120 
121 	if (xflag) {
122 		if (eflag)
123 			default_print(p, caplen);
124 		else
125 			default_print(p + hdrlen, caplen - hdrlen);
126 	}
127 out:
128 	putchar('\n');
129 	return;
130 trunc:
131 	printf("[|usb]\n");
132 }
133 
134 void
usbpcap_print_descriptor(int value)135 usbpcap_print_descriptor(int value)
136 {
137 	printf(" type=");
138 	switch (value >> 8) {
139 	case UDESC_DEVICE:
140 		printf("DEVICE");
141 		break;
142 	case UDESC_CONFIG:
143 		printf("CONFIGURATION");
144 		break;
145 	case UDESC_STRING:
146 		printf("STRING");
147 		break;
148 	case UDESC_INTERFACE:
149 		printf("INTERFACE");
150 		break;
151 	case UDESC_ENDPOINT:
152 		printf("ENDPOINT");
153 		break;
154 	case UDESC_DEVICE_QUALIFIER:
155 		printf("DEVICE_QUALIFIER");
156 		break;
157 	case UDESC_OTHER_SPEED_CONFIGURATION:
158 		printf("OTHER_SPEED_CONFIGURATION");
159 		break;
160 	case UDESC_INTERFACE_POWER:
161 		printf("INTERFACE_POWER");
162 		break;
163 	case UDESC_OTG:
164 		printf("OTG");
165 		break;
166 	case UDESC_DEBUG:
167 		printf("DEBUG");
168 		break;
169 	case UDESC_IFACE_ASSOC:
170 		printf("INTERFACE_ASSOCIATION");
171 		break;
172 	case UDESC_BOS:
173 		printf("BOS");
174 		break;
175 	case UDESC_DEVICE_CAPABILITY:
176 		printf("DEVICE_CAPABILITY");
177 		break;
178 	case UDESC_CS_DEVICE:
179 		printf("CS_DEVICE");
180 		break;
181 	case UDESC_CS_CONFIG:
182 		printf("CS_CONFIGURATION");
183 		break;
184 	case UDESC_CS_STRING:
185 		printf("CS_STRING");
186 		break;
187 	case UDESC_CS_INTERFACE:
188 		printf("CS_INTERFACE");
189 		break;
190 	case UDESC_CS_ENDPOINT:
191 		printf("CS_ENDPOINT");
192 		break;
193 	case UDESC_HUB:
194 		printf("HUB");
195 		break;
196 	case UDESC_SS_HUB:
197 		printf("SS_HUB");
198 		break;
199 	case UDESC_ENDPOINT_SS_COMP:
200 		printf("SS_COMPANION");
201 		break;
202 	default:
203 		printf("?");
204 	}
205 
206 	printf(" index=0x%02x", value & 0xff);
207 }
208 
209 void
usbpcap_print_request_type(uByte request_type)210 usbpcap_print_request_type(uByte request_type)
211 {
212 	printf(" bmRequestType=");
213 
214 	switch (request_type) {
215 	case UT_READ_DEVICE:
216 		printf("UT_READ_DEVICE");
217 		break;
218 	case UT_READ_INTERFACE:
219 		printf("UT_READ_INTERFACE");
220 		break;
221 	case UT_READ_ENDPOINT:
222 		printf("UT_READ_ENDPOINT");
223 		break;
224 	case UT_WRITE_DEVICE:
225 		printf("UT_WRITE_DEVICE");
226 		break;
227 	case UT_WRITE_INTERFACE:
228 		printf("UT_WRITE_INTERFACE");
229 		break;
230 	case UT_WRITE_ENDPOINT:
231 		printf("UT_WRITE_ENDPOINT");
232 		break;
233 	case UT_READ_CLASS_DEVICE:
234 		printf("UT_READ_CLASS_DEVICE");
235 		break;
236 	case UT_READ_CLASS_INTERFACE:
237 		printf("UT_READ_CLASS_INTERFACE");
238 		break;
239 	case UT_READ_CLASS_OTHER:
240 		printf("UT_READ_CLASS_OTHER");
241 		break;
242 	case UT_READ_CLASS_ENDPOINT:
243 		printf("UT_READ_CLASS_ENDPOINT");
244 		break;
245 	case UT_WRITE_CLASS_DEVICE:
246 		printf("UT_WRITE_CLASS_DEVICE");
247 		break;
248 	case UT_WRITE_CLASS_INTERFACE:
249 		printf("UT_WRITE_CLASS_INTERFACE");
250 		break;
251 	case UT_WRITE_CLASS_OTHER:
252 		printf("UT_WRITE_CLASS_OTHER");
253 		break;
254 	case UT_WRITE_CLASS_ENDPOINT:
255 		printf("UT_WRITE_CLASS_ENDPOINT");
256 		break;
257 	case UT_READ_VENDOR_DEVICE:
258 		printf("UT_READ_VENDOR_DEVICE");
259 		break;
260 	case UT_READ_VENDOR_INTERFACE:
261 		printf("UT_READ_VENDOR_INTERFACE");
262 		break;
263 	case UT_READ_VENDOR_OTHER:
264 		printf("UT_READ_VENDOR_OTHER");
265 		break;
266 	case UT_READ_VENDOR_ENDPOINT:
267 		printf("UT_READ_VENDOR_ENDPOINT");
268 		break;
269 	case UT_WRITE_VENDOR_DEVICE:
270 		printf("UT_WRITE_VENDOR_DEVICE");
271 		break;
272 	case UT_WRITE_VENDOR_INTERFACE:
273 		printf("UT_WRITE_VENDOR_INTERFACE");
274 		break;
275 	case UT_WRITE_VENDOR_OTHER:
276 		printf("UT_WRITE_VENDOR_OTHER");
277 		break;
278 	case UT_WRITE_VENDOR_ENDPOINT:
279 		printf("UT_WRITE_VENDOR_ENDPOINT");
280 		break;
281 	default:
282 		printf("?");
283 	}
284 }
285